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 104 YWidget * widget()
const {
return _widget; }
109 void setWidgetLabel()
111 std::ostringstream str;
122 YWidgetListConstIterator begin,
123 YWidgetListConstIterator end,
134 : targetDialog(
nullptr )
135 , spyDialog(
nullptr )
136 , widgetTree(
nullptr )
137 , propButton(
nullptr )
138 , propReplacePoint(
nullptr )
139 , propTable(
nullptr )
157 void selectedWidgetChanged();
158 void refreshProperties();
159 bool toggleProperties();
160 void highlightWidget(
bool enable =
true);
163 void addWidget(
const std::string &type);
165 void moveSelectedUp() { moveSelected(MOVE_UP); }
166 void moveSelectedDown() { moveSelected(MOVE_DOWN); }
175 void moveSelected(Direction direction);
176 void showProperties();
177 void hideProperties();
178 bool propertiesShown()
const;
179 void targetDialogUpdated();
180 void refreshButtonStates();
181 void editWidget(
YWidget *widget,
const std::string &property=
"Label");
188 highlightWidget(
false);
198 YUI_CHECK_NEW( rootItem );
200 widgetTree->
addItem( rootItem );
209 if ( ! targetDialog )
212 priv->targetDialog = targetDialog;
215 priv->spyDialog = fac->createPopupDialog();
216 YAlignment * diaMin = fac->createMinHeight( priv->spyDialog, DIA_HEIGHT );
217 YLayoutBox * vbox = fac->createVBox( diaMin );
219 auto alignment = fac->createLeft( vbox );
220 auto fileMenu = fac->createMenuButton( alignment,
"&File" );
223 priv->exportMenu =
new YMenuItem(
"Export (TODO)" );
224 items.push_back( priv->exportMenu );
225 fileMenu->addItems( items );
227 auto minSize = fac->createMinSize( vbox, TREE_WIDTH, TREE_HEIGHT );
228 minSize->
setWeight( YD_VERT, TREE_VWEIGHT );
229 priv->widgetTree = fac->createTree( minSize,
"Widget &Tree",
false );
232 fillWidgetTree(priv->targetDialog, priv->widgetTree);
234 auto hbox = fac->createHBox( vbox );
235 priv->propButton = fac->createPushButton( hbox,
"&Properties >>>" );
237 priv->addButton = fac->createMenuButton( hbox,
"&Add" );
246 add_items.push_back( menu_info );
247 add_items.push_back( menu_buttons );
248 add_items.push_back( menu_input );
249 add_items.push_back( menu_align );
250 add_items.push_back( menu_size );
251 add_items.push_back( menu_containers );
252 add_items.push_back( menu_special );
257 new YMenuItem( menu_info,
"ProgressBar" );
258 new YMenuItem( menu_info,
"BusyIndicator" );
261 new YMenuItem( menu_buttons,
"PushButton" );
262 new YMenuItem( menu_buttons,
"CheckBox" );
263 new YMenuItem( menu_buttons,
"ComboBox" );
264 new YMenuItem( menu_buttons,
"MenuButton" );
265 new YMenuItem( menu_buttons,
"RadioButton" );
267 new YMenuItem( menu_input,
"InputField" );
269 new YMenuItem( menu_input,
"MultiLineEdit" );
270 new YMenuItem( menu_input,
"MultiSelectionBox" );
272 new YMenuItem( menu_input,
"SelectionBox" );
291 new YMenuItem( menu_containers,
"MarginBox" );
292 new YMenuItem( menu_containers,
"ButtonBox" );
293 new YMenuItem( menu_containers,
"CheckBoxFrame" );
294 new YMenuItem( menu_containers,
"Frame" );
295 new YMenuItem( menu_containers,
"HBox" );
296 new YMenuItem( menu_containers,
"HSpacing" );
297 new YMenuItem( menu_containers,
"ReplacePoint" );
298 new YMenuItem( menu_containers,
"VBox" );
299 new YMenuItem( menu_containers,
"VSpacing" );
302 new YMenuItem( menu_special,
"BarGraph" );
303 new YMenuItem( menu_special,
"DateField" );
304 new YMenuItem( menu_special,
"DumbTab" );
307 new YMenuItem( menu_input,
"TimeField" );
308 new YMenuItem( menu_special,
"TimezoneSelector" );
310 priv->addButton->
addItems( add_items );
312 priv->deleteButton = fac->createPushButton( hbox,
"&Delete" );
313 priv->upButton = fac->createPushButton( hbox,
"⬆ Up" );
314 priv->downButton = fac->createPushButton( hbox,
"⬇ Down" );
316 priv->propReplacePoint = fac->createReplacePoint( vbox );
317 fac->createEmpty( priv->propReplacePoint );
327 if ( priv->spyDialog )
334 bool YDialogSpyPrivate::propertiesShown()
const 336 return propTable !=
nullptr;
344 if (targetDialog) targetDialog->highlight( enable ? selectedWidget() :
nullptr);
350 void YDialogSpyPrivate::showProperties()
354 propReplacePoint->deleteChildren();
355 propReplacePoint->setWeight( YD_VERT, PROP_VWEIGHT );
358 auto minSize = fac->createMinSize( propReplacePoint,
359 PROP_WIDTH, PROP_HEIGHT );
361 YUI_CHECK_NEW( header );
362 header->addColumn(
"Property" );
363 header->addColumn(
"Value" );
364 header->addColumn(
"Type" );
366 propTable = fac->createTable( minSize, header );
367 propTable->setNotify(
true );
369 propButton->setLabel(
"<<< &Properties" );
370 propReplacePoint->showChild();
371 spyDialog->recalcLayout();
377 void YDialogSpyPrivate::hideProperties()
381 propReplacePoint->deleteChildren();
382 propReplacePoint->setWeight( YD_VERT, 0 );
386 propButton->setLabel(
"&Properties >>>" );
387 propReplacePoint->showChild();
388 spyDialog->recalcLayout();
420 propTable->deleteAllItems();
421 auto widget = selectedWidget();
427 auto propSet = widget->propertySet();
428 items.reserve( propSet.size() );
430 for ( YPropertySet::const_iterator it = propSet.propertiesBegin();
431 it != propSet.propertiesEnd();
436 std::string propValStr;
438 switch ( prop.
type() )
440 case YStringProperty:
445 propValStr = propVal.boolVal() ?
"true" :
"false";
448 case YIntegerProperty:
449 propValStr = std::to_string(propVal.integerVal());
458 YUI_CHECK_NEW( item );
459 items.push_back( item );
462 propTable->addItems( items );
463 propTable->deselectAllItems();
474 YWidgetListConstIterator begin,
475 YWidgetListConstIterator end,
478 for ( YWidgetListConstIterator it = begin; it != end; ++it )
493 YUI_CHECK_PTR( priv->spyDialog );
498 yuiMilestone() <<
"event: " << event;
499 if (!event)
continue;
502 if ( event->eventType() == YEvent::CancelEvent )
break;
503 else if ( event->eventType() == YEvent::MenuEvent)
508 if (menu_item == priv->exportMenu)
continue;
514 auto menu_label = menu_item->
label();
515 yuiMilestone() <<
"Activated menu item: " << menu_label << std::endl;
523 if (!event->widget())
continue;
525 if ( event->widget() == priv->upButton ) priv->moveSelectedUp();
526 else if ( event->widget() == priv->downButton) priv->moveSelectedDown();
528 else if ( event->widget() == priv->deleteButton) priv->
deleteWidget();
529 else if ( event->widget() == priv->propTable ) priv->
editProperty();
548 YUI_CAUGHT( exception );
561 return item ? item->widget() :
nullptr;
571 refreshButtonStates();
579 auto selected_item =
dynamic_cast<YTableItem *
>(propTable->selectedItem());
580 if (!selected_item)
return;
582 auto cell = selected_item->
cell(0);
583 yuiMilestone() <<
"editing property: " << cell->label();
587 if (editor.
edit(cell->label())) refreshProperties();
595 auto w = selectedWidget();
598 auto parent = w->
parent();
601 yuiMilestone() <<
"removing widget: " << w << std::endl;
602 parent->removeChild(w);
617 targetDialogUpdated();
625 bool isBox(
const YWidget *widget)
627 return dynamic_cast<const YLayoutBox *
>(widget);
635 bool isVBox(
const YWidget *widget)
637 auto box =
dynamic_cast<const YLayoutBox *
>(widget);
638 return box && box->
primary() == YD_VERT;
647 void YDialogSpyPrivate::moveSelected(Direction direction)
649 auto target_widget = selectedWidget();
650 if (!target_widget)
return;
652 auto parent = target_widget->
parent();
653 if (!parent || !isBox(parent))
return;
655 if (direction == MOVE_UP)
658 if (target_widget == parent->firstChild())
return;
666 std::swap(*other, *i);
673 if (target_widget == parent->lastChild())
return;
681 std::swap(*other, *i);
685 targetDialogUpdated();
694 auto widget = selectedWidget();
701 if (type ==
"Bottom")
702 editWidget(f->createBottom(widget));
703 else if (type ==
"BusyIndicator")
704 editWidget(f->createBusyIndicator(widget,
"Busy Indicator", 10000));
705 else if (type ==
"ButtonBox")
706 editWidget(f->createButtonBox(widget));
707 else if (type ==
"ComboBox")
709 auto cb = f->createComboBox(widget,
"Combo Box");
716 for(
auto&& str: items) add_items.push_back(
new YMenuItem( str ) );
717 cb->addItems( add_items );
719 else if (type ==
"Empty")
720 editWidget(f->createEmpty(widget));
721 else if (type ==
"Frame")
722 editWidget(f->createFrame(widget,
"Frame"));
723 else if (type ==
"HBox")
724 editWidget(f->createHBox(widget));
725 else if (type ==
"Heading")
726 editWidget(f->createHeading(widget,
"Heading"));
727 else if (type ==
"HSpacing")
728 editWidget(f->createHSpacing(widget));
729 else if (type ==
"HStretch")
730 editWidget(f->createHStretch(widget));
731 else if (type ==
"CheckBox")
732 editWidget(f->createCheckBox(widget,
"Check Box"));
733 else if (type ==
"CheckBoxFrame")
735 editWidget(f->createCheckBoxFrame(widget,
"Check Box Frame",
true));
736 else if (type ==
"Image")
737 editWidget(f->createImage(widget,
""));
738 else if (type ==
"InputField")
739 editWidget(f->createInputField(widget,
"Input"));
740 else if (type ==
"IntField")
741 editWidget(f->createIntField(widget,
"Integer Field", 0, 100, 50));
742 else if (type ==
"Label")
743 editWidget(f->createLabel(widget,
"Label"));
744 else if (type ==
"Left")
745 editWidget(f->createLeft(widget));
746 else if (type ==
"LogView")
747 editWidget(f->createLogView(widget,
"Log View", 12));
748 else if (type ==
"MenuButton")
750 auto menu = f->createMenuButton( widget,
"Menu" );
757 for(
auto&& str: items) add_items.push_back(
new YMenuItem( str ) );
758 menu->addItems( add_items );
760 else if (type ==
"MinHeight")
761 editWidget(f->createMinHeight(widget, 10));
762 else if (type ==
"MinWidth")
763 editWidget(f->createMinWidth(widget, 10));
764 else if (type ==
"MinSize")
765 editWidget(f->createMinSize(widget, 10, 10));
766 else if (type ==
"MultiLineEdit")
767 editWidget(f->createMultiLineEdit(widget,
"MultiLineEdit"));
768 else if (type ==
"MultiSelectionBox")
770 auto msb = f->createMultiSelectionBox(widget,
"MultiSelection Box");
776 for(
auto&& str: items) msb->addItem(str);
778 else if (type ==
"OutputField")
779 editWidget(f->createOutputField(widget,
"Output Field"));
780 else if (type ==
"Password")
781 editWidget(f->createPasswordField(widget,
"Password"));
782 else if (type ==
"ProgressBar")
783 editWidget(f->createProgressBar(widget,
"Progress"));
784 else if (type ==
"PushButton")
785 editWidget(f->createPushButton(widget,
"Button"));
786 else if (type ==
"RadioButton")
787 editWidget(f->createRadioButton(widget,
"Radio Button"));
788 else if (type ==
"RadioButtonGroup")
789 editWidget(f->createRadioButtonGroup(widget));
790 else if (type ==
"ReplacePoint")
791 editWidget(f->createReplacePoint(widget));
792 else if (type ==
"Right")
793 editWidget(f->createRight(widget));
794 else if (type ==
"RichText")
795 editWidget(f->createRichText(widget,
"This is a <b>RichText</b>."));
796 else if (type ==
"SelectionBox")
797 editWidget(f->createSelectionBox(widget,
"Selection Box"));
798 else if (type ==
"Table")
808 for(
auto&& str: items) header->addColumn(str);
810 editWidget(f->createTable(widget, header));
813 else if (type ==
"Top")
814 editWidget(f->createTop(widget));
815 else if (type ==
"Tree")
816 editWidget(f->createTree(widget,
"Tree"));
817 else if (type ==
"VBox")
818 editWidget(f->createVBox(widget));
819 else if (type ==
"VSpacing")
820 editWidget(f->createVSpacing(widget));
821 else if (type ==
"VStretch")
822 editWidget(f->createVStretch(widget));
826 "Adding \"" + type +
"\" widget type is not supported.");
830 targetDialogUpdated();
842 void YDialogSpyPrivate::targetDialogUpdated()
845 targetDialog->recalcLayout();
849 fillWidgetTree(targetDialog, widgetTree);
855 void YDialogSpyPrivate::refreshButtonStates()
857 auto widget = selectedWidget();
858 auto parent = widget ? widget->
parent() :
nullptr;
862 if (widget && parent && isBox(parent))
864 upButton->
setEnabled(widget != parent->firstChild());
865 upButton->setLabel(isVBox(parent) ?
"⬆ Up" :
"⬅ Left");
866 downButton->setEnabled(widget != parent->lastChild());
867 downButton->setLabel(isVBox(parent) ?
"⬇ Down" :
"➡ Right");
871 upButton->setEnabled(
false);
872 downButton->setEnabled(
false);
882 deleteButton->setEnabled(parent);
890 void YDialogSpyPrivate::editWidget(
YWidget *widget,
const std::string &property)
893 targetDialog->recalcLayout();
898 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.