TestControl: concept draft how to simplify building notebook widgets
Gtk::Notebook is a quite powerful container foundation to build complex dialog widgets with multible pages on tabs. Hower, the construction, wiring an 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 obscuring the structure. The basic idea is to package each page into a locally defined child struct, which is actually heap allocated and managed automatically. This way, each child page gets its own namespace, and wiring to other components is made explicit by passing named ctor arguments -- while the overall structure of building and wiring of widgets stays close to the habits of Gtkmm programming.
This commit is contained in:
parent
0c082361f3
commit
74f3ab3932
3 changed files with 165 additions and 35 deletions
|
|
@ -40,61 +40,123 @@
|
|||
#include "gui/gtk-base.hpp"
|
||||
#include "gui/dialog/dialog.hpp"
|
||||
#include "gui/ctrl/bus-term.hpp"
|
||||
#include "lib/scoped-ptrvect.hpp"
|
||||
//#include "lib/meta/function.hpp"
|
||||
#include "lib/nocopy.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace gui {
|
||||
namespace dialog {
|
||||
|
||||
using std::forward;
|
||||
|
||||
struct FrameVBox
|
||||
{
|
||||
Gtk::Frame frame;
|
||||
Gtk::Box box;
|
||||
|
||||
FrameVBox (cuString label)
|
||||
: frame{label}
|
||||
, box{Gtk::ORIENTATION_VERTICAL}
|
||||
{
|
||||
frame.add (box);
|
||||
}
|
||||
|
||||
operator Gtk::Widget&() { return frame; }
|
||||
|
||||
void
|
||||
pack_start(Gtk::Widget& child, Gtk::PackOptions options = Gtk::PACK_EXPAND_WIDGET, guint padding = 0)
|
||||
{
|
||||
box.pack_start (child, options, padding);
|
||||
}
|
||||
};
|
||||
|
||||
class Page
|
||||
: public Gtk::Box
|
||||
, util::NonCopyable
|
||||
{
|
||||
public:
|
||||
Page()
|
||||
: Gtk::Box{Gtk::ORIENTATION_VERTICAL}
|
||||
{ }
|
||||
|
||||
virtual ~Page() { }
|
||||
};
|
||||
|
||||
class Notebook
|
||||
: public Gtk::Notebook
|
||||
, lib::ScopedPtrVect<Gtk::Widget>
|
||||
{
|
||||
public:
|
||||
template<class PAG, typename...ARGS>
|
||||
Notebook&
|
||||
buildPage (cuString pageLabel, ARGS&& ...ctorArgs)
|
||||
{
|
||||
Gtk::Notebook::append_page (this->manage (new PAG(forward<ARGS> (ctorArgs)...))
|
||||
,pageLabel);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
class TestControl
|
||||
: public Gtk::Dialog
|
||||
, ctrl::BusTerm
|
||||
{
|
||||
Gtk::Notebook notebook_;
|
||||
using Bus = ctrl::BusTerm&;
|
||||
Bus busTerm() { return *this; }
|
||||
|
||||
Gtk::Box page_1_;
|
||||
Gtk::Button trigger_1_;
|
||||
|
||||
struct Page1 : Page
|
||||
{
|
||||
FrameVBox seg_1_{_("log notification")},
|
||||
seg_2_{_("mark via UI-Bus")};
|
||||
Gtk::Button trigger_1_;
|
||||
|
||||
Page1(Bus bus)
|
||||
{
|
||||
trigger_1_.set_label ("_doIt");
|
||||
trigger_1_.set_use_underline();
|
||||
trigger_1_.set_tooltip_markup (_("<b>Ticket #1099</b>:\ntrigger Proc-GUI roundtrip"));
|
||||
trigger_1_.signal_clicked().connect(
|
||||
mem_fun(*this, &Page1::demoGuiRoundtrip));
|
||||
|
||||
seg_1_.pack_start (trigger_1_, Gtk::PACK_SHRINK);
|
||||
pack_start (seg_1_);
|
||||
pack_start (seg_2_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ticket #1099 : perform a dummy round-trip to verify Proc-GUI integration.
|
||||
* This routine invokes the command 'xxx' 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.
|
||||
*/
|
||||
void
|
||||
demoGuiRoundtrip()
|
||||
{
|
||||
UNIMPLEMENTED ("collect command arguments and then send the command message for #1099");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Notebook notebook_;
|
||||
|
||||
public:
|
||||
TestControl (ctrl::BusTerm& upLink, Gtk::Window& parent)
|
||||
: Dialog(_("Test and Diagnostics"), parent, Gtk::DIALOG_DESTROY_WITH_PARENT)
|
||||
, ctrl::BusTerm{lib::idi::EntryID<TestControl>{}, upLink}
|
||||
, page_1_{Gtk::ORIENTATION_VERTICAL}
|
||||
{
|
||||
using namespace Gtk;
|
||||
|
||||
// Setup the overall dialog layout
|
||||
set_border_width (BorderPadding);
|
||||
get_content_area()->pack_start (notebook_);
|
||||
|
||||
//-----Page-1------------------------------
|
||||
trigger_1_.set_label ("_doIt");
|
||||
trigger_1_.set_use_underline();
|
||||
trigger_1_.set_tooltip_markup (_("<b>Ticket #1099</b>:\ntrigger Proc-GUI roundtrip"));
|
||||
trigger_1_.signal_clicked().connect(
|
||||
mem_fun(*this, &TestControl::demoGuiRoundtrip));
|
||||
|
||||
page_1_.pack_start (trigger_1_, PACK_SHRINK);
|
||||
notebook_.append_page (page_1_, _("#1099"));
|
||||
|
||||
// construct and wire the pages...
|
||||
notebook_.buildPage<Page1> (_("#1099"), busTerm());
|
||||
|
||||
show_all();
|
||||
}
|
||||
|
||||
|
||||
private: /* ==== individual Test/Diagnostics routines ==== */
|
||||
|
||||
/**
|
||||
* Ticket #1099 : perform a dummy round-trip to verify Proc-GUI integration.
|
||||
* This routine invokes the command 'xxx' 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.
|
||||
*/
|
||||
void
|
||||
demoGuiRoundtrip()
|
||||
{
|
||||
UNIMPLEMENTED ("collect command arguments and then send the command message for #1099");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -118,8 +118,8 @@ namespace interact {
|
|||
|
||||
/**
|
||||
* Launch a non modal child window to trigger self-test actions.
|
||||
* This is a tool for developers and diagnostics. The operations exposed here
|
||||
* allow to trigger some hard wired actions and test routines, performing within
|
||||
* This is a tool for diagnostics and development. The operations exposed here
|
||||
* allow to launch some hard wired actions and test routines, performing within
|
||||
* the regular UI environment and on equal footing with user operated controls.
|
||||
*/
|
||||
void
|
||||
|
|
|
|||
|
|
@ -2771,6 +2771,13 @@
|
|||
<icon BUILTIN="info"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1537961550200" ID="ID_226231657" MODIFIED="1537962140152" TEXT="setup für Notebook-Widget">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#435e98" CREATED="1537961568746" ID="ID_1553519505" MODIFIED="1537962304729" TEXT="Prototyp für generischen Helper">
|
||||
<arrowlink COLOR="#6ea8be" DESTINATION="ID_591860371" ENDARROW="Default" ENDINCLINATION="1162;51;" ID="Arrow_ID_1534615646" STARTARROW="None" STARTINCLINATION="-185;836;"/>
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1537836522950" ID="ID_87203159" MODIFIED="1537836526719" TEXT="Radiobuttons">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
|
|
@ -2824,7 +2831,9 @@
|
|||
</node>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1534721737507" ID="ID_1467431829" MODIFIED="1534721762112" TEXT="verifizieren">
|
||||
<icon BUILTIN="full-6"/>
|
||||
<node CREATED="1534721764680" ID="ID_237796687" MODIFIED="1534721771410" TEXT="Belegen der View"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1534721764680" ID="ID_237796687" MODIFIED="1537961523677" TEXT="Belegen der View">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1534721772238" ID="ID_130695962" MODIFIED="1534721838886" TEXT="Verbinden mit bestehendem InfoboxPanel">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
|
|
@ -4219,6 +4228,65 @@
|
|||
<node CREATED="1537659880597" ID="ID_1214109906" MODIFIED="1537659889631" TEXT="Timecode"/>
|
||||
<node CREATED="1537659890292" ID="ID_1230379898" MODIFIED="1537659892520" TEXT="Placement"/>
|
||||
</node>
|
||||
<node CREATED="1537961656982" ID="ID_1251358269" MODIFIED="1537961731447" TEXT="frameworks">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
vorbereitete Grundstrukturen für immer wiederkehrende Setups
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<node CREATED="1537961734956" ID="ID_345535043" MODIFIED="1537961770028" TEXT="Notebook-Widget">
|
||||
<node CREATED="1537961776184" ID="ID_167848646" MODIFIED="1537961791126" TEXT="Problematik">
|
||||
<icon BUILTIN="forward"/>
|
||||
<node CREATED="1537961797061" ID="ID_104206298" MODIFIED="1537961806159" TEXT="extrem viele Komponenten-Widgets"/>
|
||||
<node CREATED="1537961807436" ID="ID_1420879044" MODIFIED="1537961819742" TEXT="Namenskollisionen zwischen Pages"/>
|
||||
<node CREATED="1537961832009" ID="ID_380956030" MODIFIED="1537961842907" TEXT="Boilerplate-Code goes Spaghetti"/>
|
||||
</node>
|
||||
<node CREATED="1537961848735" ID="ID_1187685583" MODIFIED="1537961889952" TEXT="Lösungs-Ideen">
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1537961860374" ID="ID_933681325" MODIFIED="1537961871080" TEXT="managing container"/>
|
||||
<node CREATED="1537961872836" ID="ID_1674501396" MODIFIED="1537961884942" TEXT="builder lambda"/>
|
||||
</node>
|
||||
<node CREATED="1537961894394" ID="ID_1253130867" MODIFIED="1537961909817" TEXT="Prototyp">
|
||||
<node CREATED="1537961917592" ID="ID_591860371" MODIFIED="1537962293792" TEXT="im TestControl">
|
||||
<linktarget COLOR="#6ea8be" DESTINATION="ID_591860371" ENDARROW="Default" ENDINCLINATION="1162;51;" ID="Arrow_ID_1534615646" SOURCE="ID_1553519505" STARTARROW="None" STARTINCLINATION="-185;836;"/>
|
||||
</node>
|
||||
<node CREATED="1537961950003" ID="ID_1083792924" MODIFIED="1537962085365" TEXT="Schema "managing container"">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...denn das erscheint mir bodenständiger.
|
||||
</p>
|
||||
<p>
|
||||
GUI-Programmierung muß bodenstäding bleiben,
|
||||
</p>
|
||||
<p>
|
||||
man gewinnt hier nichts durch blendende Abstraktionen.
|
||||
</p>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
Ich hoffe, daß der Hilfscontainer <i>nahezu transparent </i>gemacht werden kann.
|
||||
</p>
|
||||
<p>
|
||||
Und der Rest sollte so <i>vertraut</i> aussehen, daß es selbsterklärend wird.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1534336325916" ID="ID_762624766" MODIFIED="1534336335351" TEXT="Bindeglieder"/>
|
||||
<node CREATED="1534336335963" ID="ID_1176525116" MODIFIED="1534336338575" TEXT="Werkzeug">
|
||||
|
|
|
|||
Loading…
Reference in a new issue