rename the Client struct to ObClient
[mikachu/openbox.git] / openbox / menu_render.c
1 /* Functions for default rendering of menus. Might become pluginnable */
2
3 #include "menu.h"
4 #include "openbox.h"
5 #include "render/theme.h"
6
7 void menu_render_full(Menu *self);
8
9 void menu_render(Menu *self) {
10     if (self->update) {
11         self->update(self);
12     } else if (self->invalid) {
13         menu_render_full(self);
14     }
15 }
16
17 void menu_render_full(Menu *self) {
18     GList *it;
19     int items_h = 0;
20     int nitems = 0; /* each item, only one is used */
21     int item_y;
22
23     self->size.width = 1;
24     self->item_h = 1;
25
26     if (self->a_title == NULL) {
27         XSetWindowBorderWidth(ob_display, self->frame, ob_rr_theme->bwidth);
28         XSetWindowBackground(ob_display, self->frame,
29                              ob_rr_theme->b_color->pixel);
30         XSetWindowBorderWidth(ob_display, self->title, ob_rr_theme->bwidth);
31         XSetWindowBorder(ob_display, self->frame, ob_rr_theme->b_color->pixel);
32         XSetWindowBorder(ob_display, self->title, ob_rr_theme->b_color->pixel);
33
34         self->a_title = RrAppearanceCopy(ob_rr_theme->a_menu_title);
35         self->a_items = RrAppearanceCopy(ob_rr_theme->a_menu);
36     }
37     
38     /* set texture data and size them mofos out */
39     if (self->label) {
40         self->a_title->texture[0].data.text.string = self->label;
41         RrMinsize(self->a_title, &self->title_min_w, &self->title_h);
42         self->title_min_w += ob_rr_theme->bevel * 2;
43         self->title_h += ob_rr_theme->bevel * 2;
44         self->size.width = MAX(self->size.width, self->title_min_w);
45     }
46
47     for (it = self->entries; it; it = it->next) {
48         MenuEntry *e = it->data;
49         int h;
50
51         if (e->a_item == NULL) {
52             e->a_item = RrAppearanceCopy(ob_rr_theme->a_menu_item);
53             e->a_disabled = RrAppearanceCopy(ob_rr_theme->a_menu_disabled);
54             e->a_hilite = RrAppearanceCopy(ob_rr_theme->a_menu_hilite);
55         }
56
57         e->a_item->texture[0].data.text.string = e->label;
58         RrMinsize(e->a_item, &e->min_w, &self->item_h);
59         self->size.width = MAX(self->size.width, e->min_w);
60
61         e->a_disabled->texture[0].data.text.string = e->label;
62         RrMinsize(e->a_disabled, &e->min_w, &h);
63         self->item_h = MAX(self->item_h, h);
64         self->size.width = MAX(self->size.width, e->min_w);
65         
66         e->a_hilite->texture[0].data.text.string = e->label;
67         RrMinsize(e->a_hilite, &e->min_w, &h);
68         self->item_h = MAX(self->item_h, h);
69         self->size.width = MAX(self->size.width, e->min_w);
70
71         e->min_w += ob_rr_theme->bevel * 2;
72         ++nitems;
73     }
74     self->bullet_w = self->item_h + ob_rr_theme->bevel;
75     self->size.width += 2 * self->bullet_w + 2 * ob_rr_theme->bevel;
76     self->item_h += ob_rr_theme->bevel * 2;
77     items_h = self->item_h * MAX(nitems, 1);
78
79     self->size.height = MAX(self->title_h + items_h + ob_rr_theme->bwidth, 1);
80     XResizeWindow(ob_display, self->frame, self->size.width,self->size.height);
81     if (self->label)
82         XMoveResizeWindow(ob_display, self->title, -ob_rr_theme->bwidth,
83                           -ob_rr_theme->bwidth,
84                           self->size.width, self->title_h);
85
86     XMoveResizeWindow(ob_display, self->items, 0, 
87                       self->title_h + ob_rr_theme->bwidth, self->size.width, 
88                       items_h);
89
90     if (self->label)
91         RrPaint(self->a_title, self->title, self->size.width, self->title_h);
92     RrPaint(self->a_items, self->items, self->size.width, items_h);
93
94     item_y = 0;
95     for (it = self->entries; it; it = it->next) {
96         ((MenuEntry*)it->data)->y = item_y;
97         menu_entry_render(it->data);
98         item_y += self->item_h;
99     }
100     
101     self->invalid = FALSE;
102 }
103
104 void menu_entry_render(MenuEntry *self)
105 {
106     Menu *menu = self->parent;
107     RrAppearance *a;
108     
109     switch (self->render_type) {
110     case MenuEntryRenderType_Submenu:
111         /* TODO: submenu mask */
112     case MenuEntryRenderType_Boolean:
113         /* TODO: boolean check */
114         a = self->enabled ? (self->hilite ? self->a_hilite : self->a_item) 
115             : self->a_disabled;
116         break;
117     case MenuEntryRenderType_None:
118         a = self->enabled ? (self->hilite ? self->a_hilite : self->a_item )
119             : self->a_disabled;
120         break;
121     case MenuEntryRenderType_Separator:
122         a = self->a_item;
123         break;
124
125     default:
126         g_message("unhandled render_type");
127         a = !self->enabled ? self->a_disabled :
128         (self->hilite && 
129          (self->action || self->render_type == MenuEntryRenderType_Submenu) ? 
130          self->a_hilite : self->a_item);
131         break;
132     }
133     g_message ("%s %d", self->label, self->hilite);
134
135     XMoveResizeWindow(ob_display, self->item, 0, self->y,
136                       menu->size.width, menu->item_h);
137
138     a->surface.parent = menu->a_items;
139     a->surface.parentx = 0;
140     a->surface.parenty = self->y;
141
142     RrPaint(a, self->item, menu->size.width, menu->item_h);
143 }