key_item.cc 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  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 "device/keys.hh"
  9. #include "menu/key_item.hh"
  10. #include "window/win_evt.hh"
  11. static i4_key_accel_watcher_class i4_key_accel_watcher_instance;
  12. enum { key_space=5 };
  13. i4_key_item_class::~i4_key_item_class()
  14. {
  15. delete text;
  16. if (use_key!=I4_NO_KEY)
  17. i4_key_accel_watcher_instance.unwatch_key(this, use_key, key_modifiers);
  18. }
  19. i4_key_item_class::i4_key_item_class(const i4_const_str &_text,
  20. i4_color_hint_class *color_hint,
  21. i4_font_hint_class *font_hint,
  22. i4_graphical_style_class *style,
  23. w16 key,
  24. w16 key_modifiers,
  25. w16 pad_left_right,
  26. w16 pad_up_down
  27. )
  28. : i4_menu_item_class(0,
  29. style,
  30. font_hint->normal_font->width(_text)+pad_left_right*2,
  31. font_hint->normal_font->height(_text)+pad_up_down*2,
  32. 0,0,0,0),
  33. key_modifiers(key_modifiers),
  34. color(color_hint),
  35. font(font_hint),
  36. text(new i4_str(_text,_text.length()+1)),
  37. pad_lr(pad_left_right),
  38. pad_ud(pad_up_down),
  39. use_key(key)
  40. {
  41. key_focused=i4_F;
  42. valid=i4_T;
  43. w32 add_width=0;
  44. i4_font_class *fnt=font_hint->normal_font;
  45. if (key!=I4_NO_KEY)
  46. {
  47. i4_key_accel_watcher_instance.watch_key(this, key, key_modifiers);
  48. i4_str *key_name=i4_key_name(key, key_modifiers);
  49. add_width=fnt->width(*key_name)+key_space;
  50. delete key_name;
  51. }
  52. resize(fnt->width(_text) + add_width + pad_left_right*2,
  53. fnt->height(_text) + pad_up_down*2);
  54. }
  55. void i4_key_item_class::receive_event(i4_event *ev)
  56. {
  57. if (ev->type()==i4_event::MOUSE_BUTTON_DOWN)
  58. {
  59. CAST_PTR(b,i4_mouse_button_down_event_class,ev);
  60. if (b->but==i4_mouse_button_down_event_class::LEFT)
  61. {
  62. do_depress();
  63. send_event(send.depress, PRESSED);
  64. action();
  65. }
  66. else i4_menu_item_class::receive_event(ev);
  67. } else if (ev->type()==i4_event::KEY_PRESS)
  68. {
  69. CAST_PTR(k,i4_key_press_event_class,ev);
  70. if (k->modifiers & I4_MODIFIER_CTRL)
  71. k->modifiers |= I4_MODIFIER_CTRL;
  72. if (k->modifiers & I4_MODIFIER_ALT)
  73. k->modifiers |= I4_MODIFIER_ALT;
  74. if (k->modifiers & I4_MODIFIER_SHIFT)
  75. k->modifiers |= I4_MODIFIER_SHIFT;
  76. if (k->key_code==use_key && k->modifiers==key_modifiers)
  77. action();
  78. else if (k->key==I4_ENTER)
  79. {
  80. do_depress();
  81. send_event(send.depress, PRESSED);
  82. action();
  83. }
  84. else if (k->key==I4_TAB)
  85. {
  86. i4_window_message_class nf(i4_window_message_class::REQUEST_NEXT_KEY_FOCUS,this);
  87. i4_kernel.send_event(parent, &nf);
  88. }
  89. else if (k->key==I4_LEFT)
  90. {
  91. i4_window_message_class l(i4_window_message_class::REQUEST_LEFT_KEY_FOCUS,this);
  92. i4_kernel.send_event(parent, &l);
  93. }
  94. else if (k->key==I4_RIGHT)
  95. {
  96. i4_window_message_class r(i4_window_message_class::REQUEST_RIGHT_KEY_FOCUS,this);
  97. i4_kernel.send_event(parent, &r);
  98. }
  99. else if (k->key==I4_UP)
  100. {
  101. i4_window_message_class u(i4_window_message_class::REQUEST_UP_KEY_FOCUS,this);
  102. i4_kernel.send_event(parent, &u);
  103. }
  104. else if (k->key==I4_DOWN)
  105. {
  106. i4_window_message_class d(i4_window_message_class::REQUEST_DOWN_KEY_FOCUS,this);
  107. i4_kernel.send_event(parent, &d);
  108. }
  109. else
  110. i4_menu_item_class::receive_event(ev);
  111. }
  112. else if (ev->type()==i4_event::WINDOW_MESSAGE)
  113. {
  114. CAST_PTR(wev, i4_window_message_class, ev);
  115. if (wev->sub_type==i4_window_message_class::GOT_KEYBOARD_FOCUS)
  116. key_focused=i4_T;
  117. else if (wev->sub_type==i4_window_message_class::LOST_KEYBOARD_FOCUS)
  118. key_focused=i4_F;
  119. else if (wev->sub_type==i4_window_message_class::NOTIFY_RESIZE)
  120. {
  121. CAST_PTR(rev, i4_window_notify_resize_class, ev);
  122. if (rev->from()==parent)
  123. {
  124. w32 nw=rev->new_width-(x()-parent->x())*2;
  125. if (nw!=width())
  126. resize(nw, height());
  127. }
  128. }
  129. i4_menu_item_class::receive_event(ev);
  130. }
  131. else
  132. i4_menu_item_class::receive_event(ev);
  133. }
  134. i4_key_accel_watcher_class::i4_key_accel_watcher_class()
  135. {
  136. initialized=i4_F;
  137. memset(user,0,sizeof(user));
  138. total=0;
  139. }
  140. i4_key_item_class **i4_key_accel_watcher_class::
  141. key_item_pointer_type::get_from_modifiers(w16 modifiers)
  142. {
  143. int index=0;
  144. if (modifiers & I4_MODIFIER_SHIFT)
  145. index |= 1;
  146. if (modifiers & I4_MODIFIER_CTRL)
  147. index |= 2;
  148. if (modifiers & I4_MODIFIER_ALT)
  149. index |= 3;
  150. return &modkey[index];
  151. }
  152. void i4_key_accel_watcher_class::watch_key(i4_key_item_class *who, w16 key, w16 modifiers)
  153. {
  154. if (!initialized)
  155. {
  156. i4_kernel.request_events(this,
  157. i4_device_class::FLAG_KEY_PRESS |
  158. i4_device_class::FLAG_KEY_RELEASE);
  159. initialized=i4_T;
  160. }
  161. I4_TEST(key<I4_NUM_KEYS, "Key out of range");
  162. if (*user[key].get_from_modifiers(modifiers))
  163. {
  164. char name[80];
  165. i4_warning("key alread has function [%s]\n", i4_get_key_name(key,modifiers,name));
  166. }
  167. else total++;
  168. *user[key].get_from_modifiers(modifiers)=who;
  169. }
  170. void i4_key_accel_watcher_class::unwatch_key(i4_key_item_class *who, w16 key, w16 modifiers)
  171. {
  172. if (*user[key].get_from_modifiers(modifiers)==who)
  173. {
  174. *user[key].get_from_modifiers(modifiers)=0;
  175. total--;
  176. if (total==0)
  177. {
  178. i4_kernel.unrequest_events(this,
  179. i4_device_class::FLAG_KEY_PRESS |
  180. i4_device_class::FLAG_KEY_RELEASE);
  181. initialized=i4_F;
  182. }
  183. }
  184. }
  185. void i4_key_accel_watcher_class::receive_event(i4_event *ev)
  186. {
  187. if (ev->type()==i4_event::KEY_PRESS)
  188. {
  189. CAST_PTR(kev, i4_key_press_event_class, ev);
  190. // if the object has the keyboard focus, then it will get the key through
  191. // normal window channels
  192. i4_key_item_class *i=*(user[kev->key_code].get_from_modifiers(kev->modifiers));
  193. if (i && !i->has_keyboard_focus())
  194. i4_kernel.send_event(i, ev);
  195. }
  196. }
  197. void i4_key_item_class::parent_draw(i4_draw_context_class &context)
  198. {
  199. local_image->add_dirty(0,0,width()-1,height()-1,context);
  200. i4_color fg,bg;
  201. if (active)
  202. {
  203. fg=color->selected_text_foreground;
  204. bg=color->selected_text_background;
  205. }
  206. else
  207. {
  208. fg=color->text_foreground;
  209. bg=color->text_background;
  210. }
  211. i4_str *key_name;
  212. if (use_key!=I4_NO_KEY)
  213. key_name=i4_key_name(use_key, key_modifiers);
  214. else key_name=0;
  215. if (!active)
  216. hint->deco_neutral_fill(local_image, 0,0, width()-1, height()-1, context);
  217. else
  218. local_image->clear(bg, context);
  219. i4_font_class *fnt=font->normal_font;
  220. if (!valid)
  221. {
  222. fg=color->window.passive.dark;
  223. fnt->set_color(color->window.passive.bright);
  224. fnt->put_string(local_image, pad_lr+1, pad_ud+1, *text,context);
  225. if (key_name)
  226. fnt->put_string(local_image, width() - pad_lr - fnt->width(*key_name) + 1,
  227. pad_ud + 1,
  228. *key_name, context);
  229. }
  230. if (valid || !active)
  231. {
  232. font->normal_font->set_color(fg);
  233. font->normal_font->put_string(local_image, pad_lr, pad_ud, *text,context);
  234. if (key_name)
  235. fnt->put_string(local_image, width() - pad_lr - fnt->width(*key_name),
  236. pad_ud, *key_name, context);
  237. }
  238. if (key_name)
  239. delete key_name;
  240. }