-
Notifications
You must be signed in to change notification settings - Fork 0
Views
The ValueView
system uses the GoGi widgets to provide automatic GUI interfaces for all standard Go types.
See the giv package docs for details on all the code.
The GiEditor
for example combines a TreeView
with a StructView
to show a Ki tree on the left panel and a view of the selected struct on the right. There are also: MapView
, SliceView
and TableView
(which provides an interface for a slice of a struct, with the columns of a table as the fields of the struct, and a row for each such struct in the slice).
The dialogs.go
file defines functions that pop up a window with each of the major types of views (StructViewDialog
, SliceViewDialog
, MapViewDialog
, etc). So if you need a quick way for someone to edit one of your data elements, these can be very handy.
The ValueView
interface provides a manager that mediates between the reflect
system and specific widgets that provide a GUI interface to a particular value. For example, the StructView
iterates through its fields and gets a ValueView
type for each field, and then just calls the generic API there to create an appropriate widget etc.
Each specific type that implements the ValueView interface manages a particular type of object. To create a new custom interface for something, just create a corresponding ValueView type for that type. For example, there is an IconValueView
for the IconName
type, which shows an Action
widget whose action is to pull up the IconChooserDialog
to select an icon.
The ValueViewer
interface is a simple Stringer
-like interface that returns the appropriate ValueView
type for a given other type. You just define its ValueView()
method to return the appropriate type of ValueView
.
The ToValueView
function handles the process of finding the best value view for each type -- because you cannot define new methods on types from other packages, and you can't have cyclic dependencies between the gi and giv packages, this function handles all those cases and the basic types, but other packages that use gi/giv can just use the ValueViewer interface. The FieldToValueView
is a special front-end pass on ToValueView for struct fields.
See Tags for tags that can be added to fields in struct
s to affect view display.
There is also support for automatically creating an interface to the methods on a type, by defining a set of ki.Props
properties associated with the type (used for all Style settings in GoGi), through the kit
package AddType
type registration mechanism. The top-level properties actually require a ki.PropSlice
which maintains the order of the elements -- ki.Props
is a map
which does not maintain order.
You can also use this system to directly call a method using the giv.CallMethod
function, and it will automatically provide the full GUI support for user-entry of the args to that method. This is very useful for arbitrary code-initiated method calling when the gui is needed for filling in args (e.g., if a method takes a gi.FileName, calling it via giv.CallMethod will automatically pull up the FileViewDialog
and set the arg from the results).
Four top-level property names are recognized:
-
"ToolBar": ki.PropSlice {...}
--- defines a toolbar, which will be shown above the the content of that type in all standard views. This should contain a select subset of the most important methods, each of which is defined by a sub-property listing within this overall property, as described below. -
"MainMenu": ki.PropSlice {...}
-- defines a main menu. This will be shown in dialogs where the entire window is devoted to that type of element (e.g., aStructViewDialog
showing aStructView
). This can contain less-frequently-used methods, in addition to menu versions of methods available in the toolbar. The immediate sub-properties here should be the separate menu entries in theMenuBar
, and then within those the method properties as described below. -
"CtxtMenu*": ki.PropSlice {...}
-- defines a context menu. Forgi
GUI types (e.g.,Widgets
), this will be shown whenever someone right-clicks on that element, assuming the right mouse button release is calls theContextMenu()
method (e.g.,WidgetMouseEvents
does this). For other types, theTableView
will call the context menu on rows, if the widget does not steal the event. e.g.,FileView
calls the context menu onFileInfo
elements.TreeView
also attempts to create a context menu on the objects it is viewing. The immediate sub-properties here are the actions in the menu. You can create different menus for active vs. inactive gui views, usingCtxtMenuActive
orCtxtMenuInactive
properties -- the plainCtxtMenu
will be used by default if these special cases are not present. -
"CallMethods": ki.PropSlice {...}
-- any method that is not otherwise configured on any of the above lists can be added here for use via thegiv.CallMethod
function. CallMethod creates a cache of all registered methods and actually looks in CallMethods first, so you can also override the behavior of a method when called via CallMethod as compared to the main menu or toolbar, etc.
Each method should be entered with the property name that is the exact name of the method -- this is what will be looked up in the type to find the method to call. It should be of type ki.Props
and have any appropriate sub-properties as defined below. E.g.:
"ToolBar": ki.PropSlice{
{"Update", ki.Props{
"icon": "update",
}},
{"sep-file", ki.BlankProp{}},
{"Save", ki.Props{
"icon": "file-save",
}},
{"sep-color", ki.BlankProp{}},
{"Colors", ki.PropSlice{ // sub-menu
{"LoadColors", ki.Props{
"label": "Open Colors",
"icon": "file-open",
"Args": ki.PropSlice{
{"Color File Name", ki.Props{
"default-field": "ColorFilename",
"ext": ".json",
}},
},
}},
{"SaveColors", ki.Props{
"icon": "file-save",
"Args": ki.PropSlice{
{"Color File Name", ki.Props{
"default-field": "ColorFilename",
"ext": ".json",
}},
},
}},
}},
...
-
label: string
-- provides an alternative label instead of the method name. Note that CamelCase names will be rendered with space separation by default, so a label is not needed for that, and depending on the application, it may be beneficial to keep the GUI method names the same as the code, so that they can be more easily remembered and used in programs. -
shortcut: string or gi.KeyFuns
-- defines a key chord shortcut -- generally put shortcuts in menus, not toolbars. Don't put in both places. In context menus it can display shortcuts that are in effect to inform the user, but does not establish new shortcuts -- passing agi.KeyFuns
(e.g.,gi.KeyFunCopy
for a "Copy" method) will automatically show (one of the) key commands that activates that key function. -
keyfun: gi.KeyFun..
-- defines an action that just activates that given key function -- e.g., for Copy, Cut etc -- automatically defines the shortcut appropriately as the one for that keyfun. -
icon: string
-- name of icon for action -- generally put icons in toolbars, not menus. -
desc: string
-- for ToolBar tooltips, and when a prompt dialog is needed to fill in the argument values for a method, or a confirmation dialog is requested, this description provides info to the user about what the method will do. The description given in the source code, shown in goDoc, is not available inreflect
, so you'll have to provide this separately here. Probably you want end-users to see something different from the programmer-level comment anyway :) Full HTML styling is, as always, supported. -
confirm: bool
-- for methods with no arguments, pop up an Ok / Cancel dialog to confirm the execution of this method (in general using Undo vs. confirm is preferred, except for truly irreversible actions). -
show-return: bool
-- the return value(s) of the method will be shown in a dialog after it runs. -
submenu: field or slice
-- for methods that have a single argument, this presents user with a sub-menu with the list of options from the given slice literal or field name on object that contains a slice. -
submenu-func: giv.SubMenuFunc
-- a function that takes aninterface{}
and*gi.Viewport2D
and returns[]string
slice of options for the submenu. called right when the user clicks on the menu item to create the menu ("jit"). -
no-update-after: bool
-- do not automatically update the window after running the method -- by default it updates the window, but if the method itself does things to update the display, then this may need to be set to prevent conflicting updates (bool is ignored).- You can also specify a top-level type property of:
"MethViewNoUpdateAfter": true
(value is ignored) to set this option generically for all methods on a given type, if it should never have it. In which case theupdate-after
property can be set per method to override that default.
- You can also specify a top-level type property of:
-
updtfunc: func(iv interface{}, act *gi.Action)
-- defines an update function (typically specified right there) that can update the active / inactive status of the action. Theinterface{}
should be converted to the type of the element on which the type properties are defined. Important: useSet[In]ActiveStateUpdt
method in toolbars, but NOT in menus, which require the plainSet[In]ActiveState
version. For example, here's one from TreeView context menu:
"updtfunc": func(tvi interface{}, act *gi.Action) {
tv := tvi.(*TreeView)
act.SetInactiveState(tv.IsRootOrField(""))
},
-
Args: ki.PropSlice{...}
-- provides names and other properties for each of the arguments -- arg names are not stored in thereflect
system and must be provided here, along with any other (optional) special properties for each arg. A dialog will pop up to prompt for all the argument values, and only if the user hits Ok will the method run with those values.- Important special case: if a method has 1 arg, and the
ValueView
for that arg has an "action" associated with it (e.g., choosing item from list, opening an edit dialog for that type, or agi.FileName
from FileView), then that action is performed directly instead of opening the arg dialog. For example, a method taking a singlegi.FileName
arg (which has an associated specialFileValueView
type that opens theFileViewDialog
to choose a filename) will directly open the dialog, which is the natural and immediate behavior one would expect. If your method has more than one method along with the filename, then the user can just click on the button to get the fileview dialog within the arg dialog that comes up, along with filling in the other args values. The bottom line is that if you need any kind of special gui selection tool etc for an arg, you should give it a special type (if it doesn't already have it) and then associate a ValueView with that, and copy the template from e.g.,FileValueView
ingiv/filevalueview.go
for supporting your type. It is very straightforward.
- Important special case: if a method has 1 arg, and the
Here is an example specifying arg properties:
{"StdKeyMap", ki.Props{
"desc": "sets StdKeyMapName to selected standard keymap and installs it as the current custom keymap, as a starting point for further customization.",
"Args": ki.PropSlice{
{"Map Name", ki.Props{
"default-field": "StdKeyMapName",
}},
}},
},
The name of the arg property provides the label to show for the argument when it is prompted.
-
default: value
-- provides a default initial value for the argument -- value is aninterface{}
-- could be anything that is assignable directly to the arg, using thekit.SetRobust
method, which does a pretty good job of assigning anything to anything that is reasonable. -
default-field: string
-- name of field on struct val (the one with the method being called) that contains the value to use for default arg value. -
value: value
-- directly sets the value for this argument to the given value -- user is not prompted for this value, and if all such args are set, the method is run directly with these args (except if confirm flag is set). -
desc: string
-- provides a tooltip description of the argument that will show up when the user mouses over it -- good place to add arg-specific tips and help. - any other properties will be set as tag values for the value view for that arg, supporting all the Tags for special types, including, e.g.:
-
ext: string
-- forgi.FileName
type arg -- specifies the extension for the FileViewDialog -- if multiple, comma separated
-