1
0
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:
Sébastien Wilmet 2024-06-27 05:10:23 +02:00
parent 3c7c7c6826
commit 91043c4a6a
6 changed files with 431 additions and 0 deletions

View File

@ -25,6 +25,7 @@ subdir('quickopen')
subdir('snippets')
subdir('sort')
subdir('spell')
subdir('textsize')
subdir('time')
if get_option('buggy_plugins')

View 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',
)

View 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/

View 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:

View 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:

View 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: