pull.cc 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  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 "menu/pull.hh"
  9. #include "window/win_evt.hh"
  10. #include "device/device.hh"
  11. #include "device/keys.hh"
  12. i4_pull_menu_class::i4_pull_menu_class(i4_graphical_style_class *style,
  13. i4_parent_window_class *root_window)
  14. : i4_menu_class(i4_F),
  15. menu_colors(*style->color_hint),
  16. root(root_window),
  17. style(style)
  18. {
  19. active_top=0;
  20. active_sub=0;
  21. sub_focused=i4_F;
  22. watching_mouse=i4_F;
  23. menu_colors.selected_text_foreground=i4_read_color_from_resource("selected_menu_foreground");
  24. menu_colors.selected_text_background=i4_read_color_from_resource("selected_menu_background");
  25. }
  26. void i4_pull_menu_class::watch()
  27. {
  28. if (!watching_mouse)
  29. {
  30. watching_mouse=i4_T;
  31. i4_kernel.request_events(this,
  32. i4_device_class::FLAG_KEY_PRESS |
  33. i4_device_class::FLAG_KEY_RELEASE |
  34. i4_device_class::FLAG_MOUSE_BUTTON_DOWN |
  35. i4_device_class::FLAG_MOUSE_BUTTON_UP);
  36. }
  37. }
  38. void i4_pull_menu_class::unwatch()
  39. {
  40. if (watching_mouse)
  41. {
  42. i4_kernel.unrequest_events(this,
  43. i4_device_class::FLAG_KEY_PRESS |
  44. i4_device_class::FLAG_KEY_RELEASE |
  45. i4_device_class::FLAG_MOUSE_BUTTON_DOWN |
  46. i4_device_class::FLAG_MOUSE_BUTTON_UP);
  47. watching_mouse=i4_F;
  48. }
  49. }
  50. i4_pull_menu_class::~i4_pull_menu_class()
  51. {
  52. unwatch();
  53. hide_active();
  54. sub_menus.destroy_all();
  55. }
  56. void i4_pull_menu_class::show_active(i4_menu_item_class *who)
  57. {
  58. win_iter name=children.begin(), sub=sub_menus.begin(), last=sub_menus.end();
  59. while (who!=&*name)
  60. {
  61. last=sub;
  62. ++name;
  63. ++sub;
  64. }
  65. sw32 px,py;
  66. py=who->y()+who->height();
  67. px=who->x();
  68. i4_menu_class *m=((i4_menu_class *)(&*sub));
  69. if (last==sub_menus.end())
  70. sub_menus.erase();
  71. else
  72. sub_menus.erase_after(last);
  73. m->show(root, px-root->x(), py-root->y());
  74. if (sub->height()+sub->y()>root->height())
  75. {
  76. m->hide();
  77. py=who->y()-sub->height();
  78. m->show(root, px-root->x(), py-root->y());
  79. }
  80. if (sub->width()+sub->x()>root->width())
  81. {
  82. m->hide();
  83. px=root->width()-sub->width();
  84. m->show(root, px-root->x(), py-root->y());
  85. }
  86. active_top=who;
  87. active_sub=m;
  88. watch();
  89. }
  90. void i4_pull_menu_class::note_reaction_sent(i4_menu_item_class *who, // this is who sent it
  91. i4_event_reaction_class *ev, // who it was to
  92. i4_menu_item_class::reaction_type type)
  93. {
  94. i4_menu_class::note_reaction_sent(who, ev, type);
  95. if (type==i4_menu_item_class::PRESSED)
  96. {
  97. who->do_depress();
  98. if (!active_sub)
  99. show_active(who);
  100. } else if (type==i4_menu_item_class::ACTIVATED)
  101. {
  102. if (active_sub)
  103. {
  104. hide_active();
  105. show_active(who);
  106. }
  107. active_top=who;
  108. } else if (type==i4_menu_item_class::DEACTIVATED)
  109. {
  110. if (active_sub)
  111. who->do_activate();
  112. }
  113. }
  114. void i4_pull_menu_class::hide_active()
  115. {
  116. if (active_sub)
  117. {
  118. active_sub->hide();
  119. if ((i4_window_class *)active_top==&*children.begin())
  120. sub_menus.insert(*active_sub);
  121. else
  122. {
  123. win_iter s=sub_menus.begin(), t=children.begin();
  124. ++t;
  125. for (;(*&t)!=active_top;)
  126. {
  127. ++s;
  128. ++t;
  129. }
  130. sub_menus.insert_after(s, *active_sub);
  131. }
  132. unwatch();
  133. }
  134. if (active_top)
  135. active_top->do_deactivate();
  136. active_top=0;
  137. active_sub=0;
  138. }
  139. void i4_pull_menu_class::receive_event(i4_event *ev)
  140. {
  141. if (ev->type()==i4_event::OBJECT_MESSAGE)
  142. {
  143. CAST_PTR(lev, i4_menu_focus_event_class, ev);
  144. if (lev->focus_state==i4_menu_focus_event_class::lost_focus)
  145. sub_focused=i4_F;
  146. else
  147. sub_focused=i4_T;
  148. }
  149. else if (ev->type()==i4_event::WINDOW_MESSAGE)
  150. {
  151. CAST_PTR(wev, i4_window_message_class, ev);
  152. if (wev->sub_type==i4_window_message_class::LOST_MOUSE_FOCUS)
  153. focused=i4_F;
  154. else if (wev->sub_type==i4_window_message_class::GOT_MOUSE_FOCUS)
  155. focused=i4_T;
  156. i4_menu_class::receive_event(ev);
  157. }
  158. else if (ev->type()==i4_event::MOUSE_BUTTON_DOWN ||
  159. ev->type()==i4_event::MOUSE_BUTTON_UP)
  160. {
  161. if (!focused && !sub_focused)
  162. hide_active();
  163. if (focused)
  164. i4_menu_class::receive_event(ev);
  165. }
  166. else if (ev->type()==i4_event::KEY_PRESS)
  167. {
  168. CAST_PTR(kev, i4_key_press_event_class, ev);
  169. if (kev->key_code==I4_ESC)
  170. hide_active();
  171. else
  172. i4_menu_class::receive_event(ev);
  173. }
  174. else if (focused)
  175. i4_menu_class::receive_event(ev);
  176. }
  177. void i4_pull_menu_class::parent_draw(i4_draw_context_class &context)
  178. {
  179. i4_rect_list_class child_clip(&context.clip,0,0);
  180. child_clip.intersect_list(&undrawn_area);
  181. child_clip.swap(&context.clip);
  182. style->deco_neutral_fill(local_image, 0,0, width()-1, height()-1, context);
  183. // local_image->clear(menu_colors.text_background,context);
  184. child_clip.swap(&context.clip);
  185. i4_parent_window_class::parent_draw(context);
  186. }
  187. void i4_pull_menu_class::add_sub_menu(i4_menu_item_class *name,
  188. i4_menu_class *sub_menu)
  189. {
  190. add_item(name);
  191. name->set_menu_parent(this);
  192. sub_menu->notify_focus_change(this);
  193. sub_menus.insert_end(*sub_menu);
  194. reparent(local_image, parent);
  195. }
  196. void i4_pull_menu_class::reparent(i4_image_class *draw_area, i4_parent_window_class *parent)
  197. {
  198. i4_parent_window_class::reparent(draw_area, parent);
  199. if (parent)
  200. {
  201. resize(parent->width(), 0);
  202. arrange_right_down();
  203. w32 max_h=0;
  204. for (win_iter c=children.begin(); c!=children.end(); ++c)
  205. if (c->y()-y()+c->height()>max_h)
  206. max_h=c->y()-y()+c->height();
  207. resize(parent->width(), max_h);
  208. }
  209. }
  210. void i4_pull_menu_class::resize(w16 new_width, w16 new_height)
  211. {
  212. i4_window_class::resize(new_width, new_height);
  213. arrange_right_down();
  214. }
  215. void i4_pull_menu_class::hide()
  216. {
  217. if (parent)
  218. {
  219. parent->remove_child(this);
  220. hide_active();
  221. }
  222. parent=0;
  223. }