]> Pileus Git - ~andy/gtk/blob - gtk/gtkcolorswatch.c
Show alpha in the palette as well
[~andy/gtk] / gtk / gtkcolorswatch.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2012 Red Hat, Inc.
3  *
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.
8  *
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.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "config.h"
21
22 #include "gtkcolorswatch.h"
23 #include "gtkroundedboxprivate.h"
24 #include "gtkdnd.h"
25 #include "gtkicontheme.h"
26 #include "gtkmain.h"
27 #include "gtkmenu.h"
28 #include "gtkmenuitem.h"
29 #include "gtkmenushell.h"
30 #include "gtkbindings.h"
31 #include "gtkprivate.h"
32 #include "gtkintl.h"
33
34
35 struct _GtkColorSwatchPrivate
36 {
37   GdkRGBA color;
38   gdouble radius[4];
39   gchar *icon;
40   guint    selected         : 1;
41   guint    has_color        : 1;
42   guint    can_drop         : 1;
43   guint    contains_pointer : 1;
44 };
45
46 enum
47 {
48   PROP_ZERO,
49   PROP_COLOR,
50   PROP_SELECTED
51 };
52
53 enum
54 {
55   ACTIVATE,
56   CUSTOMIZE,
57   LAST_SIGNAL
58 };
59
60 static guint signals[LAST_SIGNAL];
61
62 G_DEFINE_TYPE (GtkColorSwatch, gtk_color_swatch, GTK_TYPE_DRAWING_AREA)
63
64 static void
65 gtk_color_swatch_init (GtkColorSwatch *swatch)
66 {
67   swatch->priv = G_TYPE_INSTANCE_GET_PRIVATE (swatch,
68                                               GTK_TYPE_COLOR_SWATCH,
69                                               GtkColorSwatchPrivate);
70
71   gtk_widget_set_can_focus (GTK_WIDGET (swatch), TRUE);
72   gtk_widget_set_events (GTK_WIDGET (swatch), GDK_BUTTON_PRESS_MASK
73                                               | GDK_BUTTON_RELEASE_MASK
74                                               | GDK_EXPOSURE_MASK
75                                               | GDK_ENTER_NOTIFY_MASK
76                                               | GDK_LEAVE_NOTIFY_MASK);
77 }
78
79 static void
80 swatch_finalize (GObject *object)
81 {
82   GtkColorSwatch *swatch = GTK_COLOR_SWATCH (object);
83
84   g_free (swatch->priv->icon);
85
86   G_OBJECT_CLASS (gtk_color_swatch_parent_class)->finalize (object);
87 }
88
89 #define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
90
91 static cairo_pattern_t *
92 get_checkered_pattern (void)
93 {
94   /* need to respect pixman's stride being a multiple of 4 */
95   static unsigned char data[8] = { 0xFF, 0x00, 0x00, 0x00,
96                                    0x00, 0xFF, 0x00, 0x00 };
97   static cairo_surface_t *checkered = NULL;
98   cairo_pattern_t *pattern;
99
100   if (checkered == NULL)
101     checkered = cairo_image_surface_create_for_data (data,
102                                                      CAIRO_FORMAT_A8,
103                                                      2, 2, 4);
104
105   pattern = cairo_pattern_create_for_surface (checkered);
106   cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
107   cairo_pattern_set_filter (pattern, CAIRO_FILTER_NEAREST);
108
109   return pattern;
110 }
111
112 static gboolean
113 swatch_draw (GtkWidget *widget,
114              cairo_t   *cr)
115 {
116   GtkColorSwatch *swatch = (GtkColorSwatch*)widget;
117   GtkRoundedBox box;
118   gint i;
119   gdouble width, height;
120   GtkStyleContext *context;
121   GtkStateFlags state;
122   GdkRGBA bg;
123
124   context = gtk_widget_get_style_context (widget);
125   state = gtk_widget_get_state_flags (widget);
126   width = gtk_widget_get_allocated_width (widget);
127   height = gtk_widget_get_allocated_height (widget);
128
129   gtk_style_context_save (context);
130   cairo_save (cr);
131
132   gtk_style_context_set_state (context, state);
133
134   _gtk_rounded_box_init_rect (&box, 0, 0, width, height);
135   for (i = 0; i < 4; i++)
136     box.corner[i].horizontal = box.corner[i].vertical = swatch->priv->radius[i];
137
138   _gtk_rounded_box_path (&box, cr);
139
140   if (swatch->priv->has_color)
141     {
142       cairo_pattern_t *pattern;
143       cairo_matrix_t matrix;
144
145       cairo_set_source_rgb (cr, 0.33, 0.33, 0.33);
146       cairo_fill_preserve (cr);
147
148       cairo_set_source_rgb (cr, 0.66, 0.66, 0.66);
149
150       pattern = get_checkered_pattern ();
151       cairo_matrix_init_scale (&matrix, 0.125, 0.125);
152       cairo_pattern_set_matrix (pattern, &matrix);
153       cairo_clip_preserve (cr);
154       cairo_mask (cr, pattern);
155       cairo_pattern_destroy (pattern);
156
157       gdk_cairo_set_source_rgba (cr, &swatch->priv->color);
158       cairo_fill_preserve (cr);
159     }
160
161   cairo_set_source_rgb (cr, 0.4, 0.4, 0.4);
162   cairo_set_line_width (cr, 1);
163   cairo_stroke (cr);
164
165   if (gtk_widget_has_visible_focus (widget))
166     {
167       cairo_set_line_width (cr, 2);
168       if (swatch->priv->has_color && INTENSITY (swatch->priv->color.red, swatch->priv->color.green, swatch->priv->color.blue) < 0.5)
169         cairo_set_source_rgba (cr, 1., 1., 1., 0.4);
170       else
171         cairo_set_source_rgba (cr, 0., 0., 0., 0.4);
172       _gtk_rounded_box_shrink (&box, 3, 3, 3, 3);
173       _gtk_rounded_box_path (&box, cr);
174       cairo_stroke (cr);
175     }
176
177   if (swatch->priv->icon)
178     {
179       GdkPixbuf *pixbuf;
180       GtkIconTheme *theme;
181       theme = gtk_icon_theme_get_default ();
182       pixbuf = gtk_icon_theme_load_icon (theme, "list-add-symbolic", 16,
183                                          GTK_ICON_LOOKUP_GENERIC_FALLBACK
184                                          | GTK_ICON_LOOKUP_USE_BUILTIN,
185                                          NULL);
186
187       gtk_render_icon (context, cr, pixbuf,
188                        (width - gdk_pixbuf_get_width (pixbuf)) / 2,
189                        (height - gdk_pixbuf_get_height (pixbuf)) / 2);
190       g_object_unref (pixbuf);
191     }
192   else  if (swatch->priv->selected)
193     {
194       gtk_style_context_get_background_color (context, state, &bg);
195       cairo_new_sub_path (cr);
196       cairo_arc (cr, width / 2, height / 2, 10, 0, 2 * G_PI);
197       cairo_close_path (cr);
198       gdk_cairo_set_source_rgba (cr, &bg);
199       cairo_fill_preserve (cr);
200       if (INTENSITY (swatch->priv->color.red, swatch->priv->color.green, swatch->priv->color.blue) > 0.5)
201         cairo_set_source_rgba (cr, 0., 0., 0., 0.4);
202       else
203         cairo_set_source_rgba (cr, 1., 1., 1., 0.4);
204       cairo_set_line_width (cr, 2);
205       cairo_stroke (cr);
206       gtk_style_context_set_state (context, state | GTK_STATE_FLAG_ACTIVE);
207       gtk_render_check (context, cr, width / 2 - 5, height / 2 - 5, 10, 10);
208     }
209
210   cairo_restore (cr);
211   gtk_style_context_restore (context);
212
213   return FALSE;
214 }
215
216 static void
217 drag_set_color_icon (GdkDragContext *context,
218                      const GdkRGBA  *color)
219 {
220   cairo_surface_t *surface;
221   cairo_t *cr;
222
223   surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 48, 32);
224   cr = cairo_create (surface);
225   gdk_cairo_set_source_rgba (cr, color);
226   cairo_paint (cr);
227
228   cairo_surface_set_device_offset (surface, -2, -2);
229   gtk_drag_set_icon_surface (context, surface);
230
231   cairo_destroy (cr);
232   cairo_surface_destroy (surface);
233 }
234
235 static void
236 swatch_drag_begin (GtkWidget      *widget,
237                    GdkDragContext *context)
238 {
239   GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
240   GdkRGBA color;
241
242   gtk_color_swatch_get_color (swatch, &color);
243   drag_set_color_icon (context, &color);
244 }
245
246 static void
247 swatch_drag_data_get (GtkWidget        *widget,
248                       GdkDragContext   *context,
249                       GtkSelectionData *selection_data,
250                       guint             info,
251                       guint             time)
252 {
253   GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
254   guint16 vals[4];
255   GdkRGBA color;
256
257   gtk_color_swatch_get_color (swatch, &color);
258
259   vals[0] = color.red * 0xffff;
260   vals[1] = color.green * 0xffff;
261   vals[2] = color.blue * 0xffff;
262   vals[3] = color.alpha * 0xffff;
263
264   gtk_selection_data_set (selection_data,
265                           gdk_atom_intern_static_string ("application/x-color"),
266                           16, (guchar *)vals, 8);
267 }
268
269 static void
270 swatch_drag_data_received (GtkWidget        *widget,
271                            GdkDragContext   *context,
272                            gint              x,
273                            gint              y,
274                            GtkSelectionData *selection_data,
275                            guint             info,
276                            guint             time)
277 {
278   gint length;
279   guint16 *vals;
280   GdkRGBA color;
281
282   length = gtk_selection_data_get_length (selection_data);
283
284   if (length < 0)
285     return;
286
287   /* We accept drops with the wrong format, since the KDE color
288    * chooser incorrectly drops application/x-color with format 8.
289    */
290   if (length != 8)
291     {
292       g_warning ("Received invalid color data\n");
293       return;
294     }
295
296   vals = (guint16 *) gtk_selection_data_get_data (selection_data);
297
298   color.red   = (gdouble)vals[0] / 0xffff;
299   color.green = (gdouble)vals[1] / 0xffff;
300   color.blue  = (gdouble)vals[2] / 0xffff;
301   color.alpha = (gdouble)vals[3] / 0xffff;
302
303   gtk_color_swatch_set_color (GTK_COLOR_SWATCH (widget), &color);
304 }
305
306 static void
307 swatch_get_property (GObject    *object,
308                      guint       prop_id,
309                      GValue     *value,
310                      GParamSpec *pspec)
311 {
312   GtkColorSwatch *swatch = GTK_COLOR_SWATCH (object);
313   GdkRGBA color;
314
315   switch (prop_id)
316     {
317     case PROP_COLOR:
318       gtk_color_swatch_get_color (swatch, &color);
319       g_value_set_boxed (value, &color);
320       break;
321     case PROP_SELECTED:
322       g_value_set_boolean (value, swatch->priv->selected);
323       break;
324     default:
325       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
326       break;
327     }
328 }
329
330 static void
331 swatch_set_property (GObject      *object,
332                      guint         prop_id,
333                      const GValue *value,
334                      GParamSpec   *pspec)
335 {
336   GtkColorSwatch *swatch = GTK_COLOR_SWATCH (object);
337
338   switch (prop_id)
339     {
340     case PROP_COLOR:
341       gtk_color_swatch_set_color (swatch, g_value_get_boxed (value));
342       break;
343     case PROP_SELECTED:
344       gtk_color_swatch_set_selected (swatch, g_value_get_boolean (value));
345       break;
346     default:
347       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
348       break;
349     }
350 }
351
352 static void
353 swatch_get_preferred_width (GtkWidget *widget,
354                             gint      *min,
355                             gint      *nat)
356 {
357   *min = *nat = 48;
358 }
359
360 static void
361 swatch_get_preferred_height (GtkWidget *widget,
362                              gint      *min,
363                              gint      *nat)
364 {
365   *min = *nat = 32;
366 }
367
368 static gboolean
369 swatch_key_press (GtkWidget   *widget,
370                   GdkEventKey *event)
371 {
372   GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
373
374   if (event->keyval == GDK_KEY_space ||
375       event->keyval == GDK_KEY_Return ||
376       event->keyval == GDK_KEY_ISO_Enter||
377       event->keyval == GDK_KEY_KP_Enter ||
378       event->keyval == GDK_KEY_KP_Space)
379     {
380       if (swatch->priv->has_color && !swatch->priv->selected)
381         gtk_color_swatch_set_selected (swatch, TRUE);
382       else
383         g_signal_emit (swatch, signals[ACTIVATE], 0);
384       return TRUE;
385     }
386
387   if (GTK_WIDGET_CLASS (gtk_color_swatch_parent_class)->key_press_event (widget, event))
388     return TRUE;
389
390   return FALSE;
391 }
392
393 static gboolean
394 swatch_enter (GtkWidget        *widget,
395               GdkEventCrossing *event)
396 {
397   GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
398   swatch->priv->contains_pointer = TRUE;
399   return FALSE;
400 }
401
402 static gboolean
403 swatch_leave (GtkWidget        *widget,
404               GdkEventCrossing *event)
405 {
406   GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
407   swatch->priv->contains_pointer = FALSE;
408   return FALSE;
409 }
410
411 static void
412 emit_customize (GtkColorSwatch *swatch)
413 {
414   g_signal_emit (swatch, signals[CUSTOMIZE], 0);
415 }
416
417 static void
418 popup_position_func (GtkMenu   *menu,
419                      gint      *x,
420                      gint      *y,
421                      gboolean  *push_in,
422                      gpointer   user_data)
423 {
424   GtkWidget *widget;
425   GtkRequisition req;
426   gint root_x, root_y;
427   GdkScreen *screen;
428   GdkWindow *window;
429   GdkRectangle monitor;
430   gint monitor_num;
431
432   widget = GTK_WIDGET (user_data);
433   g_return_if_fail (gtk_widget_get_realized (widget));
434   window = gtk_widget_get_window (widget);
435
436   screen = gtk_widget_get_screen (widget);
437   monitor_num = gdk_screen_get_monitor_at_window (screen, window);
438   if (monitor_num < 0)
439     monitor_num = 0;
440   gtk_menu_set_monitor (menu, monitor_num);
441
442   gdk_window_get_origin (window, &root_x, &root_y);
443   gtk_widget_get_preferred_size (GTK_WIDGET (menu), &req, NULL);
444
445   /* Put corner of menu centered on swatch */
446   *x = root_x + gtk_widget_get_allocated_width (widget) / 2;
447   *y = root_y + gtk_widget_get_allocated_height (widget) / 2;
448
449   /* Ensure sanity */
450   gdk_screen_get_monitor_workarea (screen, monitor_num, &monitor);
451   *x = CLAMP (*x, monitor.x, MAX (monitor.x, monitor.width - req.width));
452   *y = CLAMP (*y, monitor.y, MAX (monitor.y, monitor.height - req.height));
453 }
454
455 static void
456 do_popup (GtkWidget      *swatch,
457           GdkEventButton *event)
458 {
459   GtkWidget *menu;
460   GtkWidget *item;
461
462   menu = gtk_menu_new ();
463   item = gtk_menu_item_new_with_mnemonic (_("_Customize"));
464   gtk_menu_attach_to_widget (GTK_MENU (menu), swatch, NULL);
465
466   g_signal_connect_swapped (item, "activate",
467                             G_CALLBACK (emit_customize), swatch);
468
469   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
470
471   gtk_widget_show_all (item);
472
473   if (event)
474     gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
475                     NULL, NULL, event->button, event->time);
476   else
477     gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
478                     popup_position_func, swatch,
479                     0, gtk_get_current_event_time ());
480 }
481
482 static gboolean
483 swatch_button_press (GtkWidget      *widget,
484                      GdkEventButton *event)
485 {
486   GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
487
488   gtk_widget_grab_focus (GTK_WIDGET (swatch));
489
490   if (gdk_event_triggers_context_menu ((GdkEvent *) event) &&
491       swatch->priv->has_color)
492     {
493       do_popup (widget, event);
494       return TRUE;
495     }
496   else if (event->button == GDK_BUTTON_PRIMARY &&
497            swatch->priv->selected)
498     {
499       g_signal_emit (swatch, signals[ACTIVATE], 0);
500       return TRUE;
501     }
502
503   return FALSE;
504 }
505
506 static gboolean
507 swatch_button_release (GtkWidget      *widget,
508                        GdkEventButton *event)
509 {
510   GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
511
512   gtk_widget_grab_focus (GTK_WIDGET (swatch));
513
514   if (event->button == GDK_BUTTON_PRIMARY &&
515       swatch->priv->contains_pointer)
516     {
517       if (!swatch->priv->has_color)
518         {
519           g_signal_emit (swatch, signals[ACTIVATE], 0);
520           return TRUE;
521         }
522       else if (!swatch->priv->selected)
523         {
524           gtk_color_swatch_set_selected (swatch, TRUE);
525           return TRUE;
526         }
527     }
528
529   return FALSE;
530 }
531
532 static gboolean
533 swatch_menu (GtkWidget *swatch)
534 {
535   do_popup (swatch, NULL);
536   return TRUE;
537 }
538
539 static void
540 gtk_color_swatch_class_init (GtkColorSwatchClass *class)
541 {
542   GtkWidgetClass *widget_class = (GtkWidgetClass *)class;
543   GObjectClass *object_class = (GObjectClass *)class;
544
545   object_class->get_property = swatch_get_property;
546   object_class->set_property = swatch_set_property;
547   object_class->finalize = swatch_finalize;
548
549   widget_class->get_preferred_width = swatch_get_preferred_width;
550   widget_class->get_preferred_height = swatch_get_preferred_height;
551   widget_class->draw = swatch_draw;
552   widget_class->drag_begin = swatch_drag_begin;
553   widget_class->drag_data_get = swatch_drag_data_get;
554   widget_class->drag_data_received = swatch_drag_data_received;
555   widget_class->key_press_event = swatch_key_press;
556   widget_class->popup_menu = swatch_menu;
557   widget_class->button_press_event = swatch_button_press;
558   widget_class->button_release_event = swatch_button_release;
559   widget_class->enter_notify_event = swatch_enter;
560   widget_class->leave_notify_event = swatch_leave;
561
562   signals[ACTIVATE] =
563     g_signal_new ("activate",
564                   GTK_TYPE_COLOR_SWATCH,
565                   G_SIGNAL_RUN_FIRST,
566                   G_STRUCT_OFFSET (GtkColorSwatchClass, activate),
567                   NULL, NULL, NULL, G_TYPE_NONE, 0);
568
569   signals[CUSTOMIZE] =
570     g_signal_new ("customize",
571                   GTK_TYPE_COLOR_SWATCH,
572                   G_SIGNAL_RUN_FIRST,
573                   G_STRUCT_OFFSET (GtkColorSwatchClass, customize),
574                   NULL, NULL, NULL, G_TYPE_NONE, 0);
575
576   g_object_class_install_property (object_class, PROP_COLOR,
577       g_param_spec_boxed ("color", P_("Color"), P_("Color"),
578                           GDK_TYPE_RGBA, GTK_PARAM_READWRITE));
579
580   g_object_class_install_property (object_class, PROP_SELECTED,
581       g_param_spec_boolean ("selected", P_("Selected"), P_("Selected"),
582                             FALSE, GTK_PARAM_READWRITE));
583
584   g_type_class_add_private (object_class, sizeof (GtkColorSwatchPrivate));
585 }
586
587
588 /* Public API {{{1 */
589
590 GtkWidget *
591 gtk_color_swatch_new (void)
592 {
593   return (GtkWidget *) g_object_new (GTK_TYPE_COLOR_SWATCH, NULL);
594 }
595
596 void
597 gtk_color_swatch_set_color (GtkColorSwatch *swatch,
598                             const GdkRGBA  *color)
599 {
600   static const GtkTargetEntry targets[] = {
601     { "application/x-color", 0 }
602   };
603
604   if (!swatch->priv->has_color)
605     gtk_drag_source_set (GTK_WIDGET (swatch),
606                          GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
607                          targets, 1,
608                          GDK_ACTION_COPY | GDK_ACTION_MOVE);
609
610   swatch->priv->has_color = TRUE;
611   swatch->priv->color.red = color->red;
612   swatch->priv->color.green = color->green;
613   swatch->priv->color.blue = color->blue;
614   swatch->priv->color.alpha = color->alpha;
615
616   gtk_widget_queue_draw (GTK_WIDGET (swatch));
617   g_object_notify (G_OBJECT (swatch), "color");
618 }
619
620 gboolean
621 gtk_color_swatch_get_color (GtkColorSwatch *swatch,
622                             GdkRGBA        *color)
623 {
624   if (swatch->priv->has_color)
625     {
626       color->red = swatch->priv->color.red;
627       color->green = swatch->priv->color.green;
628       color->blue = swatch->priv->color.blue;
629       color->alpha = swatch->priv->color.alpha;
630       return TRUE;
631     }
632   else
633     {
634       color->red = 1.0;
635       color->green = 1.0;
636       color->blue = 1.0;
637       color->alpha = 1.0;
638       return FALSE;
639     }
640 }
641
642 void
643 gtk_color_swatch_set_corner_radii (GtkColorSwatch *swatch,
644                                    gdouble         top_left,
645                                    gdouble         top_right,
646                                    gdouble         bottom_right,
647                                    gdouble         bottom_left)
648 {
649   swatch->priv->radius[0] = top_left;
650   swatch->priv->radius[1] = top_right;
651   swatch->priv->radius[2] = bottom_right;
652   swatch->priv->radius[3] = bottom_left;
653
654   gtk_widget_queue_draw (GTK_WIDGET (swatch));
655 }
656
657 void
658 gtk_color_swatch_set_selected (GtkColorSwatch *swatch,
659                                gboolean        selected)
660 {
661   if (swatch->priv->selected != selected)
662     {
663       swatch->priv->selected = selected;
664       gtk_widget_queue_draw (GTK_WIDGET (swatch));
665       g_object_notify (G_OBJECT (swatch), "selected");
666     }
667 }
668
669 void
670 gtk_color_swatch_set_icon (GtkColorSwatch *swatch,
671                            const gchar    *icon)
672 {
673   swatch->priv->icon = g_strdup (icon);
674   gtk_widget_queue_draw (GTK_WIDGET (swatch));
675 }
676
677 void
678 gtk_color_swatch_set_can_drop (GtkColorSwatch *swatch,
679                                gboolean        can_drop)
680 {
681   static const GtkTargetEntry targets[] = {
682     { "application/x-color", 0 }
683   };
684
685   if (!swatch->priv->can_drop)
686     gtk_drag_dest_set (GTK_WIDGET (swatch),
687                        GTK_DEST_DEFAULT_HIGHLIGHT |
688                        GTK_DEST_DEFAULT_MOTION |
689                        GTK_DEST_DEFAULT_DROP,
690                        targets, 1,
691                        GDK_ACTION_COPY);
692
693   swatch->priv->can_drop = can_drop;
694 }
695
696 /* vim:set foldmethod=marker: */