Lumiera  0.pre.03
»edit your freedom«
test-control.hpp
Go to the documentation of this file.
1 /*
2  TEST-CONTROL.hpp - child window to trigger self tests and diagnostics
3 
4  Copyright (C) Lumiera.org
5  2018, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 
23 
38 #ifndef STAGE_DIALOG_TEST_CONTROL_H
39 #define STAGE_DIALOG_TEST_CONTROL_H
40 
41 
42 #include "stage/gtk-base.hpp"
43 #include "stage/dialog/dialog.hpp"
44 #include "stage/ctrl/bus-term.hpp"
45 #include "stage/model/tangible.hpp"
46 #include "include/ui-protocol.hpp"
47 
48 #include "steam/cmd.hpp"
51 
52 #include "lib/test/test-helper.hpp"
53 #include "lib/diff/gen-node.hpp"
54 #include "lib/scoped-ptrvect.hpp"
55 #include "lib/format-string.hpp"
56 #include "lib/format-cout.hpp"
57 #include "lib/nocopy.hpp"
58 #include "lib/util.hpp"
59 
60 #include <utility>
61 #include <string>
62 
63 namespace stage {
64 namespace dialog {
65 
66  using std::string;
67  using std::forward;
68  using lib::diff::GenNode;
69  using util::sanitise;
70  using util::_Fmt;
71 
72 
81  struct FrameBox
82  {
83  Gtk::Frame frame;
84  Gtk::Box box;
85 
86  FrameBox (cuString label,
87  Gtk::Orientation orientation =Gtk::ORIENTATION_VERTICAL)
88  : frame{label}
89  , box{orientation}
90  {
91  frame.add (box);
92  }
93 
94  operator Gtk::Widget&() { return frame; }
95 
96  void
97  pack_start(Gtk::Widget& child, Gtk::PackOptions options =Gtk::PACK_EXPAND_WIDGET, guint padding =0)
98  {
99  box.pack_start (child, options, padding);
100  }
101  };
102 
104  class Page
105  : public Gtk::Box
107  {
108  public:
109  Page()
110  : Gtk::Box{Gtk::ORIENTATION_VERTICAL}
111  { }
112  };
113 
135  class Notebook
136  : public Gtk::Notebook
137  , lib::ScopedPtrVect<Gtk::Widget>
138  {
139  public:
140  template<class PAG, typename...ARGS>
141  Notebook&
142  buildPage (cuString pageLabel, ARGS&& ...ctorArgs)
143  {
144  Gtk::Notebook::append_page (this->manage (new PAG(forward<ARGS> (ctorArgs)...))
145  ,pageLabel);
146  return *this;
147  }
148  };
149 
150 
159  : public Gtk::Dialog
160  {
161  using Bus = ctrl::BusTerm&;
162 
163  Bus uiBus_;
164  Notebook notebook_;
165 
166 
174  struct Page1 : Page
175  {
176  Gtk::Entry content_;
177  FrameBox seg_1_{_("log notification"), Gtk::ORIENTATION_HORIZONTAL},
178  seg_2_{_("mark via UI-Bus")};
179  Gtk::Button trig_1_, trig_2_, trig_3_, trig_4_;
180  Gtk::RadioButton level_info_{"Info"},
181  level_warn_{"Warn"},
182  level_erro_{"Error"};
183  Gtk::Box markParam_;
184  Gtk::ComboBoxText actionID_{true}; // has free-text entry field
185 
186  int
187  getLogLevel()
188  {
189  return level_info_.get_active()? NOTE_INFO :
190  level_warn_.get_active()? NOTE_WARN : NOTE_ERROR;
191  }
192 
193  string
194  getContent()
195  {
196  return string{content_.get_text()};
197  }
198 
199  string
200  getActionID()
201  {
202  return string{actionID_.get_entry_text()};
203  }
204 
205 
206  Page1 (Bus bus)
207  {
208  content_.set_tooltip_markup (_("<b>Ticket #1099</b>:\n"
209  "text message content\n"
210  "<i>when invoking a suitable action,\n"
211  "it will be passed down and sent back</i>"));
212  trig_1_.set_use_underline();
213  trig_1_.set_label ("_display text");
214  trig_1_.property_xalign() = 0;
215  trig_1_.set_tooltip_markup (_("Trigger Steam-Stage <b>roundtrip</b>\n"
216  "Steam invokes GuiNotification::displayInfo"));
217 
218  level_warn_.join_group(level_info_);
219  level_erro_.join_group(level_info_);
220  level_warn_.set_active();
221 
222  trig_2_.set_use_underline();
223  trig_2_.property_xalign() = 0;
224  trig_2_.set_label ("mark _error");
225  trig_2_.set_tooltip_markup (_("trigger Steam-command, which in turn\n"
226  "sends an error state mark via UI-Bus"));
227 
228  trig_3_.set_use_underline();
229  trig_3_.property_xalign() = 0;
230  trig_3_.set_label ("mark _info");
231  trig_3_.set_tooltip_markup (_("trigger Steam-command, which in turn\n"
232  "sends an info state mark via UI-Bus"));
233 
234  trig_4_.set_use_underline();
235  trig_4_.set_label ("_mark");
236  trig_4_.property_xalign() = 0;
237  trig_4_.set_tooltip_markup (_("trigger Steam-command, which in turn\n"
238  "sends an <b>state mark</b> message, using\n"
239  "the message action-ID from the combobox"));
240  actionID_.append (cuString{MARK_Flash});
241  actionID_.append (cuString{MARK_reveal});
242  actionID_.append (cuString{MARK_clearErr});
243  actionID_.append (cuString{MARK_clearMsg});
244  actionID_.append (cuString{MARK_expand});
245  actionID_.append (cuString{MARK_reset});
246  actionID_.set_active(1);
247  actionID_.set_tooltip_markup("select the specific action-ID\n"
248  "when sending a <b>mark</b> message.\n"
249  "<u>note</u>: can enter arbitrary ID");
250 
251  markParam_.pack_start(trig_4_);
252  markParam_.pack_start(actionID_, Gtk::PACK_SHRINK);
253 
254  seg_1_.pack_start (trig_1_, Gtk::PACK_EXPAND_WIDGET);
255  seg_1_.pack_start (level_info_, Gtk::PACK_SHRINK);
256  seg_1_.pack_start (level_warn_, Gtk::PACK_SHRINK);
257  seg_1_.pack_start (level_erro_, Gtk::PACK_SHRINK);
258 
259  seg_2_.pack_start (trig_2_);
260  seg_2_.pack_start (trig_3_);
261  seg_2_.pack_start (markParam_);
262 
263  pack_start (content_, Gtk::PACK_SHRINK);
264  pack_start (seg_1_, Gtk::PACK_SHRINK);
265  pack_start (seg_2_, Gtk::PACK_SHRINK);
266 
267  // define the action triggers...
268  trig_1_.signal_clicked().connect(
269  [&]{ bus.act (model::commandMessage (steam::cmd::test_meta_displayInfo, getLogLevel(), getContent())); });
270  trig_2_.signal_clicked().connect(
271  [&]{ bus.act (model::commandMessage (steam::cmd::test_meta_markError, getContent())); });
272  trig_3_.signal_clicked().connect(
273  [&]{ bus.act (model::commandMessage (steam::cmd::test_meta_markNote, getContent())); });
274  trig_4_.signal_clicked().connect(
275  [&]{ bus.act (model::commandMessage (steam::cmd::test_meta_markAction, getActionID(), getContent())); });
276  }
277  };
278 
279 
284  struct Page2 : Page
285  {
286  Gtk::Entry dummy_;
287  FrameBox part_1_{_("populate"), Gtk::ORIENTATION_HORIZONTAL}
288  , part_2_{_("modify content")}
289  ;
290  Gtk::Button seq_1_, seq_2_;
291  Gtk::Button mut_1_;
292 
293  string
294  pickDummyID()
295  {
296  string dummyID = sanitise (dummy_.get_text());
297  dummy_.set_text (string{_Fmt{"d%s%02d"} % lib::test::randStr(2) % (1 + rand() % 99)});
298  return dummyID;
299  }
300 
301 
302  Page2 (Bus bus)
303  {
304  seq_1_.set_label ("Sequence 1");
305  seq_1_.set_tooltip_markup (_("Push <b>population diff</b> up into the UI\n"
306  "provides the typical simple default timeline structure"));
307 
308  seq_2_.set_label ("Sequence 2");
309  seq_2_.set_tooltip_markup (_("Push <b>population diff</b> up into the UI\n"
310  "provides a complex nested timeline structure"));
311 
312  dummy_.set_tooltip_markup (_("<i>dummy ID value</i>\n"
313  "used to build names in the generated content"));
314  dummy_.set_max_width_chars(12);
315  pickDummyID();
316 
317  part_1_.pack_start (seq_1_, Gtk::PACK_SHRINK);
318  part_1_.pack_start (seq_2_, Gtk::PACK_SHRINK);
319  part_1_.pack_start (dummy_, Gtk::PACK_EXPAND_WIDGET);
320 
321 
322  mut_1_.set_label ("move elements");
323  mut_1_.set_tooltip_markup (_("randomly manipulate temporal position of dummy elements"));
324 
325  part_2_.pack_start (mut_1_);
326 
327  pack_start (part_1_, Gtk::PACK_SHRINK);
328  pack_start (part_2_, Gtk::PACK_SHRINK);
329 
330  // define the action triggers...
331  seq_1_.signal_clicked().connect(
332  [&]{ bus.act (model::commandMessage (steam::cmd::test_fake_injectSequence_1, pickDummyID())); });
333  seq_2_.signal_clicked().connect(
334  [&]{ bus.act (model::commandMessage (steam::cmd::test_fake_injectSequence_2, pickDummyID())); });
335 
336  mut_1_.signal_clicked().connect(
337  [&]{ cerr << "gelldaschaugst..." <<endl; });
338  }
339  };
340 
341 
342 
343  public:
344  TestControl (ctrl::BusTerm& upLink, Gtk::Window& parent)
345  : Dialog(_("Test and Diagnostics"), parent, Gtk::DIALOG_DESTROY_WITH_PARENT)
346  , uiBus_{upLink}
347  {
348  // Setup the overall dialog layout
349  set_border_width (BorderPadding);
350  get_content_area()->pack_start (notebook_);
351 
352  // construct and wire the pages...
353  notebook_.buildPage<Page1> (_("#1099"), uiBus_);
354  notebook_.buildPage<Page2> (_("Populate"), uiBus_);
355 
356  show_all();
357  notebook_.set_current_page(-1);
358  }
359  };
360 
361 
362 }} // namespace stage::dialog
363 #endif /*STAGE_DIALOG_TEST_CONTROL_H*/
Automatically use custom string conversion in C++ stream output.
Abstraction: a tangible element of the User Interface.
Hard wired key constants and basic definitions for communication with the GUI.
Major public Interface of the Lumiera GUI.
connection point at the UI-Bus.
Definition: bus-term.hpp:105
Ticket #1014 : populate the Timeline in the GUI.
explicitly named shortcut for the typical dialog page content holder
Any copy and copy construction prohibited.
Definition: nocopy.hpp:46
static const int BorderPadding
The space in pixels to pad the border of Lumiera dialog boxes.
Definition: dialog.hpp:38
Front-end for printf-style string template interpolation.
std::string sanitise(std::string const &)
produce an identifier based on the given string.
Definition: util.cpp:65
Dummy and scaffolding to help development of the UI - Session connection.
Common ID definitions for Steam-Layer commands.
something to be aware of, to be indicated unobtrusively
A front-end for using printf-style formatting.
Managing lifecycle for a collection of objects.
Simple vector based collection of pointers, managing lifecycle of the pointed-to objects.
Attachment point to the UI-Bus.
Mix-Ins to allow or prohibit various degrees of copying and cloning.
Lumiera GTK UI implementation root.
Definition: guifacade.cpp:46
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
A complex, tabbed-notebook-style non-modal dialog window, dedicated to development, diagnostics and experimentation.
Generic building block for tree shaped (meta)data structures.
A collection of frequently used helper functions to support unit testing.
lib::diff::GenNode commandMessage(Symbol cmdID, ARGS &&... args)
convenience shortcut to build a message suitable for command invocation
Definition: tangible.hpp:251
severe condition to be indicated prominently
Global constants and definitions for dialogs.
Building block for a segment within a dialog page.
possibly interesting info that can be safely ignored
A set of basic GTK includes for the UI.
virtual void act(GenNode const &command)
prepare or trigger invocation of a command.
Definition: ui-bus.cpp:139
generic data element node within a tree
Definition: gen-node.hpp:231
Helper widget to simplify construction and wiring of a [Notebook] widget.
Ticket #1099 : perform a dummy round-trip to verify Steam-Stage integration.