예제 #1
0
 def __init__(self, notification: Notification.Notification) -> None:
     self.notification = notification
     u = Declarative.DeclarativeUI()
     self.ui_view = u.create_row(
         u.create_column(
             u.create_row(
                 u.create_label(text="@binding(notification.task_name)", color="#3366CC"),
                 u.create_stretch(),
                 {"type": "notification_char_button", "text": " \N{MULTIPLICATION X} ", "on_clicked": "handle_dismiss"},
                 spacing=8
             ),
             u.create_row(
                 u.create_label(text="@binding(notification.title)", font="bold"),
                 u.create_stretch(),
                 spacing=8
             ),
             u.create_row(
                 u.create_label(text="@binding(notification.text)", word_wrap=True, width=440),
                 u.create_stretch(),
                 spacing=8
             ),
             u.create_divider(orientation="horizontal"),
             spacing=4,
         ),
     )
예제 #2
0
 def get_ui(self, version):
     actual_version = "1.0.0"
     if Utility.compare_versions(version, actual_version) > 0:
         raise NotImplementedError(
             "API requested version %s is greater than %s." %
             (version, actual_version))
     return Declarative.DeclarativeUI()
예제 #3
0
            def resources(self):
                u = Declarative.DeclarativeUI()

                driver_display_name_label = u.create_label(text="@binding(driver_display_name)")

                device_id_field = u.create_line_edit(text="@binding(settings.device_id)", width=180)

                display_name_field = u.create_line_edit(text="@binding(settings.name)", width=240)

                edit_group_content = u.create_component_instance("edit_group")

                edit_group = u.create_group(edit_group_content, margin=8)

                edit_row = u.create_row(edit_group, u.create_stretch())

                apply_button = u.create_push_button(name="apply_button", text=_("Apply"), on_clicked="apply")
                revert_button = u.create_push_button(name="revert_button", text=_("Revert"), on_clicked="revert")
                remove_button = u.create_push_button(text=_("Remove"), on_clicked="remove")
                remove_row = u.create_row(apply_button, revert_button, remove_button, u.create_stretch())

                label_column = u.create_column(u.create_label(text=_("Driver:")), u.create_label(text=_("Device ID:")), u.create_label(text=_("Display Name:")), spacing=4)
                field_column = u.create_column(driver_display_name_label, device_id_field, display_name_field, spacing=4)

                content_row = u.create_row(label_column, field_column, u.create_stretch(), spacing=12)

                content = u.create_column(content_row, edit_row, remove_row, spacing=8)

                component = u.define_component(content=content, component_id="section")

                return {"section": component}
예제 #4
0
 def resources(self) -> typing.Mapping[str, typing.Any]:
     ui = Declarative.DeclarativeUI()
     field_label = ui.create_label(name="label_widget")
     field_line_edit = ui.create_line_edit(name="value_widget", on_editing_finished="value_changed")
     field = ui.create_row(field_label, field_line_edit, ui.create_stretch(), spacing=8)
     field_events = [{"event": "on_value_changed", "parameters": ["value"]}]
     field_component = ui.define_component(content=field, events=field_events)
     return {"field": field_component}
예제 #5
0
    def __init__(
            self, document_controller: DocumentController.DocumentController
    ) -> None:
        self.document_controller = document_controller

        activities = ListModel.ListModel[Activity.Activity]()
        stack_index = Model.PropertyModel[int](0)

        def activity_appended(activity: Activity.Activity) -> None:
            async def append_activity(activity: Activity.Activity) -> None:
                activities.append_item(activity)

            document_controller.event_loop.create_task(
                append_activity(activity))

        def activity_finished(activity: Activity.Activity) -> None:
            async def finish_activity(activity: Activity.Activity) -> None:
                activities.remove_item(activities.items.index(activity))

            document_controller.event_loop.create_task(
                finish_activity(activity))

        self.__activity_appended_listener = Activity.activity_appended_event.listen(
            activity_appended)
        self.__activity_finished_listener = Activity.activity_finished_event.listen(
            activity_finished)

        self.activities = activities
        self.stack_index = stack_index

        def activity_changed(key: str, value: Activity.Activity,
                             index: int) -> None:
            stack_index.value = 1 if len(activities.items) > 0 else 0

        self.__activity_inserted_listener = self.activities.item_inserted_event.listen(
            activity_changed)
        self.__activity_removed_listener = self.activities.item_removed_event.listen(
            activity_changed)

        u = Declarative.DeclarativeUI()
        self.ui_view = u.create_column(
            u.create_label(text=_("** Activity Panel is Beta **"),
                           color="darkred",
                           font="bold"),
            u.create_stack(u.create_column(
                u.create_label(text=_("No activities.")),
                u.create_stretch(),
            ),
                           u.create_column(
                               u.create_column(items="activities.items",
                                               item_component_id="activity",
                                               spacing=6),
                               u.create_stretch(),
                           ),
                           current_index="@binding(stack_index.value)"),
            u.create_stretch(),
            spacing=8,
            margin=8)
예제 #6
0
def main(args, bootstrap_args):
    ui = Declarative.DeclarativeUI()
    button = ui.create_push_button(text=_("Hello World"),
                                   on_clicked="button_clicked")
    label = ui.create_label(name="label_item", text=_("Not Clicked"))
    column = ui.create_column(button, label, spacing=8)
    window = ui.create_window(column, title=_("Hello World"), margin=12)
    handler = Handler()
    return Declarative.run_ui(args, bootstrap_args, window, handler)
예제 #7
0
 def __init__(self, actions: typing.Sequence[Window.Action], document_controller: DocumentController.DocumentController, **kwargs: typing.Any) -> None:
     self.__document_controller = document_controller
     u = Declarative.DeclarativeUI()
     top_row = [self.__create_action_button(actions[i]) for i in range(0, len(actions), 2)]
     bottom_row = [self.__create_action_button(actions[i]) for i in range(1, len(actions), 2)]
     self.ui_view = u.create_column(u.create_spacing(4),
                                    u.create_row(*top_row),
                                    u.create_row(*bottom_row),
                                    u.create_spacing(4), u.create_stretch())
예제 #8
0
 def __init__(self, activity: Activity.Activity) -> None:
     self.activity = activity
     u = Declarative.DeclarativeUI()
     self.ui_view = u.create_row(u.create_label(
         text="@binding(activity.displayed_title)",
         word_wrap=True,
         width=296),
                                 u.create_stretch(),
                                 spacing=8)
예제 #9
0
def main(
    args: typing.Sequence[typing.Any],
    bootstrap_args: typing.Mapping[str, typing.Any]
) -> Application.BaseApplication:
    u = Declarative.DeclarativeUI()

    page_list = [
        (Buttons, "buttons", _("Buttons")),
        (CheckBoxes, "check_boxes", _("Check Boxes")),
        (ComboBoxes, "combo_boxes", _("Combo Boxes")),
        (Bindings, "bindings", _("Bindings")),
        (Compositions, "compositions", _("Compositions")),
        (Converters, "converters", _("Converters")),
        (Groups, "groups", _("Groups")),
        (LineEdits, "line_edits", _("Line Edits")),
        (ProgressBars, "progress_bars", _("Progress Bars")),
        (RadioButtons, "radio_buttons", _("Radio Buttons")),
        (Sliders, "sliders", _("Sliders")),
        (Stacks, "stacks", _("Stacks")),
        (StatusBar, "status_bar", _("Status Bar")),
        (Tabs, "tabs", _("Tabs")),
        (ComponentLayout, "component_layout", _("Component Layout")),
        (ComponentStack, "component_stack", _("Component Stack")),
        (ComponentContent, "component_content", _("Component Content")),
        (ComponentPolymorphic, "component_polymorphic",
         _("Component Polymorphic")),
    ]

    handler = Handler(page_list)

    resources = dict()

    pages = list()
    items = list()

    for page_cls, page_id, page_title in page_list:
        resources[page_id] = u.define_component(
            content=typing.cast(typing.Any, page_cls).construct_ui(u))
        instance = u.create_component_instance(page_id)
        pages.append(u.create_column(instance, u.create_stretch()))
        items.append(page_title)

    chooser_combo_box = u.create_combo_box(
        items=items, on_current_index_changed="select_page")

    page_stack = u.create_stack(*pages, name="page_stack")

    page_group = u.create_group(page_stack, margin=8)

    main_column = u.create_column(chooser_combo_box, page_group, spacing=8)

    window = u.create_window(main_column,
                             title=_("UI Demo"),
                             margin=12,
                             resources=resources)

    return Application.run_window(args, bootstrap_args, window, handler)
예제 #10
0
    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)
예제 #11
0
def main(
    args: typing.Sequence[typing.Any],
    bootstrap_args: typing.Mapping[str, typing.Any]
) -> Application.BaseApplication:
    ui = Declarative.DeclarativeUI()
    button = ui.create_push_button(text=_("Hello World"),
                                   on_clicked="button_clicked")
    label = ui.create_label(name="label_item", text=_("Not Clicked"))
    column = ui.create_column(button, label, spacing=8)
    window = ui.create_window(column, title=_("Hello World"), margin=12)
    return Application.run_window(args, bootstrap_args, window, Handler())
예제 #12
0
 def resources(self) -> typing.Mapping[str, typing.Any]:
     # when a new mode is added to the model.modes structured array, the stack will create a new child to
     # display/edit the new mode. the declarative UI for the new child is returned here under the "mode" key which is
     # the same as the "item_component_id" passed to "create_stack". the handler for the new child is returned in
     # "create_handler".
     u = Declarative.DeclarativeUI()
     title_label = u.create_label(name="title_label_widget")
     balance_field = u.create_line_edit(text="@binding(mode.balance, converter=balance_converter)")
     remove_button = u.create_push_button(text="X", on_clicked="remove")
     row = u.create_row(title_label, balance_field, remove_button, u.create_stretch(), spacing=8)
     component = u.define_component(content=row)
     return {"mode": component}
예제 #13
0
 def get_resource(self, resource_id: str, container: typing.Optional[typing.Any] = None, item: typing.Any = None) -> typing.Optional[Declarative.UIDescription]:
     u = Declarative.DeclarativeUI()
     if resource_id == "rectangle":
         width_row = u.create_row(u.create_label(text="Width:"), u.create_label(text="@binding(shape.width)"), spacing=8)
         height_row = u.create_row(u.create_label(text="Height:"), u.create_label(text="@binding(shape.height)"), spacing=8)
         return u.define_component(u.create_group(u.create_column(width_row, height_row, spacing=8), title="@binding(shape.label)"))
     elif resource_id == "circle":
         radius_row = u.create_row(u.create_label(text="Radius:"), u.create_label(text="@binding(shape.radius)"), spacing=8)
         return u.define_component(u.create_group(u.create_column(radius_row, spacing=8), title="@binding(shape.label)"))
     elif resource_id == "interval":
         left_row = u.create_row(u.create_label(text="Left:"), u.create_label(text="@binding(shape.left)"), spacing=8)
         right_row = u.create_row(u.create_label(text="Right:"), u.create_label(text="@binding(shape.right)"), spacing=8)
         return u.define_component(u.create_group(u.create_column(left_row, right_row, spacing=8), title="@binding(shape.label)"))
     return None
예제 #14
0
    def show_ok_cancel_dialog(
        self,
        title: str,
        message: str,
        *,
        ok_text: str = None,
        cancel_text: str = None,
        completion_fn: typing.Optional[typing.Callable[[bool], None]] = None
    ) -> None:
        u = Declarative.DeclarativeUI()
        error_message = u.create_label(text=message)
        button_row = u.create_row(
            u.create_stretch(),
            u.create_push_button(text=cancel_text or _("Cancel"),
                                 on_clicked="handle_reject"),
            u.create_push_button(text=ok_text or _("OK"),
                                 on_clicked="handle_accept"),
            spacing=12)
        main_column = u.create_column(error_message,
                                      button_row,
                                      spacing=8,
                                      width=380)
        window = u.create_window(main_column,
                                 title=title,
                                 margin=12,
                                 window_style="tool")

        class OkCancelHandler(Declarative.WindowHandler):
            def __init__(self):
                super().__init__(completion_fn=self.handle_close)
                self.__result = False

            def handle_close(self) -> None:
                if callable(completion_fn):
                    completion_fn(self.__result)

            def handle_accept(
                    self,
                    widget: typing.Optional[Declarative.UIWidget]) -> None:
                self.__result = True
                self.close_window(widget)

            def handle_reject(
                    self,
                    widget: typing.Optional[Declarative.UIWidget]) -> None:
                self.__result = False
                self.close_window(widget)

        OkCancelHandler().run(window, app=self)
예제 #15
0
    def build(self, ui: UserInterface.UserInterface, event_loop: asyncio.AbstractEventLoop,
              **kwargs: typing.Any) -> Declarative.DeclarativeWidget:
        u = Declarative.DeclarativeUI()

        class Handler(Declarative.HandlerLike):
            def __init__(self, ui_view: Declarative.UIDescription) -> None:
                self.ui_view = ui_view

            def close(self) -> None:
                pass

        no_content_row = u.create_row(u.create_stretch(), u.create_label(text=_("No Preferences Available")),
                                      u.create_stretch())
        content = u.create_column(no_content_row)
        return Declarative.DeclarativeWidget(ui, event_loop, Handler(content))
예제 #16
0
 def resources(self) -> typing.Mapping[str, typing.Any]:
     ui = Declarative.DeclarativeUI()
     title_label = ui.create_label(name="title_label_widget")
     count_label = ui.create_label(name="count_label_widget")
     increase_button = ui.create_push_button(text="++",
                                             on_clicked="increase_count")
     decrease_button = ui.create_push_button(text="--",
                                             on_clicked="decrease_count")
     remove_button = ui.create_push_button(text="X", on_clicked="remove")
     row = ui.create_row(title_label,
                         count_label,
                         increase_button,
                         decrease_button,
                         remove_button,
                         ui.create_stretch(),
                         spacing=8)
     component = ui.define_component(content=row)
     return {"section": component}
예제 #17
0
    def get_editor_description(self):
        u = Declarative.DeclarativeUI()

        camera_names = [
            cam.get('product', cam.get('serial'))
            for cam in self.available_cameras
        ]
        camera_index_combo = u.create_combo_box(
            items=camera_names,
            current_index="@binding(camera_index_model.value)")

        label_column = u.create_column(
            u.create_label(text=_("Select camera from list:")), spacing=4)
        field_column = u.create_column(camera_index_combo, spacing=4)

        return u.create_row(label_column,
                            field_column,
                            u.create_stretch(),
                            spacing=12)
예제 #18
0
 def __create_action_button(self, action: Window.Action) -> Declarative.UIDescription:
     action_id = action.action_id
     action_identifier = action_id.replace(".", "_")
     icon_png = getattr(action, "action_command_icon_png", None)
     if icon_png is not None:
         icon_data = CanvasItem.load_rgba_data_from_bytes(icon_png)
     else:
         icon_data = numpy.full((48, 64), 0x00FFFFFF, dtype=numpy.uint32)
         icon_data[8:40, 8:56] = 0xFFC0C0C0
     icon_property = "icon_" + action_identifier
     setattr(self, icon_property, icon_data)
     tool_tip = getattr(action, "action_tool_tip", getattr(action, "action_name", None))
     key_shortcut = Window.action_shortcuts.get(action_id, dict()).get("display_panel", None)
     if tool_tip and key_shortcut:
         tool_tip += f" ({key_shortcut})"
     u = Declarative.DeclarativeUI()
     perform_function = "perform_" + action_identifier
     def perform_action(widget: UserInterface.Widget) -> None:
         self.__document_controller.perform_action(action_id)
     setattr(self, perform_function, perform_action)
     return u.create_image(image=f"@binding({icon_property})", height=24, width=32, on_clicked=f"{perform_function}", tool_tip=tool_tip)
    def get_editor_description(self):
        u = Declarative.DeclarativeUI()

        url_field = u.create_line_edit(text="@binding(settings.url)",
                                       width=360)
        camera_index_combo = u.create_combo_box(
            items=["None", "0", "1", "2", "3"],
            current_index="@binding(camera_index_model.value)")

        label_column = u.create_column(
            u.create_label(text=_("URL:")),
            u.create_label(text=_("Camera Index (0 for none):")),
            spacing=4)
        field_column = u.create_column(url_field,
                                       camera_index_combo,
                                       spacing=4)

        return u.create_row(label_column,
                            field_column,
                            u.create_stretch(),
                            spacing=12)
예제 #20
0
 def show_ok_dialog(
     self,
     title: str,
     message: str,
     *,
     completion_fn: typing.Optional[typing.Callable[[],
                                                    None]] = None) -> None:
     u = Declarative.DeclarativeUI()
     error_message = u.create_label(text=message)
     button_row = u.create_row(
         u.create_stretch(),
         u.create_push_button(text=_("OK"), on_clicked="close_window"))
     main_column = u.create_column(error_message,
                                   button_row,
                                   spacing=8,
                                   width=300)
     window = u.create_window(main_column,
                              title=title,
                              margin=12,
                              window_style="tool")
     Declarative.WindowHandler(completion_fn=completion_fn).run(window,
                                                                app=self)
예제 #21
0
    def __init__(self, app: Application.BaseApplication) -> None:
        super().__init__()

        notifications = ListModel.ListModel[Notification.Notification]()
        stack_index = Model.PropertyModel[int](0)

        self.notifications = notifications
        self.stack_index = stack_index

        def notification_changed(key: str, value: Notification.Notification, index: int) -> None:
            stack_index.value = 1 if len(notifications.items) > 0 else 0

        self.__notification_inserted_listener = self.notifications.item_inserted_event.listen(notification_changed)
        self.__notification_removed_listener = self.notifications.item_removed_event.listen(notification_changed)

        u = Declarative.DeclarativeUI()
        main_column = u.create_column(
            u.create_stack(
                u.create_column(
                    u.create_label(text=_("No notifications.")),
                    u.create_stretch(),
                ),
                u.create_column(
                    u.create_column(items="notifications.items", item_component_id="notification", spacing=6),
                    u.create_stretch(),
                ),
                current_index="@binding(stack_index.value)"
            ),
            u.create_stretch(),
            spacing=8,
            width=460,
            min_height=260,
        )

        window = u.create_window(main_column, title=_("Notifications"), margin=8, window_style="tool")
        self.run(window, app=app, persistent_id="notification_dialog")
    def build(self, ui: UserInterface.UserInterface,
              event_loop: asyncio.AbstractEventLoop,
              **kwargs: typing.Any) -> Declarative.DeclarativeWidget:
        u = Declarative.DeclarativeUI()

        video_device_factories: typing.List[
            video_base.VideoDeviceFactoryLike] = list(
                Registry.get_components_by_type("video_device_factory"))

        class Handler(Declarative.HandlerLike):
            def __init__(
                self, ui_view: Declarative.UIDescription,
                video_sources: ListModel.ListModel[
                    video_base.VideoHardwareSource]
            ) -> None:
                self.ui_view = ui_view
                self.video_sources = video_sources
                self.video_source_type_index = Model.PropertyModel(0)

            def close(self) -> None:
                pass

            def create_new_video_device(self,
                                        widget: UserInterface.Widget) -> None:
                video_base.video_configuration.create_hardware_source(
                    video_device_factories[self.video_source_type_index.value
                                           or 0])

            def create_handler(
                self,
                component_id: str,
                container: typing.Any = None,
                item: typing.Any = None,
                **kwargs: typing.Any
            ) -> typing.Optional[Declarative.HandlerLike]:
                class SectionHandler:
                    def __init__(
                        self, container: typing.Any,
                        hardware_source: video_base.VideoHardwareSource
                    ) -> None:
                        self.container = container
                        self.hardware_source = hardware_source
                        self.settings = video_base.video_configuration.get_settings_model(
                            hardware_source)
                        self.settings_original = copy.deepcopy(self.settings)
                        self.needs_saving_model = Model.PropertyModel(False)
                        self.property_changed_event = Event.Event()
                        # these will be assigned by declarative setup
                        self.apply_button: typing.Optional[
                            UserInterface.PushButtonWidget] = None
                        self.revert_button: typing.Optional[
                            UserInterface.PushButtonWidget] = None

                        def settings_changed(property_name: str) -> None:
                            self.needs_saving_model.value = True

                        self.__settings_changed_event_listener = self.settings.property_changed_event.listen(
                            settings_changed) if self.settings else None

                        def needs_saving_model_changed(
                                property_name: str) -> None:
                            if self.apply_button:
                                self.apply_button.enabled = self.needs_saving_model.value or False
                            if self.revert_button:
                                self.revert_button.enabled = self.needs_saving_model.value or False

                        self.__needs_saving_changed_event_listener = self.needs_saving_model.property_changed_event.listen(
                            needs_saving_model_changed)

                    def close(self) -> None:
                        if self.__settings_changed_event_listener:
                            self.__settings_changed_event_listener.close()
                            self.__settings_changed_event_listener = None

                    def init_handler(self) -> None:
                        if self.apply_button:
                            self.apply_button.enabled = self.needs_saving_model.value or False
                        if self.revert_button:
                            self.revert_button.enabled = self.needs_saving_model.value or False

                    def create_handler(
                        self,
                        component_id: str,
                        container: typing.Any = None,
                        item: typing.Any = None,
                        **kwargs: typing.Any
                    ) -> typing.Optional[Declarative.HandlerLike]:
                        if component_id == "edit_group":
                            if self.__video_device_factory:
                                return typing.cast(
                                    Declarative.HandlerLike,
                                    self.__video_device_factory.
                                    create_editor_handler(self.settings))
                            else:
                                return self
                        raise ValueError("Unable to create component.")

                    @property
                    def resources(self) -> typing.Mapping[str, typing.Any]:
                        if self.__video_device_factory:
                            content = self.__video_device_factory.get_editor_description(
                            )
                        else:
                            content = u.create_label(text=_("Not Available"))

                        component = u.define_component(
                            content=content, component_id="edit_group")

                        return {"edit_group": component}

                    @property
                    def __video_device_factory(
                        self
                    ) -> typing.Optional[video_base.VideoDeviceFactoryLike]:
                        for video_device_factory in video_device_factories:
                            if video_device_factory.factory_id == getattr(
                                    self.settings, "driver", None):
                                return video_device_factory
                        return None

                    @property
                    def driver_display_name(self) -> str:
                        video_device_factory = self.__video_device_factory
                        return video_device_factory.display_name if video_device_factory else _(
                            "Unknown")

                    def apply(self, widget: UserInterface.Widget) -> None:
                        settings = self.settings
                        if settings:
                            video_base.video_configuration.set_settings_model(
                                self.hardware_source, settings)
                            self.needs_saving_model.value = False

                    def revert(self, widget: UserInterface.Widget) -> None:
                        if self.settings:
                            self.settings.copy_from(self.settings_original)
                            self.needs_saving_model.value = False

                    def remove(self, widget: UserInterface.Widget) -> None:
                        video_base.video_configuration.remove_hardware_source(
                            self.hardware_source)

                if component_id == "section":
                    return SectionHandler(container, item)

                raise ValueError("Unable to create component.")

            @property
            def resources(self) -> typing.Mapping[str, typing.Any]:
                u = Declarative.DeclarativeUI()

                driver_display_name_label = u.create_label(
                    text="@binding(driver_display_name)")

                device_id_field = u.create_line_edit(
                    text="@binding(settings.device_id)", width=180)

                display_name_field = u.create_line_edit(
                    text="@binding(settings.name)", width=240)

                edit_group_content = u.create_component_instance("edit_group")

                edit_group = u.create_group(edit_group_content, margin=8)

                edit_row = u.create_row(edit_group, u.create_stretch())

                apply_button = u.create_push_button(name="apply_button",
                                                    text=_("Apply"),
                                                    on_clicked="apply")
                revert_button = u.create_push_button(name="revert_button",
                                                     text=_("Revert"),
                                                     on_clicked="revert")
                remove_button = u.create_push_button(text=_("Remove"),
                                                     on_clicked="remove")
                remove_row = u.create_row(apply_button, revert_button,
                                          remove_button, u.create_stretch())

                label_column = u.create_column(
                    u.create_label(text=_("Driver:")),
                    u.create_label(text=_("Device ID:")),
                    u.create_label(text=_("Display Name:")),
                    spacing=4)
                field_column = u.create_column(driver_display_name_label,
                                               device_id_field,
                                               display_name_field,
                                               spacing=4)

                content_row = u.create_row(label_column,
                                           field_column,
                                           u.create_stretch(),
                                           spacing=12)

                content = u.create_column(content_row,
                                          edit_row,
                                          remove_row,
                                          spacing=8)

                component = u.define_component(content=content,
                                               component_id="section")

                return {"section": component}

        sources_column = u.create_column(items="video_sources.items",
                                         item_component_id="section",
                                         spacing=8)

        sources_content = u.create_scroll_area(
            u.create_column(sources_column, u.create_stretch()))

        video_source_types = [
            video_device_factory.display_name
            for video_device_factory in video_device_factories
        ]

        video_source_type_combo = u.create_combo_box(
            items=video_source_types,
            current_index="@binding(video_source_type_index.value)")

        button_row = u.create_row(u.create_stretch(),
                                  video_source_type_combo,
                                  u.create_push_button(
                                      text=_("New"),
                                      on_clicked="create_new_video_device"),
                                  spacing=8)

        content = u.create_column(sources_content, button_row)

        return Declarative.DeclarativeWidget(
            ui, event_loop,
            Handler(content, self.__video_configuration.video_sources))
예제 #23
0
    def __init__(self,
                 document_controller: DocumentController.DocumentController):
        super().__init__()

        self.__document_controller = document_controller

        self.title_model: Model.PropertyModel[str] = Model.PropertyModel(
            _("Generated Data"))
        self.data_type_model: Model.PropertyModel[int] = Model.PropertyModel(0)
        self.is_sequence_model: Model.PropertyModel[int] = Model.PropertyModel(
            0)
        self.collection_rank_model: Model.PropertyModel[
            int] = Model.PropertyModel(0)
        self.datum_rank_model: Model.PropertyModel[int] = Model.PropertyModel(
            1)

        self.sequence_size_model: Model.PropertyModel[
            int] = Model.PropertyModel(16)

        self.line_size_model: Model.PropertyModel[int] = Model.PropertyModel(
            512)

        self.scan_width_model: Model.PropertyModel[int] = Model.PropertyModel(
            256)
        self.scan_height_model: Model.PropertyModel[int] = Model.PropertyModel(
            256)

        self.spectrum_size_model: Model.PropertyModel[
            int] = Model.PropertyModel(1024)

        self.image_width_model: Model.PropertyModel[int] = Model.PropertyModel(
            1024)
        self.image_height_model: Model.PropertyModel[
            int] = Model.PropertyModel(1024)

        self.array_width_model: Model.PropertyModel[int] = Model.PropertyModel(
            1024)
        self.array_height_model: Model.PropertyModel[
            int] = Model.PropertyModel(256)

        self.int_converter = Converter.IntegerToStringConverter()

        u = Declarative.DeclarativeUI()

        title_row = u.create_row(
            u.create_label(text=_("Title")),
            u.create_line_edit(text="@binding(title_model.value)"),
            u.create_stretch(),
            spacing=8)

        data_type_row = u.create_row(
            u.create_label(text=_("Data Type")),
            u.create_combo_box(
                items=["Float (32-bit)"],
                current_index="@binding(data_type_model.value)"),
            u.create_stretch(),
            spacing=8)

        is_sequence_row = u.create_row(
            u.create_label(text=_("Sequence")),
            u.create_combo_box(
                items=["No", "Yes"],
                current_index="@binding(is_sequence_model.value)"),
            u.create_stretch(),
            spacing=8)

        not_sequence_column = u.create_column(
            u.create_row(
                u.create_label(text=_("No Sequence Axis"), enabled=False)))

        sequence_column = u.create_column(
            u.create_row(
                u.create_label(text=_("Sequence Length")),
                u.create_line_edit(
                    text=
                    "@binding(sequence_size_model.value, converter=int_converter)"
                ),
                u.create_stretch(),
                spacing=8), )

        is_sequence_stack = u.create_stack(
            not_sequence_column,
            sequence_column,
            current_index="@binding(is_sequence_model.value)")

        collection_rank_row = u.create_row(
            u.create_label(text=_("Collection Rank")),
            u.create_combo_box(
                items=["0 (none)", "1 (line)", "2 (scan)"],
                current_index="@binding(collection_rank_model.value)"),
            u.create_stretch(),
            spacing=8)

        no_scan_column = u.create_column(
            u.create_row(
                u.create_label(text=_("No Collection Axes"), enabled=False)))

        line_column = u.create_column(
            u.create_row(
                u.create_label(text=_("Line Length")),
                u.create_line_edit(
                    text=
                    "@binding(line_size_model.value, converter=int_converter)"
                ),
                u.create_stretch(),
                spacing=8), )

        scan_column = u.create_column(
            u.create_row(
                u.create_label(text=_("Scan Width")),
                u.create_line_edit(
                    text=
                    "@binding(scan_width_model.value, converter=int_converter)"
                ),
                u.create_label(text=_("Scan Height")),
                u.create_line_edit(
                    text=
                    "@binding(scan_height_model.value, converter=int_converter)"
                ),
                u.create_stretch(),
                spacing=8), )

        collection_stack = u.create_stack(
            no_scan_column,
            line_column,
            scan_column,
            current_index="@binding(collection_rank_model.value)")

        datum_rank_row = u.create_row(
            u.create_label(text=_("Datum Rank")),
            u.create_combo_box(
                items=["1 (spectrum)", "2 (image)", "1+1 (array of 1d)"],
                current_index="@binding(datum_rank_model.value)"),
            u.create_stretch(),
            spacing=8)

        spectrum_column = u.create_column(
            u.create_row(
                u.create_label(text=_("Length")),
                u.create_line_edit(
                    text=
                    "@binding(spectrum_size_model.value, converter=int_converter)"
                ),
                u.create_stretch(),
                spacing=8), )

        image_column = u.create_column(
            u.create_row(
                u.create_label(text=_("Width")),
                u.create_line_edit(
                    text=
                    "@binding(image_width_model.value, converter=int_converter)"
                ),
                u.create_label(text=_("Height")),
                u.create_line_edit(
                    text=
                    "@binding(image_height_model.value, converter=int_converter)"
                ),
                u.create_stretch(),
                spacing=8), )

        array_column = u.create_column(
            u.create_row(
                u.create_label(text=_("Width")),
                u.create_line_edit(
                    text=
                    "@binding(array_width_model.value, converter=int_converter)"
                ),
                u.create_label(text=_("Height")),
                u.create_line_edit(
                    text=
                    "@binding(array_height_model.value, converter=int_converter)"
                ),
                u.create_stretch(),
                spacing=8), )

        datum_stack = u.create_stack(
            spectrum_column,
            image_column,
            array_column,
            current_index="@binding(datum_rank_model.value)")

        button_row = u.create_row(u.create_stretch(),
                                  u.create_push_button(
                                      text=_("Cancel"),
                                      on_clicked="close_window"),
                                  u.create_push_button(text=_("Generate"),
                                                       on_clicked="generate"),
                                  spacing=8)

        main_page = u.create_column(title_row,
                                    data_type_row,
                                    is_sequence_row,
                                    is_sequence_stack,
                                    collection_rank_row,
                                    collection_stack,
                                    datum_rank_row,
                                    datum_stack,
                                    u.create_spacing(26),
                                    button_row,
                                    min_width=320 - 24)

        window = u.create_window(main_page,
                                 title=_("Generate Data"),
                                 margin=12,
                                 window_style="tool")

        self.run(window,
                 parent_window=document_controller,
                 persistent_id="generate_data")
        self.__document_controller.register_dialog(self.window)
예제 #24
0
def calibrate_spectrum(api: API_1_0.API, window: API_1_0.DocumentWindow):
    class UIHandler:
        def __init__(self, data_item: API_1_0.DataItem, src_data_item: API_1_0.DataItem, offset_graphic: API_1_0.Graphic, second_graphic: API_1_0.Graphic, units='eV'):
            self.ev_converter = Converter.PhysicalValueToStringConverter(units)
            self.property_changed_event = Event.Event()
            self.__data_item = data_item
            self.__src_data_item = src_data_item
            self.__offset_graphic = offset_graphic
            self.__second_graphic = second_graphic
            self.__offset_energy = 0
            self.__graphic_updating = False
            self.__second_point = data_item.display_xdata.dimensional_calibrations[0].convert_to_calibrated_value(second_graphic.position * len(data_item.display_xdata.data))
            self.__offset_changed_listener = offset_graphic._graphic.property_changed_event.listen(self.__offset_graphic_changed)
            self.__second_changed_listener = second_graphic._graphic.property_changed_event.listen(self.__second_graphic_changed)

        def close(self):
            self.__offset_changed_listener.close()
            self.__offset_changed_listener = None
            self.__second_changed_listener.close()
            self.__second_changed_listener = None
            self.__data_item = None
            self.__src_data_item = None
            self.__second_graphic = None
            self.__offset_graphic = None

        @property
        def offset_energy(self):
            return self.__offset_energy

        @offset_energy.setter
        def offset_energy(self, offset_energy):
            self.__offset_energy = offset_energy
            self.property_changed_event.fire("offset_energy")
            self.__update_calibration(keep_scale=True)

        @property
        def second_point(self):
            return self.__second_point

        @second_point.setter
        def second_point(self, energy):
            self.__second_point = energy
            self.property_changed_event.fire("second_point")
            self.__update_calibration()

        @contextlib.contextmanager
        def __lock_graphic_updates(self):
            self.__graphic_updating = True
            try:
                yield self.__graphic_updating
            finally:
                self.__graphic_updating = False

        def __update_calibration(self, keep_scale=False):
            dimensional_calibrations = copy.deepcopy(self.__data_item.display_xdata.dimensional_calibrations)
            energy_calibration = dimensional_calibrations[0]
            if keep_scale:
                scale = energy_calibration.scale
            else:
                scale = (self.__second_point - self.__offset_energy) / ((self.__second_graphic.position - self.__offset_graphic.position) * len(self.__data_item.display_xdata.data))
            offset = self.__offset_energy - self.__offset_graphic.position * len(self.__data_item.display_xdata.data) * scale
            energy_calibration.scale = scale
            energy_calibration.offset = offset
            dimensional_calibrations = list(self.__src_data_item.xdata.dimensional_calibrations)
            dimensional_calibrations[-1] = energy_calibration
            self.__src_data_item.set_dimensional_calibrations(dimensional_calibrations)
            offset_graphic_position = (self.offset_energy - offset) / scale / len(self.__data_item.display_xdata.data)
            second_graphic_position = (self.second_point - offset) / scale / len(self.__data_item.display_xdata.data)
            with self.__lock_graphic_updates():
                self.__offset_graphic.position = min(max(0, offset_graphic_position), 0.99)
                self.__second_graphic.position = min(max(0, second_graphic_position), 0.99)

        def __offset_graphic_changed(self, property_name):
            if not self.__graphic_updating:
                self.__update_calibration(keep_scale=True)

        def __second_graphic_changed(self, property_name):
            if not self.__graphic_updating:
                self.__update_calibration()


    ui = Declarative.DeclarativeUI()

    row_1 = ui.create_row(ui.create_label(text="Move the graphics in the spectrum and/or change the numbers\nin the fields below to change the calibration.\n"
                                               "The offset graphic will be positioned on the ZLP if possible."),
                          margin=5, spacing=5)
    row_2 = ui.create_row(ui.create_label(text="Offset Point energy"),
                          ui.create_line_edit(text="@binding(offset_energy, converter=ev_converter)"),
                          ui.create_stretch(),
                          margin=5, spacing=5)
    row_3 = ui.create_row(ui.create_label(text="Scale Point energy"),
                          ui.create_line_edit(text="@binding(second_point, converter=ev_converter)"),
                          ui.create_stretch(),
                          margin=5, spacing=5)
    column = ui.create_column(row_1, row_2, row_3, ui.create_stretch(), margin=5, spacing=5)

    data_item: API_1_0.DataItem = window.target_data_item

    class DummyHandler:
        ...

    if data_item is None or data_item.xdata is None or not data_item.display_xdata.is_data_1d:

        window.show_modeless_dialog(ui.create_modeless_dialog(ui.create_label(text=("This tool cannot be used for the selected type of data.\n"
                                                                                    "To use it you have to select a data item containing 1-D data or a sequence of 1-D data.")),
                                                              title="Calibrate Spectrum", margin=10),
                                    handler=DummyHandler)
        return

    if data_item._data_item.is_live:

        window.show_modeless_dialog(ui.create_modeless_dialog(ui.create_label(text=("This tool cannot be used on live data.\n"
                                                                                    "To use it you have to select a data item containing 1-D data or a sequence of 1-D data.")),
                                                              title="Calibrate Spectrum", margin=10),
                                    handler=DummyHandler)
        return

    # This is the data item we will update the calibrations on. If the selected data item is the result of a pick
    # computation we will update the source SI. Otherwise we just update the spectrum itself.
    src_data_item = data_item

    for computation in api.library._document_model.computations:
        if computation.processing_id in {"pick-point", "pick-mask-average", "pick-mask-sum"}:
            if computation.get_output("target") == data_item._data_item:
                input_ = computation.get_input("src")
                # If input_ is a "DataSource" we need to get the actual data item
                if hasattr(input_, "data_item"):
                    input_ = input_.data_item
                src_data_item = api._new_api_object(input_)

    mx_pos = numpy.nan
    try:
        mx_pos = ZLP_Analysis.estimate_zlp_amplitude_position_width_fit_spline(data_item.display_xdata.data)[1]
    except TypeError:
        pass

    # fallback to com if fit failed
    if mx_pos is numpy.nan:
        mx_pos = ZLP_Analysis.estimate_zlp_amplitude_position_width_com(data_item.display_xdata.data)[1]

    # fallback to simple max if everything else failed
    if mx_pos is numpy.nan:
        mx_pos = float(numpy.argmax(data_item.display_xdata.data))

    # We need to move the detected maximum by half a pixel because we want to center the calibration and the graphic
    # on the pixel center but the maximum is calculated for the left edge.
    mx_pos += 0.5

    dimensional_calibrations = list(data_item.display_xdata.dimensional_calibrations)
    energy_calibration = dimensional_calibrations[0]
    energy_calibration.offset = -mx_pos * energy_calibration.scale
    dimensional_calibrations = list(src_data_item.xdata.dimensional_calibrations)
    dimensional_calibrations[-1] = energy_calibration
    src_data_item.set_dimensional_calibrations(dimensional_calibrations)


    offset_graphic = data_item.add_channel_region(mx_pos / len(data_item.display_xdata.data))
    offset_graphic.label = "Offset Point"
    offset_graphic._graphic.color = "#CE00AC"
    second_graphic = data_item.add_channel_region((offset_graphic.position + 1.0) * 0.5)
    second_graphic.label = "Scale Point"
    second_graphic._graphic.color = "#CE00AC"

    handler = UIHandler(data_item, src_data_item, offset_graphic, second_graphic, units=energy_calibration.units)
    dialog = typing.cast(Dialog.ActionDialog,
                         Declarative.construct(window._document_controller.ui, window._document_controller,
                                               ui.create_modeless_dialog(column, title="Calibrate Spectrum"), handler))

    def wc(w):
        data_item.remove_region(offset_graphic)
        data_item.remove_region(second_graphic)
        getattr(handler, "configuration_dialog_close_listener").close()
        delattr(handler, "configuration_dialog_close_listener")

    # use set handler to pass type checking.
    setattr(handler, "configuration_dialog_close_listener", dialog._window_close_event.listen(wc))

    dialog.show()

    # Return the dialog which is useful for testing
    return dialog
예제 #25
0
def pose_title_edit_popup(document_controller: DocumentController.DocumentController, display_item: DisplayItem.DisplayItem, position: Geometry.IntPoint, size: Geometry.IntSize):

    class Handler:

        def __init__(self):
            self.property_changed_event = Event.Event()
            self.title_edit = None
            self.caption_edit = None
            self.__is_rejected = False
            self.__title = display_item.title
            self.__caption = display_item.caption

        def init_handler(self):
            self.title_edit.select_all()

        def init_popup(self, request_close_fn: typing.Callable[[], None]) -> None:
            self.__request_close_fn = request_close_fn

        def did_show(self):
            self.title_edit.focused = True

        @property
        def title(self):
            return self.__title

        @title.setter
        def title(self, value):
            self.__title = value
            self.property_changed_event.fire("title")

        @property
        def caption(self):
            return self.__caption

        @caption.setter
        def caption(self, value):
            self.__caption = value
            self.property_changed_event.fire("caption")

        def reject(self, widget):
            # receive this when the user hits escape. let the window handle the escape by returning False.
            # mark popup as rejected.
            self.__is_rejected = True
            return False

        def accept(self, widget):
            # receive this when the user hits return. need to request a close and return True to say we handled event.
            self.__request_close_fn()
            return True

        def handle_done(self, widget):
            self.__request_close_fn()

        def handle_cancel(self, widget):
            self.__is_rejected = True
            self.__request_close_fn()

        def close(self):
            # if not rejected and title has changed, change the title.
            if not self.__is_rejected:
                title = self.title_edit.text
                if title != display_item.title:
                    command = Inspector.ChangeDisplayItemPropertyCommand(document_controller.document_model, display_item, "title", title)
                    command.perform()
                    document_controller.push_undo_command(command)
                caption = self.caption_edit.text
                if caption != display_item.caption:
                    command = Inspector.ChangeDisplayItemPropertyCommand(document_controller.document_model, display_item, "caption", caption)
                    command.perform()
                    document_controller.push_undo_command(command)

    ui_handler = Handler()

    ui = Declarative.DeclarativeUI()

    title_edit = ui.create_line_edit(name="title_edit", text="title", placeholder_text=_("Title"), on_return_pressed="accept", on_escape_pressed="reject", width=320)

    caption_edit = ui.create_text_edit(name="caption_edit", text="caption", on_escape_pressed="reject", height=100, width=320)

    title_row = ui.create_row(ui.create_label(text=_("Title")), title_edit, spacing=8, margin=8)

    caption_row = ui.create_row(ui.create_label(text=_("Caption")), caption_edit, spacing=8, margin=8)

    button_row = ui.create_row(ui.create_stretch(), ui.create_push_button(text=_("Cancel"), on_clicked="handle_cancel"), ui.create_push_button(text=_("Done"), on_clicked="handle_done"), spacing=8, margin=8)

    column = ui.create_column(title_row, caption_row, button_row, margin=4)

    popup = Dialog.PopupWindow(document_controller, column, ui_handler)

    popup.show(position=position, size=size)
예제 #26
0
    def show_choose_project_dialog(self) -> None:
        with self.prevent_close():
            u = Declarative.DeclarativeUI()
            button_row = u.create_row(
                u.create_push_button(text=_("New..."),
                                     on_clicked="new_project"),
                u.create_push_button(text=_("Open..."),
                                     on_clicked="open_project"),
                u.create_stretch(),
                u.create_push_button(text=_("Cancel"),
                                     on_clicked="close_window"),
                u.create_push_button(text=_("Open Recent"),
                                     on_clicked="open_recent"),
                spacing=8)

            project_references_model = ListModel.FilteredListModel(
                container=self.__profile, items_key="project_references")
            project_references_model.filter = ListModel.PredicateFilter(
                lambda pr: pr.project_state != "loaded")
            project_references_model.sort_key = lambda pr: pr.last_used
            project_references_model.sort_reverse = True

            class ProjectReferenceItem:
                # provides a str converter and a tool tip.
                def __init__(self,
                             project_reference: Profile.ProjectReference):
                    self.project_reference = project_reference

                def __str__(self) -> str:
                    project_reference = self.project_reference
                    project_title = project_reference.title
                    if project_reference.project_state == "needs_upgrade":
                        project_title += " " + _("(NEEDS UPGRADE)")
                    elif project_reference.project_state != "unloaded" or project_reference.project_version != FileStorageSystem.PROJECT_VERSION:
                        project_title += " " + _("(MISSING OR UNREADABLE)")
                    return project_title

                @property
                def tool_tip(self) -> str:
                    return str(self.project_reference.path)

            project_reference_items_model = ListModel.MappedListModel(
                container=project_references_model,
                master_items_key="project_references",
                items_key="project_reference_items",
                map_fn=ProjectReferenceItem)

            item_list = u.create_list_box(
                items_ref="@binding(list_property_model.value)",
                current_index="@binding(current_index)",
                height=240,
                min_height=180,
                size_policy_horizontal="expanding",
                on_item_selected="recent_item_selected",
                on_item_handle_context_menu="item_handle_context_menu")

            main_column = u.create_column(
                u.create_label(text=_("Recent Projects")),
                item_list,
                u.create_spacing(13),
                button_row,
                spacing=8,
                width=380)
            window = u.create_window(main_column,
                                     title=_("Choose Project"),
                                     margin=12,
                                     window_style="tool")

            def open_project_reference(
                    project_reference: Profile.ProjectReference) -> None:
                self.open_project_reference(project_reference)

            def show_open_project_dialog() -> None:
                self.show_open_project_dialog()

            def show_new_project_dialog() -> None:
                NewProjectAction().invoke(
                    UIWindow.ActionContext(self, None, None))

            from nion.utils import Observable

            class ListPropertyModel(Observable.Observable):
                # copied from nionutils to avoid requiring new version.
                # remove this code once nionutils 0.3.24+ is released.

                def __init__(self, list_model):
                    super().__init__()
                    self.__list_model = list_model
                    self.__item_inserted_event_listener = list_model.item_inserted_event.listen(
                        self.__item_inserted)
                    self.__item_removed_event_listener = list_model.item_removed_event.listen(
                        self.__item_removed)

                def close(self) -> None:
                    self.__list_model = None
                    self.__item_inserted_event_listener = None
                    self.__item_removed_event_listener = None

                def __item_inserted(self, key: str, item,
                                    before_index: int) -> None:
                    self.notify_property_changed("value")

                def __item_removed(self, key: str, item, index: int) -> None:
                    self.notify_property_changed("value")

                @property
                def value(self):
                    return self.__list_model.items

            class ChooseProjectHandler(Declarative.WindowHandler):
                def __init__(self, application: Application):
                    super().__init__()
                    self.__application = application
                    self.current_index = 0
                    self.list_property_model = ListPropertyModel(
                        project_reference_items_model)

                def recent_item_selected(self, widget: Declarative.UIWidget,
                                         current_index: int) -> None:
                    if 0 <= current_index < len(project_reference_items_model.
                                                project_reference_items):
                        # to ensure the application does not close upon closing the last window, force it
                        # to stay open while the window is closed and another reopened.
                        with self.__application.prevent_close():
                            self.close_window()
                            project_reference_item = project_reference_items_model.project_reference_items[
                                current_index]
                            open_project_reference(
                                project_reference_item.project_reference)

                def new_project(self, widget: Declarative.UIWidget) -> None:
                    # to ensure the application does not close upon closing the last window, force it
                    # to stay open while the window is closed and another reopened.
                    with self.__application.prevent_close():
                        show_new_project_dialog()
                        self.close_window()

                def open_project(self, widget: Declarative.UIWidget) -> None:
                    # to ensure the application does not close upon closing the last window, force it
                    # to stay open while the window is closed and another reopened.
                    with self.__application.prevent_close():
                        show_open_project_dialog()
                        self.close_window()

                def open_recent(self, widget: Declarative.UIWidget) -> None:
                    self.recent_item_selected(widget, self.current_index)

                def item_handle_context_menu(self,
                                             widget: Declarative.UIWidget, *,
                                             gx: int, gy: int,
                                             index: typing.Optional[int],
                                             **kwargs) -> bool:
                    if index is not None:
                        project_reference_item = project_reference_items_model.project_reference_items[
                            index]
                        menu = self.window.create_context_menu()
                        menu.add_menu_item(
                            _(f"Open Project Location"),
                            functools.partial(
                                ProjectPanel.reveal_project,
                                project_reference_item.project_reference))
                        menu.add_separator()

                        def remove_project(index: int) -> None:
                            project_reference_item = project_reference_items_model.project_reference_items[
                                index]
                            self.__application.profile.remove_project_reference(
                                project_reference_item.project_reference)

                        menu.add_menu_item(
                            _(f"Remove Project from List"),
                            functools.partial(remove_project, index))
                        menu.popup(gx, gy)
                    return True

            ChooseProjectHandler(self).run(window, app=self)
예제 #27
0
    def start(self,
              *,
              profile_dir: pathlib.Path = None,
              profile: Profile.Profile = None) -> bool:
        """Start the application.

        Creates the profile object using profile_path parameter (for testing), the profile path constructed from the
        name stored in preferences, or a default profile path.

        Attaches recent projects if profile is freshly created. The recent projects will initially be disabled and
        will require the user to explicitly upgrade them.

        Creates the document model with the profile.

        Creates the document window (aka document controller) with the document model.
        """
        logging.getLogger("migration").setLevel(logging.INFO)
        logging.getLogger("loader").setLevel(logging.INFO)

        # create or load the profile object. allow test to override profile.
        is_created = False
        if not profile:
            # determine the profile_path
            if profile_dir:
                profile_path = profile_dir / pathlib.Path(
                    "Profile").with_suffix(".nsproj")
            else:
                data_dir = pathlib.Path(self.ui.get_data_location())
                profile_name = pathlib.Path(
                    self.ui.get_persistent_string("profile_name", "Profile"))
                profile_path = data_dir / profile_name.with_suffix(".nsproj")
            # create the profile
            profile, is_created = self.__establish_profile(profile_path)
        self.__profile = profile

        # configure the document model object.
        DocumentModel.DocumentModel.computation_min_period = 0.1
        DocumentModel.DocumentModel.computation_min_factor = 1.0

        # if it was created, it probably means it is migrating from an old version. so add all recent projects.
        # they will initially be disabled and the user will have to explicitly upgrade them.
        if is_created:
            # present a dialog for showing progress while finding existing projects
            u = Declarative.DeclarativeUI()
            task_message = u.create_label(
                text=_("Looking for existing projects..."))
            progress = u.create_progress_bar(
                value="@binding(progress_value_model.value)", width=300 - 24)
            progress_message = u.create_label(
                text="@binding(message_str_model.value)")
            main_column = u.create_column(task_message,
                                          progress,
                                          progress_message,
                                          spacing=8,
                                          width=300)
            window = u.create_window(main_column,
                                     title=_("Locating Existing Projects"),
                                     margin=12,
                                     window_style="tool")

            # handler for the progress window. defines two value models: progress, an int 0-100; and message, a string.
            class FindExistingProjectsWindowHandler(Declarative.WindowHandler):
                def __init__(self,
                             *,
                             completion_fn: typing.Optional[typing.Callable[
                                 [], None]] = None):
                    super().__init__(completion_fn=completion_fn)
                    self.progress_value_model = Model.PropertyModel(0)
                    self.message_str_model = Model.PropertyModel(str())

            # construct the window handler and run it. when the dialog closes, it will continue by
            # calling open default project.
            window_handler = FindExistingProjectsWindowHandler(
                completion_fn=functools.partial(self.__open_default_project,
                                                profile_dir, is_created))
            window_handler.run(window, app=self)

            # define an async routine that will perform the finding of the existing projects.
            # this is just a loop that yields via asyncio.sleep periodically. the loop loads
            # the projects and updates the progress and message value models in the dialog.
            # when finished, it asks the window to close on its next periodic call. it is
            # necessary to close this way because the close request may close the event loop
            # in which we're executing. so queueing the close request avoids that.
            async def find_existing_projects():
                recent_library_paths = self.get_recent_library_paths()
                for index, library_path in enumerate(recent_library_paths):
                    window_handler.progress_value_model.value = 100 * index // len(
                        recent_library_paths)
                    window_handler.message_str_model.value = str(
                        library_path.name)
                    logging.getLogger("loader").info(
                        f"Adding existing project {index + 1}/{len(recent_library_paths)} {library_path}"
                    )
                    await asyncio.sleep(0)
                    profile.add_project_folder(pathlib.Path(library_path),
                                               load=False)
                window_handler.progress_value_model.value = 100
                window_handler.message_str_model.value = _("Finished")
                await asyncio.sleep(1)
                window_handler.window.queue_request_close()

            # launch the find existing projects task asynchronously.
            window_handler.window.event_loop.create_task(
                find_existing_projects())
            return True
        else:
            # continue with opening the default project
            return self.__open_default_project(profile_dir, is_created)
예제 #28
0
    def build(self, ui, event_loop=None, **kwargs):
        u = Declarative.DeclarativeUI()

        video_device_factories = list(Registry.get_components_by_type("video_device_factory"))

        class Handler:
            def __init__(self, ui_view, video_sources):
                self.ui_view = ui_view
                self.video_sources = video_sources
                self.video_source_type_index = Model.PropertyModel(0)

            def create_new_video_device(self, widget):
                video_base.video_configuration.create_hardware_source(video_device_factories[self.video_source_type_index.value])

            def create_handler(self, component_id: str, container=None, item=None, **kwargs):

                class SectionHandler:

                    def __init__(self, container, hardware_source):
                        self.container = container
                        self.hardware_source = hardware_source
                        self.settings = video_base.video_configuration.get_settings_model(hardware_source)
                        self.settings_original = copy.deepcopy(self.settings)
                        self.needs_saving_model = Model.PropertyModel(False)
                        self.property_changed_event = Event.Event()
                        self.apply_button = None
                        self.revert_button = None

                        def settings_changed(property_name):
                            self.needs_saving_model.value = True

                        self.__settings_changed_event_listener = self.settings.property_changed_event.listen(settings_changed)

                        def needs_saving_model_changed(property_name):
                            if self.apply_button:
                                self.apply_button.enabled = self.needs_saving_model.value
                            if self.revert_button:
                                self.revert_button.enabled = self.needs_saving_model.value

                        self.__needs_saving_changed_event_listener = self.needs_saving_model.property_changed_event.listen(needs_saving_model_changed)

                    def close(self):
                        self.__settings_changed_event_listener.close()
                        self.__settings_changed_event_listener = None

                    def init_handler(self):
                        self.apply_button.enabled = self.needs_saving_model.value
                        self.revert_button.enabled = self.needs_saving_model.value

                    def create_handler(self, component_id: str, container=None, item=None, **kwargs):
                        if component_id == "edit_group":
                            if self.__video_device_factory:
                                return self.__video_device_factory.create_editor_handler(self.settings)
                            else:
                                return self

                    @property
                    def resources(self):
                        if self.__video_device_factory:
                            content = self.__video_device_factory.get_editor_description()
                        else:
                            content = u.create_label(text=_("Not Available"))

                        component = u.define_component(content=content, component_id="edit_group")

                        return {"edit_group": component}

                    @property
                    def __video_device_factory(self):
                        for video_device_factory in video_device_factories:
                            if video_device_factory.factory_id == self.settings.driver:
                                return video_device_factory
                        return None

                    @property
                    def driver_display_name(self) -> str:
                        video_device_factory = self.__video_device_factory
                        return video_device_factory.display_name if video_device_factory else _("Unknown")

                    def apply(self, widget):
                        video_base.video_configuration.set_settings_model(self.hardware_source, self.settings)
                        self.needs_saving_model.value = False

                    def revert(self, widget):
                        self.settings.copy_from(self.settings_original)
                        self.needs_saving_model.value = False

                    def remove(self, widget):
                        video_base.video_configuration.remove_hardware_source(self.hardware_source)

                if component_id == "section":
                    return SectionHandler(container, item)

            @property
            def resources(self):
                u = Declarative.DeclarativeUI()

                driver_display_name_label = u.create_label(text="@binding(driver_display_name)")

                device_id_field = u.create_line_edit(text="@binding(settings.device_id)", width=180)

                display_name_field = u.create_line_edit(text="@binding(settings.name)", width=240)

                edit_group_content = u.create_component_instance("edit_group")

                edit_group = u.create_group(edit_group_content, margin=8)

                edit_row = u.create_row(edit_group, u.create_stretch())

                apply_button = u.create_push_button(name="apply_button", text=_("Apply"), on_clicked="apply")
                revert_button = u.create_push_button(name="revert_button", text=_("Revert"), on_clicked="revert")
                remove_button = u.create_push_button(text=_("Remove"), on_clicked="remove")
                remove_row = u.create_row(apply_button, revert_button, remove_button, u.create_stretch())

                label_column = u.create_column(u.create_label(text=_("Driver:")), u.create_label(text=_("Device ID:")), u.create_label(text=_("Display Name:")), spacing=4)
                field_column = u.create_column(driver_display_name_label, device_id_field, display_name_field, spacing=4)

                content_row = u.create_row(label_column, field_column, u.create_stretch(), spacing=12)

                content = u.create_column(content_row, edit_row, remove_row, spacing=8)

                component = u.define_component(content=content, component_id="section")

                return {"section": component}

        sources_column = u.create_column(items="video_sources.items", item_component_id="section", spacing=8)

        sources_content = u.create_scroll_area(u.create_column(sources_column, u.create_stretch()))

        video_source_types = [video_device_factory.display_name for video_device_factory in video_device_factories]

        video_source_type_combo = u.create_combo_box(items=video_source_types, current_index="@binding(video_source_type_index.value)")

        button_row = u.create_row(u.create_stretch(), video_source_type_combo, u.create_push_button(text=_("New"), on_clicked="create_new_video_device"), spacing=8)

        content = u.create_column(sources_content, button_row)

        return Declarative.DeclarativeWidget(ui, event_loop, Handler(content, self.__video_configuration.video_sources))
예제 #29
0
def pose_select_item_pop_up(items: typing.Sequence,
                            completion_fn: typing.Callable[[typing.Any], None],
                            *,
                            window: Window.Window,
                            current_item: int = 0,
                            item_getter: typing.Optional[typing.Callable[
                                [typing.Any], str]] = None,
                            title: str = None) -> None:

    item_getter = item_getter or str

    class Handler:
        def __init__(self):
            self.is_rejected = True
            self.computation_index_model = Model.PropertyModel(current_item)
            self.item_list = None

        def init_popup(self, request_close_fn: typing.Callable[[],
                                                               None]) -> None:
            self.__request_close_fn = request_close_fn

        def did_show(self):
            self.item_list.focused = True

        def reject(self, widget):
            # receive this when the user hits escape. let the window handle the escape by returning False.
            # mark popup as rejected.
            return False

        def accept(self, widget):
            # receive this when the user hits return. need to request a close and return True to say we handled event.
            self.__request_close_fn()
            self.is_rejected = False
            return True

        def handle_select(self, widget):
            self.is_rejected = False
            self.__request_close_fn()

        def handle_cancel(self, widget):
            self.__request_close_fn()

    from nion.ui import Declarative  # avoid circular reference

    # calculate the max string width, add 10%, min 200, max 480
    width = min(
        max(
            int(
                max([
                    window.get_font_metrics("system", item_getter(c)).width
                    for c in items
                ]) * 1.10), 200), 480)

    ui_handler = Handler()
    u = Declarative.DeclarativeUI()
    title_row = u.create_row(u.create_label(text=title or _("Select Item")),
                             u.create_stretch())
    item_list = u.create_list_box(
        name="item_list",
        items=[item_getter(c) for c in items],
        width=width,
        height=120,
        min_height=90,
        size_policy_horizontal="expanding",
        current_index="@binding(computation_index_model.value)",
        on_return_pressed="accept",
        on_escape_pressed="reject")
    button_row = u.create_row(u.create_stretch(),
                              u.create_push_button(text=_("Cancel"),
                                                   on_clicked="handle_cancel"),
                              u.create_push_button(text=_("Select"),
                                                   on_clicked="handle_select"),
                              spacing=8)
    column = u.create_column(title_row,
                             item_list,
                             button_row,
                             spacing=4,
                             margin=8)
    popup = PopupWindow(window, column, ui_handler)

    def handle_close() -> None:
        if not ui_handler.is_rejected:
            computation = items[ui_handler.computation_index_model.value]
            completion_fn(computation)
        else:
            completion_fn(None)

    popup.on_close = handle_close
    popup.show()  #position=position, size=size)
예제 #30
0
    def show_choose_project_dialog(self) -> None:
        with self.prevent_close():
            u = Declarative.DeclarativeUI()
            button_row = u.create_row(
                u.create_push_button(text=_("New..."),
                                     on_clicked="new_project"),
                u.create_push_button(text=_("Open..."),
                                     on_clicked="open_project"),
                u.create_stretch(),
                u.create_push_button(text=_("Cancel"),
                                     on_clicked="close_window"),
                u.create_push_button(text=_("Open Recent"),
                                     on_clicked="open_recent"),
                spacing=8)

            used_project_references = list()
            project_titles = list()

            project_references = filter(
                lambda pr: pr.project_state != "loaded",
                self.__profile.project_references)
            project_references = sorted(project_references,
                                        key=operator.attrgetter("last_used"),
                                        reverse=True)
            for project_reference in project_references[:20]:
                if project_reference.project_state != "loaded":
                    project_title = project_reference.title
                    if project_reference.project_state == "needs_upgrade":
                        project_title += " " + _("(NEEDS UPGRADE)")
                    elif project_reference.project_state != "unloaded" or project_reference.project_version != FileStorageSystem.PROJECT_VERSION:
                        project_title += " " + _("(MISSING OR UNREADABLE)")
                    used_project_references.append(project_reference)
                    project_titles.append(project_title)

            item_list = u.create_list_box(
                items=project_titles,
                current_index="@binding(current_index)",
                height=240,
                min_height=180,
                size_policy_horizontal="expanding",
                on_item_selected="recent_item_selected")

            main_column = u.create_column(
                u.create_label(text=_("Recent Projects")),
                item_list,
                u.create_spacing(13),
                button_row,
                spacing=8,
                width=380)
            window = u.create_window(main_column,
                                     title=_("Choose Project"),
                                     margin=12,
                                     window_style="tool")

            def open_project_reference(
                    project_reference: Profile.ProjectReference) -> None:
                self.open_project_reference(project_reference)

            def show_open_project_dialog() -> None:
                self.show_open_project_dialog()

            def show_new_project_dialog() -> None:
                NewProjectAction().invoke(
                    UIWindow.ActionContext(self, None, None))

            class ChooseProjectHandler(Declarative.WindowHandler):
                def __init__(self, application: Application):
                    super().__init__()
                    self.__application = application
                    self.current_index = 0

                def recent_item_selected(self, widget: Declarative.UIWidget,
                                         current_index: int) -> None:
                    if 0 <= current_index < len(used_project_references):
                        with self.__application.prevent_close():
                            self.close_window()
                            open_project_reference(
                                used_project_references[current_index])

                def new_project(self, widget: Declarative.UIWidget) -> None:
                    with self.__application.prevent_close():
                        show_new_project_dialog()
                        self.close_window()

                def open_project(self, widget: Declarative.UIWidget) -> None:
                    with self.__application.prevent_close():
                        show_open_project_dialog()
                        self.close_window()

                def open_recent(self, widget: Declarative.UIWidget) -> None:
                    self.recent_item_selected(widget, self.current_index)

            ChooseProjectHandler(self).run(window, app=self)