def visit_value(value_path, value): if isinstance(value, dict): is_expanded = self.__is_expanded(value_path) format_str = "{} {{{}}}" text_item = CanvasItem.StaticTextCanvasItem( format_str.format(value_path[-1], len(value))) text_item.font = text_font text_item.size_to_content(get_font_metrics_fn) items.append((text_item, "parent", is_expanded, value_path)) if is_expanded: visit_dict(value, value_path) elif isinstance(value, list) or isinstance(value, tuple): is_expanded = self.__is_expanded(value_path) format_str = "{} ({})" text_item = CanvasItem.StaticTextCanvasItem( format_str.format(value_path[-1], len(value))) text_item.font = text_font text_item.size_to_content(get_font_metrics_fn) items.append((text_item, "parent", is_expanded, value_path)) if is_expanded: visit_list(value, value_path) else: text_item = CanvasItem.StaticTextCanvasItem("{}: {}".format( value_path[-1], value)) text_item.font = text_font text_item.size_to_content(get_font_metrics_fn) items.append((text_item, "child", None, value_path))
def __init__(self, cursor_changed_fn: typing.Callable[[float], None]): super().__init__() # tell the canvas item that we want mouse events. self.wants_mouse_events = True # create the component canvas items: adornments and the graph. self.__adornments_canvas_item = AdornmentsCanvasItem() self.__simple_line_graph_canvas_item = SimpleLineGraphCanvasItem() self.__histogram_color_map_canvas_item = ColorMapCanvasItem() # canvas items get added back to front column = CanvasItem.CanvasItemComposition() column.layout = CanvasItem.CanvasItemColumnLayout() graph_and_adornments = CanvasItem.CanvasItemComposition() graph_and_adornments.add_canvas_item( self.__simple_line_graph_canvas_item) graph_and_adornments.add_canvas_item(self.__adornments_canvas_item) column.add_canvas_item(graph_and_adornments) column.add_canvas_item(self.__histogram_color_map_canvas_item) self.add_canvas_item(column) # used for mouse tracking. self.__pressed = False self.on_set_display_limits = None self.__cursor_changed = cursor_changed_fn
def start_mouse_tracker( ui, event_loop: asyncio.AbstractEventLoop, canvas_item: CanvasItem.AbstractCanvasItem, mouse_position_changed_by_fn: typing.Callable[[Geometry.IntPoint], None], global_pos: Geometry.IntPoint, size: Geometry.IntSize): tracking_canvas_item = TrackingCanvasItem() tracking_canvas_item.on_mouse_position_changed_by = mouse_position_changed_by_fn tracking_canvas_item.add_canvas_item(canvas_item) async def close_window(document_window): document_window.request_close() def handle_close(document_window): tracking_canvas_item.release_mouse() event_loop.create_task(close_window(document_window)) def activation_changed(document_window, activated): if not activated: handle_close(document_window) # create the popup window document_window = ui.create_document_window() document_window.window_style = "mousegrab" document_window.on_activation_changed = functools.partial( activation_changed, document_window) tracking_canvas_item.on_close = functools.partial(handle_close, document_window) # configure canvas widget, attach to document window mousegrab_window_pos = global_pos - Geometry.IntPoint(x=size.width, y=size.height / 2) document_window.show(size=size, position=mousegrab_window_pos) if sys.platform == "win32": relative_pos = Geometry.IntPoint() else: relative_pos = mousegrab_window_pos document_window.fill_screen() canvas_widget = ui.create_canvas_widget() tracking_canvas_item.sizing.set_fixed_size(size) content_row_canvas_item = CanvasItem.CanvasItemComposition() content_row_canvas_item.layout = CanvasItem.CanvasItemRowLayout() content_row_canvas_item.add_spacing(relative_pos.x) content_row_canvas_item.add_canvas_item(tracking_canvas_item) content_row_canvas_item.add_stretch() content_canvas_item = CanvasItem.CanvasItemComposition() content_canvas_item.layout = CanvasItem.CanvasItemColumnLayout() content_canvas_item.add_spacing(relative_pos.y) content_canvas_item.add_canvas_item(content_row_canvas_item) content_canvas_item.add_stretch() canvas_widget.canvas_item.add_canvas_item(content_canvas_item) document_window.attach(canvas_widget) tracking_canvas_item.request_focus() tracking_canvas_item.cursor_shape = "blank" canvas_widget.set_cursor_shape("blank") tracking_canvas_item.grab_mouse(relative_pos.x + size.width // 2, relative_pos.y + size.height // 2)
def __init__(self, document_controller: DocumentController.DocumentController, panel_id: str, properties: Persistence.PersistentDictType) -> None: super().__init__(document_controller, panel_id, _("Toolbar")) self.__component_registered_listener = Registry.listen_component_registered_event(self.__component_registered) self.widget = self.ui.create_column_widget() # note: "maximum" here means the size hint is maximum and the widget can be smaller. Qt layout is atrocious. self.__toolbar_widget_row = self.ui.create_row_widget(properties={"size-policy-horizontal": "maximum"}) toolbar_row_widget = self.ui.create_row_widget() toolbar_row_widget.add(self.__toolbar_widget_row) toolbar_row_widget.add_stretch() self.widget.add(toolbar_row_widget) # make a map from widget_id to widget factory. widget_factories = dict() for component in Registry.get_components_by_type("toolbar-widget"): widget_factories[component.toolbar_widget_id] = component # define the order of widgets. # this part is hard coded for now; needs some work to make it dynamically order widgets as they become # available from packages. widget_id_list = [ "nion.swift.toolbar-widget.tool-mode", "nion.swift.toolbar-widget.raster-zoom", "nion.swift.toolbar-widget.workspace" ] # add the widgets. for widget_id in widget_id_list: widget_factory = widget_factories[widget_id] widget_handler = widget_factory(document_controller=self.document_controller) widget = Declarative.DeclarativeWidget(self.ui, self.document_controller.event_loop, widget_handler) widget_section = self.ui.create_row_widget() widget_section.add(widget) section_bar = self.ui.create_canvas_widget(properties={"width": 9, "size_policy_vertical": "expanding"}) def draw(drawing_context: DrawingContext.DrawingContext, canvas_size: Geometry.IntSize, *args: typing.Any, **kwargs: typing.Any) -> None: with drawing_context.saver(): drawing_context.rect(0, 0, canvas_size.width, canvas_size.height) drawing_context.fill_style = "#DDD" drawing_context.stroke_style = "#AAA" drawing_context.fill() drawing_context.stroke() section_bar.canvas_item.add_canvas_item(CanvasItem.DrawCanvasItem(draw)) self.__toolbar_widget_row.add(section_bar) self.__toolbar_widget_row.add_spacing(8) self.__toolbar_widget_row.add(widget_section) self.__toolbar_widget_row.add_spacing(8) end_divider = self.ui.create_canvas_widget(properties={"width": 1, "size_policy_vertical": "expanding"}) end_divider.canvas_item.add_canvas_item(CanvasItem.DividerCanvasItem(color="#888")) self.__toolbar_widget_row.add(end_divider)
def __init__(self, ui_settings: UISettings.UISettings, delegate, event_loop, draw_background: bool = True): super().__init__() self.__ui_settings = ui_settings self.delegate = delegate self.__drawing_context_lock = threading.RLock() self.__drawing_context = DrawingContext.DrawingContext() self.__display_data = None self.__display_script = None self.__closing_lock = threading.RLock() self.__closed = False self.__data = None self.__last_data = None # canvas items get added back to front # create the child canvas items # the background self.add_canvas_item(CanvasItem.BackgroundCanvasItem()) # frame rate self.__display_frame_rate_id = None self.__display_frame_rate_last_index = 0
def __init__( self, ui_settings: UISettings.UISettings, delegate: typing.Optional[DisplayCanvasItem.DisplayCanvasItemDelegate] ) -> None: super().__init__() self.__ui_settings = ui_settings self.delegate = delegate self.__drawing_context_lock = threading.RLock() self.__drawing_context = DrawingContext.DrawingContext() self.__display_xdata: typing.Optional[ DataAndMetadata.DataAndMetadata] = None self.__display_script: typing.Optional[str] = None self.__closing_lock = threading.RLock() self.__closed = False # canvas items get added back to front # create the child canvas items # the background self.add_canvas_item(CanvasItem.BackgroundCanvasItem()) # frame rate self.__display_frame_rate_id: typing.Optional[str] = None self.__display_frame_rate_last_index = 0
def __init__( self, ui: UserInterface.UserInterface, rgba_bitmap_data: typing.Optional[DrawingContext.RGBA32Type] = None, properties: typing.Optional[typing.Mapping[str, typing.Any]] = None ) -> None: column_widget = ui.create_column_widget(properties=properties) super().__init__(column_widget) self.ui = ui self.on_clicked = None self.__image_binding: typing.Optional[Binding.Binding] = None def button_clicked() -> None: if callable(self.on_clicked): self.on_clicked() self.__bitmap_canvas_item = CanvasItem.BitmapButtonCanvasItem( rgba_bitmap_data) self.__bitmap_canvas_item.on_button_clicked = button_clicked bitmap_canvas_widget = self.ui.create_canvas_widget() bitmap_canvas_widget.canvas_item.add_canvas_item( self.__bitmap_canvas_item) column_widget.add(bitmap_canvas_widget) self.image = rgba_bitmap_data
def __init__(self, ui, app=None): super().__init__(ui, app) # first create a root canvas item in which the rest of the user interface will go canvas_widget = ui.create_canvas_widget() background_canvas_item = CanvasItem.BackgroundCanvasItem("#FFF") metadata = { "Dictionary1": { "abc": 5, "def": "hello", "List2": ["Red", "Green", "Blue"] }, "List1": [4, 5, 6] } metadata_editor_canvas_item = TreeCanvasItem.TreeCanvasItem( ui.get_font_metrics, MetadataEditorTreeDelegate(metadata)) metadata_editor_canvas_item.reconstruct() # finally add the column to the root canvas item. canvas_widget.canvas_item.add_canvas_item(background_canvas_item) canvas_widget.canvas_item.add_canvas_item(metadata_editor_canvas_item) # attach the root canvas item to the document window self.attach_widget(canvas_widget)
def __init__(self, ui: UserInterface.UserInterface, thumbnail_source: AbstractThumbnailSource, size: typing.Optional[Geometry.IntSize] = None) -> None: super().__init__() bitmap_overlay_canvas_item = BitmapOverlayCanvasItem() bitmap_canvas_item = CanvasItem.BitmapCanvasItem( background_color="#CCC", border_color="#444") bitmap_overlay_canvas_item.add_canvas_item(bitmap_canvas_item) if size is not None: bitmap_canvas_item.update_sizing( bitmap_canvas_item.sizing.with_fixed_size(size)) thumbnail_source.overlay_canvas_item.update_sizing( thumbnail_source.overlay_canvas_item.sizing.with_fixed_size( size)) bitmap_overlay_canvas_item.add_canvas_item( thumbnail_source.overlay_canvas_item) self.__thumbnail_source = thumbnail_source self.on_drag: typing.Optional[typing.Callable[[ UserInterface.MimeData, typing.Optional[_ImageDataType], int, int ], None]] = None self.on_drop_mime_data: typing.Optional[typing.Callable[ [UserInterface.MimeData, int, int], str]] = None self.on_delete: typing.Optional[typing.Callable[[], None]] = None def drag_pressed(x: int, y: int, modifiers: UserInterface.KeyboardModifiers) -> None: on_drag = self.on_drag if callable(on_drag): mime_data = ui.create_mime_data() valid, thumbnail = thumbnail_source.populate_mime_data_for_drag( mime_data, Geometry.IntSize(width=80, height=80)) if valid: on_drag(mime_data, thumbnail, x, y) def drop_mime_data(mime_data: UserInterface.MimeData, x: int, y: int) -> str: if callable(self.on_drop_mime_data): return self.on_drop_mime_data(mime_data, x, y) return "ignore" def delete() -> None: on_delete = self.on_delete if callable(on_delete): on_delete() bitmap_overlay_canvas_item.on_drag_pressed = drag_pressed bitmap_overlay_canvas_item.on_drop_mime_data = drop_mime_data bitmap_overlay_canvas_item.on_delete = delete def thumbnail_data_changed( thumbnail_data: typing.Optional[_NDArray]) -> None: bitmap_canvas_item.rgba_bitmap_data = thumbnail_data self.__thumbnail_source.on_thumbnail_data_changed = thumbnail_data_changed bitmap_canvas_item.rgba_bitmap_data = self.__thumbnail_source.thumbnail_data self.add_canvas_item(bitmap_overlay_canvas_item)
def __init__(self, document_controller: DocumentController.DocumentController, panel_id: str, properties: typing.Mapping[str, typing.Any]) -> None: super().__init__(document_controller, panel_id, _("Metadata")) ui = self.ui self.__metadata_model = MetadataModel(document_controller) delegate = MetadataEditorTreeDelegate(dict()) metadata_editor_widget = ui.create_canvas_widget() metadata_editor_canvas_item = TreeCanvasItem.TreeCanvasItem( ui.get_font_metrics, delegate) metadata_editor_widget.canvas_item.layout = CanvasItem.CanvasItemColumnLayout( ) metadata_editor_widget.canvas_item.add_canvas_item( metadata_editor_canvas_item) metadata_editor_widget.canvas_item.add_stretch() self.__metadata_editor_canvas_item = metadata_editor_canvas_item column = self.ui.create_column_widget() column.add_spacing(6) column.add(metadata_editor_widget) column.add_spacing(6) scroll_area = self.ui.create_scroll_area_widget() scroll_area.set_scrollbar_policies("needed", "needed") scroll_area.content = column def content_height_changed(content_height: int) -> None: desired_height = content_height + 12 metadata_editor_canvas_item.update_sizing( metadata_editor_canvas_item.sizing.with_fixed_height( desired_height)) metadata_editor_widget.canvas_item.update_layout( Geometry.IntPoint(), scroll_area.size) if metadata_editor_canvas_item._has_layout: column.size = Geometry.IntSize(height=desired_height, width=column.size.width) metadata_editor_canvas_item.on_content_height_changed = content_height_changed def metadata_changed(metadata: DataAndMetadata.MetadataType) -> None: delegate.metadata = metadata def reconstruct_metadata() -> None: if self.__metadata_editor_canvas_item: # use this instead of local variable to handle close properly self.__metadata_editor_canvas_item.reconstruct() self.document_controller.queue_task(reconstruct_metadata) self.__metadata_changed_event_listener = self.__metadata_model.metadata_changed_event.listen( metadata_changed) self.widget = scroll_area
def __init__(self, *, document_controller: DocumentController.DocumentController, **kwargs: typing.Any) -> None: self.radio_button_value: Model.PropertyModel[int] = Model.PropertyModel(0) u = Declarative.DeclarativeUI() top_row_items = list() bottom_row_items = list() modes = list() tool_actions = list() for action in Window.actions.values(): if action.action_id.startswith("window.set_tool_mode"): tool_actions.append(typing.cast(DocumentController.SetToolModeAction, action)) for i, tool_action in enumerate(tool_actions): tool_id = tool_action.tool_mode icon_png = tool_action.tool_icon tool_tip = tool_action.tool_tip key_shortcut = Window.action_shortcuts.get(tool_action.action_id, dict()).get("display_panel", None) if key_shortcut: tool_tip += f" ({key_shortcut})" modes.append(tool_id) assert icon_png is not None icon_data = CanvasItem.load_rgba_data_from_bytes(icon_png) icon_property = "icon_" + tool_id setattr(self, icon_property, icon_data) radio_button = u.create_radio_button(icon=f"@binding({icon_property})", value=i, group_value="@binding(radio_button_value.value)", width=32, height=24, tool_tip=tool_tip) if i % 2 == 0: top_row_items.append(radio_button) else: bottom_row_items.append(radio_button) top_row = u.create_row(*top_row_items) bottom_row = u.create_row(*bottom_row_items) self.ui_view = u.create_row(u.create_column(u.create_spacing(4), top_row, bottom_row, u.create_spacing(4), u.create_stretch())) self.radio_button_value.value = modes.index(document_controller.tool_mode) def tool_mode_changed(tool_mode: str) -> None: self.radio_button_value.value = modes.index(tool_mode) self.__tool_mode_changed_event_listener = document_controller.tool_mode_changed_event.listen(tool_mode_changed) tool_mode_changed(document_controller.tool_mode) def radio_button_changed(property: str) -> None: if property == "value": mode_index = self.radio_button_value.value if mode_index is not None: document_controller.tool_mode = modes[mode_index] self.__radio_button_value_listener = self.radio_button_value.property_changed_event.listen(radio_button_changed)
def __init__(self, ui: UserInterface.UserInterface, parent_window: UIWindow.Window, version_str: str): super().__init__(ui, include_cancel=False, parent_window=parent_window) row = self.ui.create_row_widget() logo_column = self.ui.create_column_widget() logo_button = self.ui.create_push_button_widget() logo_button.icon = CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/Logo3.png")) logo_column.add_spacing(26) logo_column.add(logo_button) logo_column.add_stretch() column = self.ui.create_column_widget() def make_label_row(label: str): row_one = self.ui.create_row_widget() row_one.add_spacing(13) row_one.add(self.ui.create_label_widget(label)) row_one.add_spacing(13) row_one.add_stretch() return row_one column.add_spacing(26) column.add(make_label_row(f"Nion Swift {version_str}")) column.add( make_label_row( "Copyright 2012-2021 Nion Company. All Rights Reserved." )) column.add_spacing(13) column.add(make_label_row(f"Python {sys.version}")) if sys.base_prefix: column.add_spacing(13) column.add(make_label_row(sys.base_prefix)) package_name_column = self.ui.create_column_widget() package_version_column = self.ui.create_column_widget() for _, package_name, package_version in Application.get_nion_swift_version_info( ): package_name_column.add( self.ui.create_label_widget(package_name)) package_version_column.add( self.ui.create_label_widget(package_version)) version_columns = self.ui.create_row_widget() version_columns.add_spacing(13) version_columns.add(package_name_column) version_columns.add_spacing(8) version_columns.add(package_version_column) version_columns.add_spacing(13) version_columns.add_stretch() column.add_spacing(13) column.add(version_columns) column.add_spacing(13) column.add_stretch() row.add(logo_column) row.add(column) self.content.add(row)
def test_shift_click_extends_selection(self): selection = Selection.IndexedSelection() delegate = ListCanvasItemDelegate() canvas_item = ListCanvasItem.ListCanvasItem(delegate, selection) canvas_item.update_layout((0, 0), (320, 100)) self.assertEqual(selection.indexes, set()) canvas_item.simulate_click(Geometry.IntPoint(y=120, x=50)) self.assertEqual(selection.indexes, {1}) modifiers = CanvasItem.KeyboardModifiers(shift=True) canvas_item.simulate_click(Geometry.IntPoint(y=200, x=50), modifiers) self.assertEqual(selection.indexes, {1, 2})
def __init__(self, ui: UserInterface.UserInterface, thumbnail_source: AbstractThumbnailSource, size: typing.Optional[Geometry.IntSize] = None, properties: typing.Optional[ Persistence.PersistentDictType] = None, is_expanding: bool = False) -> None: content_widget = ui.create_column_widget( properties={ "size-policy-horizontal": "expanding", "size-policy-vertical": "expanding" } if is_expanding else None) super().__init__(content_widget) if not is_expanding: size = size or Geometry.IntSize(width=80, height=80) thumbnail_canvas_item = ThumbnailCanvasItem(ui, thumbnail_source, size) properties = properties or ({ "height": size.height, "width": size.width } if size else dict()) bitmap_canvas_widget = ui.create_canvas_widget(properties=properties) thumbnail_square = CanvasItem.CanvasItemComposition() thumbnail_square.layout = SquareCanvasItemLayout() thumbnail_square.add_canvas_item(thumbnail_canvas_item) bitmap_canvas_widget.canvas_item.add_canvas_item(thumbnail_square) content_widget.add(bitmap_canvas_widget) self.on_drop_mime_data: typing.Optional[typing.Callable[ [UserInterface.MimeData, int, int], str]] = None self.on_drag: typing.Optional[typing.Callable[[ UserInterface.MimeData, typing.Optional[_ImageDataType], int, int ], None]] = None self.on_delete: typing.Optional[typing.Callable[[], None]] = None def drop_mime_data(mime_data: UserInterface.MimeData, x: int, y: int) -> str: if callable(self.on_drop_mime_data): return self.on_drop_mime_data(mime_data, x, y) return "ignore" def drag(mime_data: UserInterface.MimeData, thumbnail: typing.Optional[_NDArray], x: int, y: int) -> None: on_drag = self.on_drag if callable(on_drag): on_drag(mime_data, thumbnail, x, y) def delete() -> None: on_delete = self.on_delete if callable(on_delete): on_delete() thumbnail_canvas_item.on_drop_mime_data = drop_mime_data thumbnail_canvas_item.on_drag = drag thumbnail_canvas_item.on_delete = delete
def __init__(self, ui: UserInterface.UserInterface, section_title: str, section: UserInterface.Widget, section_id: typing.Optional[str] = None) -> None: section_widget = ui.create_column_widget() super().__init__(section_widget) section_title_row = ui.create_row_widget() twist_down_canvas_item = CanvasItem.TwistDownCanvasItem() twist_down_canvas_widget = ui.create_canvas_widget(properties={ "height": 20, "width": 20 }) twist_down_canvas_widget.canvas_item.add_canvas_item( twist_down_canvas_item) section_title_label = ui.create_label_widget(section_title) section_title_label.text_font = "bold" section_title_row.add(twist_down_canvas_widget) section_title_row.add(section_title_label) section_title_row.add_stretch() section_widget.add(section_title_row) section_content_row = ui.create_row_widget() section_content_column = ui.create_column_widget() section_content_column.add_spacing(4) section_content_column.add(section) section_content_row.add_spacing(20) section_content_row.add(section_content_column) section_widget.add(section_content_row) section_widget.add_spacing(4) def toggle() -> None: twist_down_canvas_item.checked = not twist_down_canvas_item.checked section_content_column.visible = twist_down_canvas_item.checked if section_id: ui.set_persistent_string( section_id, "true" if twist_down_canvas_item.checked else "false") section_open = ui.get_persistent_string( section_id, "true") == "true" if section_id else True twist_down_canvas_item.checked = section_open section_content_column.visible = section_open twist_down_canvas_item.on_button_clicked = toggle self.section_title_row = section_title_row self.__twist_down_canvas_item = twist_down_canvas_item
def __init__(self, ui, section_title: str, section, section_id: str = None): super().__init__(ui.create_column_widget()) section_widget = self.content_widget section_title_row = ui.create_row_widget() twist_down_canvas_item = CanvasItem.TwistDownCanvasItem() twist_down_canvas_widget = ui.create_canvas_widget(properties={ "height": 20, "width": 20 }) twist_down_canvas_widget.canvas_item.add_canvas_item( twist_down_canvas_item) section_title_row.add(twist_down_canvas_widget) section_title_row.add( ui.create_label_widget( section_title, properties={"stylesheet": "font-weight: bold"})) section_title_row.add_stretch() section_widget.add(section_title_row) section_content_row = ui.create_row_widget() section_content_column = ui.create_column_widget() section_content_column.add_spacing(4) section_content_column.add(section) section_content_row.add_spacing(20) section_content_row.add(section_content_column) section_widget.add(section_content_row) section_widget.add_spacing(4) def toggle(): twist_down_canvas_item.checked = not twist_down_canvas_item.checked section_content_column.visible = twist_down_canvas_item.checked if section_id: ui.set_persistent_string( section_id, "true" if twist_down_canvas_item.checked else "false") section_open = ui.get_persistent_string( section_id, "true") == "true" if section_id else True twist_down_canvas_item.checked = section_open section_content_column.visible = section_open twist_down_canvas_item.on_button_clicked = toggle self.__twist_down_canvas_item = twist_down_canvas_item
def __init__(self, ui, thumbnail_source: AbstractThumbnailSource, size: Geometry.IntSize): super().__init__() bitmap_overlay_canvas_item = BitmapOverlayCanvasItem() bitmap_canvas_item = CanvasItem.BitmapCanvasItem( background_color="#CCC", border_color="#444") bitmap_canvas_item.sizing.set_fixed_size(size) bitmap_overlay_canvas_item.add_canvas_item(bitmap_canvas_item) thumbnail_source.overlay_canvas_item.sizing.set_fixed_size(size) bitmap_overlay_canvas_item.add_canvas_item( thumbnail_source.overlay_canvas_item) self.__thumbnail_source = thumbnail_source self.on_drag = None self.on_drop_mime_data = None self.on_delete = None def drag_pressed(x, y, modifiers): on_drag = self.on_drag if callable(on_drag): mime_data = ui.create_mime_data() valid, thumbnail = thumbnail_source.populate_mime_data_for_drag( mime_data, size) if valid: on_drag(mime_data, thumbnail, x, y) def drop_mime_data(mime_data: UserInterface.MimeData, x: int, y: int) -> str: if callable(self.on_drop_mime_data): return self.on_drop_mime_data(mime_data, x, y) return "ignore" def delete(): on_delete = self.on_delete if callable(on_delete): on_delete() bitmap_overlay_canvas_item.on_drag_pressed = drag_pressed bitmap_overlay_canvas_item.on_drop_mime_data = drop_mime_data bitmap_overlay_canvas_item.on_delete = delete def thumbnail_data_changed(thumbnail_data): bitmap_canvas_item.rgba_bitmap_data = thumbnail_data self.__thumbnail_source.on_thumbnail_data_changed = thumbnail_data_changed bitmap_canvas_item.rgba_bitmap_data = self.__thumbnail_source.thumbnail_data self.add_canvas_item(bitmap_overlay_canvas_item)
def image(self, rgba_bitmap_data: typing.Optional[numpy.ndarray]) -> None: self.content_widget.remove_all() if rgba_bitmap_data is not None: height, width = rgba_bitmap_data.shape bitmap_canvas_item = CanvasItem.BitmapButtonCanvasItem(rgba_bitmap_data) # bitmap_canvas_item.update_sizing(bitmap_canvas_item.sizing.with_fixed_size(Geometry.IntSize(height=height, width=width))) def button_clicked(): if callable(self.on_clicked): self.on_clicked() bitmap_canvas_item.on_button_clicked = button_clicked bitmap_canvas_widget = self.ui.create_canvas_widget() bitmap_canvas_widget.canvas_item.add_canvas_item(bitmap_canvas_item) self.content_widget.add(bitmap_canvas_widget) self.__rgba_bitmap_data = rgba_bitmap_data
def __create_action_button(self, action: Window.Action) -> Declarative.UIDescription: action_id = action.action_id action_identifier = action_id.replace(".", "_") icon_png = getattr(action, "action_command_icon_png", None) if icon_png is not None: icon_data = CanvasItem.load_rgba_data_from_bytes(icon_png) else: icon_data = numpy.full((48, 64), 0x00FFFFFF, dtype=numpy.uint32) icon_data[8:40, 8:56] = 0xFFC0C0C0 icon_property = "icon_" + action_identifier setattr(self, icon_property, icon_data) tool_tip = getattr(action, "action_tool_tip", getattr(action, "action_name", None)) key_shortcut = Window.action_shortcuts.get(action_id, dict()).get("display_panel", None) if tool_tip and key_shortcut: tool_tip += f" ({key_shortcut})" u = Declarative.DeclarativeUI() perform_function = "perform_" + action_identifier def perform_action(widget: UserInterface.Widget) -> None: self.__document_controller.perform_action(action_id) setattr(self, perform_function, perform_action) return u.create_image(image=f"@binding({icon_property})", height=24, width=32, on_clicked=f"{perform_function}", tool_tip=tool_tip)
def __init__( self, ui: UserInterface.UserInterface, properties: typing.Optional[typing.Mapping[str, typing.Any]] = None): column_widget = ui.create_column_widget(properties=properties) super().__init__(column_widget) self.ui = ui self.on_clicked: typing.Optional[typing.Callable[[], None]] = None self.__bitmap_canvas_item = CanvasItem.BitmapButtonCanvasItem( None, border_color="#CCC") self.__bitmap_canvas_item.on_button_clicked = self.__handle_clicked self.__value: typing.Optional[int] = None self.__group_value: typing.Optional[int] = None self.__on_group_value_changed: typing.Optional[typing.Callable[ [typing.Optional[int]], None]] = None self.__group_value_binding: typing.Optional[Binding.Binding] = None self.__icon_binding: typing.Optional[Binding.Binding] = None self.__enabled = True self.__checked = False bitmap_canvas_widget = self.ui.create_canvas_widget() bitmap_canvas_widget.canvas_item.add_canvas_item( self.__bitmap_canvas_item) column_widget.add(bitmap_canvas_widget)
def __init__(self, ui, list_item_delegate, *, items=None, selection_style=None, properties=None, selection=None, border_color=None, v_scroll_enabled: bool=True, v_auto_resize: bool=False): super().__init__(ui.create_column_widget()) self.property_changed_event = Event.Event() items = items or list() self.__items: typing.List = list() self.on_selection_changed = None self.on_item_selected = None self.on_cancel = None self.on_item_handle_context_menu = None # used for declarative self.__items_binding = None self.__current_index_binding = None self.__on_current_index_changed = None self.__v_auto_resize = v_auto_resize self.on_escape_pressed : typing.Optional[typing.Callable[[], bool]] = None self.on_return_pressed : typing.Optional[typing.Callable[[], bool]] = None self.__selection = selection if selection else Selection.IndexedSelection(selection_style) def selection_changed(): on_selection_changed = self.on_selection_changed if callable(on_selection_changed): on_selection_changed(self.__selection.indexes) if callable(self.__on_current_index_changed): self.__on_current_index_changed(self.current_index) def handle_delegate_cancel(): if callable(self.on_cancel): self.on_cancel() if callable(self.on_escape_pressed): self.on_escape_pressed() def handle_delegate_item_selected(index): if callable(self.on_item_selected): self.on_item_selected(index) if callable(self.on_return_pressed): self.on_return_pressed() self.__selection_changed_event_listener = self.__selection.changed_event.listen(selection_changed) self.__list_canvas_item_delegate = list_item_delegate self.__list_canvas_item_delegate.on_cancel = handle_delegate_cancel self.__list_canvas_item_delegate.on_item_selected = handle_delegate_item_selected self.__list_canvas_item = ListCanvasItem.ListCanvasItem(self.__list_canvas_item_delegate, self.__selection, 20) scroll_area_canvas_item = CanvasItem.ScrollAreaCanvasItem(self.__list_canvas_item) scroll_area_canvas_item.auto_resize_contents = True scroll_group_canvas_item = CanvasItem.CanvasItemComposition() if border_color is not None: scroll_group_canvas_item.border_color = border_color scroll_group_canvas_item.layout = CanvasItem.CanvasItemRowLayout() scroll_group_canvas_item.add_canvas_item(scroll_area_canvas_item) if v_scroll_enabled: scroll_bar_canvas_item = CanvasItem.ScrollBarCanvasItem(scroll_area_canvas_item) scroll_group_canvas_item.add_canvas_item(scroll_bar_canvas_item) canvas_widget = ui.create_canvas_widget(properties=properties) canvas_widget.canvas_item.add_canvas_item(scroll_group_canvas_item) self.content_widget.add(canvas_widget) self.__canvas_widget = canvas_widget self.items = items
def __init__(self, display_panel, hardware_source_id): assert hardware_source_id is not None hardware_source = HardwareSource.HardwareSourceManager().get_hardware_source_for_hardware_source_id(hardware_source_id) self.type = VideoDisplayPanelController.type self.__hardware_source_id = hardware_source_id # configure the hardware source state controller self.__state_controller = VideoSourceStateController(hardware_source, display_panel.document_controller.queue_task, display_panel.document_controller.document_model) # configure the user interface self.__play_button_enabled = False self.__play_button_play_button_state = "play" self.__data_item_states = list() self.__display_panel = display_panel self.__display_panel.header_canvas_item.end_header_color = "#DAA520" self.__playback_controls_composition = CanvasItem.CanvasItemComposition() self.__playback_controls_composition.layout = CanvasItem.CanvasItemLayout() self.__playback_controls_composition.sizing.set_fixed_height(30) playback_controls_row = CanvasItem.CanvasItemComposition() playback_controls_row.layout = CanvasItem.CanvasItemRowLayout() play_button_canvas_item = CanvasItem.TextButtonCanvasItem() play_button_canvas_item.border_enabled = False abort_button_canvas_item = CanvasItem.TextButtonCanvasItem() abort_button_canvas_item.border_enabled = False status_text_canvas_item = CanvasItem.StaticTextCanvasItem(str()) hardware_source_display_name_canvas_item = CanvasItem.StaticTextCanvasItem(str()) playback_controls_row.add_canvas_item(play_button_canvas_item) playback_controls_row.add_canvas_item(abort_button_canvas_item) playback_controls_row.add_canvas_item(status_text_canvas_item) playback_controls_row.add_stretch() playback_controls_row.add_canvas_item(hardware_source_display_name_canvas_item) self.__playback_controls_composition.add_canvas_item(CanvasItem.BackgroundCanvasItem("#DAA520")) self.__playback_controls_composition.add_canvas_item(playback_controls_row) self.__display_panel.footer_canvas_item.insert_canvas_item(0, self.__playback_controls_composition) def display_name_changed(display_name): hardware_source_display_name_canvas_item.text = display_name hardware_source_display_name_canvas_item.size_to_content(display_panel.image_panel_get_font_metrics) def play_button_state_changed(enabled, play_button_state): play_button_canvas_item.enabled = enabled map_play_button_state_to_text = {"play": _("Play"), "pause": _("Pause")} play_button_canvas_item.text = map_play_button_state_to_text[play_button_state] play_button_canvas_item.size_to_content(display_panel.image_panel_get_font_metrics) def abort_button_state_changed(visible, enabled): abort_button_canvas_item.text = _("Abort") if visible else str() abort_button_canvas_item.enabled = enabled abort_button_canvas_item.size_to_content(display_panel.image_panel_get_font_metrics) def update_status_text(): map_channel_state_to_text = {"stopped": _("Stopped"), "complete": _("Acquiring"), "partial": _("Acquiring"), "marked": _("Stopping")} for data_item_state in self.__data_item_states: channel_state = data_item_state["channel_state"] new_text = map_channel_state_to_text[channel_state] if status_text_canvas_item.text != new_text: status_text_canvas_item.text = new_text status_text_canvas_item.size_to_content(display_panel.image_panel_get_font_metrics) return def data_item_states_changed(data_item_states): self.__data_item_states = data_item_states update_status_text() def display_data_item_changed(data_item): display_panel.set_displayed_data_item(data_item) def display_new_data_item(data_item): result_display_panel = display_panel.document_controller.next_result_display_panel() if result_display_panel: result_display_panel.set_display_panel_data_item(data_item) result_display_panel.request_focus() self.__state_controller.on_display_name_changed = display_name_changed self.__state_controller.on_play_button_state_changed = play_button_state_changed self.__state_controller.on_abort_button_state_changed = abort_button_state_changed self.__state_controller.on_data_item_states_changed = data_item_states_changed self.__state_controller.on_display_data_item_changed = display_data_item_changed self.__state_controller.on_display_new_data_item = display_new_data_item play_button_canvas_item.on_button_clicked = self.__state_controller.handle_play_clicked abort_button_canvas_item.on_button_clicked = self.__state_controller.handle_abort_clicked self.__state_controller.initialize_state() document_model = self.__display_panel.document_controller.document_model
def __init__(self): self.on_thumbnail_data_changed = None self.__thumbnail_data = None self.overlay_canvas_item = CanvasItem.EmptyCanvasItem()
def __init__(self, document_controller, panel_id, properties): super(ToolbarPanel, self).__init__(document_controller, panel_id, _("Toolbar")) self.widget = self.ui.create_column_widget() toolbar_row_widget = self.ui.create_row_widget() # see https://www.iconfinder.com ui = document_controller.ui document_controller_weak_ref = weakref.ref(document_controller) icon_size = Geometry.IntSize(height=24, width=32) border_color = "#CCC" margins = Geometry.Margins(left=2, right=2, top=3, bottom=3) tool_palette_grid_canvas_item = CanvasItem.CanvasItemComposition() tool_palette_grid_canvas_item.layout = CanvasItem.CanvasItemGridLayout( size=Geometry.IntSize(height=2, width=6), margins=margins) pointer_tool_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/pointer_icon.png")), border_color=border_color) pointer_tool_button.size = icon_size pointer_tool_button.tool_tip = _("Pointer tool for selecting graphics") hand_tool_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/hand_icon.png")), border_color=border_color) hand_tool_button.size = icon_size hand_tool_button.tool_tip = _( "Hand tool for dragging images within panel") line_tool_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/line_icon.png")), border_color=border_color) line_tool_button.size = icon_size line_tool_button.tool_tip = _( "Line tool for making line regions on images") rectangle_tool_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/rectangle_icon.png")), border_color=border_color) rectangle_tool_button.size = icon_size rectangle_tool_button.tool_tip = _( "Rectangle tool for making rectangle regions on images") ellipse_tool_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/ellipse_icon.png")), border_color=border_color) ellipse_tool_button.size = icon_size ellipse_tool_button.tool_tip = _( "Ellipse tool for making ellipse regions on images") point_tool_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/point_icon.png")), border_color=border_color) point_tool_button.size = icon_size point_tool_button.tool_tip = _( "Point tool for making point regions on images") line_profile_tool_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/line_profile_icon.png")), border_color=border_color) line_profile_tool_button.size = icon_size line_profile_tool_button.tool_tip = _( "Line profile tool for making line profiles on images") interval_tool_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/interval_icon.png")), border_color=border_color) interval_tool_button.size = icon_size interval_tool_button.tool_tip = _( "Interval tool for making intervals on line plots") spot_tool_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/spot_icon.png")), border_color=border_color) spot_tool_button.size = icon_size spot_tool_button.tool_tip = _("Spot tool for creating spot masks") wedge_tool_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/wedge_icon.png")), border_color=border_color) wedge_tool_button.size = icon_size wedge_tool_button.tool_tip = _("Wedge tool for creating wedge masks") ring_tool_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/annular_ring.png")), border_color=border_color) ring_tool_button.size = icon_size ring_tool_button.tool_tip = _("Ring tool for creating ring masks") lattice_tool_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/lattice_icon.png")), border_color=border_color) lattice_tool_button.size = icon_size lattice_tool_button.tool_tip = _( "Lattice tool for creating periodic lattice masks") tool_palette_grid_canvas_item.add_canvas_item( pointer_tool_button, Geometry.IntPoint(x=0, y=0)) tool_palette_grid_canvas_item.add_canvas_item( hand_tool_button, Geometry.IntPoint(x=0, y=1)) tool_palette_grid_canvas_item.add_canvas_item( line_tool_button, Geometry.IntPoint(x=1, y=0)) tool_palette_grid_canvas_item.add_canvas_item( ellipse_tool_button, Geometry.IntPoint(x=1, y=1)) tool_palette_grid_canvas_item.add_canvas_item( rectangle_tool_button, Geometry.IntPoint(x=2, y=0)) tool_palette_grid_canvas_item.add_canvas_item( point_tool_button, Geometry.IntPoint(x=2, y=1)) tool_palette_grid_canvas_item.add_canvas_item( line_profile_tool_button, Geometry.IntPoint(x=3, y=0)) tool_palette_grid_canvas_item.add_canvas_item( interval_tool_button, Geometry.IntPoint(x=3, y=1)) tool_palette_grid_canvas_item.add_canvas_item( spot_tool_button, Geometry.IntPoint(x=4, y=0)) tool_palette_grid_canvas_item.add_canvas_item( wedge_tool_button, Geometry.IntPoint(x=4, y=1)) tool_palette_grid_canvas_item.add_canvas_item( ring_tool_button, Geometry.IntPoint(x=5, y=0)) tool_palette_grid_canvas_item.add_canvas_item( lattice_tool_button, Geometry.IntPoint(x=5, y=1)) modes = "pointer", "hand", "line", "rectangle", "ellipse", "point", "line-profile", "interval", "spot", "wedge", "ring", "lattice" self.__tool_button_group = CanvasItem.RadioButtonGroup([ pointer_tool_button, hand_tool_button, line_tool_button, rectangle_tool_button, ellipse_tool_button, point_tool_button, line_profile_tool_button, interval_tool_button, spot_tool_button, wedge_tool_button, ring_tool_button ]) def tool_mode_changed(tool_mode): self.__tool_button_group.current_index = modes.index(tool_mode) self.__tool_mode_changed_event_listener = document_controller.tool_mode_changed_event.listen( tool_mode_changed) self.__tool_button_group.current_index = modes.index( document_controller.tool_mode) self.__tool_button_group.on_current_index_changed = lambda index: setattr( document_controller_weak_ref(), "tool_mode", modes[index]) tool_mode_changed(document_controller.tool_mode) new_group_button = self.ui.create_push_button_widget() new_group_button.tool_tip = _("New Group") new_group_button.icon = CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/new_group_icon.png")) new_group_button.on_clicked = lambda: document_controller_weak_ref( ).perform_action("project.add_group") delete_button = self.ui.create_push_button_widget() delete_button.tool_tip = _("Delete") delete_button.icon = CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/delete_icon.png")) delete_button.on_clicked = lambda: document_controller_weak_ref( ).perform_action("window.delete") export_button = self.ui.create_push_button_widget() export_button.tool_tip = _("Export") export_button.icon = CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/export_icon.png")) export_button.on_clicked = lambda: document_controller_weak_ref( ).perform_action("file.export") view_palette_grid_canvas_item = CanvasItem.CanvasItemComposition() view_palette_grid_canvas_item.layout = CanvasItem.CanvasItemGridLayout( size=Geometry.IntSize(height=2, width=2), margins=margins) fit_view_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/fit_icon.png")), border_color=border_color) fit_view_button.size = icon_size fit_view_button.on_button_clicked = lambda: document_controller_weak_ref( )._fit_view_action.trigger() fit_view_button.tool_tip = _("Zoom to fit to enclosing space") fill_view_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/fill_icon.png")), border_color=border_color) fill_view_button.size = icon_size fill_view_button.on_button_clicked = lambda: document_controller_weak_ref( )._fill_view_action.trigger() fill_view_button.tool_tip = _("Zoom to fill enclosing space") one_to_one_view_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/1x1_icon.png")), border_color=border_color) one_to_one_view_button.size = icon_size one_to_one_view_button.on_button_clicked = lambda: document_controller_weak_ref( )._one_to_one_view_action.trigger() one_to_one_view_button.tool_tip = _( "Zoom to one image pixel per screen pixel") two_to_one_view_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/2x1_icon.png")), border_color=border_color) two_to_one_view_button.size = icon_size two_to_one_view_button.on_button_clicked = lambda: document_controller_weak_ref( )._two_to_one_view_action.trigger() two_to_one_view_button.tool_tip = _( "Zoom to two image pixels per screen pixel") view_palette_grid_canvas_item.add_canvas_item( fit_view_button, Geometry.IntPoint(x=0, y=0)) view_palette_grid_canvas_item.add_canvas_item( fill_view_button, Geometry.IntPoint(x=0, y=1)) view_palette_grid_canvas_item.add_canvas_item( one_to_one_view_button, Geometry.IntPoint(x=1, y=0)) view_palette_grid_canvas_item.add_canvas_item( two_to_one_view_button, Geometry.IntPoint(x=1, y=1)) toggle_filter_button = self.ui.create_push_button_widget() toggle_filter_button.tool_tip = _("Toggle Filter Panel") toggle_filter_button.icon = CanvasItem.load_rgba_data_from_bytes( pkgutil.get_data(__name__, "resources/filter_icon.png")) toggle_filter_button.on_clicked = lambda: document_controller_weak_ref( )._toggle_filter_action.trigger() tool_palette_widget = ui.create_canvas_widget(properties={ "height": 54, "width": 164 }) tool_palette_widget.canvas_item.add_canvas_item( tool_palette_grid_canvas_item) tool_group_widget = self.ui.create_row_widget() tool_group_widget.add(tool_palette_widget) commands_group_widget = self.ui.create_row_widget() commands_group_widget.add(new_group_button) commands_group_widget.add(delete_button) commands_group_widget.add(export_button) view_palette_widget = ui.create_canvas_widget(properties={ "height": 54, "width": 68 }) view_palette_widget.canvas_item.add_canvas_item( view_palette_grid_canvas_item) view_group_widget = self.ui.create_row_widget() view_group_widget.add(view_palette_widget) filter_group_widget = self.ui.create_row_widget() filter_group_widget.add(toggle_filter_button) toolbar_row_widget.add_spacing(12) toolbar_row_widget.add(tool_group_widget) toolbar_row_widget.add_spacing(12) toolbar_row_widget.add(commands_group_widget) toolbar_row_widget.add_spacing(12) toolbar_row_widget.add(view_group_widget) toolbar_row_widget.add_spacing(12) toolbar_row_widget.add(filter_group_widget) toolbar_row_widget.add_spacing(12) toolbar_row_widget.add_stretch() self.widget.add(toolbar_row_widget)
def __init__(self, event_loop: asyncio.AbstractEventLoop, ui, display_item_adapters_model, selection, direction=GridCanvasItem.Direction.Row, wrap=True): super().__init__() self.__event_loop = event_loop self.__pending_tasks : typing.List = list() self.ui = ui self.__selection = selection self.on_delete_display_item_adapters : typing.Optional[typing.Callable[[typing.List[DisplayItemAdapter]], None]] = None self.on_key_pressed : typing.Optional[typing.Callable[[UserInterface.Key], bool]] = None self.on_display_item_adapter_double_clicked : typing.Optional[typing.Callable[[DisplayItemAdapter], bool]] = None self.on_display_item_adapter_selection_changed : typing.Optional[typing.Callable[[typing.List[DisplayItemAdapter]], None]] = None self.on_context_menu_event : typing.Optional[typing.Callable[[typing.Optional[DisplayItem.DisplayItem], int, int, int, int], bool]] = None self.on_focus_changed : typing.Optional[typing.Callable[[bool], None]] = None self.on_drag_started : typing.Optional[typing.Callable[[UserInterface.MimeData, numpy.ndarray], None]] = None self.__display_item_adapters : typing.List[DisplayItemAdapter] = list() self.__display_item_adapter_needs_update_listeners : typing.List = list() self.__display_item_adapters_model = display_item_adapters_model self.__display_item_adapter_inserted_event_listener = self.__display_item_adapters_model.item_inserted_event.listen(self.__display_item_adapter_inserted) self.__display_item_adapter_removed_event_listener = self.__display_item_adapters_model.item_removed_event.listen(self.__display_item_adapter_removed) self.__display_item_adapter_end_changes_event_listener = self.__display_item_adapters_model.end_changes_event.listen(self.__display_item_adapter_end_changes) class GridCanvasItemDelegate: def __init__(self, data_grid_controller: DataGridController): self.__data_grid_controller = data_grid_controller @property def item_count(self) -> int: return self.__data_grid_controller.display_item_adapter_count @property def items(self) -> typing.List[DisplayItemAdapter]: return self.__data_grid_controller.display_item_adapters def paint_item(self, drawing_context: DrawingContext.DrawingContext, display_item_adapter: DisplayItemAdapter, rect: Geometry.IntRect, is_selected: bool) -> None: display_item_adapter.draw_grid_item(drawing_context, rect) def on_context_menu_event(self, index: int, x: int, y: int, gx: int, gy: int) -> bool: return self.__data_grid_controller.context_menu_event(index, x, y, gx, gy) def on_delete_pressed(self) -> None: self.__data_grid_controller._delete_pressed() def on_key_pressed(self, key: UserInterface.Key) -> bool: return self.__data_grid_controller._key_pressed(key) def on_mouse_double_clicked(self, mouse_index: int, x: int, y: int, modifiers: UserInterface.KeyboardModifiers) -> bool: return self.__data_grid_controller._double_clicked() def on_drag_started(self, index: int, x: int, y: int, modifiers: UserInterface.KeyboardModifiers) -> None: self.__data_grid_controller.drag_started(index, x, y, modifiers) self.icon_view_canvas_item = GridCanvasItem.GridCanvasItem(GridCanvasItemDelegate(self), self.__selection, direction, wrap) def icon_view_canvas_item_focus_changed(focused: bool) -> None: self.icon_view_canvas_item.update() if self.on_focus_changed: self.on_focus_changed(focused) self.icon_view_canvas_item.on_focus_changed = icon_view_canvas_item_focus_changed self.scroll_area_canvas_item = CanvasItem.ScrollAreaCanvasItem(self.icon_view_canvas_item) self.scroll_area_canvas_item.auto_resize_contents = True self.scroll_group_canvas_item = CanvasItem.CanvasItemComposition() if (wrap and direction == GridCanvasItem.Direction.Row) or (not wrap and direction == GridCanvasItem.Direction.Column): self.scroll_bar_canvas_item = CanvasItem.ScrollBarCanvasItem(self.scroll_area_canvas_item) self.scroll_group_canvas_item.layout = CanvasItem.CanvasItemRowLayout() else: self.scroll_bar_canvas_item = CanvasItem.ScrollBarCanvasItem(self.scroll_area_canvas_item, CanvasItem.Orientation.Horizontal) self.scroll_group_canvas_item.layout = CanvasItem.CanvasItemColumnLayout() self.scroll_group_canvas_item.add_canvas_item(self.scroll_area_canvas_item) self.scroll_group_canvas_item.add_canvas_item(self.scroll_bar_canvas_item) """ # dual scroll bars, leave here for easy testing self.vertical_scroll_bar_canvas_item = CanvasItem.ScrollBarCanvasItem(self.scroll_area_canvas_item) self.horizontal_scroll_bar_canvas_item = CanvasItem.ScrollBarCanvasItem(self.scroll_area_canvas_item, CanvasItem.Orientation.Horizontal) self.scroll_group_canvas_item.layout = CanvasItem.CanvasItemGridLayout(Geometry.IntSize(width=2, height=2)) self.scroll_group_canvas_item.add_canvas_item(self.scroll_area_canvas_item, Geometry.IntPoint(x=0, y=0)) self.scroll_group_canvas_item.add_canvas_item(self.vertical_scroll_bar_canvas_item, Geometry.IntPoint(x=1, y=0)) self.scroll_group_canvas_item.add_canvas_item(self.horizontal_scroll_bar_canvas_item, Geometry.IntPoint(x=0, y=1)) """ self.canvas_item = self.scroll_group_canvas_item def selection_changed() -> None: self.selected_indexes = list(self.__selection.indexes) if callable(self.on_display_item_adapter_selection_changed): self.on_display_item_adapter_selection_changed([self.__display_item_adapters[index] for index in list(self.__selection.indexes)]) self.icon_view_canvas_item.make_selection_visible() self.__selection_changed_listener = self.__selection.changed_event.listen(selection_changed) self.selected_indexes = list() # changed display items keep track of items whose content has changed # the content changed messages may come from a thread so have to be # moved to the main thread via this object. self.__changed_display_item_adapters = False self.__changed_display_item_adapters_mutex = threading.RLock() self.__closed = False for index, display_item_adapter in enumerate(self.__display_item_adapters_model.display_item_adapters): self.__display_item_adapter_inserted("display_item_adapters", display_item_adapter, index)
def __init__(self, document_controller: DocumentController.DocumentController, panel_id: str, properties: typing.Dict): super().__init__(document_controller, panel_id, _("Data Items")) ui = document_controller.ui def show_context_menu(display_item: typing.Optional[DisplayItem.DisplayItem], x: int, y: int, gx: int, gy: int) -> bool: menu = document_controller.create_context_menu_for_display(display_item, use_selection=True) menu.popup(gx, gy) return True def map_display_item_to_display_item_adapter(display_item: DisplayItem.DisplayItem) -> DisplayItemAdapter: return DisplayItemAdapter(display_item, ui) def unmap_display_item_to_display_item_adapter(display_item_adapter: DisplayItemAdapter) -> None: display_item_adapter.close() self.__filtered_display_item_adapters_model = ListModel.MappedListModel(container=document_controller.filtered_display_items_model, master_items_key="display_items", items_key="display_item_adapters", map_fn=map_display_item_to_display_item_adapter, unmap_fn=unmap_display_item_to_display_item_adapter) self.__selection = self.document_controller.selection self.__focused = False def selection_changed() -> None: # called when the selection changes; notify selected display item changed if focused. self.__notify_focus_changed() self.__selection_changed_event_listener = self.__selection.changed_event.listen(selection_changed) def display_item_adapter_selection_changed(display_item_adapters: typing.List[DisplayItemAdapter]) -> None: indexes = set() for index, display_item_adapter in enumerate(self.__filtered_display_item_adapters_model.display_item_adapters): if display_item_adapter in display_item_adapters: indexes.add(index) self.__selection.set_multiple(indexes) self.__notify_focus_changed() def focus_changed(focused: bool) -> None: self.focused = focused def delete_display_item_adapters(display_item_adapters: typing.List[DisplayItemAdapter]) -> None: document_controller.delete_display_items([display_item_adapter.display_item for display_item_adapter in display_item_adapters if display_item_adapter.display_item]) self.data_list_controller = DataListController(document_controller.event_loop, ui, self.__filtered_display_item_adapters_model, self.__selection) self.data_list_controller.on_display_item_adapter_selection_changed = display_item_adapter_selection_changed self.data_list_controller.on_context_menu_event = show_context_menu self.data_list_controller.on_focus_changed = focus_changed self.data_list_controller.on_delete_display_item_adapters = delete_display_item_adapters self.data_grid_controller = DataGridController(document_controller.event_loop, ui, self.__filtered_display_item_adapters_model, self.__selection) self.data_grid_controller.on_display_item_adapter_selection_changed = display_item_adapter_selection_changed self.data_grid_controller.on_context_menu_event = show_context_menu self.data_grid_controller.on_focus_changed = focus_changed self.data_grid_controller.on_delete_display_item_adapters = delete_display_item_adapters data_list_widget = DataListWidget(ui, self.data_list_controller) data_grid_widget = DataGridWidget(ui, self.data_grid_controller) list_icon_button = CanvasItem.BitmapButtonCanvasItem(CanvasItem.load_rgba_data_from_bytes(pkgutil.get_data(__name__, "resources/list_icon_20.png"))) grid_icon_button = CanvasItem.BitmapButtonCanvasItem(CanvasItem.load_rgba_data_from_bytes(pkgutil.get_data(__name__, "resources/grid_icon_20.png"))) list_icon_button.sizing.set_fixed_size(Geometry.IntSize(20, 20)) grid_icon_button.sizing.set_fixed_size(Geometry.IntSize(20, 20)) button_row = CanvasItem.CanvasItemComposition() button_row.layout = CanvasItem.CanvasItemRowLayout(spacing=4) button_row.add_canvas_item(list_icon_button) button_row.add_canvas_item(grid_icon_button) buttons_widget = ui.create_canvas_widget(properties={"height": 20, "width": 44}) buttons_widget.canvas_item.add_canvas_item(button_row) search_widget = ui.create_row_widget() search_widget.add_spacing(8) search_widget.add(ui.create_label_widget(_("Filter"))) search_widget.add_spacing(8) search_line_edit = ui.create_line_edit_widget() search_line_edit.placeholder_text = _("No Filter") search_line_edit.clear_button_enabled = True # Qt 5.3 doesn't signal text edited or editing finished when clearing. useless so disabled. search_line_edit.on_text_edited = self.document_controller.filter_controller.text_filter_changed search_line_edit.on_editing_finished = self.document_controller.filter_controller.text_filter_changed search_widget.add(search_line_edit) search_widget.add_spacing(6) search_widget.add(buttons_widget) search_widget.add_spacing(8) self.data_view_widget = ui.create_stack_widget() self.data_view_widget.add(data_list_widget) self.data_view_widget.add(data_grid_widget) self.data_view_widget.current_index = 0 self.__view_button_group = CanvasItem.RadioButtonGroup([list_icon_button, grid_icon_button]) self.__view_button_group.current_index = 0 self.__view_button_group.on_current_index_changed = lambda index: setattr(self.data_view_widget, "current_index", index) widget = ui.create_column_widget(properties=properties) widget.add(self.data_view_widget) widget.add_spacing(6) widget.add(search_widget) widget.add_spacing(6) self.widget = widget self._data_list_widget = data_list_widget self._data_grid_widget = data_grid_widget
def __init__(self, ui, items, selection_style=None, stringify_item=None, properties=None): super().__init__(ui.create_column_widget()) self.__items = items content_widget = self.content_widget self.on_selection_changed = None self.on_item_selected = None stringify_item = str if stringify_item is None else stringify_item class ListCanvasItemDelegate: def __init__(self, string_list_widget, items, selection): self.__string_list_widget = string_list_widget self.__items = items self.__selection = selection @property def items(self): return self.__items @items.setter def items(self, value): self.__items = value @property def item_count(self): return len(self.__items) def on_context_menu_event(self, index, x, y, gx, gy): return False def on_delete_pressed(self): pass def on_key_pressed(self, key): return False def on_drag_started(self, index, x, y, modifiers): pass def on_item_selected(self, index): if callable(self.__string_list_widget.on_item_selected): return self.__string_list_widget.on_item_selected(index) return False def paint_item(self, drawing_context, display_item, rect, is_selected): item = stringify_item(display_item) with drawing_context.saver(): drawing_context.fill_style = "#000" drawing_context.font = "12px" drawing_context.text_align = 'left' drawing_context.text_baseline = 'bottom' drawing_context.fill_text(item, rect[0][1] + 4, rect[0][0] + 20 - 4) self.__selection = Selection.IndexedSelection(selection_style) def selection_changed(): on_selection_changed = self.on_selection_changed if callable(on_selection_changed): on_selection_changed(self.__selection.indexes) self.__selection_changed_event_listener = self.__selection.changed_event.listen( selection_changed) self.__list_canvas_item_delegate = ListCanvasItemDelegate( self, items, self.__selection) self.__list_canvas_item = ListCanvasItem.ListCanvasItem( self.__list_canvas_item_delegate, self.__selection, 20) scroll_area_canvas_item = CanvasItem.ScrollAreaCanvasItem( self.__list_canvas_item) scroll_area_canvas_item.auto_resize_contents = True scroll_bar_canvas_item = CanvasItem.ScrollBarCanvasItem( scroll_area_canvas_item) scroll_group_canvas_item = CanvasItem.CanvasItemComposition() scroll_group_canvas_item.border_color = "#888" scroll_group_canvas_item.layout = CanvasItem.CanvasItemRowLayout() scroll_group_canvas_item.add_canvas_item(scroll_area_canvas_item) scroll_group_canvas_item.add_canvas_item(scroll_bar_canvas_item) canvas_widget = ui.create_canvas_widget(properties=properties) canvas_widget.canvas_item.add_canvas_item(scroll_group_canvas_item) content_widget.add(canvas_widget)
def __init__(self) -> None: self.on_thumbnail_data_changed: typing.Optional[typing.Callable[ [typing.Optional[_NDArray]], None]] = None self.__thumbnail_data: typing.Optional[_NDArray] = None self.overlay_canvas_item: CanvasItem.AbstractCanvasItem = CanvasItem.EmptyCanvasItem( )
def __init__(self, display_panel: DisplayPanel.DisplayPanel, hardware_source_id: str) -> None: assert hardware_source_id is not None hardware_source = HardwareSource.HardwareSourceManager( ).get_hardware_source_for_hardware_source_id(hardware_source_id) assert isinstance(hardware_source, video_base.VideoHardwareSource) self.type = VideoDisplayPanelController.type self.__hardware_source_id = hardware_source_id # configure the hardware source state controller self.__state_controller = VideoSourceStateController( hardware_source, display_panel.document_controller.queue_task, display_panel.document_controller.document_model) # configure the user interface self.__play_button_enabled = False self.__play_button_play_button_state = "play" self.__display_panel = display_panel self.__display_panel.header_canvas_item.end_header_color = "#DAA520" self.__playback_controls_composition = CanvasItem.CanvasItemComposition( ) self.__playback_controls_composition.layout = CanvasItem.CanvasItemLayout( ) self.__playback_controls_composition.update_sizing( self.__playback_controls_composition.sizing.with_fixed_height(30)) playback_controls_row = CanvasItem.CanvasItemComposition() playback_controls_row.layout = CanvasItem.CanvasItemRowLayout() play_button_canvas_item = CanvasItem.TextButtonCanvasItem() play_button_canvas_item.border_enabled = False abort_button_canvas_item = CanvasItem.TextButtonCanvasItem() abort_button_canvas_item.border_enabled = False status_text_canvas_item = CanvasItem.StaticTextCanvasItem(str()) hardware_source_display_name_canvas_item = CanvasItem.StaticTextCanvasItem( str()) playback_controls_row.add_canvas_item(play_button_canvas_item) playback_controls_row.add_canvas_item(abort_button_canvas_item) playback_controls_row.add_canvas_item(status_text_canvas_item) playback_controls_row.add_stretch() playback_controls_row.add_canvas_item( hardware_source_display_name_canvas_item) self.__playback_controls_composition.add_canvas_item( CanvasItem.BackgroundCanvasItem("#DAA520")) self.__playback_controls_composition.add_canvas_item( playback_controls_row) self.__display_panel.footer_canvas_item.insert_canvas_item( 0, self.__playback_controls_composition) def display_name_changed(display_name: str) -> None: hardware_source_display_name_canvas_item.text = display_name hardware_source_display_name_canvas_item.size_to_content( display_panel.image_panel_get_font_metrics) def play_button_state_changed(enabled: bool, play_button_state: str) -> None: play_button_canvas_item.enabled = enabled map_play_button_state_to_text = { "play": _("Play"), "pause": _("Pause") } play_button_canvas_item.text = map_play_button_state_to_text[ play_button_state] play_button_canvas_item.size_to_content( display_panel.image_panel_get_font_metrics) def abort_button_state_changed(visible: bool, enabled: bool) -> None: abort_button_canvas_item.text = _("Abort") if visible else str() abort_button_canvas_item.enabled = enabled abort_button_canvas_item.size_to_content( display_panel.image_panel_get_font_metrics) def acquisition_state_changed(key: str) -> None: # this may be called on a thread. create an async method (guaranteed to run on the main thread) # and add it to the window event loop. async def update_acquisition_state_label( acquisition_state: typing.Optional[str]) -> None: acquisition_state = acquisition_state or "stopped" status_text_canvas_item.text = map_channel_state_to_text[ acquisition_state] status_text_canvas_item.size_to_content( display_panel.image_panel_get_font_metrics) self.__display_panel.document_controller.event_loop.create_task( update_acquisition_state_label( self.__state_controller.acquisition_state_model.value)) def display_new_data_item(data_item: DataItem.DataItem) -> None: result_display_panel = display_panel.document_controller.next_result_display_panel( ) if result_display_panel: result_display_panel.set_display_panel_data_item(data_item) result_display_panel.request_focus() self.__state_controller.on_display_name_changed = display_name_changed self.__state_controller.on_play_button_state_changed = play_button_state_changed self.__state_controller.on_abort_button_state_changed = abort_button_state_changed self.__state_controller.on_display_new_data_item = display_new_data_item display_panel.set_data_item_reference( self.__state_controller.data_item_reference) play_button_canvas_item.on_button_clicked = self.__state_controller.handle_play_clicked abort_button_canvas_item.on_button_clicked = self.__state_controller.handle_abort_clicked self.__acquisition_state_changed_listener = self.__state_controller.acquisition_state_model.property_changed_event.listen( acquisition_state_changed) self.__state_controller.initialize_state() acquisition_state_changed("value")
def create_panel_widget( self, ui: Facade.UserInterface, document_controller: Facade.DocumentWindow) -> Facade.ColumnWidget: # note: anything created here should be disposed in close. # this method may be called more than once. if not self.stem_controller: return ui.create_column_widget() self.line_edit_widgets = dict() self._stem_controller = None self._camera = None self._scan_controller = None self.multi_acquire_controller = MultiAcquire.MultiAcquireController( self.stem_controller, savepath=os.path.join(os.path.expanduser('~'), 'MultiAcquire')) self.__acquisition_state_changed_event_listener = self.multi_acquire_controller.acquisition_state_changed_event.listen( self.acquisition_state_changed) self.__multi_eels_parameters_changed_event_listener = self.multi_acquire_controller.spectrum_parameters.parameters_changed_event.listen( self.spectrum_parameters_changed) self.__progress_updated_event_listener = self.multi_acquire_controller.progress_updated_event.listen( self.update_progress_bar) self.__settings_changed_event_listener = None self.__component_registered_event_listener = None self.__component_unregistered_event_listener = None self.__scan_frame_parameters_changed_event_listener = None self.__new_scan_data_ready_event_listener = None self.settings_window_open = False self.parameter_column = None self.result_data_items = None self.__acquisition_running = False self.__acquisition_thread = None self.ui = ui self.document_controller = document_controller def start_clicked() -> None: multi_acquire_controller = self.multi_acquire_controller if not multi_acquire_controller: return if self.__acquisition_running: multi_acquire_controller.cancel() else: multi_acquire_controller.stem_controller = self.stem_controller multi_acquire_controller.camera = self.camera def run_multi_eels() -> None: assert multi_acquire_controller data_dict = multi_acquire_controller.acquire_multi_eels_spectrum( ) def create_and_display_data_item() -> None: self.create_result_data_item(data_dict) document_controller.queue_task(create_and_display_data_item ) # must occur on UI thread self.__acquisition_thread = threading.Thread( target=run_multi_eels, daemon=True) self.__acquisition_thread.start() def start_si_clicked() -> None: multi_acquire_controller = self.multi_acquire_controller if not multi_acquire_controller: return if self.__acquisition_running: multi_acquire_controller.cancel() else: # Camera must be accessed from the UI thread, so do it here and re-use later camera = self.camera scan_controller = self.scan_controller assert camera assert scan_controller multi_acquire_controller.stem_controller = self.stem_controller multi_acquire_controller.camera = camera multi_acquire_controller.scan_controller = scan_controller def create_acquisition_handler( multi_acquire_parameters: MultiAcquire.MultiEELSParameters, current_parameters_index: int, multi_acquire_settings: MultiAcquire.MultiEELSSettings ) -> MultiAcquire.SISequenceAcquisitionHandler: assert camera assert scan_controller assert multi_acquire_controller document_model = self.document_controller._document_controller.document_model camera_frame_parameters = camera.get_current_frame_parameters( ) scan_frame_parameters = scan_controller.get_current_frame_parameters( ) camera_frame_parameters.exposure_ms = multi_acquire_parameters[ current_parameters_index]['exposure_ms'] camera_frame_parameters.processing = multi_acquire_settings[ 'processing'] scan_frame_parameters.scan_id = scan_frame_parameters.scan_id or uuid.uuid4( ) grab_synchronized_info = scan_controller.grab_synchronized_get_info( scan_frame_parameters=scan_frame_parameters, camera=camera, camera_frame_parameters=camera_frame_parameters) camera_data_channel: typing.Optional[ MultiAcquire.CameraDataChannel] = None scan_data_channel: typing.Optional[ MultiAcquire.ScanDataChannel] = None channels_ready_event = threading.Event() def create_channels() -> None: assert camera assert scan_controller nonlocal camera_data_channel, scan_data_channel stack_metadata_keys = getattr(camera.camera, 'stack_metadata_keys', None) camera_data_channel = MultiAcquire.CameraDataChannel( document_model, camera.display_name, grab_synchronized_info, multi_acquire_parameters, multi_acquire_settings, current_parameters_index, stack_metadata_keys=stack_metadata_keys) enabled_channels = scan_controller.get_enabled_channels( ) enabled_channel_names = [ scan_controller.data_channels[i].name or str() for i in enabled_channels ] scan_data_channel = MultiAcquire.ScanDataChannel( document_model, enabled_channel_names, grab_synchronized_info, multi_acquire_parameters, multi_acquire_settings, current_parameters_index) camera_data_channel.start() scan_data_channel.start() channels_ready_event.set() self.document_controller.queue_task(create_channels) assert channels_ready_event.wait(10) assert camera_data_channel assert scan_data_channel sequence_behavior = MultiAcquire.SequenceBehavior( multi_acquire_controller, current_parameters_index) si_sequence_behavior = MultiAcquire.SISequenceBehavior( None, None, sequence_behavior, 1) handler = MultiAcquire.SISequenceAcquisitionHandler( camera, camera_data_channel, camera_frame_parameters, scan_controller, scan_data_channel, scan_frame_parameters, si_sequence_behavior) listener = handler.camera_data_channel.progress_updated_event.listen( multi_acquire_controller.set_progress_counter) def finish_fn() -> None: listener.close() def close_channels() -> None: handler.camera_data_channel.stop() handler.scan_data_channel.stop() self.document_controller.queue_task(close_channels) handler.finish_fn = finish_fn return handler self.__acquisition_thread = threading.Thread( target=multi_acquire_controller. start_multi_acquire_spectrum_image, args=(create_acquisition_handler, )) self.__acquisition_thread.start() def settings_button_clicked() -> None: if not self.settings_window_open: self.settings_window_open = True self.show_config_box() def help_clicked() -> None: webbrowser.open( 'https://nionswift-instrumentation.readthedocs.io/en/latest/userguide.html#multi-acquire-panel', new=2) def camera_changed( current_item: camera_base.CameraHardwareSource) -> None: multi_acquire_controller = self.multi_acquire_controller if current_item and multi_acquire_controller: multi_acquire_controller.settings[ 'camera_hardware_source_id'] = current_item.hardware_source_id if current_item.features.get("has_masked_sum_option"): self.binning_choice_combo_box.items = [ 'Spectra', 'Images', 'MultiEELS Spectra', 'Virtual Detectors' ] else: self.binning_choice_combo_box.items = [ 'Spectra', 'Images', 'MultiEELS Spectra' ] binning_changed( typing.cast(str, self.binning_choice_combo_box.current_item)) def binning_changed(current_item: str) -> None: multi_acquire_controller = self.multi_acquire_controller if not multi_acquire_controller: return if not self.__acquisition_running: self.start_button._widget.enabled = True if current_item == 'Spectra': multi_acquire_controller.settings['processing'] = 'sum_project' multi_acquire_controller.settings[ 'use_multi_eels_calibration'] = False elif current_item == 'Images': multi_acquire_controller.settings['processing'] = None multi_acquire_controller.settings[ 'use_multi_eels_calibration'] = False elif current_item == 'MultiEELS Spectra': multi_acquire_controller.settings['processing'] = 'sum_project' multi_acquire_controller.settings[ 'use_multi_eels_calibration'] = True elif current_item == 'Virtual Detectors': multi_acquire_controller.settings['processing'] = 'sum_masked' multi_acquire_controller.settings[ 'use_multi_eels_calibration'] = False self.start_button._widget.enabled = False camera_choice_row = ui.create_row_widget() self.binning_choice_combo_box = ui.create_combo_box_widget() # Delay connecting the callback functions because otherwise loading the plugin fails because "start button" is not defined yet self.binning_choice_combo_box.items = [ 'Spectra', 'Images', 'MultiEELS Spectra' ] sliders_icon_png = pkgutil.get_data(__name__, "resources/sliders_icon_24.png") assert sliders_icon_png settings_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes(sliders_icon_png, "png")) settings_widget = ui._ui.create_canvas_widget(properties={ "height": 24, "width": 24 }) settings_widget.canvas_item.add_canvas_item(settings_button) settings_button.on_button_clicked = settings_button_clicked help_icon_png = pkgutil.get_data(__name__, "resources/help_icon_24.png") assert help_icon_png help_button = CanvasItem.BitmapButtonCanvasItem( CanvasItem.load_rgba_data_from_bytes(help_icon_png, "png")) help_widget = ui._ui.create_canvas_widget(properties={ "height": 24, "width": 24 }) help_widget.canvas_item.add_canvas_item(help_button) help_button.on_button_clicked = help_clicked self.camera_choice_combo_box = ui.create_combo_box_widget( item_text_getter=lambda camera: typing.cast( str, getattr(camera, 'display_name'))) camera_choice_row.add_spacing(5) camera_choice_row.add(self.camera_choice_combo_box) camera_choice_row.add_spacing(10) camera_choice_row.add(self.binning_choice_combo_box) camera_choice_row.add_stretch() camera_choice_row.add_spacing(10) typing.cast(UserInterface.BoxWidget, camera_choice_row._widget).add(help_widget) camera_choice_row.add_spacing(10) typing.cast(UserInterface.BoxWidget, camera_choice_row._widget).add(settings_widget) camera_choice_row.add_spacing(10) self.update_camera_list() self.update_current_camera() self.__settings_changed_event_listener = self.multi_acquire_controller.settings.settings_changed_event.listen( self.update_current_camera) self.__settings_changed_event_listener_2 = self.multi_acquire_controller.settings.settings_changed_event.listen( self.update_binning_combo_box) def component_changed(component: typing.Any, component_types: typing.Set[str]) -> None: if 'camera_hardware_source' in component_types: self.update_camera_list() self.__component_registered_event_listener = Registry.listen_component_registered_event( component_changed) self.__component_unregistered_event_listener = Registry.listen_component_unregistered_event( component_changed) change_parameters_row = ui.create_row_widget() change_parameters_row.add_spacing(5) change_parameters_row.add( ui.create_label_widget('MultiAcquire parameters:')) change_parameters_row.add_stretch() change_parameters_row.add_spacing(20) parameter_description_row = ui.create_row_widget() parameter_description_row.add_spacing(5) parameter_description_row.add(ui.create_label_widget('#')) parameter_description_row.add_spacing(20) offset_label = ui.create_label_widget('Offset') parameter_description_row.add(offset_label) parameter_description_row.add_stretch() parameter_description_row.add(ui.create_label_widget('Exposure (ms)')) parameter_description_row.add_stretch() parameter_description_row.add_stretch() parameter_description_row.add_stretch() frames_label = ui.create_label_widget('Frames') parameter_description_row.add(frames_label) parameter_description_row.add_stretch() def update_offset_label() -> None: multi_acquire_controller = self.multi_acquire_controller if not multi_acquire_controller: return if multi_acquire_controller.settings['shift_each_sequence_slice']: offset_label.text = 'Offset (per frame) ' else: offset_label.text = 'Offset ' if multi_acquire_controller.settings['sum_frames']: frames_label.text = 'Frames (summed)' else: frames_label.text = 'Frames ' update_offset_label() self.__settings_changed_event_listener_3 = self.multi_acquire_controller.settings.settings_changed_event.listen( update_offset_label) add_remove_parameters_row = ui.create_row_widget() add_parameters_button = ui.create_push_button_widget('+') add_parameters_button._widget.set_property('width', 40) add_parameters_button.on_clicked = self.multi_acquire_controller.add_spectrum remove_parameters_button = ui.create_push_button_widget('-') remove_parameters_button._widget.set_property('width', 40) remove_parameters_button.on_clicked = self.multi_acquire_controller.remove_spectrum add_remove_parameters_row.add_spacing(5) add_remove_parameters_row.add(add_parameters_button) add_remove_parameters_row.add_spacing(5) add_remove_parameters_row.add(remove_parameters_button) add_remove_parameters_row.add_spacing(90) self.progress_bar = ui.create_progress_bar_widget() add_remove_parameters_row.add(self.progress_bar) add_remove_parameters_row.add_spacing(5) time_estimate_row = ui.create_row_widget() time_estimate_row.add_spacing(6) self.time_estimate_label = ui.create_label_widget() time_estimate_row.add(self.time_estimate_label) time_estimate_row.add_spacing(5) time_estimate_row.add_stretch() self.si_time_estimate_label = ui.create_label_widget() time_estimate_row.add(self.si_time_estimate_label) time_estimate_row.add_spacing(6) self.multi_acquire_controller.stem_controller = self.stem_controller self.multi_acquire_controller.scan_controller = self.scan_controller def frame_parameters_changed( profile_index: int, frame_parameters: scan_base.ScanFrameParameters) -> None: self.update_time_estimate() if self.scan_controller: self.__scan_frame_parameters_changed_event_listener = self.scan_controller.frame_parameters_changed_event.listen( frame_parameters_changed) self.update_camera_list() self.start_button = ui.create_push_button_widget('Start MultiAcquire') self.start_button.on_clicked = start_clicked self.start_si_button = ui.create_push_button_widget( 'Start MultiAcquire spectrum image') self.start_si_button.on_clicked = start_si_clicked start_row = ui.create_row_widget() start_row.add_spacing(5) start_row.add(self.start_button) start_row.add_spacing(5) start_row.add_stretch() start_row.add(self.start_si_button) start_row.add_spacing(5) column = ui.create_column_widget() column.add_spacing(5) column.add(camera_choice_row) column.add_spacing(10) column.add(change_parameters_row) column.add_spacing(5) column.add(parameter_description_row) column.add_spacing(10) self.parameter_column = ui.create_column_widget() for spectrum_parameters in self.multi_acquire_controller.spectrum_parameters: line = self.create_parameter_line(spectrum_parameters) self.parameter_column.add(line) column.add(self.parameter_column) column.add_spacing(5) column.add(add_remove_parameters_row) column.add_spacing(15) column.add(time_estimate_row) column.add_spacing(5) column.add(start_row) column.add_spacing(10) column.add_stretch() # Make sure we update the available options in the binning combo box. camera_changed( typing.cast(camera_base.CameraHardwareSource, self.camera_choice_combo_box.current_item)) # Make sure the binning combo box shows the actual settings self.update_binning_combo_box() # Delay setting up the callbacks until the end to make sure loading the plugin doesn't fail due to missing attributes self.binning_choice_combo_box.on_current_item_changed = binning_changed self.camera_choice_combo_box.on_current_item_changed = camera_changed return column