Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGonzalo Odiard <godiard@gmail.com>2013-06-11 20:09:23 (GMT)
committer Gonzalo Odiard <godiard@gmail.com>2013-06-11 20:09:23 (GMT)
commita886bb31553e6550b007f5c2b737e029a58fdbaf (patch)
tree23b5f39976435f78a03372ce1f3727fab4749a75
parent868ea2dcf018161da1e334927437bb9ae407c56b (diff)
Use new widgets for font selection to improve use with touch
Signed-off-by: Gonzalo Odiard <gonzalo@laptop.org>
-rw-r--r--fontcombobox.py309
-rw-r--r--icons/font-text.svg32
-rw-r--r--icons/resize+.svg41
-rw-r--r--icons/resize-.svg43
-rw-r--r--toolbar.py68
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
diff --git a/toolbar.py b/toolbar.py
index 2141304..5ff28cd 100644
--- a/toolbar.py
+++ b/toolbar.py
@@ -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)