class VideoView(SurfaceView): """VideoView displays a video file""" #: Source of the video file or URI src = d_(Str()) #: Player actions control = d_(Enum("play", "stop", "pause")) #: State state = d_( Enum("idle", "stopped", "paused", "loading", "complete", "playing", "error"), writable=False, ) #: Error event error = d_(Event(dict), writable=False) #: Info event, such as buffering info = d_(Event(dict), writable=False) #: A reference to the ProxyViewGroup object. proxy = Typed(ProxyVideoView) @observe("src", "control") def _update_proxy(self, change): super()._update_proxy(change) def seek_to(self, ms: int): """Seek to the given time.""" proxy = self.proxy assert proxy is not None proxy.seek_to(ms)
class KeyEvent(Control): #: Proxy reference proxy = Typed(ProxyKeyEvent) #: List of keys that or codes to filter #: Can be a key letter or code and including modifiers #: Ex. Ctrl + r, up, esc, etc.. #: If empty will fire for any key combination keys = d_(List(str)) #: Listen for events enabled = d_(Bool(True)) #: Fire multiple times when the key is held repeats = d_(Bool(True)) #: Pressed event pressed = d_(Event(dict), writable=False) #: Released event released = d_(Event(dict), writable=False) @observe("enabled", "keys") def _update_proxy(self, change): """An observer which sends state change to the proxy.""" super(KeyEvent, self)._update_proxy(change)
class ActionMenuView(LinearLayout): """ A simple control for displaying a ActionMenuView. """ #: Reference to the checked radio button or None overflow_icon = d_(Unicode()) #: Show menu show = d_(Event()) #: Hide menu hide = d_(Event()) #: TODO: Should this be more like a Picker/Combo where you pass options #: A reference to the ProxyLabel object. proxy = Typed(ProxyActionMenuView) # ------------------------------------------------------------------------- # Observers # ------------------------------------------------------------------------- @observe('show', 'hide', 'overflow_icon') def _update_proxy(self, change): """ An observer which sends the state change to the proxy. """ if change['type'] == 'event' and self.proxy_is_active: self.proxy.set_opened(change['name'] == 'show') else: super(ActionMenuView, self)._update_proxy(change)
class VideoView(SurfaceView): """ VideoView displays a video file """ #: Source of the video file or URI src = d_(Unicode()) #: Player actions control = d_(Enum('play', 'stop', 'pause')) #: State state = d_(Enum('idle', 'stopped', 'paused', 'loading', 'complete', 'playing', 'error'), writable=False) #: Error event error = d_(Event(dict), writable=False) #: Info event, such as buffering info = d_(Event(dict), writable=False) #: A reference to the ProxyViewGroup object. proxy = Typed(ProxyVideoView) @observe('src', 'src', 'control') def _update_proxy(self, change): super(VideoView, self)._update_proxy(change) def seek_to(self, ms): """ Seek to the given time. """ self.proxy.seek_to(ms)
class ActionMenuView(LinearLayout): """A simple control for displaying a ActionMenuView.""" #: Reference to the checked radio button or None overflow_icon = d_(Str()) #: Show menu show = d_(Event()) #: Hide menu hide = d_(Event()) #: TODO: Should this be more like a Picker/Combo where you pass options #: A reference to the ProxyLabel object. proxy = Typed(ProxyActionMenuView) # ------------------------------------------------------------------------- # Observers # ------------------------------------------------------------------------- @observe("show", "hide", "overflow_icon") def _update_proxy(self, change): if change["type"] == "event" and self.proxy_is_active: self.proxy.set_opened(change["name"] == "show") else: super()._update_proxy(change)
class ScrollView(FrameLayout): """ A simple control for displaying a ScrollView. """ #: Vertical or horizontal scrollview orientation = d_(Enum('vertical', 'horizontal')) #: Scroll to position (x, y), 'top', or 'bottom scroll_to = d_(Event(object)) #: Scroll to by delta (x, y) scroll_by = d_(Event(tuple)) #: A reference to the ProxyScrollView object. proxy = Typed(ProxyScrollView) # ------------------------------------------------------------------------- # Observers # ------------------------------------------------------------------------- @observe('orientation', 'scroll_to', 'scroll_by') def _update_proxy(self, change): """ An observer which sends the state change to the proxy. """ if change['type'] in ['event', 'update'] and self.proxy_is_active: handler = getattr(self.proxy, 'set_' + change['name'], None) if handler is not None: handler(change['value'])
class AbstractWidgetItemGroup(Control): #: Triggered when clicked clicked = d_(Event(), writable=False) #: Triggered when double clicked double_clicked = d_(Event(), writable=False) #: Triggered when the row, column, or item is entered entered = d_(Event(), writable=False) #: Triggered when the row, column, or item is pressed pressed = d_(Event(), writable=False) #: Triggered when the row, column, or item's selection changes selection_changed = d_(Event(bool), writable=False) def _get_items(self): return [c for c in self.children if isinstance(c, AbstractWidgetItem)] #: Internal item reference _items = Property(lambda self: self._get_items(), cached=True) def child_added(self, child): """ Reset the item cache when a child is added """ super(AbstractWidgetItemGroup, self).child_added(child) self.get_member('_items').reset(self) def child_removed(self, child): """ Reset the item cache when a child is removed """ super(AbstractWidgetItemGroup, self).child_removed(child) self.get_member('_items').reset(self)
class ExecutableGraph(model.Graph): controller = ForwardInstance(_import_graph_calculator_controller) nxgraph = Property(lambda self: self._get_nxgraph(), cached=True) topologyChanged = Event() valuesChanged = Event() attributesChanged = Event() def _get_nxgraph(self): g = nx.MultiDiGraph() for node in self.nodes: g.add_node(node.id, id=node.id, name=node.name) for edge in self.edges: g.add_edge(edge.start_socket.node.id, edge.end_socket.node.id, id=edge.id, source_socket=edge.start_socket.name, target_socket=edge.end_socket.name) return g def _observe_topologyChanged(self, change): self.get_member('nxgraph').reset(self) self.execute_graph() def _observe_valuesChanged(self, change): self.execute_graph() def _observe_attributesChanged(self, change): self.execute_graph() def execute_graph(self): for node_id in nx.topological_sort(self.nxgraph): self.node_dict[node_id].update()
class Snackbar(ToolkitObject): """A toast is a view containing a quick little message for the user.""" #: Text to display #: if this node has a child view this is ignored text = d_(Str()) #: Text to display in the action button action_text = d_(Str()) #: Color for the action text button action_text_color = d_(Str()) #: Duration to display in ms or 0 for infinite duration = d_(Int(3000)) #: Alias for the action is clicked clicked = d_(Event(), writable=False) #: When an action occurs such as swiped out, clicked, timed out, etc.. action = d_(Event(str), writable=False) #: Show the snackbar for the given duration show = d_(Bool()) #: A reference to the proxy object. proxy = Typed(ProxySnackbar) # ------------------------------------------------------------------------- # Observers # ------------------------------------------------------------------------- @observe("text", "duration", "action_text", "action_text_color", "show") def _update_proxy(self, change): super()._update_proxy(change)
class ScrollView(FrameLayout): """A simple control for displaying a ScrollView.""" #: Vertical or horizontal scrollview orientation = d_(Enum("vertical", "horizontal")) #: Scroll to position (x, y), 'top', or 'bottom scroll_to = d_(Event(object)) #: Scroll to by delta (x, y) scroll_by = d_(Event(tuple)) #: Set which scrollbars are enabled scrollbars = d_(Enum("both", "vertical", "horizontal", "none")) #: A reference to the ProxyScrollView object. proxy = Typed(ProxyScrollView) # ------------------------------------------------------------------------- # Observers # ------------------------------------------------------------------------- @observe("orientation", "scroll_to", "scroll_by", "scrollbars") def _update_proxy(self, change): if change["type"] in ["event", "update"] and self.proxy_is_active: handler = getattr(self.proxy, f"set_{change['name']}", None) if handler is not None: handler(change["value"])
class XYDataObject(DataObjectBase): #might be up for a refactoring of the name if theres also going to be 2d data objects (XYDataObject, ListObject?) """ has x and y array""" label = Str('') x = Typed(np.ndarray) y = Typed(np.ndarray) x_updated = Event(kind=bool) y_updated = Event(kind=bool) from atomicplot.fit import Fit1D from atomicplot.plot import Plot1D fit = Typed(Fit1D) plot = Typed(Plot1D) file_path = Str # Optional file path pointing to original data file def __init__(self, x, y, *args, **kwargs): if not isinstance(x, (np.ndarray, list)): raise TypeError("xdata needs to be list or numpy array") if not isinstance(y, (np.ndarray, list)): raise TypeError("ydata needs to be list or numpy array") if isinstance(x, np.ndarray): if not len(x) == x.size: raise ValueError("xdata is not an one-dimensional array") if isinstance(y, np.ndarray): if not len(y) == y.size: raise ValueError("ydata is not an one-dimensional array") if not len(x) == len(y): raise ValueError("xdata, ydata have unequal length; found {}, {}".format(len(x), len(y))) self.x = UpdateArray(x, self.x_updated) self.y = UpdateArray(y, self.y_updated) self.fit = Fit1D(self) self.plot = Plot1D(self) super(XYDataObject, self).__init__(*args, **kwargs) @observe('x_updated') def testfunc(self, new): print('x updated in dataobject') @observe('y_updated') def testfunc(self, new): print('y updated in dataobject') @observe('y') def tf1(self, new): print('fully y updated') def savetxt(self, file_path, **kwargs): pass #todo implement this def reset(self): """restores x, y with data which it was initialized""" raise NotImplementedError()
class AbstractWidgetItem(AbstractWidgetItemGroup): """ Item to be shared between table views and tree views """ #: Model index or row within the view row = d_(Int(), writable=False) #: Column within the view column = d_(Int(), writable=False) #: Text to display within the cell text = d_(Unicode()) #: Text alignment within the cell text_alignment = d_( Enum(*[(h, v) for h in ('left', 'right', 'center', 'justify') for v in ('center', 'top', 'bottom')])) #: Icon to display in the cell icon = d_(Typed(Icon)) #: The size to use for the icon. The default is an invalid size #: and indicates that an appropriate default should be used. icon_size = d_(Coerced(Size, (-1, -1))) #: Whether the item or group can be selected selectable = d_(Bool(True)) #: Selection state of the item or group selected = d_(Bool()) #: Whether the item or group can be checked checkable = d_(Bool()) #: Checked state of the item or group checked = d_(Bool()) #: Whether the item or group can be edited editable = d_(Bool()) #: Triggered when the item's contents change changed = d_(Event(), writable=False) #: Triggered when the checkbox state changes toggled = d_(Event(bool), writable=False) @observe('row', 'column', 'text', 'text_alignment', 'icon', 'icon_size', 'selectable', 'selected', 'checkable', 'checked', 'editable') def _update_proxy(self, change): """ An observer which sends state change to the proxy. """ if change['name'] in ['row', 'column']: super(AbstractWidgetItem, self)._update_proxy(change) else: self.proxy.data_changed(change)
class AppState(Atom): context = Dict() extensions = Typed(WorkspaceExtensionManager) current_workspace = Value() args = Value() options = Value() syslog = Typed(Syslog) workspace_started = Event() workspace_stopped = Event()
class BarcodeView(ViewGroup): """ Camera preview. Note: This should not be used directly! """ #: Camera is active active = d_(Bool(True)) #: Flashlight enabled light = d_(Bool()) #: Scanning is active scanning = d_(Bool(False)) #: Trigger a scan mode = d_(Enum('single', 'continuous'), readable=False) #: Scan result scanned = d_(Event(dict), writable=False) #: Reference to the proxy implementation proxy = Typed(ProxyBarcodeView) @observe('light', 'active', 'mode', 'scanning') def _update_proxy(self, change): """ Update the proxy """ #: The superclass implementation is sufficient super(BarcodeView, self)._update_proxy(change)
def _create_user_storage(self): stack = [self._root] while stack: node = stack.pop() klass = node.typeclass members = klass.members() for storage in node.storage_defs: m = members.get(storage.name) if m is not None: if m.metadata is None or not m.metadata.get('d_member'): msg = "cannot override non-declarative member '%s'" msg = msg % storage.name self._raise_error(DeclarativeError, msg, storage) if m.metadata.get('d_final'): msg = "cannot override the final member '%s'" msg = msg % storage.name self._raise_error(DeclarativeError, msg, storage) if storage.kind == 'event': event = Event(storage.typeclass) new = d_(event, writable=False, final=False) else: attr = Instance(storage.typeclass) new = d_(attr, final=False) if m is not None: new.set_index(m.index) new.copy_static_observers(m) else: new.set_index(len(members)) new.set_name(storage.name) members[storage.name] = new setattr(klass, storage.name, new) stack.extend(node.child_defs)
class EventSignalTest(Atom): e = Event() s = Signal() counter = Int()
class Label(Control): """ A simple control for displaying read-only text. """ #: The unicode text for the label. text = d_(Unicode()) #: The horizontal alignment of the text in the widget area. align = d_(Enum('left', 'right', 'center', 'justify')) #: The vertical alignment of the text in the widget area. vertical_align = d_(Enum('center', 'top', 'bottom')) #: An event emitted when the user clicks a link in the label. #: The payload will be the link that was clicked. link_activated = d_(Event(), writable=False) #: Labels hug their width weakly by default. hug_width = set_default('weak') #: A reference to the ProxyLabel object. proxy = Typed(ProxyLabel) #-------------------------------------------------------------------------- # Observers #-------------------------------------------------------------------------- @observe('text', 'align', 'vertical_align') def _update_proxy(self, change): """ An observer which sends the state change to the proxy. """ # The superclass implementation is sufficient. super(Label, self)._update_proxy(change)
class ContextGroup(PSIContribution): ''' Used to group together context items in a single dock item pane. ''' #: Are the parameters in this group visible? visible = d_(Bool(True)) updated = d_(Event())
class ContextItem(Declarative): ''' Defines the core elements of a context item. These items are made available to the context namespace. ''' #: Must be a valid Python identifier. Used by eval() in expressions. name = d_(Str()) #: Long-format label for display in the GUI. Include units were applicable. label = d_(Str()) # Datatype of the value. Required for properly initializing some data # plugins (e.g., those that save data to a HDF5 file). dtype = d_(Str()) #: Name of the group to display the item under. This should never be #: overwitten even if we remove the item from the group (e.g., when #: loading/unloading plugin tokens). group_name = d_(Str()) # Compact label where there is less space in the GUI (e.g., under a column # heading for example). compact_label = d_(Str()) # Is this visible via the standard configuration menus? visible = d_(Bool(True)) # Can this be configured by the user? This will typically be False if the # experiment configuration has contributed an Expression that assigns the # value of this parameter. editable = Bool(True) updated = Event() def _default_label(self): return self.name.capitalize().replace('_', ' ') def _default_compact_label(self): return self.label def coerce_to_type(self, value): coerce_function = np.dtype(self.dtype).type value = coerce_function(value) return value.item() def __repr__(self): return f'<{self.__class__.__name__}: {self}>' def __str__(self): if isinstance(self.parent, ContextGroup): l = f'{self.name} in {self.parent.name}' elif self.group_name: l = f'{self.name} in {self.group_name}' else: l = f'{self.name}' if not self.visible: l = f'{l} (not visible)' if not self.editable: l = f'{l} (not editable)' return l
class TestClass(Atom): arr = Typed(np.ndarray) val = Value(default=np.arange(10)) number = Int(default=10) x_arr = Typed(np.ndarray) x_arr_updated = Event(kind=bool) def __init__(self, x, *args, **kwargs): super(TestClass, self).__init__(*args, **kwargs) # print(id(self.x_arr_updated)) print(self.number) print(self.x_arr_updated) self.x_arr = Arr(x, self.x_arr_updated) @observe('x_arr') def _x_arr_changed(self, new): print('xarr') @observe('x_arr_updated') def _xarr_setitem(self, new): print('setitem') @observe('number') def _number_changed(self, new_value): print(new_value) print('number') @observe('arr') def _arr_changed(self, new_value): print(new_value) print(type(new_value)) print('arr')
class BaseSelector(SimpleState, Declarative): context_info = Typed(dict, {}) parameters = ContainerList() updated = Event() def append_parameter(self, parameter): self.insert_parameter(len(self.parameters), parameter) self.updated = True def remove_parameter(self, parameter): self.parameters.remove(parameter) self.updated = True def insert_parameter(self, index, parameter): self.parameters.insert(index, parameter) self.updated = True def find_parameter(self, name): for p in self.parameters: if p.name == name: return p def move_parameter(self, parameter, after=None): if parameter == after: return self.parameters.remove(parameter) if after is None: index = 0 else: index = self.parameters.index(after) + 1 self.parameters.insert(index, parameter) self.updated = True
class Html(Tag): #: Dom modified event. This will fire when any child node is updated, added #: or removed. Observe this event to handle updating websockets. modified = d_(Event(dict), writable=False).tag(attr=False) def _default_tag(self): return 'html'
class AbstractButton(Control): """ A base class for creating button-like controls. """ #: The text to use as the button's label. text = d_(Unicode()) #: The source url for the icon to use for the button. icon = d_(Typed(Icon)) #: The size to use for the icon. The default is an invalid size #: and indicates that an appropriate default should be used. icon_size = d_(Coerced(Size, (-1, -1))) #: Whether or not the button is checkable. The default is False. checkable = d_(Bool(False)) #: Whether a checkable button is currently checked. checked = d_(Bool(False)) #: Fired when the button is pressed then released. The payload will #: be the current checked state. This event is triggered by the #: proxy object when the button is clicked. clicked = d_(Event(bool), writable=False) #: Fired when a checkable button is toggled. The payload will be #: the current checked state. This event is triggered by the #: proxy object when a togglable button is toggled. toggled = d_(Event(bool), writable=False) #: Buttons hug their contents' width weakly by default. hug_width = set_default('weak') #: A reference to the ProxyAbstractButton object. proxy = Typed(ProxyAbstractButton) #-------------------------------------------------------------------------- # Observers #-------------------------------------------------------------------------- @observe('text', 'icon', 'icon_size', 'checkable', 'checked') def _update_proxy(self, change): """ An observer which updates the proxy widget. """ # The superclass implementation is sufficient. super(AbstractButton, self)._update_proxy(change)
class NameTest(Atom): v = Value() l = List(Int()) d = Dict(Int(), Int()) e = Event(Int())
class ListItem(ToolkitObject): """ A holder for a View within a ListItem. """ #: The item this view should render item = d_(Value(), writable=False) #: The position of this item within the ListView index = d_(Int(), writable=False) #: Triggered when this item is clicked clicked = d_(Event()) #: Triggered when this item is long clicked long_clicked = d_(Event()) #: A reference to the ProxyLabel object. proxy = Typed(ProxyListItem)
class IndexTest(Atom): v1 = Value() v2 = Value() l = List(Int()) d = Dict(Int(), Int()) e = Event(Int())
class BaseSelector(PSIContribution): context_items = Typed(list, []) symbols = Typed(dict, {}) updated = Event() #: Since order of context items is important for certain selectors (e.g., #: the CartesianProduct), this attribute is used to persist experiment #: settings when saving/loading from a file. context_item_order = Property().tag(preference=True) def _get_context_item_order(self): return [i.name for i in self.context_items] def _set_context_item_order(self, order): old_items = self.context_items[:] new_items = [] for name in order: for item in old_items[:]: if item.name == name: new_items.append(item) old_items.remove(item) # Be sure to tack on any old items that were not saved to the ordering # in the preferences file. new_items.extend(old_items) self.context_items = new_items def append_item(self, item): ''' Add context item to selector Parameters ---------- item : ContextItem Item to add to selector ''' context_items = self.context_items[:] context_items.append(item) self.context_items = context_items self.updated = True def remove_item(self, item): ''' Remove context item from selector Parameters ---------- item : ContextItem Item to remove from selector ''' context_items = self.context_items[:] context_items.remove(item) self.context_items = context_items self.updated = True
class Timer(ToolkitObject): """ An object which represents a toolkit independent timer. """ #: The interval of the timer, in milliseconds. The default is 0 and #: indicates that the timer will fire as soon as the event queue is #: emptied of all pending events. interval = d_(Int(0)) #: Whether the timer fires only once, or repeatedly until stopped. single_shot = d_(Bool(False)) #: An event fired when the timer times out. timeout = d_(Event(), writable=False) #: A reference to the ProxyTimer object. proxy = Typed(ProxyTimer) #-------------------------------------------------------------------------- # Observers #-------------------------------------------------------------------------- @observe('single_shot', 'interval') def _update_proxy(self, change): """ An observer which updates the proxy when the state changes. """ # The superclass implementation is sufficient. super(Timer, self)._update_proxy(change) def start(self): """ Start or restart the timer. If the timer is already started, it will be stopped and restarted. """ if self.proxy_is_active: self.proxy.start() def stop(self): """ Stop the timer. If the timer is already stopped, this is a no-op. """ if self.proxy_is_active: self.proxy.stop() def is_active(self): """ Returns True if the timer is running, False otherwise. """ if self.proxy_is_active: return self.proxy.is_running() return False
class NameTest(Atom): v = Value() t = Tuple(Int()) li = List(Int()) d = Dict(Int(), Int()) e = Event(Int())
def add_storage(node, name, store_type, kind): """ Add user storage to a Declarative subclass. Parameters ---------- node : DeclarativeNode The declarative node to which storage should be added. name : str The name of the attribute or event to add to the class. store_type : type or None The type of values to allow on the attribute. kind : 'attr' or 'event' The kind of storage to add to the class. """ if store_type is None: store_type = object elif not isinstance(store_type, type): raise TypeError("%s is not a type" % store_type) klass = node.klass members = klass.members() member = members.get(name) if member is not None: if member.metadata is None or not member.metadata.get('d_member'): msg = "can't override non-declarative member '%s.%s'" raise TypeError(msg % (klass.__name__, name)) if member.metadata.get('d_final'): msg = "can't override final member '%s.%s'" raise TypeError(msg % (klass.__name__, name)) elif hasattr(klass, name): _override_fail(klass, name) if kind == 'event': new = d_(Event(store_type), writable=False, final=False) elif kind == 'attr': new = d_(Instance(store_type), final=False) else: raise RuntimeError("invalid kind '%s'" % kind) if member is not None: new.set_index(member.index) new.copy_static_observers(member) else: new.set_index(len(members)) new.set_name(name) patch_d_member(new) members[name] = new setattr(klass, name, new)