def __init__(
        self,
        *,
        image_acquisition: ImageAcquisitionService,
        features_params_factory: PendantFeaturesParamsFactory,
        features_service: PendantFeaturesService,
    ) -> None:
        self._image_acquisition = image_acquisition

        self.bn_active_tool = VariableBindable(ToolID.DROP_REGION)

        region_clip = AccessorBindable(getter=self._get_region_clip)

        self.drop_region_plugin = DefineRegionPluginModel(
            in_region=GObjectPropertyBindable(features_params_factory,
                                              'drop-region'),
            in_clip=region_clip,
        )

        self.needle_region_plugin = DefineRegionPluginModel(
            in_region=GObjectPropertyBindable(features_params_factory,
                                              'needle-region'),
            in_clip=region_clip,
        )

        self.preview_plugin = IFTPreviewPluginModel(
            image_acquisition=image_acquisition,
            features_params_factory=features_params_factory,
            features_service=features_service,
        )
Exemple #2
0
    def _do_init(
        self,
        view_context: ImageProcessorPluginViewContext,
        tool_id: Any,
        color: Tuple[float, float, float],
        label: str,
        z_index: int,
    ) -> None:
        self._view_context = view_context
        self._tool_ref = view_context.get_tool_item(tool_id)

        view_context.render.connect(
            'cursor-up-event',
            lambda render, pos: self.presenter.cursor_up(pos),
        )

        view_context.render.connect(
            'cursor-down-event',
            lambda render, pos: self.presenter.cursor_down(pos),
        )

        view_context.render.connect(
            'cursor-motion-event',
            lambda render, pos: self.presenter.cursor_move(pos),
        )

        self.bn_tool_button_is_active = self._tool_ref.bn_is_active

        self._render = view_context.render

        self._defined_ro = RectangleWithLabel(
            border_color=color,
            border_width=2,
            label=label,
            z_index=z_index,
        )
        self._render.add_render_object(self._defined_ro)

        self._dragging_ro = Rectangle(
            border_color=color,
            border_width=1,
            z_index=z_index,
        )
        self._render.add_render_object(self._dragging_ro)

        self.bn_dragging = GObjectPropertyBindable(
            g_obj=self._dragging_ro,
            prop_name='extents',
        )

        self.bn_defined = GObjectPropertyBindable(
            g_obj=self._defined_ro,
            prop_name='extents',
        )

        self.presenter.view_ready()
Exemple #3
0
    def _do_init(
        self,
        view_context: ImageProcessorPluginViewContext,
        tool_id: Any,
        color: Tuple[float, float, float],
        label: str,
        z_index: int,
    ) -> None:
        self._view_context = view_context
        self._tool_ref = view_context.get_tool_item(tool_id)

        view_context.canvas.connect(
            'cursor-up',
            lambda canvas, pos: self.presenter.cursor_up(pos),
        )

        view_context.canvas.connect(
            'cursor-down',
            lambda canvas, pos: self.presenter.cursor_down(pos),
        )

        view_context.canvas.connect(
            'cursor-motion',
            lambda canvas, pos: self.presenter.cursor_move(pos),
        )

        self.bn_tool_button_is_active = self._tool_ref.bn_is_active

        self._canvas = view_context.canvas

        self._defined_rect = RectangleArtist(
            stroke_color=color,
            stroke_width=1,
            scale_strokes=True,
        )
        self._canvas.add_artist(self._defined_rect, z_index=z_index)

        self._dragging_rect = RectangleArtist(
            stroke_color=color,
            stroke_width=1,
            scale_strokes=True,
        )
        self._canvas.add_artist(self._dragging_rect, z_index=z_index)

        self.bn_defined = GObjectPropertyBindable(
            g_obj=self._defined_rect,
            prop_name='extents',
        )

        self.bn_dragging = GObjectPropertyBindable(
            g_obj=self._dragging_rect,
            prop_name='extents',
        )

        self.presenter.view_ready()
Exemple #4
0
    def _do_init(self, view_context: ImageProcessorPluginViewContext) -> None:
        self._view_context = view_context
        self._tool_ref = self._view_context.get_tool_item(
            ToolID.EDGE_DETECTION)

        self.bn_tool_button_is_active = self._tool_ref.bn_is_active

        self._button_body = Gtk.Grid(hexpand=True, vexpand=True)
        self._tool_ref.button_interior.add(self._button_body)

        button_lbl = Gtk.Label(
            label="Edge detection",
            vexpand=True,
            valign=Gtk.Align.CENTER,
        )
        self._button_body.add(button_lbl)

        self._button_body.show_all()

        self._popover = Gtk.Popover(
            relative_to=self._button_body,
            modal=False,
        )

        # Prevent the popover from being dismissed by the user clicking on it.
        self._popover.connect('button-release-event', lambda *_: True)

        popover_body = Gtk.Grid(
            margin=10,
            width_request=250,
        )
        self._popover.add(popover_body)

        canny_adjuster = CannyParameters()
        popover_body.add(canny_adjuster)

        self.bn_canny_min = GObjectPropertyBindable(
            g_obj=canny_adjuster,
            prop_name='min-thresh',
        )

        self.bn_canny_max = GObjectPropertyBindable(
            g_obj=canny_adjuster,
            prop_name='max-thresh',
        )

        popover_body.show_all()

        self.presenter.view_ready()
    def fixture(self):
        # Reset the property getter and setter mocks (since they are shared with all instances)
        MockGObjectWithProperty.prop_getter.reset_mock()
        MockGObjectWithProperty.prop_setter.reset_mock()

        self.g_obj = MockGObjectWithProperty()
        self.g_obj_prop_bindable = GObjectPropertyBindable(self.g_obj, 'prop')
Exemple #6
0
    def set_referents(
        self,
        tool_id: Any,
        tool_button: Gtk.Button,
        tool_button_interior: Gtk.Grid,
        do_request_deactivate: Callable[[Any], Any],
    ) -> None:
        assert not self._referents_set
        self._referents_set = True

        self._bn_is_active = GObjectPropertyBindable(
            g_obj=tool_button,
            prop_name='active',
        )

        self._tool_id = tool_id
        self._tool_button = tool_button
        self._tool_button_interior = tool_button_interior
        self._do_request_deactivate = do_request_deactivate
Exemple #7
0
    def _do_init(self) -> Gtk.Widget:
        self._render = Render(hexpand=True, vexpand=True)

        self._background_ro = PixbufFill()
        self._render.add_render_object(self._background_ro)

        surface_line_ro = Line(stroke_color=(0.25, 1.0, 0.25))
        self._render.add_render_object(surface_line_ro)
        self.bn_surface_line = GObjectPropertyBindable(surface_line_ro, 'line')

        drop_contour_ro = Polyline(stroke_color=(0.0, 0.5, 1.0))
        self._render.add_render_object(drop_contour_ro)
        self.bn_drop_contours = GObjectPropertyBindable(
            drop_contour_ro, 'polyline')

        left_angle_ro = Angle(stroke_color=(1.0, 0.0, 0.5), clockwise=False)
        self._render.add_render_object(left_angle_ro)

        self.bn_left_angle = GObjectPropertyBindable(left_angle_ro,
                                                     'delta-angle')
        self.bn_left_point = GObjectPropertyBindable(left_angle_ro,
                                                     'vertex-pos')

        surface_line_ro.bind_property(
            'line', left_angle_ro, 'start-angle',
            GObject.BindingFlags.SYNC_CREATE,
            lambda _, line: -math.atan(line.gradient)
            if line is not None else 0)

        right_angle_ro = Angle(stroke_color=(1.0, 0.0, 0.5), clockwise=True)
        self._render.add_render_object(right_angle_ro)

        self.bn_right_angle = GObjectPropertyBindable(
            right_angle_ro,
            'delta-angle',
            transform_to=lambda angle: -angle,
            transform_from=lambda angle: -angle)
        self.bn_right_point = GObjectPropertyBindable(right_angle_ro,
                                                      'vertex-pos')

        surface_line_ro.bind_property(
            'line', right_angle_ro, 'start-angle',
            GObject.BindingFlags.SYNC_CREATE, lambda _, line: math.pi -
            (math.atan(line.gradient) if line is not None else 0))

        self.presenter.view_ready()

        return self._render
Exemple #8
0
    def _do_init(self, footer_area: Gtk.Grid) -> Gtk.Widget:
        self._widget = Gtk.Grid(margin=10, column_spacing=10, row_spacing=10)

        image_source_lbl = Gtk.Label('Image source:')
        self._widget.attach(image_source_lbl, 0, 0, 1, 1)

        self._image_source_combobox = Gtk.ComboBoxText(hexpand=True,
                                                       halign=Gtk.Align.START)
        self._widget.attach(self._image_source_combobox, 1, 0, 1, 1)

        self._populate_combobox()

        self._widget.attach(
            Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL,
                          hexpand=True), 0, 1, 2, 1)

        _, configurator_area = self.new_component(
            configurator_cs.factory(in_acquirer=self.presenter.bn_acquirer))
        self._widget.attach(configurator_area, 0, 2, 2, 1)

        self.bn_selected_acquirer_type = GObjectPropertyBindable(
            g_obj=self._image_source_combobox,
            prop_name='active-id',
            transform_to=lambda e: e.name if e is not None else None,
            transform_from=lambda name: AcquirerType[name]
            if name is not None else None,
        )  # type: Bindable[Optional[str]]

        _, footer_inside = self.new_component(
            linear_navigator_footer_cs.factory(
                do_next=self.presenter.next_page))
        footer_inside.show()
        footer_area.add(footer_inside)

        self.presenter.view_ready()

        self._widget.foreach(Gtk.Widget.show)

        return self._widget
Exemple #9
0
    def _do_init(self) -> Gtk.Grid:
        self._widget = Gtk.Grid(column_spacing=5)

        left_btn = Gtk.Button('<')
        self._widget.attach(left_btn, 0, 0, 1, 1)

        self._idx_inp = IntegerEntry(lower=1, width_chars=3)
        self._widget.attach(self._idx_inp, 1, 0, 1, 1)

        self._num_images_lbl = Gtk.Label()
        self._widget.attach(self._num_images_lbl, 2, 0, 1, 1)

        right_btn = Gtk.Button('>')
        self._widget.attach(right_btn, 3, 0, 1, 1)

        self.bn_show_index = GObjectPropertyBindable(
            g_obj=self._idx_inp,
            prop_name='value',
            # User input is 1-based indexing
            transform_to=lambda x: x + 1 if x is not None else None,
            transform_from=lambda x: x - 1 if x is not None else None,
        )
        self._idx_inp.connect(
            'activate', lambda *_: self.presenter.view_show_idx_changed())
        self._idx_inp.connect(
            'focus-out-event',
            lambda *_: self.presenter.view_show_idx_changed())

        left_btn.connect('clicked', lambda *_: self.presenter.prev_image())
        right_btn.connect('clicked', lambda *_: self.presenter.next_image())

        self._widget.show_all()

        self.presenter.view_ready()

        return self._widget
Exemple #10
0
    def _do_init(self, parent_window: Optional[Gtk.Window]) -> Gtk.Window:
        self._window = Gtk.Window(
            title='Select camera',
            transient_for=parent_window,
            resizable=False,
            modal=True,
            window_position=Gtk.WindowPosition.CENTER,
        )

        body = Gtk.Grid()
        self._window.add(body)

        content = Gtk.Grid(margin=10, column_spacing=10)
        body.attach(content, 0, 0, 1, 1)

        camera_index_lbl = Gtk.Label('Camera index:')
        content.attach(camera_index_lbl, 0, 0, 1, 1)

        camera_index_inp = IntegerEntry(lower=0, upper=99999, max_length=5, width_chars=6)
        camera_index_inp.get_style_context().add_class('small-pad')
        content.attach_next_to(camera_index_inp, camera_index_lbl, Gtk.PositionType.RIGHT, 1, 1)

        # Setting max_width_chars to 0 seems to allow the label to occupy as much space as its parent, allowing
        # line wrapping to work.
        self._error_msg_lbl = Gtk.Label(margin_top=10, max_width_chars=0)
        self._error_msg_lbl.set_line_wrap(True)
        self._error_msg_lbl.get_style_context().add_class('error-text')
        content.attach(self._error_msg_lbl, 0, 1, 2, 1)

        footer = Gtk.Grid()
        footer.get_style_context().add_class('change-cam-dialog-view-footer')
        footer.get_style_context().add_class('linked')
        body.attach(footer, 0, 1, 1, 1)

        cancel_btn = Gtk.Button('Cancel', hexpand=True)
        cancel_btn.get_style_context().add_class('dialog-footer-button')
        footer.attach(cancel_btn, 0, 0, 1, 1)

        connect_btn = Gtk.Button('Connect', hexpand=True)
        connect_btn.get_style_context().add_class('dialog-footer-button')
        footer.attach(connect_btn, 1, 0, 1, 1)

        self._window.show_all()

        # Hide the error message label (since self.widget.show_all() would have made all descendant widgets
        # visible).
        self._error_msg_lbl.hide()

        # Wiring things up

        connect_btn.connect('clicked', lambda *_: self.presenter.connect())
        cancel_btn.connect('clicked', lambda *_: self.presenter.cancel())

        self._window.connect('delete-event', self._hdl_widget_delete_event)

        self.bn_camera_index = GObjectPropertyBindable(camera_index_inp, 'value')  # type: Bindable[int]
        self.bn_connect_btn_sensitive = GObjectPropertyBindable(connect_btn, 'sensitive')  # type: Bindable[bool]

        self.presenter.view_ready()

        return self._window
Exemple #11
0
    def _do_init(
        self,
        view_context: ImageProcessorPluginViewContext,
        tool_id: Any,
        color: Tuple[float, float, float],
        z_index: int,
    ) -> None:
        self._view_context = view_context
        self._tool_ref = view_context.get_tool_item(tool_id)

        view_context.canvas.connect(
            'cursor-up',
            lambda canvas, pos: self.presenter.cursor_up(pos),
        )

        view_context.canvas.connect(
            'cursor-down',
            lambda canvas, pos: self.presenter.cursor_down(pos),
        )

        view_context.canvas.connect(
            'cursor-motion',
            lambda canvas, pos: self.presenter.cursor_move(pos),
        )

        view_context.canvas.connect(
            'key-press-event',
            self._hdl_canvas_key_press_event,
        )

        self.bn_tool_button_is_active = self._tool_ref.bn_is_active

        self._canvas = view_context.canvas

        self._defined_artist = LineArtist(
            stroke_color=color,
            stroke_width=1,
            scale_strokes=True,
        )
        self._canvas.add_artist(self._defined_artist, z_index=z_index)

        self._dragging_artist = LineArtist(
            stroke_color=color,
            stroke_width=1,
            scale_strokes=True,
        )
        self._canvas.add_artist(self._dragging_artist, z_index=z_index)

        self._control_point_artist = CircleArtist(
            fill_color=color,
            scale_radius=True,
        )
        self._canvas.add_artist(self._control_point_artist, z_index=z_index)

        self.bn_defined = GObjectPropertyBindable(
            g_obj=self._defined_artist,
            prop_name='line',
        )

        self.bn_dragging = GObjectPropertyBindable(
            g_obj=self._dragging_artist,
            prop_name='line',
        )

        self.presenter.view_ready()
Exemple #12
0
    def _do_init(self) -> Gtk.Widget:
        self._widget = Gtk.Grid(row_spacing=10,
                                hexpand=False,
                                width_request=220)

        parameters_lbl = Gtk.Label(xalign=0)
        parameters_lbl.set_markup('<b>Parameters</b>')
        self._widget.attach(parameters_lbl, 0, 0, 1, 1)

        sheet = Gtk.Grid(row_spacing=10, column_spacing=10)
        self._widget.attach(sheet, 0, 1, 1, 1)

        interfacial_tension_lbl = Gtk.Label('IFT (mN/m):', xalign=0)
        sheet.attach(interfacial_tension_lbl, 0, 0, 1, 1)

        volume_lbl = Gtk.Label('Volume (mm³):', xalign=0)
        sheet.attach(volume_lbl, 0, 1, 1, 1)

        surface_area_lbl = Gtk.Label('Surface area (mm²):', xalign=0)
        sheet.attach(surface_area_lbl, 0, 2, 1, 1)

        sheet.attach(
            Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL,
                          hexpand=True), 0, 3, 2, 1)

        worthington_lbl = Gtk.Label('Worthington:', xalign=0)
        sheet.attach(worthington_lbl, 0, 4, 1, 1)

        bond_number_lbl = Gtk.Label('Bond number:', xalign=0)
        sheet.attach(bond_number_lbl, 0, 5, 1, 1)

        apex_coords_lbl = Gtk.Label('Apex coordinates (px):', xalign=0)
        sheet.attach(apex_coords_lbl, 0, 6, 1, 1)

        image_angle_lbl = Gtk.Label('Image angle:', xalign=0)
        sheet.attach(image_angle_lbl, 0, 7, 1, 1)

        interfacial_tension_val = Gtk.Label(xalign=0)
        sheet.attach_next_to(interfacial_tension_val, interfacial_tension_lbl,
                             Gtk.PositionType.RIGHT, 1, 1)

        volume_val = Gtk.Label(xalign=0)
        sheet.attach_next_to(volume_val, volume_lbl, Gtk.PositionType.RIGHT, 1,
                             1)

        surface_area_val = Gtk.Label(xalign=0)
        sheet.attach_next_to(surface_area_val, surface_area_lbl,
                             Gtk.PositionType.RIGHT, 1, 1)

        worthington_val = Gtk.Label(xalign=0)
        sheet.attach_next_to(worthington_val, worthington_lbl,
                             Gtk.PositionType.RIGHT, 1, 1)

        bond_number_val = Gtk.Label(xalign=0)
        sheet.attach_next_to(bond_number_val, bond_number_lbl,
                             Gtk.PositionType.RIGHT, 1, 1)

        apex_coords_val = Gtk.Label(xalign=0)
        sheet.attach_next_to(apex_coords_val, apex_coords_lbl,
                             Gtk.PositionType.RIGHT, 1, 1)

        image_angle_val = Gtk.Label(xalign=0)
        sheet.attach_next_to(image_angle_val, image_angle_lbl,
                             Gtk.PositionType.RIGHT, 1, 1)

        self._widget.foreach(Gtk.Widget.show_all)

        self.bn_interfacial_tension = GObjectPropertyBindable(
            interfacial_tension_val,
            'label',
            transform_to=lambda v: '{:.4g}'.format(v * 1e3),
        )  # type: WriteBindable[float]

        self.bn_volume = GObjectPropertyBindable(
            volume_val,
            'label',
            transform_to=lambda v: '{:.4g}'.format(v * 1e9),
        )  # type: WriteBindable[float]

        self.bn_surface_area = GObjectPropertyBindable(
            surface_area_val,
            'label',
            transform_to=lambda v: '{:.4g}'.format(v * 1e6),
        )  # type: WriteBindable[float]

        self.bn_worthington = GObjectPropertyBindable(
            worthington_val,
            'label',
            transform_to=lambda v: '{:.4g}'.format(v),
        )  # type: WriteBindable[float]

        self.bn_bond_number = GObjectPropertyBindable(
            bond_number_val,
            'label',
            transform_to=lambda v: '{:.4g}'.format(v),
        )  # type: WriteBindable[float]

        self.bn_apex_coords = GObjectPropertyBindable(
            apex_coords_val,
            'label',
            transform_to=lambda v: '({0[0]:.4g}, {0[1]:.4g})'.format(
                v))  # type: WriteBindable[Tuple[float, float]]

        self.bn_image_angle = GObjectPropertyBindable(
            image_angle_val,
            'label',
            transform_to=lambda v: '{:.4g}°'.format(math.degrees(
                v)))  # type: WriteBindable[float]

        self.presenter.view_ready()

        return self._widget
Exemple #13
0
    def _do_init(self) -> Gtk.Widget:
        self._widget = Gtk.Grid(row_spacing=10, column_spacing=10)

        file_chooser_lbl = Gtk.Label('Image files:', xalign=0)
        self._widget.attach(file_chooser_lbl, 0, 0, 1, 1)

        self._file_chooser_inp = FileChooserButton(
            file_filter=self._FILE_INPUT_FILTER, select_multiple=True)
        self._file_chooser_inp.get_style_context().add_class('small-pad')
        self._widget.attach_next_to(self._file_chooser_inp, file_chooser_lbl,
                                    Gtk.PositionType.RIGHT, 1, 1)

        frame_interval_lbl = Gtk.Label('Frame interval (s):')
        self._widget.attach(frame_interval_lbl, 0, 1, 1, 1)

        frame_interval_inp_container = Gtk.Grid()
        self._widget.attach_next_to(frame_interval_inp_container,
                                    frame_interval_lbl, Gtk.PositionType.RIGHT,
                                    1, 1)

        self._frame_interval_inp = FloatEntry(lower=0,
                                              width_chars=6,
                                              invisible_char='\0',
                                              caps_lock_warning=False)
        self._frame_interval_inp.get_style_context().add_class('small-pad')
        frame_interval_inp_container.add(self._frame_interval_inp)

        # Error message labels

        self._file_chooser_err_msg_lbl = Gtk.Label(xalign=0)
        self._file_chooser_err_msg_lbl.get_style_context().add_class(
            'error-text')
        self._widget.attach_next_to(self._file_chooser_err_msg_lbl,
                                    self._file_chooser_inp,
                                    Gtk.PositionType.RIGHT, 1, 1)

        self._frame_interval_err_msg_lbl = Gtk.Label(xalign=0)
        self._frame_interval_err_msg_lbl.get_style_context().add_class(
            'error-text')
        self._widget.attach_next_to(self._frame_interval_err_msg_lbl,
                                    frame_interval_inp_container,
                                    Gtk.PositionType.RIGHT, 1, 1)

        self._widget.show_all()

        self._frame_interval_inp.bind_property(
            'sensitive', self._frame_interval_inp, 'visibility',
            GObject.BindingFlags.SYNC_CREATE)

        self.bn_selected_image_paths = GObjectPropertyBindable(
            self._file_chooser_inp, 'file-paths')
        self.bn_frame_interval = GObjectPropertyBindable(
            self._frame_interval_inp, 'value')
        self.bn_frame_interval_sensitive = GObjectPropertyBindable(
            self._frame_interval_inp, 'sensitive')

        # Set which widget is first focused
        self._file_chooser_inp.grab_focus()

        self.presenter.view_ready()

        return self._widget
Exemple #14
0
    def _do_init(
            self,
            view_context: ImageProcessorPluginViewContext,
            tool_id: Any,
            color: Tuple[float, float, float],
            z_index: int,
    ) -> None:
        self._view_context = view_context
        self._tool_ref = view_context.get_tool_item(tool_id)

        view_context.render.connect(
            'cursor-up-event',
            lambda render, pos: self.presenter.cursor_up(pos),
        )

        view_context.render.connect(
            'cursor-down-event',
            lambda render, pos: self.presenter.cursor_down(pos),
        )

        view_context.render.connect(
            'cursor-motion-event',
            lambda render, pos: self.presenter.cursor_move(pos),
        )

        view_context.render.connect(
            'key-press-event',
            self._hdl_render_key_press_event
        )

        self.bn_tool_button_is_active = self._tool_ref.bn_is_active

        self._render = view_context.render

        self._defined_ro = Line(
            stroke_color=color,
            stroke_width=2,
            draw_control_points=False,
            z_index=z_index,
        )
        self._render.add_render_object(self._defined_ro)

        self._dragging_ro = Line(
            stroke_color=color,
            stroke_width=1,
            draw_control_points=True,
            z_index=z_index,
        )
        self._render.add_render_object(self._dragging_ro)

        self.bn_dragging = GObjectPropertyBindable(
            g_obj=self._dragging_ro,
            prop_name='line',
        )

        self.bn_defined = GObjectPropertyBindable(
            g_obj=self._defined_ro,
            prop_name='line',
        )

        self.presenter.view_ready()
Exemple #15
0
    def _do_init(self, view_context: ImageProcessorPluginViewContext) -> None:
        self._view_context = view_context
        self._tool_ref = self._view_context.get_tool_item(
            ToolID.FOREGROUND_DETECTION)

        self.bn_tool_button_is_active = self._tool_ref.bn_is_active

        self._button_body = Gtk.Grid(hexpand=True, vexpand=True)
        self._tool_ref.button_interior.add(self._button_body)

        button_lbl = Gtk.Label(
            label="Foreground detection",
            vexpand=True,
            valign=Gtk.Align.CENTER,
        )
        self._button_body.add(button_lbl)

        self._button_body.show_all()

        self._popover = Gtk.Popover(
            relative_to=self._button_body,
            modal=False,
        )

        # Prevent the popover from being dismissed by the user clicking on it.
        self._popover.connect('button-release-event', lambda *_: True)

        popover_body = Gtk.Grid(
            margin=10,
            row_spacing=10,
            column_spacing=10,
            width_request=250,
        )
        self._popover.add(popover_body)

        thresh_inp = Gtk.Adjustment(value=255, lower=1, upper=255)

        thresh_lbl = Gtk.Label('Threshold:', halign=Gtk.Align.START)
        popover_body.attach(thresh_lbl, 0, 0, 1, 1)

        thresh_scl = Gtk.Scale(orientation=Gtk.Orientation.HORIZONTAL,
                               adjustment=thresh_inp,
                               hexpand=True,
                               draw_value=False)
        thresh_scl.get_style_context().add_class('small-pad')
        thresh_scl.get_style_context().add_provider(
            self._STYLE_PROV, Gtk.STYLE_PROVIDER_PRIORITY_USER)
        thresh_scl.show()
        popover_body.attach(thresh_scl, 1, 0, 1, 1)

        thresh_ety = FloatEntry(width_chars=5, xalign=0)
        thresh_ety.get_style_context().add_class('small-pad')
        thresh_ety.get_style_context().add_provider(
            self._STYLE_PROV, Gtk.STYLE_PROVIDER_PRIORITY_USER)
        thresh_ety.show()
        popover_body.attach(thresh_ety, 2, 0, 1, 1)

        # Bind the properties of Gtk.Adjustment to the Gtk.Entry widget.
        for (src, targ), prop in itertools.product(
            ((thresh_inp, thresh_ety), ), ('value', 'lower', 'upper')):
            src.bind_property(
                prop,  # source_property
                targ,
                prop,  # target, target_property
                GObject.BindingFlags.BIDIRECTIONAL  # flags
                | GObject.BindingFlags.SYNC_CREATE,
                lambda _, v: round(v, 1),  # transform_to
                lambda _, v: v  # transform_from
            )

        self.bn_thresh = GObjectPropertyBindable(
            g_obj=thresh_inp,
            prop_name='value',
        )

        popover_body.show_all()

        self.presenter.view_ready()
Exemple #16
0
    def _do_init(self, parent_window: Optional[Gtk.Window] = None) -> Gtk.Window:
        self._window = Gtk.Window(
            title='Save analysis',
            resizable=False,
            modal=True,
            transient_for=parent_window,
            window_position=Gtk.WindowPosition.CENTER,
        )

        body = Gtk.Grid(margin=10, row_spacing=10)
        self._window.add(body)

        content = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
        body.attach(content, 0, 0, 1, 1)

        save_location_frame = Gtk.Frame(label='Save location')
        content.add(save_location_frame)
        save_location_content = Gtk.Grid(margin=10, column_spacing=10, row_spacing=5)
        save_location_frame.add(save_location_content)

        save_dir_lbl = Gtk.Label('Parent:', xalign=0)
        save_location_content.attach(save_dir_lbl, 0, 0, 1, 1)

        self._save_dir_parent_inp = Gtk.FileChooserButton(action=Gtk.FileChooserAction.SELECT_FOLDER, hexpand=True)
        self._save_dir_parent_inp.get_style_context().add_class('small-combobox')
        save_location_content.attach_next_to(self._save_dir_parent_inp, save_dir_lbl, Gtk.PositionType.RIGHT, 1, 1)

        save_dir_parent_err_lbl = Gtk.Label(xalign=0, width_request=190)
        save_dir_parent_err_lbl.get_style_context().add_class('error-text')
        save_location_content.attach_next_to(save_dir_parent_err_lbl, self._save_dir_parent_inp, Gtk.PositionType.RIGHT, 1, 1)

        save_name_lbl = Gtk.Label('Name:', xalign=0)
        save_location_content.attach(save_name_lbl, 0, 1, 1, 1)

        save_dir_name_inp = Gtk.Entry()
        save_dir_name_inp.get_style_context().add_class('small-pad')
        save_location_content.attach_next_to(save_dir_name_inp, save_name_lbl, Gtk.PositionType.RIGHT, 1, 1)

        save_dir_name_err_lbl = Gtk.Label(xalign=0, width_request=190)
        save_dir_name_err_lbl.get_style_context().add_class('error-text')
        save_location_content.attach_next_to(save_dir_name_err_lbl, save_dir_name_inp, Gtk.PositionType.RIGHT, 1, 1)

        figures_frame = Gtk.Frame(label='Figures')
        content.add(figures_frame)
        figures_content = Gtk.Grid(margin=10, column_spacing=10, row_spacing=5)
        figures_frame.add(figures_content)

        _, angles_figure_options_area = self.new_component(
            figure_options_cs.factory(
                model=self.presenter.angle_figure_options,
                figure_name='contact angles plot',
            )
        )
        angles_figure_options_area.show()
        figures_content.attach(angles_figure_options_area, 0, 0, 1, 1)

        footer = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        body.attach_next_to(footer, content, Gtk.PositionType.BOTTOM, 1, 1)

        ok_btn = Gtk.Button('OK')
        ok_btn.get_style_context().add_class('conan-analysis-saver-view-footer-button')
        footer.pack_end(ok_btn, expand=False, fill=False, padding=0)

        cancel_btn = Gtk.Button('Cancel')
        cancel_btn.get_style_context().add_class('conan-analysis-saver-view-footer-button')
        footer.pack_end(cancel_btn, expand=False, fill=False, padding=0)

        self._window.show_all()

        # Wiring things up

        ok_btn.connect('clicked', lambda *_: self.presenter.ok())
        cancel_btn.connect('clicked', lambda *_: self.presenter.cancel())

        self._window.connect('delete-event', self._hdl_window_delete_event)

        self.bn_save_dir_parent = AccessorBindable(self._get_save_dir_parent, self._set_save_dir_parent)
        self.bn_save_dir_name = GObjectPropertyBindable(save_dir_name_inp, 'text')

        self._confirm_overwrite_dialog = None
        self._file_exists_info_dialog = None

        self.presenter.view_ready()

        return self._window
Exemple #17
0
    def _do_init(self, footer_area: Gtk.Grid) -> Gtk.Widget:
        self._widget = Gtk.Grid(margin=20, row_spacing=10, column_spacing=10)

        # Label widgets
        inner_density_lbl = Gtk.Label('Inner density (kg/m³):', xalign=0)
        self._widget.attach(inner_density_lbl, 0, 0, 1, 1)

        outer_density_lbl = Gtk.Label('Outer density (kg/m³):', xalign=0)
        self._widget.attach(outer_density_lbl, 0, 1, 1, 1)

        needle_width_lbl = Gtk.Label('Needle diameter (mm):', xalign=0)
        self._widget.attach(needle_width_lbl, 0, 2, 1, 1)

        gravity_lbl = Gtk.Label('Gravity (m/s²):', xalign=0)
        self._widget.attach(gravity_lbl, 0, 3, 1, 1)

        # Input widgets
        self._inner_density_inp = FloatEntry(lower=0, width_chars=10)
        self._widget.attach_next_to(self._inner_density_inp, inner_density_lbl,
                                    Gtk.PositionType.RIGHT, 1, 1)

        self._outer_density_inp = FloatEntry(lower=0, width_chars=10)
        self._widget.attach_next_to(self._outer_density_inp, outer_density_lbl,
                                    Gtk.PositionType.RIGHT, 1, 1)

        self._needle_width_inp = FloatEntry(lower=0, width_chars=10)
        self._widget.attach_next_to(self._needle_width_inp, needle_width_lbl,
                                    Gtk.PositionType.RIGHT, 1, 1)

        self._gravity_inp = FloatEntry(lower=0, width_chars=10)
        self._widget.attach_next_to(self._gravity_inp, gravity_lbl,
                                    Gtk.PositionType.RIGHT, 1, 1)

        self._inner_density_err_msg_lbl = Gtk.Label(xalign=0)
        self._inner_density_err_msg_lbl.get_style_context().add_class(
            'error-text')
        self._widget.attach_next_to(self._inner_density_err_msg_lbl,
                                    self._inner_density_inp,
                                    Gtk.PositionType.RIGHT, 1, 1)

        self._outer_density_err_msg_lbl = Gtk.Label(xalign=0)
        self._outer_density_err_msg_lbl.get_style_context().add_class(
            'error-text')
        self._widget.attach_next_to(self._outer_density_err_msg_lbl,
                                    self._outer_density_inp,
                                    Gtk.PositionType.RIGHT, 1, 1)

        self._needle_width_err_msg_lbl = Gtk.Label(xalign=0)
        self._needle_width_err_msg_lbl.get_style_context().add_class(
            'error-text')
        self._widget.attach_next_to(self._needle_width_err_msg_lbl,
                                    self._needle_width_inp,
                                    Gtk.PositionType.RIGHT, 1, 1)

        self._gravity_err_msg_lbl = Gtk.Label(xalign=0)
        self._gravity_err_msg_lbl.get_style_context().add_class('error-text')
        self._widget.attach_next_to(self._gravity_err_msg_lbl,
                                    self._gravity_inp, Gtk.PositionType.RIGHT,
                                    1, 1)

        self._widget.show_all()

        self.bn_inner_density = GObjectPropertyBindable(
            g_obj=self._inner_density_inp,
            prop_name='value',
        )

        self.bn_outer_density = GObjectPropertyBindable(
            g_obj=self._outer_density_inp,
            prop_name='value',
        )

        self.bn_needle_width = GObjectPropertyBindable(
            g_obj=self._needle_width_inp,
            prop_name='value',
            # Needle width shown to user is in millimetres.
            transform_from=lambda x: x / 1000 if x is not None else None,
            transform_to=lambda x: x * 1000 if x is not None else None,
        )

        self.bn_gravity = GObjectPropertyBindable(
            g_obj=self._gravity_inp,
            prop_name='value',
        )

        _, footer_inside = self.new_component(
            linear_navigator_footer_cs.factory(
                do_back=self.presenter.prev_page,
                do_next=self.presenter.next_page,
            ))
        footer_inside.show()
        footer_area.add(footer_inside)

        self.presenter.view_ready()

        return self._widget
Exemple #18
0
    def _do_init(self, figure_name: str) -> Gtk.Widget:
        self._widget = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5)

        self._should_save_figure_inp = Gtk.CheckButton(
            label='Save {}'.format(figure_name))
        self._widget.add(self._should_save_figure_inp)

        self._more_options = Gtk.Grid(margin_left=30,
                                      row_spacing=5,
                                      column_spacing=10)
        self._widget.add(self._more_options)

        dpi_lbl = Gtk.Label('Figure DPI:', xalign=0)
        self._more_options.attach(dpi_lbl, 0, 0, 1, 1)

        dpi_inp_ctn = Gtk.Grid()
        self._more_options.attach_next_to(dpi_inp_ctn, dpi_lbl,
                                          Gtk.PositionType.RIGHT, 1, 1)
        dpi_inp = IntegerEntry(value=300, lower=72, upper=10000, width_chars=5)
        dpi_inp.get_style_context().add_class('small-pad')
        dpi_inp_ctn.add(dpi_inp)

        dpi_err_lbl = Gtk.Label(xalign=0, width_request=190)
        dpi_err_lbl.get_style_context().add_class('error-text')
        self._more_options.attach_next_to(dpi_err_lbl, dpi_inp_ctn,
                                          Gtk.PositionType.RIGHT, 1, 1)

        size_lbl = Gtk.Label('Figure size (cm):', xalign=0)
        self._more_options.attach(size_lbl, 0, 1, 1, 1)

        size_inp_ctn = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL,
                               spacing=5)
        self._more_options.attach_next_to(size_inp_ctn, size_lbl,
                                          Gtk.PositionType.RIGHT, 1, 1)

        size_w_lbl = Gtk.Label('W:')
        size_inp_ctn.add(size_w_lbl)
        size_w_inp = FloatEntry(value=10, lower=0, upper=10000, width_chars=6)
        size_w_inp.get_style_context().add_class('small-pad')

        size_inp_ctn.add(size_w_inp)
        size_h_lbl = Gtk.Label('H:')
        size_inp_ctn.add(size_h_lbl)

        size_h_inp = FloatEntry(value=10, lower=0, upper=10000, width_chars=6)
        size_h_inp.get_style_context().add_class('small-pad')
        size_inp_ctn.add(size_h_inp)

        size_err_lbl = Gtk.Label(xalign=0, width_request=190)
        size_err_lbl.get_style_context().add_class('error-text')
        self._more_options.attach_next_to(size_err_lbl, size_inp_ctn,
                                          Gtk.PositionType.RIGHT, 1, 1)

        self._should_save_figure_inp.bind_property(
            'active',  # source_property
            self._more_options,  # target
            'sensitive',  # target_property
            GObject.BindingFlags.SYNC_CREATE,  # flags
        )

        self.bn_should_save = GObjectPropertyBindable(
            g_obj=self._should_save_figure_inp,
            prop_name='active',
        )

        self.bn_dpi = GObjectPropertyBindable(
            g_obj=dpi_inp,
            prop_name='value',
        )

        self.bn_size_w = GObjectPropertyBindable(
            g_obj=size_w_inp,
            prop_name='value',
        )

        self.bn_size_h = GObjectPropertyBindable(
            g_obj=size_h_inp,
            prop_name='value',
        )

        self.presenter.view_ready()

        self._widget.show_all()

        return self._widget
Exemple #19
0
    def _do_init(self) -> Gtk.Widget:
        self._change_camera_dialog_cid = None  # type: Any

        self._widget = Gtk.Grid(row_spacing=10, column_spacing=10)

        # Populate self.widget

        camera_container = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5)
        self._widget.attach(camera_container, 0, 0, 2, 1)

        camera_lbl = Gtk.Label('Camera:', xalign=0)
        camera_container.add(camera_lbl)

        self._current_camera_lbl = Gtk.Label(xalign=0)
        camera_container.add(self._current_camera_lbl)

        self._change_camera_btn = Gtk.Button('Connect camera')
        self._change_camera_btn.get_style_context().add_class('small-pad')
        camera_container.add(self._change_camera_btn)

        num_frames_lbl = Gtk.Label('Number of images to capture:', xalign=0)
        self._widget.attach(num_frames_lbl, 0, 1, 1, 1)

        num_frames_inp_container = Gtk.Grid()
        self._widget.attach_next_to(num_frames_inp_container, num_frames_lbl, Gtk.PositionType.RIGHT, 1, 1)

        self._num_frames_inp = IntegerEntry(lower=1, upper=200, value=1, width_chars=6)
        self._num_frames_inp.get_style_context().add_class('small-pad')
        num_frames_inp_container.add(self._num_frames_inp)

        frame_interval_lbl = Gtk.Label('Frame interval (s):', xalign=0)
        self._widget.attach(frame_interval_lbl, 0, 2, 1, 1)

        frame_interval_inp_container = Gtk.Grid()
        self._widget.attach_next_to(frame_interval_inp_container, frame_interval_lbl, Gtk.PositionType.RIGHT, 1, 1)

        self._frame_interval_inp = FloatEntry(lower=0, width_chars=6, sensitive=False, invisible_char='\0')
        self._frame_interval_inp.get_style_context().add_class('small-pad')
        frame_interval_inp_container.add(self._frame_interval_inp)

        self._current_camera_err_msg_lbl = Gtk.Label(xalign=0)
        self._current_camera_err_msg_lbl.get_style_context().add_class('error-text')
        self._widget.attach_next_to(self._current_camera_err_msg_lbl, camera_container, Gtk.PositionType.RIGHT, 1, 1)

        self._num_frames_err_msg_lbl = Gtk.Label(xalign=0)
        self._num_frames_err_msg_lbl.get_style_context().add_class('error-text')
        self._widget.attach_next_to(self._num_frames_err_msg_lbl, num_frames_inp_container, Gtk.PositionType.RIGHT, 1, 1)

        self._frame_interval_err_msg_lbl = Gtk.Label(xalign=0)
        self._frame_interval_err_msg_lbl.get_style_context().add_class('error-text')
        self._widget.attach_next_to(self._frame_interval_err_msg_lbl, frame_interval_inp_container, Gtk.PositionType.RIGHT, 1, 1)

        self._widget.show_all()

        # Wiring things up

        self._change_camera_btn.connect('clicked', lambda *_: self.presenter.hdl_change_camera_btn_clicked())

        self.bn_frame_interval = GObjectPropertyBindable(self._frame_interval_inp, 'value')
        self.bn_num_frames = GObjectPropertyBindable(self._num_frames_inp, 'value')

        self.bn_frame_interval_sensitive = GObjectPropertyBindable(self._frame_interval_inp, 'sensitive')

        self._frame_interval_inp.bind_property(
            'sensitive',
            self._frame_interval_inp,
            'visibility',
            GObject.BindingFlags.SYNC_CREATE
        )

        self.presenter.view_ready()

        return self._widget