Timeline: draft a concept to attack the custom layout

the core question is: how to translate time into pixel coordinates
This commit is contained in:
Fischlurch 2018-11-24 17:03:03 +01:00
parent 7b7ec310b3
commit 116600b20a
9 changed files with 433 additions and 14 deletions

View file

@ -0,0 +1,45 @@
/*
ZoomWindow - generic translation from domain to screen coordinates
Copyright (C) Lumiera.org
2018, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
/** @file zoom-window.cpp
** Common implementation details related to zoom handling and
** transformation into screen coordinates.
**
*/
#include "stage/model/zoom-window.hpp"
//#include "include/ui-protocol.hpp"
//#include "lib/diff/gen-node.hpp"
namespace stage {
namespace model {
/** */
}} // namespace stage::model

View file

@ -0,0 +1,92 @@
/*
ZOOM-WINDOW.hpp - generic translation from domain to screen coordinates
Copyright (C) Lumiera.org
2018, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/** @file zoom-window.hpp
** Abstraction: a multi-dimensional extract from model space into screen coordinates.
** This is a generic component to represent and handle the zooming and positioning of
** views within an underlying model space. This model space is conceived to be two fold:
** - it is a place or excerpt within the model topology (e.g. the n-th track in the fork)
** - it has a temporal extension within a larger temporal frame (e.g. some seconds within the timeline)
**
** ## rationale
**
** TBW
**
** ## Interactions
**
** - *bla*: connect to blubb
** see [sigc-track] for an explanation.
**
** [MVC-Pattern]: http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
** [sigc-track]: http://issues.lumiera.org/ticket/940#comment:3 "Ticket #940"
**
** @see \ref ZoomWindow_test
**
*/
#ifndef STAGE_MODEL_ZOOM_WINDOW_H
#define STAGE_MODEL_ZOOM_WINDOW_H
#include "lib/error.hpp"
//#include "lib/nocopy.hpp"
//#include "lib/idi/entry-id.hpp"
//#include "lib/symbol.hpp"
//#include <utility>
//#include <string>
namespace stage {
namespace model {
// using std::string;
// using lib::Symbol;
/**
*/
struct ZoomWindow
{
ZoomWindow()
{ }
void reset();
protected:
private:
};
/** */
}} // namespace stage::model
#endif /*STAGE_MODEL_ZOOM_WINDOW_H*/

View file

@ -0,0 +1,82 @@
/*
DisplayManager - abstraction to translate model structure and extension into screen layout
Copyright (C) Lumiera.org
2018, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
/** @file display-manager.cpp
** Implementation details regarding timeline layout management and widget coordination.
**
** @todo WIP-WIP-WIP as of 11/2018
** @todo as of 10/2018 timeline display in the UI is rebuilt to match the architecture
**
*/
#include "stage/gtk-base.hpp"
#include "stage/timeline/display-manager.hpp"
//#include "gui/ui-bus.hpp"
//#include "lib/format-string.hpp"
//#include "lib/format-cout.hpp"
//#include "lib/util.hpp"
//#include <algorithm>
//#include <vector>
//using util::_Fmt;
//using util::contains;
//using Gtk::Widget;
//using sigc::mem_fun;
//using sigc::ptr_fun;
//using std::cout;
//using std::endl;
namespace stage {
namespace timeline {
DisplayManager::~DisplayManager() { } // emit VTables here....
//DisplayManager::DisplayManager()
// : paneSplitPosition_{topLevelContainer.property_position()}
// , bodyCanvas_{}
// , headerPane_{bodyCanvas_.get_vadjustment()} // wire the header pane (Gtk::Viewport) to follow the body vertical scroll movement
// {
// topLevelContainer.add1 (headerPane_);
// topLevelContainer.add2 (bodyCanvas_);
// }
/**
* This function is
*/
}}// namespace stage::timeline

View file

@ -0,0 +1,94 @@
/*
DISPLAY-MANAGER.hpp - abstraction to translate model structure and extension into screen layout
Copyright (C) Lumiera.org
2018, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/** @file display-manager.hpp
** Abstraction: service for the widgets to translate themselves into screen layout.
**
** # Architecture
**
** We strive to break up the whole process of controlling the layout into several
** local concerns, each of which can be made self contained. The backbone is formed by
** a recursive collaboration between two abstractions (interfaces)
** - the building blocks of the timeline expose the interface timeline::Element
** - the global timeline widget implements a timeline::LayoutManager interface
**
** ## Display evaluation pass
**
** Whenever the layout of timeline contents has to be (re)established, we trigger a recursive
** evaluation pass, which in fact is a tree walk. The layout manager creates a DisplayEvaluation
** record, which is passed to the [Element's allocate function](\ref Element::allocate). The element
** in turn has the liability to walk its children and recursively initiate a nested evaluation
** by invoking DisplayEvaluation::evaluateChild(Element), which in turn calls back to
** LayoutManager::evaluate() to initiate a recursive evaluation pass. Within the recursively
** created DisplayEvaluation elements, we are able to transport and aggregate information
** necessary to give each element it' screen allocation. And this in turn allows us to
** decide upon a suitable display strategy for each individual element, within a local
** and self-contained context.
**
** @todo WIP-WIP-WIP as of 11/2018
** @todo as of 10/2018 timeline display in the UI is rebuilt to match the architecture
**
*/
#ifndef STAGE_TIMELINE_DISPLAY_MANAGER_H
#define STAGE_TIMELINE_DISPLAY_MANAGER_H
#include "lib/error.hpp"
#include "lib/nocopy.hpp"
//#include "lib/util.hpp"
//#include <memory>
//#include <vector>
namespace stage {
namespace timeline {
// class TrackHeadWidget;
/**
* Interface used by the widgets to translate themselves into screen layout.
* @todo WIP-WIP as of 11/2018
*/
class DisplayManager
: util::NonCopyable
{
// TimelineLayout();
public:
virtual ~DisplayManager(); ///< this is an interface
private:/* ===== Internals ===== */
};
}}// namespace stage::timeline
#endif /*STAGE_TIMELINE_DISPLAY_MANAGER_H*/

View file

@ -83,6 +83,7 @@
#define STAGE_TIMELINE_TIMELINE_LAYOUT_H
#include "stage/gtk-base.hpp"
#include "stage/timeline/display-manager.hpp"
#include "stage/timeline/header-pane-widget.hpp"
#include "stage/timeline/body-canvas-widget.hpp"
@ -107,6 +108,7 @@ namespace timeline {
* @todo WIP-WIP as of 10/2018
*/
class TimelineLayout
: public DisplayManager
{
Glib::PropertyProxy<int> paneSplitPosition_;
@ -121,6 +123,8 @@ namespace timeline {
/** @internal anchor the display of the root track into the two display panes */
void installRootTrack (TrackHeadWidget&,TrackBody&);
protected:/* ==== Interface: LayoutManager===== */
private:/* ===== Internals ===== */
};

View file

@ -111,14 +111,14 @@ namespace session {
const RandID forkRootID{stage::ATTR_fork};
const GenNode timeline = emptyTimeline (baseID, forkRootID)
, rootTrackName = GenNode{string{stage::ATTR_name}, "Track-"+baseID}
, FORK_ROOT = MakeRec().genNode(forkRootID)
, forkRoot = MakeRec().genNode(forkRootID)
;
return MutationMessage{ ins (timeline)
, mut (timeline)
, mut (FORK_ROOT)
, mut (forkRoot)
, set (rootTrackName)
, emu (FORK_ROOT)
, emu (forkRoot)
, emu (timeline)
};
}

View file

@ -0,0 +1,93 @@
/*
ZoomWindow(Test) - verify translation from model to screen coordinates
Copyright (C) Lumiera.org
2018, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
/** @file zoom-window-test.cpp
** unit test \ref ZoomWindow_test
*/
#include "lib/test/run.hpp"
#include "lib/test/test-helper.hpp"
#include "stage/model/zoom-window.hpp"
//#include "lib/util.hpp"
//#include <utility>
//#include <memory>
//using util::isSameObject;
//using std::make_unique;
//using std::move;
namespace stage{
namespace model{
namespace test {
namespace { // Test fixture...
// template<typename X>
// struct DummyWidget
// : public sigc::trackable
// {
// X val = 1 + rand() % 100;
// };
}
/*************************************************************************************//**
* @test verify technicalities regarding the translation between domain model coordinates
* and screen layout coordinates.
* - bla
* - blubb
* @see zoom-window.hpp
*/
class ZoomWindow_test : public Test
{
virtual void
run (Arg)
{
verify_standardUsage();
}
/** @test the standard use case is to.... TBW
*/
void
verify_standardUsage()
{
}
/** @test */
};
/** Register this test class... */
LAUNCHER (ZoomWindow_test, "unit gui");
}}} // namespace stage::model::test

View file

@ -9078,13 +9078,18 @@ Besides building on the asset management, implementing Timeline (and Sequence) a
This topic is {{red{postponed as of 10/2018}}} &amp;rarr; [[#1083|http://issues.lumiera.org/ticket/1083]]
</pre>
</div>
<div title="TimelineDisplayManager" creator="Ichthyostega" modifier="Ichthyostega" created="201611280235" modified="201810281443" tags="spec GuiPattern img" changecount="5">
<div title="TimelineDisplayManager" creator="Ichthyostega" modifier="Ichthyostega" created="201611280235" modified="201811101600" tags="spec GuiPattern img" changecount="8">
<pre>//guide and control the concrete display properties of the various sub components (tracks, clips) comprising a timeline display.//
The TimelineDisplayManager actually is an abstraction, a control interface, revolving around the guidance individual components need in order to settle on a proper display. Those components are represented as mediating entities, the TrackPresenter and the ClipPresenter, each of which controls and manages a mostly passive GTK widget. To this end, the presenters need to know at which virtual coordinates their corresponding widgets would show up, and they need to know if these widgets need to be actually present at the moment. Also, especially the ClipPresenter needs to know which ''clip appearance style'' to choose for the corresponding slave widget.
!display evaluation pass
[&gt;img[Clip presentation control|uml/Timeline-display-evaluation.png]]Since the timeline display is formed by several nested collections of elements, a proper display layout must incorporate information from all those parts. A naive approach likely would just iterate over them and reach in to extract data -- or even worse, build a separate display data store, which then needs to be kept in sync with the component hierarchy. Any of these naive working styles would lead to high coupling and it turns the necessary adjustment and changes into a liability, which raises due to evolution of requirements. Over time, such a dangerous situation can only be avoided altogether by admitting the collaborative nature of the task at hand. To get there, we need to distil the abstraction shared between the global and the local concerns, and we need to shape it such as to build onto some kind of invariant, allowing that abstraction to re-emerge at several levels of locality.
!translation service for the widgets
Another, closely related topic, handled within this context, is the translation from model structures and units in to display layout coordinates. Within the model, we can distinguish several dimensions (degrees of freedom). For one, there is the topology, the ''location or part'' of the model to expose through the UI. Moreover, there is the ''degree of detail'' for this UI representation. And then, there is the ''temporal position and extension'' to represent.
By principle, //widgets always work exclusively in pixel coordinates// -- thus we need the help of a coordinating entity to find out where some entity shall be located on the GTK drawing canvas. This becomes especially relevant for the timeline body, since there we're relying on a GuiCustomWidget to perform and control some of the UI drawing by specific custom rules and procedures.
</pre>
</div>
<div title="TimelineSequences" modifier="Ichthyostega" created="200811011836" modified="201505310138" tags="design decision img" changecount="4">

View file

@ -17901,7 +17901,8 @@
<i>Standard</i>&#160;UI-Mechanik &#252;berlassen wir GTK
</p>
</body>
</html></richcontent>
</html>
</richcontent>
<richcontent TYPE="NOTE"><html>
<head>
@ -17917,7 +17918,8 @@
Aus Gr&#252;nden der Konsistenz und Zukunftsf&#228;higkeit
</p>
</body>
</html></richcontent>
</html>
</richcontent>
</node>
<node CREATED="1541858088132" ID="ID_303565989" MODIFIED="1541858326966">
<richcontent TYPE="NODE"><html>
@ -17929,7 +17931,8 @@
unser <b>InteractionControl</b>&#160;ist eine Zwischenschicht
</p>
</body>
</html></richcontent>
</html>
</richcontent>
<richcontent TYPE="NOTE"><html>
<head>
@ -17950,7 +17953,8 @@
</li>
</ul>
</body>
</html></richcontent>
</html>
</richcontent>
</node>
</node>
</node>
@ -19089,7 +19093,7 @@
<node CREATED="1541857340976" ID="ID_433103364" MODIFIED="1541857347211" TEXT="Lumiera Time Framework">
<node CREATED="1541857349526" ID="ID_1259099260" MODIFIED="1541857355010" TEXT="bietet Konzept &quot;Grid&quot;"/>
</node>
<node CREATED="1541861495569" ID="ID_1949450244" MODIFIED="1542309879488" TEXT="generische ZoomWindow-Komponente">
<node CREATED="1541861495569" ID="ID_1949450244" MODIFIED="1541861631284" TEXT="generische ZoomWindow-Komponente">
<arrowlink COLOR="#5b5ca1" DESTINATION="ID_838803024" ENDARROW="Default" ENDINCLINATION="-519;-1168;" ID="Arrow_ID_1674512697" STARTARROW="None" STARTINCLINATION="490;0;"/>
</node>
<node CREATED="1541857367446" ID="ID_34718193" MODIFIED="1541857371325" TEXT="Anfragen">
@ -19461,7 +19465,7 @@
</node>
<node CREATED="1541861481967" ID="ID_1316730142" MODIFIED="1541861716241" TEXT="Feststellen der Canvas-Position">
<arrowlink COLOR="#2a79c1" DESTINATION="ID_1038931568" ENDARROW="Default" ENDINCLINATION="-511;19;" ID="Arrow_ID_1052516165" STARTARROW="None" STARTINCLINATION="-253;-12;"/>
<node CREATED="1541862243012" ID="ID_400560063" MODIFIED="1542309934167" TEXT="Canvas kennt seine eigene Ausdehnung (in Pixeln)">
<node CREATED="1541862243012" ID="ID_400560063" MODIFIED="1541862257541" TEXT="Canvas kennt seine eigene Ausdehnung (in Pixeln)">
<linktarget COLOR="#60749f" DESTINATION="ID_400560063" ENDARROW="Default" ENDINCLINATION="-46;0;" ID="Arrow_ID_449772156" SOURCE="ID_1283622298" STARTARROW="None" STARTINCLINATION="-13;18;"/>
</node>
<node CREATED="1541861743088" ID="ID_1696653468" MODIFIED="1541865199414" TEXT="Display-Manager">
@ -21295,8 +21299,8 @@
<node CREATED="1488423493014" ID="ID_64529473" MODIFIED="1518487921085" TEXT="Navigation"/>
<node CREATED="1488423514355" ID="ID_917891687" MODIFIED="1518487921085" TEXT="Steuerelemente">
<node CREATED="1541858529489" ID="ID_838803024" MODIFIED="1541861634012" TEXT="ZoomWindow">
<linktarget COLOR="#5b5ca1" DESTINATION="ID_838803024" ENDARROW="Default" ENDINCLINATION="-519;-1168;" ID="Arrow_ID_1674512697" SOURCE="ID_1949450244" STARTARROW="None" STARTINCLINATION="490;0;"/>
<linktarget COLOR="#5b5ca1" DESTINATION="ID_838803024" ENDARROW="Default" ENDINCLINATION="-499;-1329;" ID="Arrow_ID_842684168" SOURCE="ID_1828075998" STARTARROW="None" STARTINCLINATION="490;0;"/>
<linktarget COLOR="#5b5ca1" DESTINATION="ID_838803024" ENDARROW="Default" ENDINCLINATION="-519;-1168;" ID="Arrow_ID_1674512697" SOURCE="ID_1949450244" STARTARROW="None" STARTINCLINATION="490;0;"/>
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1541858541550" ID="ID_1912142591" MODIFIED="1541858559935" TEXT="generische Abstraktionskomponente">
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="yes"/>
@ -21325,7 +21329,7 @@
<node CREATED="1541859280000" ID="ID_1932782561" MODIFIED="1541859283008" TEXT="playhead"/>
<node CREATED="1541859284069" ID="ID_299608050" MODIFIED="1541859293743" TEXT="mouse"/>
</node>
<node CREATED="1541859608646" ID="ID_412475230" MODIFIED="1542384357227" TEXT="time translation anchor point">
<node CREATED="1541859608646" ID="ID_412475230" MODIFIED="1541859614182" TEXT="time translation anchor point">
<node CREATED="1542384728240" ID="ID_538080146" MODIFIED="1542384737841" TEXT="nicht der Nullpunkt derZeitskala"/>
<node CREATED="1542384738364" ID="ID_922112299" MODIFIED="1542384750313" TEXT="sondern der Bezugspunkt f&#xfc;r die &#xdc;bersetzung Zeit -&gt; Pixel"/>
</node>
@ -21418,7 +21422,7 @@
<node CREATED="1541860828603" ID="ID_111513506" MODIFIED="1541860839002" TEXT="Zeit"/>
<node CREATED="1541860831875" ID="ID_1775831703" MODIFIED="1541860835311" TEXT="Extension"/>
</node>
<node CREATED="1541860818012" FOLDED="true" ID="ID_814200290" MODIFIED="1544127129504" TEXT="vertikale Dimension stets topologisch">
<node CREATED="1541860818012" FOLDED="true" ID="ID_814200290" MODIFIED="1541860825864" TEXT="vertikale Dimension stets topologisch">
<node CREATED="1544127119809" ID="ID_431805088" MODIFIED="1544127122858" TEXT="nicht immer...."/>
<node CREATED="1544127123803" ID="ID_1360167609" MODIFIED="1544127127665" TEXT="Ausnahme: Kurven"/>
</node>
@ -21466,7 +21470,7 @@
<font ITALIC="true" NAME="SansSerif" SIZE="12"/>
</node>
<node CREATED="1541860985526" ID="ID_640984391" MODIFIED="1541861006543" TEXT="Struct mit Methoden"/>
<node CREATED="1541861314456" ID="ID_267107783" MODIFIED="1544310842808" TEXT="generisch">
<node CREATED="1541861314456" ID="ID_267107783" MODIFIED="1541861376398" TEXT="generisch">
<richcontent TYPE="NOTE"><html>
<head>