/* SPDX-License-Identifier: LGPL-3.0-or-later */
/*
* Copyright (C) 2008 Banco do Brasil S.A.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 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 Lesser General Public License
* along with this program. If not, see .
*/
/**
* @brief Implements the V3270 Font Chooser widget.
*
* Reference:
*
*/
#include "../private.h"
#include
#include
#include
#include
#include
/*--[ Widget definition ]----------------------------------------------------------------------------*/
#define GTK_TYPE_V3270_FONT_CHOOSER (V3270FontChooserWidget_get_type ())
#define GTK_V3270_FONT_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_V3270_FONT_CHOOSER, V3270FontChooserWidget))
#define GTK_V3270_FONT_CHOOSER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_V3270_FONT_CHOOSER, V3270FontChooserWidgetClass))
#define GTK_IS_V3270_FONT_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_V3270_FONT_CHOOSER))
#define GTK_IS_V3270_FONT_CHOOSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_V3270_FONT_CHOOSER))
#define GTK_V3270_FONT_CHOOSER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_V3270_FONT_CHOOSER, V3270FontChooserWidgetClass))
typedef struct _V3270FontChooserWidget
{
V3270Settings parent;
GtkWidget * font_list;
GtkWidget * preview;
GtkToggleButton * bold;
GtkToggleButton * dynamic;
struct {
cairo_font_face_t * face;
cairo_font_weight_t weight;
} font;
struct {
gchar * family;
gboolean bold;
gboolean dynamic;
} saved;
} V3270FontChooserWidget;
typedef struct _V3270HostSelectWidgetClass
{
V3270SettingsClass parent_class;
} V3270FontChooserWidgetClass;
G_DEFINE_TYPE(V3270FontChooserWidget, V3270FontChooserWidget, GTK_TYPE_V3270_SETTINGS);
/*--[ Implement ]------------------------------------------------------------------------------------*/
static void cancel(GtkWidget *widget, GtkWidget *terminal)
{
debug("V3270FontChooserWidget::%s",__FUNCTION__);
V3270FontChooserWidget *chooser = GTK_V3270_FONT_CHOOSER(widget);
if(chooser->saved.family)
v3270_set_font_family(terminal,chooser->saved.family);
v3270_set_toggle(terminal,LIB3270_TOGGLE_BOLD,chooser->saved.bold);
v3270_set_dynamic_font_spacing(terminal,chooser->saved.dynamic);
}
static void load(GtkWidget *widget, GtkWidget *terminal)
{
V3270FontChooserWidget *chooser = GTK_V3270_FONT_CHOOSER(widget);
debug("V3270FontChooserWidget::%s",__FUNCTION__);
if(chooser->saved.family) {
g_free(chooser->saved.family);
}
chooser->saved.family = g_strdup(v3270_get_font_family(terminal));
chooser->saved.bold = v3270_get_toggle(terminal,LIB3270_TOGGLE_BOLD);
chooser->saved.dynamic = v3270_get_dynamic_font_spacing(terminal);
GtkTreeIter active;
gtk_tree_view_set_model(
GTK_TREE_VIEW(chooser->font_list),
v3270_font_family_model_new(
chooser->font_list,
chooser->saved.family,
&active
)
);
gtk_tree_selection_select_iter(
gtk_tree_view_get_selection(GTK_TREE_VIEW(chooser->font_list)),
&active
);
gtk_toggle_button_set_active(chooser->bold,chooser->saved.bold);
gtk_toggle_button_set_active(chooser->dynamic,chooser->saved.dynamic);
gtk_widget_queue_draw(chooser->preview);
}
static void dispose(GObject *object)
{
V3270FontChooserWidget * widget = GTK_V3270_FONT_CHOOSER(object);
if(widget->font.face) {
cairo_font_face_destroy(widget->font.face);
widget->font.face = NULL;
}
if(widget->saved.family) {
g_free(widget->saved.family);
widget->saved.family = NULL;
}
G_OBJECT_CLASS(V3270FontChooserWidget_parent_class)->dispose(object);
}
static void V3270FontChooserWidget_class_init(V3270FontChooserWidgetClass *klass)
{
V3270SettingsClass * widget = GTK_V3270_SETTINGS_CLASS(klass);
G_OBJECT_CLASS(klass)->dispose = dispose;
widget->revert = cancel;
widget->load = load;
}
static void set_font_family(V3270FontChooserWidget *widget, const gchar * font_family)
{
// Update font
if(widget->font.face) {
cairo_font_face_destroy(widget->font.face);
widget->font.face = NULL;
}
widget->font.face = cairo_toy_font_face_create(font_family, CAIRO_FONT_SLANT_NORMAL, widget->font.weight);
gtk_widget_queue_draw(widget->preview);
}
static void font_selected(GtkTreeSelection *selection, V3270FontChooserWidget *widget)
{
GValue value = { 0, };
GtkTreeModel * model;
GtkTreeIter iter;
if(!gtk_tree_selection_get_selected(selection,&model,&iter))
return;
gtk_tree_model_get_value(model,&iter,0,&value);
debug("Font-family: %s",g_value_get_string(&value));
// Update terminal widget
if(widget->parent.terminal)
v3270_set_font_family(widget->parent.terminal,g_value_get_string(&value));
set_font_family(widget,g_value_get_string(&value));
g_value_unset(&value);
}
static gboolean draw_preview(GtkWidget *widget, cairo_t *cr, V3270FontChooserWidget *chooser) {
GtkWidget * t = v3270_settings_get_terminal_widget(GTK_WIDGET(chooser));
if(!t)
return TRUE;
v3270 * terminal = GTK_V3270(t);
guint width = gtk_widget_get_allocated_width (widget);
guint height = gtk_widget_get_allocated_height (widget);
gdk_cairo_set_source_rgba(cr,terminal->color+V3270_COLOR_BACKGROUND);
cairo_rectangle(cr, 0, 0, width, height);
cairo_fill(cr);
cairo_stroke(cr);
if(chooser->font.face) {
// debug("%s",__FUNCTION__);
cairo_set_font_face(cr,chooser->font.face);
cairo_set_font_size(cr,15);
cairo_font_extents_t extents;
cairo_font_extents(cr,&extents);
double spacing = extents.height + extents.descent;
double row = spacing;
static const enum V3270_COLOR colors[] = {
V3270_COLOR_FIELD,
V3270_COLOR_FIELD_INTENSIFIED,
V3270_COLOR_FIELD_PROTECTED_INTENSIFIED
};
size_t ix;
for(ix = 0; ix < G_N_ELEMENTS(colors); ix++) {
cairo_move_to(cr,6,row);
gdk_cairo_set_source_rgba(cr,terminal->color+colors[ix]);
cairo_show_text(cr,pango_language_get_sample_string(NULL));
row += spacing;
}
}
cairo_stroke(cr);
return FALSE;
}
static void bold_toggled(GtkToggleButton *togglebutton, V3270FontChooserWidget *widget)
{
gboolean active = gtk_toggle_button_get_active(togglebutton);
widget->font.weight = (active ? CAIRO_FONT_WEIGHT_BOLD : CAIRO_FONT_WEIGHT_NORMAL);
v3270_set_toggle(widget->parent.terminal,LIB3270_TOGGLE_BOLD,active);
set_font_family(widget,v3270_get_font_family(widget->parent.terminal));
}
static void dynamic_spacing_toggled(GtkToggleButton *togglebutton, V3270FontChooserWidget *widget)
{
v3270_set_dynamic_font_spacing(widget->parent.terminal,gtk_toggle_button_get_active(togglebutton));
}
static void V3270FontChooserWidget_init(V3270FontChooserWidget *widget)
{
widget->font.weight = CAIRO_FONT_WEIGHT_NORMAL;
gtk_widget_set_size_request(GTK_WIDGET(widget),-1,136);
// Create font list view
{
widget->font_list = gtk_tree_view_new();
gtk_widget_set_tooltip_markup(widget->font_list,_("Available fonts"));
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(widget->font_list),FALSE);
gtk_tree_view_insert_column_with_attributes( GTK_TREE_VIEW(widget->font_list),
-1,
"text",gtk_cell_renderer_text_new(),"text",
0, NULL
);
// Setup selection mode.
GtkTreeSelection * select = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget->font_list));
gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
g_signal_connect(G_OBJECT(select),"changed",G_CALLBACK(font_selected),widget);
// Put the view inside a scrolled window.
GtkWidget * box = gtk_scrolled_window_new(NULL,NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(box),GTK_POLICY_NEVER,GTK_POLICY_ALWAYS);
gtk_container_add(GTK_CONTAINER(box),widget->font_list);
gtk_widget_set_vexpand(box,TRUE);
gtk_widget_set_hexpand(box,FALSE);
gtk_grid_attach(GTK_GRID(widget),box,0,0,1,5);
}
// Add preview widget
{
GtkWidget * frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type(GTK_FRAME (frame), GTK_SHADOW_IN);
gtk_widget_set_vexpand(frame,TRUE);
gtk_widget_set_hexpand(frame,TRUE);
widget->preview = gtk_drawing_area_new();
gtk_widget_set_margin_start(widget->preview,8);
gtk_widget_set_vexpand(widget->preview,TRUE);
gtk_widget_set_hexpand(widget->preview,TRUE);
gtk_widget_set_size_request(widget->preview,400,-1);
g_signal_connect(widget->preview, "draw", G_CALLBACK(draw_preview), widget);
gtk_container_add(GTK_CONTAINER (frame), widget->preview);
gtk_grid_attach(GTK_GRID(widget),frame,1,0,5,3);
}
// Add font-weight button
{
widget->bold = GTK_TOGGLE_BUTTON(gtk_check_button_new_with_label(_("Bold")));
gtk_grid_attach(GTK_GRID(widget),GTK_WIDGET(widget->bold),1,3,1,1);
g_signal_connect(G_OBJECT(widget->bold),"toggled",G_CALLBACK(bold_toggled),widget);
}
// Add dynamic font spacing button
{
widget->dynamic = GTK_TOGGLE_BUTTON(gtk_check_button_new_with_label(_("Dynamic font spacing")));
gtk_grid_attach(GTK_GRID(widget),GTK_WIDGET(widget->dynamic),2,3,1,1);
g_signal_connect(G_OBJECT(widget->dynamic),"toggled",G_CALLBACK(dynamic_spacing_toggled),widget);
}
gtk_widget_show_all(GTK_WIDGET(widget));
}
GtkWidget * v3270_font_settings_new()
{
V3270Settings * settings = GTK_V3270_SETTINGS(g_object_new(GTK_TYPE_V3270_FONT_CHOOSER, NULL));
settings->title = _("Terminal font");
settings->label = _("Font");
return GTK_WIDGET(settings);
}
GtkWidget * v3270_font_chooser_widget_new()
{
return v3270_font_settings_new();
}