Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fontcombobox.py306
-rw-r--r--icons/font-text.svg32
-rw-r--r--icons/resize+.svg41
-rw-r--r--icons/resize-.svg43
-rw-r--r--toolbar.py23
-rw-r--r--widgets.py103
6 files changed, 409 insertions, 139 deletions
diff --git a/fontcombobox.py b/fontcombobox.py
index 9de5e34..0ae4d0f 100644
--- a/fontcombobox.py
+++ b/fontcombobox.py
@@ -15,52 +15,292 @@
# 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.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()
+ 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()
+ 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 e344776..3b18f13 100644
--- a/toolbar.py
+++ b/toolbar.py
@@ -41,8 +41,8 @@ from sugar3.activity.widgets import RedoButton
from widgets import AbiButton
from widgets import AbiMenuItem
-from widgets import FontSizeCombo
from fontcombobox import FontComboBox
+from fontcombobox import FontSize
from gridcreate import GridCreateWidget
logger = logging.getLogger('write-activity')
@@ -430,8 +430,12 @@ class TextToolbar(Gtk.Toolbar):
self._font_family_cb)
self.insert(ToolComboBox(self.font_name_combo), -1)
- font_size = ToolComboBox(FontSizeCombo(abiword_canvas))
- self.insert(font_size, -1)
+ self.font_size = FontSize()
+ self._abi_handler = abiword_canvas.connect('font-size',
+ self._font_size_cb)
+ self._changed_id = self.font_size.connect(
+ 'changed', self._font_size_changed_cb, abiword_canvas)
+ self.insert(self.font_size, -1)
bold = ToggleToolButton('format-text-bold')
bold.set_tooltip(_('Bold'))
@@ -520,6 +524,19 @@ class TextToolbar(Gtk.Toolbar):
logging.debug('Abiword font changed to %s', font_family)
self.font_name_combo.set_font_name(font_family)
+ def _font_size_changed_cb(self, widget, abi):
+ abi.handler_block(self._abi_handler)
+ try:
+ abi.set_font_size(str(widget.get_font_size()))
+ finally:
+ abi.handler_unblock(self._abi_handler)
+
+ def _font_size_cb(self, abi, size):
+ logging.debug('Abiword font size changed to %s', size)
+ self.handler_block(self._changed_id)
+ self.font_size.set_font_size(int(size))
+ self.handler_unblock(self._changed_id)
+
def _setToggleButtonState(self, button, b, id):
button.handler_block(id)
button.set_active(b)
diff --git a/widgets.py b/widgets.py
index 18aa08a..2579007 100644
--- a/widgets.py
+++ b/widgets.py
@@ -22,8 +22,6 @@ from gi.repository import Abi
from gi.repository import GLib
from sugar3.graphics.radiotoolbutton import RadioToolButton
-from sugar3.graphics.combobox import ComboBox
-from sugar3.graphics.palette import Palette
from sugar3.graphics.toolbutton import ToolButton
from sugar3.graphics.palettemenu import PaletteMenuItem
from sugar3.datastore import datastore
@@ -32,107 +30,6 @@ from sugar3.activity.activity import SCOPE_PRIVATE
logger = logging.getLogger('write-activity')
-"""
-# The FontCombo is not used anymore, keep the code here for reference
-# for a few versions
-
-class FontCombo(ComboBox):
-
- def __init__(self, abi):
- ComboBox.__init__(self)
-
- self._has_custom_fonts = False
- self._fonts = sorted(abi.get_font_names())
- self._fonts_changed_id = self.connect('changed', self._font_changed_cb,
- abi)
-
- for i, f in enumerate(self._fonts):
- self.append_item(i, f, None)
- if f == 'Times New Roman':
- self.set_active(i)
-
- self._abi_handler = abi.connect('font-family', self._font_family_cb)
-
- def _font_changed_cb(self, combobox, abi):
- if self.get_active() != -1:
- logger.debug('Setting font: %s', self._fonts[self.get_active()])
- try:
- abi.handler_block(self._abi_handler)
- abi.set_font_name(self._fonts[self.get_active()])
- finally:
- abi.handler_unblock(self._abi_handler)
-
- def _font_family_cb(self, abi, font_family):
- font_index = -1
-
- # search for the font name in our font list
- for i, f in enumerate(self._fonts):
- if f == font_family:
- font_index = i
- break
-
- # if we don't know this font yet, then add it (temporary) to the list
- if font_index == -1:
- logger.debug('Font not found in font list: %s', font_family)
- if not self._has_custom_fonts:
- # add a separator to seperate the non-available fonts from
- # the available ones
- self._fonts.append('') # ugly
- self.append_separator()
- self._has_custom_fonts = True
- # add the new font
- self._fonts.append(font_family)
- self.append_item(0, font_family, None)
- # see how many fonts we have now, so we can select the last one
- model = self.get_model()
- num_children = model.iter_n_children(None)
- logger.debug('Number of fonts in the list: %d', num_children)
- font_index = num_children - 1
-
- # activate the found font
- if (font_index > -1):
- self.handler_block(self._fonts_changed_id)
- self.set_active(font_index)
- self.handler_unblock(self._fonts_changed_id)
-"""
-
-
-class FontSizeCombo(ComboBox):
-
- def __init__(self, abi):
- ComboBox.__init__(self)
-
- self._abi_handler = abi.connect('font-size', self._font_size_cb)
-
- self._font_sizes = ['8', '9', '10', '11', '12', '14', '16', '20', \
- '22', '24', '26', '28', '36', '48', '72']
- self._changed_id = self.connect('changed', self._font_size_changed_cb,
- abi)
-
- for i, s in enumerate(self._font_sizes):
- self.append_item(i, s, None)
- if s == '12':
- self.set_active(i)
-
- def _font_size_changed_cb(self, combobox, abi):
- if self.get_active() != -1:
- logger.debug('Setting font size: %d',
- int(self._font_sizes[self.get_active()]))
-
- abi.handler_block(self._abi_handler)
- try:
- abi.set_font_size(self._font_sizes[self.get_active()])
- finally:
- abi.handler_unblock(self._abi_handler)
-
- def _font_size_cb(self, abi, size):
- for i, s in enumerate(self._font_sizes):
- if int(s) == int(size):
- self.handler_block(self._changed_id)
- self.set_active(i)
- self.handler_unblock(self._changed_id)
- break
-
class AbiButton(RadioToolButton):