27 #define YUILogComponent "ui-dialog-spy" 30 #include <YDialogSpy.h> 31 #include <YWidgetFactory.h> 36 #include <YTreeItem.h> 37 #include <YLayoutBox.h> 38 #include <YAlignment.h> 39 #include <YButtonBox.h> 40 #include <YPushButton.h> 41 #include <YMenuButton.h> 42 #include <YComboBox.h> 43 #include <YInputField.h> 44 #include <YCheckBox.h> 45 #include <YRadioButton.h> 46 #include <YProgressBar.h> 47 #include <YRichText.h> 48 #include <YBusyIndicator.h> 49 #include <YSelectionBox.h> 50 #include <YMultiSelectionBox.h> 51 #include <YMultiLineEdit.h> 54 #include <YIntField.h> 59 #include <YPackageSelector.h> 60 #include <YReplacePoint.h> 61 #include <YPropertyEditor.h> 62 #include <YPopupInternal.h> 63 #include <YAlignment.h> 64 #include <YCheckBoxFrame.h> 65 #include <YRadioButtonGroup.h> 68 #define TREE_VWEIGHT 40 69 #define PROP_VWEIGHT 60 73 #define TREE_HEIGHT 10 76 #define PROP_HEIGHT 12 103 YWidget * widget()
const {
return _widget; }
108 void setWidgetLabel()
110 std::ostringstream str;
121 YWidgetListConstIterator begin,
122 YWidgetListConstIterator end,
133 : targetDialog(
nullptr )
134 , spyDialog(
nullptr )
135 , widgetTree(
nullptr )
136 , propButton(
nullptr )
137 , propReplacePoint(
nullptr )
138 , propTable(
nullptr )
156 void selectedWidgetChanged();
157 void refreshProperties();
158 bool toggleProperties();
159 void highlightWidget(
bool enable =
true);
162 void addWidget(
const std::string &type);
164 void moveSelectedUp() { moveSelected(MOVE_UP); }
165 void moveSelectedDown() { moveSelected(MOVE_DOWN); }
174 void moveSelected(Direction direction);
175 void showProperties();
176 void hideProperties();
177 bool propertiesShown()
const;
178 void targetDialogUpdated();
179 void refreshButtonStates();
180 void editWidget(
YWidget *widget,
const std::string &property=
"Label");
187 highlightWidget(
false);
197 YUI_CHECK_NEW( rootItem );
199 widgetTree->
addItem( rootItem );
208 if ( ! targetDialog )
211 priv->targetDialog = targetDialog;
214 priv->spyDialog = fac->createPopupDialog();
215 YAlignment * diaMin = fac->createMinHeight( priv->spyDialog, DIA_HEIGHT );
216 YLayoutBox * vbox = fac->createVBox( diaMin );
218 auto alignment = fac->createLeft( vbox );
219 auto fileMenu = fac->createMenuButton( alignment,
"&File" );
222 priv->exportMenu =
new YMenuItem(
"Export (TODO)" );
223 items.push_back( priv->exportMenu );
224 fileMenu->addItems( items );
226 auto minSize = fac->createMinSize( vbox, TREE_WIDTH, TREE_HEIGHT );
227 minSize->
setWeight( YD_VERT, TREE_VWEIGHT );
228 priv->widgetTree = fac->createTree( minSize,
"Widget &Tree",
false );
231 fillWidgetTree(priv->targetDialog, priv->widgetTree);
233 auto hbox = fac->createHBox( vbox );
234 priv->propButton = fac->createPushButton( hbox,
"&Properties >>>" );
236 priv->addButton = fac->createMenuButton( hbox,
"&Add" );
245 add_items.push_back( menu_info );
246 add_items.push_back( menu_buttons );
247 add_items.push_back( menu_input );
248 add_items.push_back( menu_align );
249 add_items.push_back( menu_size );
250 add_items.push_back( menu_containers );
251 add_items.push_back( menu_special );
256 new YMenuItem( menu_info,
"ProgressBar" );
257 new YMenuItem( menu_info,
"BusyIndicator" );
260 new YMenuItem( menu_buttons,
"PushButton" );
261 new YMenuItem( menu_buttons,
"CheckBox" );
262 new YMenuItem( menu_buttons,
"ComboBox" );
263 new YMenuItem( menu_buttons,
"MenuButton" );
264 new YMenuItem( menu_buttons,
"RadioButton" );
266 new YMenuItem( menu_input,
"InputField" );
268 new YMenuItem( menu_input,
"MultiLineEdit" );
269 new YMenuItem( menu_input,
"MultiSelectionBox" );
271 new YMenuItem( menu_input,
"SelectionBox" );
290 new YMenuItem( menu_containers,
"MarginBox" );
291 new YMenuItem( menu_containers,
"ButtonBox" );
292 new YMenuItem( menu_containers,
"CheckBoxFrame" );
293 new YMenuItem( menu_containers,
"Frame" );
294 new YMenuItem( menu_containers,
"HBox" );
295 new YMenuItem( menu_containers,
"HSpacing" );
296 new YMenuItem( menu_containers,
"ReplacePoint" );
297 new YMenuItem( menu_containers,
"VBox" );
298 new YMenuItem( menu_containers,
"VSpacing" );
301 new YMenuItem( menu_special,
"BarGraph" );
302 new YMenuItem( menu_special,
"DateField" );
303 new YMenuItem( menu_special,
"DumbTab" );
306 new YMenuItem( menu_input,
"TimeField" );
307 new YMenuItem( menu_special,
"TimezoneSelector" );
309 priv->addButton->
addItems( add_items );
311 priv->deleteButton = fac->createPushButton( hbox,
"&Delete" );
312 priv->upButton = fac->createPushButton( hbox,
"⬆ Up" );
313 priv->downButton = fac->createPushButton( hbox,
"⬇ Down" );
315 priv->propReplacePoint = fac->createReplacePoint( vbox );
316 fac->createEmpty( priv->propReplacePoint );
326 if ( priv->spyDialog )
333 bool YDialogSpyPrivate::propertiesShown()
const 335 return propTable !=
nullptr;
343 if (targetDialog) targetDialog->highlight( enable ? selectedWidget() :
nullptr);
349 void YDialogSpyPrivate::showProperties()
353 propReplacePoint->deleteChildren();
354 propReplacePoint->setWeight( YD_VERT, PROP_VWEIGHT );
357 auto minSize = fac->createMinSize( propReplacePoint,
358 PROP_WIDTH, PROP_HEIGHT );
360 YUI_CHECK_NEW( header );
361 header->addColumn(
"Property" );
362 header->addColumn(
"Value" );
363 header->addColumn(
"Type" );
365 propTable = fac->createTable( minSize, header );
366 propTable->setNotify(
true );
368 propButton->setLabel(
"<<< &Properties" );
369 propReplacePoint->showChild();
370 spyDialog->recalcLayout();
376 void YDialogSpyPrivate::hideProperties()
380 propReplacePoint->deleteChildren();
381 propReplacePoint->setWeight( YD_VERT, 0 );
385 propButton->setLabel(
"&Properties >>>" );
386 propReplacePoint->showChild();
387 spyDialog->recalcLayout();
417 propTable->deleteAllItems();
419 auto widget = selectedWidget();
422 auto propSet = widget->propertySet();
424 items.reserve( propSet.size() );
426 for ( YPropertySet::const_iterator it = propSet.propertiesBegin();
427 it != propSet.propertiesEnd();
432 std::string propValStr;
434 switch ( prop.
type() )
436 case YStringProperty:
441 propValStr = propVal.boolVal() ?
"true" :
"false";
444 case YIntegerProperty:
445 propValStr = std::to_string(propVal.integerVal());
454 YUI_CHECK_NEW( item );
455 items.push_back( item );
458 propTable->addItems( items );
459 propTable->deselectAllItems();
470 YWidgetListConstIterator begin,
471 YWidgetListConstIterator end,
474 for ( YWidgetListConstIterator it = begin; it != end; ++it )
489 YUI_CHECK_PTR( priv->spyDialog );
494 yuiMilestone() <<
"event: " << event;
495 if (!event)
continue;
498 if ( event->eventType() == YEvent::CancelEvent )
break;
499 else if ( event->eventType() == YEvent::MenuEvent)
504 if (menu_item == priv->exportMenu)
continue;
510 auto menu_label = menu_item->
label();
511 yuiMilestone() <<
"Activated menu item: " << menu_label << std::endl;
519 if (!event->widget())
continue;
521 if ( event->widget() == priv->upButton ) priv->moveSelectedUp();
522 else if ( event->widget() == priv->downButton) priv->moveSelectedDown();
524 else if ( event->widget() == priv->deleteButton) priv->
deleteWidget();
525 else if ( event->widget() == priv->propTable ) priv->
editProperty();
544 YUI_CAUGHT( exception );
557 return item ? item->widget() :
nullptr;
567 refreshButtonStates();
575 auto selected_item =
dynamic_cast<YTableItem *
>(propTable->selectedItem());
576 if (!selected_item)
return;
578 auto cell = selected_item->
cell(0);
579 yuiMilestone() <<
"editing property: " << cell->label();
583 if (editor.
edit(cell->label())) refreshProperties();
591 auto w = selectedWidget();
594 auto parent = w->
parent();
597 yuiMilestone() <<
"removing widget: " << w << std::endl;
598 parent->removeChild(w);
613 targetDialogUpdated();
621 bool isBox(
const YWidget *widget)
623 return dynamic_cast<const YLayoutBox *
>(widget);
631 bool isVBox(
const YWidget *widget)
633 auto box =
dynamic_cast<const YLayoutBox *
>(widget);
634 return box && box->
primary() == YD_VERT;
643 void YDialogSpyPrivate::moveSelected(Direction direction)
645 auto target_widget = selectedWidget();
646 if (!target_widget)
return;
648 auto parent = target_widget->
parent();
649 if (!parent || !isBox(parent))
return;
651 if (direction == MOVE_UP)
654 if (target_widget == parent->firstChild())
return;
662 std::swap(*other, *i);
669 if (target_widget == parent->lastChild())
return;
677 std::swap(*other, *i);
681 targetDialogUpdated();
690 auto widget = selectedWidget();
697 if (type ==
"Bottom")
698 editWidget(f->createBottom(widget));
699 else if (type ==
"BusyIndicator")
700 editWidget(f->createBusyIndicator(widget,
"Busy Indicator", 10000));
701 else if (type ==
"ButtonBox")
702 editWidget(f->createButtonBox(widget));
703 else if (type ==
"ComboBox")
705 auto cb = f->createComboBox(widget,
"Combo Box");
712 for(
auto&& str: items) add_items.push_back(
new YMenuItem( str ) );
713 cb->addItems( add_items );
715 else if (type ==
"Empty")
716 editWidget(f->createEmpty(widget));
717 else if (type ==
"Frame")
718 editWidget(f->createFrame(widget,
"Frame"));
719 else if (type ==
"HBox")
720 editWidget(f->createHBox(widget));
721 else if (type ==
"Heading")
722 editWidget(f->createHeading(widget,
"Heading"));
723 else if (type ==
"HSpacing")
724 editWidget(f->createHSpacing(widget));
725 else if (type ==
"HStretch")
726 editWidget(f->createHStretch(widget));
727 else if (type ==
"CheckBox")
728 editWidget(f->createCheckBox(widget,
"Check Box"));
729 else if (type ==
"CheckBoxFrame")
731 editWidget(f->createCheckBoxFrame(widget,
"Check Box Frame",
true));
732 else if (type ==
"Image")
733 editWidget(f->createImage(widget,
""));
734 else if (type ==
"InputField")
735 editWidget(f->createInputField(widget,
"Input"));
736 else if (type ==
"IntField")
737 editWidget(f->createIntField(widget,
"Integer Field", 0, 100, 50));
738 else if (type ==
"Label")
739 editWidget(f->createLabel(widget,
"Label"));
740 else if (type ==
"Left")
741 editWidget(f->createLeft(widget));
742 else if (type ==
"LogView")
743 editWidget(f->createLogView(widget,
"Log View", 12));
744 else if (type ==
"MenuButton")
746 auto menu = f->createMenuButton( widget,
"Menu" );
753 for(
auto&& str: items) add_items.push_back(
new YMenuItem( str ) );
754 menu->addItems( add_items );
756 else if (type ==
"MinHeight")
757 editWidget(f->createMinHeight(widget, 10));
758 else if (type ==
"MinWidth")
759 editWidget(f->createMinWidth(widget, 10));
760 else if (type ==
"MinSize")
761 editWidget(f->createMinSize(widget, 10, 10));
762 else if (type ==
"MultiLineEdit")
763 editWidget(f->createMultiLineEdit(widget,
"MultiLineEdit"));
764 else if (type ==
"MultiSelectionBox")
766 auto msb = f->createMultiSelectionBox(widget,
"MultiSelection Box");
772 for(
auto&& str: items) msb->addItem(str);
774 else if (type ==
"OutputField")
775 editWidget(f->createOutputField(widget,
"Output Field"));
776 else if (type ==
"Password")
777 editWidget(f->createPasswordField(widget,
"Password"));
778 else if (type ==
"ProgressBar")
779 editWidget(f->createProgressBar(widget,
"Progress"));
780 else if (type ==
"PushButton")
781 editWidget(f->createPushButton(widget,
"Button"));
782 else if (type ==
"RadioButton")
783 editWidget(f->createRadioButton(widget,
"Radio Button"));
784 else if (type ==
"RadioButtonGroup")
785 editWidget(f->createRadioButtonGroup(widget));
786 else if (type ==
"ReplacePoint")
787 editWidget(f->createReplacePoint(widget));
788 else if (type ==
"Right")
789 editWidget(f->createRight(widget));
790 else if (type ==
"RichText")
791 editWidget(f->createRichText(widget,
"This is a <b>RichText</b>."));
792 else if (type ==
"SelectionBox")
793 editWidget(f->createSelectionBox(widget,
"Selection Box"));
794 else if (type ==
"Table")
804 for(
auto&& str: items) header->addColumn(str);
806 editWidget(f->createTable(widget, header));
809 else if (type ==
"Top")
810 editWidget(f->createTop(widget));
811 else if (type ==
"Tree")
812 editWidget(f->createTree(widget,
"Tree"));
813 else if (type ==
"VBox")
814 editWidget(f->createVBox(widget));
815 else if (type ==
"VSpacing")
816 editWidget(f->createVSpacing(widget));
817 else if (type ==
"VStretch")
818 editWidget(f->createVStretch(widget));
822 "Adding \"" + type +
"\" widget type is not supported.");
826 targetDialogUpdated();
838 void YDialogSpyPrivate::targetDialogUpdated()
841 targetDialog->recalcLayout();
845 fillWidgetTree(targetDialog, widgetTree);
851 void YDialogSpyPrivate::refreshButtonStates()
853 auto widget = selectedWidget();
854 auto parent = widget ? widget->
parent() :
nullptr;
858 if (widget && parent && isBox(parent))
860 upButton->
setEnabled(widget != parent->firstChild());
861 upButton->setLabel(isVBox(parent) ?
"⬆ Up" :
"⬅ Left");
862 downButton->setEnabled(widget != parent->lastChild());
863 downButton->setLabel(isVBox(parent) ?
"⬇ Down" :
"➡ Right");
867 upButton->setEnabled(
false);
868 downButton->setEnabled(
false);
878 deleteButton->setEnabled(parent);
886 void YDialogSpyPrivate::editWidget(
YWidget *widget,
const std::string &property)
889 targetDialog->recalcLayout();
894 editor.
edit(property);
void highlightWidget(bool enable=true)
Highlight the currently selected widget in the spy dialog.
virtual bool hasChildren() const
Return 'true' if this item has any child items.
virtual YItemIterator childrenEnd()
Return an iterator that points after the last child item of this item.
std::string label() const
Return this item's label.
static YWidgetFactory * widgetFactory()
Return the widget factory that provides all the createXY() methods for standard (mandatory, i.e.
A vertical or horizontal stacking of widgets, implementing HBox and VBox.
A placeholder that can have its contents exchanged, using ReplaceWidget.
void deleteWidget()
Delete the currently selected widget.
Transport class for the value of simple properties.
std::vector< YItem * > YItemCollection
Collection of pointers to YItem.
void hideProperties()
Hide the "Properties" sub-window.
bool contains(const std::string &propertyName) const
Check if a property 'propertyName' exists in this property set.
An internal helper class for displaying the widget property editor in the spy dialog.
YPropertyType type() const
Returns the type of this property.
const YTableCell * cell(int index) const
Return the cell at the specified index (counting from 0 on) or 0 if there is none.
void editProperty()
Run the property editor for the current widget.
bool isOpen() const
Return 'true' if this tree item should be displayed open (with its children visible) by default...
std::string typeAsStr() const
Returns the type of this property as string.
void showProperties()
Show the "Properties" sub-window.
std::string name() const
Returns the name of this property.
bool edit(const std::string &property)
Display a popup for editing a widget property.
Table: Selection list with multiple columns.
virtual YTreeItem * parent() const
Returns this item's parent item or 0 if it is a toplevel item.
An interactive dialog debugger: Show the structure and content of a dialog and its widgets...
void addWidget(const std::string &type)
Generic handler for adding widgets.
bool toggleProperties()
Hide or show the properties dialog.
Implementation of all the alignment widgets:
YTreeItem(const std::string &label, bool isOpen=false)
Constructors for toplevel items.
virtual ~YDialogSpy()
Destructor.
std::string stringVal() const
Methods to get the value of this property.
YDialogSpy(YDialog *dialog=0)
Constructor: Create a YDialogSpy for the specified dialog.
Class for widget properties.
void setLabel(const std::string &newLabel)
Set this item's label.
static void showDialogSpy(YDialog *dialog=0)
Show a YDialogSpy for the specified dialog.
void exec()
Execute the event loop.
const std::string & msg() const
Return the message string provided to the constructor.
bool propertiesShown() const
Return 'true' if the "Properties" sub-window is currently shown, 'false' if not.
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.
void refreshProperties()
Refresh the displayed properties.
A window in the desktop environment.
virtual YItemIterator childrenBegin()
Return an iterator that points to the first child item of this item.
Item class for YTable items.
void selectedWidgetChanged()
The selected item has been changed, refresh the UI.
static YDialog * topmostDialog(bool doThrow=true)
Alias for currentDialog().
Base class for UI Exceptions.
~YDialogSpyPrivate()
Destructor - switch off widget highlighting at the end.
YUIDimension primary() const
Return the primary dimension, i.e., the dimension this LayoutBox lays out its children in: YD_VERT fo...
YWidget * selectedWidget()
The currently selected wiget.
Item class for tree items.
bool destroy(bool doThrow=true)
Close and delete this dialog (and all its children) if it is the topmost dialog.
YEvent * waitForEvent(int timeout_millisec=0)
Wait for a user event.