OBUTTON.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. /*
  2. * Seven Kingdoms: Ancient Adversaries
  3. *
  4. * Copyright 1997,1998 Enlight Software Ltd.
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. *
  19. */
  20. //Filename : OBUTTON.CPP
  21. //Description : Button Object
  22. #include <KEY.h>
  23. #include <ALL.h>
  24. #include <OHELP.h>
  25. #include <OFONT.h>
  26. #include <OSYS.h>
  27. #include <OMOUSE.h>
  28. #include <OVGA.h>
  29. #include <OIMGRES.h>
  30. #include <OBUTTON.h>
  31. //----------- Begin of function Button::Button -----------//
  32. //
  33. Button::Button()
  34. {
  35. init_flag = 0;
  36. x1 = -1;
  37. enable_flag = 1;
  38. button_key = 0; // set by set_key()
  39. use_texture_flag = 0;
  40. help_code[0] = NULL;
  41. font_ptr = &font_san;
  42. }
  43. //-------------- End of function Button::Button ----------//
  44. //-------- Begin of function Button::set_help_code -------//
  45. //
  46. void Button::set_help_code(char* helpCode)
  47. {
  48. strncpy( help_code, helpCode, HELP_CODE_LEN );
  49. help_code[HELP_CODE_LEN] = NULL;
  50. }
  51. //--------- End of function Button::set_help_code --------//
  52. //-------- Begin of function Button::set_font -------//
  53. //
  54. // Set the font of the button, if not set, default use font_san.
  55. //
  56. // <Font*> fontPtr = pointer to the font
  57. //
  58. void Button::set_font(Font* fontPtr)
  59. {
  60. err_when(!fontPtr);
  61. font_ptr = fontPtr;
  62. }
  63. //--------- End of function Button::set_font --------//
  64. //-------- Begin of function Button::create_text -------//
  65. //
  66. // Given only the top left position of the button, it will calculate
  67. // the width and height of the button based on the given text and
  68. // current button font.
  69. //
  70. // Syntax : create(<int>,<int>,<int>,<int>,<int>,<int>,<char>)
  71. //
  72. // <int> x1, y1 = coordination of the button
  73. // <char*> textPtr = text pointer, depended on the type of the button
  74. //
  75. // [int] elastic = Whether the button is elastic
  76. // Elastic button will pop up immediately when button release
  77. // Non-elastic button will remain pushed until pop() is called
  78. // (default : 1)
  79. //
  80. // [int] defIsPushed = default is_pushed : 1-Pushed, 0-Non-pushed
  81. // (default : 0)
  82. //
  83. void Button::create_text(int pX1, int pY1, char* textPtr, char pElastic, char defIsPushed)
  84. {
  85. int pX2, pY2;
  86. pX2 = pX1 + font_ptr->text_width( textPtr ) + 9;
  87. pY2 = pY1 + font_ptr->height() + 7;
  88. create( BUTTON_TEXT,pX1,pY1,pX2,pY2,textPtr,pElastic,defIsPushed);
  89. }
  90. //-------- End of function Button::create_text -----//
  91. //-------- Begin of function Button::paint_text -------//
  92. //
  93. // Given only the top left position of the button, it will calculate
  94. // the width and height of the button based on the given text and
  95. // current button font.
  96. //
  97. // Syntax : create(<int>,<int>,<int>,<int>,<int>,<int>,<char>)
  98. //
  99. // <int> x1, y1 = coordination of the button
  100. // <char*> textPtr = text pointer, depended on the type of the button
  101. //
  102. // [int] elastic = Whether the button is elastic
  103. // Elastic button will pop up immediately when button release
  104. // Non-elastic button will remain pushed until pop() is called
  105. // (default : 1)
  106. //
  107. // [int] defIsPushed = default is_pushed : 1-Pushed, 0-Non-pushed
  108. // (default : 0)
  109. //
  110. // Note : it use the color setting in (vga) and (font_san)
  111. //
  112. void Button::paint_text(int pX1, int pY1, char* textPtr, char pElastic, char defIsPushed)
  113. {
  114. int pX2, pY2;
  115. pX2 = pX1 + font_ptr->text_width( textPtr ) + 9;
  116. pY2 = pY1 + font_ptr->height() + 7;
  117. create( BUTTON_TEXT,pX1,pY1,pX2,pY2,textPtr,pElastic,defIsPushed);
  118. paint();
  119. }
  120. //-------- End of function Button::paint_text -----//
  121. //-------- Begin of function Button::create -------//
  122. //
  123. // Syntax : create(<int>,<int>,<int>,<int>,<int>,<int>,<char>)
  124. //
  125. // <int> buttonType = BUTTON_TEXT (1) - text button, BUTTON_BITMAP (2) - icon button
  126. // <int> x1, y1 = coordination of the button
  127. // <int> x2, y2 = coordination of the button
  128. // <void*> bodyPtr = text or icon pointer or pointer to user defined function,
  129. // depended on the type of the button allow NULL icon
  130. // pointer, which no icon will be displayed
  131. // [int] elastic = Whether the button is elastic
  132. // Elastic button will pop up immediately when button release
  133. // Non-elastic button will remain pushed until pop() is called
  134. // (default : 1)
  135. //
  136. // [int] defIsPushed = default is_pushed : 1-Pushed, 0-Non-pushed
  137. // (default : 0)
  138. //
  139. // Note : it use the color setting in (vga) and (font_san)
  140. //
  141. void Button::create(int buttonType, int pX1, int pY1, int pX2, int pY2,
  142. void* bodyPtr, char pElastic, char defIsPushed)
  143. {
  144. int strLen;
  145. init_flag = 1;
  146. button_type = buttonType;
  147. x1 = pX1;
  148. y1 = pY1;
  149. x2 = pX2;
  150. y2 = pY2;
  151. elastic = pElastic;
  152. is_pushed = defIsPushed;
  153. enable_flag = 1;
  154. //------------------------------------//
  155. if( buttonType == BUTTON_TEXT )
  156. {
  157. strLen = strlen((char*)bodyPtr); // copy the string to class member buffer
  158. // some string are temporary, we need it for repaint
  159. if( strLen > STR_BUF_LEN )
  160. strLen = STR_BUF_LEN;
  161. memcpy( str_buf, bodyPtr, strLen );
  162. str_buf[strLen] = NULL;
  163. }
  164. else
  165. body_ptr = bodyPtr;
  166. }
  167. //--------- End of function Button::create --------//
  168. //-------- Begin of function Button::set_body -------//
  169. //
  170. // <void*> bodyPtr = text or icon pointer or pointer to user defined function,
  171. //
  172. void Button::set_body(void* bodyPtr)
  173. {
  174. if( button_type == BUTTON_TEXT )
  175. {
  176. int strLen = strlen((char*)bodyPtr); // copy the string to class member buffer
  177. // some string are temporary, we need it for repaint
  178. if( strLen > STR_BUF_LEN )
  179. strLen = STR_BUF_LEN;
  180. memcpy( str_buf, bodyPtr, strLen );
  181. str_buf[strLen] = NULL;
  182. }
  183. else
  184. body_ptr = bodyPtr;
  185. }
  186. //--------- End of function Button::set_body --------//
  187. //--------- Begin of function Button::hide ----------//
  188. //
  189. // Hide and disable the button
  190. //
  191. // Syntax : hide(char)
  192. //
  193. // <char> backColor = background color
  194. //
  195. void Button::hide(char backColor)
  196. {
  197. if( init_flag )
  198. {
  199. init_flag = 0;
  200. if( x1 >= 0 ) // when create() hasn't been called x1 is -1
  201. Vga::active_buf->bar( x1,y1,x2,y2,backColor );
  202. }
  203. }
  204. //------------ End of function Button::hide ---------//
  205. //--------- Begin of function Button::show ----------//
  206. //
  207. // Show a button hiden by hide().
  208. //
  209. void Button::show()
  210. {
  211. if( !init_flag )
  212. {
  213. init_flag = 1;
  214. paint(0, 1);
  215. }
  216. }
  217. //------------ End of function Button::show ---------//
  218. //----------- Begin of function Button::paint -----------//
  219. //
  220. // [int] defIsPushed = default is_pushed : 1-Pushed, 0-Non-pushed
  221. // (default : is_pushed)
  222. //
  223. // [int] repaintBody = repaint the button body or only repaint panel sides
  224. // (default : 1), 0 when called by detect()
  225. //
  226. void Button::paint(int defIsPushed, int repaintBody)
  227. {
  228. if( !init_flag )
  229. return;
  230. int colorUp = Vga::active_buf->color_up;
  231. int colorLight = Vga::active_buf->color_light;
  232. Vga::active_buf->color_light = (char) V_WHITE; // don't use layer colors
  233. if( enable_flag )
  234. {
  235. if( defIsPushed >= 0 )
  236. is_pushed = defIsPushed;
  237. if( !is_pushed )
  238. {
  239. if( use_texture_flag )
  240. vga.d3_panel_up( x1, y1, x2, y2 );
  241. else
  242. {
  243. Vga::active_buf->color_up = Vga::active_buf->color_down;
  244. Vga::active_buf->d3_panel_up( x1, y1, x2, y2, 1, repaintBody || button_type==1 );
  245. }
  246. }
  247. else
  248. {
  249. if( use_texture_flag )
  250. {
  251. vga.d3_panel_down( x1, y1, x2, y2 );
  252. }
  253. else
  254. {
  255. if( repaintBody || button_type==1 ) // text button
  256. Vga::active_buf->d3_panel_up( x1, y1, x2, y2, 2 );
  257. Vga::active_buf->d3_panel_down( x1,y1,x2,y2, 1, 0 );
  258. }
  259. }
  260. }
  261. else // button disabled
  262. {
  263. Vga::active_buf->color_up = Vga::active_buf->color_up+1;
  264. Vga::active_buf->d3_panel_up( x1, y1, x2, y2, 1, repaintBody );
  265. }
  266. Vga::active_buf->color_up = colorUp;
  267. Vga::active_buf->color_light = colorLight;
  268. //--------- put button body -------------//
  269. if( button_type == BUTTON_TEXT ) // text button
  270. {
  271. int tx = x1 + ((x2-x1) - font_ptr->text_width(str_buf))/2;
  272. int ty = y1 + ((y2-y1) - font_ptr->height())/2 - 1;
  273. tx = max( tx, x1+4 );
  274. ty = max( ty, y1+1 );
  275. font_ptr->put( tx, ty, str_buf, 0, x2-3 );
  276. }
  277. else if( button_type == BUTTON_BITMAP )
  278. {
  279. if( body_ptr && repaintBody )
  280. {
  281. int tx = x1 + ((x2-x1+1) - *((short*)body_ptr))/2;
  282. int ty = y1 + ((y2-y1+1) - *((short*)body_ptr+1))/2;
  283. Vga::active_buf->put_bitmap( tx, ty, (char*) body_ptr ); // 0 means not clear background
  284. }
  285. }
  286. else // BUTTON_UDF, user defined function
  287. {
  288. if( body_ptr )
  289. (*((ButtonFP*)body_ptr))(x1+3,x2+3,y1-3,y2-3);
  290. }
  291. }
  292. //---------- End of function Button::paint -----------//
  293. //-------- Begin of function Button::detect -----------//
  294. //
  295. // Detect whether the button has been pressed,
  296. // if so, act correspondly.
  297. // Check for left mouse button only
  298. //
  299. // [unsigned] keyCode1 = if the specified key is pressed, emulate button pressed
  300. // (default : 0)
  301. //
  302. // [unsigned] keyCode2 = if the specified key is pressed, emulate button pressed
  303. // (default : 0)
  304. //
  305. // [int] detectRight = whether also detect the right button or not
  306. // (default : 0)
  307. //
  308. // [int] suspendPop = don't pop up the button even it should
  309. // (defalut : 0)
  310. //
  311. // Return : 1 - if left mouse button pressed
  312. // 2 - if right mouse button pressed
  313. // 3 - the key is pressed (only when keyCode is specified)
  314. // 0 - if not
  315. //
  316. int Button::detect(unsigned keyCode1, unsigned keyCode2, int detectRight, int suspendPop)
  317. {
  318. int rc=0;
  319. if( !init_flag || !enable_flag )
  320. return 0;
  321. help.set_help( x1, y1, x2, y2, help_code );
  322. if( mouse.any_click(x1,y1,x2,y2,LEFT_BUTTON) )
  323. rc=1;
  324. else if( detectRight && mouse.any_click(x1,y1,x2,y2,RIGHT_BUTTON) )
  325. rc=2;
  326. else if(mouse.key_code)
  327. {
  328. unsigned mouseKey=mouse.key_code;
  329. if( mouseKey >= 'a' && mouseKey <= 'z' ) // non-case sensitive comparsion
  330. mouseKey -= 32; // convert from lower case to upper case
  331. if( mouseKey == keyCode1 || mouseKey == keyCode2 || mouseKey == button_key )
  332. {
  333. rc=3;
  334. }
  335. }
  336. if( !rc )
  337. return 0;
  338. //----- paint the button with pressed shape ------//
  339. #define PRESSED_TIMEOUT_SECONDS 1 // 1 seconds
  340. DWORD timeOutTime = m.get_time()+PRESSED_TIMEOUT_SECONDS*1000;
  341. if( elastic )
  342. {
  343. if( !is_pushed )
  344. paint(1,0); // 0-no need to repaint button body (text or icon)
  345. while( (rc==1 && mouse.left_press) || (rc==2 && mouse.right_press) )
  346. {
  347. sys.yield();
  348. mouse.get_event();
  349. if( m.get_time() >= timeOutTime )
  350. break;
  351. }
  352. if( elastic )
  353. paint(0,0);
  354. }
  355. else // inelastic button
  356. {
  357. if( suspendPop )
  358. is_pushed = 1;
  359. else
  360. is_pushed = !is_pushed;
  361. paint(is_pushed,0);
  362. while( (rc==1 && mouse.left_press) || (rc==2 && mouse.right_press) )
  363. {
  364. sys.yield();
  365. mouse.get_event();
  366. if( m.get_time() >= timeOutTime )
  367. break;
  368. }
  369. }
  370. return rc;
  371. }
  372. //----------- End of function Button::detect -------------//
  373. //--------- Begin of function Button::wait_press ----------//
  374. //
  375. // Wait for user to press the button
  376. //
  377. // [int] timeOut - 1=enable inactive timeout
  378. // 0=disable inactive timeout
  379. // (default : 1 )
  380. //
  381. void Button::wait_press(int timeOut)
  382. {
  383. #define INACTIVE_TIMEOUT_SECONDS 10 // 10 seconds
  384. int lastMouseX= -1, lastMouseY;
  385. DWORD timeOutTime = m.get_time()+INACTIVE_TIMEOUT_SECONDS*1000;
  386. mouse.get_event(); // clean up previous mouse events
  387. while( !detect(KEY_RETURN,KEY_ESC) && !mouse.any_click(1) ) // 1-only right mouse button
  388. {
  389. sys.yield();
  390. mouse.get_event();
  391. //--- when the user is inactive for a certain time, ----//
  392. //--------- close the report automatically -------------//
  393. if( timeOut )
  394. {
  395. if( lastMouseX == mouse.cur_x && lastMouseY == mouse.cur_y )
  396. {
  397. if( m.get_time() >= timeOutTime )
  398. break;
  399. }
  400. else
  401. {
  402. lastMouseX = mouse.cur_x;
  403. lastMouseY = mouse.cur_y;
  404. timeOutTime = m.get_time()+INACTIVE_TIMEOUT_SECONDS*1000;
  405. }
  406. }
  407. }
  408. }
  409. //----------- End of function Button::wait_press ----------//
  410. //.........................................................//
  411. //-------- Begin of function ButtonGroup::ButtonGroup -------//
  412. ButtonGroup::ButtonGroup(int buttonNum)
  413. {
  414. button_pressed = 0;
  415. button_num = buttonNum;
  416. button_array = new Button[buttonNum];
  417. }
  418. //---------- End of function ButtonGroup::ButtonGroup -------//
  419. //----------- Begin of function ButtonGroup::~ButtonGroup -----------//
  420. //
  421. ButtonGroup::~ButtonGroup()
  422. {
  423. delete[] button_array;
  424. }
  425. //-------------- End of function ButtonGroup::~ButtonGroup ----------//
  426. //--------- Begin of function ButtonGroup::paint ----------//
  427. //
  428. // Paint all buttons in this button nation.
  429. //
  430. // [int] buttonPressed = the default pressed button
  431. // (default no change to button_pressed)
  432. //
  433. void ButtonGroup::paint(int buttonPressed)
  434. {
  435. int i;
  436. if( buttonPressed >= 0 )
  437. button_pressed = buttonPressed;
  438. for( i=0 ; i<button_num ; i++ )
  439. button_array[i].paint(button_pressed==i);
  440. }
  441. //----------- End of function ButtonGroup::paint ----------//
  442. //--------- Begin of function ButtonGroup::detect ----------//
  443. //
  444. // Detect all buttons in this button nation.
  445. // Since only one button can be pressed at one time,
  446. // so if any one of them is pressed, the previously pressed one
  447. // will be pop up.
  448. //
  449. // Return : <int> -1 - if no button pressed
  450. // >=0 - the record no. of the button pressed
  451. //
  452. int ButtonGroup::detect()
  453. {
  454. int i;
  455. for( i=0 ; i<button_num ; i++ )
  456. {
  457. if( !button_array[i].is_pushed && button_array[i].detect() )
  458. {
  459. button_array[button_pressed].pop();
  460. button_pressed = i;
  461. return i;
  462. }
  463. }
  464. return -1;
  465. }
  466. //----------- End of function ButtonGroup::detect ----------//
  467. //--------- Begin of function ButtonGroup::push ----------//
  468. //
  469. // Push the specified button.
  470. //
  471. // <int> buttonId = Id. of the button.
  472. //
  473. void ButtonGroup::push(int buttonId)
  474. {
  475. int i;
  476. button_pressed = buttonId;
  477. for( i=0 ; i<button_num ; i++ )
  478. {
  479. if( i==buttonId )
  480. button_array[i].push();
  481. else
  482. button_array[i].pop();
  483. }
  484. }
  485. //----------- End of function ButtonGroup::push ----------//
  486. //--------- Begin of function ButtonGroup::operator[] ----------//
  487. //
  488. // <int> buttonId = Id. of the button, start from 0
  489. //
  490. Button& ButtonGroup::operator[](int buttonId)
  491. {
  492. err_when( buttonId<0 || buttonId >= button_num );
  493. return button_array[buttonId];
  494. }
  495. //----------- End of function ButtonGroup::operator[] ----------//