27 #define YUILogComponent "ui-dialog-spy"
30 #include <YDialogSpy.h>
31 #include <YWidgetFactory.h>
32 #include <YWidgetID.h>
37 #include <YTreeItem.h>
38 #include <YLayoutBox.h>
39 #include <YAlignment.h>
40 #include <YButtonBox.h>
41 #include <YPushButton.h>
42 #include <YMenuButton.h>
43 #include <YComboBox.h>
44 #include <YInputField.h>
45 #include <YCheckBox.h>
46 #include <YRadioButton.h>
47 #include <YProgressBar.h>
48 #include <YRichText.h>
49 #include <YBusyIndicator.h>
50 #include <YSelectionBox.h>
51 #include <YMultiSelectionBox.h>
52 #include <YMultiLineEdit.h>
55 #include <YIntField.h>
60 #include <YPackageSelector.h>
61 #include <YReplacePoint.h>
62 #include <YPropertyEditor.h>
63 #include <YPopupInternal.h>
64 #include <YAlignment.h>
65 #include <YCheckBoxFrame.h>
66 #include <YRadioButtonGroup.h>
69 #define TREE_VWEIGHT 40
70 #define PROP_VWEIGHT 60
74 #define TREE_HEIGHT 10
77 #define PROP_HEIGHT 12
109 YWidget * widget()
const {
return _widget; }
114 void setWidgetLabel()
116 std::ostringstream str;
128 YWidgetListConstIterator begin,
129 YWidgetListConstIterator end,
139 : targetDialog(
nullptr )
140 , spyDialog(
nullptr )
141 , widgetTree(
nullptr )
142 , propButton(
nullptr )
143 , propReplacePoint(
nullptr )
144 , propTable(
nullptr )
171 void moveSelectedUp() { moveSelected(MOVE_UP); }
172 void moveSelectedDown() { moveSelected(MOVE_DOWN); }
182 void moveSelected( Direction direction );
183 void showProperties();
184 void hideProperties();
185 bool propertiesShown()
const;
186 void targetDialogUpdated();
187 void refreshButtonStates();
188 void editWidget(
YWidget *widget,
const string & property=
"Label" );
209 YUI_CHECK_NEW( rootItem );
211 widgetTree->
addItem( rootItem );
222 if ( ! targetDialog )
225 priv->targetDialog = targetDialog;
228 priv->spyDialog = fac->createPopupDialog();
229 YAlignment * diaMin = fac->createMinHeight( priv->spyDialog, DIA_HEIGHT );
230 YLayoutBox * vbox = fac->createVBox( diaMin );
232 auto alignment = fac->createLeft( vbox );
233 auto fileMenu = fac->createMenuButton( alignment,
"&File" );
236 priv->exportMenu =
new YMenuItem(
"Export (TODO)" );
237 items.push_back( priv->exportMenu );
238 fileMenu->addItems( items );
240 auto minSize = fac->createMinSize( vbox, TREE_WIDTH, TREE_HEIGHT );
241 minSize->
setWeight( YD_VERT, TREE_VWEIGHT );
242 priv->widgetTree = fac->createTree( minSize,
"Widget &Tree",
false );
245 fillWidgetTree(priv->targetDialog, priv->widgetTree);
247 auto hbox = fac->createHBox( vbox );
248 priv->propButton = fac->createPushButton( hbox,
"&Properties >>>" );
250 priv->addButton = fac->createMenuButton( hbox,
"&Add" );
259 add_items.push_back( menu_info );
260 add_items.push_back( menu_buttons );
261 add_items.push_back( menu_input );
262 add_items.push_back( menu_align );
263 add_items.push_back( menu_size );
264 add_items.push_back( menu_containers );
265 add_items.push_back( menu_special );
270 new YMenuItem( menu_info,
"ProgressBar" );
271 new YMenuItem( menu_info,
"BusyIndicator" );
274 new YMenuItem( menu_buttons,
"PushButton" );
275 new YMenuItem( menu_buttons,
"CheckBox" );
276 new YMenuItem( menu_buttons,
"ComboBox" );
277 new YMenuItem( menu_buttons,
"MenuButton" );
278 new YMenuItem( menu_buttons,
"RadioButton" );
280 new YMenuItem( menu_input,
"InputField" );
282 new YMenuItem( menu_input,
"MultiLineEdit" );
283 new YMenuItem( menu_input,
"MultiSelectionBox" );
285 new YMenuItem( menu_input,
"SelectionBox" );
304 new YMenuItem( menu_containers,
"MarginBox" );
305 new YMenuItem( menu_containers,
"ButtonBox" );
306 new YMenuItem( menu_containers,
"CheckBoxFrame" );
307 new YMenuItem( menu_containers,
"Frame" );
308 new YMenuItem( menu_containers,
"HBox" );
309 new YMenuItem( menu_containers,
"HSpacing" );
310 new YMenuItem( menu_containers,
"ReplacePoint" );
311 new YMenuItem( menu_containers,
"VBox" );
312 new YMenuItem( menu_containers,
"VSpacing" );
315 new YMenuItem( menu_special,
"BarGraph" );
316 new YMenuItem( menu_special,
"DateField" );
317 new YMenuItem( menu_special,
"DumbTab" );
320 new YMenuItem( menu_input,
"TimeField" );
321 new YMenuItem( menu_special,
"TimezoneSelector" );
323 priv->addButton->
addItems( add_items );
325 priv->deleteButton = fac->createPushButton( hbox,
"&Delete" );
326 priv->upButton = fac->createPushButton( hbox,
"⬆ Up" );
327 priv->downButton = fac->createPushButton( hbox,
"⬇ Down" );
329 priv->propReplacePoint = fac->createReplacePoint( vbox );
330 fac->createEmpty( priv->propReplacePoint );
340 if ( priv->spyDialog )
347 bool YDialogSpyPrivate::propertiesShown()
const
349 return propTable !=
nullptr;
363 void YDialogSpyPrivate::showProperties()
365 if ( propertiesShown() )
return;
368 propReplacePoint->
setWeight( YD_VERT, PROP_VWEIGHT );
371 auto minSize = fac->createMinSize( propReplacePoint,
372 PROP_WIDTH, PROP_HEIGHT );
374 YUI_CHECK_NEW( header );
375 header->addColumn(
"Property" );
376 header->addColumn(
"Value" );
377 header->addColumn(
"Type" );
379 propTable = fac->createTable( minSize, header );
382 propButton->
setLabel(
"<<< &Properties" );
390 void YDialogSpyPrivate::hideProperties()
392 if ( !propertiesShown() )
return;
395 propReplacePoint->
setWeight( YD_VERT, 0 );
399 propButton->
setLabel(
"&Properties >>>" );
410 bool ret = !propertiesShown();
440 auto propSet = widget->propertySet();
441 items.reserve( propSet.size() );
443 for ( YPropertySet::const_iterator it = propSet.propertiesBegin();
444 it != propSet.propertiesEnd();
451 switch ( prop.
type() )
453 case YStringProperty:
458 propValStr = propVal.boolVal() ?
"true" :
"false";
461 case YIntegerProperty:
462 propValStr = std::to_string(propVal.integerVal());
471 YUI_CHECK_NEW( item );
472 items.push_back( item );
487 YWidgetListConstIterator begin,
488 YWidgetListConstIterator end,
491 for ( YWidgetListConstIterator it = begin; it != end; ++it )
506 YUI_CHECK_PTR( priv->spyDialog );
511 yuiMilestone() <<
"event: " << event;
512 if (!event)
continue;
515 if ( event->eventType() == YEvent::CancelEvent )
break;
516 else if ( event->eventType() == YEvent::MenuEvent)
521 if (menu_item == priv->exportMenu)
continue;
527 auto menu_label = menu_item->
label();
528 yuiMilestone() <<
"Activated menu item: " << menu_label << endl;
536 if (!event->widget())
continue;
538 if ( event->widget() == priv->upButton ) priv->moveSelectedUp();
539 else if ( event->widget() == priv->downButton) priv->moveSelectedDown();
541 else if ( event->widget() == priv->deleteButton) priv->
deleteWidget();
542 else if ( event->widget() == priv->propTable ) priv->
editProperty();
561 YUI_CAUGHT( exception );
574 return item ? item->widget() :
nullptr;
584 refreshButtonStates();
593 if (!selected_item)
return;
595 auto cell = selected_item->
cell(0);
596 yuiMilestone() <<
"editing property: " << cell->label();
611 auto parent = w->
parent();
614 yuiMilestone() <<
"removing widget: " << w << endl;
615 parent->removeChild(w);
630 targetDialogUpdated();
638 bool isBox(
const YWidget *widget)
640 return dynamic_cast<const YLayoutBox *
>(widget);
648 bool isVBox(
const YWidget *widget)
650 auto box =
dynamic_cast<const YLayoutBox *
>(widget);
651 return box && box->
primary() == YD_VERT;
660 void YDialogSpyPrivate::moveSelected(Direction direction)
663 if (!target_widget)
return;
665 auto parent = target_widget->
parent();
666 if (!parent || !isBox(parent))
return;
668 if (direction == MOVE_UP)
671 if (target_widget == parent->firstChild())
return;
679 std::swap(*other, *i);
686 if (target_widget == parent->lastChild())
return;
694 std::swap(*other, *i);
698 targetDialogUpdated();
714 if (type ==
"Bottom")
715 editWidget(f->createBottom(widget));
716 else if (type ==
"BusyIndicator")
717 editWidget(f->createBusyIndicator(widget,
"Busy Indicator", 10000));
718 else if (type ==
"ButtonBox")
719 editWidget(f->createButtonBox(widget));
720 else if (type ==
"ComboBox")
722 auto cb = f->createComboBox(widget,
"Combo Box");
729 for(
auto&& str: items) add_items.push_back(
new YMenuItem( str ) );
730 cb->addItems( add_items );
732 else if (type ==
"Empty")
733 editWidget(f->createEmpty(widget));
734 else if (type ==
"Frame")
735 editWidget(f->createFrame(widget,
"Frame"));
736 else if (type ==
"HBox")
737 editWidget(f->createHBox(widget));
738 else if (type ==
"Heading")
739 editWidget(f->createHeading(widget,
"Heading"));
740 else if (type ==
"HSpacing")
741 editWidget(f->createHSpacing(widget));
742 else if (type ==
"HStretch")
743 editWidget(f->createHStretch(widget));
744 else if (type ==
"CheckBox")
745 editWidget(f->createCheckBox(widget,
"Check Box"));
746 else if (type ==
"CheckBoxFrame")
748 editWidget(f->createCheckBoxFrame(widget,
"Check Box Frame",
true));
749 else if (type ==
"Image")
750 editWidget(f->createImage(widget,
""));
751 else if (type ==
"InputField")
752 editWidget(f->createInputField(widget,
"Input"));
753 else if (type ==
"IntField")
754 editWidget(f->createIntField(widget,
"Integer Field", 0, 100, 50));
755 else if (type ==
"Label")
756 editWidget(f->createLabel(widget,
"Label"));
757 else if (type ==
"Left")
758 editWidget(f->createLeft(widget));
759 else if (type ==
"LogView")
760 editWidget(f->createLogView(widget,
"Log View", 12));
761 else if (type ==
"MenuButton")
763 auto menu = f->createMenuButton( widget,
"Menu" );
770 for(
auto&& str: items) add_items.push_back(
new YMenuItem( str ) );
771 menu->addItems( add_items );
773 else if (type ==
"MinHeight")
774 editWidget(f->createMinHeight(widget, 10));
775 else if (type ==
"MinWidth")
776 editWidget(f->createMinWidth(widget, 10));
777 else if (type ==
"MinSize")
778 editWidget(f->createMinSize(widget, 10, 10));
779 else if (type ==
"MultiLineEdit")
780 editWidget(f->createMultiLineEdit(widget,
"MultiLineEdit"));
781 else if (type ==
"MultiSelectionBox")
783 auto msb = f->createMultiSelectionBox(widget,
"MultiSelection Box");
789 for(
auto&& str: items) msb->addItem(str);
791 else if (type ==
"OutputField")
792 editWidget(f->createOutputField(widget,
"Output Field"));
793 else if (type ==
"Password")
794 editWidget(f->createPasswordField(widget,
"Password"));
795 else if (type ==
"ProgressBar")
796 editWidget(f->createProgressBar(widget,
"Progress"));
797 else if (type ==
"PushButton")
798 editWidget(f->createPushButton(widget,
"Button"));
799 else if (type ==
"RadioButton")
800 editWidget(f->createRadioButton(widget,
"Radio Button"));
801 else if (type ==
"RadioButtonGroup")
802 editWidget(f->createRadioButtonGroup(widget));
803 else if (type ==
"ReplacePoint")
804 editWidget(f->createReplacePoint(widget));
805 else if (type ==
"Right")
806 editWidget(f->createRight(widget));
807 else if (type ==
"RichText")
808 editWidget(f->createRichText(widget,
"This is a <b>RichText</b>."));
809 else if (type ==
"SelectionBox")
810 editWidget(f->createSelectionBox(widget,
"Selection Box"));
811 else if (type ==
"Table")
821 for(
auto&& str: items) header->addColumn(str);
823 editWidget(f->createTable(widget, header));
826 else if (type ==
"Top")
827 editWidget(f->createTop(widget));
828 else if (type ==
"Tree")
829 editWidget(f->createTree(widget,
"Tree"));
830 else if (type ==
"VBox")
831 editWidget(f->createVBox(widget));
832 else if (type ==
"VSpacing")
833 editWidget(f->createVSpacing(widget));
834 else if (type ==
"VStretch")
835 editWidget(f->createVStretch(widget));
839 "Adding \"" + type +
"\" widget type is not supported.");
843 targetDialogUpdated();
855 void YDialogSpyPrivate::targetDialogUpdated()
862 fillWidgetTree(targetDialog, widgetTree);
868 void YDialogSpyPrivate::refreshButtonStates()
871 auto parent = widget ? widget->
parent() :
nullptr;
875 if (widget && parent && isBox(parent))
877 upButton->
setEnabled(widget != parent->firstChild());
878 upButton->
setLabel(isVBox(parent) ?
"⬆ Up" :
"⬅ Left");
879 downButton->
setEnabled(widget != parent->lastChild());
880 downButton->
setLabel(isVBox(parent) ?
"⬇ Down" :
"➡ Right");
903 void YDialogSpyPrivate::editWidget(
YWidget *widget,
const string &property)
911 editor.edit(property);
std::vector< YItem * > YItemCollection
Collection of pointers to YItem.
Implementation of all the alignment widgets:
void refreshProperties()
Refresh the displayed properties.
void addWidget(const string &type)
Generic handler for adding widgets.
~YDialogSpyPrivate()
Destructor - switch off widget highlighting at the end.
void deleteWidget()
Delete the currently selected widget.
void editProperty()
Run the property editor for the current widget.
YWidget * selectedWidget()
The currently selected wiget.
void highlightWidget(bool enable=true)
Highlight the currently selected widget in the spy dialog.
void selectedWidgetChanged()
The selected item has been changed, refresh the UI.
bool toggleProperties()
Hide or show the properties dialog.
An interactive dialog debugger: Show the structure and content of a dialog and its widgets.
void exec()
Execute the event loop.
static void showDialogSpy(YDialog *dialog=0)
Show a YDialogSpy for the specified dialog.
YDialogSpy(YDialog *dialog=0)
Constructor: Create a YDialogSpy for the specified dialog.
virtual ~YDialogSpy()
Destructor.
A window in the desktop environment.
static YDialog * topmostDialog(bool doThrow=true)
Alias for currentDialog().
bool destroy(bool doThrow=true)
Close and delete this dialog (and all its children) if it is the topmost dialog.
virtual void highlight(YWidget *child)
Highlight a child widget of this dialog.
YEvent * waitForEvent(int timeout_millisec=0)
Wait for a user event.
void recalcLayout()
Recalculate the layout of the dialog and of all its children after children have been added or remove...
std::string label() const
Return this item's label.
void setLabel(const std::string &newLabel)
Set this item's label.
A vertical or horizontal stacking of widgets, implementing HBox and VBox.
YUIDimension primary() const
Return the primary dimension, i.e., the dimension this LayoutBox lays out its children in: YD_VERT fo...
An internal helper class for displaying the widget property editor in the spy dialog.
bool edit(const std::string &property)
Display a popup for editing a widget property.
bool contains(const std::string &propertyName) const
Check if a property 'propertyName' exists in this property set.
Transport class for the value of simple properties.
std::string stringVal() const
Methods to get the value of this property.
Class for widget properties.
std::string name() const
Returns the name of this property.
std::string typeAsStr() const
Returns the type of this property as string.
YPropertyType type() const
Returns the type of this property.
A placeholder that can have its contents exchanged, using ReplaceWidget.
virtual void showChild()
Show a newly added child.
Item class for YTable items.
const YTableCell * cell(int index) const
Return the cell at the specified index (counting from 0 on) or 0 if there is none.
Table: Selection list with multiple columns.
Item class for tree items.
virtual bool hasChildren() const
Return 'true' if this item has any child items.
virtual YTreeItem * parent() const
Returns this item's parent item or 0 if it is a toplevel item.
virtual YItemIterator childrenBegin()
Return an iterator that points to the first child item of this item.
virtual YItemIterator childrenEnd()
Return an iterator that points after the last child item of this item.
bool isOpen() const
Return 'true' if this tree item should be displayed open (with its children visible) by default.
YTreeItem(const std::string &label, bool isOpen=false)
Constructors for toplevel items.
Tree: List box that displays a (scrollable) list of hierarchical items from which the user can select...
virtual void rebuildTree()=0
Rebuild the displayed tree from the internally stored YTreeItems.
Base class for UI Exceptions.
const std::string & msg() const
Return the message string provided to the constructor.
static YWidgetFactory * widgetFactory()
Return the widget factory that provides all the createXY() methods for standard (mandatory,...