~lightdm-gtk-greeter-team/lightdm-gtk-greeter/trunk

« back to all changes in this revision

Viewing changes to src/greetermenubar.c

  • Committer: Lionel Le Folgoc
  • Date: 2012-10-22 17:04:16 UTC
  • Revision ID: mrpouit@ubuntu.com-20121022170416-yczkln2fcytglcej
Generate a proper changelog during dist

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#include <gtk/gtk.h>
2
 
#include "greetermenubar.h"
3
 
 
4
 
static void greeter_menu_bar_size_allocate(GtkWidget* widget, GtkAllocation* allocation);
5
 
 
6
 
G_DEFINE_TYPE(GreeterMenuBar, greeter_menu_bar, GTK_TYPE_MENU_BAR);
7
 
 
8
 
static void
9
 
greeter_menu_bar_class_init(GreeterMenuBarClass* klass)
10
 
{
11
 
        GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
12
 
        widget_class->size_allocate = greeter_menu_bar_size_allocate;
13
 
}
14
 
 
15
 
static void
16
 
greeter_menu_bar_init(GreeterMenuBar* square)
17
 
{
18
 
 
19
 
}
20
 
 
21
 
GtkWidget*
22
 
greeter_menu_bar_new(void)
23
 
{
24
 
        return GTK_WIDGET(g_object_new(greeter_menu_bar_get_type(), NULL));
25
 
}
26
 
 
27
 
static gint
28
 
sort_minimal_size(gconstpointer a, gconstpointer b, GtkRequestedSize* sizes)
29
 
{
30
 
    gint a_size = sizes[GPOINTER_TO_INT(a)].natural_size;
31
 
    gint b_size = sizes[GPOINTER_TO_INT(b)].natural_size;
32
 
    return a_size == b_size ? 0 : a_size > b_size ? -1 : +1;
33
 
}
34
 
 
35
 
static void
36
 
greeter_menu_bar_size_allocate(GtkWidget* widget, GtkAllocation* allocation)
37
 
{
38
 
        GtkPackDirection  pack_direction;
39
 
    GList                        *item;
40
 
    GList                        *shell_children;
41
 
    GList                        *expand_nums = NULL;
42
 
    guint                         visible_count = 0;
43
 
        guint                     expand_count = 0;
44
 
 
45
 
        g_return_if_fail(allocation != NULL);
46
 
        g_return_if_fail(GREETER_IS_MENU_BAR(widget));
47
 
 
48
 
    gtk_widget_set_allocation(widget, allocation);
49
 
 
50
 
    pack_direction = gtk_menu_bar_get_pack_direction(GTK_MENU_BAR(widget));
51
 
    g_return_if_fail(pack_direction == GTK_PACK_DIRECTION_LTR || pack_direction == GTK_PACK_DIRECTION_RTL);
52
 
 
53
 
    shell_children = gtk_container_get_children(GTK_CONTAINER(widget));
54
 
 
55
 
    for(item = shell_children; item; item = g_list_next(item))
56
 
        if(gtk_widget_get_visible(item->data))
57
 
        {
58
 
            if(gtk_widget_compute_expand(item->data, GTK_ORIENTATION_HORIZONTAL))
59
 
            {
60
 
                expand_nums = g_list_prepend(expand_nums, GINT_TO_POINTER(visible_count));
61
 
                expand_count++;
62
 
            }
63
 
            visible_count++;
64
 
        }
65
 
 
66
 
    if(gtk_widget_get_realized(widget))
67
 
        gdk_window_move_resize(gtk_widget_get_window(widget),
68
 
                               allocation->x, allocation->y,
69
 
                               allocation->width, allocation->height);
70
 
 
71
 
    if(visible_count > 0)
72
 
    {
73
 
        GtkAllocation remaining_space;
74
 
        GtkStyleContext* context = gtk_widget_get_style_context(widget);
75
 
        GtkStateFlags flags = gtk_widget_get_state_flags(widget);
76
 
        GtkRequestedSize* requested_sizes = g_newa(GtkRequestedSize, visible_count);
77
 
        guint border_width = gtk_container_get_border_width(GTK_CONTAINER(widget));
78
 
        GtkShadowType shadow_type = GTK_SHADOW_OUT;
79
 
        GtkBorder border;
80
 
        gint toggle_size;
81
 
                GtkRequestedSize* request;
82
 
                gboolean ltr;
83
 
                int size;
84
 
 
85
 
        gtk_style_context_get_padding(context, flags, &border);
86
 
        gtk_widget_style_get(widget, "shadow-type", &shadow_type, NULL);
87
 
 
88
 
        remaining_space.x = (border_width + border.left);
89
 
        remaining_space.y = (border_width + border.top);
90
 
        remaining_space.width = allocation->width -
91
 
                                2 * border_width - border.left - border.right;
92
 
        remaining_space.height = allocation->height -
93
 
                                 2 * border_width - border.top - border.bottom;
94
 
 
95
 
        if (shadow_type != GTK_SHADOW_NONE)
96
 
        {
97
 
            gtk_style_context_get_border(context, flags, &border);
98
 
 
99
 
            remaining_space.x += border.left;
100
 
            remaining_space.y += border.top;
101
 
            remaining_space.width -= border.left + border.right;
102
 
            remaining_space.height -= border.top + border.bottom;
103
 
        }
104
 
 
105
 
        request = requested_sizes;
106
 
        size = remaining_space.width;
107
 
        ltr = (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_LTR) == (pack_direction == GTK_PACK_DIRECTION_LTR);
108
 
 
109
 
        for(item = shell_children; item; item = g_list_next(item))
110
 
        {
111
 
            if (!gtk_widget_get_visible(item->data))
112
 
                continue;
113
 
 
114
 
            request->data = item->data;
115
 
            gtk_widget_get_preferred_width_for_height(item->data, remaining_space.height,
116
 
                    &request->minimum_size,
117
 
                    &request->natural_size);
118
 
            gtk_menu_item_toggle_size_request(GTK_MENU_ITEM(item->data),
119
 
                                              &toggle_size);
120
 
            request->minimum_size += toggle_size;
121
 
            request->natural_size += toggle_size;
122
 
 
123
 
            gtk_menu_item_toggle_size_allocate(GTK_MENU_ITEM(item->data), toggle_size);
124
 
 
125
 
            size -= request->minimum_size;
126
 
            request++;
127
 
        }
128
 
 
129
 
        size = gtk_distribute_natural_allocation(size, visible_count, requested_sizes);
130
 
 
131
 
        /* Distribution extra space for widgets with expand=True */
132
 
        if(size > 0 && expand_nums)
133
 
        {
134
 
                        GList *first_item = NULL;
135
 
            gint   needed_size = -1;
136
 
            gint   max_size = 0;
137
 
            gint   total_needed_size = 0;
138
 
 
139
 
            expand_nums = g_list_sort_with_data(expand_nums, (GCompareDataFunc)sort_minimal_size,
140
 
                                                requested_sizes);
141
 
            first_item = expand_nums;
142
 
            max_size = requested_sizes[GPOINTER_TO_INT(first_item->data)].natural_size;
143
 
 
144
 
            /* Free space that all widgets need to have the same (max_size) width
145
 
             * [___max_width___][widget         ][widget____     ]
146
 
             * total_needed_size := [] + [         ] + [     ]
147
 
             * total_needed_size = [              ]
148
 
             */
149
 
            for(item = g_list_next(expand_nums); item; item = g_list_next(item))
150
 
                total_needed_size += max_size - requested_sizes[GPOINTER_TO_INT(item->data)].natural_size;
151
 
 
152
 
            while(first_item)
153
 
            {
154
 
                if(size >= total_needed_size)
155
 
                {
156
 
                    /* total_needed_size is enough for all remaining widgets */
157
 
                    needed_size = max_size + (size - total_needed_size)/expand_count;
158
 
                    break;
159
 
                }
160
 
                /* Removing current maximal widget from list */
161
 
                total_needed_size -= max_size - requested_sizes[GPOINTER_TO_INT(first_item->data)].natural_size;
162
 
                first_item = g_list_next(first_item);
163
 
                if(first_item)
164
 
                    max_size = requested_sizes[GPOINTER_TO_INT(first_item->data)].natural_size;
165
 
            }
166
 
 
167
 
            for(item = first_item; item; item = g_list_next(item))
168
 
            {
169
 
                                gint dsize = 0;
170
 
 
171
 
                request = &requested_sizes[GPOINTER_TO_INT(item->data)];
172
 
                dsize = needed_size - request->natural_size;
173
 
                if(size < dsize)
174
 
                    dsize = size;
175
 
                size -= dsize;
176
 
                request->natural_size += dsize;
177
 
            }
178
 
        }
179
 
 
180
 
 
181
 
        for(guint i = 0; i < visible_count; i++)
182
 
        {
183
 
            GtkAllocation child_allocation = remaining_space;
184
 
            request = &requested_sizes[i];
185
 
 
186
 
            child_allocation.width = request->natural_size;
187
 
            remaining_space.width -= request->natural_size;
188
 
            if (ltr)
189
 
                remaining_space.x += request->natural_size;
190
 
            else
191
 
                child_allocation.x += remaining_space.width;
192
 
            gtk_widget_size_allocate(request->data, &child_allocation);
193
 
        }
194
 
        g_list_free(expand_nums);
195
 
    }
196
 
    g_list_free(shell_children);
197
 
}