예제 #1
0
    def _render_options(self, options):
        visible = min(4, len(options))
        offsetTop = 6
        self.layout.height = visible * 30 + offsetTop + 11
        self.container.height = visible * 30 + offsetTop + 1
        self.layout.update_layout()
        self.container.remove_all_children()
        
        currentY = offsetTop
        for optId, optVal in options:
            optContainer = LUIObject(self.container, x=0, y=currentY, w=self.container.width - 30, h=30)

            optBg = LUISprite(optContainer, "blank", "skin")
            optBg.width = self.container.width
            optBg.height = optContainer.height
            optBg.color = (0,0,0,0)
            optBg.bind("mouseover", self._on_opt_over)
            optBg.bind("mouseout", self._on_opt_out)
            optBg.bind("click", partial(self._on_opt_click, optId))
            optBg.solid = True

            optLabel = LUILabel(parent=optContainer, text=unicode(optVal), shadow=True)
            optLabel.top = 5
            optLabel.left = 8

            if optId == self.selectbox.get_selected_option():
                optLabel.color = (0.6, 0.9, 0.4, 1.0)

            divider = LUISprite(optContainer, "SelectdropDivider", "skin")
            divider.top = 30 - divider.height / 2
            divider.width = self.container.width

            currentY += 30
예제 #2
0
    def _render_options(self, options):
        """ Internal method to update the options """
        num_visible_options = min(4, len(options))
        offset_top = 6
        self._layout.height = num_visible_options * 30 + offset_top + 11
        self._container.height = num_visible_options * 30 + offset_top + 1
        self._container.remove_all_children()

        current_y = offset_top
        for opt_id, opt_val in options:
            opt_container = LUIObject(self._container,
                                      x=0,
                                      y=current_y,
                                      w=self._container.width - 30,
                                      h=30)

            opt_bg = LUISprite(opt_container, "blank", "skin")
            opt_bg.width = self._container.width
            opt_bg.height = opt_container.height
            opt_bg.color = (0, 0, 0, 0)
            opt_bg.bind("mouseover", self._on_opt_over)
            opt_bg.bind("mouseout", self._on_opt_out)
            opt_bg.bind("mousedown", lambda *args: self.request_focus())
            opt_bg.bind("click", partial(self._on_opt_click, opt_id))
            opt_bg.solid = True

            opt_label = LUILabel(parent=opt_container, text=unicode(opt_val))
            opt_label.top = 8
            opt_label.left = 8

            if opt_id == self._selectbox.selected_option:
                opt_label.color = (0.6, 0.9, 0.4, 1.0)

            divider = LUISprite(opt_container, "SelectdropDivider", "skin")
            divider.top = 30 - divider.height / 2
            divider.width = self._container.width

            current_y += 30
예제 #3
0
class LUISlider(LUIObject):
    """ Slider which can be used to control values """
    def __init__(self,
                 parent=None,
                 filled=True,
                 min_value=0.0,
                 max_value=1.0,
                 width=100.0,
                 value=None,
                 **kwargs):
        """ Constructs a new slider. If filled is True, the part behind the knob
        will be solid """
        LUIObject.__init__(self, x=0, y=0, solid=True)
        self.set_width(width)
        self._knob = LUISprite(self, "SliderKnob", "skin")
        self._knob.z_offset = 2
        self._knob.solid = True

        # Construct the background
        self._slider_bg = LUIHorizontalStretchedLayout(parent=self,
                                                       prefix="SliderBg",
                                                       center_vertical=True,
                                                       width="100%",
                                                       margin=(-1, 0, 0, 0))

        self._filled = filled
        self._min_value = min_value
        self._max_value = max_value

        self._side_margin = self._knob.width / 4
        self._effective_width = self.width - 2 * self._side_margin

        if self._filled:
            self._slider_fill = LUIObject(self)
            self._fill_left = LUISprite(self._slider_fill, "SliderBgFill_Left",
                                        "skin")
            self._fill_mid = LUISprite(self._slider_fill, "SliderBgFill",
                                       "skin")
            self._fill_mid.left = self._fill_left.width
            self._slider_fill.z_offset = 1
            self._slider_fill.center_vertical = True

        if parent is not None:
            self.parent = parent

        # Handle various events
        self._knob.bind("mousedown", self._start_drag)
        self._knob.bind("mousemove", self._update_drag)
        self._knob.bind("mouseup", self._stop_drag)
        self._knob.bind("keydown", self._on_keydown)
        self._knob.bind("blur", self._stop_drag)
        self._knob.bind("keyrepeat", self._on_keydown)

        self._drag_start_pos = None
        self._dragging = False
        self._drag_start_val = 0
        self.current_val = 10

        # Set initial value
        if value is None:
            self.set_value((self._min_value + self._max_value) / 2.0)
        else:
            self.set_value(value)

        self._update_knob()

        LUIInitialState.init(self, kwargs)

    def on_click(self, event):
        """ Internal on click handler """
        # I don't like this behaviour
        # relative_pos = self.get_relative_pos(event.coordinates)
        # if not self._dragging:
        #     self._set_current_val(relative_pos.x)

    def _update_knob(self):
        """ Internal method to update the slider knob """
        self._knob.left = self.current_val - (self._knob.width /
                                              2) + self._side_margin
        if self._filled:
            self._fill_mid.width = self.current_val - self._fill_left.width + self._side_margin

    def _set_current_val(self, pixels):
        """ Internal method to set the current value in pixels """
        pixels = max(0, min(self._effective_width, pixels))
        self.current_val = pixels
        self.trigger_event("changed")
        self._update_knob()

    def _start_drag(self, event):
        """ Internal drag start handler """
        self._knob.request_focus()
        if not self._dragging:
            self._drag_start_pos = event.coordinates
            self._dragging = True
            self._drag_start_val = self.current_val
            self._knob.color = (0.8, 0.8, 0.8, 1.0)

    def set_value(self, value):
        """ Sets the value of the slider, should be between minimum and maximum. """
        scaled = (float(value) - float(self._min_value)) \
                 / (float(self._max_value) - float(self._min_value)) \
                 * self._effective_width
        self._set_current_val(scaled)

    def get_value(self):
        """ Returns the current value of the slider """
        return (self.current_val / float(self._effective_width)) \
                 * (float(self._max_value) - float(self._min_value)) \
                + self._min_value

    value = property(get_value, set_value)

    def _on_keydown(self, event):
        """ Internal keydown handler """
        if event.message == "arrow_right":
            self._set_current_val(self.current_val + 2)
        elif event.message == "arrow_left":
            self._set_current_val(self.current_val - 2)
        elif event.message == "escape":
            self.current_val = self._drag_start_val
            self._stop_drag(event)
            self._update_knob()

    def _update_drag(self, event):
        """ Internal drag handler """
        if self._dragging:
            dragOffset = event.coordinates.x - self._drag_start_pos.x
            finalValue = self._drag_start_val + dragOffset
            self._set_current_val(finalValue)

    def _stop_drag(self, event):
        """ Internal drag stop handelr """
        self._drag_start_pos = None
        self._dragging = False
        self._drag_start_val = self.current_val
        self._knob.color = (1, 1, 1, 1)
예제 #4
0
class DemoFramework:

    """ This is a small helper class to setup common stuff for the demos """

    def __init__(self):
        base.win.set_clear_color(Vec4(0, 0, 0, 1))
        self.skin = LUIDefaultSkin()
        self.skin.load()

        # Construct the LUIRegion
        region = LUIRegion.make("LUI", base.win)
        handler = LUIInputHandler()
        base.mouseWatcher.attach_new_node(handler)
        region.set_input_handler(handler)

        self.root = region.root()
        self.constructorParams = []

    def prepare_demo(self, demo_title=u"Some Demo"):

        # Background
        self.background = LUISprite(self.root, "res/DemoBackground.png")

        
        # Make the background solid and recieve events
        self.background.bind("click", lambda event: self.background.request_focus())
        self.background.solid = True

        # Logo
        self.logo = LUISprite(self.root, "res/LUILogo.png")
        self.logo.top = 15
        self.logo.left = 20

        # Title
        self.titleLabel = LUILabel(parent=self.root, text=demo_title, font_size=40, font="header")
        self.titleLabel.pos = (120, 20)
        self.subtitleLabel = LUILabel(parent=self.root, text="Widget Demo", font_size=14, font="default")
        self.subtitleLabel.pos = (121, 65)
        self.subtitleLabel.color = (1,1,1,0.5)

        # Right bar
        self.rightBar = LUIVerticalLayout(parent=self.root, width=350, spacing=20)
        self.rightBar.pos = (410, 120)

        # Constructor parameters
        # self.constructorParameters = LUIFrame(width=340, style=LUIFrame.Sunken)
        # self.constructorLabel = LUILabel(parent=self.constructorParameters, text=u"Additional Constructor Parameters")
        # self.constructorLayout = UIVerticalLayout(parent=self.constructorParameters, spacing=10, use_dividers=True)
        # self.constructorLayout.top = 30

        # Public functions
        self.publicFunctions = LUIFrame(width=340, style=LUIFrame.Sunken)
        self.functionsLabel = LUILabel(parent=self.publicFunctions, text=U"Additional Public functions")
        self.functionsLayout = LUIVerticalLayout(parent=self.publicFunctions,spacing=10, use_dividers=True)
        self.functionsLayout.top = 30

        # Events
        self.events = LUIFrame(width=340,style=LUIFrame.Sunken)
        self.eventsLabel = LUILabel(parent=self.events, text=U"Additional Events")
        self.eventsLayout = LUIVerticalLayout(parent=self.events, spacing=10, use_dividers=True)
        self.eventsLayout.top = 30

        # Actions
        self.actions = LUIFrame(width=340,style=LUIFrame.Sunken, height=80)
        self.actionsLabel = LUILabel(parent=self.actions, text=U"Demo-Actions")
        self.actionsSelect = LUISelectbox(parent=self.actions, width=245, top=30)
        self.actionsBtn = LUIButton(parent=self.actions, right=0, top=30, text=u"Execute", template="ButtonMagic")
        self.actionsBtn.bind("click", self._exec_action)

        self.rightBar.add_row(self.actions)
        # self.rightBar.add_row(self.constructorParameters)
        self.rightBar.add_row(self.publicFunctions)
        self.rightBar.add_row(self.events)

        # Widget
        self.widgetContainer = LUIFrame(parent=self.root, width=360, height=250, style=LUIFrame.Sunken)
        self.widgetLabel = LUILabel(parent=self.widgetContainer, text=u"Widget Demo")
        self.widgetContainer.left = 26
        self.widgetContainer.top = 120

        # Source Code
        self.sourceContainer = LUIFrame(parent=self.root, width=360, height=200, style=LUIFrame.Sunken)
        self.sourceLabel = LUILabel(parent=self.sourceContainer, text=u"Default Constructor")
        self.copyCodeButton = LUIButton(parent=self.sourceContainer, 
                text=u"Copy to Clipboard", template="ButtonMagic", 
                right=-5, bottom=-5)
        self.sourceContainer.left = 26
        self.sourceContainer.top = 390
        self.sourceContent = LUIObject(self.sourceContainer)
        self.sourceContent.top = 40


        self.widgetNode = LUIObject(self.widgetContainer, x=0, y=40)


    def _exec_action(self, event):
        selected = self.actionsSelect.get_selected_option()
        if selected is not None:
            selected()

    def set_actions(self, actions):
        opts = []

        for name, action in actions.items():
            opts.append((action, name))

        self.actionsSelect.set_options(opts)

    def add_public_function(self, name, parameters=None, return_type="void"):
        label = LUIFormattedLabel()
        label.add_text(text=return_type + " ", color = (102/255.0, 217/255.0, 239/255.0))
        label.add_text(text=name + " ", color = (166/255.0, 226/255.0, 46/255.0))

        label.add_text(text="( ", color=(0.9,0.9,0.9))

        if parameters is not None:
            for index, (pname, ptype) in enumerate(parameters):
                label.add_text(text=pname, color=(255/255.0, 151/255.0, 31/255.0))
                label.add_text(text=" : ", color=(0.9,0.9,0.9))
                label.add_text(text=ptype, color=(102/255.0, 217/255.0, 239/255.0))

                if index < len(parameters) - 1:
                    label.add_text(text=",", color=(0.9,0.9,0.9))
        label.add_text(text=" )", color=(0.9,0.9,0.9))
        self.functionsLayout.add_row(label)
        self.update_layouts()

    def add_constructor_parameter(self, name, default):
        # label = UIFormattedLabel()
        # label.add_text(text=name, color=(255/255.0, 151/255.0, 31/255.0))
        # label.add_text(text=" = ", color=(249/255.0, 38/255.0, 114/255.0))
        # label.add_text(text=default, color=(153/255.0, 129/255.0, 255/255.0))
        # self.constructorLayout.add_row(label)
        self.constructorParams.append((name, default))
        self.update_layouts()

    def add_event(self, event_name):
        label = LUILabel(text=event_name)
        label.color = (1,1,1,0.5)
        self.eventsLayout.add_row(label)
        self.update_layouts()

    def update_layouts(self):
        self.publicFunctions.fit_height_to_children()
        # self.constructorParameters.fit_height_to_children()
        self.events.fit_height_to_children()
        self.rightBar.update()

    def construct_sourcecode(self, classname):
        self.sourceContent.remove_all_children()
        label = LUIFormattedLabel(parent=self.sourceContent)
        label.add_text(text="element ", color=(0.9,0.9,0.9))
        label.add_text(text="= ", color=(249/255.0, 38/255.0, 114/255.0))
        label.add_text(text=classname, color=(166/255.0, 226/255.0, 46/255.0))
        label.add_text(text="(", color=(0.9,0.9,0.9))

        for index, (pname, pvalue) in enumerate(self.constructorParams):
            label.br()
            label.add_text(text=" " * 15)
            label.add_text(text=pname, color=(255/255.0, 151/255.0, 31/255.0))
            label.add_text(text=" = ")
            label.add_text(text=pvalue, color=(153/255.0, 129/255.0, 255/255.0))

            if index < len(self.constructorParams) - 1:
                label.add_text(text=",")

        label.add_text(text=")")

        self.sourceContent.fit_height_to_children()
        self.sourceContainer.fit_height_to_children()
        self.sourceContainer.height += 40


    def get_widget_node(self):
        return self.widgetNode
예제 #5
0
class LUISelectbox(LUIObject, LUICallback):

    def __init__(self, width=200, options=None, selectedOption=None, **kwargs):
        LUIObject.__init__(self, x=0, y=0, w=width+4, h=0, solid=True)
        LUIInitialState.init(self, kwargs)
        LUICallback.__init__(self)

        # The selectbox has a small border, to correct this we move it
        self.margin_left = -2

        self.bgLeft = LUISprite(self, "Selectbox_Left", "skin")
        self.bgMid = LUISprite(self, "Selectbox", "skin")
        self.bgRight = LUISprite(self, "Selectbox_Right", "skin")

        self.bgMid.width = self.width - self.bgLeft.width - self.bgRight.width
        self.bgMid.left = self.bgLeft.width
        self.bgRight.left = self.bgMid.width + self.bgMid.left

        self.bgRight.z_offset = 1

        self.labelContainer = LUIObject(self, x=10, y=6, w=width - 20 - self.bgRight.width, h=self.bgMid.height - 6)
        self.labelContainer.clip_bounds = (0,0,0,0)

        self.label = LUILabel(parent=self.labelContainer, text=u"Select an option ..", shadow=True)

        self.bgRight.bind("mouseover", self._knob_mouseover)
        self.bgRight.bind("mouseout", self._knob_mouseout)
        self.bgRight.bind("click", self.on_click)
        self.bgRight.bind("click", self.on_click)

        self.fit_to_children()

        self.dropMenu = UISelectdrop(parent=self, width=width)
        self.dropMenu.top = self.bgMid.height - 7
        self.dropMenu.topmost = True

        self.dropOpen = False
        self.dropMenu.hide()

        self.options = []
        self.currentOptionId = None

        if options is not None:
            self.options = options

        self._select_option(selectedOption)

    def get_selected_option(self):
        return self.currentOptionId

    def _render_options(self):
        self.dropMenu._render_options(self.options)

    def set_options(self, options):
        self.options = options
        self.currentOptionId = None
        self._render_options()

    def _select_option(self, optid):
        self.label.color = (1,1,1,1)
        for optID, optVal in self.options:
            if optID == optid:
                self.label.set_text(optVal)
                self.currentOptionId = optID
                return
        self.label.color = (1,1,1,0.5)

    def _knob_mouseover(self, event):
        self.bgRight.color = (0.9,0.9,0.9,1.0)

    def _knob_mouseout(self, event):
        self.bgRight.color = (1,1,1,1.0)

    def on_click(self, event):
        self.request_focus()
        if self.dropOpen:
            self._close_drop()
        else:
            self._open_drop()

    def on_mousedown(self, event):
        self.bgLeft.color = (0.9,0.9,0.9,1.0)
        self.bgMid.color = (0.9,0.9,0.9,1.0)

    def on_mouseup(self, event):
        self.bgLeft.color = (1,1,1,1.0)
        self.bgMid.color = (1,1,1,1.0)

    def _open_drop(self):
        if not self.dropOpen:
            self._render_options()
            self.dropMenu.show()
            self.request_focus()

            self.dropOpen = True

    def _close_drop(self):
        if self.dropOpen:
            self.dropMenu.hide()

            self.dropOpen = False

    def _on_option_selected(self, optid):
        self._select_option(optid)
        self._close_drop()

    def on_blur(self, event):
        self._close_drop()