1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
6 * Copyright (C) 2000 Eazel, Inc.
7 * Copyright (C) 2004 Red Hat, Inc.
9 * Nautilus is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * Nautilus is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * Author: Andy Hertzfeld <andy@eazel.com>
24 * Alexander Larsson <alexl@redhat.com>
26 * This is the zoom control for the location bar
31 #include "nautilus-zoom-control.h"
33 #include <atk/atkaction.h>
34 #include <glib/gi18n.h>
35 #include <eel/eel-accessibility.h>
36 #include <eel/eel-glib-extensions.h>
37 #include <eel/eel-graphic-effects.h>
38 #include <eel/eel-gtk-extensions.h>
39 #include <gtk/gtkaccessible.h>
40 #include <gtk/gtkmenu.h>
41 #include <gtk/gtkradiomenuitem.h>
42 #include <gtk/gtkstock.h>
43 #include <gtk/gtkbindings.h>
44 #include <gdk/gdkkeysyms.h>
45 #include <libgnome/gnome-macros.h>
46 #include <libnautilus-private/nautilus-file-utilities.h>
47 #include <libnautilus-private/nautilus-global-preferences.h>
48 #include <libnautilus-private/nautilus-marshal.h>
62 struct NautilusZoomControlDetails
{
65 GtkWidget
*zoom_label
;
66 GtkWidget
*zoom_button
;
68 NautilusZoomLevel zoom_level
;
69 NautilusZoomLevel min_zoom_level
;
70 NautilusZoomLevel max_zoom_level
;
71 gboolean has_min_zoom_level
;
72 gboolean has_max_zoom_level
;
73 GList
*preferred_zoom_levels
;
75 gboolean marking_menu_items
;
79 static guint signals
[LAST_SIGNAL
];
81 static gpointer accessible_parent_class
;
83 static const char * const nautilus_zoom_control_accessible_action_names
[] = {
86 N_("Zoom to Default"),
89 static const int nautilus_zoom_control_accessible_action_signals
[] = {
95 static const char * const nautilus_zoom_control_accessible_action_descriptions
[] = {
96 N_("Show the contents in more detail"),
97 N_("Show the contents in less detail"),
98 N_("Show in the default detail level"),
101 static GtkMenu
*create_zoom_menu (NautilusZoomControl
*zoom_control
);
103 static GType
nautilus_zoom_control_accessible_get_type (void);
105 /* button assignments */
106 #define CONTEXTUAL_MENU_BUTTON 3
108 #define NUM_ACTIONS ((int)G_N_ELEMENTS (nautilus_zoom_control_accessible_action_names))
110 GNOME_CLASS_BOILERPLATE (NautilusZoomControl
, nautilus_zoom_control
,
111 GtkHBox
, GTK_TYPE_HBOX
)
114 nautilus_zoom_control_finalize (GObject
*object
)
116 g_list_free (NAUTILUS_ZOOM_CONTROL (object
)->details
->preferred_zoom_levels
);
118 G_OBJECT_CLASS (parent_class
)->finalize (object
);
122 zoom_button_clicked (GtkButton
*button
, NautilusZoomControl
*zoom_control
)
124 g_signal_emit (zoom_control
, signals
[ZOOM_TO_DEFAULT
], 0);
128 zoom_popup_menu_show (GdkEventButton
*event
, NautilusZoomControl
*zoom_control
)
130 eel_pop_up_context_menu (create_zoom_menu (zoom_control
),
131 EEL_DEFAULT_POPUP_MENU_DISPLACEMENT
,
132 EEL_DEFAULT_POPUP_MENU_DISPLACEMENT
,
137 menu_position_under_widget (GtkMenu
*menu
,
144 GtkWidget
*container
;
146 GtkRequisition menu_req
;
147 GdkRectangle monitor
;
151 widget
= GTK_WIDGET (user_data
);
152 g_return_if_fail (GTK_IS_WIDGET (widget
));
154 container
= gtk_widget_get_ancestor (widget
, GTK_TYPE_CONTAINER
);
155 g_return_if_fail (container
!= NULL
);
157 gtk_widget_size_request (widget
, &req
);
158 gtk_widget_size_request (GTK_WIDGET (menu
), &menu_req
);
160 screen
= gtk_widget_get_screen (GTK_WIDGET (menu
));
161 monitor_num
= gdk_screen_get_monitor_at_window (screen
, widget
->window
);
162 if (monitor_num
< 0) {
165 gdk_screen_get_monitor_geometry (screen
, monitor_num
, &monitor
);
167 gdk_window_get_origin (widget
->window
, x
, y
);
168 if (GTK_WIDGET_NO_WINDOW (widget
)) {
169 *x
+= widget
->allocation
.x
;
170 *y
+= widget
->allocation
.y
;
173 if (gtk_widget_get_direction (container
) == GTK_TEXT_DIR_LTR
) {
174 *x
+= widget
->allocation
.width
- req
.width
;
176 *x
+= req
.width
- menu_req
.width
;
179 if ((*y
+ widget
->allocation
.height
+ menu_req
.height
) <= monitor
.y
+ monitor
.height
) {
180 *y
+= widget
->allocation
.height
;
181 } else if ((*y
- menu_req
.height
) >= monitor
.y
) {
182 *y
-= menu_req
.height
;
183 } else if (monitor
.y
+ monitor
.height
- (*y
+ widget
->allocation
.height
) > *y
) {
184 *y
+= widget
->allocation
.height
;
186 *y
-= menu_req
.height
;
194 zoom_popup_menu (GtkWidget
*widget
, NautilusZoomControl
*zoom_control
)
198 menu
= create_zoom_menu (zoom_control
);
199 gtk_menu_popup (menu
, NULL
, NULL
,
200 menu_position_under_widget
, widget
,
201 0, gtk_get_current_event_time ());
202 gtk_menu_shell_select_first (GTK_MENU_SHELL (menu
), FALSE
);
205 /* handle button presses */
207 nautilus_zoom_control_button_press_event (GtkWidget
*widget
,
208 GdkEventButton
*event
,
209 NautilusZoomControl
*zoom_control
)
211 if (event
->type
!= GDK_BUTTON_PRESS
) {
215 /* check for the context menu button and show the menu */
216 if (event
->button
== CONTEXTUAL_MENU_BUTTON
) {
217 zoom_popup_menu_show (event
, zoom_control
);
220 /* We don't change our state (to reflect the new zoom) here.
221 The zoomable will call back with the new level.
222 Actually, the callback goes to the viewframe containing the
223 zoomable which, in turn, emits zoom_level_changed,
224 which someone (e.g. nautilus_window) picks up and handles by
225 calling into is - nautilus_zoom_control_set_zoom_level.
232 zoom_out_clicked (GtkButton
*button
,
233 NautilusZoomControl
*zoom_control
)
235 if (nautilus_zoom_control_can_zoom_out (zoom_control
)) {
236 g_signal_emit (G_OBJECT (zoom_control
), signals
[ZOOM_OUT
], 0);
241 zoom_in_clicked (GtkButton
*button
,
242 NautilusZoomControl
*zoom_control
)
244 if (nautilus_zoom_control_can_zoom_in (zoom_control
)) {
245 g_signal_emit (G_OBJECT (zoom_control
), signals
[ZOOM_IN
], 0);
250 set_label_size (NautilusZoomControl
*zoom_control
)
257 text
= gtk_label_get_text (GTK_LABEL (zoom_control
->details
->zoom_label
));
258 layout
= gtk_label_get_layout (GTK_LABEL (zoom_control
->details
->zoom_label
));
259 pango_layout_set_text (layout
, "100%", -1);
260 pango_layout_get_pixel_size (layout
, &width
, &height
);
261 gtk_widget_set_size_request (zoom_control
->details
->zoom_label
, width
, height
);
262 gtk_label_set_text (GTK_LABEL (zoom_control
->details
->zoom_label
),
267 label_style_set_callback (GtkWidget
*label
,
271 set_label_size (NAUTILUS_ZOOM_CONTROL (user_data
));
275 nautilus_zoom_control_instance_init (NautilusZoomControl
*zoom_control
)
280 zoom_control
->details
= G_TYPE_INSTANCE_GET_PRIVATE (zoom_control
, NAUTILUS_TYPE_ZOOM_CONTROL
, NautilusZoomControlDetails
);
282 zoom_control
->details
->zoom_level
= NAUTILUS_ZOOM_LEVEL_STANDARD
;
283 zoom_control
->details
->min_zoom_level
= NAUTILUS_ZOOM_LEVEL_SMALLEST
;
284 zoom_control
->details
->max_zoom_level
= NAUTILUS_ZOOM_LEVEL_LARGEST
;
285 zoom_control
->details
->has_min_zoom_level
= TRUE
;
286 zoom_control
->details
->has_max_zoom_level
= TRUE
;
288 for (i
= NAUTILUS_ZOOM_LEVEL_LARGEST
; i
>= NAUTILUS_ZOOM_LEVEL_SMALLEST
; i
--) {
289 zoom_control
->details
->preferred_zoom_levels
= g_list_prepend (
290 zoom_control
->details
->preferred_zoom_levels
,
291 GINT_TO_POINTER (i
));
294 image
= gtk_image_new_from_stock (GTK_STOCK_ZOOM_OUT
, GTK_ICON_SIZE_MENU
);
295 zoom_control
->details
->zoom_out
= gtk_button_new ();
296 gtk_button_set_focus_on_click (GTK_BUTTON (zoom_control
->details
->zoom_out
), FALSE
);
297 gtk_button_set_relief (GTK_BUTTON (zoom_control
->details
->zoom_out
),
299 g_signal_connect (G_OBJECT (zoom_control
->details
->zoom_out
),
300 "clicked", G_CALLBACK (zoom_out_clicked
),
302 gtk_container_add (GTK_CONTAINER (zoom_control
->details
->zoom_out
), image
);
303 gtk_box_pack_start (GTK_BOX (zoom_control
),
304 zoom_control
->details
->zoom_out
, FALSE
, FALSE
, 0);
306 zoom_control
->details
->zoom_button
= gtk_button_new ();
307 gtk_button_set_focus_on_click (GTK_BUTTON (zoom_control
->details
->zoom_button
), FALSE
);
308 gtk_button_set_relief (GTK_BUTTON (zoom_control
->details
->zoom_button
),
311 gtk_widget_add_events (GTK_WIDGET (zoom_control
->details
->zoom_button
),
312 GDK_BUTTON_PRESS_MASK
313 | GDK_BUTTON_RELEASE_MASK
314 | GDK_POINTER_MOTION_MASK
);
316 g_signal_connect (G_OBJECT (zoom_control
->details
->zoom_button
),
317 "button-press-event",
318 G_CALLBACK (nautilus_zoom_control_button_press_event
),
321 g_signal_connect (G_OBJECT (zoom_control
->details
->zoom_button
),
322 "clicked", G_CALLBACK (zoom_button_clicked
),
325 g_signal_connect (G_OBJECT (zoom_control
->details
->zoom_button
),
326 "popup-menu", G_CALLBACK (zoom_popup_menu
),
329 zoom_control
->details
->zoom_label
= gtk_label_new ("100%");
330 g_signal_connect (zoom_control
->details
->zoom_label
,
332 G_CALLBACK (label_style_set_callback
),
334 set_label_size (zoom_control
);
336 gtk_container_add (GTK_CONTAINER (zoom_control
->details
->zoom_button
), zoom_control
->details
->zoom_label
);
338 gtk_box_pack_start (GTK_BOX (zoom_control
),
339 zoom_control
->details
->zoom_button
, TRUE
, TRUE
, 0);
341 image
= gtk_image_new_from_stock (GTK_STOCK_ZOOM_IN
, GTK_ICON_SIZE_MENU
);
342 zoom_control
->details
->zoom_in
= gtk_button_new ();
343 gtk_button_set_focus_on_click (GTK_BUTTON (zoom_control
->details
->zoom_in
), FALSE
);
344 gtk_button_set_relief (GTK_BUTTON (zoom_control
->details
->zoom_in
),
346 g_signal_connect (G_OBJECT (zoom_control
->details
->zoom_in
),
347 "clicked", G_CALLBACK (zoom_in_clicked
),
350 gtk_container_add (GTK_CONTAINER (zoom_control
->details
->zoom_in
), image
);
351 gtk_box_pack_start (GTK_BOX (zoom_control
),
352 zoom_control
->details
->zoom_in
, FALSE
, FALSE
, 0);
354 gtk_widget_show_all (zoom_control
->details
->zoom_out
);
355 gtk_widget_show_all (zoom_control
->details
->zoom_button
);
356 gtk_widget_show_all (zoom_control
->details
->zoom_in
);
359 /* Allocate a new zoom control */
361 nautilus_zoom_control_new (void)
363 return gtk_widget_new (nautilus_zoom_control_get_type (), NULL
);
367 nautilus_zoom_control_redraw (NautilusZoomControl
*zoom_control
)
372 gtk_widget_set_sensitive (zoom_control
->details
->zoom_in
,
373 nautilus_zoom_control_can_zoom_in (zoom_control
));
374 gtk_widget_set_sensitive (zoom_control
->details
->zoom_out
,
375 nautilus_zoom_control_can_zoom_out (zoom_control
));
377 percent
= floor ((100.0 * nautilus_get_relative_icon_size_for_zoom_level (zoom_control
->details
->zoom_level
)) + .5);
378 num_str
= g_strdup_printf ("%d%%", percent
);
379 gtk_label_set_text (GTK_LABEL (zoom_control
->details
->zoom_label
), num_str
);
383 /* routines to create and handle the zoom menu */
386 zoom_menu_callback (GtkMenuItem
*item
, gpointer callback_data
)
388 NautilusZoomLevel zoom_level
;
389 NautilusZoomControl
*zoom_control
;
392 zoom_control
= NAUTILUS_ZOOM_CONTROL (callback_data
);
394 /* Don't do anything if we're just setting the toggle state of menu items. */
395 if (zoom_control
->details
->marking_menu_items
) {
399 /* Don't send the signal if the menuitem was toggled off */
400 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item
))) {
404 zoom_level
= (NautilusZoomLevel
) GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item
), "zoom_level"));
406 /* Assume we can zoom and then check whether we're right. */
408 if (zoom_control
->details
->has_min_zoom_level
&&
409 zoom_level
< zoom_control
->details
->min_zoom_level
)
410 can_zoom
= FALSE
; /* no, we're below the minimum zoom level. */
411 if (zoom_control
->details
->has_max_zoom_level
&&
412 zoom_level
> zoom_control
->details
->max_zoom_level
)
413 can_zoom
= FALSE
; /* no, we're beyond the upper zoom level. */
417 g_signal_emit (zoom_control
, signals
[ZOOM_TO_LEVEL
], 0, zoom_level
);
421 static GtkRadioMenuItem
*
422 create_zoom_menu_item (NautilusZoomControl
*zoom_control
, GtkMenu
*menu
,
423 NautilusZoomLevel zoom_level
,
424 GtkRadioMenuItem
*previous_radio_item
)
426 GtkWidget
*menu_item
;
428 GSList
*radio_item_group
;
431 /* Set flag so that callback isn't activated when set_active called
432 * to set toggle state of other radio items.
434 zoom_control
->details
->marking_menu_items
= TRUE
;
436 percent
= floor ((100.0 * nautilus_get_relative_icon_size_for_zoom_level (zoom_level
)) + .5);
437 item_text
= g_strdup_printf ("%d%%", percent
);
439 radio_item_group
= previous_radio_item
== NULL
441 : gtk_radio_menu_item_get_group (previous_radio_item
);
442 menu_item
= gtk_radio_menu_item_new_with_label (radio_item_group
, item_text
);
445 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item
),
446 zoom_level
== zoom_control
->details
->zoom_level
);
448 g_object_set_data (G_OBJECT (menu_item
), "zoom_level", GINT_TO_POINTER (zoom_level
));
449 g_signal_connect_object (menu_item
, "activate",
450 G_CALLBACK (zoom_menu_callback
), zoom_control
, 0);
452 gtk_widget_show (menu_item
);
453 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), menu_item
);
455 zoom_control
->details
->marking_menu_items
= FALSE
;
457 return GTK_RADIO_MENU_ITEM (menu_item
);
461 create_zoom_menu (NautilusZoomControl
*zoom_control
)
464 GtkRadioMenuItem
*previous_item
;
467 menu
= GTK_MENU (gtk_menu_new ());
469 previous_item
= NULL
;
470 for (node
= zoom_control
->details
->preferred_zoom_levels
; node
!= NULL
; node
= node
->next
) {
471 previous_item
= create_zoom_menu_item
472 (zoom_control
, menu
, GPOINTER_TO_INT (node
->data
), previous_item
);
479 nautilus_zoom_control_get_accessible (GtkWidget
*widget
)
481 AtkObject
*accessible
;
483 accessible
= eel_accessibility_get_atk_object (widget
);
489 accessible
= g_object_new
490 (nautilus_zoom_control_accessible_get_type (), NULL
);
492 return eel_accessibility_set_atk_object_return (widget
, accessible
);
496 nautilus_zoom_control_change_value (NautilusZoomControl
*zoom_control
,
497 GtkScrollType scroll
)
500 case GTK_SCROLL_STEP_DOWN
:
501 if (nautilus_zoom_control_can_zoom_out (zoom_control
)) {
502 g_signal_emit (zoom_control
, signals
[ZOOM_OUT
], 0);
505 case GTK_SCROLL_STEP_UP
:
506 if (nautilus_zoom_control_can_zoom_in (zoom_control
)) {
507 g_signal_emit (zoom_control
, signals
[ZOOM_IN
], 0);
511 g_warning ("Invalid scroll type %d for NautilusZoomControl:change_value", scroll
);
516 nautilus_zoom_control_set_zoom_level (NautilusZoomControl
*zoom_control
,
517 NautilusZoomLevel zoom_level
)
519 zoom_control
->details
->zoom_level
= zoom_level
;
520 nautilus_zoom_control_redraw (zoom_control
);
524 nautilus_zoom_control_set_parameters (NautilusZoomControl
*zoom_control
,
525 NautilusZoomLevel min_zoom_level
,
526 NautilusZoomLevel max_zoom_level
,
527 gboolean has_min_zoom_level
,
528 gboolean has_max_zoom_level
,
531 g_return_if_fail (NAUTILUS_IS_ZOOM_CONTROL (zoom_control
));
533 zoom_control
->details
->min_zoom_level
= min_zoom_level
;
534 zoom_control
->details
->max_zoom_level
= max_zoom_level
;
535 zoom_control
->details
->has_min_zoom_level
= has_min_zoom_level
;
536 zoom_control
->details
->has_max_zoom_level
= has_max_zoom_level
;
538 g_list_free (zoom_control
->details
->preferred_zoom_levels
);
539 zoom_control
->details
->preferred_zoom_levels
= zoom_levels
;
541 nautilus_zoom_control_redraw (zoom_control
);
545 nautilus_zoom_control_get_zoom_level (NautilusZoomControl
*zoom_control
)
547 return zoom_control
->details
->zoom_level
;
551 nautilus_zoom_control_get_min_zoom_level (NautilusZoomControl
*zoom_control
)
553 return zoom_control
->details
->min_zoom_level
;
557 nautilus_zoom_control_get_max_zoom_level (NautilusZoomControl
*zoom_control
)
559 return zoom_control
->details
->max_zoom_level
;
563 nautilus_zoom_control_has_min_zoom_level (NautilusZoomControl
*zoom_control
)
565 return zoom_control
->details
->has_min_zoom_level
;
569 nautilus_zoom_control_has_max_zoom_level (NautilusZoomControl
*zoom_control
)
571 return zoom_control
->details
->has_max_zoom_level
;
575 nautilus_zoom_control_can_zoom_in (NautilusZoomControl
*zoom_control
)
577 return !zoom_control
->details
->has_max_zoom_level
||
578 (zoom_control
->details
->zoom_level
579 < zoom_control
->details
->max_zoom_level
);
583 nautilus_zoom_control_can_zoom_out (NautilusZoomControl
*zoom_control
)
585 return !zoom_control
->details
->has_min_zoom_level
||
586 (zoom_control
->details
->zoom_level
587 > zoom_control
->details
->min_zoom_level
);
591 nautilus_zoom_control_scroll_event (GtkWidget
*widget
, GdkEventScroll
*event
)
593 NautilusZoomControl
*zoom_control
;
595 zoom_control
= NAUTILUS_ZOOM_CONTROL (widget
);
597 if (event
->type
!= GDK_SCROLL
) {
601 if (event
->direction
== GDK_SCROLL_DOWN
&&
602 nautilus_zoom_control_can_zoom_out (zoom_control
)) {
603 g_signal_emit (widget
, signals
[ZOOM_OUT
], 0);
604 } else if (event
->direction
== GDK_SCROLL_UP
&&
605 nautilus_zoom_control_can_zoom_in (zoom_control
)) {
606 g_signal_emit (widget
, signals
[ZOOM_IN
], 0);
609 /* We don't change our state (to reflect the new zoom) here. The zoomable will
610 * call back with the new level. Actually, the callback goes to the view-frame
611 * containing the zoomable which, in turn, emits zoom_level_changed, which
612 * someone (e.g. nautilus_window) picks up and handles by calling into us -
613 * nautilus_zoom_control_set_zoom_level.
621 nautilus_zoom_control_class_init (NautilusZoomControlClass
*class)
623 GtkWidgetClass
*widget_class
;
624 GtkBindingSet
*binding_set
;
626 G_OBJECT_CLASS (class)->finalize
= nautilus_zoom_control_finalize
;
628 widget_class
= GTK_WIDGET_CLASS (class);
630 widget_class
->get_accessible
= nautilus_zoom_control_get_accessible
;
631 widget_class
->scroll_event
= nautilus_zoom_control_scroll_event
;
633 class->change_value
= nautilus_zoom_control_change_value
;
636 g_signal_new ("zoom_in",
637 G_TYPE_FROM_CLASS (class),
639 G_STRUCT_OFFSET (NautilusZoomControlClass
,
642 g_cclosure_marshal_VOID__VOID
,
646 g_signal_new ("zoom_out",
647 G_TYPE_FROM_CLASS (class),
649 G_STRUCT_OFFSET (NautilusZoomControlClass
,
652 g_cclosure_marshal_VOID__VOID
,
655 signals
[ZOOM_TO_LEVEL
] =
656 g_signal_new ("zoom_to_level",
657 G_TYPE_FROM_CLASS (class),
659 G_STRUCT_OFFSET (NautilusZoomControlClass
,
662 g_cclosure_marshal_VOID__INT
,
667 signals
[ZOOM_TO_DEFAULT
] =
668 g_signal_new ("zoom_to_default",
669 G_TYPE_FROM_CLASS (class),
670 G_SIGNAL_RUN_LAST
| G_SIGNAL_ACTION
,
671 G_STRUCT_OFFSET (NautilusZoomControlClass
,
674 g_cclosure_marshal_VOID__VOID
,
677 signals
[CHANGE_VALUE
] =
678 g_signal_new ("change_value",
679 G_TYPE_FROM_CLASS (class),
680 G_SIGNAL_RUN_LAST
| G_SIGNAL_ACTION
,
681 G_STRUCT_OFFSET (NautilusZoomControlClass
,
684 g_cclosure_marshal_VOID__ENUM
,
685 G_TYPE_NONE
, 1, GTK_TYPE_SCROLL_TYPE
);
687 binding_set
= gtk_binding_set_by_class (class);
689 gtk_binding_entry_add_signal (binding_set
,
692 1, GTK_TYPE_SCROLL_TYPE
,
693 GTK_SCROLL_STEP_DOWN
);
694 gtk_binding_entry_add_signal (binding_set
,
697 1, GTK_TYPE_SCROLL_TYPE
,
698 GTK_SCROLL_STEP_DOWN
);
700 gtk_binding_entry_add_signal (binding_set
,
704 gtk_binding_entry_add_signal (binding_set
,
709 gtk_binding_entry_add_signal (binding_set
,
712 1, GTK_TYPE_SCROLL_TYPE
,
714 gtk_binding_entry_add_signal (binding_set
,
717 1, GTK_TYPE_SCROLL_TYPE
,
720 g_type_class_add_private (G_OBJECT_CLASS (class), sizeof (NautilusZoomControlDetails
));
724 nautilus_zoom_control_accessible_do_action (AtkAction
*accessible
, int i
)
728 g_return_val_if_fail (i
>= 0 && i
< NUM_ACTIONS
, FALSE
);
730 widget
= GTK_ACCESSIBLE (accessible
)->widget
;
735 g_signal_emit (widget
,
736 signals
[nautilus_zoom_control_accessible_action_signals
[i
]],
743 nautilus_zoom_control_accessible_get_n_actions (AtkAction
*accessible
)
749 static G_CONST_RETURN
char *
750 nautilus_zoom_control_accessible_action_get_description (AtkAction
*accessible
,
753 g_return_val_if_fail (i
>= 0 && i
< NUM_ACTIONS
, NULL
);
755 return _(nautilus_zoom_control_accessible_action_descriptions
[i
]);
758 static G_CONST_RETURN
char *
759 nautilus_zoom_control_accessible_action_get_name (AtkAction
*accessible
,
762 g_return_val_if_fail (i
>= 0 && i
< NUM_ACTIONS
, NULL
);
764 return _(nautilus_zoom_control_accessible_action_names
[i
]);
768 nautilus_zoom_control_accessible_action_interface_init (AtkActionIface
*iface
)
770 iface
->do_action
= nautilus_zoom_control_accessible_do_action
;
771 iface
->get_n_actions
= nautilus_zoom_control_accessible_get_n_actions
;
772 iface
->get_description
= nautilus_zoom_control_accessible_action_get_description
;
773 iface
->get_name
= nautilus_zoom_control_accessible_action_get_name
;
777 nautilus_zoom_control_accessible_get_current_value (AtkValue
*accessible
,
780 NautilusZoomControl
*control
;
782 g_value_init (value
, G_TYPE_INT
);
784 control
= NAUTILUS_ZOOM_CONTROL (GTK_ACCESSIBLE (accessible
)->widget
);
786 g_value_set_int (value
, NAUTILUS_ZOOM_LEVEL_STANDARD
);
790 g_value_set_int (value
, control
->details
->zoom_level
);
794 nautilus_zoom_control_accessible_get_maximum_value (AtkValue
*accessible
,
797 NautilusZoomControl
*control
;
799 g_value_init (value
, G_TYPE_INT
);
801 control
= NAUTILUS_ZOOM_CONTROL (GTK_ACCESSIBLE (accessible
)->widget
);
803 g_value_set_int (value
, NAUTILUS_ZOOM_LEVEL_STANDARD
);
807 g_value_set_int (value
, control
->details
->max_zoom_level
);
811 nautilus_zoom_control_accessible_get_minimum_value (AtkValue
*accessible
,
814 NautilusZoomControl
*control
;
816 g_value_init (value
, G_TYPE_INT
);
818 control
= NAUTILUS_ZOOM_CONTROL (GTK_ACCESSIBLE (accessible
)->widget
);
820 g_value_set_int (value
, NAUTILUS_ZOOM_LEVEL_STANDARD
);
824 g_value_set_int (value
, control
->details
->min_zoom_level
);
827 static NautilusZoomLevel
828 nearest_preferred (NautilusZoomControl
*zoom_control
, NautilusZoomLevel value
)
830 NautilusZoomLevel last_value
;
831 NautilusZoomLevel current_value
;
834 if (!zoom_control
->details
->preferred_zoom_levels
) {
838 last_value
= GPOINTER_TO_INT (zoom_control
->details
->preferred_zoom_levels
->data
);
839 current_value
= last_value
;
841 for (l
= zoom_control
->details
->preferred_zoom_levels
; l
!= NULL
; l
= l
->next
) {
842 current_value
= GPOINTER_TO_INT (l
->data
);
844 if (current_value
> value
) {
845 float center
= (last_value
+ current_value
) / 2;
847 return (value
< center
) ? last_value
: current_value
;
851 last_value
= current_value
;
854 return current_value
;
858 nautilus_zoom_control_accessible_set_current_value (AtkValue
*accessible
,
861 NautilusZoomControl
*control
;
862 NautilusZoomLevel zoom
;
864 control
= NAUTILUS_ZOOM_CONTROL (GTK_ACCESSIBLE (accessible
)->widget
);
869 zoom
= nearest_preferred (control
, g_value_get_int (value
));
871 g_signal_emit (control
, signals
[ZOOM_TO_LEVEL
], 0, zoom
);
877 nautilus_zoom_control_accessible_value_interface_init (AtkValueIface
*iface
)
879 iface
->get_current_value
= nautilus_zoom_control_accessible_get_current_value
;
880 iface
->get_maximum_value
= nautilus_zoom_control_accessible_get_maximum_value
;
881 iface
->get_minimum_value
= nautilus_zoom_control_accessible_get_minimum_value
;
882 iface
->set_current_value
= nautilus_zoom_control_accessible_set_current_value
;
885 static G_CONST_RETURN
char *
886 nautilus_zoom_control_accessible_get_name (AtkObject
*accessible
)
891 static G_CONST_RETURN
char *
892 nautilus_zoom_control_accessible_get_description (AtkObject
*accessible
)
894 return _("Set the zoom level of the current view");
898 nautilus_zoom_control_accessible_initialize (AtkObject
*accessible
,
901 if (ATK_OBJECT_CLASS (accessible_parent_class
)->initialize
!= NULL
) {
902 ATK_OBJECT_CLASS (accessible_parent_class
)->initialize (accessible
, data
);
904 atk_object_set_role (accessible
, ATK_ROLE_DIAL
);
908 nautilus_zoom_control_accessible_class_init (AtkObjectClass
*klass
)
910 accessible_parent_class
= g_type_class_peek_parent (klass
);
912 klass
->get_name
= nautilus_zoom_control_accessible_get_name
;
913 klass
->get_description
= nautilus_zoom_control_accessible_get_description
;
914 klass
->initialize
= nautilus_zoom_control_accessible_initialize
;
918 nautilus_zoom_control_accessible_get_type (void)
920 static GType type
= 0;
923 static GInterfaceInfo atk_action_info
= {
924 (GInterfaceInitFunc
)nautilus_zoom_control_accessible_action_interface_init
,
925 (GInterfaceFinalizeFunc
)NULL
,
929 static GInterfaceInfo atk_value_info
= {
930 (GInterfaceInitFunc
)nautilus_zoom_control_accessible_value_interface_init
,
931 (GInterfaceFinalizeFunc
)NULL
,
935 type
= eel_accessibility_create_derived_type
936 ("NautilusZoomControlAccessible",
938 nautilus_zoom_control_accessible_class_init
);
940 g_type_add_interface_static (type
, ATK_TYPE_ACTION
,
942 g_type_add_interface_static (type
, ATK_TYPE_VALUE
,