class ApplicationState(State): """ The application state object contains all the current front-end state, including the loaded data name references, the active viewers, plugins, and layout. This state object allows for nested callbacks in mutable objects like dictionaries and makes it so incremental changes to nested values propagate to the traitlet in order to trigger a UI re-render. """ drawer = CallbackProperty(False, docstring="State of the plugins drawer.") snackbar = DictCallbackProperty( { 'show': False, 'test': "", 'color': None, 'timeout': 3000, 'loading': False }, docstring="State of the quick toast messages.") settings = DictCallbackProperty( { 'data': { 'auto_populate': False, 'parser': None }, 'visible': { 'menu_bar': True, 'toolbar': True, 'tray': True, 'tab_headers': True, }, 'context': { 'notebook': { 'max_height': '600px' } }, 'layout': {} }, docstring="Top-level application settings.") data_items = ListCallbackProperty( docstring="List of data items parsed from the Glue data collection.") tool_items = ListCallbackProperty( docstring="Collection of toolbar items displayed in the application.") tray_items = ListCallbackProperty( docstring="List of plugins displayed in the sidebar tray area.") stack_items = ListCallbackProperty( docstring="Nested collection of viewers constructed to support the " "Golden Layout viewer area.")
class ViewerState(State): """ A base class for all viewer states. """ layers = ListCallbackProperty( docstring='A collection of all layers in the viewer') @property def layers_data(self): return [layer_state.layer for layer_state in self.layers]
class Vispy3DViewerState(ViewerState): """ A common state object for all vispy 3D viewers """ x_att = SelectionCallbackProperty() x_min = CallbackProperty(0) x_max = CallbackProperty(1) x_stretch = CallbackProperty(1.) y_att = SelectionCallbackProperty(default_index=1) y_min = CallbackProperty(0) y_max = CallbackProperty(1) y_stretch = CallbackProperty(1.) z_att = SelectionCallbackProperty(default_index=2) z_min = CallbackProperty(0) z_max = CallbackProperty(1) z_stretch = CallbackProperty(1.) visible_axes = CallbackProperty(True) perspective_view = CallbackProperty(False) clip_data = CallbackProperty(True) native_aspect = CallbackProperty(False) line_width = CallbackProperty(1.) layers = ListCallbackProperty() limits_cache = CallbackProperty() def _update_priority(self, name): if name == 'layers': return 2 elif name.endswith(('_min', '_max')): return 0 else: return 1 def __init__(self, **kwargs): super(Vispy3DViewerState, self).__init__(**kwargs) if self.limits_cache is None: self.limits_cache = {} self.x_lim_helper = StateAttributeLimitsHelper(self, attribute='x_att', lower='x_min', upper='x_max', cache=self.limits_cache) self.y_lim_helper = StateAttributeLimitsHelper(self, attribute='y_att', lower='y_min', upper='y_max', cache=self.limits_cache) self.z_lim_helper = StateAttributeLimitsHelper(self, attribute='z_att', lower='z_min', upper='z_max', cache=self.limits_cache) # TODO: if limits_cache is re-assigned to a different object, we need to # update the attribute helpers. However if in future we make limits_cache # into a smart dictionary that can call callbacks when elements are # changed then we shouldn't always call this. It'd also be nice to # avoid this altogether and make it more clean. self.add_callback('limits_cache', self._update_limits_cache) def reset_limits(self): self.x_lim_helper.log = False self.x_lim_helper.percentile = 100. self.x_lim_helper.update_values(force=True) self.y_lim_helper.log = False self.y_lim_helper.percentile = 100. self.y_lim_helper.update_values(force=True) self.z_lim_helper.log = False self.z_lim_helper.percentile = 100. self.z_lim_helper.update_values(force=True) def _update_limits_cache(self, *args): self.x_lim_helper._cache = self.limits_cache self.x_lim_helper._update_attribute() self.y_lim_helper._cache = self.limits_cache self.y_lim_helper._update_attribute() self.z_lim_helper._cache = self.limits_cache self.z_lim_helper._update_attribute() @property def aspect(self): # TODO: this could be cached based on the limits, but is not urgent aspect = np.array([1, 1, 1], dtype=float) if self.native_aspect: aspect[0] = 1. aspect[1] = (self.y_max - self.y_min) / (self.x_max - self.x_min) aspect[2] = (self.z_max - self.z_min) / (self.x_max - self.x_min) aspect /= aspect.max() return aspect def reset(self): pass def flip_x(self): self.x_lim_helper.flip_limits() def flip_y(self): self.y_lim_helper.flip_limits() def flip_z(self): self.z_lim_helper.flip_limits() @property def clip_limits(self): return (self.x_min, self.x_max, self.y_min, self.y_max, self.z_min, self.z_max) def set_limits(self, x_min, x_max, y_min, y_max, z_min, z_max): with delay_callback(self, 'x_min', 'x_max', 'y_min', 'y_max', 'z_min', 'z_max'): self.x_min = x_min self.x_max = x_max self.y_min = y_min self.y_max = y_max self.z_min = z_min self.z_max = z_max
class CustomState(State): a = CallbackProperty(1) b = CallbackProperty(2) sub = ListCallbackProperty()
class WWTDataViewerState(ViewerState): mode = SelectionCallbackProperty(default_index=0) frame = SelectionCallbackProperty(default_index=0) lon_att = SelectionCallbackProperty(default_index=0) lat_att = SelectionCallbackProperty(default_index=1) alt_att = SelectionCallbackProperty(default_index=0) alt_unit = SelectionCallbackProperty(default_index=0) alt_type = SelectionCallbackProperty(default_index=0) foreground = SelectionCallbackProperty(default_index=1) foreground_opacity = CallbackProperty(1) background = SelectionCallbackProperty(default_index=8) galactic = CallbackProperty(False) layers = ListCallbackProperty() # For now we need to include this here otherwise when loading files, the # imagery layers are only available asynchronously and the session loading # fails. imagery_layers = ListCallbackProperty() def __init__(self, **kwargs): super(WWTDataViewerState, self).__init__() WWTDataViewerState.mode.set_choices(self, ['Sky'] + MODES_3D + MODES_BODIES) WWTDataViewerState.frame.set_choices(self, CELESTIAL_FRAMES) WWTDataViewerState.alt_unit.set_choices(self, [str(x) for x in ALT_UNITS]) WWTDataViewerState.alt_type.set_choices(self, ALT_TYPES) self.add_callback('imagery_layers', self._update_imagery_layers) self.lon_att_helper = ComponentIDComboHelper(self, 'lon_att', numeric=True, categorical=False, world_coord=True, pixel_coord=False) self.lat_att_helper = ComponentIDComboHelper(self, 'lat_att', numeric=True, categorical=False, world_coord=True, pixel_coord=False) self.alt_att_helper = ComponentIDComboHelper(self, 'alt_att', numeric=True, categorical=False, world_coord=True, pixel_coord=False, none='None') self.add_callback('layers', self._on_layers_changed) self._on_layers_changed() self.update_from_dict(kwargs) def _on_layers_changed(self, *args): self.lon_att_helper.set_multiple_data(self.layers_data) self.lat_att_helper.set_multiple_data(self.layers_data) self.alt_att_helper.set_multiple_data(self.layers_data) def _update_imagery_layers(self, *args): WWTDataViewerState.foreground.set_choices(self, self.imagery_layers) WWTDataViewerState.background.set_choices(self, self.imagery_layers) def _update_priority(self, name): if name == 'layers': return 2 elif name == 'imagery_layers': return 1 else: return 0
class Stub(HasCallbackProperties): prop1 = ListCallbackProperty() prop2 = ListCallbackProperty()
class TestList(HasCallbackProperties): prop = ListCallbackProperty(default=[1, 2, 3])
class SimpleTestState(State): a = CallbackProperty() b = CallbackProperty() flat = ListCallbackProperty() nested = ListCallbackProperty()