1 /*
2  * e-editor-selection.c
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) version 3.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with the program; if not, see <http://www.gnu.org/licenses/>
16  *
17  */
18 
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22 
23 #include "biji-editor-selection.h"
24 
25 #include <string.h>
26 #include <stdlib.h>
27 #include <ctype.h>
28 
29 struct _EEditorSelectionPrivate {
30 	WebKitWebView *webview;
31         WebKitEditorTypingAttributes attrs;
32 };
33 
34 G_DEFINE_TYPE_WITH_PRIVATE (
35 	EEditorSelection,
36 	e_editor_selection,
37 	G_TYPE_OBJECT
38 );
39 
40 enum {
41 	PROP_0,
42 	PROP_WEBVIEW,
43 	PROP_BOLD,
44 	PROP_ITALIC,
45 	PROP_STRIKE_THROUGH,
46 };
47 
48 static void
check_and_update_typing_attr(EEditorSelection * selection,WebKitEditorTypingAttributes attrs,unsigned attr,const char * poperty_name)49 check_and_update_typing_attr (EEditorSelection *selection,
50                               WebKitEditorTypingAttributes attrs,
51                               unsigned attr,
52                               const char *poperty_name)
53 {
54         if (attrs & attr) {
55                 if (!(selection->priv->attrs & attr)) {
56                         selection->priv->attrs |= attr;
57                         g_object_notify (G_OBJECT (selection), poperty_name);
58                 }
59         } else if (!(attrs & attr)) {
60                 if (selection->priv->attrs & attr) {
61                         selection->priv->attrs &= ~attr;
62                         g_object_notify (G_OBJECT (selection), poperty_name);
63                 }
64         }
65 }
66 
67 static void
webview_typing_attributes_changed(WebKitEditorState * editor,GParamSpec * spec,EEditorSelection * selection)68 webview_typing_attributes_changed (WebKitEditorState *editor,
69                                    GParamSpec *spec,
70                                    EEditorSelection *selection)
71 {
72         WebKitEditorTypingAttributes attrs;
73 
74         attrs = webkit_editor_state_get_typing_attributes (editor);
75 
76         g_object_freeze_notify (G_OBJECT (selection));
77         check_and_update_typing_attr (selection, attrs, WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD, "bold");
78         check_and_update_typing_attr (selection, attrs, WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC, "italic");
79         check_and_update_typing_attr (selection, attrs, WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH, "strike-through");
80         g_object_thaw_notify (G_OBJECT (selection));
81 }
82 
83 static void
editor_selection_set_webview(EEditorSelection * selection,WebKitWebView * webview)84 editor_selection_set_webview (EEditorSelection *selection,
85 			      WebKitWebView *webview)
86 {
87         WebKitEditorState *editor;
88 
89         g_clear_object (&selection->priv->webview);
90 	selection->priv->webview = g_object_ref (webview);
91 
92         editor = webkit_web_view_get_editor_state (webview);
93         selection->priv->attrs = webkit_editor_state_get_typing_attributes (editor);
94         g_signal_connect (
95                 editor, "notify::typing-attributes",
96                 G_CALLBACK (webview_typing_attributes_changed), selection);
97 }
98 
99 
100 static void
e_editor_selection_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)101 e_editor_selection_get_property (GObject *object,
102 				 guint property_id,
103 				 GValue *value,
104 				 GParamSpec *pspec)
105 {
106 	EEditorSelection *selection = E_EDITOR_SELECTION (object);
107 
108 	switch (property_id) {
109 		case PROP_BOLD:
110 			g_value_set_boolean (value,
111 				e_editor_selection_get_bold (selection));
112 			break;
113 
114 		case PROP_ITALIC:
115 			g_value_set_boolean (value,
116 				e_editor_selection_get_italic (selection));
117 			break;
118 
119 		case PROP_STRIKE_THROUGH:
120 			g_value_set_boolean (value,
121 				e_editor_selection_get_strike_through (selection));
122 			break;
123 
124 		default:
125 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
126 			break;
127 	}
128 }
129 
130 static void
e_editor_selection_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)131 e_editor_selection_set_property (GObject *object,
132 				 guint property_id,
133 				 const GValue *value,
134 				 GParamSpec *pspec)
135 {
136 	EEditorSelection *selection = E_EDITOR_SELECTION (object);
137 
138 	switch (property_id) {
139 		case PROP_WEBVIEW:
140 			editor_selection_set_webview (
141 				selection, g_value_get_object (value));
142 			break;
143 
144 		case PROP_BOLD:
145 			e_editor_selection_set_bold (
146 				selection, g_value_get_boolean (value));
147 			break;
148 
149 		case PROP_ITALIC:
150 			e_editor_selection_set_italic (
151 				selection, g_value_get_boolean (value));
152 			break;
153 
154 		case PROP_STRIKE_THROUGH:
155 			e_editor_selection_set_strike_through (
156 				selection, g_value_get_boolean (value));
157 			break;
158 
159 		default:
160 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
161 	}
162 }
163 
164 static void
e_editor_selection_finalize(GObject * object)165 e_editor_selection_finalize (GObject *object)
166 {
167 	EEditorSelection *selection = E_EDITOR_SELECTION (object);
168 
169         g_object_unref (selection->priv->webview);
170 
171         G_OBJECT_CLASS (e_editor_selection_parent_class)->finalize (object);
172 }
173 
174 static void
e_editor_selection_class_init(EEditorSelectionClass * klass)175 e_editor_selection_class_init (EEditorSelectionClass *klass)
176 {
177 	GObjectClass *object_class;
178 
179 	object_class = G_OBJECT_CLASS (klass);
180 	object_class->get_property = e_editor_selection_get_property;
181 	object_class->set_property = e_editor_selection_set_property;
182 	object_class->finalize = e_editor_selection_finalize;
183 
184 	g_object_class_install_property (
185 		object_class,
186 		PROP_WEBVIEW,
187 		g_param_spec_object (
188 			"webview",
189 			NULL,
190 			NULL,
191 		        WEBKIT_TYPE_WEB_VIEW,
192 		        G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
193 
194 	g_object_class_install_property (
195 		object_class,
196 		PROP_BOLD,
197 		g_param_spec_boolean (
198 			"bold",
199 			NULL,
200 			NULL,
201 			FALSE,
202 			G_PARAM_READWRITE));
203 
204 	g_object_class_install_property (
205 		object_class,
206 		PROP_ITALIC,
207 		g_param_spec_boolean (
208 			"italic",
209 			NULL,
210 			NULL,
211 			FALSE,
212 			G_PARAM_READWRITE));
213 
214 	g_object_class_install_property (
215 		object_class,
216 		PROP_STRIKE_THROUGH,
217 		g_param_spec_boolean (
218 			"strike-through",
219 			NULL,
220 			NULL,
221 			FALSE,
222 			G_PARAM_READWRITE));
223 }
224 
225 
226 static void
e_editor_selection_init(EEditorSelection * selection)227 e_editor_selection_init (EEditorSelection *selection)
228 {
229 	selection->priv = e_editor_selection_get_instance_private (selection);
230 }
231 
232 EEditorSelection *
e_editor_selection_new(WebKitWebView * parent_view)233 e_editor_selection_new (WebKitWebView *parent_view)
234 {
235 	g_return_val_if_fail (WEBKIT_IS_WEB_VIEW (parent_view), NULL);
236 
237 	return g_object_new (
238 			E_TYPE_EDITOR_SELECTION,
239 			"webview", parent_view, NULL);
240 }
241 
242 gboolean
e_editor_selection_get_bold(EEditorSelection * selection)243 e_editor_selection_get_bold (EEditorSelection *selection)
244 {
245 	g_return_val_if_fail (E_IS_EDITOR_SELECTION (selection), FALSE);
246 
247 	return selection->priv->attrs & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD;
248 }
249 
250 void
e_editor_selection_set_bold(EEditorSelection * selection,gboolean bold)251 e_editor_selection_set_bold (EEditorSelection *selection,
252 			     gboolean bold)
253 {
254 	g_return_if_fail (E_IS_EDITOR_SELECTION (selection));
255 
256 	if ((e_editor_selection_get_bold (selection) ? TRUE : FALSE)
257 				== (bold ? TRUE : FALSE)) {
258 		return;
259 	}
260 
261         webkit_web_view_execute_editing_command (selection->priv->webview, "Bold");
262 }
263 
264 gboolean
e_editor_selection_get_italic(EEditorSelection * selection)265 e_editor_selection_get_italic (EEditorSelection *selection)
266 {
267 	g_return_val_if_fail (E_IS_EDITOR_SELECTION (selection), FALSE);
268 
269 	return selection->priv->attrs & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC;
270 }
271 
272 void
e_editor_selection_set_italic(EEditorSelection * selection,gboolean italic)273 e_editor_selection_set_italic (EEditorSelection *selection,
274 			       gboolean italic)
275 {
276 	g_return_if_fail (E_IS_EDITOR_SELECTION (selection));
277 
278 	if ((e_editor_selection_get_italic (selection) ? TRUE : FALSE)
279 				== (italic ? TRUE : FALSE)) {
280 		return;
281 	}
282 
283         webkit_web_view_execute_editing_command (selection->priv->webview, "Italic");
284 }
285 
286 gboolean
e_editor_selection_get_strike_through(EEditorSelection * selection)287 e_editor_selection_get_strike_through (EEditorSelection *selection)
288 {
289 	g_return_val_if_fail (E_IS_EDITOR_SELECTION (selection), FALSE);
290 
291 	return selection->priv->attrs & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH;
292 }
293 
294 void
e_editor_selection_set_strike_through(EEditorSelection * selection,gboolean strike_through)295 e_editor_selection_set_strike_through (EEditorSelection *selection,
296 				       gboolean strike_through)
297 {
298 	g_return_if_fail (E_IS_EDITOR_SELECTION (selection));
299 
300 	if ((e_editor_selection_get_strike_through (selection) ? TRUE : FALSE)
301 				== (strike_through? TRUE : FALSE)) {
302 		return;
303 	}
304 
305         webkit_web_view_execute_editing_command (selection->priv->webview, "Strikethrough");
306 }
307