source: golgotha/src/i4/gui/tab_bar.cc @ 608

Last change on this file since 608 was 80, checked in by Sam Hocevar, 15 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 6.5 KB
Line 
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
13struct tab
14{
15  i4_menu_item_class *tab_top;
16  i4_window_class *tab_body;
17  int desired_width;   
18};
19
20enum { 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
29struct 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
45i4_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
54i4_tab_bar::~i4_tab_bar()
55{
56  delete data; 
57 
58}
59
60
61void 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
128void 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
154void 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
173void 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
188void 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}
Note: See TracBrowser for help on using the repository browser.