diff --git a/src/gui/dialog/test-control.hpp b/src/gui/dialog/test-control.hpp index 039c00ad3..f9644b474 100644 --- a/src/gui/dialog/test-control.hpp +++ b/src/gui/dialog/test-control.hpp @@ -105,7 +105,7 @@ namespace dialog { /** * Helper widget to simplify construction and wiring of a [Notebook] widget. * Gtk::Notebook is quite powerful container foundation to build complex dialog widgets with - * multiple pages on tabs. However, the construction, wiring an setup is notoriously tedious, + * multiple pages on tabs. However, the construction, wiring and setup is notoriously tedious, * due to the repetitiveness and the sheer amount of child widgets spread over various pages. * * This design draft is an attempt to mitigate the required boilerplate, without overly much @@ -157,10 +157,10 @@ namespace dialog { /** * Ticket #1099 : perform a dummy round-trip to verify Proc-GUI integration. - * This routine invokes the command `test_meta_displayInfo` down in Proc-Layer, passing the settings - * from the radio buttons to select the flavour of feedback, and the text for feedback content. - * The expected behaviour is for the invoked command to send a feedback via UI-Bus towards - * the ErrorLogDisplay within the InfoboxPanel. + * This routine invokes the command `test_meta_displayInfo` and friends down in Proc-Layer, + * passing the settings from the radio buttons to select the flavour of feedback, and the text + * for feedback content. The expected behaviour is for the invoked command to send a feedback + * via UI-Bus towards the ErrorLogDisplay within the InfoboxPanel. */ struct Page1 : Page { diff --git a/src/gui/panel/panel.cpp b/src/gui/panel/panel.cpp index a663db660..1b740d2af 100644 --- a/src/gui/panel/panel.cpp +++ b/src/gui/panel/panel.cpp @@ -42,7 +42,8 @@ namespace panel{ ,Gdl::DockItem& dockItem ,const gchar* longName ,const gchar* stockID) - : panelManager_(panelManager) + : Gtk::Box{Gtk::ORIENTATION_VERTICAL} + , panelManager_(panelManager) , dockItem_(dockItem) , panelBar_(*this, stockID) { diff --git a/src/gui/panel/panel.hpp b/src/gui/panel/panel.hpp index d79c24305..8b34e9bdc 100644 --- a/src/gui/panel/panel.hpp +++ b/src/gui/panel/panel.hpp @@ -36,18 +36,18 @@ #include namespace gui { - namespace workspace { - class PanelManager; - class WorkspaceWindow; - } - namespace panel { +namespace workspace { + class PanelManager; + class WorkspaceWindow; +} +namespace panel { /** * The base class for all dockable panels. */ class Panel - : public Gtk::VBox + : public Gtk::Box { protected: diff --git a/src/gui/panel/timeline-panel.cpp b/src/gui/panel/timeline-panel.cpp index 97131c60d..38c6fe81f 100644 --- a/src/gui/panel/timeline-panel.cpp +++ b/src/gui/panel/timeline-panel.cpp @@ -33,105 +33,48 @@ #include "gui/gtk-base.hpp" #include "gui/panel/timeline-panel.hpp" +#include "gui/timeline/timeline-widget.hpp" +#include "gui/timeline/timeline-widget-empty.hpp" //#include "gui/workspace/workspace-window.hpp" -#include "gui/ui-bus.hpp" -#include "lib/format-string.hpp" -#include "lib/format-cout.hpp" +//#include "gui/ui-bus.hpp" +//#include "lib/format-string.hpp" +//#include "lib/format-cout.hpp" //#include "lib/util.hpp" -#include -#include -#include +//#include +//#include +//#include -using util::_Fmt; +//using util::_Fmt; //using std::shared_ptr; -//using std::weak_ptr; +using std::make_unique; //using util::contains; -using Gtk::Widget; -using sigc::mem_fun; -using sigc::ptr_fun; -using std::string; -using std::rand; -using std::max; +//using Gtk::Widget; +//using sigc::mem_fun; +//using sigc::ptr_fun; +//using std::string; namespace gui { namespace panel { - + + using timeline::TimelineWidget; + using timeline::TimelineWidgetEmpty; TimelinePanel::TimelinePanel (workspace::PanelManager& panelManager, Gdl::DockItem& dockItem) : Panel(panelManager, dockItem, getTitle(), getStockID()) - , twoParts_(Gtk::ORIENTATION_VERTICAL) - , buttons_() - , frame_("Gtk::Layout Experiments") - , scroller_() - , canvas_() + , tabs_{} + , pages_{} { - twoParts_.pack_start(buttons_, Gtk::PACK_SHRINK); - twoParts_.pack_start(frame_); - - buttons_.set_layout(Gtk::BUTTONBOX_START); - - // buttons to trigger experiments - button_1_.set_label("_place"); - button_1_.set_use_underline(); - button_1_.set_tooltip_markup("Experiment 1:\nplace new child widget\nat random position on the canvas"); - button_1_.signal_clicked().connect( - mem_fun(*this, &TimelinePanel::experiment_1)); - buttons_.add(button_1_); - - button_2_.set_label("_move"); - button_2_.set_use_underline(); - button_2_.set_tooltip_markup("Experiment 2:\nmove all child widgets randomly"); - button_2_.signal_clicked().connect( - mem_fun(*this, &TimelinePanel::experiment_2)); - buttons_.add(button_2_); - - button_3_.set_label("a_lign"); - button_3_.set_use_underline(); - button_3_.set_tooltip_markup("Experiment 3:\nalign all child widgets in a row\nwith silight random vertical offset"); - button_3_.signal_clicked().connect( - mem_fun(*this, &TimelinePanel::experiment_3)); - buttons_.add(button_3_); - - button_4_.set_label("_grow"); - button_4_.set_use_underline(); - button_4_.set_tooltip_markup("Experiment 4:\nextend arbitrary child widget's text"); - button_4_.signal_clicked().connect( - mem_fun(*this, &TimelinePanel::experiment_4)); - buttons_.add(button_4_); - - button_5_.set_label("_kill"); - button_5_.set_use_underline(); - button_5_.set_tooltip_markup("Experiment 5:\nkill arbitrary child widget"); - button_5_.signal_clicked().connect( - mem_fun(*this, &TimelinePanel::experiment_5)); - buttons_.add(button_5_); - - toggleDraw_.set_label("draw"); - toggleDraw_.signal_clicked().connect( - [this]() { - canvas_.enableDraw (this->toggleDraw_.get_active()); - }); - buttons_.add(toggleDraw_); - //(End)buttons... - - frame_.add(scroller_); - frame_.set_border_width(5); - - scroller_.set_shadow_type(Gtk::SHADOW_NONE); - scroller_.set_border_width(10); - scroller_.add(canvas_); - - canvas_.adjustSize(); + pages_.emplace_back (new TimelineWidgetEmpty{}); // show everything.... - this->add(twoParts_); + this->add(tabs_); this->show_all(); } @@ -150,236 +93,10 @@ namespace panel { void - TimelinePanel::addTimeline (std::unique_ptr&& widget) + TimelinePanel::addTimeline (PageHandle&& pTimelineWidget) { UNIMPLEMENTED ("take ownership of the widget and place it into a new tab"); } - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1016 : WIP kill everything below.... - void - TimelinePanel::experiment_1() - { - frame_.set_label("Experiment 1... PLACE"); - - ChildEx* chld = makeChld(); - childz_.push_back(chld); - uint x = rand() % 1000; - uint y = rand() % 500; - canvas_.put(*chld, x, y); - chld->show(); - canvas_.adjustSize(); - } - - - void - TimelinePanel::experiment_2() - { - frame_.set_label("Experiment 2... MOVE"); - for (Widget* chld : childz_) - { - uint x = canvas_.child_property_x(*chld); - uint y = canvas_.child_property_y(*chld); - int deltaX = -20 + rand() % 41; - int deltaY = -15 + rand() % 31; - x = uint(max (0, int(x) + deltaX)); - y = uint(max (0, int(y) + deltaY)); - - canvas_.move (*chld, x,y); - } - canvas_.adjustSize(); - } - - - void - TimelinePanel::experiment_3() - { - frame_.set_label("Experiment 3... ALIGN"); - uint pos=0; - for (Widget* chld : childz_) - { - uint y = rand() % 30; - canvas_.move (*chld, pos, y); - - int width = chld->get_allocated_width(); - pos += 0.6 * width; - } - canvas_.adjustSize(); - } - - - void - TimelinePanel::experiment_4() - { - frame_.set_label("Experiment 4... GROW"); - uint selector = rand() % childz_.size(); - ChildEx& toGrow = *childz_[selector]; - toGrow.set_label ("***"+toGrow.get_label()+"***"); - } - - - void - TimelinePanel::experiment_5() - { - frame_.set_label("Experiment 5... KILL"); - uint killPos = rand() % childz_.size(); - ChildV::iterator killThat(&childz_[killPos]); - ChildEx* victim = *killThat; - childz_.erase (killThat); - canvas_.remove (*victim); - delete victim; - } - - - void - Canvas::enableDraw (bool yes) - { - shallDraw_ = yes; - - // force redrawing of the visible area... - auto win = get_window(); - if (win) - { - int w = get_allocation().get_width(); - int h = get_allocation().get_height(); - Gdk::Rectangle rect{0, 0, w, h}; - win->invalidate_rect(rect, false); - } - } - - - - void - Canvas::adjustSize() - { - recalcExtension_ = true; - } - - void - Canvas::determineExtension() - { - if (not recalcExtension_) return; - - uint extH=20, extV=20; - Gtk::Container::ForeachSlot callback - = [&](Gtk::Widget& chld) - { - auto alloc = chld.get_allocation(); - uint x = alloc.get_x(); - uint y = alloc.get_y(); - x += alloc.get_width(); - y += alloc.get_height(); - extH = max (extH, x); - extV = max (extV, y); - }; - foreach(callback); - recalcExtension_ = false; - set_size (extH, extV); - } - - - bool - Canvas::on_draw(Cairo::RefPtr const& cox) - { - if (shallDraw_) - { - uint extH, extV; - determineExtension(); - get_size (extH, extV); - - auto adjH = get_hadjustment(); - auto adjV = get_vadjustment(); - double offH = adjH->get_value(); - double offV = adjV->get_value(); - - cox->save(); - cox->translate(-offH, -offV); - - // draw red diagonal line - cox->set_source_rgb(0.8, 0.0, 0.0); - cox->set_line_width (10.0); - cox->move_to(0, 0); - cox->line_to(extH, extV); - cox->stroke(); - cox->restore(); - - // cause child widgets to be redrawn - bool event_is_handled = Gtk::Layout::on_draw(cox); - - // any drawing which follows happens on top of child widgets... - cox->save(); - cox->translate(-offH, -offV); - - cox->set_source_rgb(0.2, 0.4, 0.9); - cox->set_line_width (2.0); - cox->rectangle(0,0, extH, extV); - cox->stroke(); - cox->restore(); - - return event_is_handled; - } - else - return Gtk::Layout::on_draw(cox); - } - - - /* === Support for Investigation === */ - - namespace { - _Fmt childID("Chld-%02d"); - - int instanceCnt = 0; - } - - - uint ChildEx::childNo = 0; - - - ChildEx::ChildEx() - : Gtk::Button(string (childID % childNo++)) - { - ++instanceCnt; - } - - - void - ChildEx::on_clicked() - { - cout << "|=="< 0) - cout << " ↯↯ still "< #include #include namespace gui { -namespace model{ - class Sequence; -} -namespace panel { - -//using std::shared_ptr; - - /** - * "experimental" child widget for investigation of Gtk::Layout - */ - class ChildEx - : public Gtk::Button - { - static uint childNo; - - public: - ChildEx(); - ~ChildEx(); - - private: - void on_clicked() override; - }; - - void __verifyDeadChildren(); - - - - /** - * "experimental" custom canvas, based on Gtk::Layout. - * In addition this customised widget supports direct drawing - */ - class Canvas - : public Gtk::Layout - { - bool shallDraw_; - bool recalcExtension_ = false; - - public: - void enableDraw (bool); - void adjustSize(); - - private: - virtual bool on_draw (Cairo::RefPtr const&) override; - - void determineExtension(); - }; - +namespace panel{ /** * Dockable panel to hold timeline widget(s). - * @todo build the actual implementation, after finishing the investigation - * - * ## Investigation of gtk::GtkLayout - * As of 10/2016, we start this task with an exploration of GTK behaviour - * - * \par Plan of investigation - * 1. place some simple widgets (Buttons) ✔ - * 2. learn how to draw ✔ - * 3. place a huge number of widgets, to scrutinise scrolling and performance - * 4. place widgets overlapping and irregularily, beyond the scrollable area ✔ - * 5. bind signals to those widgets, to verify event dispatching ✔ - * 6. bind some further signal(s) to the ~GtkLayout container - * 7. hide and re-show a partially and a totally overlapped widget - * 8. find a way to move a widget ✔ and delete arbitrary widgets ✔ - * 9. expand an existing widget (text change) ✔ - * 10. build a custom "clip" widget - * 11. retrofit all preceding tests to use this "clip" widget + * @todo WIP 10/2018 the actual re-implementation of Lumiera's Timeline display */ class TimelinePanel : public Panel { + using PageHandle = std::unique_ptr; + using Timelines = std::vector; + + Gtk::Notebook tabs_; + Timelines pages_; + public: /** * @param panel_manager The owner panel manager widget. * @param dock_item The GdlDockItem that will host this panel. */ - TimelinePanel(workspace::PanelManager&, Gdl::DockItem&); + TimelinePanel (workspace::PanelManager&, Gdl::DockItem&); static const char* getTitle(); static const gchar* getStockID(); /////////////////////////////////////////////////////////////TODO WIP - void addTimeline (std::unique_ptr&&); + void addTimeline (PageHandle &&); private: -/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1016 : WIP kill everything below.... - Gtk::Box twoParts_; - Gtk::ButtonBox buttons_; - Gtk::Button button_1_; - Gtk::Button button_2_; - Gtk::Button button_3_; - Gtk::Button button_4_; - Gtk::Button button_5_; - Gtk::CheckButton toggleDraw_; - Gtk::Frame frame_; - Gtk::ScrolledWindow scroller_; - Canvas canvas_; - - ChildEx* makeChld(); - - using ChildV = std::vector; - ChildV childz_; - - void experiment_1(); - void experiment_2(); - void experiment_3(); - void experiment_4(); - void experiment_5(); }; diff --git a/src/gui/timeline/timeline-gui.cpp b/src/gui/timeline/timeline-gui.cpp index b2295e862..332e4b456 100644 --- a/src/gui/timeline/timeline-gui.cpp +++ b/src/gui/timeline/timeline-gui.cpp @@ -41,7 +41,7 @@ #include using lib::diff::TreeMutator; -using std::make_unique; +using std::unique_ptr; namespace gui { @@ -77,15 +77,24 @@ namespace timeline { /** - * actually build a TimelineWidget to enact the role - * represented by this smart-handle + * actually build a TimelineWidget to enact the role represented by this smart-handle. + * @remark some implementation twist involved here, since TimelinePanel manages a collection + * of `unique_ptr`, in order to be able to hold an empty placeholder page. + * Since C++ unfortunately does not support _Covariance_ proper, we need to fabricate a + * unique_ptr right here, which can than be handed over to TimelinePanel, + * yet still we _do inherit_ from WLink, i.e. expose the subclass. + * The `unque_ptr` owns and manages the TimelineWidget, which is itself non-copyable + * and stays at a fixed location in heap memory, as is required by gui::ctrl::Nexus + * to maintain a registration of the UI-Bus connection. WLink to the contrary + * just connects to the widget, and is automatically disconnected when it dies. */ - std::unique_ptr + unique_ptr TimelineGui::buildTimelineWidget (BusTerm& nexus) { - auto widget = std::make_unique (timelineID_, rootTrackID_, nexus); + TimelineWidget* widget; + unique_ptr pageHandle {widget = new TimelineWidget{timelineID_, rootTrackID_, nexus}}; this->connect (*widget); - return widget; + return pageHandle; } diff --git a/src/gui/timeline/timeline-gui.hpp b/src/gui/timeline/timeline-gui.hpp index ad6b96a21..495645cde 100644 --- a/src/gui/timeline/timeline-gui.hpp +++ b/src/gui/timeline/timeline-gui.hpp @@ -63,6 +63,7 @@ namespace gui { namespace timeline { + class TimelinePage; class TimelineWidget; using ctrl::BusTerm; @@ -93,7 +94,7 @@ namespace timeline { /** actually build a TimelineWidget to enact the role * represented by this smart-handle */ - std::unique_ptr buildTimelineWidget (BusTerm&); + std::unique_ptr buildTimelineWidget (BusTerm&); /** @internal this method is invoked by the UI-Bus when dispatching a MutationMessage... */ void buildMutator (lib::diff::TreeMutator::Handle buffer) override; diff --git a/src/gui/timeline/timeline-widget-empty.hpp b/src/gui/timeline/timeline-widget-empty.hpp index 4bb681a19..3e9d17d6e 100644 --- a/src/gui/timeline/timeline-widget-empty.hpp +++ b/src/gui/timeline/timeline-widget-empty.hpp @@ -38,6 +38,7 @@ #include "gui/gtk-base.hpp" +#include "gui/timeline/timeline-widget.hpp" #include "lib/time/timevalue.hpp" //#include @@ -56,6 +57,7 @@ namespace timeline { * and a scrollable timeline body (right). The layout of both parts is aligned. */ class TimelineWidgetEmpty + : public TimelinePage { public: /** diff --git a/src/gui/timeline/timeline-widget.cpp b/src/gui/timeline/timeline-widget.cpp index 7fcc6db8b..9d6c7b787 100644 --- a/src/gui/timeline/timeline-widget.cpp +++ b/src/gui/timeline/timeline-widget.cpp @@ -66,7 +66,7 @@ namespace timeline { TimelineWidget::TimelineWidget (BusTerm::ID identity, BusTerm::ID trackID, BusTerm& nexus) - : Gtk::Paned{Gtk::ORIENTATION_VERTICAL} + : TimelinePage{} , control_{new TimelineController{identity, trackID, nexus}} , layout_{new LayoutManager} { diff --git a/src/gui/timeline/timeline-widget.hpp b/src/gui/timeline/timeline-widget.hpp index cac87d043..68581bc7b 100644 --- a/src/gui/timeline/timeline-widget.hpp +++ b/src/gui/timeline/timeline-widget.hpp @@ -78,6 +78,20 @@ namespace timeline { using ctrl::BusTerm; + /** + * Interface: GUI page holding a timeline display + */ + class TimelinePage + : public Gtk::Paned + { + public: + virtual ~TimelinePage() { } ///< this is an interface + + TimelinePage() + : Gtk::Paned{Gtk::ORIENTATION_VERTICAL} + { } + }; + /** * Core timeline display (custom widget). * Top level entry point to the timeline display component. @@ -86,7 +100,7 @@ namespace timeline { * and a scrollable timeline body (right). The layout of both parts is aligned. */ class TimelineWidget - : public Gtk::Paned + : public TimelinePage { std::unique_ptr control_; std::unique_ptr layout_; diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 5eea72275..1a2cc5268 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -19053,11 +19053,17 @@ - - + + + + + + + + @@ -35312,6 +35318,46 @@ + + + + + + + + + + +

+ GUI und Session schicken Nachrichten. +

+

+ Während der Builder läuft, kann das GUI schon weitere Nachrichten geschickt haben, +

+

+ die dann noch in der ProcDispatcher-Queue hängen. Daher kann sich die Antwort +

+

+ als Resultat auf einen Builder-Lauf noch auf einen vorherigen Zustand beziehen. +

+

+ Es kann aber auch ein Builder-Lauf die kummulierten Ergebnisse von mehreren Commands behandeln. +

+

+ In jedem Fall muß der DiffConstituent genau wissen, was der zuletzt geschickte Stand war, +

+

+ damit er einen Diff erzeugt, der garantiert auf der anderen Seite anwendbar ist. +

+

+ Denn letzteres ist bei uns eine Grundannahme. Es gibt keine ungefähren Diffs! +

+ + +
+
+
+