コード例 #1
0
 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))
コード例 #2
0
ファイル: HistogramPanel.py プロジェクト: meyer9/nionswift
    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
コード例 #3
0
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)
コード例 #4
0
ファイル: ToolbarPanel.py プロジェクト: cmeyer/nionswift
    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)
コード例 #5
0
    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
コード例 #6
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
コード例 #7
0
ファイル: Widgets.py プロジェクト: Brow71189/nionui
    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
コード例 #8
0
    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)
コード例 #9
0
    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)
コード例 #10
0
    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
コード例 #11
0
ファイル: ToolbarPanel.py プロジェクト: cmeyer/nionswift
    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)
コード例 #12
0
            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)
コード例 #13
0
 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})
コード例 #14
0
    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
コード例 #15
0
ファイル: Widgets.py プロジェクト: Brow71189/nionui
    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
コード例 #16
0
    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
コード例 #17
0
    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)
コード例 #18
0
    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
コード例 #19
0
ファイル: ToolbarPanel.py プロジェクト: cmeyer/nionswift
 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)
コード例 #20
0
ファイル: Widgets.py プロジェクト: Brow71189/nionui
 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)
コード例 #21
0
    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
コード例 #22
0
    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
コード例 #23
0
 def __init__(self):
     self.on_thumbnail_data_changed = None
     self.__thumbnail_data = None
     self.overlay_canvas_item = CanvasItem.EmptyCanvasItem()
コード例 #24
0
    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)
コード例 #25
0
ファイル: DataPanel.py プロジェクト: shabihsherjeel/nionswift
    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)
コード例 #26
0
ファイル: DataPanel.py プロジェクト: shabihsherjeel/nionswift
    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
コード例 #27
0
    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)
コード例 #28
0
 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(
     )
コード例 #29
0
    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")
コード例 #30
0
    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