def _bp_edit_box_button_press_cb(self, evbox, event, dialog, editable): modifiers = event.state & gtk.accelerator_get_default_mod_mask() bp_name = button_press_name(event.button, modifiers) bp_displayname = button_press_displayname(event.button, modifiers) if modifiers == 0 and event.button == 1: self._bp_edit_dialog_set_error( dialog, _("{button} cannot be bound without modifier keys " "(its meaning is fixed, sorry)").format( button=escape(bp_displayname), ), ) dialog.ok_btn.set_sensitive(False) return action = None if bp_name != dialog.bp_name_orig: action = self.bindings.get(bp_name, None) if action is not None: action_label = self.action_labels.get(action, action) self._bp_edit_dialog_set_error( dialog, _("{button_combination} is already bound " "to the action '{action_name}'").format( button_combination=escape(str(bp_displayname)), action_name=escape(str(action_label)), ), ) dialog.ok_btn.set_sensitive(False) else: self._bp_edit_dialog_set_standard_hint(dialog) dialog.bp_name = bp_name dialog.bp_label.set_text(str(bp_displayname)) dialog.ok_btn.set_sensitive(True) dialog.ok_btn.grab_focus()
def update(self, doc=None): self.data = self.ani.timeline self.data.cleanup() current_layer = self.doc.ani.timeline.layer # Update the common widgets self.opacity_scale.set_value(current_layer.opacity * 100) self.update_opacity_tooltip() combo = self.layer_mode_combo already_correct = (combo.get_active_id() == str( current_layer.composite)) if not already_correct: combo.set_active_id(str(current_layer.composite)) label, desc = COMBINE_MODE_STRINGS.get(current_layer.composite) tooltip = self.tooltip_format.format( blendingmode_name=escape(label), blendingmode_description=escape(desc)) combo.set_tooltip_markup(tooltip) self._update_buttons_sensitive() if self.ani.cleared == True: self.ani.cleared = False self.update_digits() self.timeline_widget.resize() self.scroll_to(self.ani.timeline.idx) self.emit('update') if not self.is_playing and self.ani.player_state == "play": use_lightbox = self.app.preferences.get("xsheet.play_lightbox", False) self._play_animation(use_lightbox=use_lightbox)
def _bp_edit_box_button_press_cb(self, evbox, event, dialog, editable): modifiers = event.state & gtk.accelerator_get_default_mod_mask() bp_name = button_press_name(event.button, modifiers) if modifiers == 0 and event.button == 1: self._bp_edit_dialog_set_error( dialog, _("%s cannot be bound by itself, without keyboard modifiers.") % escape(bp_name) ) dialog.ok_btn.set_sensitive(False) return action = None if bp_name != dialog.bp_name_orig: action = self.bindings.get(bp_name, None) if action is not None: action_label = self.action_labels.get(action, action) self._bp_edit_dialog_set_error( dialog, _("%s is already bound to the action '%s'") % ( escape(str(bp_name)), escape(str(action_label)) ) ) dialog.ok_btn.set_sensitive(False) else: self._bp_edit_dialog_set_standard_hint(dialog) dialog.bp_name = bp_name dialog.bp_label.set_text(str(bp_name)) dialog.ok_btn.set_sensitive(True) dialog.ok_btn.grab_focus()
def update(self, doc=None): self.data = self.ani.timeline self.data.cleanup() current_layer = self.doc.ani.timeline.layer # Update the common widgets self.opacity_scale.set_value(current_layer.opacity*100) self.update_opacity_tooltip() combo = self.layer_mode_combo already_correct = (combo.get_active_id() == str(current_layer.composite)) if not already_correct: combo.set_active_id(str(current_layer.composite)) label, desc = COMBINE_MODE_STRINGS.get(current_layer.composite) tooltip = self.tooltip_format.format( blendingmode_name = escape(label), blendingmode_description = escape(desc)) combo.set_tooltip_markup(tooltip) self._update_buttons_sensitive() if self.ani.cleared == True: self.ani.cleared = False self.update_digits() self.timeline_widget.resize() self.scroll_to(self.ani.timeline.idx) self.emit('update') if not self.is_playing and self.ani.player_state == "play": use_lightbox = self.app.preferences.get("xsheet.play_lightbox", False) self._play_animation(use_lightbox=use_lightbox)
def _bp_edit_box_button_press_cb(self, evbox, event, dialog, editable): modifiers = event.state & gtk.accelerator_get_default_mod_mask() bp_name = button_press_name(event.button, modifiers) if modifiers == 0 and event.button == 1: self._bp_edit_dialog_set_error( dialog, _("%s cannot be bound by itself, without keyboard modifiers.") % (escape(bp_name), )) dialog.ok_btn.set_sensitive(False) return action = None if bp_name != dialog.bp_name_orig: action = self.bindings.get(bp_name, None) if action is not None: action_label = self.action_labels.get(action, action) self._bp_edit_dialog_set_error( dialog, _("%s is already bound to the action '%s'") % (escape(str(bp_name)), escape(str(action_label)))) dialog.ok_btn.set_sensitive(False) else: self._bp_edit_dialog_set_standard_hint(dialog) dialog.bp_name = bp_name dialog.bp_label.set_text(str(bp_name)) dialog.ok_btn.set_sensitive(True) dialog.ok_btn.grab_focus()
def on_layer_mode_changed(self, *ignored): doc = self.app.doc.model mode = int(self.layer_mode_combo.get_active_id()) label, desc = COMBINE_MODE_STRINGS.get(mode) doc.ani.set_layer_composite(mode) tooltip = self.tooltip_format.format( blendingmode_name = escape(label), blendingmode_description = escape(desc)) self.layer_mode_combo.set_tooltip_markup(tooltip)
def on_layer_mode_changed(self, *ignored): doc = self.app.doc.model mode = int(self.layer_mode_combo.get_active_id()) label, desc = COMBINE_MODE_STRINGS.get(mode) doc.ani.set_layer_composite(mode) tooltip = self.tooltip_format.format( blendingmode_name=escape(label), blendingmode_description=escape(desc)) self.layer_mode_combo.set_tooltip_markup(tooltip)
def find_iter(model, path, iter, data): md = model.get_value(iter, 0) md_name = model.get_value(iter, 1) md_desc = model.get_value(iter, 2) if md == mode: self.layer_mode_combo.set_active_iter(iter) tooltip = self.tooltip_format.format( blendingmode_name=escape(md_name), blendingmode_description=escape(md_desc)) self.layer_mode_combo.set_tooltip_markup(tooltip)
def find_iter(model, path, iter, data): md = model.get_value(iter, 0) md_name = model.get_value(iter, 1) md_desc = model.get_value(iter, 2) if md == mode: self.layer_mode_combo.set_active_iter(iter) tooltip = self.tooltip_format.format( blendingmode_name = escape(md_name), blendingmode_description = escape(md_desc)) self.layer_mode_combo.set_tooltip_markup(tooltip)
def _update_layer_mode_combo(self): """Updates the layer mode combo's value from the model""" assert self._processing_model_updates combo = self._layer_mode_combo layer = self.app.doc.model.layer_stack.current if combo.get_active_id() == str(layer.mode): return combo.set_active_id(str(layer.mode)) label, desc = COMBINE_MODE_STRINGS.get(layer.mode) template = self.LAYER_MODE_TOOLTIP_MARKUP_TEMPLATE tooltip = template.format(name=escape(label), description=escape(desc)) combo.set_tooltip_markup(tooltip)
def _app_name_datafunc(self, col, cell, model, it, data): app = model.get_value(it, 0) name = app.get_display_name() desc = app.get_description() if desc is not None: markup_template = "<b>{name}</b>\n{description}" else: markup_template = "<b>{name}</b>\n<i>({description})</i>" desc = _("no description") markup = markup_template.format( name=escape(name), description=escape(desc), ) cell.set_property("markup", markup)
def on_layer_mode_changed(self, *ignored): if self.is_updating: return self.is_updating = True doc = self.app.doc.model i = self.layer_mode_combo.get_active_iter() mode_name, display_name, desc = self.layer_mode_model.get(i, 0, 1, 2) doc.set_layer_compositeop(mode_name) tooltip = self.tooltip_format.format( blendingmode_name=escape(display_name), blendingmode_description=escape(desc)) self.layer_mode_combo.set_tooltip_markup(tooltip) self.scroll_to_highlighted_row() self.is_updating = False
def on_layer_mode_changed(self, *ignored): if self.is_updating: return self.is_updating = True doc = self.app.doc.model i = self.layer_mode_combo.get_active_iter() mode_name, display_name, desc = self.layer_mode_model.get(i, 0, 1, 2) doc.set_layer_compositeop(mode_name) tooltip = self.tooltip_format.format( blendingmode_name = escape(display_name), blendingmode_description = escape(desc)) self.layer_mode_combo.set_tooltip_markup(tooltip) self.scroll_to_highlighted_row() self.is_updating = False
def _update_widgets(self): editing = self._brush_to_edit is not None if editing: brush = self._brush_to_edit else: brush = self._bm.selected_brush # Fairly rare: corresponds to no brush being selected on startup valid = brush.name is not None # Button states self._revert_button.set_sensitive(valid and editing) self._edit_button.set_sensitive(valid and not editing) self._clear_button.set_sensitive(valid and editing) self._save_button.set_sensitive(valid and editing) self._model.layer.locked = not (valid and editing) # Text to display in the various states if not valid: tmpl = self._ICON_INVALID_TMPL elif editing: if self._preview_modified: tmpl = self._ICON_MODIFIED_TMPL else: tmpl = self._ICON_MODIFIABLE_TMPL else: tmpl = self._ICON_PREVIEWING_TMPL # Update edit flag label name = brush.name if (not valid) or name is None: name = self._NO_BRUSH_NAME markup = tmpl % (escape(name),) self.brush_name_label.set_markup(markup)
def layer_name_text_datafunc(column, cell, model, it, data): """Show the layer name, with italics for layer groups""" layer = model.get_layer(it=it) if layer is None or layer.name is None: if layer is None: # Can happen under some rare conditions, code has to be # robust. Pick something placeholdery, and hope it's # temporary. default_name = lib.layer.PlaceholderLayer.DEFAULT_NAME else: default_name = layer.DEFAULT_NAME path = model.get_path(it) markup = UNNAMED_LAYER_DISPLAY_NAME_TEMPLATE.format( default_name=default_name, path=str(path), ) else: markup = escape(layer.name) if isinstance(layer, lib.layer.LayerStack): markup = u"<i>%s</i>" % (markup, ) attrs = Pango.AttrList() parse_result = Pango.parse_markup(markup, -1, '\000') parse_ok, attrs, text, accel_char = parse_result assert parse_ok cell.set_property("attributes", attrs) cell.set_property("text", text)
def _fmt_accel_label(self, label): if label: return self._ACCEL_LABEL_COLUMN_TEMPLATE.format( accel_label = escape(label.decode("utf-8")), ) else: return ""
def _update_ui(self): """Update the UI to show the options widget of the current mode""" mode = self._app.doc.modes.top # Get the new options widget old_options = self._options_bin.get_child() new_options = self._no_options_label if hasattr(mode, "get_options_widget"): new_options = mode.get_options_widget() # Only update if the current mode exposes a non-NULL options widget if new_options is None: return # Label markup = self.OPTIONS_MARKUP % (escape(mode.get_name()),) self._options_label.set_markup(markup) # Icon icon_name = mode.get_icon_name() self._mode_icon.set_from_icon_name(icon_name, Gtk.IconSize.SMALL_TOOLBAR) # Options widget: only update if there's a change if new_options is not old_options: if old_options: old_options.hide() self._options_bin.remove(old_options) self._options_bin.add(new_options) new_options.show() self._options_bin.show_all()
def __init__(self, text, menu): gtk.Button.__init__(self) self.menu = menu hbox1 = gtk.HBox() hbox2 = gtk.HBox() label = gtk.Label() hbox1.pack_start(label, True, True) arrow = gtk.Arrow(gtk.ARROW_DOWN, gtk.SHADOW_IN) hbox1.pack_start(arrow, False, False) hbox2.pack_start(hbox1, True, True, widgets.SPACING_TIGHT) # Text settings text = unicode(text) markup = "<b>%s</b>" % escape(text) label.set_markup(markup) self.add(hbox2) self.set_relief(gtk.RELIEF_NONE) self.connect("button-press-event", self.on_button_press) # No keynav. #DISABLED: self.connect("toggled", self.on_toggled) self.set_can_focus(False) self.set_can_default(False) for sig in "selection-done", "deactivate", "cancel": menu.connect(sig, self.on_menu_dismiss)
def layer_name_text_datafunc(column, cell, model, it, data): """Show the layer name, with italics for layer groups""" layer = model.get_layer(it=it) if layer is None or layer.name is None: if layer is None: # Can happen under some rare conditions, code has to be # robust. Pick something placeholdery, and hope it's # temporary. default_name = lib.layer.PlaceholderLayer.DEFAULT_NAME else: default_name = layer.DEFAULT_NAME path = model.get_path(it) markup = UNNAMED_LAYER_DISPLAY_NAME_TEMPLATE.format( default_name=default_name, path=str(path), ) else: markup = escape(layer.name) if isinstance(layer, lib.layer.LayerStack): markup = u"<i>%s</i>" % (markup,) attrs = Pango.AttrList() parse_result = Pango.parse_markup(markup, -1, '\000') parse_ok, attrs, text, accel_char = parse_result assert parse_ok cell.set_property("attributes", attrs) cell.set_property("text", text)
def _mode_icon_query_tooltip_cb(self, widget, x, y, kbmode, tooltip): mode = self.app.doc.modes.top icon_name = mode.get_icon_name() if not icon_name: icon_name = "missing-image" icon_size = Gtk.IconSize.DIALOG tooltip.set_icon_from_icon_name(icon_name, icon_size) description = None action = mode.get_action() if action: description = action.get_tooltip() if not description: description = mode.get_usage() params = { "name": helpers.escape(mode.get_name()), "description": helpers.escape(description) } markup = self._MODE_ICON_TEMPLATE.format(**params) tooltip.set_markup(markup) return True
def _query_tooltip_cb(self, da, x, y, keyboard_mode, tooltip): s = self._TOOLTIP_ICON_SIZE scaled_pixbuf = self._get_scaled_pixbuf(s) tooltip.set_icon(scaled_pixbuf) template_params = {"brush_name": escape(self._brush_name)} markup_template = C_( "current brush indicator: tooltip (no-description case)", u"<b>{brush_name}</b>", ) if self._brush_desc: markup_template = C_( "current brush indicator: tooltip (description case)", u"<b>{brush_name}</b>\n{brush_desc}", ) template_params["brush_desc"] = escape(self._brush_desc) markup = markup_template.format(**template_params) tooltip.set_markup(markup) # TODO: summarize changes? return True
def _update_layer_mode_combo(self): """Updates the layer mode combo's value from the model""" assert self._processing_model_updates combo = self._layer_mode_combo rootstack = self.app.doc.model.layer_stack layer = rootstack.current if layer is rootstack or not layer: combo.set_sensitive(False) return elif not combo.get_sensitive(): combo.set_sensitive(True) already_correct = (combo.get_active_id() == str(layer.mode)) if already_correct: return combo.set_active_id(str(layer.mode)) label, desc = COMBINE_MODE_STRINGS.get(layer.mode) template = self.LAYER_MODE_TOOLTIP_MARKUP_TEMPLATE tooltip = template.format(name=escape(label), description=escape(desc)) combo.set_tooltip_markup(tooltip)
def _update_layer_mode_combo(self): """Updates the layer mode combo's value from the model""" assert self._processing_model_updates combo = self._layer_mode_combo rootstack = self.app.doc.model.layer_stack layer = rootstack.current if layer is rootstack or not layer: combo.set_sensitive(False) return elif not combo.get_sensitive(): combo.set_sensitive(True) already_correct = (combo.get_active_id() == str(layer.mode)) if already_correct: return combo.set_active_id(str(layer.mode)) label, desc = COMBINE_MODE_STRINGS.get(layer.mode) template = self.LAYER_MODE_TOOLTIP_MARKUP_TEMPLATE tooltip = template.format( name=escape(label), description=escape(desc) ) combo.set_tooltip_markup(tooltip)
def _update_layer_mode_combo(self): """Updates the layer mode combo's value from the model""" assert self._processing_model_updates combo = self._layer_mode_combo rootstack = self.app.doc.model.layer_stack current = rootstack.current if current is rootstack or not current: combo.set_sensitive(False) return elif not combo.get_sensitive(): combo.set_sensitive(True) active_iter = None current_mode = current.mode for row in combo.get_model(): mode = row[0] if mode == current_mode: active_iter = row.iter row[2] = (mode in current.PERMITTED_MODES) combo.set_active_iter(active_iter) label, desc = lib.layer.MODE_STRINGS.get(current_mode) template = self.LAYER_MODE_TOOLTIP_MARKUP_TEMPLATE tooltip = template.format(name=escape(label), description=escape(desc)) combo.set_tooltip_markup(tooltip)
def _bp_edit_box_button_press_cb(self, evbox, event, dialog, editable): modifiers = event.state & gtk.accelerator_get_default_mod_mask() bp_name = button_press_name(event.button, modifiers) bp_displayname = button_press_displayname(event.button, modifiers) if modifiers == 0 and event.button == 1: self._bp_edit_dialog_set_error( dialog, _("{button} cannot be bound without modifier keys " "(its meaning is fixed, sorry)") .format( button=escape(bp_displayname), ), ) dialog.ok_btn.set_sensitive(False) return action = None if bp_name != dialog.bp_name_orig: action = self.bindings.get(bp_name, None) if action is not None: action_label = self.action_labels.get(action, action) self._bp_edit_dialog_set_error( dialog, _("{button_combination} is already bound " "to the action '{action_name}'") .format( button_combination=escape(str(bp_displayname)), action_name=escape(str(action_label)), ), ) dialog.ok_btn.set_sensitive(False) else: self._bp_edit_dialog_set_standard_hint(dialog) dialog.bp_name = bp_name dialog.bp_label.set_text(str(bp_displayname)) dialog.ok_btn.set_sensitive(True) dialog.ok_btn.grab_focus()
def add_objects_from_template_string(builder, buffer_, object_ids, params): """Templatizes, parses, merges, and returns objects from a Builder UI-def This function wraps `Gtk.Builder.add_objects_from_string()`, with the addition that the `buffer_` parameter, and each element of `object_ids` is formatted using `str.format()` using `params` before use. This templatizing is required to produce a different result for the string buffer of XML data, and for each object ID. :param builder: a Gtk.Buider :param buffer_: the string to templatize then parse :param object_ids: list of object names to build (after templatizing) :param params: dict of template params :returns: a list of constructed objects The constructed objects are returned in a Python list if this wrapped method call is successful. When templatizing the XML fragment, paramater values will be escaped using `lib.helpers.escape()`. Therefore `params` is limited to fairly simple dicts. """ object_ids2 = [] for oid in object_ids: oid2 = oid.format(**params) if oid == oid2: msg = "object_id %s unchanged after .format(...)ing" % oid raise ValueError, msg object_ids2.append(oid2) params_esc = {} for p, v in params.iteritems(): params_esc[p] = escape(v) buffer_2 = buffer_.format(**params_esc) if buffer_2 == buffer_: msg = "buffer_ unchanged after .format(...)ing" raise ValueError, msg result = [] if builder.add_objects_from_string(buffer_2, object_ids2): for oid2 in object_ids2: obj2 = builder.get_object(oid2) assert obj2 is not None result.append(obj2) return result
def layer_name_datafunc(self, column, renderer, model, tree_iter, *data_etc): layer = model.get_value(tree_iter, 0) path = model.get_path(tree_iter) name = layer.name attrs = pango.AttrList() if not name: layer_num = self.app.doc.get_number_for_nameless_layer(layer) name = _(u"Untitled layer #%d") % layer_num markup = "<small><i>%s</i></small> " % (escape(name), ) if gtk2compat.USE_GTK3: parse_result = pango.parse_markup(markup, -1, '\000') parse_ok, attrs, name, accel_char = parse_result assert parse_ok else: parse_result = pango.parse_markup(markup) attrs, name, accel_char = parse_result renderer.set_property("attributes", attrs) renderer.set_property("text", name)
def _update_ui_with_options_widget(self, new_options, name, icon_name): old_options = self._options_bin.get_child() logger.info("name: %r, icon name: %r", name, icon_name) if name: markup = self.OPTIONS_MARKUP.format(mode_name=escape(name), ) self._options_label.set_markup(markup) if icon_name: self._mode_icon.set_from_icon_name( icon_name, Gtk.IconSize.SMALL_TOOLBAR, ) # Options widget: only update if there's a change if new_options is not old_options: if old_options: old_options.hide() self._options_bin.remove(old_options) self._options_bin.add(new_options) new_options.show() self._options_bin.show_all()
def layer_name_datafunc(self, column, renderer, model, tree_iter, *data_etc): layer = model.get_value(tree_iter, 0) path = model.get_path(tree_iter) name = layer.name attrs = pango.AttrList() if not name: layer_num = self.app.doc.get_number_for_nameless_layer(layer) name = _(u"Untitled layer #%d") % layer_num markup = "<small><i>%s</i></small> " % (escape(name),) if pygtkcompat.USE_GTK3: parse_result = pango.parse_markup(markup, -1, '\000') parse_ok, attrs, name, accel_char = parse_result assert parse_ok else: parse_result = pango.parse_markup(markup) attrs, name, accel_char = parse_result renderer.set_property("attributes", attrs) renderer.set_property("text", name)
def _update_ui_with_options_widget(self, new_options, name, icon_name): old_options = self._options_bin.get_child() logger.info("name: %r, icon name: %r", name, icon_name) if name: markup = self.OPTIONS_MARKUP.format( mode_name=escape(name), ) self._options_label.set_markup(markup) if icon_name: self._mode_icon.set_from_icon_name( icon_name, Gtk.IconSize.SMALL_TOOLBAR, ) # Options widget: only update if there's a change if new_options is not old_options: if old_options: old_options.hide() self._options_bin.remove(old_options) self._options_bin.add(new_options) new_options.show() self._options_bin.show_all()
def _init_from_accel_map(self): """Initializes from the app UIManager and the global AccelMap""" if self.ui_manager is None: import application app = application.get_app() self.ui_manager = app.ui_manager assert self.ui_manager is not None self._action_labels.clear() self._store.clear() accel_labels = {} for path, key, mods, changed in self._get_accel_map_entries(): accel_labels[path] = Gtk.accelerator_get_label(key, mods) for group in self.ui_manager.get_action_groups(): group_name = group.get_name() for action in group.list_actions(): action_name = action.get_name() path = "<Actions>/%s/%s" % (group_name, action_name) if isinstance(action, Gtk.RecentAction): logger.debug("Skipping %r: GtkRecentAction", path) continue if action.__class__.__name__.endswith("FactoryAction"): logger.debug("Skipping %r: MyPaintFactoryAction", path) continue action_label = action.get_label() if not action_label: continue action_label = action_label action_desc = action.get_tooltip() if action_name.endswith("Mode"): if isinstance(action, Gtk.RadioAction): logger.debug( "Not listing %r (radio action for a mode)" "Assume there is a 'Flip'+%r action that's " "better for keybindings.", path, action_name, ) continue if not action_desc: if action_name.startswith("toolbar1"): logger.debug( "Not listing %r (toolbar placeholder action)", path, ) elif action_name.endswith("Menu"): logger.debug( "Not listing %r (menu-structure-only action)", path, ) else: logger.warning( "Not listing %r (no tooltip, fix before release!)", path, ) continue self._action_labels[path] = action_label # NOT markup action_markup = self._ACTION_LABEL_COLUMN_TEMPLATE.format( action_label = escape(action_label.decode("utf-8")), action_desc = escape(action_desc.decode("utf-8")), ) accel_label = accel_labels.get(path) if not accel_label: accel_label = "" self._accel_labels[path] = accel_label accel_markup = self._fmt_accel_label(accel_label) search_text = self._SEARCH_TEXT_COLUMN_TEMPLATE.format( action_label = action_label, action_desc = action_desc, accel_label = accel_label or "", ) row = [None for t in self._COLUMN_TYPES] row[self._PATH_COLUMN] = path row[self._ACTION_LABEL_COLUMN] = action_markup row[self._ACCEL_LABEL_COLUMN] = accel_markup row[self._SEARCH_TEXT_COLUMN] = search_text self._store.append(row)
def _init_widgets(self): # Icon preview and edit TDW self._tdw = tileddrawwidget.TiledDrawWidget() self._tdw.set_model(self._model) self._tdw.set_size_request(brushmanager.PREVIEW_W*self._SCALE, brushmanager.PREVIEW_H*self._SCALE) self._tdw.scale = float(self._SCALE) self._tdw.scroll_on_allocate = False self._tdw.pixelize_threshold = 0 tdw_align = Gtk.Alignment(xalign=0.5, yalign=0.0, xscale=0.0, yscale=0.0) tdw_align.add(self._tdw) self.attach(tdw_align, 0, 0, 1, 1) ctrlr = CanvasController(self._tdw) ctrlr.init_pointer_events() ctrlr.modes.default_mode_class = FreehandOnlyMode # Brush name label lbl = Gtk.Label() lbl.set_alignment(0.5, 0.0) lbl.set_justify(Gtk.Justification.CENTER) lbl_tmpl = self._ICON_PREVIEWING_TMPL lbl.set_markup(lbl_tmpl % (escape(self._NO_BRUSH_NAME),)) self.attach(lbl, 0, 1, 1, 1) self.brush_name_label = lbl # Action buttons button_box = Gtk.VButtonBox() button_box.set_homogeneous(False) button_box.set_layout(Gtk.ButtonBoxStyle.START) button_box.set_spacing(4) # TRANSLATORS: begin editing a brush's preview icon b = self._make_image_button(_('Edit'), Gtk.STOCK_EDIT, self._edit_cb) b.set_tooltip_text(_("Begin editing this preview icon")) button_box.pack_start(b, expand=False) self._edit_button = b # TRANSLATORS: revert edits to a brush icon b = self._make_image_button(_('Revert'), Gtk.STOCK_REVERT_TO_SAVED, self._revert_cb) b.set_tooltip_text(_("Discard changes, and cancel editing")) button_box.pack_start(b, expand=False) button_box.set_child_secondary(b, False) self._revert_button = b # TRANSLATORS: clear the brush preview icon being edited b = self._make_image_button(_('Clear'), Gtk.STOCK_CLEAR, self._clear_cb) b.set_tooltip_text(_("Clear the preview icon")) button_box.pack_start(b, expand=False) self._clear_button = b #lbl = Gtk.Label(_("Use any brush and color when editing")) #lbl.set_line_wrap(Pango.WrapMode.WORD_CHAR) #button_box.pack_start(lbl, expand=False) # TRANSLATORS: save edits to a brush icon b = self._make_image_button(_('Save'), Gtk.STOCK_SAVE, self._save_cb) b.set_tooltip_text(_("Save this preview icon, and finish editing")) button_box.pack_start(b, expand=False) button_box.set_child_secondary(b, True) self._save_button = b self.attach(button_box, 1, 0, 1, 2) self.connect_after("show", self._show_cb) mb = self._bm.selected_brush preview = mb.preview self._set_preview_pixbuf(preview) name = mb.name if name is None: name = self._NO_BRUSH_NAME self.brush_name_label.set_markup(lbl_tmpl % (escape(name),))
def lay_out_group_names(self, width): """Typeset the group names into a new Pango layout at a given width. """ layout = pango.Layout(self.get_pango_context()) layout.set_width(width*pango.SCALE) all_groups = list(sorted(self.bm.groups.keys())) idx = 0 attr = pango.AttrList() self.idx2group = {} # Pick separator chars. Platform-dependent, but assume Unicode # for modern OSes first. pad_s = u"\u202f" # NARROW NO-BREAK SPACE sp_s = pad_s + u"\u200b" # ZERO WIDTH SPACE if platform.system() == 'Windows' or platform.system() == 'Darwin': # workaround for https://gna.org/bugs/?15192 pad_s = '' sp_s = ' ' markup = '' for group in all_groups: group_label = brushmanager.translate_group_name(group) u = pad_s + group_label + pad_s idx_start = idx for c in u.encode('utf-8'): self.idx2group[idx] = group idx += 1 # Note the difference in terminology here colors_name = "normal" set_bgcolor = False if group == self.gtkstate_active_group: # activated the menu colors_name = "active" set_bgcolor = True elif group in self.bm.active_groups: # those groups visible colors_name = "selected" set_bgcolor = True if group == self.gtkstate_prelight_group: colors_name += "_pre" set_bgcolor = True fg, bg = self._text_colors[colors_name] if group == self.drag_target_group: # Invert colours fg, bg = bg, fg c_fg = fg.to_hex_str() m = escape(u) if set_bgcolor: c_bg = bg.to_hex_str() bgcolor = " bgcolor='%s'" % (c_bg,) else: bgcolor = "" m = "<span fgcolor='%s'%s>%s</span>" % (c_fg, bgcolor, m) markup += m + sp_s idx += len(sp_s.encode("utf-8")) layout.set_markup(markup) layout.set_spacing(self._leading) return layout
def lay_out_group_names(self, width): "Typeset the group names into a new Pango layout at a given width" self.ensure_style() style = self.get_style() layout = pango.Layout(self.get_pango_context()) layout.set_width(width*pango.SCALE) #layout.set_font_description(style.font_desc) # Needed? all_groups = list(sorted(self.bm.groups.keys())) idx = 0 attr = pango.AttrList() self.idx2group = {} # Pick separator chars. Platform-dependent, but assume Unicode # for modern OSes first. pad_s = u"\u202f" # NARROW NO-BREAK SPACE sp_s = pad_s + u"\u200b" # ZERO WIDTH SPACE import platform if platform.system() == 'Windows' or platform.system() == 'Darwin': # workaround for https://gna.org/bugs/?15192 pad_s = '' sp_s = ' ' def _gdk_color_to_hex(col): rgb = (col.red, col.green, col.blue) rgb = [max(min(c>>8, 255), 0) for c in rgb] return "#%02x%02x%02x" % tuple(rgb) markup = '' for group in all_groups: group_label = brushmanager.translate_group_name(group) u = pad_s + group_label + pad_s idx_start = idx for c in u.encode('utf-8'): self.idx2group[idx] = group idx += 1 # Note the difference in terminology here bg_state = fg_state = gtk.STATE_NORMAL if group == self.gtkstate_active_group: # activated the menu bg_state = fg_state = gtk.STATE_ACTIVE elif group in self.bm.active_groups: # those groups visible bg_state = fg_state = gtk.STATE_SELECTED elif group == self.gtkstate_prelight_group: bg_state = fg_state = gtk.STATE_PRELIGHT style_fg, style_bg = style.fg, style.bg if group == self.drag_target_group: # Invert colours style_fg, style_bg = style.bg, style.fg # always use the STATE_SELECTED fg if the group is visible if group in self.bm.active_groups: fg_state = gtk.STATE_SELECTED c_bg = _gdk_color_to_hex(style_bg[bg_state]) c_fg = _gdk_color_to_hex(style_fg[fg_state]) m = escape(u) m = "<span fgcolor='%s' bgcolor='%s'>%s</span>" % (c_fg, c_bg, m) markup += m + sp_s idx += len(sp_s.encode("utf-8")) layout.set_markup(markup) leading = style.font_desc.get_size() / 6 layout.set_spacing(leading) return layout
def _edit_dialog_key_press_cb(self, dialog, event, editable): if event.type != Gdk.EventType.KEY_PRESS: return False if event.is_modifier: return False if self._USE_NORMAL_DIALOG_KEYS: if event.keyval == Gdk.KEY_Return: dialog.response(Gtk.ResponseType.OK) return True elif event.keyval == Gdk.KEY_Escape: dialog.response(Gtk.ResponseType.CANCEL) return True elif event.keyval == Gdk.KEY_BackSpace: dialog.response(Gtk.ResponseType.REJECT) return True # Stolen from GTK 2.24's gtk/gtkmenu.c (gtk_menu_key_press()) # Figure out what modifiers went into determining the key symbol keymap = Gdk.Keymap.get_default() bound, keyval, effective_group, level, consumed_modifiers = ( keymap.translate_keyboard_state( event.hardware_keycode, event.state, event.group, )) keyval = Gdk.keyval_to_lower(keyval) mods = Gdk.ModifierType( event.state & Gtk.accelerator_get_default_mod_mask() & ~consumed_modifiers ) # If lowercasing affects the keysym, then we need to include # SHIFT in the modifiers. We re-upper case when we match against # the keyval, but display and save in caseless form. if keyval != event.keyval: mods |= Gdk.ModifierType.SHIFT_MASK accel_name = Gtk.accelerator_name(keyval, mods) accel_label = Gtk.accelerator_get_label(keyval, mods) # So we get (<Shift>j, Shift+J) but just (plus, +). As I # understand it. if not Gtk.accelerator_valid(keyval, mods): return True clash_accel_path = None clash_action_label = None for path, kv, m, changed in self._get_accel_map_entries(): if (kv, m) == (keyval, mods): clash_accel_path = path clash_action_label = self._action_labels.get( clash_accel_path, _("Unknown Action"), ) break if clash_accel_path == dialog.accel_path: # no change self._edit_dialog_set_standard_hint(dialog) label = str(accel_label) dialog.accel_label_widget.set_text(label) elif clash_accel_path: markup_tmpl = _( "<b>{accel} is already in use for '{action}'. " "The existing assignment will be replaced.</b>" ) markup = markup_tmpl.format( accel=escape(accel_label), action=escape(clash_action_label), ) self._edit_dialog_set_hint(dialog, markup) label = "%s (replace)" % (accel_label,) dialog.accel_label_widget.set_text(str(label)) else: self._edit_dialog_set_standard_hint(dialog) label = "%s (changed)" % (accel_label,) dialog.accel_label_widget.set_text(label) dialog.result_mods = mods dialog.result_keyval = keyval return True
def _edit_dialog_key_press_cb(self, dialog, event, editable): if event.type != Gdk.EventType.KEY_PRESS: return False if event.is_modifier: return False if self._USE_NORMAL_DIALOG_KEYS: if event.keyval == Gdk.KEY_Return: dialog.response(Gtk.ResponseType.OK) return True elif event.keyval == Gdk.KEY_Escape: dialog.response(Gtk.ResponseType.CANCEL) return True elif event.keyval == Gdk.KEY_BackSpace: dialog.response(Gtk.ResponseType.REJECT) return True # Stolen from GTK 2.24's gtk/gtkmenu.c (gtk_menu_key_press()) # Figure out what modifiers went into determining the key symbol keymap = Gdk.Keymap.get_default() bound, keyval, effective_group, level, consumed_modifiers = ( keymap.translate_keyboard_state( event.hardware_keycode, event.state, event.group, )) keyval = Gdk.keyval_to_lower(keyval) mods = Gdk.ModifierType(event.state & Gtk.accelerator_get_default_mod_mask() & ~consumed_modifiers) # If lowercasing affects the keysym, then we need to include # SHIFT in the modifiers. We re-upper case when we match against # the keyval, but display and save in caseless form. if keyval != event.keyval: mods |= Gdk.ModifierType.SHIFT_MASK accel_name = Gtk.accelerator_name(keyval, mods) accel_label = Gtk.accelerator_get_label(keyval, mods) # So we get (<Shift>j, Shift+J) but just (plus, +). As I # understand it. if not Gtk.accelerator_valid(keyval, mods): return True clash_accel_path = None clash_action_label = None for path, kv, m, changed in self._get_accel_map_entries(): if (kv, m) == (keyval, mods): clash_accel_path = path clash_action_label = self._action_labels.get( clash_accel_path, _("Unknown Action"), ) break if clash_accel_path == dialog.accel_path: # no change self._edit_dialog_set_standard_hint(dialog) label = str(accel_label) dialog.accel_label_widget.set_text(label) elif clash_accel_path: markup_tmpl = _("<b>{accel} is already in use for '{action}'. " "The existing assignment will be replaced.</b>") markup = markup_tmpl.format( accel=escape(accel_label), action=escape(clash_action_label), ) self._edit_dialog_set_hint(dialog, markup) label = "%s (replace)" % (accel_label, ) dialog.accel_label_widget.set_text(str(label)) else: self._edit_dialog_set_standard_hint(dialog) label = "%s (changed)" % (accel_label, ) dialog.accel_label_widget.set_text(label) dialog.result_mods = mods dialog.result_keyval = keyval return True