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
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)
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()
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
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
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
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
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
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]
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
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
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]
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 """