Пример #1
0
 def __init__(self, group, text, pos, fsize=18, padding=8, name='', **kwargs):
     """Radiobutton with a optional text label.
     group - the widget to which this button belongs. (must be None or another radiobutton)
     text - string to display
     pos - position to display the box
     fsize - Font size
     padding - space in pixels around the text
     name - string to indicate this object
     kwargs - bgcol, fgcol
     """
     self.box_pos = pos
     self.image_pos = (pos[0]+1, pos[1]+1)
     self.name = name
     
     if not group:
         self._rb_group = [self]
     else:
         self._rb_group = group._rb_group + [self]
         for rb in self._rb_group:
             rb._rb_group = self._rb_group
     self._rb_selected = False
     box = pygame.Surface((18, 18))
     box.fill(WHITE)
     rect = box.get_rect()
     lbl = Label(text, (pos[0] + 10 + rect.width, pos[1]), fsize=18, transparent=True, \
                         fgcol=WHITE, bold=True)
     lbl.display_sprite()
     pygame.draw.line(box, GREY30, (0, 0), (18, 0), 1)
     pygame.draw.line(box, GREY30, (0, 0), (0, 18), 1)
     pygame.draw.line(box, GREY30, (17, 0), (17, 17), 1)
     pygame.draw.line(box, GREY30, (1, 17), (17, 17), 1)
     self.box = box.convert()
     Widget.__init__(self, box, name=name)
     self.selected_image = utils.load_image(os.path.join(self.THEME['defaultpath'], 'radiobut_selected.png'))
     self.moveto(self.box_pos)
     self.connect_callback(self._cbf_on_select, MOUSEBUTTONUP)
Пример #2
0
    def __init__(self, interactor, action=None, corner_radius=5, width=None, font="Arial",
                 height=None, left=0, top=0, image=None, label="", bgcolor=(.5, .5, .5), fgcolor=(1,1,1),
                 opacity=1, size=14, states = None, halign=LEFT_ALIGN, valign=CENTER_ALIGN, tooltip=None, tooltip_property=None):
        """
        @kwargs:
            action: A callback function that will receive the current state ID when the button is clicked.
            width: if width is None, use the size of the label to determine width
            height: if height is None, use the size of the label to determine height
            left: Distance from the left of the window to place the button
            top: Distance from the top of the window to place the button
            image: Icon to place on top of the background
            label: Default label to use for all states (if no states are provided, creates a state using defaults)
            bgcolor: Default background color of the button (if states do not provide a bgcolor, this one is used)
            fgcolor: Default font color of the label (if states do not provide an fgcolor, this one is used)
            opacity: Default opacity of button & label (if states do not provide an opacity, this one is used)
            size: Default font size of the label (if states do not provide a font size, this one is used)
            halign: If the button states have multiple widths (different labels/images), this will align them horizontally as specified
            valign: If the button states have multiple heights (labels with newlines, images), this will align them vertically as specified
        """

        self.width = width
        self.height = height
        self.left = left
        self.top = top
        self.radius = corner_radius
        self.action = action

        if halign not in (LEFT_ALIGN, RIGHT_ALIGN, CENTER_ALIGN):
            raise TypeError("halign must be one of LEFT_ALIGN, RIGHT_ALIGN, or CENTER_ALIGN")
        self.halign = halign

        if valign not in (TOP_ALIGN, BOTTOM_ALIGN, CENTER_ALIGN):
            raise TypeError("valign must be one of TOP_ALIGN, BOTTOM_ALIGN, or CENTER_ALIGN")
        self.valign = valign
        if image:
            self.image = load_image(image)
        else:
            self.image = None

        self.__placing__ = False

        text = states[0].label if states else label
        # Text widget will be placed over the button; clicks on it have to propogate down
        self.text_widget = Label(interactor, text, on_click = self.__advance__, size=size, font=font)

        self.label = label
        self.size = size
        self.opacity = opacity
        self.fgcolor = fgcolor
        self.bgcolor = bgcolor

        if states:
            self.states = states
        else:
            self.states = [ButtonState(label=label)]

        widget = vtk.vtkButtonWidget()
        widget.SetRepresentation(vtk.vtkTexturedButtonRepresentation2D())

        super(Button, self).__init__(interactor, widget)

        if tooltip:
            if tooltip_property is not None:
                tooltip_property.SetVerticalJustificationToTop()
            self.tooltip_label = Label(interactor, tooltip, textproperty=tooltip_property)
            self.hover_handler = self.interactor.AddObserver("MouseMoveEvent", self.hover)
            self.hover_timer = None
            self.timer_handler = self.interactor.AddObserver("TimerEvent", self.still_hovering)

        self.update()
        self.subscribe( 'StateChangedEvent', self.clicked)
Пример #3
0
class Button(Widget):
    def __init__(self, interactor, action=None, corner_radius=5, width=None, font="Arial",
                 height=None, left=0, top=0, image=None, label="", bgcolor=(.5, .5, .5), fgcolor=(1,1,1),
                 opacity=1, size=14, states = None, halign=LEFT_ALIGN, valign=CENTER_ALIGN, tooltip=None, tooltip_property=None):
        """
        @kwargs:
            action: A callback function that will receive the current state ID when the button is clicked.
            width: if width is None, use the size of the label to determine width
            height: if height is None, use the size of the label to determine height
            left: Distance from the left of the window to place the button
            top: Distance from the top of the window to place the button
            image: Icon to place on top of the background
            label: Default label to use for all states (if no states are provided, creates a state using defaults)
            bgcolor: Default background color of the button (if states do not provide a bgcolor, this one is used)
            fgcolor: Default font color of the label (if states do not provide an fgcolor, this one is used)
            opacity: Default opacity of button & label (if states do not provide an opacity, this one is used)
            size: Default font size of the label (if states do not provide a font size, this one is used)
            halign: If the button states have multiple widths (different labels/images), this will align them horizontally as specified
            valign: If the button states have multiple heights (labels with newlines, images), this will align them vertically as specified
        """

        self.width = width
        self.height = height
        self.left = left
        self.top = top
        self.radius = corner_radius
        self.action = action

        if halign not in (LEFT_ALIGN, RIGHT_ALIGN, CENTER_ALIGN):
            raise TypeError("halign must be one of LEFT_ALIGN, RIGHT_ALIGN, or CENTER_ALIGN")
        self.halign = halign

        if valign not in (TOP_ALIGN, BOTTOM_ALIGN, CENTER_ALIGN):
            raise TypeError("valign must be one of TOP_ALIGN, BOTTOM_ALIGN, or CENTER_ALIGN")
        self.valign = valign
        if image:
            self.image = load_image(image)
        else:
            self.image = None

        self.__placing__ = False

        text = states[0].label if states else label
        # Text widget will be placed over the button; clicks on it have to propogate down
        self.text_widget = Label(interactor, text, on_click = self.__advance__, size=size, font=font)

        self.label = label
        self.size = size
        self.opacity = opacity
        self.fgcolor = fgcolor
        self.bgcolor = bgcolor

        if states:
            self.states = states
        else:
            self.states = [ButtonState(label=label)]

        widget = vtk.vtkButtonWidget()
        widget.SetRepresentation(vtk.vtkTexturedButtonRepresentation2D())

        super(Button, self).__init__(interactor, widget)

        if tooltip:
            if tooltip_property is not None:
                tooltip_property.SetVerticalJustificationToTop()
            self.tooltip_label = Label(interactor, tooltip, textproperty=tooltip_property)
            self.hover_handler = self.interactor.AddObserver("MouseMoveEvent", self.hover)
            self.hover_timer = None
            self.timer_handler = self.interactor.AddObserver("TimerEvent", self.still_hovering)

        self.update()
        self.subscribe( 'StateChangedEvent', self.clicked)

    def hover(self, obj, event):
        if self.widget.GetEnabled() == 0:
            return

        x, y = self.interactor.GetEventPosition()

        if self.hover_timer is None and self.tooltip_label.showing() == False:
            if self.in_bounds(x, y):
                self.hover_timer = self.interactor.CreateOneShotTimer(300)

        if self.in_bounds(x, y) == False:
            if self.hover_timer is not None:
                self.interactor.DestroyTimer(self.hover_timer)
                self.hover_timer = None
            if self.tooltip_label.showing():
                self.tooltip_label.hide()

    def still_hovering(self, obj, event):
        if self.hover_timer:
            self.tooltip_label.place()
            self.tooltip_label.show()
            self.hover_timer = None

    def get_text(self):
        return self.text_widget.get_text()

    def add_state(self, label=None, image=None, bgcolor=None, fgcolor=None, opacity=None):
        self.states.append(ButtonState(label=label, image=image, bgcolor=bgcolor, fgcolor=fgcolor, opacity=opacity))

    def place(self):

        width, height = self.get_dimensions()
        x, y = self.get_position()
        bounds = (x, x + width, y - height, y, 0, 0)
        self.repr.SetPlaceFactor(1)
        self.repr.PlaceWidget(bounds)
        self.repr.Modified()
        if self.showing():
            # This One Weird Hack will make your Buttons Go In the Right Place - Developers hate it!
            # Buttons weren't always getting properly placed (toolbars in toolbars being the canonical example)
            # This makes them show up correctly. Weird, but it works.
            h_state = self.repr.GetHighlightState()
            self.repr.Highlight((h_state + 1) % 3)
            self.repr.Highlight(h_state)

        text_width, text_height = self.text_widget.get_dimensions()
        swidth, sheight = self.interactor.GetRenderWindow().GetSize()

        self.text_widget.left = x + (width - text_width) / 2.0
        self.text_widget.top = sheight - y + BUTTON_MARGIN

        self.text_widget.place()

        try:
            w, h = self.tooltip_label.get_dimensions()

            if x + 5 + w < swidth:
                self.tooltip_label.left = x + 5
            else:
                self.tooltip_label.left = swidth - w - 5

            self.tooltip_label.top = sheight - (y - height)
            self.tooltip_label.place()
        except AttributeError:
            pass


    def get_dimensions(self):
        image = self.repr.GetButtonTexture(self.repr.GetState())
        width, height, _ = image.GetDimensions()

        return width, height

    def update(self):
        self.repr.SetNumberOfStates(len(self.states))

        max_width = 0
        max_height = 0

        for index, state in enumerate(self.states):
            # Set up attributes with defaults if nothing is set
            label_text = state.label if state.label else self.label
            image = state.image if state.image else self.image

            if image:
                # Image supersedes label
                w, h, _ = image.GetDimensions()
                # Use a 3 px padding for now
                max_height = max(max_height, h)
                max_width = max(max_width, w)

            elif label_text:
                l_w, l_h = text_dimensions(label_text, self.text_widget.actor.GetTextProperty())

                max_height = max(max_height, l_h)
                max_width = max(max_width, l_w)

        # Pad the text
        max_width += 2 * BUTTON_MARGIN
        max_height += 2 * BUTTON_MARGIN

        for index, state in enumerate(self.states):

            image = state.image if state.image else self.image
            bgcolor = state.bgcolor if state.bgcolor else self.bgcolor
            # Opacity not yet supported by this code
            #opacity = state.opacity if state.opacity else self.opacity

            # Something weird happens when images of drastically different sizes are passed in;
            # not hunting down that fix right now.
            if image is not None:
                width, height, _ = image.GetDimensions()
            else:
                width = self.width if self.width else int(max_width)
                height = self.height if self.height else int(max_height)

            # Optimization can be done here; can use the same image for everything with same bgcolor + h/w
            bg_image = rounded_rect(width, height, self.radius, bgcolor)
            if image is not None:
                image = pad_image(image, max_width, max_height)
                bg_image = combine_images(bg_image, image)

            # Should deal with opacity here-ish
            self.repr.SetButtonTexture(index, bg_image)

    def get_position(self):
        default_texture = self.repr.GetButtonTexture(0)
        dwidth, dheight, _ = default_texture.GetDimensions()
        width, height = self.get_dimensions()

        window = self.interactor.GetRenderWindow()
        size = window.GetSize()

        if self.halign == LEFT_ALIGN:
            left = self.left
        elif self.halign == CENTER_ALIGN:
            left = (self.left - (width - dwidth) / 2)
        elif self.halign == RIGHT_ALIGN:
            left = size[0] - self.left - width

        if dheight == height or self.valign == TOP_ALIGN:
            top = self.top
        elif self.valign == CENTER_ALIGN:
            top = (self.top - (height - dheight) / 2)
        elif self.valign == BOTTOM_ALIGN:
            top = size[1] - (self.top - (height - dheight))

        return left, size[1] - top

    def get_state(self):
        return self.repr.GetState()

    def set_state(self, state):
        new_state = self.states[state]
        label = self.label if new_state.label is None else new_state.label
        self.text_widget.set_text(label)
        self.repr.SetState(state)
        self.place()

    def show(self):
        super(Button, self).show()
        self.text_widget.show()
        self.place()

    def detach(self):
        self.text_widget.detach()
        self.text_widget = None
        try:
            self.tooltip_label.detach()
            self.tooltip_label = None
            self.interactor.RemoveObserver(self.hover_handler)
        except:
            pass
        self.action = None
        super(Button, self).detach()

    def hide(self):
        super(Button, self).hide()
        try:
            self.tooltip_label.hide()
        except AttributeError:
            pass
        self.text_widget.hide()

    def in_bounds(self, x, y):
        w, h = self.get_dimensions()
        box_x, box_y = self.get_position()
        return x < box_x + w and x > box_x and y > box_y - h and y < box_y

    def __advance__(self, point):
        state = self.repr.GetState()
        self.set_state( (state + 1) % len(self.states) )
        self.clicked(self.widget, "StateChangedEvent")

    def clicked(self, obj, event):
        state = self.get_state()
        button_state = self.states[state]

        self.text_widget.set_text( button_state.label if button_state.label else self.label )
        self.text_widget.set_font_color( button_state.fgcolor if button_state.fgcolor else self.fgcolor )
        self.place()
        if self.action:
            self.action(state)

    def copy(self, interactor, button_type=None, button_args=None, button_kwargs=None, skip_args=None):
        # In the future, we'll want to do some optimization with states and images here.
        b = Button(interactor, action=self.action, corner_radius=self.radius, width=self.width,
             height=self.height, left=self.left, top=self.top, image=self.image, label=self.label, bgcolor=self.bgcolor, fgcolor=self.fgcolor,
             opacity=self.opacity, size=self.size, states = self.states, halign=self.halign, valign=self.valign)

        state = self.get_state()
        if state != 0:
            b.set_state(state)
            b.action(state)

        return b
Пример #4
0
    def __init__(self,
                 interactor,
                 action=None,
                 corner_radius=5,
                 width=None,
                 font="Arial",
                 height=None,
                 left=0,
                 top=0,
                 image=None,
                 label="",
                 bgcolor=(.5, .5, .5),
                 fgcolor=(1, 1, 1),
                 opacity=1,
                 size=14,
                 states=None,
                 halign=LEFT_ALIGN,
                 valign=CENTER_ALIGN,
                 tooltip=None,
                 tooltip_property=None):
        """
        @kwargs:
            action: A callback function that will receive the current state ID when the button is clicked.
            width: if width is None, use the size of the label to determine width
            height: if height is None, use the size of the label to determine height
            left: Distance from the left of the window to place the button
            top: Distance from the top of the window to place the button
            image: Icon to place on top of the background
            label: Default label to use for all states (if no states are provided, creates a state using defaults)
            bgcolor: Default background color of the button (if states do not provide a bgcolor, this one is used)
            fgcolor: Default font color of the label (if states do not provide an fgcolor, this one is used)
            opacity: Default opacity of button & label (if states do not provide an opacity, this one is used)
            size: Default font size of the label (if states do not provide a font size, this one is used)
            halign: If the button states have multiple widths (different labels/images), this will align them horizontally as specified
            valign: If the button states have multiple heights (labels with newlines, images), this will align them vertically as specified
        """  # noqa

        self.width = width
        self.height = height
        self.left = left
        self.top = top
        self.radius = corner_radius
        self.action = action

        if halign not in (LEFT_ALIGN, RIGHT_ALIGN, CENTER_ALIGN):
            raise TypeError(
                "halign must be one of LEFT_ALIGN, RIGHT_ALIGN, or CENTER_ALIGN"
            )
        self.halign = halign

        if valign not in (TOP_ALIGN, BOTTOM_ALIGN, CENTER_ALIGN):
            raise TypeError(
                "valign must be one of TOP_ALIGN, BOTTOM_ALIGN, or CENTER_ALIGN"
            )
        self.valign = valign
        if image:
            self.image = load_image(image)
        else:
            self.image = None

        self.__placing__ = False

        text = states[0].label if states else label
        # Text widget will be placed over the button; clicks on it have to
        # propogate down
        self.text_widget = Label(interactor,
                                 text,
                                 on_click=self.__advance__,
                                 size=size,
                                 font=font)

        self.label = label
        self.size = size
        self.opacity = opacity
        self.fgcolor = fgcolor
        self.bgcolor = bgcolor

        if states:
            self.states = states
        else:
            self.states = [ButtonState(label=label)]

        widget = vtk.vtkButtonWidget()
        widget.SetRepresentation(vtk.vtkTexturedButtonRepresentation2D())

        super(Button, self).__init__(interactor, widget)

        if tooltip:
            if tooltip_property is not None:
                tooltip_property.SetVerticalJustificationToTop()
            self.tooltip_label = Label(interactor,
                                       tooltip,
                                       textproperty=tooltip_property)
            self.hover_handler = self.interactor.AddObserver(
                "MouseMoveEvent", self.hover)
            self.hover_timer = None
            self.timer_handler = self.interactor.AddObserver(
                "TimerEvent", self.still_hovering)

        self.update()
        self.subscribe('StateChangedEvent', self.clicked)
Пример #5
0
class Button(Widget):
    def __init__(self,
                 interactor,
                 action=None,
                 corner_radius=5,
                 width=None,
                 font="Arial",
                 height=None,
                 left=0,
                 top=0,
                 image=None,
                 label="",
                 bgcolor=(.5, .5, .5),
                 fgcolor=(1, 1, 1),
                 opacity=1,
                 size=14,
                 states=None,
                 halign=LEFT_ALIGN,
                 valign=CENTER_ALIGN,
                 tooltip=None,
                 tooltip_property=None):
        """
        @kwargs:
            action: A callback function that will receive the current state ID when the button is clicked.
            width: if width is None, use the size of the label to determine width
            height: if height is None, use the size of the label to determine height
            left: Distance from the left of the window to place the button
            top: Distance from the top of the window to place the button
            image: Icon to place on top of the background
            label: Default label to use for all states (if no states are provided, creates a state using defaults)
            bgcolor: Default background color of the button (if states do not provide a bgcolor, this one is used)
            fgcolor: Default font color of the label (if states do not provide an fgcolor, this one is used)
            opacity: Default opacity of button & label (if states do not provide an opacity, this one is used)
            size: Default font size of the label (if states do not provide a font size, this one is used)
            halign: If the button states have multiple widths (different labels/images), this will align them horizontally as specified
            valign: If the button states have multiple heights (labels with newlines, images), this will align them vertically as specified
        """  # noqa

        self.width = width
        self.height = height
        self.left = left
        self.top = top
        self.radius = corner_radius
        self.action = action

        if halign not in (LEFT_ALIGN, RIGHT_ALIGN, CENTER_ALIGN):
            raise TypeError(
                "halign must be one of LEFT_ALIGN, RIGHT_ALIGN, or CENTER_ALIGN"
            )
        self.halign = halign

        if valign not in (TOP_ALIGN, BOTTOM_ALIGN, CENTER_ALIGN):
            raise TypeError(
                "valign must be one of TOP_ALIGN, BOTTOM_ALIGN, or CENTER_ALIGN"
            )
        self.valign = valign
        if image:
            self.image = load_image(image)
        else:
            self.image = None

        self.__placing__ = False

        text = states[0].label if states else label
        # Text widget will be placed over the button; clicks on it have to
        # propogate down
        self.text_widget = Label(interactor,
                                 text,
                                 on_click=self.__advance__,
                                 size=size,
                                 font=font)

        self.label = label
        self.size = size
        self.opacity = opacity
        self.fgcolor = fgcolor
        self.bgcolor = bgcolor

        if states:
            self.states = states
        else:
            self.states = [ButtonState(label=label)]

        widget = vtk.vtkButtonWidget()
        widget.SetRepresentation(vtk.vtkTexturedButtonRepresentation2D())

        super(Button, self).__init__(interactor, widget)

        if tooltip:
            if tooltip_property is not None:
                tooltip_property.SetVerticalJustificationToTop()
            self.tooltip_label = Label(interactor,
                                       tooltip,
                                       textproperty=tooltip_property)
            self.hover_handler = self.interactor.AddObserver(
                "MouseMoveEvent", self.hover)
            self.hover_timer = None
            self.timer_handler = self.interactor.AddObserver(
                "TimerEvent", self.still_hovering)

        self.update()
        self.subscribe('StateChangedEvent', self.clicked)

    def hover(self, obj, event):
        if self.widget.GetEnabled() == 0:
            return

        x, y = self.interactor.GetEventPosition()

        if self.hover_timer is None and self.tooltip_label.showing() is False:
            if self.in_bounds(x, y):
                self.hover_timer = self.interactor.CreateOneShotTimer(300)

        if self.in_bounds(x, y) is False:
            if self.hover_timer is not None:
                self.interactor.DestroyTimer(self.hover_timer)
                self.hover_timer = None
            if self.tooltip_label.showing():
                self.tooltip_label.hide()

    def still_hovering(self, obj, event):
        if self.hover_timer:
            self.tooltip_label.place()
            self.tooltip_label.show()
            self.hover_timer = None

    def get_text(self):
        return self.text_widget.get_text()

    def add_state(self,
                  label=None,
                  image=None,
                  bgcolor=None,
                  fgcolor=None,
                  opacity=None):
        self.states.append(
            ButtonState(label=label,
                        image=image,
                        bgcolor=bgcolor,
                        fgcolor=fgcolor,
                        opacity=opacity))

    def place(self):

        width, height = self.get_dimensions()
        x, y = self.get_position()
        bounds = (x, x + width, y - height, y, 0, 0)
        self.repr.SetPlaceFactor(1)
        self.repr.PlaceWidget(bounds)
        self.repr.Modified()
        if self.showing():
            # This One Weird Hack will make your Buttons Go In the Right Place - Developers hate it!
            # Buttons weren't always getting properly placed (toolbars in toolbars being the canonical example)
            # This makes them show up correctly. Weird, but it works.
            h_state = self.repr.GetHighlightState()
            self.repr.Highlight((h_state + 1) % 3)
            self.repr.Highlight(h_state)
        else:
            # Can't properly place if not showing, so let's save some cycles.
            return
        text_width, text_height = self.text_widget.get_dimensions()
        swidth, sheight = self.interactor.GetRenderWindow().GetSize()

        self.text_widget.left = x + (width - text_width) / 2.0
        self.text_widget.top = sheight - y + BUTTON_MARGIN

        self.text_widget.place()

        try:
            w, h = self.tooltip_label.get_dimensions()

            if x + 5 + w < swidth:
                self.tooltip_label.left = x + 5
            else:
                self.tooltip_label.left = swidth - w - 5

            self.tooltip_label.top = sheight - (y - height)
            self.tooltip_label.place()
        except AttributeError:
            pass

    def get_dimensions(self):
        image = self.repr.GetButtonTexture(self.repr.GetState())
        width, height, _ = image.GetDimensions()

        return width, height

    def update(self):
        self.repr.SetNumberOfStates(len(self.states))
        dpi = self.interactor.GetRenderWindow().GetDPI()

        max_width = 0
        max_height = 0

        for index, state in enumerate(self.states):
            # Set up attributes with defaults if nothing is set
            label_text = state.label if state.label else self.label
            image = state.image if state.image else self.image

            if image:
                # Image supersedes label
                w, h, _ = image.GetDimensions()
                # Use a 3 px padding for now
                max_height = max(max_height, h)
                max_width = max(max_width, w)

            elif label_text:
                l_w, l_h = text_dimensions(
                    label_text, self.text_widget.actor.GetTextProperty(), dpi)

                max_height = max(max_height, l_h)
                max_width = max(max_width, l_w)

        # Pad the text
        max_width += 2 * BUTTON_MARGIN
        max_height += 2 * BUTTON_MARGIN

        for index, state in enumerate(self.states):

            image = state.image if state.image else self.image
            bgcolor = state.bgcolor if state.bgcolor else self.bgcolor
            # Opacity not yet supported by this code
            # opacity = state.opacity if state.opacity else self.opacity

            # Something weird happens when images of drastically different sizes are passed in;
            # not hunting down that fix right now.
            if image is not None:
                width, height, _ = image.GetDimensions()
            else:
                width = self.width if self.width else int(max_width)
                height = self.height if self.height else int(max_height)

            # Optimization can be done here; can use the same image for
            # everything with same bgcolor + h/w
            bg_image = rounded_rect(width, height, self.radius, bgcolor)
            if image is not None:
                image = pad_image(image, max_width, max_height)
                bg_image = combine_images(bg_image, image)

            # Should deal with opacity here-ish
            self.repr.SetButtonTexture(index, bg_image)

    def get_position(self):
        default_texture = self.repr.GetButtonTexture(0)
        dwidth, dheight, _ = default_texture.GetDimensions()
        width, height = self.get_dimensions()

        window = self.interactor.GetRenderWindow()
        size = window.GetSize()

        if self.halign == LEFT_ALIGN:
            left = self.left
        elif self.halign == CENTER_ALIGN:
            left = (self.left - (width - dwidth) / 2)
        elif self.halign == RIGHT_ALIGN:
            left = size[0] - self.left - width

        if dheight == height or self.valign == TOP_ALIGN:
            top = self.top
        elif self.valign == CENTER_ALIGN:
            top = (self.top - (height - dheight) / 2)
        elif self.valign == BOTTOM_ALIGN:
            top = size[1] - (self.top - (height - dheight))

        return left, size[1] - top

    def get_state(self):
        return self.repr.GetState()

    def set_state(self, state):
        new_state = self.states[state]
        label = self.label if new_state.label is None else new_state.label
        self.text_widget.set_text(label)
        self.repr.SetState(state)
        self.place()

    def show(self):
        super(Button, self).show()
        self.text_widget.show()
        self.place()

    def detach(self):
        self.text_widget.detach()
        self.text_widget = None
        try:
            self.tooltip_label.detach()
            self.tooltip_label = None
            self.interactor.RemoveObserver(self.hover_handler)
        except:
            pass
        self.action = None
        super(Button, self).detach()

    def hide(self):
        super(Button, self).hide()
        try:
            self.tooltip_label.hide()
        except AttributeError:
            pass
        self.text_widget.hide()

    def in_bounds(self, x, y):
        w, h = self.get_dimensions()
        box_x, box_y = self.get_position()
        return x < box_x + w and x > box_x and y > box_y - h and y < box_y

    def __advance__(self, point):
        state = self.repr.GetState()
        self.set_state((state + 1) % len(self.states))
        self.clicked(self.widget, "StateChangedEvent")

    def clicked(self, obj, event):
        state = self.get_state()
        button_state = self.states[state]

        self.text_widget.set_text(
            button_state.label if button_state.label else self.label)
        self.text_widget.set_font_color(
            button_state.fgcolor if button_state.fgcolor else self.fgcolor)
        self.place()
        if self.action:
            self.action(state)

    def copy(self,
             interactor,
             button_type=None,
             button_args=None,
             button_kwargs=None,
             skip_args=None):
        # In the future, we'll want to do some optimization with states and
        # images here.
        b = Button(interactor,
                   action=self.action,
                   corner_radius=self.radius,
                   width=self.width,
                   height=self.height,
                   left=self.left,
                   top=self.top,
                   image=self.image,
                   label=self.label,
                   bgcolor=self.bgcolor,
                   fgcolor=self.fgcolor,
                   opacity=self.opacity,
                   size=self.size,
                   states=self.states,
                   halign=self.halign,
                   valign=self.valign)

        state = self.get_state()
        if state != 0:
            b.set_state(state)
            b.action(state)

        return b
Пример #6
0
import sys

from PySide2.QtGui import QIcon, QStandardItem, QStandardItemModel
from PySide2.QtCore import QObject, QRunnable, Qt, QThread, QThreadPool, Signal, Slot


class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent=parent)
        self.setupUi(self)

    @Slot(str)
    def cs(self):
        print("x")
        self.lineEdit.setPlaceholderText("gnuh")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = MainWindow()
    options_model = QStandardItemModel(w.listView)
    individual_option = QStandardItem("butts")
    options_model.appendRow(individual_option)

    w.pushButton.clicked.connect(w.cs)
    w.pushButton.clicked.connect(call_conan)

    w.verticalLayout.addWidget(QPushButton("wee!"))
    w.verticalLayout.addWidget(Label("An Label"))
    w.show()
    sys.exit(app.exec_())
Пример #7
0
    def __init__(self, name):
        super().__init__()
        print('loading subcircuit {}...'.format(name))
        if not os.path.isdir(os.path.join('subcircuits', name)):
            raise ValueError('subcircuit {} does not exist'.format(name))
        if not os.path.isfile(os.path.join('subcircuits', name, '{}.circuit.txt'.format(name))):
            raise ValueError('missing .circuit.txt file for subcircuit {}'.format(name))
        cols = GridDimension(False)
        rows = GridDimension(True)
        self._name = name
        self._pins = Pins()
        self._interfaces = []
        self._net_insns = []
        self._net_ties = []
        self._instances = []
        self._routers = []
        self._shunters = []
        self._outlines = []
        self._labels = []
        instance_names = set()
        forwarded_pins = []
        with open(os.path.join('subcircuits', name, '{}.circuit.txt'.format(name)), 'r') as f:
            for line in f.read().split('\n'):
                line = line.split('#', maxsplit=1)[0].strip()
                if not line:
                    continue
                args = line.split()

                if args[0] == 'columns':
                    cols.configure(*args[1:])
                    continue

                if args[0] == 'rows':
                    rows.configure(*args[1:])
                    continue

                if args[0] in ('in', 'out'):
                    coord = (cols.convert(args[3]), rows.convert(args[4]))
                    self._pins.add(args[1], args[0], args[2], (0, 0), coord, 0.0)
                    name = '.{}'.format(args[1])
                    self._net_insns.append((name, args[2], (0, 0), coord, 0.0, args[0]))
                    continue

                if args[0] in ('fwd_in', 'fwd_out'):
                    forwarded_pins.append((args[0][4:], args[1]))
                    continue

                if args[0] in ('prim', 'subc'):
                    coord = (cols.convert(args[4]), rows.convert(args[5]))
                    rotation = float(args[3]) / 180 * math.pi
                    instance_type = args[1]
                    instance_name = args[2]
                    if instance_name in instance_names:
                        raise ValueError('duplicate instance name {}'.format(instance_name))
                    instance_names.add(instance_name)
                    if args[0] == 'prim' and instance_type == 'tie':
                        master = args[-1].split('=', maxsplit=1)[1]
                        for arg in args[6:-1]:
                            slave = arg.split('=', maxsplit=1)[1]
                            self._net_ties.append(('.' + master, '.' + slave))
                    instance = Instance(
                        args[0] == 'prim', instance_type, instance_name,
                        coord, rotation, *args[6:]
                    )
                    for pin, net in instance.get_pinmap():
                        if pin.is_output():
                            mode = 'driver' if args[0] == 'prim' else 'in'
                        else:
                            mode = 'user' if args[0] == 'prim' else 'out'
                        self._net_insns.append((
                            net,
                            pin.get_layer(),
                            pin.get_coord(),
                            transrot(pin.get_translate(), coord, rotation),
                            pin.get_rotate() + rotation,
                            mode
                        ))
                    self._instances.append(instance)
                    for direction, vhd_type, iface in instance.get_data().get_interfaces():
                        self._interfaces.append((direction, vhd_type, '{}_{}'.format(instance_name, iface)))
                    continue

                if args[0] == 'route':
                    self._routers.append((cols.convert(args[1]), ['.{}'.format(x) for x in args[2:]]))
                    continue

                if args[0] == 'shunt':
                    coord1 = (cols.convert(args[1]), rows.convert(args[2]))
                    net1 = '.{}'.format(args[3])
                    coord2 = (cols.convert(args[4]), rows.convert(args[5]))
                    net2 = '.{}'.format(args[6])
                    layer = args[7]
                    self._shunters.append((coord1, coord2, layer))
                    self._net_insns.append((net1, layer, (0, 0), coord1, 0, 'user'))
                    self._net_insns.append((net2, layer, (0, 0), coord2, 0, 'user'))
                    continue

                if args[0] in 'outline':
                    self._outlines.append((
                        cols.convert(args[1]),
                        rows.convert(args[2]),
                        cols.convert(args[3]),
                        rows.convert(args[4]),
                        from_mm(args[5]), # expansion
                        from_mm(args[6]), # corner radius
                        args[7]
                    ))
                    continue

                if args[0] == 'text':
                    text = args[1].replace('~', ' ')
                    coord = (cols.convert(args[3]) + from_mm(args[5]), rows.convert(args[4]) + from_mm(args[6]))
                    rotation = float(args[2]) / 180 * math.pi
                    scale = float(args[7]) if len(args) > 7 else 1.0
                    halign = float(args[8]) if len(args) > 8 else 0.5
                    valign = float(args[9]) if len(args) > 9 else None
                    self._labels.append(Label(text, coord, rotation, scale, halign, valign))
                    continue

                print('warning: unknown subcircuit construct: {}'.format(line))

        forwarded_pin_nets = set()
        for direction, name in forwarded_pins:
            insns = []
            for insn in self._net_insns:
                if insn[0] == '.' + name:
                    insns.append(insn)
            if not insns:
                raise ValueError('cannot forward pins for nonexistant net {}'.format(name))
            if len(insns) != 1:
                raise ValueError('multiple pins exist for forwarded pin {}; this is not supported'.format(name))
            net, layer, coord, translate, rotate, mode = insns[0]
            self._pins.add(name, direction, layer, coord, translate, rotate)
            self._net_insns.append((net, layer, coord, translate, rotate, direction))
            forwarded_pin_nets.add(net)

        print('doing basic DRC for subcircuit {}...'.format(self._name))
        netlist = Netlist()
        for net, layer, coord, translate, rotate, mode in self._net_insns:
            netlist.add(net, layer, transrot(coord, translate, rotate), mode)
        good = netlist.check_subcircuit()
        unrouted = set(map(lambda x: x.get_name(), netlist.iter_logical()))
        routed = set()
        for x, nets in self._routers:
            ranges = []
            for net in nets:
                if net in routed:
                    print('net {} is routed multiple times'.format(net))
                    good = False
                elif net not in unrouted:
                    print('net {} cannot be routed because it does not exist'.format(net))
                    good = False
                routed.add(net)
                unrouted.remove(net)
                y_min = None
                y_max = None
                for _, (_, y), _ in netlist.get_logical(net).iter_points():
                    if y_min is None or y < y_min:
                        y_min = y
                    if y_max is None or y > y_max:
                        y_max = y
                assert y_min is not None
                assert y_max is not None
                ranges.append((y_min, y_max, net))
            ranges.sort()
            for i in range(len(ranges) - 1):
                if ranges[i+1][0] - from_mm(0.5) < ranges[i][1]:
                    print('nets {} and {} overlap in routing column;'.format(ranges[i][2], ranges[i+1][2]))
                    print('  {} goes down to Y{} and {} up to Y{} at X{}'.format(
                        ranges[i+1][2], to_mm(ranges[i+1][0]),
                        ranges[i][2], to_mm(ranges[i][1]),
                        to_mm(x)))
                    good = False
        for net in forwarded_pin_nets:
            if net in routed:
                print('net {} is routed multiple times'.format(net))
                good = False
            elif net not in unrouted:
                print('net {} cannot be routed because it does not exist'.format(net))
                good = False
            routed.add(net)
            unrouted.remove(net)
        for net in unrouted:
            print('net {} is not routed'.format(net))
            good = False
        if not good:
            raise ValueError('basic DRC failed for subcircuit {}'.format(self._name))
        print('finished loading subcircuit {}, basic DRC passed'.format(self._name))

        # Write VHDL for the netlist.
        with open(os.path.join('subcircuits', self._name, '{}.gen.vhd'.format(self._name)), 'w') as f:
            f.write('library ieee;\nuse ieee.std_logic_1164.all;\n\nentity {} is\n  port (\n'.format(self._name))

            pin_directions = {}
            for pin in self._pins:
                direction = pin.get_direction()
                pin = pin.get_name().split('~')[0].split('*')[0]
                if pin in pin_directions:
                    if direction == 'out':
                        pin_directions[pin] = 'out'
                else:
                    pin_directions[pin] = direction

            first = True
            nets = set()
            for pin in self._pins:
                pin = pin.get_name().split('~')[0].split('*')[0]
                direction = pin_directions[pin]
                if pin in nets:
                    continue
                nets.add(pin)
                if first:
                    first = False
                else:
                    f.write(';\n')
                f.write('    {} : {} std_logic'.format(pin, direction))
            for direction, vhd_type, iface_name in self._interfaces:
                if first:
                    first = False
                else:
                    f.write(';\n')
                f.write('    if_{} : {} {}'.format(iface_name, direction, vhd_type))
            f.write('\n  );\nend entity;\n\narchitecture model of {} is\n'.format(self._name))
            for net, *_ in self._net_insns:
                if not net.startswith('.'):
                    continue
                net = net[1:].split('~')[0].split('*')[0]
                if net in nets:
                    continue
                f.write('  signal {} : std_logic;\n'.format(net))
                nets.add(net)
            f.write('begin\n\n')
            for instance in self._instances:
                name = instance.get_name().replace('*', '').replace('~', '')
                f.write('  {}_inst: entity work.{}\n    port map (\n'.format(name, instance.get_data().get_name()))
                pins = set()
                first = True
                for pin, net in instance.get_pinmap():
                    pin = pin.get_name().split('~')[0].split('*')[0]
                    if pin in pins:
                        continue
                    pins.add(pin)
                    net = net[1:].split('~')[0].split('*')[0]
                    if first:
                        first = False
                    else:
                        f.write(',\n')
                    f.write('      {} => {}'.format(pin, net))
                for _, _, iface_name in instance.get_data().get_interfaces():
                    if first:
                        first = False
                    else:
                        f.write(',\n')
                    f.write('      if_{} => if_{}_{}'.format(iface_name, name, iface_name))
                f.write('\n    );\n\n')
            f.write('end architecture;\n')