GnuCash c935c2f+
Loading...
Searching...
No Matches
gnc-cell-renderer-text-view.c
1/*************************************************************************
2 * The following code implements a text view in a custom GtkCellRenderer.
3 *
4 * Copyright (C) 2020 Robert Fewell
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 *************************************************************************/
21#include <config.h>
22
23#include <gtk/gtk.h>
24#include <glib/gi18n.h>
25#include <gdk/gdkkeysyms.h>
26
27#include "gnc-cell-renderer-text-view.h"
28#include "gnc-cell-view.h"
29
30static GtkCellEditable *gcrtv_start_editing (GtkCellRenderer *cell,
31 GdkEvent *event,
32 GtkWidget *widget,
33 const gchar *path,
34 const GdkRectangle *background_area,
35 const GdkRectangle *cell_area,
36 GtkCellRendererState flags);
37
38#define GNC_CELL_RENDERER_TEXT_VIEW_PATH "gnc-cell-renderer-text-view-path"
39
41{
42 GtkCellRendererText parent;
43
44 /* The editable entry. */
45 GtkWidget *editable;
46};
47
48G_DEFINE_TYPE (GncCellRendererTextView, gnc_cell_renderer_text_view, GTK_TYPE_CELL_RENDERER_TEXT)
49
50static void
51gnc_cell_renderer_text_view_init (GncCellRendererTextView *self)
52{
53}
54
55static void
56gnc_cell_renderer_text_view_finalize (GObject *object)
57{
58 G_OBJECT_CLASS (gnc_cell_renderer_text_view_parent_class)->finalize (object);
59}
60
61static void
62gnc_cell_renderer_text_view_class_init (GncCellRendererTextViewClass *klass)
63{
64 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
65 GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS(klass);
66
67 gobject_class->finalize = gnc_cell_renderer_text_view_finalize;
68
69 cell_class->start_editing = gcrtv_start_editing;
70}
71
72static void
73gcrtv_editing_done (GtkCellEditable *editable,
74 GncCellRendererTextView *cell_tv)
75{
76 gchar *path;
77 gchar *new_text;
78
79 if (GNC_CELL_VIEW(editable)->focus_out_id > 0)
80 {
81 g_signal_handler_disconnect (GNC_CELL_VIEW(editable)->text_view,
82 GNC_CELL_VIEW(editable)->focus_out_id);
83 GNC_CELL_VIEW(editable)->focus_out_id = 0;
84 }
85
86 if (GNC_CELL_VIEW(editable)->populate_popup_id > 0)
87 {
88 g_signal_handler_disconnect (GNC_CELL_VIEW(editable)->text_view,
89 GNC_CELL_VIEW(editable)->populate_popup_id);
90 GNC_CELL_VIEW(editable)->populate_popup_id = 0;
91 }
92
93 if (GNC_CELL_VIEW(editable)->editing_canceled)
94 {
95 gtk_cell_renderer_stop_editing (GTK_CELL_RENDERER(cell_tv), TRUE);
96 return;
97 }
98
99 path = g_object_get_data (G_OBJECT(editable),
100 GNC_CELL_RENDERER_TEXT_VIEW_PATH);
101
102 new_text = gnc_cell_view_get_text (GNC_CELL_VIEW(editable));
103
104 gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE(editable));
105
106 g_signal_emit_by_name (cell_tv, "edited", path, new_text);
107
108 g_free (new_text);
109}
110
111static gboolean
112gcrtv_button_press_event (GtkWidget *widget,
113 GdkEventButton *event,
114 gpointer user_data)
115{
116 // allows mouse clicks in text view
117 return TRUE;
118}
119
120static GtkCellEditable *
121gcrtv_start_editing (GtkCellRenderer *cell,
122 GdkEvent *event,
123 GtkWidget *widget,
124 const gchar *path,
125 const GdkRectangle *background_area,
126 const GdkRectangle *cell_area,
127 GtkCellRendererState flags)
128{
129 GncCellRendererTextView *cell_tv = GNC_CELL_RENDERER_TEXT_VIEW(cell);
130 GtkWidget *editable;
131 gchar *text = NULL;
132 gboolean iseditable;
133
134 g_object_get (G_OBJECT(cell_tv), "editable", &iseditable, NULL);
135
136 /* If the cell isn't editable we return NULL. */
137 if (iseditable == FALSE)
138 return NULL;
139
140 editable = g_object_new (GNC_TYPE_CELL_VIEW, NULL);
141
142 g_signal_connect (editable, "button-press-event",
143 G_CALLBACK(gcrtv_button_press_event),
144 NULL);
145
146 g_object_get (G_OBJECT(cell), "text", &text, NULL);
147
148 gnc_cell_view_set_text (GNC_CELL_VIEW(editable), text);
149
150 g_free (text);
151
152 gtk_widget_grab_focus (GTK_WIDGET(editable));
153
154 g_object_set_data_full (G_OBJECT(editable),
155 GNC_CELL_RENDERER_TEXT_VIEW_PATH,
156 g_strdup (path),
157 g_free);
158
159 gtk_widget_show (editable);
160
161 g_signal_connect (editable, "editing-done", G_CALLBACK(gcrtv_editing_done), cell_tv);
162
163 cell_tv->editable = editable;
164
165 g_object_add_weak_pointer (G_OBJECT(cell_tv->editable),
166 (gpointer) &cell_tv->editable);
167
168 return GTK_CELL_EDITABLE(editable);
169}
170
171GtkCellRenderer *
172gnc_cell_renderer_text_view_new (void)
173{
174 return g_object_new (GNC_TYPE_CELL_RENDERER_TEXT_VIEW, NULL);
175}