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 "gtkselectionwindow.h"
31 #include "gtkprivate.h"
37 " <toolitem name='cut' action='Cut' />" \
38 " <toolitem name='copy' action='Copy' />" \
39 " <toolitem name='paste' action='Paste' />" \
44 static void _action_cut_cb (GtkAction *action,
45 GtkSelectionWindow *window);
46 static void _action_copy_cb (GtkAction *action,
47 GtkSelectionWindow *window);
48 static void _action_paste_cb (GtkAction *action,
49 GtkSelectionWindow *window);
51 static GtkActionEntry entries[] = {
52 { "Cut", GTK_STOCK_CUT, NULL, NULL, NULL, G_CALLBACK (_action_cut_cb) },
53 { "Copy", GTK_STOCK_COPY, NULL, NULL, NULL, G_CALLBACK (_action_copy_cb) },
54 { "Paste", GTK_STOCK_PASTE, NULL, NULL, NULL, G_CALLBACK (_action_paste_cb) }
69 static guint signals[N_SIGNALS] = { 0 };
71 struct _GtkSelectionWindowPrivate
73 GtkUIManager *ui_manager;
76 guint has_selection : 1;
79 G_DEFINE_TYPE (GtkSelectionWindow, gtk_selection_window, GTK_TYPE_BUBBLE_WINDOW)
82 _action_cut_cb (GtkAction *action,
83 GtkSelectionWindow *window)
85 g_signal_emit (window, signals[CUT], 0);
89 _action_copy_cb (GtkAction *action,
90 GtkSelectionWindow *window)
92 g_signal_emit (window, signals[COPY], 0);
96 _action_paste_cb (GtkAction *action,
97 GtkSelectionWindow *window)
99 g_signal_emit (window, signals[PASTE], 0);
103 _gtk_selection_window_update_state (GtkSelectionWindow *window)
105 GtkSelectionWindowPrivate *priv;
106 GtkClipboard *clipboard;
107 gboolean text_available;
110 priv = window->_priv;
111 clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window),
112 GDK_SELECTION_CLIPBOARD);
113 text_available = gtk_clipboard_wait_is_text_available (clipboard);
115 action = gtk_ui_manager_get_action (priv->ui_manager, "/toolbar/cut");
116 gtk_action_set_sensitive (action, priv->editable && priv->has_selection);
118 action = gtk_ui_manager_get_action (priv->ui_manager, "/toolbar/copy");
119 gtk_action_set_sensitive (action, priv->has_selection);
121 action = gtk_ui_manager_get_action (priv->ui_manager, "/toolbar/paste");
122 gtk_action_set_sensitive (action, text_available && priv->editable);
126 gtk_selection_window_map (GtkWidget *widget)
128 _gtk_selection_window_update_state (GTK_SELECTION_WINDOW (widget));
129 GTK_WIDGET_CLASS (gtk_selection_window_parent_class)->map (widget);
133 gtk_selection_window_finalize (GObject *object)
135 GtkSelectionWindowPrivate *priv;
137 priv = GTK_SELECTION_WINDOW (object)->_priv;
138 g_object_unref (priv->ui_manager);
140 G_OBJECT_CLASS (gtk_selection_window_parent_class)->finalize (object);
144 gtk_selection_window_set_property (GObject *object,
152 gtk_selection_window_set_editable (GTK_SELECTION_WINDOW (object),
153 g_value_get_boolean (value));
155 case PROP_HAS_SELECTION:
156 gtk_selection_window_set_has_selection (GTK_SELECTION_WINDOW (object),
157 g_value_get_boolean (value));
160 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
166 gtk_selection_window_get_property (GObject *object,
171 GtkSelectionWindowPrivate *priv;
173 priv = GTK_SELECTION_WINDOW (object)->_priv;
178 g_value_set_boolean (value, priv->editable);
180 case PROP_HAS_SELECTION:
181 g_value_set_boolean (value, priv->has_selection);
184 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
190 gtk_selection_window_class_init (GtkSelectionWindowClass *klass)
192 GObjectClass *object_class = G_OBJECT_CLASS (klass);
193 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
195 object_class->finalize = gtk_selection_window_finalize;
196 object_class->set_property = gtk_selection_window_set_property;
197 object_class->get_property = gtk_selection_window_get_property;
199 widget_class->map = gtk_selection_window_map;
201 g_object_class_install_property (object_class,
203 g_param_spec_boolean ("editable",
205 P_("Whether content is editable"),
207 GTK_PARAM_READWRITE |
209 g_object_class_install_property (object_class,
211 g_param_spec_boolean ("has-selection",
213 P_("Whether there is any content currently selected"),
215 GTK_PARAM_READWRITE |
218 g_signal_new (I_("cut"),
219 G_OBJECT_CLASS_TYPE (object_class),
220 G_SIGNAL_RUN_LAST, 0,
222 g_cclosure_marshal_VOID__VOID,
225 g_signal_new (I_("copy"),
226 G_OBJECT_CLASS_TYPE (object_class),
227 G_SIGNAL_RUN_LAST, 0,
229 g_cclosure_marshal_VOID__VOID,
232 g_signal_new (I_("paste"),
233 G_OBJECT_CLASS_TYPE (object_class),
234 G_SIGNAL_RUN_LAST, 0,
236 g_cclosure_marshal_VOID__VOID,
239 g_type_class_add_private (klass, sizeof (GtkSelectionWindowPrivate));
243 gtk_selection_window_init (GtkSelectionWindow *window)
245 GtkSelectionWindowPrivate *priv;
246 GtkActionGroup *group;
248 window->_priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (window,
249 GTK_TYPE_SELECTION_WINDOW,
250 GtkSelectionWindowPrivate);
252 group = gtk_action_group_new ("SelectionToolbar");
253 gtk_action_group_add_actions (group, entries, G_N_ELEMENTS (entries), window);
255 priv->ui_manager = gtk_ui_manager_new ();
256 gtk_ui_manager_insert_action_group (priv->ui_manager, group, 0);
257 gtk_ui_manager_add_ui_from_string (priv->ui_manager, TOOLBAR_UI, -1, NULL);
259 priv->toolbar = gtk_ui_manager_get_widget (priv->ui_manager, "/toolbar");
260 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (priv->toolbar), FALSE);
261 gtk_widget_show_all (priv->toolbar);
263 gtk_container_add (GTK_CONTAINER (window), priv->toolbar);
267 * gtk_selection_window_new:
269 * Creates a new #GtkSelectionWindow
271 * Returns: a newly created #GtkSelectionWindow
274 gtk_selection_window_new (void)
276 return g_object_new (GTK_TYPE_SELECTION_WINDOW, NULL);
280 * gtk_selection_window_set_editable:
281 * @window: a #GtkSelectionWindow
282 * @editable: whether the current selection is editable
284 * Sets whether the current selection is editable. Toolbar options'
285 * sensitivity will change according to this.
290 gtk_selection_window_set_editable (GtkSelectionWindow *window,
293 GtkSelectionWindowPrivate *priv;
294 gboolean need_update;
296 g_return_if_fail (GTK_IS_SELECTION_WINDOW (window));
298 priv = window->_priv;
299 need_update = priv->editable != editable &&
300 gtk_widget_get_visible (GTK_WIDGET (window));
301 priv->editable = editable;
304 _gtk_selection_window_update_state (window);
306 g_object_notify (G_OBJECT (window), "editable");
310 * gtk_selection_window_get_editable:
311 * @window: a #GtkSelectionWindow
313 * Returns whether the contents are editable according to @window
315 * Returns: whether the contents are editable
320 gtk_selection_window_get_editable (GtkSelectionWindow *window)
322 GtkSelectionWindowPrivate *priv;
324 g_return_val_if_fail (GTK_IS_SELECTION_WINDOW (window), FALSE);
326 priv = window->_priv;
328 return priv->editable;
332 * gtk_selection_window_set_has_selection:
333 * @window: a #GtkSelectionWindow
334 * @has_selection: whether there is currently a selection
336 * Sets whether there is any selected content. Toolbar options'
337 * sensitivity will change according to this.
342 gtk_selection_window_set_has_selection (GtkSelectionWindow *window,
343 gboolean has_selection)
345 GtkSelectionWindowPrivate *priv;
346 gboolean need_update;
348 g_return_if_fail (GTK_IS_SELECTION_WINDOW (window));
350 priv = window->_priv;
351 need_update = priv->has_selection != has_selection &&
352 gtk_widget_get_visible (GTK_WIDGET (window));
353 priv->has_selection = has_selection;
356 _gtk_selection_window_update_state (window);
358 g_object_notify (G_OBJECT (window), "has-selection");
362 * gtk_selection_window_get_has_selection:
363 * @window: a #GtkSelectionWindow
365 * Returns whether there any content is selected according to @window
367 * Returns: whether there is selected content
372 gtk_selection_window_get_has_selection (GtkSelectionWindow *window)
374 GtkSelectionWindowPrivate *priv;
376 g_return_val_if_fail (GTK_IS_SELECTION_WINDOW (window), FALSE);
378 priv = window->_priv;
380 return priv->has_selection;
384 * gtk_selection_window_get_toolbar:
385 * @window: a #GtkSelectionWindow
387 * Returns the toolbar contained by @window so e.g. new elements
390 * Returns: the internal toolbar
395 gtk_selection_window_get_toolbar (GtkSelectionWindow *window)
397 GtkSelectionWindowPrivate *priv;
399 g_return_val_if_fail (GTK_IS_SELECTION_WINDOW (window), FALSE);
401 priv = window->_priv;
403 return priv->toolbar;