Structure-Change: push a set of suitable ViewHook-Interfaces into the DisplayFrame

...actual Operations not yet implemented (but trivial to implement in the end)
This commit is contained in:
Fischlurch 2019-12-20 22:15:35 +01:00
parent 33a19c404b
commit c5d0ddb01b
10 changed files with 227 additions and 53 deletions

View file

@ -69,6 +69,7 @@ namespace timeline {
using util::max;
using model::ViewHooked;
class TrackHeadWidget;
class TrackBody;

View file

@ -89,10 +89,7 @@ namespace timeline {
: Controller{identity, nexus}
, name_{identity.getSym()} // fallback initialise name from human-readable ID symbol
, markers_{}
, fork_{new TrackPresenter{trackID, nexus, [&](TrackHeadWidget& head,TrackBody& body)
{
layoutManager.installRootTrack (head, body);
}}}
, fork_{new TrackPresenter{trackID, nexus, layoutManager}}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1201 : test/code... remove this
, DEBUG_canvas_{layoutManager.exposeCanvasForDebug()}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1201 : test/code... remove this

View file

@ -101,8 +101,6 @@ namespace timeline {
class TrackHeadWidget;
class TrackBody;
using model::ViewHooked;
/**
* Top-level anchor point for the timeline display (widgets).

View file

@ -107,6 +107,34 @@ namespace timeline {
}
/* ==== Interface: ViewHook ===== */
void
TrackBody::hook (TrackBody& subBody, int xPos, int yPos)
{
UNIMPLEMENTED ("attach sub-TrackBody");
}
void
TrackBody::move (TrackBody& subBody, int xPos, int yPos)
{
NOTREACHED ("woot?? can we even move a sub-TrackBody????");
}
void
TrackBody::remove (TrackBody& subBody)
{
UNIMPLEMENTED ("detach sub-TrackBody");
}
void
TrackBody::rehook (ViewHooked<TrackBody>& subBody) noexcept
{
UNIMPLEMENTED ("re-attach sub-TrackBody");
}
/* ==== Code for vertical track display layout ==== */
/**
* recursively calculate the height in pixels to display this track,

View file

@ -92,6 +92,7 @@ namespace timeline {
* @todo WIP-WIP as of 6/2019
*/
class TrackBody
: public model::ViewHook<TrackBody>
{
uint contentHeight_;
uint contentOffset_;
@ -117,13 +118,21 @@ namespace timeline {
uint calcRulerHeight();
uint calcHeight();
uint getContentOffsetY() { return startLine_; }
DisplayManager::SignalStructureChange signalStructureChange_;
private:/* ===== Internals ===== */
/* ==== Interface: ViewHook ===== */
void hook (TrackBody&, int xPos=0, int yPos=0) override;
void move (TrackBody&, int xPos, int yPos) override;
void remove (TrackBody&) override;
void rehook (ViewHooked<TrackBody>&) noexcept override;
/* ===== Internals ===== */
/**
* Allow the TrackPresenter to manage the rulers
* @internal Allow the TrackPresenter to manage the rulers
* The collection of rulers is part of the systematic UI model
* and thus formally a direct child of the TrackPresenter; however they
* are only relevant for the immediate display and interaction mechanics,
@ -138,7 +147,6 @@ namespace timeline {
return rulers_;
}
friend class TrackPresenter;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1201 : test/code... remove this
uString TODO_trackName_;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1201 : test/code... remove this

View file

@ -112,5 +112,32 @@ namespace timeline {
}
/* ==== Interface: ViewHook ===== */
void
TrackHeadWidget::hook (TrackHeadWidget& subHead, int xPos, int yPos)
{
UNIMPLEMENTED ("attach sub-TrackHead");
}
void
TrackHeadWidget::move (TrackHeadWidget& subHead, int xPos, int yPos)
{
NOTREACHED ("woot?? can we even move a sub-TrackHead????");
}
void
TrackHeadWidget::remove (TrackHeadWidget& subHead)
{
UNIMPLEMENTED ("detach sub-TrackHead");
}
void
TrackHeadWidget::rehook (ViewHooked<TrackHeadWidget>& hookedSubHead) noexcept
{
UNIMPLEMENTED ("re-attach sub-TrackHead");
}
}}// namespace stage::timeline

View file

@ -48,6 +48,7 @@
#include "stage/gtk-base.hpp"
#include "stage/ctrl/bus-term.hpp"
#include "stage/model/view-hook.hpp"
//#include "lib/util.hpp"
@ -60,6 +61,7 @@ namespace stage {
namespace timeline {
using ID = ctrl::BusTerm::ID;
using model::ViewHooked;
/**
* Header pane control area corresponding to a Track with nested child Tracks.
@ -70,12 +72,20 @@ namespace timeline {
*/
class TrackHeadWidget
: public Gtk::Grid
, public model::ViewHook<TrackHeadWidget>
{
Gtk::Label nameTODO_;
Gtk::Label treeTODO_;
uint childCnt_;
/* ==== Interface: ViewHook ===== */
void hook (TrackHeadWidget&, int xPos=0, int yPos=0) override;
void move (TrackHeadWidget&, int xPos, int yPos) override;
void remove (TrackHeadWidget&) override;
void rehook (ViewHooked<TrackHeadWidget>&) noexcept override;
public:
TrackHeadWidget();
~TrackHeadWidget();

View file

@ -85,7 +85,8 @@ namespace timeline {
void
TrackPresenter::injectDebugTrackLabels(BodyCanvasWidget& bodyCanvas)
{
bodyCanvas.DEBUG_injectTrackLabel (display_.body.TODO_trackName_, display_.body.startLine_ + display_.body.contentOffset_);
///////////////////////////TODO TOD-oh
// bodyCanvas.DEBUG_injectTrackLabel (display_.body_.TODO_trackName_, display_.body_.startLine_ + display_.body_.contentOffset_);
for (auto& subTrack : subFork_)
subTrack->injectDebugTrackLabels (bodyCanvas);
}
@ -109,7 +110,7 @@ namespace timeline {
buffer.create (
TreeMutator::build()
.attach (collection(display_.body.bindRulers())
.attach (collection(display_.bindRulers())
.isApplicableIf ([&](GenNode const& spec) -> bool
{ // »Selector« : require object-like sub scope with type-field "Ruler"
return TYPE_Ruler == spec.data.recordType();
@ -177,12 +178,7 @@ namespace timeline {
})
.constructFrom ([&](GenNode const& spec) -> PFork
{
return make_unique<TrackPresenter> (spec.idi
,this->uiBus_
,[&](TrackHeadWidget& head,TrackBody& body)
{
display_.injectSubTrack (head, body);
});
return make_unique<TrackPresenter> (spec.idi, uiBus_, this->display_);
})
.buildChildMutator ([&](PFork& target, GenNode::ID const& subID, TreeMutator::Handle buff) -> bool
{

View file

@ -74,43 +74,103 @@ namespace timeline {
/**
* Reference frame to organise the display related to a specific Track in the Timeline-GUI.
* ViewHook decorator to apply a (dynamic) offset
* when attaching or moving Widgets on the shared canvas.
*/
class CanvasOffsetHook
: public model::ViewHook<Gtk::Widget>
{
model::ViewHook<Gtk::Widget>& refHook_;
/* ==== Interface: ViewHook ===== */
void
hook (Gtk::Widget& widget, int xPos=0, int yPos=0) override
{
refHook_.hook (widget, hookAdjX (xPos), hookAdjY (yPos));
}
void
move (Gtk::Widget& widget, int xPos, int yPos) override
{
refHook_.move (widget, hookAdjX (xPos), hookAdjY (yPos));
}
void
remove (Gtk::Widget& widget) override
{
refHook_.remove (widget);
}
void
rehook (ViewHooked<Gtk::Widget>& hookedWidget) noexcept override
{
refHook_.rehook (hookedWidget);
}
protected: /* === extended Interface for relative view hook === */
virtual int hookAdjX (int xPos) =0;
virtual int hookAdjY (int yPos) =0;
public:
CanvasOffsetHook(model::ViewHook<Gtk::Widget>& refHook)
: refHook_{refHook}
{ }
};
/**
* Reference frame to organise the presentation related to a specific Track in the Timeline-GUI.
* With the help of such a common frame of reference, we solve the problem that each individual
* track display needs to hook into two distinct UI presentation structures: the track head controls
* and the presentation of track contents on the BodyCanvasWidget.
*/
struct DisplayFrame
class DisplayFrame
: util::NonCopyable
, public DisplayViewHooks
, public CanvasOffsetHook
{
TrackHeadWidget head;
TrackBody body;
TrackHeadWidget head_;
TrackBody body_;
template<class FUN>
DisplayFrame (FUN anchorDisplay)
: head{}
, body{}
{
anchorDisplay (head, body);
}
/* ==== Interface: DisplayViewHooks===== */
~DisplayFrame()
{
// Note: ~TrackBody triggers DisplayManager::signalStructureChange_()
TODO ("cause the managed presentation elements to detach from their parents");
} ///////////////////////////////////TICKET #1198 -- clarify to what extent esp. the header widgets need to be actively removed from the display structure. Is it sufficient just to kill the TrackHeadWidget
model::ViewHook<TrackHeadWidget>& getHeadHook() override { return head_; };
model::ViewHook<TrackBody>& getBodyHook() override { return body_; };
model::ViewHook<Gtk::Widget>& getClipHook() override { return *this; };
/* === extended Interface for relative view hook === */
int hookAdjX (int xPos) override { return xPos; };
int hookAdjY (int yPos) override { return yPos + body_.getContentOffsetY(); };
public:
DisplayFrame (DisplayViewHooks& displayAnchor)
: CanvasOffsetHook{displayAnchor.getClipHook()}
, head_{}
, body_{}
{ }
void
setTrackName (cuString& name)
{
head.setTrackName (name);
body.setTrackName (name); ///////////////////////////////////TICKET #1017 -- TODO 11/18 : not clear yet if TrackBody needs to know its name
head_.setTrackName (name);
body_.setTrackName (name); ///////////////////////////////////TICKET #1017 -- TODO 11/18 : not clear yet if TrackBody needs to know its name
}
void
injectSubTrack (TrackHeadWidget& subHead, TrackBody& subBody)
{
head.injectSubFork (subHead);
body.attachSubTrack (&subBody);
head_.injectSubFork (subHead);
body_.attachSubTrack (&subBody);
}
vector<unique_ptr<RulerTrack>>&
bindRulers()
{
return body_.bindRulers();
}
};
@ -136,10 +196,9 @@ namespace timeline {
* @param nexus a way to connect this Controller to the UI-Bus.
* @param anchorDisplay a one-way closure to attach into the display fabric
*/
template<class FUN>
TrackPresenter (ID id, ctrl::BusTerm& nexus, FUN anchorDisplay)
TrackPresenter (ID id, ctrl::BusTerm& nexus, DisplayViewHooks& displayAnchor)
: Controller{id, nexus}
, display_{anchorDisplay}
, display_{displayAnchor}
, subFork_{}
, markers_{}
, clips_{}

View file

@ -21435,7 +21435,7 @@
</body>
</html></richcontent>
<arrowlink COLOR="#5f74b7" DESTINATION="ID_1964864197" ENDARROW="Default" ENDINCLINATION="-1024;0;" ID="Arrow_ID_465735263" STARTARROW="None" STARTINCLINATION="-717;0;"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1573315138011" ID="ID_1957325688" MODIFIED="1575652920080" TEXT="brauchen wir hier eine Erweiterung auf mehrere Typen...?">
<node COLOR="#435e98" CREATED="1573315138011" FOLDED="true" ID="ID_1957325688" MODIFIED="1576876407022" TEXT="brauchen wir hier eine Erweiterung auf mehrere Typen...?">
<arrowlink COLOR="#684be4" DESTINATION="ID_1458279581" ENDARROW="Default" ENDINCLINATION="-1681;0;" ID="Arrow_ID_1672277618" STARTARROW="None" STARTINCLINATION="788;-76;"/>
<icon BUILTIN="help"/>
<node CREATED="1575652924086" ID="ID_996829512" MODIFIED="1575653116780" TEXT="Antwort: im Prinzip ja">
@ -21464,11 +21464,34 @@
<icon BUILTIN="stop-sign"/>
</node>
<node CREATED="1575653121588" ID="ID_46973905" MODIFIED="1575653151603" TEXT="also bleibt nur, die Typisierung in den Funktions-Signaturen explizit auszudr&#xfc;cken"/>
<node CREATED="1576876291037" ID="ID_114617089" MODIFIED="1576876404029" TEXT="dieses Problem versuchen wir, &quot;pragmatisch auszusitzen&quot;">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Streng genommen w&#252;rden wir in der Tat einen generischen Quer-Zugriffsmechanismus brauchen.
</p>
<p>
Allerdings ist dieser entweder nicht implementierbar, oder, wenn implementierbar, dann auch redundant.
</p>
<p>
Und zudem kristallisiert sich bereits heraus, da&#223; wir es nicht mit einem &quot;Universum&quot; generischer Typen zu tun bekommen, sondern mit einer kleinen Auswahl, f&#252;r die wir halt dann die Quer-Verbindungen direkt auscoden und gut is...
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="yes"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1575065263201" ID="ID_1640997956" MODIFIED="1575065274457" TEXT="zu kl&#xe4;ren: Zugang zu diesem ViewHook">
<icon BUILTIN="flag-yellow"/>
</node>
<node COLOR="#338800" CREATED="1575065263201" FOLDED="true" ID="ID_1640997956" MODIFIED="1576876415142" TEXT="zu kl&#xe4;ren: Zugang zu diesem ViewHook">
<icon BUILTIN="button_ok"/>
<node CREATED="1575653188938" ID="ID_619809248" MODIFIED="1575653206332" TEXT="es l&#xe4;uft darauf hinaus, den Zugang in den DisplayFrames zusammenzufassen"/>
<node CREATED="1575653207328" ID="ID_1942901156" MODIFIED="1575653233600" TEXT="diese m&#xfc;ssen daher eine Referenz auf einen &quot;irgendwo vorhandenen&quot; Timeline-ViewHook haben"/>
<node CREATED="1575653207328" ID="ID_1942901156" MODIFIED="1576876278735" TEXT="diese brauchen daher eine Referenz auf einen &quot;irgendwo vorhandenen&quot; Timeline-ViewHook"/>
<node COLOR="#338800" CREATED="1576876251659" ID="ID_1249561924" MODIFIED="1576876267532" TEXT="und tats&#xe4;chlich bekommen sie diesen per verketteter Initialisierung">
<icon BUILTIN="button_ok"/>
</node>
</node>
</node>
<node CREATED="1563467398036" ID="ID_828698459" MODIFIED="1563467403607" TEXT="Implementierung">
@ -21817,10 +21840,28 @@
<arrowlink COLOR="#507b9b" DESTINATION="ID_1193961919" ENDARROW="Default" ENDINCLINATION="-877;88;" ID="Arrow_ID_624713040" STARTARROW="None" STARTINCLINATION="706;62;"/>
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1576757730509" ID="ID_1816490333" MODIFIED="1576758006669" TEXT="Thema &#xbb;Widget-Position&#xab;">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1576757730509" ID="ID_1816490333" MODIFIED="1576876200239" TEXT="Thema &#xbb;Widget-Position&#xab;">
<arrowlink COLOR="#605bb8" DESTINATION="ID_1949130658" ENDARROW="Default" ENDINCLINATION="204;611;" ID="Arrow_ID_993970158" STARTARROW="None" STARTINCLINATION="512;51;"/>
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1576758030604" HGAP="54" ID="ID_1869378616" MODIFIED="1576758051786" TEXT="entsprechende Erweiterung f&#xfc;r delegating-ViewHook notwendig" VSHIFT="26">
<linktarget COLOR="#15bcc9" DESTINATION="ID_1816490333" ENDARROW="Default" ENDINCLINATION="-785;86;" ID="Arrow_ID_408864676" SOURCE="ID_1121301646" STARTARROW="None" STARTINCLINATION="-225;17;"/>
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1576758030604" HGAP="54" ID="ID_1869378616" MODIFIED="1576876023320" TEXT="entsprechende Erweiterung f&#xfc;r delegating-ViewHook notwendig" VSHIFT="26">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1576876029833" HGAP="57" ID="ID_893654405" MODIFIED="1576876116458" TEXT="kl&#xe4;ren: brauchen wir verschiedene Offsets per Typ" VSHIFT="3">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
also einen speziellen Offset f&#252;r Clips und einen anderen speziellen Offset f&#252;r Effekt-Marker?
</p>
<p>
Oder, anders, wie bekommen wir diese Dinger jeweils in den richtigen unter-Bereich des Track-Layouts??
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="flag-yellow"/>
</node>
</node>
@ -21879,8 +21920,8 @@
<node CREATED="1576705652570" ID="ID_551481195" MODIFIED="1576705666257" TEXT="ViewHook&lt;Widget&gt;">
<icon BUILTIN="info"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1576705712654" ID="ID_1745971143" MODIFIED="1576705720810" TEXT="implementieren im TrackCanvas">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1576705712654" ID="ID_1745971143" MODIFIED="1576876014371" TEXT="implementieren im TrackCanvas">
<icon BUILTIN="flag-pink"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1576705413085" ID="ID_1979905155" MODIFIED="1576705430397" TEXT="Konstruktor / &quot;ein-H&#xe4;kel&quot;-Mchanismus darauf umstellen">
@ -21895,7 +21936,8 @@
<icon BUILTIN="smily_bad"/>
</node>
<node CREATED="1576760324713" ID="ID_1267786696" MODIFIED="1576760340354" TEXT="einziger Ausweg... Display-Manager wird zum Super-Hook"/>
<node COLOR="#338800" CREATED="1576806720057" ID="ID_805988831" MODIFIED="1576855579888" TEXT="noch besser: das in ein Sammel-Interface packen">
<node COLOR="#338800" CREATED="1576806720057" ID="ID_805988831" MODIFIED="1576875959056" TEXT="noch besser: das in ein Sammel-Interface packen">
<linktarget COLOR="#67d289" DESTINATION="ID_805988831" ENDARROW="Default" ENDINCLINATION="-36;221;" ID="Arrow_ID_909815140" SOURCE="ID_1966295709" STARTARROW="None" STARTINCLINATION="495;16;"/>
<icon BUILTIN="idea"/>
<node CREATED="1576806744893" ID="ID_526365809" MODIFIED="1576855570801" TEXT="vielleicht sogar ein Accessor-Interface">
<icon BUILTIN="idea"/>
@ -21919,7 +21961,7 @@
</node>
</node>
</node>
<node CREATED="1576710544415" ID="ID_88564726" MODIFIED="1576710556729" TEXT="zwei F&#xe4;lle zu unterscheiden">
<node CREATED="1576710544415" FOLDED="true" ID="ID_88564726" MODIFIED="1576875999707" TEXT="zwei F&#xe4;lle zu unterscheiden">
<icon BUILTIN="idea"/>
<node CREATED="1576710558354" ID="ID_146653361" MODIFIED="1576710566077" TEXT="top-Level">
<node CREATED="1576710810240" ID="ID_1493306680" MODIFIED="1576710989724" TEXT="bisher...">
@ -21963,7 +22005,14 @@
</node>
</node>
</node>
<node CREATED="1576710566905" ID="ID_1380718144" MODIFIED="1576710570556" TEXT="Rekursion"/>
<node CREATED="1576710566905" ID="ID_1380718144" MODIFIED="1576710570556" TEXT="Rekursion">
<node CREATED="1576875874270" ID="ID_345044928" MODIFIED="1576875883513" TEXT="unproblematisch"/>
<node CREATED="1576875884389" ID="ID_209901177" MODIFIED="1576875891784" TEXT="basierend auf der L&#xf6;sung f&#xfc;r top-Level"/>
<node CREATED="1576875892588" ID="ID_1966295709" MODIFIED="1576875968903" TEXT="DisplayFrame selber implementiert wieder das DisplayViewHooks Sammel-Interface">
<arrowlink COLOR="#67d289" DESTINATION="ID_805988831" ENDARROW="Default" ENDINCLINATION="-36;221;" ID="Arrow_ID_909815140" STARTARROW="None" STARTINCLINATION="495;16;"/>
<icon BUILTIN="idea"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1576753128134" ID="ID_1066136383" MODIFIED="1576753147236" TEXT="signalStructureChange_ anders l&#xf6;sen">
<icon BUILTIN="flag-yellow"/>
@ -22045,7 +22094,8 @@
<node CREATED="1576705779910" ID="ID_968522268" MODIFIED="1576705792920" TEXT="damit ViewHook&lt;Clip&gt;"/>
<node CREATED="1576705802515" ID="ID_674496871" MODIFIED="1576705809765" TEXT="und ViewHook&lt;Marker&gt;"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1576855620250" ID="ID_1121301646" MODIFIED="1576855705548" TEXT="relatives Positionieren erm&#xf6;glichen">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1576855620250" ID="ID_1121301646" MODIFIED="1576876200239" TEXT="relatives Positionieren erm&#xf6;glichen">
<arrowlink COLOR="#15bcc9" DESTINATION="ID_1816490333" ENDARROW="Default" ENDINCLINATION="-785;86;" ID="Arrow_ID_408864676" STARTARROW="None" STARTINCLINATION="-225;17;"/>
<linktarget COLOR="#6780d3" DESTINATION="ID_1121301646" ENDARROW="Default" ENDINCLINATION="551;-498;" ID="Arrow_ID_229033893" SOURCE="ID_1642579599" STARTARROW="None" STARTINCLINATION="-477;21;"/>
<icon BUILTIN="flag-yellow"/>
</node>