mirror of
https://github.com/GNOME/gedit
synced 2024-06-30 23:15:01 +00:00
plugins: add textsize, coming from the gedit-plugins repo
The textsize/ directory has been copied as-is from the gedit-plugins repo (after some adaptations in gedit-plugins). The user manual page will be moved in a follow-up commit. Fixes https://gitlab.gnome.org/GNOME/gedit/-/issues/482
This commit is contained in:
parent
3c7c7c6826
commit
91043c4a6a
|
@ -25,6 +25,7 @@ subdir('quickopen')
|
|||
subdir('snippets')
|
||||
subdir('sort')
|
||||
subdir('spell')
|
||||
subdir('textsize')
|
||||
subdir('time')
|
||||
|
||||
if get_option('buggy_plugins')
|
||||
|
|
13
plugins/textsize/meson.build
Normal file
13
plugins/textsize/meson.build
Normal file
|
@ -0,0 +1,13 @@
|
|||
install_subdir(
|
||||
'textsize',
|
||||
install_dir: get_option('libdir') / 'gedit/plugins',
|
||||
)
|
||||
|
||||
custom_target(
|
||||
'textsize.plugin',
|
||||
input: 'textsize.plugin.desktop.in',
|
||||
output: 'textsize.plugin',
|
||||
command: msgfmt_plugin_cmd,
|
||||
install: true,
|
||||
install_dir: get_option('libdir') / 'gedit/plugins',
|
||||
)
|
9
plugins/textsize/textsize.plugin.desktop.in
Normal file
9
plugins/textsize/textsize.plugin.desktop.in
Normal file
|
@ -0,0 +1,9 @@
|
|||
[Plugin]
|
||||
Loader=python3
|
||||
Module=textsize
|
||||
IAge=3
|
||||
Name=Text Size
|
||||
Description=Easily increase and decrease the text size.
|
||||
Authors=Konstantin Mikhaylov <jtraub.devel@gmail.com>;Wouter Bolsterlee <wbolster@gnome.org>;Jesse van den Kieboom <jessevdk@gnome.org>
|
||||
Copyright=Copyright © 2008 by the authors
|
||||
Website=https://gedit-technology.github.io/apps/gedit/
|
118
plugins/textsize/textsize/__init__.py
Normal file
118
plugins/textsize/textsize/__init__.py
Normal file
|
@ -0,0 +1,118 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# __init__.py - Text size plugin
|
||||
#
|
||||
# Copyright (C) 2008 - Konstantin Mikhaylov <jtraub.devel@gmail.com>
|
||||
# Copyright (C) 2009 - Wouter Bolsterlee <wbolster@gnome.org>
|
||||
# Copyright (C) 2010 - Ignacio Casal Quinteiro <icq@gnome.org>
|
||||
# Copyright (C) 2010 - Jesse van den Kieboom <jessevdk@gnome.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# 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 Street, Fifth Floor,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
gi.require_version('Gedit', '3.0')
|
||||
from gi.repository import GObject, Gio, Gtk, Gdk, Gedit
|
||||
from .viewactivatable import TextSizeViewActivatable
|
||||
|
||||
try:
|
||||
import gettext
|
||||
gettext.bindtextdomain('gedit-plugins')
|
||||
gettext.textdomain('gedit-plugins')
|
||||
_ = gettext.gettext
|
||||
except:
|
||||
_ = lambda s: s
|
||||
|
||||
|
||||
class TextSizeAppActivatable(GObject.Object, Gedit.AppActivatable):
|
||||
|
||||
app = GObject.Property(type=Gedit.App)
|
||||
|
||||
def __init__(self):
|
||||
GObject.Object.__init__(self)
|
||||
|
||||
def do_activate(self):
|
||||
self.app.set_accels_for_action("win.text-larger", ["<Primary>plus", "<Primary>KP_Add"])
|
||||
self.app.set_accels_for_action("win.text-smaller", ["<Primary>minus", "<Primary>KP_Subtract"])
|
||||
self.app.set_accels_for_action("win.text-normal", ["<Primary>0", "<Primary>KP_0"])
|
||||
|
||||
self.menu_ext = self.extend_menu("view-section-2")
|
||||
item = Gio.MenuItem.new(_("_Normal size"), "win.text-normal")
|
||||
self.menu_ext.prepend_menu_item(item)
|
||||
item = Gio.MenuItem.new(_("S_maller Text"), "win.text-smaller")
|
||||
self.menu_ext.prepend_menu_item(item)
|
||||
item = Gio.MenuItem.new(_("_Larger Text"), "win.text-larger")
|
||||
self.menu_ext.prepend_menu_item(item)
|
||||
|
||||
def do_deactivate(self):
|
||||
self.app.set_accels_for_action("win.text-larger", [])
|
||||
self.app.set_accels_for_action("win.text-smaller", [])
|
||||
self.app.set_accels_for_action("win.text-normal", [])
|
||||
self.menu_ext = None
|
||||
|
||||
|
||||
class TextSizeWindowActivatable(GObject.Object, Gedit.WindowActivatable):
|
||||
|
||||
window = GObject.Property(type=Gedit.Window)
|
||||
|
||||
def __init__(self):
|
||||
GObject.Object.__init__(self)
|
||||
|
||||
def do_activate(self):
|
||||
action = Gio.SimpleAction(name="text-larger")
|
||||
action.connect('activate', self.on_larger_text_activate)
|
||||
self.window.add_action(action)
|
||||
|
||||
action = Gio.SimpleAction(name="text-smaller")
|
||||
action.connect('activate', self.on_smaller_text_activate)
|
||||
self.window.add_action(action)
|
||||
|
||||
action = Gio.SimpleAction(name="text-normal")
|
||||
action.connect('activate', self.on_normal_size_activate)
|
||||
self.window.add_action(action)
|
||||
|
||||
def do_deactivate(self):
|
||||
self.window.remove_action("text-larger")
|
||||
self.window.remove_action("text-smaller")
|
||||
self.window.remove_action("text-normal")
|
||||
|
||||
def do_update_state(self):
|
||||
self.window.lookup_action("text-larger").set_enabled(self.window.get_active_document() != None)
|
||||
self.window.lookup_action("text-smaller").set_enabled(self.window.get_active_document() != None)
|
||||
self.window.lookup_action("text-normal").set_enabled(self.window.get_active_document() != None)
|
||||
|
||||
def get_view_activatable(self, view):
|
||||
if not hasattr(view, "textsize_view_activatable"):
|
||||
return None
|
||||
return view.textsize_view_activatable
|
||||
|
||||
def call_view_activatable(self, cb):
|
||||
view = self.window.get_active_view()
|
||||
|
||||
if view:
|
||||
cb(self.get_view_activatable(view))
|
||||
|
||||
# Menu activate handlers
|
||||
def on_larger_text_activate(self, action, parameter, user_data=None):
|
||||
self.call_view_activatable(lambda va: va.larger_text())
|
||||
|
||||
def on_smaller_text_activate(self, action, parameter, user_data=None):
|
||||
self.call_view_activatable(lambda va: va.smaller_text())
|
||||
|
||||
def on_normal_size_activate(self, action, parameter, user_data=None):
|
||||
self.call_view_activatable(lambda va: va.normal_size())
|
||||
|
||||
# ex:ts=4:et:
|
92
plugins/textsize/textsize/signals.py
Normal file
92
plugins/textsize/textsize/signals.py
Normal file
|
@ -0,0 +1,92 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# signals.py
|
||||
#
|
||||
# Copyright (C) 2009 - Jesse van den Kieboom
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# 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 Street, Fifth Floor,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
|
||||
class Signals(object):
|
||||
def __init__(self):
|
||||
self._signals = {}
|
||||
|
||||
def _connect(self, obj, name, handler, connector):
|
||||
ret = self._signals.setdefault(obj, {})
|
||||
|
||||
hid = connector(name, handler)
|
||||
ret.setdefault(name, []).append(hid)
|
||||
|
||||
return hid
|
||||
|
||||
def connect_signal(self, obj, name, handler):
|
||||
return self._connect(obj, name, handler, obj.connect)
|
||||
|
||||
def connect_signal_after(self, obj, name, handler):
|
||||
return self._connect(obj, name, handler, obj.connect_after)
|
||||
|
||||
def disconnect_signals(self, obj):
|
||||
if obj not in self._signals:
|
||||
return False
|
||||
|
||||
for name in self._signals[obj]:
|
||||
for hid in self._signals[obj][name]:
|
||||
obj.disconnect(hid)
|
||||
|
||||
del self._signals[obj]
|
||||
return True
|
||||
|
||||
def block_signal(self, obj, name):
|
||||
if obj not in self._signals:
|
||||
return False
|
||||
|
||||
if name not in self._signals[obj]:
|
||||
return False
|
||||
|
||||
for hid in self._signals[obj][name]:
|
||||
obj.handler_block(hid)
|
||||
|
||||
return True
|
||||
|
||||
def unblock_signal(self, obj, name):
|
||||
if obj not in self._signals:
|
||||
return False
|
||||
|
||||
if name not in self._signals[obj]:
|
||||
return False
|
||||
|
||||
for hid in self._signals[obj][name]:
|
||||
obj.handler_unblock(hid)
|
||||
|
||||
return True
|
||||
|
||||
def disconnect_signal(self, obj, name):
|
||||
if obj not in self._signals:
|
||||
return False
|
||||
|
||||
if name not in self._signals[obj]:
|
||||
return False
|
||||
|
||||
for hid in self._signals[obj][name]:
|
||||
obj.disconnect(hid)
|
||||
|
||||
del self._signals[obj][name]
|
||||
|
||||
if len(self._signals[obj]) == 0:
|
||||
del self._signals[obj]
|
||||
|
||||
return True
|
||||
|
||||
# ex:ts=4:et:
|
198
plugins/textsize/textsize/viewactivatable.py
Normal file
198
plugins/textsize/textsize/viewactivatable.py
Normal file
|
@ -0,0 +1,198 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# viewactivatable.py - Gedit View Activatable Implementation
|
||||
#
|
||||
# Copyright (C) 2010 - Jesse van den Kieboom
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# 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 Street, Fifth Floor,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
|
||||
from .signals import Signals
|
||||
from gi.repository import GObject, Gtk, Gdk, Pango, Gedit
|
||||
|
||||
class TextSizeViewActivatable(GObject.Object, Gedit.ViewActivatable, Signals):
|
||||
|
||||
view = GObject.Property(type=Gedit.View)
|
||||
|
||||
def __init__(self):
|
||||
GObject.Object.__init__(self)
|
||||
Signals.__init__(self)
|
||||
|
||||
def do_activate(self):
|
||||
self.connect_signal(self.view, 'scroll-event', self.on_scroll_event)
|
||||
self.connect_signal(self.view, 'button-press-event', self.on_button_press_event)
|
||||
|
||||
self.view.textsize_view_activatable = self
|
||||
|
||||
self._default_font = None
|
||||
self._last_font = None
|
||||
self._font_tags = {}
|
||||
|
||||
def do_deactivate(self):
|
||||
if self._default_font:
|
||||
self.view.override_font(self._default_font)
|
||||
|
||||
self.remove_font_tags()
|
||||
self.disconnect_signals(self.view)
|
||||
|
||||
delattr(self.view, "textsize_view_activatable")
|
||||
|
||||
def remove_font_tags(self):
|
||||
buf = self.view.get_buffer()
|
||||
table = buf.get_tag_table()
|
||||
|
||||
# Remove all the font tags
|
||||
for size in self._font_tags:
|
||||
tag = self._font_tags[size]
|
||||
table.remove(tag)
|
||||
|
||||
self._font_tags = {}
|
||||
|
||||
def update_default_font(self):
|
||||
context = self.view.get_style_context()
|
||||
description = context.get_font(context.get_state()).copy()
|
||||
|
||||
if not self._last_font or description.hash() != self._last_font.hash():
|
||||
self._default_font = description
|
||||
|
||||
def get_font_tags(self, start, end):
|
||||
tags = set()
|
||||
|
||||
# Check all the know font tags
|
||||
for size in self._font_tags:
|
||||
tag = self._font_tags[size]
|
||||
|
||||
if start.has_tag(tag):
|
||||
tags.add(tag)
|
||||
else:
|
||||
cp = start.copy()
|
||||
|
||||
if cp.forward_to_tag_toggle(tag) and cp.compare(end) < 0:
|
||||
tags.add(tag)
|
||||
|
||||
return list(tags)
|
||||
|
||||
def set_font_size(self, amount):
|
||||
self.update_default_font()
|
||||
|
||||
context = self.view.get_style_context()
|
||||
description = context.get_font(context.get_state()).copy()
|
||||
|
||||
buf = self.view.get_buffer()
|
||||
bounds = buf.get_selection_bounds()
|
||||
size = description.get_size() / Pango.SCALE
|
||||
|
||||
if not bounds:
|
||||
description.set_size(max(1, (size + amount)) * Pango.SCALE)
|
||||
|
||||
self.view.override_font(description)
|
||||
self._last_font = description
|
||||
else:
|
||||
start = bounds[0]
|
||||
end = bounds[1]
|
||||
|
||||
tags = self.get_font_tags(start, end)
|
||||
|
||||
if not tags:
|
||||
# Simply use the overall font size as the base
|
||||
newsize = size + amount
|
||||
elif len(tags) == 1:
|
||||
newsize = tags[0].props.font_desc.get_size() / Pango.SCALE + amount
|
||||
else:
|
||||
newsize = 0
|
||||
|
||||
for tag in tags:
|
||||
newsize += tag.props.font_desc.get_size() / Pango.SCALE
|
||||
|
||||
newsize = round(newsize / len(tags))
|
||||
|
||||
newsize = int(max(1, newsize))
|
||||
|
||||
if not newsize in self._font_tags:
|
||||
newtag = buf.create_tag(None)
|
||||
|
||||
desc = description
|
||||
desc.set_size(newsize * Pango.SCALE)
|
||||
|
||||
newtag.props.font_desc = desc
|
||||
self._font_tags[newsize] = newtag
|
||||
else:
|
||||
newtag = self._font_tags[newsize]
|
||||
|
||||
# Remove all the previous mix of tags
|
||||
for tag in tags:
|
||||
buf.remove_tag(tag, start, end)
|
||||
|
||||
buf.apply_tag(newtag, start, end)
|
||||
|
||||
def larger_text(self):
|
||||
self.set_font_size(1)
|
||||
|
||||
def smaller_text(self):
|
||||
self.set_font_size(-1)
|
||||
|
||||
def normal_size(self):
|
||||
self.update_default_font()
|
||||
|
||||
buf = self.view.get_buffer()
|
||||
bounds = buf.get_selection_bounds()
|
||||
|
||||
if not bounds:
|
||||
self.remove_font_tags()
|
||||
|
||||
self.view.override_font(self._default_font)
|
||||
self._last_font = self._default_font
|
||||
else:
|
||||
tags = self.get_font_tags(bounds[0], bounds[1])
|
||||
|
||||
for tag in tags:
|
||||
buf.remove_tag(tag, bounds[0], bounds[1])
|
||||
|
||||
def on_scroll_event(self, view, event):
|
||||
state = event.state & Gtk.accelerator_get_default_mod_mask()
|
||||
|
||||
if state != Gdk.ModifierType.CONTROL_MASK:
|
||||
return False
|
||||
|
||||
# Scroll to the keep the line in the centre of the screen anchored
|
||||
visible_rect = self.view.get_visible_rect()
|
||||
central_line_y = visible_rect.height / 2 + visible_rect.y
|
||||
central_line_iter, _ = self.view.get_line_at_y(central_line_y)
|
||||
self.view.scroll_to_iter(central_line_iter, 0, True, 0.5, 0.5)
|
||||
|
||||
if event.direction == Gdk.ScrollDirection.UP:
|
||||
self.larger_text()
|
||||
return True
|
||||
elif event.direction == Gdk.ScrollDirection.DOWN:
|
||||
self.smaller_text()
|
||||
return True
|
||||
elif event.direction == Gdk.ScrollDirection.SMOOTH:
|
||||
if event.delta_y > 0:
|
||||
self.smaller_text()
|
||||
elif event.delta_y < 0:
|
||||
self.larger_text()
|
||||
|
||||
return False
|
||||
|
||||
def on_button_press_event(self, view, event):
|
||||
state = event.state & Gtk.accelerator_get_default_mod_mask()
|
||||
|
||||
if state == Gdk.ModifierType.CONTROL_MASK and event.button == 2:
|
||||
self.normal_size()
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
# ex:ts=4:et:
|
Loading…
Reference in New Issue
Block a user