示例#1
0
    def _parse_key(self, node, parent):
        key = RectKey()
        key.parent = parent # assign parent early to make get_filename() work

        # parse standard layout item attributes
        self._parse_dom_node_item(node, key)

        attributes = dict(list(node.attributes.items()))
        self._init_key(key, attributes)

        # get key geometry from the closest svg file
        filename = key.get_filename()
        if not filename:
            _logger.warning(_("Ignoring key '{}'."
                              " No svg filename defined.").format(key.theme_id))
        else:
            svg_keys = self._get_svg_keys(filename)
            svg_key = None
            if svg_keys:
                svg_key = svg_keys.get(key.id)
                if not svg_key:
                    _logger.warning(_("Ignoring key '{}'."
                                      " Not found in '{}'.") \
                                    .format(key.theme_id, filename))
                else:
                    key.set_border_rect(svg_key.get_border_rect().copy())
                    return key

        return None  # ignore keys not found in an svg file
    def _on_draw(self, widget, cr):
        """
        Draw the onboard icon.
        """
        if not Gtk.cairo_should_draw_window(cr, self.get_window()):
            return False

        rect = Rect(0.0, 0.0, float(self.get_allocated_width()),
                    float(self.get_allocated_height()))
        color_scheme = self.get_color_scheme()

        # clear background
        cr.save()
        cr.set_operator(cairo.OPERATOR_CLEAR)
        cr.paint()
        cr.restore()

        # draw background color
        background_rgba = list(color_scheme.get_icon_rgba("background"))

        if Gdk.Screen.get_default().is_composited():
            background_rgba[3] *= 0.75
            cr.set_source_rgba(*background_rgba)

            corner_radius = min(rect.w, rect.h) * 0.1

            roundrect_arc(cr, rect, corner_radius)
            cr.fill()

            # decoration frame
            line_rect = rect.deflate(2)
            cr.set_line_width(2)
            roundrect_arc(cr, line_rect, corner_radius)
            cr.stroke()
        else:
            cr.set_source_rgba(*background_rgba)
            cr.paint()

        # draw themed icon
        self._draw_themed_icon(cr, rect, color_scheme)

        # draw dwell progress
        rgba = [0.8, 0.0, 0.0, 0.5]
        bg_rgba = [0.1, 0.1, 0.1, 0.5]
        if color_scheme:
            key = RectKey(
                "icon0")  # take dwell color from the first icon "key"
            rgba = color_scheme.get_key_rgba(key, "dwell-progress")
            rgba[3] = min(0.75, rgba[3])  # more transparency

            key = RectKey("icon1")
            bg_rgba = color_scheme.get_key_rgba(key, "fill")
            bg_rgba[3] = min(0.75, rgba[3])  # more transparency

        dwell_rect = rect.grow(0.5)
        self._dwell_progress.draw(cr, dwell_rect, rgba, bg_rgba)

        return True
示例#3
0
    def build(source_key, color_scheme, alternatives):
        key_sequence = []
        for i, label in enumerate(alternatives):
            key = RectKey("_alternative" + str(i))
            key.type = KeyCommon.CHAR_TYPE
            key.labels = {0: label}
            key.code  = label[0]
            key_sequence.append(key)

        return LayoutBuilderKeySequence.build(source_key, color_scheme, 
                                              key_sequence)
示例#4
0
    def build(source_key, color_scheme, alternatives):
        key_sequence = []
        for i, label in enumerate(alternatives):
            key = RectKey("_alternative" + str(i))
            key.type = KeyCommon.CHAR_TYPE
            key.labels = {0: label}
            key.code = label[0]
            key_sequence.append(key)

        return LayoutBuilderKeySequence.build(source_key, color_scheme,
                                              key_sequence)
示例#5
0
    def _draw_themed_icon(self, cr, icon_rect, color_scheme):
        """ draw themed icon """
        keys = [RectKey("icon" + str(i)) for i in range(4)]

        # Default colors for the case when none of the icon keys
        # are defined in the color scheme.
        # background_rgba =  [1.0, 1.0, 1.0, 1.0]
        fill_rgbas = [[0.9, 0.7, 0.0, 0.75], [1.0, 1.0, 1.0, 1.0],
                      [1.0, 1.0, 1.0, 1.0], [0.0, 0.54, 1.0, 1.0]]
        stroke_rgba = [0.0, 0.0, 0.0, 1.0]
        label_rgba = [0.0, 0.0, 0.0, 1.0]

        themed = False
        if color_scheme:
            if any(color_scheme.is_key_in_scheme(key) for key in keys):
                themed = True

        # four rounded rectangles
        rects = Rect(0.0, 0.0, 100.0, 100.0).deflate(5) \
                                            .subdivide(2, 2, 6)
        cr.save()
        cr.scale(icon_rect.w / 100., icon_rect.h / 100.0)
        cr.translate(icon_rect.x, icon_rect.y)
        cr.select_font_face("sans-serif")
        cr.set_line_width(2)

        for i, key in enumerate(keys):
            rect = rects[i]

            if themed:
                fill_rgba = color_scheme.get_key_rgba(key, "fill")
                stroke_rgba = color_scheme.get_key_rgba(key, "stroke")
                label_rgba = color_scheme.get_key_rgba(key, "label")
            else:
                fill_rgba = fill_rgbas[i]

            roundrect_arc(cr, rect, 5)
            cr.set_source_rgba(*fill_rgba)
            cr.fill_preserve()

            cr.set_source_rgba(*stroke_rgba)
            cr.stroke()

            if i == 0 or i == 3:
                if i == 0:
                    letter = "O"
                else:
                    letter = "B"

                cr.set_font_size(25)
                (x_bearing, y_bearing, _width, _height, x_advance,
                 y_advance) = cr.text_extents(letter)
                r = rect.align_rect(Rect(0, 0, _width, _height), 0.3, 0.33)
                cr.move_to(r.x - x_bearing, r.y - y_bearing)
                cr.set_source_rgba(*label_rgba)
                cr.show_text(letter)
                cr.new_path()

        cr.restore()
示例#6
0
    def _parse_key(self, node, parent):
        result = None

        id = node.attributes["id"].value
        if id == "inputline":
            item_class = InputlineKey
        else:
            item_class = RectKey

        # find template attributes
        attributes = {}
        if node.hasAttribute("id"):
            theme_id, id = RectKey.parse_id(node.attributes["id"].value)
            attributes.update(self.find_template(parent, RectKey, [id]))

        # let current node override any preceding templates
        attributes.update(dict(node.attributes.items()))

        # handle common layout-item attributes
        key = self._init_item(attributes, item_class)
        key.parent = parent  # assign early to have get_filename() work

        # handle key-specific attributes
        self._init_key(key, attributes)

        # get key geometry from the closest svg file
        filename = key.get_filename()
        if not filename:
            if not attributes.get("group") == "wsbutton":
                _logger.warning(
                    _format("Ignoring key '{}'."
                            " No svg filename defined.", key.id))
        else:
            svg_nodes = self._get_svg_keys(filename)
            if svg_nodes:
                # try svg_id first, if there is one
                if key.svg_id != key.id:
                    svg_node = svg_nodes.get(key.svg_id)
                else:
                    # then the regular id
                    svg_node = svg_nodes.get(key.id)

                if svg_node:
                    r, geometry = svg_node.extract_key_params()
                    key.set_initial_border_rect(r.copy())
                    key.set_border_rect(r.copy())
                    key.geometry = geometry
                    result = key
                else:
                    _logger.info("Ignoring key '{}'."
                                 " No svg object found for '{}'." \
                                 .format(key.id, key.svg_id))

        return result  # ignore keys not found in an svg file
示例#7
0
    def _parse_key(self, node, parent):
        result = None

        id = node.attributes["id"].value
        if id == "inputline":
            item_class = InputlineKey
        else:
            item_class = RectKey

        # find template attributes
        attributes = {}
        if node.hasAttribute("id"):
            theme_id, id = RectKey.parse_id(node.attributes["id"].value)
            attributes.update(self.find_template(parent, RectKey, [id]))

        # let current node override any preceding templates
        attributes.update(dict(node.attributes.items()))

        # handle common layout-item attributes
        key = self._init_item(attributes, item_class)
        key.parent = parent  # assign early to have get_filename() work

        # handle key-specific attributes
        self._init_key(key, attributes)

        # get key geometry from the closest svg file
        filename = key.get_filename()
        if not filename:
            if not attributes.get("group") == "wsbutton":
                _logger.warning(_format("Ignoring key '{}'."
                                        " No svg filename defined.",
                                        key.id))
        else:
            svg_nodes = self._get_svg_keys(filename)
            if svg_nodes:
                # try svg_id first, if there is one
                if key.svg_id != key.id:
                    svg_node = svg_nodes.get(key.svg_id)
                else:
                    # then the regular id
                    svg_node = svg_nodes.get(key.id)

                if svg_node:
                    r, geometry = svg_node.extract_key_params()
                    key.set_initial_border_rect(r.copy())
                    key.set_border_rect(r.copy())
                    key.geometry = geometry
                    result = key
                else:
                    _logger.info("Ignoring key '{}'."
                                 " No svg object found for '{}'." \
                                 .format(key.id, key.svg_id))

        return result  # ignore keys not found in an svg file
示例#8
0
    def _parse_key(self, node, parent):
        result = None

        id = node.attributes["id"].value
        if id == "inputline":
            item_class = InputlineKey
        else:
            item_class = RectKey

        # parse standard layout-item attributes
        key = self._parse_dom_node_item(node, item_class)
        key.parent = parent  # assign parent early to make get_filename() work

        # find template attributes
        attributes = {}
        if node.hasAttribute("id"):
            theme_id, id = RectKey.split_id(node.attributes["id"].value)
            attributes.update(self.find_template(parent, RectKey, [id]))

        # let current node override any preceding templates
        attributes.update(dict(node.attributes.items()))

        # set up the key
        self._init_key(key, attributes)

        # get key geometry from the closest svg file
        filename = key.get_filename()
        if not filename:
            if not attribute.get("group") == "wsbutton":
                _logger.warning(
                    _format("Ignoring key '{}'."
                            " No svg filename defined.", key.id))
        else:
            svg_keys = self._get_svg_keys(filename)
            svg_key = None
            if svg_keys:
                # try svg_id first
                if key.svg_id != key.id:
                    svg_key = svg_keys.get(key.svg_id)
                else:
                    # then the regular id
                    svg_key = svg_keys.get(key.id)

                if svg_key:
                    r = svg_key.get_border_rect()
                    key.set_initial_border_rect(r.copy())
                    key.set_border_rect(r.copy())
                    result = key

        return result  # ignore keys not found in an svg file
示例#9
0
    def _parse_key(self, node, parent):
        result = None

        id = node.attributes["id"].value
        if id == "inputline":
            item_class = InputlineKey
        else:
            item_class = RectKey

        # parse standard layout-item attributes
        key = self._parse_dom_node_item(node, item_class)
        key.parent = parent # assign parent early to make get_filename() work

        # find template attributes
        attributes = {}
        if node.hasAttribute("id"):
            theme_id, id = RectKey.split_id(node.attributes["id"].value)
            attributes.update(self.find_template(parent, RectKey, [id]))

        # let current node override any preceding templates
        attributes.update(dict(node.attributes.items()))

        # set up the key
        self._init_key(key, attributes)

        # get key geometry from the closest svg file
        filename = key.get_filename()
        if not filename:
            if not attribute.get("group") == "wsbutton": 
                _logger.warning(_format("Ignoring key '{}'."
                                        " No svg filename defined.",
                                        key.id))
        else:
            svg_keys = self._get_svg_keys(filename)
            svg_key = None
            if svg_keys:
                # try svg_id first
                if key.svg_id != key.id:
                    svg_key = svg_keys.get(key.svg_id)
                else:
                    # then the regular id
                    svg_key = svg_keys.get(key.id)

                if svg_key:
                    r = svg_key.get_border_rect()
                    key.set_initial_border_rect(r.copy())
                    key.set_border_rect(r.copy())
                    result = key

        return result  # ignore keys not found in an svg file
示例#10
0
    def _parse_svg(self, svg_dom):
        keys = {}
        for rect in svg_dom.getElementsByTagName("rect"):
            id = rect.attributes["id"].value

            rect = Rect(float(rect.attributes['x'].value),
                        float(rect.attributes['y'].value),
                        float(rect.attributes['width'].value),
                        float(rect.attributes['height'].value))

            # Use RectKey as cache for svg provided properties.
            # This key instance doesn't enter the layout and will
            # be discarded after the layout tree has been loaded.
            key = RectKey(id, rect)

            keys[id] = key

        return keys
示例#11
0
    def _parse_legacy_layout(self, dom_node):

        # parse panes
        panes = []
        is_scan = False
        for i, pane_node in enumerate(dom_node.getElementsByTagName("pane")):
            item = LayoutPanel()
            item.layer_id = "layer {}".format(i)

            item.id       = pane_node.attributes["id"].value
            item.filename = pane_node.attributes["filename"].value

            # parse keys
            keys = []
            for node in pane_node.getElementsByTagName("key"):
                key = self._parse_key(node, item)                
                if key:
                    # some keys have changed since Onboard 0.95
                    if key.id == "middleClick":
                        key.set_id("middleclick")
                        key.action_type = KeyCommon.BUTTON_ACTION
                    if key.id == "secondaryClick":
                        key.set_id("secondaryclick")
                        key.action_type = KeyCommon.BUTTON_ACTION
                        
                    keys.append(key)
                    
            item.set_items(keys)

            # check for scan columns
            if pane_node.getElementsByTagName("column"):
                is_scan = True

            panes.append(item)

        layer_area = LayoutPanel()
        layer_area.id = "layer_area"
        layer_area.set_items(panes)

        # find the most frequent key width
        histogram = {}
        for key in layer_area.iter_keys():
            w = key.get_border_rect().w
            histogram[w] = histogram.get(w, 0) + 1
        most_frequent_width = max(list(zip(list(histogram.values()), list(histogram.keys()))))[1] \
                              if histogram else 18

        # Legacy onboard had automatic tab-keys for pane switching.
        # Simulate this by generating layer buttons from scratch.
        keys = []
        group = "__layer_buttons__"
        widen = 1.4 if not is_scan else 1.0
        rect = Rect(0, 0, most_frequent_width * widen, 20)

        key = RectKey()
        attributes = {}
        attributes["id"]     = "hide"
        attributes["group"]  = group
        attributes["image"]  = "close.svg"
        attributes["button"] = "true"
        attributes["scannable"] = "false"
        self._init_key(key, attributes)
        key.set_border_rect(rect.copy())
        keys.append(key)

        key = RectKey()
        attributes = {}
        attributes["id"]     = "move"
        attributes["group"]  = group
        attributes["image"]  = "move.svg"
        attributes["button"] = "true"
        attributes["scannable"] = "false"
        self._init_key(key, attributes)
        key.set_border_rect(rect.copy())
        keys.append(key)

        if len(panes) > 1:
            for i, pane in enumerate(panes):
                key = RectKey()
                attributes = {}
                attributes["id"]     = "layer{}".format(i)
                attributes["group"]  = group
                attributes["label"]  = pane.id
                attributes["button"] = "true"
                self._init_key(key, attributes)
                key.set_border_rect(rect.copy())
                keys.append(key)

        layer_switch_column = LayoutBox()
        layer_switch_column.horizontal = False
        layer_switch_column.set_items(keys)

        layout = LayoutBox()
        layout.border = 1
        layout.spacing = 2
        layout.set_items([layer_area, layer_switch_column])

        return [layout]
示例#12
0
    def _layout_sequence(sequence):
        """
        Split sequence into lines.
        """
        max_columns = LayoutBuilderAlternatives.MAX_KEY_COLUMNS
        min_columns = max_columns // 2
        add_close = False
        fill_gaps = True

        # find the number of columns with the best packing,
        # i.e. the least number of empty slots.
        n = len(sequence)
        if add_close:
            n += 1    # +1 for close button
        max_mod = 0
        ncolumns = max_columns
        for i in range(max_columns, min_columns, -1):
            m = n % i
            if m == 0:
                max_mod = m
                ncolumns = i
                break
            if max_mod < m:
                max_mod = m
                ncolumns = i

        # limit to len for the single row case
        ncolumns = min(n, ncolumns)

        # cut the input into lines of the newly found optimal length
        lines = []
        line = []
        column = 0
        for item in sequence:
            line.append(item)
            column += 1
            if column >= ncolumns:
                lines.append(line)
                line = []
                column = 0

        # append close button
        if add_close:
            n = len(line)
            line.extend([None]*(ncolumns - (n+1)))

            key = RectKey("_close_")
            key.labels = {}
            key.image_filenames = {ImageSlot.NORMAL : "close.svg"}
            key.type = KeyCommon.BUTTON_TYPE
            line.append(key)

        # fill empty slots with dummy buttons
        if fill_gaps:
            n = len(line)
            if n:
                for i in range(ncolumns - n):
                    key = RectKey("_dummy_")
                    key.sensitive = False
                    line.append(key)

        if line:
            lines.append(line)
    
        return lines, ncolumns
示例#13
0
    def _layout_sequence(sequence):
        """
        Split sequence into lines.
        """
        max_columns = LayoutBuilderAlternatives.MAX_KEY_COLUMNS
        min_columns = max_columns // 2
        add_close = False
        fill_gaps = True

        # find the number of columns with the best packing,
        # i.e. the least number of empty slots.
        n = len(sequence)
        if add_close:
            n += 1  # +1 for close button
        max_mod = 0
        ncolumns = max_columns
        for i in range(max_columns, min_columns, -1):
            m = n % i
            if m == 0:
                max_mod = m
                ncolumns = i
                break
            if max_mod < m:
                max_mod = m
                ncolumns = i

        # limit to len for the single row case
        ncolumns = min(n, ncolumns)

        # cut the input into lines of the newly found optimal length
        lines = []
        line = []
        column = 0
        for item in sequence:
            line.append(item)
            column += 1
            if column >= ncolumns:
                lines.append(line)
                line = []
                column = 0

        # append close button
        if add_close:
            n = len(line)
            line.extend([None] * (ncolumns - (n + 1)))

            key = RectKey("_close_")
            key.labels = {}
            key.image_filenames = {ImageSlot.NORMAL: "close.svg"}
            key.type = KeyCommon.BUTTON_TYPE
            line.append(key)

        # fill empty slots with dummy buttons
        if fill_gaps:
            n = len(line)
            if n:
                for i in range(ncolumns - n):
                    key = RectKey("_dummy_")
                    key.sensitive = False
                    line.append(key)

        if line:
            lines.append(line)

        return lines, ncolumns
示例#14
0
    def _parse_legacy_layout(self, dom_node):

        # parse panes
        panes = []
        is_scan = False
        for i, pane_node in enumerate(dom_node.getElementsByTagName("pane")):
            item = LayoutPanel()
            item.layer_id = "layer {}".format(i)

            item.id = pane_node.attributes["id"].value
            item.filename = pane_node.attributes["filename"].value

            # parse keys
            keys = []
            for node in pane_node.getElementsByTagName("key"):
                key = self._parse_key(node, item)
                if key:
                    # some keys have changed since Onboard 0.95
                    if key.id == "middleClick":
                        key.set_id("middleclick")
                        key.type = KeyCommon.BUTTON_TYPE
                    if key.id == "secondaryClick":
                        key.set_id("secondaryclick")
                        key.type = KeyCommon.BUTTON_TYPE

                    keys.append(key)

            item.set_items(keys)

            # check for scan columns
            if pane_node.getElementsByTagName("column"):
                is_scan = True

            panes.append(item)

        layer_area = LayoutPanel()
        layer_area.id = "layer_area"
        layer_area.set_items(panes)

        # find the most frequent key width
        histogram = {}
        for key in layer_area.iter_keys():
            w = key.get_border_rect().w
            histogram[w] = histogram.get(w, 0) + 1
        most_frequent_width = max(list(zip(list(histogram.values()), list(histogram.keys()))))[1] \
                              if histogram else 18

        # Legacy onboard had automatic tab-keys for pane switching.
        # Simulate this by generating layer buttons from scratch.
        keys = []
        group = "__layer_buttons__"
        widen = 1.4 if not is_scan else 1.0
        rect = Rect(0, 0, most_frequent_width * widen, 20)

        key = RectKey()
        attributes = {}
        attributes["id"] = "hide"
        attributes["group"] = group
        attributes["image"] = "close.svg"
        attributes["button"] = "true"
        attributes["scannable"] = "false"
        self._init_key(key, attributes)
        key.set_border_rect(rect.copy())
        keys.append(key)

        key = RectKey()
        attributes = {}
        attributes["id"] = "move"
        attributes["group"] = group
        attributes["image"] = "move.svg"
        attributes["button"] = "true"
        attributes["scannable"] = "false"
        self._init_key(key, attributes)
        key.set_border_rect(rect.copy())
        keys.append(key)

        if len(panes) > 1:
            for i, pane in enumerate(panes):
                key = RectKey()
                attributes = {}
                attributes["id"] = "layer{}".format(i)
                attributes["group"] = group
                attributes["label"] = pane.id
                attributes["button"] = "true"
                self._init_key(key, attributes)
                key.set_border_rect(rect.copy())
                keys.append(key)

        layer_switch_column = LayoutBox()
        layer_switch_column.horizontal = False
        layer_switch_column.set_items(keys)

        layout = LayoutBox()
        layout.border = 1
        layout.spacing = 2
        layout.set_items([layer_area, layer_switch_column])

        return [layout]
示例#15
0
    def load_keys_geometry(self, svgdoc, color_scheme, keys, label_rgba):
        for rect in svgdoc.getElementsByTagName("rect"):
            id = rect.attributes["id"].value

            styleString = rect.attributes["style"].value
            result = re.search("(fill:#\d?\D?\d?\D?\d?\D?\d?\D?\d?\D?\d?\D?;)", styleString).groups()[0]

            rgba = [
                hexstring_to_float(result[6:8]) / 255,
                hexstring_to_float(result[8:10]) / 255,
                hexstring_to_float(result[10:12]) / 255,
                1,
            ]  # not bothered for now

            key = RectKey(
                id,
                (float(rect.attributes["x"].value), float(rect.attributes["y"].value)),
                (float(rect.attributes["width"].value), float(rect.attributes["height"].value)),
                rgba,
            )

            # print color_scheme.get_key_label_rgba(name)

            # old colors for backwards compatibility
            key.hover_rgba = rgba
            key.pressed_rgba = rgba
            key.latched_rgba = [0.5, 0.5, 0.5, 1]
            key.locked_rgba = [1, 0, 0, 1]
            key.scanned_rgba = [0.45, 0.45, 0.7, 1]
            key.stroke_rgba = [0.0, 0.0, 0.0, 1.0]
            key.label_rgba = label_rgba

            # get colors from color scheme
            if color_scheme:
                key.rgba = color_scheme.get_key_rgba(id, "fill")
                key.hover_rgba = color_scheme.get_key_rgba(id, "hover")
                key.pressed_rgba = color_scheme.get_key_rgba(id, "pressed")
                key.latched_rgba = color_scheme.get_key_rgba(id, "latched")
                key.locked_rgba = color_scheme.get_key_rgba(id, "locked")
                key.scanned_rgba = color_scheme.get_key_rgba(id, "scanned")
                key.stroke_rgba = color_scheme.get_key_rgba(id, "stroke")
                key.label_rgba = color_scheme.get_key_rgba(id, "label")

            keys[id] = key

            # TODO fix LineKeys
            """