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, ), )
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()
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}
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}
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)
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)
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())
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)
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)
def __init__(self, *, document_controller: DocumentController.DocumentController, **kwargs: typing.Any) -> None: self.radio_button_value: Model.PropertyModel[int] = Model.PropertyModel(0) u = Declarative.DeclarativeUI() top_row_items = list() bottom_row_items = list() modes = list() tool_actions = list() for action in Window.actions.values(): if action.action_id.startswith("window.set_tool_mode"): tool_actions.append(typing.cast(DocumentController.SetToolModeAction, action)) for i, tool_action in enumerate(tool_actions): tool_id = tool_action.tool_mode icon_png = tool_action.tool_icon tool_tip = tool_action.tool_tip key_shortcut = Window.action_shortcuts.get(tool_action.action_id, dict()).get("display_panel", None) if key_shortcut: tool_tip += f" ({key_shortcut})" modes.append(tool_id) assert icon_png is not None icon_data = CanvasItem.load_rgba_data_from_bytes(icon_png) icon_property = "icon_" + tool_id setattr(self, icon_property, icon_data) radio_button = u.create_radio_button(icon=f"@binding({icon_property})", value=i, group_value="@binding(radio_button_value.value)", width=32, height=24, tool_tip=tool_tip) if i % 2 == 0: top_row_items.append(radio_button) else: bottom_row_items.append(radio_button) top_row = u.create_row(*top_row_items) bottom_row = u.create_row(*bottom_row_items) self.ui_view = u.create_row(u.create_column(u.create_spacing(4), top_row, bottom_row, u.create_spacing(4), u.create_stretch())) self.radio_button_value.value = modes.index(document_controller.tool_mode) def tool_mode_changed(tool_mode: str) -> None: self.radio_button_value.value = modes.index(tool_mode) self.__tool_mode_changed_event_listener = document_controller.tool_mode_changed_event.listen(tool_mode_changed) tool_mode_changed(document_controller.tool_mode) def radio_button_changed(property: str) -> None: if property == "value": mode_index = self.radio_button_value.value if mode_index is not None: document_controller.tool_mode = modes[mode_index] self.__radio_button_value_listener = self.radio_button_value.property_changed_event.listen(radio_button_changed)
def 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())
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}
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
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)
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))
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}
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)
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)
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)
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))
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)
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
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)
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)
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)
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))
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)
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)