]> Pileus Git - ~andy/gtk/blob - gtk/gtkmenuitem.c
yeppers, accelerator changes to fix the gimp. commit message dedicated to
[~andy/gtk] / gtk / gtkmenuitem.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library 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  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library 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 #include <string.h>
20 #include "gtkaccellabel.h"
21 #include "gtkmain.h"
22 #include "gtkmenu.h"
23 #include "gtkmenuitem.h"
24 #include "gtksignal.h"
25
26
27 #define BORDER_SPACING  3
28 #define SELECT_TIMEOUT  20
29
30 #define MENU_ITEM_CLASS(w)  GTK_MENU_ITEM_CLASS (GTK_OBJECT (w)->klass)
31
32
33 enum {
34   ACTIVATE,
35   LAST_SIGNAL
36 };
37
38
39 static void gtk_menu_item_class_init     (GtkMenuItemClass *klass);
40 static void gtk_menu_item_init           (GtkMenuItem      *menu_item);
41 static void gtk_menu_item_destroy        (GtkObject        *object);
42 static void gtk_menu_item_size_request   (GtkWidget        *widget,
43                                           GtkRequisition   *requisition);
44 static void gtk_menu_item_size_allocate  (GtkWidget        *widget,
45                                           GtkAllocation    *allocation);
46 static void gtk_menu_item_paint          (GtkWidget        *widget,
47                                           GdkRectangle     *area);
48 static void gtk_menu_item_draw           (GtkWidget        *widget,
49                                           GdkRectangle     *area);
50 static gint gtk_menu_item_expose         (GtkWidget        *widget,
51                                           GdkEventExpose   *event);
52 static void gtk_real_menu_item_select    (GtkItem          *item);
53 static void gtk_real_menu_item_deselect  (GtkItem          *item);
54 static gint gtk_menu_item_select_timeout (gpointer          data);
55 static void gtk_menu_item_position_menu  (GtkMenu          *menu,
56                                           gint             *x,
57                                           gint             *y,
58                                           gpointer          user_data);
59 static void gtk_menu_item_show_all       (GtkWidget        *widget);
60 static void gtk_menu_item_hide_all       (GtkWidget        *widget);
61
62 static GtkItemClass *parent_class;
63 static guint menu_item_signals[LAST_SIGNAL] = { 0 };
64
65
66 GtkType
67 gtk_menu_item_get_type (void)
68 {
69   static GtkType menu_item_type = 0;
70
71   if (!menu_item_type)
72     {
73       GtkTypeInfo menu_item_info =
74       {
75         "GtkMenuItem",
76         sizeof (GtkMenuItem),
77         sizeof (GtkMenuItemClass),
78         (GtkClassInitFunc) gtk_menu_item_class_init,
79         (GtkObjectInitFunc) gtk_menu_item_init,
80         (GtkArgSetFunc) NULL,
81         (GtkArgGetFunc) NULL,
82       };
83
84       menu_item_type = gtk_type_unique (gtk_item_get_type (), &menu_item_info);
85       gtk_type_set_chunk_alloc (menu_item_type, 16);
86     }
87
88   return menu_item_type;
89 }
90
91 static void
92 gtk_menu_item_class_init (GtkMenuItemClass *klass)
93 {
94   GtkObjectClass *object_class;
95   GtkWidgetClass *widget_class;
96   GtkItemClass *item_class;
97
98   object_class = (GtkObjectClass*) klass;
99   widget_class = (GtkWidgetClass*) klass;
100   item_class = (GtkItemClass*) klass;
101
102   parent_class = gtk_type_class (gtk_item_get_type ());
103
104   menu_item_signals[ACTIVATE] =
105     gtk_signal_new ("activate",
106                     GTK_RUN_FIRST,
107                     object_class->type,
108                     GTK_SIGNAL_OFFSET (GtkMenuItemClass, activate),
109                     gtk_signal_default_marshaller,
110                     GTK_TYPE_NONE, 0);
111
112   gtk_object_class_add_signals (object_class, menu_item_signals, LAST_SIGNAL);
113
114   object_class->destroy = gtk_menu_item_destroy;
115
116   widget_class->activate_signal = menu_item_signals[ACTIVATE];
117   widget_class->size_request = gtk_menu_item_size_request;
118   widget_class->size_allocate = gtk_menu_item_size_allocate;
119   widget_class->draw = gtk_menu_item_draw;
120   widget_class->expose_event = gtk_menu_item_expose;
121   widget_class->show_all = gtk_menu_item_show_all;
122   widget_class->hide_all = gtk_menu_item_hide_all;  
123
124   item_class->select = gtk_real_menu_item_select;
125   item_class->deselect = gtk_real_menu_item_deselect;
126
127   klass->activate = NULL;
128
129   klass->toggle_size = 0;
130 }
131
132 static void
133 gtk_menu_item_init (GtkMenuItem *menu_item)
134 {
135   menu_item->submenu = NULL;
136   menu_item->accelerator_signal = menu_item_signals[ACTIVATE];
137   menu_item->toggle_size = 0;
138   menu_item->accelerator_width = 0;
139   menu_item->show_toggle_indicator = FALSE;
140   menu_item->show_submenu_indicator = FALSE;
141   menu_item->submenu_direction = GTK_DIRECTION_RIGHT;
142   menu_item->submenu_placement = GTK_TOP_BOTTOM;
143   menu_item->right_justify = FALSE;
144
145   menu_item->timer = 0;
146 }
147
148 GtkWidget*
149 gtk_menu_item_new (void)
150 {
151   return GTK_WIDGET (gtk_type_new (gtk_menu_item_get_type ()));
152 }
153
154 GtkWidget*
155 gtk_menu_item_new_with_label (const gchar *label)
156 {
157   GtkWidget *menu_item;
158   GtkWidget *accel_label;
159
160   menu_item = gtk_menu_item_new ();
161   accel_label = gtk_accel_label_new (label);
162   gtk_misc_set_alignment (GTK_MISC (accel_label), 0.0, 0.5);
163
164   gtk_container_add (GTK_CONTAINER (menu_item), accel_label);
165   gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (accel_label), menu_item);
166   gtk_widget_show (accel_label);
167
168   return menu_item;
169 }
170
171 static void
172 gtk_menu_item_destroy (GtkObject *object)
173 {
174   GtkMenuItem *menu_item;
175
176   g_return_if_fail (object != NULL);
177   g_return_if_fail (GTK_IS_MENU_ITEM (object));
178
179   menu_item = GTK_MENU_ITEM (object);
180
181   if (menu_item->submenu)
182     gtk_widget_destroy (menu_item->submenu);
183
184   if (GTK_OBJECT_CLASS (parent_class)->destroy)
185     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
186 }
187
188 static void
189 gtk_menu_item_detacher (GtkWidget     *widget,
190                         GtkMenu       *menu)
191 {
192   GtkMenuItem *menu_item;
193
194   g_return_if_fail (widget != NULL);
195   g_return_if_fail (GTK_IS_MENU_ITEM (widget));
196
197   menu_item = GTK_MENU_ITEM (widget);
198   g_return_if_fail (menu_item->submenu == (GtkWidget*) menu);
199
200   menu_item->submenu = NULL;
201 }
202
203 void
204 gtk_menu_item_set_submenu (GtkMenuItem *menu_item,
205                            GtkWidget   *submenu)
206 {
207   g_return_if_fail (menu_item != NULL);
208   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
209   
210   if (menu_item->submenu != submenu)
211     {
212       gtk_menu_item_remove_submenu (menu_item);
213       
214       menu_item->submenu = submenu;
215       gtk_menu_attach_to_widget (GTK_MENU (submenu),
216                                  GTK_WIDGET (menu_item),
217                                  gtk_menu_item_detacher);
218       
219       if (GTK_WIDGET (menu_item)->parent)
220         gtk_widget_queue_resize (GTK_WIDGET (menu_item));
221     }
222 }
223
224 void
225 gtk_menu_item_remove_submenu (GtkMenuItem         *menu_item)
226 {
227   g_return_if_fail (menu_item != NULL);
228   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
229       
230   if (menu_item->submenu)
231     gtk_menu_detach (GTK_MENU (menu_item->submenu));
232 }
233
234 void
235 gtk_menu_item_set_placement (GtkMenuItem         *menu_item,
236                              GtkSubmenuPlacement  placement)
237 {
238   g_return_if_fail (menu_item != NULL);
239   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
240
241   menu_item->submenu_placement = placement;
242 }
243
244 void
245 gtk_menu_item_configure (GtkMenuItem *menu_item,
246                          gint         show_toggle_indicator,
247                          gint         show_submenu_indicator)
248 {
249   g_return_if_fail (menu_item != NULL);
250   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
251
252   menu_item->show_toggle_indicator = (show_toggle_indicator == TRUE);
253   menu_item->show_submenu_indicator = (show_submenu_indicator == TRUE);
254 }
255
256 void
257 gtk_menu_item_select (GtkMenuItem *menu_item)
258 {
259   gtk_item_select (GTK_ITEM (menu_item));
260 }
261
262 void
263 gtk_menu_item_deselect (GtkMenuItem *menu_item)
264 {
265   gtk_item_deselect (GTK_ITEM (menu_item));
266 }
267
268 void
269 gtk_menu_item_activate (GtkMenuItem *menu_item)
270 {
271   gtk_signal_emit (GTK_OBJECT (menu_item), menu_item_signals[ACTIVATE]);
272 }
273
274 static void
275 gtk_menu_item_accel_width_foreach (GtkWidget *widget,
276                                    gpointer data)
277 {
278   guint *width = data;
279
280   if (GTK_IS_ACCEL_LABEL (widget))
281     {
282       guint w;
283
284       w = gtk_accel_label_accelerator_width (GTK_ACCEL_LABEL (widget));
285       *width = MAX (*width, w);
286     }
287   else if (GTK_IS_CONTAINER (widget))
288     gtk_container_foreach (GTK_CONTAINER (widget),
289                            gtk_menu_item_accel_width_foreach,
290                            data);
291 }
292
293 static void
294 gtk_menu_item_size_request (GtkWidget      *widget,
295                             GtkRequisition *requisition)
296 {
297   GtkMenuItem *menu_item;
298   GtkBin *bin;
299   guint accel_width;
300
301   g_return_if_fail (widget != NULL);
302   g_return_if_fail (GTK_IS_MENU_ITEM (widget));
303   g_return_if_fail (requisition != NULL);
304
305   bin = GTK_BIN (widget);
306   menu_item = GTK_MENU_ITEM (widget);
307
308   requisition->width = (GTK_CONTAINER (widget)->border_width +
309                         widget->style->klass->xthickness +
310                         BORDER_SPACING) * 2;
311   requisition->height = (GTK_CONTAINER (widget)->border_width +
312                          widget->style->klass->ythickness) * 2;
313
314   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
315     {
316       gtk_widget_size_request (bin->child, &bin->child->requisition);
317
318       requisition->width += bin->child->requisition.width;
319       requisition->height += bin->child->requisition.height;
320     }
321
322   if (menu_item->submenu && menu_item->show_submenu_indicator)
323     requisition->width += 21;
324
325   accel_width = 0;
326   gtk_container_foreach (GTK_CONTAINER (menu_item),
327                          gtk_menu_item_accel_width_foreach,
328                          &accel_width);
329   menu_item->accelerator_width = accel_width;
330 }
331
332 static void
333 gtk_menu_item_size_allocate (GtkWidget     *widget,
334                              GtkAllocation *allocation)
335 {
336   GtkMenuItem *menu_item;
337   GtkBin *bin;
338   GtkAllocation child_allocation;
339
340   g_return_if_fail (widget != NULL);
341   g_return_if_fail (GTK_IS_MENU_ITEM (widget));
342   g_return_if_fail (allocation != NULL);
343
344   menu_item = GTK_MENU_ITEM (widget);
345   bin = GTK_BIN (widget);
346   
347   widget->allocation = *allocation;
348
349   if (bin->child)
350     {
351       child_allocation.x = (GTK_CONTAINER (widget)->border_width +
352                             widget->style->klass->xthickness +
353                             BORDER_SPACING);
354       child_allocation.y = (GTK_CONTAINER (widget)->border_width +
355                             widget->style->klass->ythickness);
356       child_allocation.width = MAX (1, allocation->width - child_allocation.x * 2);
357       child_allocation.height = MAX (1, allocation->height - child_allocation.y * 2);
358       child_allocation.x += GTK_MENU_ITEM (widget)->toggle_size;
359       child_allocation.width -= GTK_MENU_ITEM (widget)->toggle_size;
360       if (menu_item->submenu && menu_item->show_submenu_indicator)
361         child_allocation.width -= 21;
362       
363       gtk_widget_size_allocate (bin->child, &child_allocation);
364     }
365
366   if (GTK_WIDGET_REALIZED (widget))
367     gdk_window_move_resize (widget->window,
368                             allocation->x, allocation->y,
369                             allocation->width, allocation->height);
370
371   if (menu_item->submenu)
372     gtk_menu_reposition (GTK_MENU (menu_item->submenu));
373 }
374
375 static void
376 gtk_menu_item_paint (GtkWidget    *widget,
377                      GdkRectangle *area)
378 {
379   GtkMenuItem *menu_item;
380   GtkStateType state_type;
381   GtkShadowType shadow_type;
382   gint width, height;
383   gint x, y;
384
385   g_return_if_fail (widget != NULL);
386   g_return_if_fail (GTK_IS_MENU_ITEM (widget));
387
388   if (GTK_WIDGET_DRAWABLE (widget))
389     {
390       menu_item = GTK_MENU_ITEM (widget);
391
392       state_type = widget->state;
393       if (!GTK_WIDGET_IS_SENSITIVE (widget))
394         state_type = GTK_STATE_INSENSITIVE;
395
396       gtk_style_set_background (widget->style, widget->window, state_type);
397       gdk_window_clear_area (widget->window, area->x, area->y, area->width, area->height);
398
399       x = GTK_CONTAINER (menu_item)->border_width;
400       y = GTK_CONTAINER (menu_item)->border_width;
401       width = widget->allocation.width - x * 2;
402       height = widget->allocation.height - y * 2;
403
404       if ((state_type == GTK_STATE_PRELIGHT) &&
405           (GTK_BIN (menu_item)->child))
406         gtk_draw_shadow (widget->style,
407                          widget->window,
408                          GTK_STATE_PRELIGHT,
409                          GTK_SHADOW_OUT,
410                          x, y, width, height);
411
412       if (menu_item->submenu && menu_item->show_submenu_indicator)
413         {
414           shadow_type = GTK_SHADOW_OUT;
415           if (state_type == GTK_STATE_PRELIGHT)
416             shadow_type = GTK_SHADOW_IN;
417
418           gtk_draw_arrow (widget->style, widget->window,
419                           state_type, shadow_type, GTK_ARROW_RIGHT, FALSE,
420                           x + width - 15, y + height / 2 - 5, 10, 10);
421         }
422       else if (!GTK_BIN (menu_item)->child)
423         {
424           gtk_draw_hline (widget->style, widget->window, GTK_STATE_NORMAL,
425                           0, widget->allocation.width, 0);
426         }
427     }
428 }
429
430 static void
431 gtk_menu_item_draw (GtkWidget    *widget,
432                     GdkRectangle *area)
433 {
434   GtkBin *bin;
435   GdkRectangle child_area;
436
437   g_return_if_fail (widget != NULL);
438   g_return_if_fail (GTK_IS_MENU_ITEM (widget));
439   g_return_if_fail (area != NULL);
440
441   if (GTK_WIDGET_DRAWABLE (widget))
442     {
443       gtk_menu_item_paint (widget, area);
444
445       bin = GTK_BIN (widget);
446
447       if (bin->child)
448         {
449           if (gtk_widget_intersect (bin->child, area, &child_area))
450             gtk_widget_draw (bin->child, &child_area);
451         }
452     }
453 }
454
455 static gint
456 gtk_menu_item_expose (GtkWidget      *widget,
457                       GdkEventExpose *event)
458 {
459   GtkBin *bin;
460   GdkEventExpose child_event;
461
462   g_return_val_if_fail (widget != NULL, FALSE);
463   g_return_val_if_fail (GTK_IS_MENU_ITEM (widget), FALSE);
464   g_return_val_if_fail (event != NULL, FALSE);
465
466   if (GTK_WIDGET_DRAWABLE (widget))
467     {
468       gtk_menu_item_paint (widget, &event->area);
469
470       bin = GTK_BIN (widget);
471
472       if (bin->child)
473         {
474           child_event = *event;
475
476           if (GTK_WIDGET_NO_WINDOW (bin->child) &&
477               gtk_widget_intersect (bin->child, &event->area, &child_event.area))
478             gtk_widget_event (bin->child, (GdkEvent*) &child_event);
479         }
480     }
481
482   return FALSE;
483 }
484
485 static void
486 gtk_real_menu_item_select (GtkItem *item)
487 {
488   GtkMenuItem *menu_item;
489
490   g_return_if_fail (item != NULL);
491   g_return_if_fail (GTK_IS_MENU_ITEM (item));
492
493   menu_item = GTK_MENU_ITEM (item);
494
495   if (menu_item->submenu && !GTK_WIDGET_VISIBLE (menu_item->submenu))
496     menu_item->timer = gtk_timeout_add (SELECT_TIMEOUT, gtk_menu_item_select_timeout, menu_item);
497
498   gtk_widget_set_state (GTK_WIDGET (menu_item), GTK_STATE_PRELIGHT);
499   gtk_widget_draw (GTK_WIDGET (menu_item), NULL);
500 }
501
502 static void
503 gtk_real_menu_item_deselect (GtkItem *item)
504 {
505   GtkMenuItem *menu_item;
506
507   g_return_if_fail (item != NULL);
508   g_return_if_fail (GTK_IS_MENU_ITEM (item));
509
510   menu_item = GTK_MENU_ITEM (item);
511
512   if (menu_item->submenu)
513     {
514       if (menu_item->timer)
515         gtk_timeout_remove (menu_item->timer);
516       else
517         gtk_menu_popdown (GTK_MENU (menu_item->submenu));
518     }
519
520   gtk_widget_set_state (GTK_WIDGET (menu_item), GTK_STATE_NORMAL);
521   gtk_widget_draw (GTK_WIDGET (menu_item), NULL);
522 }
523
524 static gint
525 gtk_menu_item_select_timeout (gpointer data)
526 {
527   GtkMenuItem *menu_item;
528
529   menu_item = GTK_MENU_ITEM (data);
530   menu_item->timer = 0;
531
532   gtk_menu_popup (GTK_MENU (menu_item->submenu),
533                   GTK_WIDGET (menu_item)->parent,
534                   GTK_WIDGET (menu_item),
535                   gtk_menu_item_position_menu,
536                   menu_item,
537                   GTK_MENU_SHELL (GTK_WIDGET (menu_item)->parent)->button,
538                   0);
539
540   return FALSE;
541 }
542
543 static void
544 gtk_menu_item_position_menu (GtkMenu  *menu,
545                              gint     *x,
546                              gint     *y,
547                              gpointer  user_data)
548 {
549   GtkMenuItem *menu_item;
550   GtkWidget *parent_menu_item;
551   gint screen_width;
552   gint screen_height;
553   gint twidth, theight;
554   gint tx, ty;
555
556   g_return_if_fail (menu != NULL);
557   g_return_if_fail (x != NULL);
558   g_return_if_fail (y != NULL);
559
560   menu_item = GTK_MENU_ITEM (user_data);
561
562   twidth = GTK_WIDGET (menu)->requisition.width;
563   theight = GTK_WIDGET (menu)->requisition.height;
564
565   screen_width = gdk_screen_width ();
566   screen_height = gdk_screen_height ();
567
568   if (!gdk_window_get_origin (GTK_WIDGET (menu_item)->window, &tx, &ty))
569     {
570       g_warning ("Menu not on screen");
571       return;
572     }
573
574   switch (menu_item->submenu_placement)
575     {
576     case GTK_TOP_BOTTOM:
577       if ((ty + GTK_WIDGET (menu_item)->allocation.height + theight) <= screen_height)
578         ty += GTK_WIDGET (menu_item)->allocation.height;
579       else if ((ty - theight) >= 0)
580         ty -= theight;
581       else
582         ty += GTK_WIDGET (menu_item)->allocation.height;
583
584       if ((tx + twidth) > screen_width)
585         {
586           tx -= ((tx + twidth) - screen_width);
587           if (tx < 0)
588             tx = 0;
589         }
590       break;
591
592     case GTK_LEFT_RIGHT:
593       menu_item->submenu_direction = GTK_DIRECTION_RIGHT;
594       parent_menu_item = GTK_MENU (GTK_WIDGET (menu_item)->parent)->parent_menu_item;
595       if (parent_menu_item)
596         menu_item->submenu_direction = GTK_MENU_ITEM (parent_menu_item)->submenu_direction;
597
598       switch (menu_item->submenu_direction)
599         {
600         case GTK_DIRECTION_LEFT:
601           if ((tx - twidth) >= 0)
602             tx -= twidth;
603           else
604             {
605               menu_item->submenu_direction = GTK_DIRECTION_RIGHT;
606               tx += GTK_WIDGET (menu_item)->allocation.width - 5;
607             }
608           break;
609
610         case GTK_DIRECTION_RIGHT:
611           if ((tx + GTK_WIDGET (menu_item)->allocation.width + twidth - 5) <= screen_width)
612             tx += GTK_WIDGET (menu_item)->allocation.width - 5;
613           else
614             {
615               menu_item->submenu_direction = GTK_DIRECTION_LEFT;
616               tx -= twidth;
617             }
618           break;
619         }
620
621       if ((ty + GTK_WIDGET (menu_item)->allocation.height / 4 + theight) <= screen_height)
622         ty += GTK_WIDGET (menu_item)->allocation.height / 4;
623       else
624         {
625           ty -= ((ty + theight) - screen_height);
626           if (ty < 0)
627             ty = 0;
628         }
629       break;
630     }
631
632   *x = tx;
633   *y = ty;
634 }
635
636 void
637 gtk_menu_item_right_justify(GtkMenuItem *menuitem)
638 {
639   g_return_if_fail (menuitem != NULL);
640   g_return_if_fail (GTK_IS_MENU_ITEM (menuitem));
641
642   menuitem->right_justify = 1;
643 }
644
645 static void
646 gtk_menu_item_show_all (GtkWidget *widget)
647 {
648   GtkContainer *container;
649   GtkMenuItem  *menu_item;
650
651   g_return_if_fail (widget != NULL);
652   g_return_if_fail (GTK_IS_MENU_ITEM (widget));
653   container = GTK_CONTAINER (widget);
654   menu_item = GTK_MENU_ITEM (widget);
655
656   /* Show children, traverse to submenu, show self. */
657   gtk_container_foreach (container, (GtkCallback) gtk_widget_show_all, NULL);
658   if (menu_item->submenu)
659     gtk_widget_show_all (menu_item->submenu);
660   gtk_widget_show (widget);
661 }
662
663
664 static void
665 gtk_menu_item_hide_all (GtkWidget *widget)
666 {
667   GtkContainer *container;
668   GtkMenuItem  *menu_item;
669
670   g_return_if_fail (widget != NULL);
671   g_return_if_fail (GTK_IS_MENU_ITEM (widget));
672   container = GTK_CONTAINER (widget);
673   menu_item = GTK_MENU_ITEM (widget);
674
675   /* Reverse order of gtk_menu_item_show_all */
676   gtk_widget_hide (widget);
677   if (menu_item->submenu)
678     gtk_widget_hide_all (menu_item->submenu);
679   gtk_container_foreach (container, (GtkCallback) gtk_widget_hide_all, NULL);
680 }