Idea behind control is to improve user interaction in application. For that purpose, idea is to write a minimum amount of code to define only part specific to your needs and let openalealab generate automatically complex widgets and user interaction like
- Graphical view to draw virtual "laboratory equipment" (virtual oscilloscope for instance)
- Table to summarize and edit all user input data (useful for user productivity)
- Drag and drop between panels, view, models, ...
- Compatibility with all frontends like OpenAleaLab, notebooks and command line
- All future features you'll benefit without rewriting code
Example of "summary table", "data editor" and "user data creator" generated automatically from "curve widget"
A control widget is a graphical element that allow user to edit, view or create Control.
A Control widget selector is an object able to return the right widget depending on context. Context depends on:
- shape and place available: small, large, vertical
- kind of use: editing, viewing, creating or painting
The widget part (control widget selector) loads and returns widget class. The plugin part (control widget selector plugin) describes contexts supported by widget selector and provides preview.
These two steps (widget / plugin) are necessary because :
- in one hand, users want to know all available widget to choose the best for their use.
- in the other hand, widgets can be complex and heavy and cannot be loaded at startup
The "plugin part", by only describing widget, can answer to user expectations without loading real class.
If your widget fits well to all contexts, the easiest way is to use the widget class as both "Control widget" and "Control widget selector". You just need to define the widget part as this widget will be used in all cases described in plugin.
from openalea.oalab.gui.control.widget import AbstractQtControlWidget
class XyzControlWidget(AbstractQtControlWidget):
def __init__(self):
AbstractQtControlWidget.__init__(self)
self.value_changed_signal = 'qt signal' # for example 'valueChanged()', 'currentTextChanged()', ...
def reset(self, value=None, **kwargs):
if value is None:
self.setValue(REAL_VALUE)
self.setC1(kwargs.get('constraint1', DEFAULT_CONSTRAINT1))
def setValue(self, value):
raise NotImplementedError
def value(self):
raise NotImplementedError
To create a valid ControlWidgetSelectorPlugin, you must fill all these attributes :
- controls: list of interface name supported. Ex: ['IInt', 'IFloat']
- name: widget name (generally widget class name)
- icon_path: path to an image (icon size) representing this widget
- preview_path: path to an image (preview size) representing this widget
- edit_shape: list of control shape supported in edit mode
- view_shape: list of control shape supported in view mode
- create_shape: list of control shape supported in create mode
- paint: says if control widget is able to paint
Class is derivated from ControlWidgetSelectorPlugin that considers that attributes that are not explicitly defined are empty (edit_shape, view_shape), null (icon_path='') or disabled (paint=False).
See also
See IBool example for real case
First example shows how to use QCheckBox to edit an IBool in all cases. Second example, a bit more complex, shows how to use all Qt sliders (QSpinBox, QSlider and QDial) to edit an IInt. This example also define a constraint widget to set min and max value for sliders.
Import used in both examples:
1 2 3 4 5 6 | from openalea.vpltk.qt import QtCore, QtGui
from openalea.deploy.shared_data import shared_data
import openalea.oalab
from openalea.oalab.plugins.control import ControlWidgetSelectorPlugin
from openalea.oalab.gui.control.widget import AbstractQtControlWidget
|
We define a widget based on QCheckBox like that:
This widget will be used for all shapes and will also be used as selector.
Now, lets define plugin that links to it: