Guide is a cross GUI system databinding and widget layout engine. At the time of this writing, there are Guide implementations for CEGUI, WxPython, HTML, and Panda3D's DirectGUI. Not all widgets are available in all implementations, but in most cases, the same layout files and bound data can be used to create a GUI in any of those systems. To see just how easy it is, here's an example:
<!-- hello.xml -->
<Window text="VAR" onClose="{Event onClose}">
<StackFrame>
<Label>Hello Guide World</Label>
<Button>Click Me!</Button>
</StackFrame>
</Window>
# hello.py
from twisted.internet import wxreactor
wxreactor.install()
from twisted.internet import reactor
import wx
from mv3d.tools.guidewx import WxParser
app = wx.PySimpleApp(0)
wx.InitAllImageHandlers()
wxparser = WxParser(guidewx)
wxguide = wxparser.load("hello.xml", None)
app.SetTopWindow(wxguide.window)
wxguide.show()
reactor.registerWxApp(app) #@UndefinedVariable
reactor.run()
And here's the result:
This is of course for WxPython. The main bits of code to pay attention to are these lines:
wxparser = WxParser(guidewx)
wxguide = wxparser.load("hello.xml", data)
wxguide.show()
That's the main pattern for creating a new window in Guide. The first line instantiates a new parser. There's a parser for each GUI system implementation.
The next line loads and parses the xml file. All the parsers follow the same API. See the load method of guide.Parser for more information on how to use this. The load method returns a widget which in the third line is displayed.
All attributes in Guide can use databinding. Databinding is just as it sounds-- a way to bind data to something. In order for an attribute to use the databinding engine, the value must start and end with braces {}. The main way to bind an attribute to data is to use the Bind command. The Bind command is fairly simple. In order to bind the text attribute to the value of foo on the dataContext, you could do something like this:
<TextBox text="{Bind foo}"/>
Since databinding goes both ways, the initial text in the box would be whatever the value of foo was. If the value of foo was changed at a later date, the textbox would update accordingly. Alternately, if the user were to change the text in the box, then the value of foo would be updated.
But where is foo? The foo attribute is on the dataContext which is an object that is bound to the GUI. All top level widgets are bound to the dataContext object. It is possible that other widgets may be bound to attributes of the top level dataContext. One way to do this is to specify the dataContext attribute on the widget.
Events are another type of command used in databinding. While the Bind command binds to data, the Event command binds to function calls. Take the following dataContext object:
class Foo(ChangeNotifier):
def somethingHappened(self, obj, eventData):
print obj, "fired the event with", eventData
This event could be bound to left mouse clicks with the following xml:
<Label onLeftUp="{Event somethingHappened}">Click me</Label>
When called, the first argument (obj in this case) is set to the widget firing the event. The second argument (eventData) is set to something specific to the event. For example, a key event may include which key was pressed.
Styles are similar to CSS. Basically, they provide a way to set the look and feel of widgets without having to specify the same attributes over and over again. They are defined at the top level of the document (under the Guide tag) like this:
<Style name="A Style">
<TextBox>
<Width>50</Width>
<Height>20</Height>
</TextBox>
<Any>
<Text>Oh my!</Text>
</Any>
</Style>
This would make it so that any text box with that style applied would have a width of 50 and height of 20. Any widgets with the style will have "Oh my!" as their text. This style could be used like this:
<StackFrame style="A Style">
<TextBox/>
<Button/>
</StackFrame>
When a style is defined, it is applied to all children.
A Template is a way to define a set of widgets that can be used multiple times. Templates are defined at the top level of the xml document (under the Guide element). They look like this:
<Template name="The Template">
<StackFrame>
<Label text="Foo"/>
<Label text="Bar"/>
</StackFrame>
</Template>
Templates can then be used with the Template command:
<ListFrame itemTemplate="{Template The Template}"/>
When using the databinding engine, you need to make sure changes are broadcasted to all listeners. This can be done by inheriting from [pydoc:mv3d.util.guide.ChangeNotifier]. Then whenever an attribute changes, call {{{self.propertyChanged("propertyName")}}}.
from mv3d.util.guide import ChangeNotifier
class Foo(ChangeNotifier):
def __init__(self):
self.bar = 23
def setBar(self, value):
self.bar = value
self.propertyChanged("bar")
Since there's a lot of manual work involved with that way of doing things. Instead, using guide.NotifierProperty. Here's the same class using this method:
from mv3d.util.guide import ChangeNotifier, NotifierProperty
class Foo(ChangeNotifier):
bar = NotifierProperty("bar")
def __init__(self):
self.bar = 23
Now whenever bar is set, the propertyChanged notification will automatically be fired.
Guide has quite a big variety of widgets. Every widget isn't supported on all platforms, but all the core widgets are implemented on all platforms.
A basic frame that provides no layout.
A cell in a Grid Frame which is part of a Grid Row.
* colspan (1) - How many columns this cell takes up.
A frame that arranges items in a grid using GridRow and GridCell.
A row in a Grid Frame.
* rowspan (1) - How many rows does this row take up.
Groups contents in a box that has a label.
* direction (vertical) - The direction to lay out the contents.
A static image.
* image - Defines the actual image object.
* imageFile - Can be set to a filename of an image to load.
A simple text label.
Displays a list of items that can be selected.
* items - The list of items to display.
* itemTemplate - Template used to display the items (not currently supported).
* selection - The current selection.
* selectMultiple (False) - If True, multiple items can be selected.
* columns - If set, this defines the columns.
* firstSelection - Set to the first selected item (in multiple selection or single selection mode).
* onSelect - Event that is fired when an item is selected.
* onDoubleClick - Event that is fired when an item is double clicked.
This is a frame that is basically a stack frame where the items are templated and pulled from a list.
* items - The list of items to display.
* itemTemplate - A data template to use when displaying each item.
* direction (vertical) - The direction to stack the items.
A standard window menu.
A standard window menu bar. It includes one or more Menus.
A menu item from a Menu.
* itemType (normal) - The type of item. Options are:
* normal: just text.
* check: Has a check box.
* radio: Has a radio selector.
* separator: No text, just a separator. Likely un-clickable.
* selected - Set to true if this is a check or radio menu item that has been selected.
* subMenu - Set to a Menu define a sub menu off of this item.
* onClick - Event that is fired when the Menu Item is clicked.
A compound widget for editing an orientation. It is displayed as a euler angle (in degrees or radians) and translates to either a euler angle (radians) or a quaternion.
* euler - The euler representation of the orientation.
* quaternion - The quaternion representation of the orientation.
* renderFrame - Currently unused.
* showGizmo - Currently unused.
* units (radians) - Set to radians or degrees to choose the units to use.
A compound widget for editing a position vector in 3 dimensions.
* vector - The output vector.
* renderFrame - Currently unused.
* showGizmo - Currently unused.
Shows a Python console.
* locals - Defines any extra locals for the console.
Shows a 3D scene in a frame.
* cameraPosition (0, 0, 0) - Sets the camera position
* cameraOrientation (1, 0, 0, 0) - Sets the camera orientation as a quaternion.
* cameraTarget (0, 0, 0) - The target of the camera.
* renderMode (solid) - Can be set to solid or wireframe.
* backgroundColor (0, 0, 0) - The background color of the window.
* mouseMove (True) - Allow mouse movements.
* cameraMode - Deprecated
* cameraController (mv3d.util.camera.DefaultCameraController) - Defines the type of camera controller to use.
* orbitDist - Sets the orbit distance for the camera
* lockCamera - Locks the camera in place.
* lockSelection - Locks the selected item.
* items - List of items in the scene.
* selection - The selected item.
* onBeginDrag - An event called when the mouse begins dragging in the window.
* onEndDrag - An event that is called when the mouse stops dragging in the window.
A simple text entry box.
* multiline (False) - Set to True to enable multi line input.
* editable (True) - Set to False to disable editing.
* mask (False) - boolean indicating whether or not to mask the text (for a password field).
* isLog (False) - If True, this is treated like a log.
* onEnter - An event that is fired when enter is hit in the widget.
Toolbars are a strip of widgets which can include Toolbar Items or any other widget.
* location - The docking location (top, bottom, etc).
* position - The order for the specified docking location.
* hasGripper - Whether the toolbar has a gripper.
* hasBorder - Whether the toolbar has a border.
* dockable - Whether the toolbar can be docked.
* floatable - Whether the toolbar can be floated.
* movable - Whether the toolbar can be moved.
An item in a toolbar. They have multiple types including buttons, toggle buttons, radio buttons, spacers and separators.
* type - One of the types mentioned above.
* image - Default image to show for the toolbar.
* hoverImage - The image to show when the mouse is over the item.
* pressedImage - The image to show when the item is pressed or on.
* checked - True when a toggle/radio toolbar item is on.
* onClick - Event that is fired when the item is clicked.
Displays a tree of items which can be selected.
* root - The root object in the tree.
* selection - Set to the selected tree item.
* template - Can be used to define the hierarchy and how to display items.
* onSelect - Event that is fired when an item is selected.
* onDoubleClick - Event that is fired when an item is double clicked.
* onExpand - Event that is fired when an item is expanded.
* onCollapse - Event that is fired when an item is collapsed.
A frame that scrolls anything that is added to it if it is bigger than the space that is available.
A slider widget.
* start (0.0) - The start position on the slider.
* end (1.0) - The end position on the slider.
* value (0.0) - The current value of the slider.
A numeric input control which has up and down buttons to "spin" the number higher or lower.
* editable (True) - Set to false to disable editing the number directly.
* minimum (None) - Set to a value to restrict the minimum number.
* maximum (None) - Set to a value to restrict the maximum number.
* increment (1.0) - Defines how much the up or down button modifies the number.
* decimalPlaces (0) - Number of decimal places in the number to display.
* value - The current numeric value.
* onEnter - Event that is called when enter is hit on the control.
A frame that has a split in the middle which can be moved.
* direction (vertical) - The direction to stack widgets in.
* sashOffset (0) - The offset of where the split is.
A tab within a Tab Frame.
* onClose - Event that is called when the tab is closed.
A frame that can contain multiple tabs.
* selection - Set to the current selected tab.
A top level window. Most of the time, this will be the top of the guide xml file. This is required for wx, but optional for CEGUI and DirectGUI.
* menubar - Can be used to define a menu bar for the window.