1 | /********************************************************************** <BR>
|
---|
2 | This file is part of Crack dot Com's free source code release of
|
---|
3 | Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
|
---|
4 | information about compiling & licensing issues visit this URL</a>
|
---|
5 | <PRE> If that doesn't help, contact Jonathan Clark at
|
---|
6 | golgotha_source@usa.net (Subject should have "GOLG" in it)
|
---|
7 | ***********************************************************************/
|
---|
8 |
|
---|
9 | #include "gui/tab_bar.hh"
|
---|
10 | #include "memory/array.hh"
|
---|
11 | #include "window/style.hh"
|
---|
12 |
|
---|
13 | struct tab
|
---|
14 | {
|
---|
15 | i4_menu_item_class *tab_top;
|
---|
16 | i4_window_class *tab_body;
|
---|
17 | int desired_width;
|
---|
18 | };
|
---|
19 |
|
---|
20 | enum { LEFT_SPACING=5,
|
---|
21 | RIGHT_SPACING=5,
|
---|
22 | TAB_TOP_MARGIN=6,
|
---|
23 | TAB_BOTTOM_MARGIN=4,
|
---|
24 | TAB_LEFT_MARGIN=3,
|
---|
25 | TAB_RIGHT_MARGIN=3 };
|
---|
26 |
|
---|
27 |
|
---|
28 |
|
---|
29 | struct i4_tab_bar_data
|
---|
30 | {
|
---|
31 | i4_array<tab> tabs;
|
---|
32 | int current_tab;
|
---|
33 | int top_height;
|
---|
34 | i4_graphical_style_class *style;
|
---|
35 |
|
---|
36 | i4_tab_bar_data()
|
---|
37 | : tabs(0,8)
|
---|
38 | {
|
---|
39 | top_height=0;
|
---|
40 | }
|
---|
41 |
|
---|
42 | };
|
---|
43 |
|
---|
44 |
|
---|
45 | i4_tab_bar::i4_tab_bar(int width, int height, i4_graphical_style_class *style)
|
---|
46 | : i4_menu_class(i4_F)
|
---|
47 | {
|
---|
48 | data=new i4_tab_bar_data();
|
---|
49 | data->style=style;
|
---|
50 | private_resize(width, height);
|
---|
51 |
|
---|
52 | }
|
---|
53 |
|
---|
54 | i4_tab_bar::~i4_tab_bar()
|
---|
55 | {
|
---|
56 | delete data;
|
---|
57 |
|
---|
58 | }
|
---|
59 |
|
---|
60 |
|
---|
61 | void i4_tab_bar::private_resize(w16 new_width, w16 new_height)
|
---|
62 | {
|
---|
63 | i4_parent_window_class::private_resize(new_width, new_height);
|
---|
64 | if (!data->tabs.size())
|
---|
65 | return ;
|
---|
66 |
|
---|
67 |
|
---|
68 | int i, t_tabs=data->tabs.size();
|
---|
69 | remove_child(data->tabs[data->current_tab].tab_body);
|
---|
70 |
|
---|
71 | for (i=0; i<t_tabs; i++)
|
---|
72 | remove_child(data->tabs[i].tab_top);
|
---|
73 |
|
---|
74 |
|
---|
75 |
|
---|
76 |
|
---|
77 | int available_size=width()-LEFT_SPACING-RIGHT_SPACING-t_tabs*(TAB_LEFT_MARGIN+TAB_RIGHT_MARGIN);
|
---|
78 |
|
---|
79 | int suggested_size=available_size / t_tabs;
|
---|
80 | int leftover_size=0;
|
---|
81 |
|
---|
82 | for (i=0; i<t_tabs; i++)
|
---|
83 | if (data->tabs[i].desired_width<suggested_size)
|
---|
84 | leftover_size+=suggested_size-data->tabs[i].desired_width;
|
---|
85 |
|
---|
86 | leftover_size+=available_size-suggested_size*t_tabs;
|
---|
87 |
|
---|
88 |
|
---|
89 | int client_w=width()-4;
|
---|
90 | int client_h=height()-data->top_height-TAB_TOP_MARGIN-TAB_BOTTOM_MARGIN;
|
---|
91 |
|
---|
92 | int xpos=LEFT_SPACING + TAB_LEFT_MARGIN;
|
---|
93 | int ypos=TAB_TOP_MARGIN-2;
|
---|
94 | for (i=0; i<t_tabs; i++)
|
---|
95 | {
|
---|
96 | int new_w=suggested_size;
|
---|
97 |
|
---|
98 | int additional_size_needed=data->tabs[i].desired_width-suggested_size;
|
---|
99 | if (additional_size_needed>0)
|
---|
100 | {
|
---|
101 | if (additional_size_needed>leftover_size)
|
---|
102 | {
|
---|
103 | new_w=suggested_size+leftover_size;
|
---|
104 | leftover_size=0;
|
---|
105 | }
|
---|
106 | else
|
---|
107 | {
|
---|
108 | leftover_size-=additional_size_needed;
|
---|
109 | new_w=data->tabs[i].desired_width;
|
---|
110 | }
|
---|
111 | }
|
---|
112 | else new_w=data->tabs[i].desired_width;
|
---|
113 |
|
---|
114 |
|
---|
115 | data->tabs[i].tab_top->resize(new_w, data->top_height);
|
---|
116 | i4_parent_window_class::add_child(xpos, ypos, data->tabs[i].tab_top);
|
---|
117 |
|
---|
118 | data->tabs[i].tab_body->resize(client_w, client_h);
|
---|
119 | if (i==data->current_tab)
|
---|
120 | i4_parent_window_class::add_child(2, data->top_height+TAB_TOP_MARGIN, data->tabs[i].tab_body);
|
---|
121 |
|
---|
122 | xpos+=new_w+TAB_LEFT_MARGIN+TAB_RIGHT_MARGIN;
|
---|
123 | }
|
---|
124 | }
|
---|
125 |
|
---|
126 |
|
---|
127 |
|
---|
128 | void i4_tab_bar::add_tab(i4_menu_item_class *tab_top, i4_window_class *tab_body)
|
---|
129 | {
|
---|
130 | i4_parent_window_class::add_child(0,0, tab_top);
|
---|
131 | if (!data->tabs.size())
|
---|
132 | {
|
---|
133 | data->current_tab=0;
|
---|
134 | i4_parent_window_class::add_child(0,0, tab_body);
|
---|
135 | }
|
---|
136 |
|
---|
137 | if (tab_top->height()>data->top_height)
|
---|
138 | data->top_height=tab_top->height();
|
---|
139 |
|
---|
140 |
|
---|
141 | tab t;
|
---|
142 | t.tab_top=tab_top;
|
---|
143 | t.tab_body=tab_body;
|
---|
144 | t.desired_width=tab_top->width();
|
---|
145 | data->tabs.add(t);
|
---|
146 |
|
---|
147 | tab_top->set_menu_parent(this);
|
---|
148 |
|
---|
149 | resize(width(), height());
|
---|
150 | }
|
---|
151 |
|
---|
152 |
|
---|
153 |
|
---|
154 | void i4_tab_bar::set_current_tab(int tab_number)
|
---|
155 | {
|
---|
156 | if (!data->tabs.size() || tab_number==data->current_tab)
|
---|
157 | return ;
|
---|
158 |
|
---|
159 | i4_window_class *client=data->tabs[data->current_tab].tab_body;
|
---|
160 | int cx=client->x()-x(), cy=client->y()-y();
|
---|
161 |
|
---|
162 |
|
---|
163 | remove_child(client);
|
---|
164 | if (tab_number<0) tab_number=0;
|
---|
165 | if (tab_number>=data->tabs.size())
|
---|
166 | tab_number=data->tabs.size()-1;
|
---|
167 |
|
---|
168 | data->current_tab=tab_number;
|
---|
169 | i4_parent_window_class::add_child(cx, cy, data->tabs[tab_number].tab_body);
|
---|
170 | }
|
---|
171 |
|
---|
172 |
|
---|
173 | void i4_tab_bar::note_reaction_sent(i4_menu_item_class *who,
|
---|
174 | i4_event_reaction_class *ev,
|
---|
175 | i4_menu_item_class::reaction_type type)
|
---|
176 | {
|
---|
177 | if (type==i4_menu_item_class::PRESSED)
|
---|
178 | {
|
---|
179 | for (int i=0; i<data->tabs.size(); i++)
|
---|
180 | if (who==data->tabs[i].tab_top)
|
---|
181 | set_current_tab(i);
|
---|
182 | }
|
---|
183 | }
|
---|
184 |
|
---|
185 |
|
---|
186 |
|
---|
187 |
|
---|
188 | void i4_tab_bar::parent_draw(i4_draw_context_class &context)
|
---|
189 | {
|
---|
190 | data->style->deco_neutral_fill(local_image, 0,0, width()-1, height()-1, context);
|
---|
191 |
|
---|
192 |
|
---|
193 | w32 black=0,
|
---|
194 | bright=data->style->color_hint->button.passive.bright,
|
---|
195 | med=data->style->color_hint->button.passive.medium,
|
---|
196 | dark=data->style->color_hint->button.passive.dark;
|
---|
197 |
|
---|
198 | i4_image_class *im=local_image;
|
---|
199 |
|
---|
200 | int dx=LEFT_SPACING, dy=0;
|
---|
201 | int cur=data->current_tab;
|
---|
202 |
|
---|
203 |
|
---|
204 | int client_y=TAB_TOP_MARGIN+data->top_height;
|
---|
205 | int client_h=data->tabs[0].tab_body->height();
|
---|
206 |
|
---|
207 | im->bar(0, client_y-2, width()-1, client_y-2, bright, context);
|
---|
208 | im->bar(1, client_y-1, width()-2, client_y-1, med, context);
|
---|
209 |
|
---|
210 | im->bar(0, client_y-2, 0, client_y+client_h+2, bright, context);
|
---|
211 | im->bar(1, client_y-1, 1, client_y+client_h+1, med, context);
|
---|
212 |
|
---|
213 | im->bar(width()-2, client_y, width()-2, client_y+client_h+1, dark, context);
|
---|
214 | im->bar(width()-1, client_y-1, width()-1, client_y+client_h+2, black, context);
|
---|
215 |
|
---|
216 | im->bar(2, client_y+client_h+1, width()-2, client_y+client_h+1, dark, context);
|
---|
217 | im->bar(1, client_y+client_h+2, width()-1, client_y+client_h+2, black, context);
|
---|
218 |
|
---|
219 |
|
---|
220 |
|
---|
221 | for (int i=0; i<data->tabs.size(); i++)
|
---|
222 | {
|
---|
223 | int x1=dx, y1=dy+2, x2=dx+data->tabs[i].tab_top->width()+TAB_LEFT_MARGIN+TAB_RIGHT_MARGIN-1,
|
---|
224 | y2=dy+TAB_TOP_MARGIN+data->top_height-3;
|
---|
225 |
|
---|
226 | if (i==cur)
|
---|
227 | {
|
---|
228 | y1-=2;
|
---|
229 | y2+=2;
|
---|
230 | x1+=1;
|
---|
231 | x2+=1;
|
---|
232 | }
|
---|
233 |
|
---|
234 | if (i-1!=cur)
|
---|
235 | im->bar(x1, y1+2, x1, y2, bright, context); // left edge
|
---|
236 | im->bar(x1+1, y1+1, x1+1, y1+1, bright, context); // round off left edge to top
|
---|
237 |
|
---|
238 |
|
---|
239 | im->bar(x1+2, y1, x2-(i+1==cur ? 1 : 2), y1, bright, context); // top edge
|
---|
240 |
|
---|
241 |
|
---|
242 | if (i+1!=cur)
|
---|
243 | {
|
---|
244 | im->bar(x2-1, y1, x2-1, y2, dark, context);
|
---|
245 | im->bar(x2, y1+1, x2, y2, black, context);
|
---|
246 | }
|
---|
247 |
|
---|
248 | if (i==cur)
|
---|
249 | data->style->deco_neutral_fill(im, x1+1, y2-2, x2-2, y2, context);
|
---|
250 |
|
---|
251 | dx+=data->tabs[i].tab_top->width()+TAB_LEFT_MARGIN+TAB_RIGHT_MARGIN;
|
---|
252 | }
|
---|
253 | }
|
---|