tab_bar.cc 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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. #include "gui/tab_bar.hh"
  9. #include "memory/array.hh"
  10. #include "window/style.hh"
  11. struct tab
  12. {
  13. i4_menu_item_class *tab_top;
  14. i4_window_class *tab_body;
  15. int desired_width;
  16. };
  17. enum { LEFT_SPACING=5,
  18. RIGHT_SPACING=5,
  19. TAB_TOP_MARGIN=6,
  20. TAB_BOTTOM_MARGIN=4,
  21. TAB_LEFT_MARGIN=3,
  22. TAB_RIGHT_MARGIN=3 };
  23. struct i4_tab_bar_data
  24. {
  25. i4_array<tab> tabs;
  26. int current_tab;
  27. int top_height;
  28. i4_graphical_style_class *style;
  29. i4_tab_bar_data()
  30. : tabs(0,8)
  31. {
  32. top_height=0;
  33. }
  34. };
  35. i4_tab_bar::i4_tab_bar(int width, int height, i4_graphical_style_class *style)
  36. : i4_menu_class(i4_F)
  37. {
  38. data=new i4_tab_bar_data();
  39. data->style=style;
  40. private_resize(width, height);
  41. }
  42. i4_tab_bar::~i4_tab_bar()
  43. {
  44. delete data;
  45. }
  46. void i4_tab_bar::private_resize(w16 new_width, w16 new_height)
  47. {
  48. i4_parent_window_class::private_resize(new_width, new_height);
  49. if (!data->tabs.size())
  50. return ;
  51. int i, t_tabs=data->tabs.size();
  52. remove_child(data->tabs[data->current_tab].tab_body);
  53. for (i=0; i<t_tabs; i++)
  54. remove_child(data->tabs[i].tab_top);
  55. int available_size=width()-LEFT_SPACING-RIGHT_SPACING-t_tabs*(TAB_LEFT_MARGIN+TAB_RIGHT_MARGIN);
  56. int suggested_size=available_size / t_tabs;
  57. int leftover_size=0;
  58. for (i=0; i<t_tabs; i++)
  59. if (data->tabs[i].desired_width<suggested_size)
  60. leftover_size+=suggested_size-data->tabs[i].desired_width;
  61. leftover_size+=available_size-suggested_size*t_tabs;
  62. int client_w=width()-4;
  63. int client_h=height()-data->top_height-TAB_TOP_MARGIN-TAB_BOTTOM_MARGIN;
  64. int xpos=LEFT_SPACING + TAB_LEFT_MARGIN;
  65. int ypos=TAB_TOP_MARGIN-2;
  66. for (i=0; i<t_tabs; i++)
  67. {
  68. int new_w=suggested_size;
  69. int additional_size_needed=data->tabs[i].desired_width-suggested_size;
  70. if (additional_size_needed>0)
  71. {
  72. if (additional_size_needed>leftover_size)
  73. {
  74. new_w=suggested_size+leftover_size;
  75. leftover_size=0;
  76. }
  77. else
  78. {
  79. leftover_size-=additional_size_needed;
  80. new_w=data->tabs[i].desired_width;
  81. }
  82. }
  83. else new_w=data->tabs[i].desired_width;
  84. data->tabs[i].tab_top->resize(new_w, data->top_height);
  85. i4_parent_window_class::add_child(xpos, ypos, data->tabs[i].tab_top);
  86. data->tabs[i].tab_body->resize(client_w, client_h);
  87. if (i==data->current_tab)
  88. i4_parent_window_class::add_child(2, data->top_height+TAB_TOP_MARGIN, data->tabs[i].tab_body);
  89. xpos+=new_w+TAB_LEFT_MARGIN+TAB_RIGHT_MARGIN;
  90. }
  91. }
  92. void i4_tab_bar::add_tab(i4_menu_item_class *tab_top, i4_window_class *tab_body)
  93. {
  94. i4_parent_window_class::add_child(0,0, tab_top);
  95. if (!data->tabs.size())
  96. {
  97. data->current_tab=0;
  98. i4_parent_window_class::add_child(0,0, tab_body);
  99. }
  100. if (tab_top->height()>data->top_height)
  101. data->top_height=tab_top->height();
  102. tab t;
  103. t.tab_top=tab_top;
  104. t.tab_body=tab_body;
  105. t.desired_width=tab_top->width();
  106. data->tabs.add(t);
  107. tab_top->set_menu_parent(this);
  108. resize(width(), height());
  109. }
  110. void i4_tab_bar::set_current_tab(int tab_number)
  111. {
  112. if (!data->tabs.size() || tab_number==data->current_tab)
  113. return ;
  114. i4_window_class *client=data->tabs[data->current_tab].tab_body;
  115. int cx=client->x()-x(), cy=client->y()-y();
  116. remove_child(client);
  117. if (tab_number<0) tab_number=0;
  118. if (tab_number>=data->tabs.size())
  119. tab_number=data->tabs.size()-1;
  120. data->current_tab=tab_number;
  121. i4_parent_window_class::add_child(cx, cy, data->tabs[tab_number].tab_body);
  122. }
  123. void i4_tab_bar::note_reaction_sent(i4_menu_item_class *who,
  124. i4_event_reaction_class *ev,
  125. i4_menu_item_class::reaction_type type)
  126. {
  127. if (type==i4_menu_item_class::PRESSED)
  128. {
  129. for (int i=0; i<data->tabs.size(); i++)
  130. if (who==data->tabs[i].tab_top)
  131. set_current_tab(i);
  132. }
  133. }
  134. void i4_tab_bar::parent_draw(i4_draw_context_class &context)
  135. {
  136. data->style->deco_neutral_fill(local_image, 0,0, width()-1, height()-1, context);
  137. w32 black=0,
  138. bright=data->style->color_hint->button.passive.bright,
  139. med=data->style->color_hint->button.passive.medium,
  140. dark=data->style->color_hint->button.passive.dark;
  141. i4_image_class *im=local_image;
  142. int dx=LEFT_SPACING, dy=0;
  143. int cur=data->current_tab;
  144. int client_y=TAB_TOP_MARGIN+data->top_height;
  145. int client_h=data->tabs[0].tab_body->height();
  146. im->bar(0, client_y-2, width()-1, client_y-2, bright, context);
  147. im->bar(1, client_y-1, width()-2, client_y-1, med, context);
  148. im->bar(0, client_y-2, 0, client_y+client_h+2, bright, context);
  149. im->bar(1, client_y-1, 1, client_y+client_h+1, med, context);
  150. im->bar(width()-2, client_y, width()-2, client_y+client_h+1, dark, context);
  151. im->bar(width()-1, client_y-1, width()-1, client_y+client_h+2, black, context);
  152. im->bar(2, client_y+client_h+1, width()-2, client_y+client_h+1, dark, context);
  153. im->bar(1, client_y+client_h+2, width()-1, client_y+client_h+2, black, context);
  154. for (int i=0; i<data->tabs.size(); i++)
  155. {
  156. int x1=dx, y1=dy+2, x2=dx+data->tabs[i].tab_top->width()+TAB_LEFT_MARGIN+TAB_RIGHT_MARGIN-1,
  157. y2=dy+TAB_TOP_MARGIN+data->top_height-3;
  158. if (i==cur)
  159. {
  160. y1-=2;
  161. y2+=2;
  162. x1+=1;
  163. x2+=1;
  164. }
  165. if (i-1!=cur)
  166. im->bar(x1, y1+2, x1, y2, bright, context); // left edge
  167. im->bar(x1+1, y1+1, x1+1, y1+1, bright, context); // round off left edge to top
  168. im->bar(x1+2, y1, x2-(i+1==cur ? 1 : 2), y1, bright, context); // top edge
  169. if (i+1!=cur)
  170. {
  171. im->bar(x2-1, y1, x2-1, y2, dark, context);
  172. im->bar(x2, y1+1, x2, y2, black, context);
  173. }
  174. if (i==cur)
  175. data->style->deco_neutral_fill(im, x1+1, y2-2, x2-2, y2, context);
  176. dx+=data->tabs[i].tab_top->width()+TAB_LEFT_MARGIN+TAB_RIGHT_MARGIN;
  177. }
  178. }