375 lines
9.6 KiB
C
375 lines
9.6 KiB
C
/* SPDX-FileCopyrightText: 2024 - Sébastien Wilmet
|
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
*/
|
|
|
|
#include "gedit-text-size-view-activatable.h"
|
|
#include <gedit/gedit-view-activatable.h>
|
|
|
|
struct _GeditTextSizeViewActivatablePrivate
|
|
{
|
|
GeditView *view;
|
|
PangoFontDescription *default_font;
|
|
|
|
/* For Ctrl+scroll event with smooth direction. */
|
|
gdouble cur_delta_y;
|
|
};
|
|
|
|
enum
|
|
{
|
|
PROP_0,
|
|
PROP_VIEW
|
|
};
|
|
|
|
#define GEDIT_VIEW_KEY "GeditTextSizeViewActivatable-key"
|
|
|
|
static void gedit_view_activatable_iface_init (GeditViewActivatableInterface *iface);
|
|
|
|
G_DEFINE_DYNAMIC_TYPE_EXTENDED (GeditTextSizeViewActivatable,
|
|
gedit_text_size_view_activatable,
|
|
G_TYPE_OBJECT,
|
|
0,
|
|
G_ADD_PRIVATE_DYNAMIC (GeditTextSizeViewActivatable)
|
|
G_IMPLEMENT_INTERFACE_DYNAMIC (GEDIT_TYPE_VIEW_ACTIVATABLE,
|
|
gedit_view_activatable_iface_init))
|
|
|
|
/* Returns: (transfer full) (nullable) */
|
|
static PangoFontDescription *
|
|
get_current_font (GeditTextSizeViewActivatable *self)
|
|
{
|
|
GtkStyleContext *style_context;
|
|
PangoFontDescription *font = NULL;
|
|
|
|
if (self->priv->view == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
style_context = gtk_widget_get_style_context (GTK_WIDGET (self->priv->view));
|
|
|
|
gtk_style_context_get (style_context,
|
|
gtk_style_context_get_state (style_context),
|
|
GTK_STYLE_PROPERTY_FONT, &font,
|
|
NULL);
|
|
|
|
return font;
|
|
}
|
|
|
|
static void
|
|
set_font (GeditTextSizeViewActivatable *self,
|
|
const PangoFontDescription *font)
|
|
{
|
|
if (self->priv->view != NULL)
|
|
{
|
|
tepl_utils_override_font_description (GTK_WIDGET (self->priv->view), font);
|
|
}
|
|
}
|
|
|
|
static void
|
|
change_font_size (GeditTextSizeViewActivatable *self,
|
|
gint amount)
|
|
{
|
|
PangoFontDescription *font;
|
|
gint size;
|
|
gint new_size;
|
|
|
|
font = get_current_font (self);
|
|
if (font == NULL)
|
|
{
|
|
g_warning ("textsize plugin: failed to get the current font.");
|
|
return;
|
|
}
|
|
|
|
size = pango_font_description_get_size (font);
|
|
new_size = size + amount * PANGO_SCALE;
|
|
if (new_size < PANGO_SCALE)
|
|
{
|
|
new_size = PANGO_SCALE;
|
|
}
|
|
|
|
if (pango_font_description_get_size_is_absolute (font))
|
|
{
|
|
pango_font_description_set_absolute_size (font, new_size);
|
|
}
|
|
else
|
|
{
|
|
pango_font_description_set_size (font, new_size);
|
|
}
|
|
|
|
set_font (self, font);
|
|
|
|
pango_font_description_free (font);
|
|
}
|
|
|
|
static void
|
|
default_font_changed_cb (TeplSettings *settings,
|
|
GeditTextSizeViewActivatable *self)
|
|
{
|
|
g_clear_pointer (&self->priv->default_font, pango_font_description_free);
|
|
self->priv->default_font = get_current_font (self);
|
|
}
|
|
|
|
static gboolean
|
|
scroll_event_cb (GeditView *view,
|
|
GdkEventScroll *event,
|
|
GeditTextSizeViewActivatable *self)
|
|
{
|
|
guint state;
|
|
|
|
state = event->state & gtk_accelerator_get_default_mod_mask ();
|
|
|
|
if (state != GDK_CONTROL_MASK)
|
|
{
|
|
return GDK_EVENT_PROPAGATE;
|
|
}
|
|
|
|
if (event->direction == GDK_SCROLL_UP)
|
|
{
|
|
gedit_text_size_view_activatable_make_larger (self);
|
|
return GDK_EVENT_STOP;
|
|
}
|
|
else if (event->direction == GDK_SCROLL_DOWN)
|
|
{
|
|
gedit_text_size_view_activatable_make_smaller (self);
|
|
return GDK_EVENT_STOP;
|
|
}
|
|
else if (event->direction == GDK_SCROLL_SMOOTH)
|
|
{
|
|
gint discrete_steps;
|
|
|
|
self->priv->cur_delta_y += event->delta_y;
|
|
|
|
/* A cast from double to int does the same as the trunc() function. */
|
|
discrete_steps = (gint) self->priv->cur_delta_y;
|
|
|
|
self->priv->cur_delta_y -= discrete_steps;
|
|
|
|
if (discrete_steps != 0)
|
|
{
|
|
/* Note the minus sign. */
|
|
change_font_size (self, -discrete_steps);
|
|
}
|
|
|
|
return GDK_EVENT_STOP;
|
|
}
|
|
|
|
return GDK_EVENT_PROPAGATE;
|
|
}
|
|
|
|
static gboolean
|
|
button_press_event_cb (GeditView *view,
|
|
GdkEventButton *event,
|
|
GeditTextSizeViewActivatable *self)
|
|
{
|
|
guint state;
|
|
|
|
state = event->state & gtk_accelerator_get_default_mod_mask ();
|
|
|
|
if (state == GDK_CONTROL_MASK &&
|
|
event->button == 2)
|
|
{
|
|
gedit_text_size_view_activatable_reset_to_normal_size (self);
|
|
return GDK_EVENT_STOP;
|
|
}
|
|
|
|
return GDK_EVENT_PROPAGATE;
|
|
}
|
|
|
|
static void
|
|
gedit_text_size_view_activatable_get_property (GObject *object,
|
|
guint prop_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GeditTextSizeViewActivatable *activatable = GEDIT_TEXT_SIZE_VIEW_ACTIVATABLE (object);
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_VIEW:
|
|
g_value_set_object (value, activatable->priv->view);
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gedit_text_size_view_activatable_set_property (GObject *object,
|
|
guint prop_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GeditTextSizeViewActivatable *activatable = GEDIT_TEXT_SIZE_VIEW_ACTIVATABLE (object);
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_VIEW:
|
|
g_assert (activatable->priv->view == NULL);
|
|
activatable->priv->view = GEDIT_VIEW (g_value_dup_object (value));
|
|
|
|
g_object_set_data (G_OBJECT (activatable->priv->view),
|
|
GEDIT_VIEW_KEY,
|
|
activatable);
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gedit_text_size_view_activatable_dispose (GObject *object)
|
|
{
|
|
GeditTextSizeViewActivatable *activatable = GEDIT_TEXT_SIZE_VIEW_ACTIVATABLE (object);
|
|
|
|
if (activatable->priv->view != NULL)
|
|
{
|
|
g_object_set_data (G_OBJECT (activatable->priv->view),
|
|
GEDIT_VIEW_KEY,
|
|
NULL);
|
|
}
|
|
|
|
g_clear_object (&activatable->priv->view);
|
|
|
|
G_OBJECT_CLASS (gedit_text_size_view_activatable_parent_class)->dispose (object);
|
|
}
|
|
|
|
static void
|
|
gedit_text_size_view_activatable_finalize (GObject *object)
|
|
{
|
|
GeditTextSizeViewActivatable *activatable = GEDIT_TEXT_SIZE_VIEW_ACTIVATABLE (object);
|
|
|
|
g_clear_pointer (&activatable->priv->default_font, pango_font_description_free);
|
|
|
|
G_OBJECT_CLASS (gedit_text_size_view_activatable_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
gedit_text_size_view_activatable_class_init (GeditTextSizeViewActivatableClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
object_class->get_property = gedit_text_size_view_activatable_get_property;
|
|
object_class->set_property = gedit_text_size_view_activatable_set_property;
|
|
object_class->dispose = gedit_text_size_view_activatable_dispose;
|
|
object_class->finalize = gedit_text_size_view_activatable_finalize;
|
|
|
|
g_object_class_override_property (object_class, PROP_VIEW, "view");
|
|
}
|
|
|
|
static void
|
|
gedit_text_size_view_activatable_class_finalize (GeditTextSizeViewActivatableClass *klass)
|
|
{
|
|
}
|
|
|
|
static void
|
|
gedit_text_size_view_activatable_init (GeditTextSizeViewActivatable *activatable)
|
|
{
|
|
activatable->priv = gedit_text_size_view_activatable_get_instance_private (activatable);
|
|
|
|
activatable->priv->cur_delta_y = 0.0;
|
|
}
|
|
|
|
static void
|
|
gedit_text_size_view_activatable_activate (GeditViewActivatable *activatable)
|
|
{
|
|
GeditTextSizeViewActivatable *self = GEDIT_TEXT_SIZE_VIEW_ACTIVATABLE (activatable);
|
|
TeplSettings *settings;
|
|
|
|
g_clear_pointer (&self->priv->default_font, pango_font_description_free);
|
|
self->priv->default_font = get_current_font (self);
|
|
|
|
/* When the "font-changed" signal is emitted, it means that the user has
|
|
* explicitly changed the font setting, and as such he or she probably
|
|
* wants to use that font instead. So the expected behavior in that case
|
|
* is to reset the zoom level.
|
|
*
|
|
* Connect with the 'after' flag, to ensure to get the new font in the
|
|
* same manner (with get_current_font()).
|
|
*/
|
|
settings = tepl_settings_get_singleton ();
|
|
g_signal_connect_after (settings,
|
|
"font-changed",
|
|
G_CALLBACK (default_font_changed_cb),
|
|
self);
|
|
|
|
g_signal_connect (self->priv->view,
|
|
"scroll-event",
|
|
G_CALLBACK (scroll_event_cb),
|
|
self);
|
|
|
|
g_signal_connect (self->priv->view,
|
|
"button-press-event",
|
|
G_CALLBACK (button_press_event_cb),
|
|
self);
|
|
}
|
|
|
|
static void
|
|
gedit_text_size_view_activatable_deactivate (GeditViewActivatable *activatable)
|
|
{
|
|
GeditTextSizeViewActivatable *self = GEDIT_TEXT_SIZE_VIEW_ACTIVATABLE (activatable);
|
|
TeplSettings *settings;
|
|
|
|
settings = tepl_settings_get_singleton ();
|
|
g_signal_handlers_disconnect_by_func (settings, default_font_changed_cb, self);
|
|
|
|
g_signal_handlers_disconnect_by_func (self->priv->view, scroll_event_cb, self);
|
|
g_signal_handlers_disconnect_by_func (self->priv->view, button_press_event_cb, self);
|
|
|
|
gedit_text_size_view_activatable_reset_to_normal_size (self);
|
|
g_clear_pointer (&self->priv->default_font, pango_font_description_free);
|
|
}
|
|
|
|
static void
|
|
gedit_view_activatable_iface_init (GeditViewActivatableInterface *iface)
|
|
{
|
|
iface->activate = gedit_text_size_view_activatable_activate;
|
|
iface->deactivate = gedit_text_size_view_activatable_deactivate;
|
|
}
|
|
|
|
void
|
|
gedit_text_size_view_activatable_register (PeasObjectModule *module)
|
|
{
|
|
gedit_text_size_view_activatable_register_type (G_TYPE_MODULE (module));
|
|
|
|
peas_object_module_register_extension_type (module,
|
|
GEDIT_TYPE_VIEW_ACTIVATABLE,
|
|
GEDIT_TYPE_TEXT_SIZE_VIEW_ACTIVATABLE);
|
|
}
|
|
|
|
GeditTextSizeViewActivatable *
|
|
gedit_text_size_view_activatable_get_from_view (GeditView *view)
|
|
{
|
|
g_return_val_if_fail (GEDIT_IS_VIEW (view), NULL);
|
|
|
|
return g_object_get_data (G_OBJECT (view), GEDIT_VIEW_KEY);
|
|
}
|
|
|
|
void
|
|
gedit_text_size_view_activatable_make_larger (GeditTextSizeViewActivatable *self)
|
|
{
|
|
g_return_if_fail (GEDIT_IS_TEXT_SIZE_VIEW_ACTIVATABLE (self));
|
|
|
|
change_font_size (self, 1);
|
|
}
|
|
|
|
void
|
|
gedit_text_size_view_activatable_make_smaller (GeditTextSizeViewActivatable *self)
|
|
{
|
|
g_return_if_fail (GEDIT_IS_TEXT_SIZE_VIEW_ACTIVATABLE (self));
|
|
|
|
change_font_size (self, -1);
|
|
}
|
|
|
|
void
|
|
gedit_text_size_view_activatable_reset_to_normal_size (GeditTextSizeViewActivatable *self)
|
|
{
|
|
g_return_if_fail (GEDIT_IS_TEXT_SIZE_VIEW_ACTIVATABLE (self));
|
|
|
|
if (self->priv->default_font != NULL)
|
|
{
|
|
set_font (self, self->priv->default_font);
|
|
}
|
|
}
|