diff options
author | Gonzalo Odiard <godiard@gmail.com> | 2013-06-11 20:09:23 (GMT) |
---|---|---|
committer | Gonzalo Odiard <godiard@gmail.com> | 2013-06-11 20:09:23 (GMT) |
commit | a886bb31553e6550b007f5c2b737e029a58fdbaf (patch) | |
tree | 23b5f39976435f78a03372ce1f3727fab4749a75 | |
parent | 868ea2dcf018161da1e334927437bb9ae407c56b (diff) |
Use new widgets for font selection to improve use with touch
Signed-off-by: Gonzalo Odiard <gonzalo@laptop.org>
-rw-r--r-- | fontcombobox.py | 309 | ||||
-rw-r--r-- | icons/font-text.svg | 32 | ||||
-rw-r--r-- | icons/resize+.svg | 41 | ||||
-rw-r--r-- | icons/resize-.svg | 43 | ||||
-rw-r--r-- | toolbar.py | 68 |
5 files changed, 416 insertions, 77 deletions
diff --git a/fontcombobox.py b/fontcombobox.py index a7515bd..747dc9a 100644 --- a/fontcombobox.py +++ b/fontcombobox.py @@ -15,52 +15,295 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +import os +import shutil +from gettext import gettext as _ + from gi.repository import Gtk from gi.repository import GObject +from gi.repository import Gio + +from sugar3.graphics.icon import Icon +from sugar3.graphics.palette import Palette, ToolInvoker +from sugar3.graphics.palettemenu import PaletteMenuBox +from sugar3.graphics.palettemenu import PaletteMenuItem +from sugar3.graphics import style +from sugar3 import env + +DEFAULT_FONTS = ['Sans', 'Serif', 'Monospace'] +USER_FONTS_FILE_PATH = env.get_profile_path('fonts') +GLOBAL_FONTS_FILE_PATH = '/etc/sugar_fonts' + + +class FontLabel(Gtk.Label): + + def __init__(self, default_font='Sans'): + Gtk.Label.__init__(self) + self._font = None + self.set_font(default_font) + + def set_font(self, font): + if self._font != font: + self.set_markup('<span font="%s">%s</span>' % (font, font)) -FONT_BLACKLIST = ['cmex10', 'cmmi10', 'cmr10', 'cmsy10', 'esint10', 'eufm10', - 'msam10', 'msbm10', 'rsfs10', 'wasy10'] +class FontComboBox(Gtk.ToolItem): -class FontComboBox(Gtk.ComboBox): + __gsignals__ = { + 'changed': (GObject.SignalFlags.RUN_LAST, None, ([])), } def __init__(self): - GObject.GObject.__init__(self) - font_renderer = Gtk.CellRendererText() - self.pack_start(font_renderer, True) - self.add_attribute(font_renderer, 'text', 0) - self.add_attribute(font_renderer, 'font', 0) - font_model = Gtk.ListStore(str) + self._palette_invoker = ToolInvoker() + Gtk.ToolItem.__init__(self) + self._font_label = FontLabel() + bt = Gtk.Button('') + bt.set_can_focus(False) + bt.remove(bt.get_children()[0]) + box = Gtk.HBox() + bt.add(box) + icon = Icon(icon_name='font-text') + box.pack_start(icon, False, False, 10) + box.pack_start(self._font_label, False, False, 10) + self.add(bt) + self.show_all() + + self._font_name = 'Sans' + + # theme the button, can be removed if add the style to the sugar css + if style.zoom(100) == 100: + subcell_size = 15 + else: + subcell_size = 11 + radius = 2 * subcell_size + theme = "GtkButton {border-radius: %dpx;}" % radius + css_provider = Gtk.CssProvider() + css_provider.load_from_data(theme) + style_context = bt.get_style_context() + style_context.add_provider(css_provider, + Gtk.STYLE_PROVIDER_PRIORITY_USER) + + # init palette + self._hide_tooltip_on_click = True + self._palette_invoker.attach_tool(self) + self._palette_invoker.props.toggle_palette = True + + self.palette = Palette(_('Select font')) + self.palette.set_invoker(self._palette_invoker) + + # load the fonts in the palette menu + self._menu_box = PaletteMenuBox() + self.props.palette.set_content(self._menu_box) + self._menu_box.show() context = self.get_pango_context() - font_index = 0 - self.faces = {} + self._init_font_list() + + tmp_list = [] for family in context.list_families(): name = family.get_name() - if name not in FONT_BLACKLIST: - font_model.append([name]) - # TODO gtk3 -# font_faces = [] -# for face in family.list_faces(): -# face_name = face.get_face_name() -# font_faces.append(face_name) -# self.faces[name] = font_faces - - font_model.set_sort_column_id(0, Gtk.SortType.ASCENDING) - self.set_model(font_model) - self.show() + if name in self._font_white_list: + tmp_list.append(name) + for name in sorted(tmp_list): + self._add_menu(name, self.__font_selected_cb) + + self._font_label.set_font(self._font_name) + + def _init_font_list(self): + self._font_white_list = [] + self._font_white_list.extend(DEFAULT_FONTS) + + # check if there are a user configuration file + if not os.path.exists(USER_FONTS_FILE_PATH): + # verify if exists a file in /etc + if os.path.exists(GLOBAL_FONTS_FILE_PATH): + shutil.copy(GLOBAL_FONTS_FILE_PATH, USER_FONTS_FILE_PATH) + + if os.path.exists(USER_FONTS_FILE_PATH): + # get the font names in the file to the white list + fonts_file = open(USER_FONTS_FILE_PATH) + # get the font names in the file to the white list + for line in fonts_file: + self._font_white_list.append(line.strip()) + # monitor changes in the file + gio_fonts_file = Gio.File.new_for_path(USER_FONTS_FILE_PATH) + self.monitor = gio_fonts_file.monitor_file( + Gio.FileMonitorFlags.NONE, None) + self.monitor.set_rate_limit(5000) + self.monitor.connect('changed', self._reload_fonts) + + def _reload_fonts(self, monitor, gio_file, other_file, event): + if event != Gio.FileMonitorEvent.CHANGES_DONE_HINT: + return + self._font_white_list = [] + self._font_white_list.extend(DEFAULT_FONTS) + fonts_file = open(USER_FONTS_FILE_PATH) + for line in fonts_file: + self._font_white_list.append(line.strip()) + # update the menu + for child in self._menu_box.get_children(): + self._menu_box.remove(child) + child = None + context = self.get_pango_context() + tmp_list = [] + for family in context.list_families(): + name = family.get_name() + if name in self._font_white_list: + tmp_list.append(name) + for name in sorted(tmp_list): + self._add_menu(name, self.__font_selected_cb) + return False + + def __font_selected_cb(self, menu, font_name): + self._font_name = font_name + self._font_label.set_font(font_name) + self.emit('changed') + + def _add_menu(self, font_name, activate_cb): + label = '<span font="%s">%s</span>' % (font_name, font_name) + menu_item = PaletteMenuItem() + menu_item.set_label(label) + menu_item.connect('activate', activate_cb, font_name) + self._menu_box.append_item(menu_item) + menu_item.show() + + def __destroy_cb(self, icon): + if self._palette_invoker is not None: + self._palette_invoker.detach() + + def create_palette(self): + return None + + def get_palette(self): + return self._palette_invoker.palette + + def set_palette(self, palette): + self._palette_invoker.palette = palette + + palette = GObject.property( + type=object, setter=set_palette, getter=get_palette) + + def get_palette_invoker(self): + return self._palette_invoker + + def set_palette_invoker(self, palette_invoker): + self._palette_invoker.detach() + self._palette_invoker = palette_invoker + + palette_invoker = GObject.property( + type=object, setter=set_palette_invoker, getter=get_palette_invoker) def set_font_name(self, font_name): - count = 0 - tree_iter = self.get_model().get_iter_first() - while tree_iter is not None: - value = self.get_model().get_value(tree_iter, 0) - if value == font_name: - self.set_active(count) - count = count + 1 - tree_iter = self.get_model().iter_next(tree_iter) + self._font_label.set_font(font_name) def get_font_name(self): - tree_iter = self.get_active_iter() - return self.get_model().get_value(tree_iter, 0) + return self._font_name + + +class FontSize(Gtk.ToolItem): + + __gsignals__ = { + 'changed': (GObject.SignalFlags.RUN_LAST, None, ([])), } + + def __init__(self): + + Gtk.ToolItem.__init__(self) + + self._font_sizes = [8, 9, 10, 11, 12, 14, 16, 20, 22, 24, 26, 28, 36, + 48, 72] + + # theme the buttons, can be removed if add the style to the sugar css + # these are the same values used in gtk-widgets.css.em + if style.zoom(100) == 100: + subcell_size = 15 + default_padding = 6 + else: + subcell_size = 11 + default_padding = 4 + + hbox = Gtk.HBox() + vbox = Gtk.VBox() + self.add(vbox) + # add a vbox to set the padding up and down + vbox.pack_start(hbox, True, True, default_padding) + self._size_down = Gtk.Button() + self._size_down.set_can_focus(False) + icon = Icon(icon_name='resize-') + self._size_down.set_image(icon) + self._size_down.connect('clicked', self.__font_sizes_cb, False) + hbox.pack_start(self._size_down, False, False, 5) + + # TODO: default? + self._default_size = 12 + self._font_size = self._default_size + + self._size_label = Gtk.Label(str(self._font_size)) + hbox.pack_start(self._size_label, False, False, 10) + + self._size_up = Gtk.Button() + self._size_up.set_can_focus(False) + icon = Icon(icon_name='resize+') + self._size_up.set_image(icon) + self._size_up.connect('clicked', self.__font_sizes_cb, True) + hbox.pack_start(self._size_up, False, False, 5) + + radius = 2 * subcell_size + theme_up = "GtkButton {border-radius:0px %dpx %dpx 0px;}" % (radius, + radius) + css_provider_up = Gtk.CssProvider() + css_provider_up.load_from_data(theme_up) + + style_context = self._size_up.get_style_context() + style_context.add_provider(css_provider_up, + Gtk.STYLE_PROVIDER_PRIORITY_USER) + + theme_down = "GtkButton {border-radius: %dpx 0px 0px %dpx;}" % (radius, + radius) + css_provider_down = Gtk.CssProvider() + css_provider_down.load_from_data(theme_down) + style_context = self._size_down.get_style_context() + style_context.add_provider(css_provider_down, + Gtk.STYLE_PROVIDER_PRIORITY_USER) + + self.show_all() + + def __font_sizes_cb(self, button, increase): + if self._font_size in self._font_sizes: + i = self._font_sizes.index(self._font_size) + if increase: + if i < len(self._font_sizes) - 1: + i += 1 + else: + if i > 0: + i -= 1 + else: + i = self._font_sizes.index(self._default_size) + + self._font_size = self._font_sizes[i] + self._size_label.set_text(str(self._font_size)) + self._size_down.set_sensitive(i != 0) + self._size_up.set_sensitive(i < len(self._font_sizes) - 1) + self.emit('changed') + + def set_font_size(self, size): + if size not in self._font_sizes: + # assure the font assigned is in the range + # if not, assign one close. + for font_size in self._font_sizes: + if font_size > size: + size = font_size + break + if size > self._font_sizes[-1]: + size = self._font_sizes[-1] + + self._font_size = size + self._size_label.set_text(str(self._font_size)) + + # update the buttons states + i = self._font_sizes.index(self._font_size) + self._size_down.set_sensitive(i != 0) + self._size_up.set_sensitive(i < len(self._font_sizes) - 1) + self.emit('changed') + + def get_font_size(self): + return self._font_size diff --git a/icons/font-text.svg b/icons/font-text.svg new file mode 100644 index 0000000..ad3f9fa --- /dev/null +++ b/icons/font-text.svg @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="55" + height="54.695999" + viewBox="0 0 55 54.696" + id="svg2" + xml:space="preserve"><metadata + id="metadata22"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs + id="defs20" /><text + x="-2.6176355" + y="43.461388" + transform="scale(0.90891499,1.1002129)" + id="text3591" + xml:space="preserve" + style="font-size:49.5765152px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Verdana;-inkscape-font-specification:Verdana"><tspan + x="-2.6176355" + y="43.461388" + id="tspan3593" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Serif;-inkscape-font-specification:Serif"><tspan + id="tspan2992" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Sans;-inkscape-font-specification:Sans">F</tspan>F</tspan></text> +</svg>
\ No newline at end of file diff --git a/icons/resize+.svg b/icons/resize+.svg new file mode 100644 index 0000000..0fae3c3 --- /dev/null +++ b/icons/resize+.svg @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="55" + height="54.695999" + viewBox="0 0 55 54.696" + id="svg2" + xml:space="preserve"><defs + id="defs21"> + + + + + </defs><g + transform="translate(-0.4354,0)" + id="g7"> + <g + id="g9"> + <path + d="m 25.263,12.435 h 24.656 v 3.562 H 39.575 V 41.59 H 35.606 V 15.996 H 25.263 v -3.561 z" + id="path11" + style="fill:#ffffff" /> + </g> + </g><g + transform="translate(-8.4356,0)" + id="g13"> + <g + id="g15"> + <path + d="m 13.953,24.435 h 16.656 v 3.562 H 24.265 V 41.59 H 20.296 V 27.997 h -6.344 v -3.562 z" + id="path17" + style="fill:#ffffff" /> + </g> + </g><path + d="m 25.5774,23.677763 6,-6.000001 -4,0" + id="path3618" + style="fill:none;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></svg>
\ No newline at end of file diff --git a/icons/resize-.svg b/icons/resize-.svg new file mode 100644 index 0000000..e3b719e --- /dev/null +++ b/icons/resize-.svg @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="55" + height="54.695999" + viewBox="0 0 55 54.696" + id="svg2" + xml:space="preserve"><defs + id="defs21"> + + + + + </defs><g + transform="translate(3.5644,0)" + id="g2821"><g + transform="matrix(-1,0,0,1,51.871,0)" + id="g7"> + <g + id="g9"> + <path + d="m 25.263,12.435 h 24.656 v 3.562 H 39.575 V 41.59 H 35.606 V 15.996 H 25.263 v -3.561 z" + id="path11" + style="fill:#ffffff" /> + </g> + </g><g + transform="matrix(-1,0,0,1,59.8712,0)" + id="g13"> + <g + id="g15"> + <path + d="m 13.953,24.435 h 16.656 v 3.562 H 24.265 V 41.59 H 20.296 V 27.997 h -6.344 v -3.562 z" + id="path17" + style="fill:#ffffff" /> + </g> + </g><path + d="m 19.8582,17.677762 6,6.000001 -4,0" + id="path3618" + style="fill:none;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></svg>
\ No newline at end of file @@ -33,6 +33,7 @@ from sugar3.graphics.palettemenu import PaletteMenuItem from sugar3.graphics.palettemenu import PaletteMenuBox from fontcombobox import FontComboBox +from fontcombobox import FontSize import globos from sugar3.graphics.colorbutton import ColorToolButton @@ -277,32 +278,17 @@ class TextToolbar(Gtk.Toolbar): separator.set_draw(True) self.insert(separator, -1) - # tamanio - self._font_size_icon = Icon(icon_name="format-text-size", - icon_size=Gtk.IconSize.LARGE_TOOLBAR) - tool_item = Gtk.ToolItem() - tool_item.add(self._font_size_icon) - self.insert(tool_item, -1) - - self._font_size_combo = ComboBox() - self._font_sizes = ['8', '10', '12', '14', '16', '20', '22', '24', - '26', '28', '36', '48', '72'] + self._font_size_combo = FontSize() self._font_size_changed_id = self._font_size_combo.connect( 'changed', self._font_size_changed_cb) - for i, s in enumerate(self._font_sizes): - self._font_size_combo.append_item(i, s, None) - if s == '10': - self._font_size_combo.set_active(i) - tool_item = ToolComboBox(self._font_size_combo) - self.insert(tool_item, -1) + self.insert(self._font_size_combo, -1) # font self._font_combo = FontComboBox() self._font_combo.set_font_name(globos.DEFAULT_FONT) self._fonts_changed_id = self._font_combo.connect( 'changed', self._font_changed_cb) - tool_item = ToolComboBox(self._font_combo) - self.insert(tool_item, -1) + self.insert(ToolComboBox(self._font_combo), -1) self.show_all() @@ -338,25 +324,22 @@ class TextToolbar(Gtk.Toolbar): texto.color = (color.red, color.green, color.blue) self._page.get_active_box().redraw() - def _font_size_changed_cb(self, combobox): - if self._font_size_combo.get_active() != -1: - size = int(self._font_sizes[self._font_size_combo.get_active()]) - logger.debug('Setting font size: %d', size) - globo_activo = self._page.get_globo_activo() - if globo_activo is not None and globo_activo.texto is not None: - globo_activo.texto.font_size = size - globo_activo.texto.alto_renglon = size - self._page.get_active_box().redraw() - - def _font_changed_cb(self, combobox): - if self._font_combo.get_active() != -1: - font_name = self._font_combo.get_font_name() - logger.debug('Setting font name: %s', font_name) - globo_activo = self._page.get_globo_activo() - if globo_activo is not None and globo_activo.texto is not None: - globo_activo.texto.font_type = font_name - self._page.selected_font_name = font_name - self._page.get_active_box().redraw() + def _font_size_changed_cb(self, widget): + size = widget.get_font_size() + logger.debug('Setting font size: %d', size) + globo_activo = self._page.get_globo_activo() + if globo_activo is not None and globo_activo.texto is not None: + globo_activo.texto.font_size = size + self._page.get_active_box().redraw() + + def _font_changed_cb(self, widget): + font_name = widget.get_font_name() + logger.debug('Setting font name: %s', font_name) + globo_activo = self._page.get_globo_activo() + if globo_activo is not None and globo_activo.texto is not None: + globo_activo.texto.font_type = font_name + self._page.selected_font_name = font_name + self._page.get_active_box().redraw() """ Estos son los metodos para setear los contrles de la barra en base a el @@ -377,13 +360,10 @@ class TextToolbar(Gtk.Toolbar): # color self._text_color.set_color(Gdk.Color(*globeText.color)) # font size - for i, s in enumerate(self._font_sizes): - if int(s) == int(globeText.font_size): - self._font_size_combo.handler_block(self._font_size_changed_id) - self._font_size_combo.set_active(i) - self._font_size_combo.handler_unblock( - self._font_size_changed_id) - break + logging.error('Setting font size from globe %s %s', globeText.font_size, globeText.font_size.__class__) + self._font_size_combo.handler_block(self._font_size_changed_id) + self._font_size_combo.set_font_size(int(globeText.font_size)) + self._font_size_combo.handler_unblock(self._font_size_changed_id) # font seleccionada self._font_combo.handler_block(self._fonts_changed_id) |