1 /* GTK - The GIMP Toolkit
2 * Copyright © 2013 Carlos Garnacho <carlosg@gnome.org>
4 * This library 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) any later version.
9 * This library 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.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
19 * SECTION:gtkselectionwindow
20 * @Short_description: Bubble window for content edition
21 * @Title: GtkSelectionWindow
23 * GtkSelection widget is a small helper object to implement
24 * touch-friendly content edition. #GtkEntry and #GtkTextView
25 * use this internally to allow text selection edition and
30 #include "gtkselectionwindowprivate.h"
31 #include "gtkactiongroup.h"
32 #include "gtkuimanager.h"
33 #include "gtkclipboard.h"
34 #include "gtktoolbar.h"
35 #include "gtkprivate.h"
41 " <toolitem name='cut' action='Cut' />" \
42 " <toolitem name='copy' action='Copy' />" \
43 " <toolitem name='paste' action='Paste' />" \
48 static void _action_cut_cb (GtkAction *action,
49 GtkSelectionWindow *window);
50 static void _action_copy_cb (GtkAction *action,
51 GtkSelectionWindow *window);
52 static void _action_paste_cb (GtkAction *action,
53 GtkSelectionWindow *window);
55 static GtkActionEntry entries[] = {
56 { "Cut", GTK_STOCK_CUT, NULL, NULL, NULL, G_CALLBACK (_action_cut_cb) },
57 { "Copy", GTK_STOCK_COPY, NULL, NULL, NULL, G_CALLBACK (_action_copy_cb) },
58 { "Paste", GTK_STOCK_PASTE, NULL, NULL, NULL, G_CALLBACK (_action_paste_cb) }
73 static guint signals[N_SIGNALS] = { 0 };
75 struct _GtkSelectionWindowPrivate
77 GtkUIManager *ui_manager;
80 guint has_selection : 1;
83 G_DEFINE_TYPE (GtkSelectionWindow, gtk_selection_window, GTK_TYPE_BUBBLE_WINDOW)
86 _action_cut_cb (GtkAction *action,
87 GtkSelectionWindow *window)
89 g_signal_emit (window, signals[CUT], 0);
93 _action_copy_cb (GtkAction *action,
94 GtkSelectionWindow *window)
96 g_signal_emit (window, signals[COPY], 0);
100 _action_paste_cb (GtkAction *action,
101 GtkSelectionWindow *window)
103 g_signal_emit (window, signals[PASTE], 0);
107 _gtk_selection_window_update_state (GtkSelectionWindow *window)
109 GtkSelectionWindowPrivate *priv;
110 GtkClipboard *clipboard;
111 gboolean text_available;
114 priv = window->_priv;
115 clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window),
116 GDK_SELECTION_CLIPBOARD);
117 text_available = gtk_clipboard_wait_is_text_available (clipboard);
119 action = gtk_ui_manager_get_action (priv->ui_manager, "/toolbar/cut");
120 gtk_action_set_sensitive (action, priv->editable && priv->has_selection);
122 action = gtk_ui_manager_get_action (priv->ui_manager, "/toolbar/copy");
123 gtk_action_set_sensitive (action, priv->has_selection);
125 action = gtk_ui_manager_get_action (priv->ui_manager, "/toolbar/paste");
126 gtk_action_set_sensitive (action, text_available && priv->editable);
130 gtk_selection_window_map (GtkWidget *widget)
132 _gtk_selection_window_update_state (GTK_SELECTION_WINDOW (widget));
133 GTK_WIDGET_CLASS (gtk_selection_window_parent_class)->map (widget);
137 gtk_selection_window_finalize (GObject *object)
139 GtkSelectionWindowPrivate *priv;
141 priv = GTK_SELECTION_WINDOW (object)->_priv;
142 g_object_unref (priv->ui_manager);
144 G_OBJECT_CLASS (gtk_selection_window_parent_class)->finalize (object);
148 gtk_selection_window_set_property (GObject *object,
156 gtk_selection_window_set_editable (GTK_SELECTION_WINDOW (object),
157 g_value_get_boolean (value));
159 case PROP_HAS_SELECTION:
160 gtk_selection_window_set_has_selection (GTK_SELECTION_WINDOW (object),
161 g_value_get_boolean (value));
164 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
170 gtk_selection_window_get_property (GObject *object,
175 GtkSelectionWindowPrivate *priv;
177 priv = GTK_SELECTION_WINDOW (object)->_priv;
182 g_value_set_boolean (value, priv->editable);
184 case PROP_HAS_SELECTION:
185 g_value_set_boolean (value, priv->has_selection);
188 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
194 gtk_selection_window_class_init (GtkSelectionWindowClass *klass)
196 GObjectClass *object_class = G_OBJECT_CLASS (klass);
197 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
199 object_class->finalize = gtk_selection_window_finalize;
200 object_class->set_property = gtk_selection_window_set_property;
201 object_class->get_property = gtk_selection_window_get_property;
203 widget_class->map = gtk_selection_window_map;
205 g_object_class_install_property (object_class,
207 g_param_spec_boolean ("editable",
209 P_("Whether content is editable"),
211 GTK_PARAM_READWRITE |
213 g_object_class_install_property (object_class,
215 g_param_spec_boolean ("has-selection",
217 P_("Whether there is any content currently selected"),
219 GTK_PARAM_READWRITE |
222 g_signal_new (I_("cut"),
223 G_OBJECT_CLASS_TYPE (object_class),
224 G_SIGNAL_RUN_LAST, 0,
226 g_cclosure_marshal_VOID__VOID,
229 g_signal_new (I_("copy"),
230 G_OBJECT_CLASS_TYPE (object_class),
231 G_SIGNAL_RUN_LAST, 0,
233 g_cclosure_marshal_VOID__VOID,
236 g_signal_new (I_("paste"),
237 G_OBJECT_CLASS_TYPE (object_class),
238 G_SIGNAL_RUN_LAST, 0,
240 g_cclosure_marshal_VOID__VOID,
243 g_type_class_add_private (klass, sizeof (GtkSelectionWindowPrivate));
247 gtk_selection_window_init (GtkSelectionWindow *window)
249 GtkSelectionWindowPrivate *priv;
250 GtkActionGroup *group;
252 window->_priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
253 GTK_TYPE_SELECTION_WINDOW,
254 GtkSelectionWindowPrivate);
256 group = gtk_action_group_new ("SelectionToolbar");
257 gtk_action_group_add_actions (group, entries, G_N_ELEMENTS (entries), window);
259 priv->ui_manager = gtk_ui_manager_new ();
260 gtk_ui_manager_insert_action_group (priv->ui_manager, group, 0);
261 gtk_ui_manager_add_ui_from_string (priv->ui_manager, TOOLBAR_UI, -1, NULL);
263 priv->toolbar = gtk_ui_manager_get_widget (priv->ui_manager, "/toolbar");
264 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (priv->toolbar), FALSE);
265 gtk_widget_show_all (priv->toolbar);
267 gtk_container_add (GTK_CONTAINER (window), priv->toolbar);
271 * gtk_selection_window_new:
273 * Creates a new #GtkSelectionWindow
275 * Returns: a newly created #GtkSelectionWindow
278 gtk_selection_window_new (void)
280 return g_object_new (GTK_TYPE_SELECTION_WINDOW, NULL);
284 * gtk_selection_window_set_editable:
285 * @window: a #GtkSelectionWindow
286 * @editable: whether the current selection is editable
288 * Sets whether the current selection is editable. Toolbar options'
289 * sensitivity will change according to this.
294 gtk_selection_window_set_editable (GtkSelectionWindow *window,
297 GtkSelectionWindowPrivate *priv;
298 gboolean need_update;
300 g_return_if_fail (GTK_IS_SELECTION_WINDOW (window));
302 priv = window->_priv;
303 need_update = priv->editable != editable &&
304 gtk_widget_get_visible (GTK_WIDGET (window));
305 priv->editable = editable;
308 _gtk_selection_window_update_state (window);
310 g_object_notify (G_OBJECT (window), "editable");
314 * gtk_selection_window_get_editable:
315 * @window: a #GtkSelectionWindow
317 * Returns whether the contents are editable according to @window
319 * Returns: whether the contents are editable
324 gtk_selection_window_get_editable (GtkSelectionWindow *window)
326 GtkSelectionWindowPrivate *priv;
328 g_return_val_if_fail (GTK_IS_SELECTION_WINDOW (window), FALSE);
330 priv = window->_priv;
332 return priv->editable;
336 * gtk_selection_window_set_has_selection:
337 * @window: a #GtkSelectionWindow
338 * @has_selection: whether there is currently a selection
340 * Sets whether there is any selected content. Toolbar options'
341 * sensitivity will change according to this.
346 gtk_selection_window_set_has_selection (GtkSelectionWindow *window,
347 gboolean has_selection)
349 GtkSelectionWindowPrivate *priv;
350 gboolean need_update;
352 g_return_if_fail (GTK_IS_SELECTION_WINDOW (window));
354 priv = window->_priv;
355 need_update = priv->has_selection != has_selection &&
356 gtk_widget_get_visible (GTK_WIDGET (window));
357 priv->has_selection = has_selection;
360 _gtk_selection_window_update_state (window);
362 g_object_notify (G_OBJECT (window), "has-selection");
366 * gtk_selection_window_get_has_selection:
367 * @window: a #GtkSelectionWindow
369 * Returns whether there any content is selected according to @window
371 * Returns: whether there is selected content
376 gtk_selection_window_get_has_selection (GtkSelectionWindow *window)
378 GtkSelectionWindowPrivate *priv;
380 g_return_val_if_fail (GTK_IS_SELECTION_WINDOW (window), FALSE);
382 priv = window->_priv;
384 return priv->has_selection;
388 * gtk_selection_window_get_toolbar:
389 * @window: a #GtkSelectionWindow
391 * Returns the toolbar contained by @window so e.g. new elements
394 * Returns: the internal toolbar
399 gtk_selection_window_get_toolbar (GtkSelectionWindow *window)
401 GtkSelectionWindowPrivate *priv;
403 g_return_val_if_fail (GTK_IS_SELECTION_WINDOW (window), FALSE);
405 priv = window->_priv;
407 return priv->toolbar;