OVBROWSE.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  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 : OVBROWSE.CPP
  21. //Description : Object Visual Browse
  22. #include <ALL.h>
  23. #include <OINFO.h>
  24. #include <OMOUSE.h>
  25. #include <OVGA.h>
  26. #include <OFONT.h>
  27. #include <OPOWER.h>
  28. #include <OVBROWSE.h>
  29. //---------- Define static class variables -------//
  30. char VBrowse::press_record=0; // for detecting pulling records upwards and downloads
  31. VBrowse* VBrowse::press_vbrowse_ptr;
  32. //--------- Begin of function VBrowse::init --------//
  33. //
  34. // <int> x1, y1, x2, y2 = the coordinations of the list box
  35. // <int> rec_width = record area width
  36. // (0 if get the maximum width)
  37. // <int> rec_height = record area height
  38. // <int> totalRec = total no. of records (for generating scroll bar indicator)
  39. //
  40. // <BrowDispFP> dispFunc = The pointer to function which will return the
  41. // content of the record.
  42. // When call this function a <int> rec_no parameter
  43. // will pass to it.
  44. // [int] dispFrame = whether display a frame highlighting current
  45. // item or not
  46. // (default : 1)
  47. // [int] minInterSpace = minimum inter-record space
  48. // (default : MIN_SPACE)
  49. //
  50. void VBrowse::init(int inX1, int inY1, int inX2, int inY2,
  51. int recWidth, int recHeight,
  52. int totalRec, BrowDispFP dispFunc,
  53. int dispFrame, int minInterSpace)
  54. {
  55. x1 = inX1;
  56. y1 = inY1;
  57. x2 = inX2;
  58. y2 = inY2;
  59. ix1 = x1+6; // content area coordination
  60. iy1 = y1+6;
  61. ix2 = x2-6-SCROLL_BAR_WIDTH;
  62. iy2 = y2-6;
  63. //---------------------------------------------//
  64. if( recWidth <= 0 )
  65. rec_width = ix2-ix1+1;
  66. else
  67. rec_width = recWidth;
  68. rec_height = recHeight;
  69. disp_rec_func = dispFunc;
  70. disp_frame = dispFrame;
  71. x_max_rec = (ix2-ix1+minInterSpace+1) / (rec_width +minInterSpace);
  72. y_max_rec = (iy2-iy1+minInterSpace+1) / (rec_height+minInterSpace);
  73. detect_pull_flag = 1; // whether detect pulling records or not
  74. err_if( x_max_rec <= 0 || y_max_rec <= 0 )
  75. err_now( "VBrowse::init() error : disp_max_rec <= 0" );
  76. //--- calculate the suitable inter-record space -------//
  77. if( x_max_rec > 1 )
  78. rec_x_space = minInterSpace + (ix2-ix1+minInterSpace+1) % (rec_width +minInterSpace)/(x_max_rec-1);
  79. else
  80. rec_x_space = minInterSpace;
  81. if( y_max_rec > 1 )
  82. rec_y_space = minInterSpace + (iy2-iy1+minInterSpace+1) % (rec_height+minInterSpace)/(y_max_rec-1);
  83. else
  84. rec_y_space = minInterSpace;
  85. init_var(totalRec,-1);
  86. init_flag = 1;
  87. //------- paint the list box --------//
  88. paint();
  89. }
  90. //---------- End of function VBrowse::init ---------//
  91. //---------- Begin of function VBrowse::init_var -------//
  92. //
  93. // Initialize variables for visual browser
  94. //
  95. void VBrowse::init_var(int totalRec, int recNo)
  96. {
  97. if( totalRec >= 0 ) // if totalRec == -1, then no change
  98. {
  99. none_record = totalRec==0;
  100. if( totalRec == 0 )
  101. total_rec_num = 1; // prevent divided by zero if it is a closed box
  102. else
  103. total_rec_num = totalRec;
  104. }
  105. //--- maximum records can be display on a browse box ---//
  106. disp_max_rec = x_max_rec * y_max_rec;
  107. if( disp_max_rec > total_rec_num )
  108. disp_max_rec = total_rec_num;
  109. //------- changable variables --------//
  110. rec_no = recNo;
  111. top_rec_no = recNo - disp_max_rec/2;
  112. top_rec_no = max(1,top_rec_no);
  113. if( top_rec_no+disp_max_rec-1 > total_rec_num ) // if there is an empty area at the lower part of the browser
  114. {
  115. top_rec_no = total_rec_num-disp_max_rec+1;
  116. top_rec_no = max(top_rec_no,1);
  117. }
  118. //------------- initialize scroll bar ---------------//
  119. //
  120. // If display frame , then scroll unit is 1 record
  121. // If don't display frame, then the scroll unit is disp_max_rec record
  122. //
  123. //---------------------------------------------------//
  124. scroll_bar.init( 1, x2-SCROLL_BAR_WIDTH, y1, x2, y2, disp_max_rec,
  125. (disp_frame && x_max_rec==1 ? 1 : disp_max_rec), // only use record as scroller unit when it's a vertical browser with frame
  126. total_rec_num, 1 );
  127. }
  128. //----------- End of function VBrowse::init_var ----------//
  129. //--------- Begin of function VBrowse::open ---------//
  130. //
  131. // Open the list box
  132. //
  133. // [int] recNo = the initial record no.
  134. // -1 if keep current record no.
  135. // (default : 1, the top record)
  136. //
  137. // [int] newTotalRec - new total record count. This is usually given
  138. // when in INFO_UPDATE mode.
  139. // (default: no change)
  140. //
  141. void VBrowse::open(int recNo, int newTotalRec)
  142. {
  143. state = 1; // state = OPENED
  144. if( newTotalRec >= 0 )
  145. total_rec_num = newTotalRec;
  146. if( recNo > 0 ) // keep current record no.
  147. rec_no = recNo;
  148. if( rec_no<1 )
  149. rec_no=1;
  150. if( rec_no > total_rec_num )
  151. rec_no = total_rec_num;
  152. //------- set the top recno ----------//
  153. if( !newTotalRec )
  154. {
  155. top_rec_no = rec_no - disp_max_rec/2;
  156. top_rec_no = max(1,top_rec_no);
  157. }
  158. else // keep the original top_rec_no
  159. {
  160. if( rec_no > top_rec_no+disp_max_rec-1 )
  161. top_rec_no = rec_no-disp_max_rec+1;
  162. if( rec_no < top_rec_no )
  163. top_rec_no = rec_no;
  164. }
  165. if( top_rec_no+disp_max_rec-1 > total_rec_num ) // if there is an empty area at the lower part of the browser
  166. {
  167. top_rec_no = total_rec_num-disp_max_rec+1;
  168. top_rec_no = max(top_rec_no,1);
  169. }
  170. //------- display all records -------//
  171. disp_all();
  172. }
  173. //--------- End of function VBrowse::open ---------//
  174. //--------- Begin of function VBrowse::close ---------//
  175. //
  176. // Close the list box, disable scroll bar and list content
  177. //
  178. void VBrowse::close()
  179. {
  180. state = 0; // state = CLOSED
  181. //-------- paint the closed outlook of the list box -------//
  182. Vga::active_buf->d3_panel_up( x1+1, y1+1, x2-SCROLL_BAR_WIDTH-3, y2-1 ); // the place a large block on the list content box
  183. }
  184. //--------- End of function VBrowse::close ---------//
  185. //--------- Begin of function VBrowse::paint ---------//
  186. //
  187. // Display the movie list box
  188. //
  189. void VBrowse::paint()
  190. {
  191. Vga::active_buf->d3_panel_down( x1, y1, x2-SCROLL_BAR_WIDTH-3, y2 ); // the list content box
  192. Vga::active_buf->bar( x2-SCROLL_BAR_WIDTH-2, y1, x2-SCROLL_BAR_WIDTH-1, y2, Vga::active_buf->color_up );
  193. scroll_bar.paint();
  194. }
  195. //--------- End of function VBrowse::paint ---------//
  196. //------- Begin of function VBrowse::refresh ---------//
  197. //
  198. // Reset the no. of record and current record pointer and cause displaying
  199. //
  200. // [int] newRecNo = new current record no.
  201. // (default : -1, no change)
  202. // [int] newTotalRec = new total no. of records
  203. // (default : -1, no change)
  204. //
  205. void VBrowse::refresh(int newRecNo, int newTotalRec)
  206. {
  207. disp_one(rec_no,CLEAR_HIGH);
  208. if( newRecNo>=0 || newTotalRec>=0 ) // if current recno and total recno has no change, don't do the recalculation
  209. {
  210. if( newRecNo >= 1 )
  211. rec_no = newRecNo;
  212. if( newTotalRec != -1 && rec_no > newTotalRec )
  213. rec_no = newTotalRec;
  214. if( rec_no==0 && newTotalRec>0 ) // if originally rec_no==0, and total_rec is also 0, when the new total_rec is > 0, the rec_no should also be adjusted
  215. rec_no=1;
  216. init_var(newTotalRec,rec_no);
  217. }
  218. disp_all();
  219. }
  220. //---------- End of function VBrowse::refresh ----------//
  221. //------- Begin of function VBrowse::update ---------//
  222. //
  223. // Yield all records which currently display in the vbrowse
  224. //
  225. void VBrowse::update()
  226. {
  227. int recNo, x, y;
  228. if( none_record )
  229. return;
  230. for( recNo=top_rec_no ; recNo<=total_rec_num && recNo<top_rec_no+disp_max_rec ; recNo++ )
  231. {
  232. y = iy1 + (recNo-top_rec_no)/x_max_rec * (rec_height+rec_y_space);
  233. x = ix1 + (recNo-top_rec_no)%x_max_rec * (rec_width+rec_x_space);
  234. disp_rec( recNo, x, y, INFO_UPDATE ); // call user defined function
  235. }
  236. }
  237. //---------- End of function VBrowse::update ----------//
  238. //--------- Begin of function VBrowse::detect ------//
  239. //
  240. // Detect for any mouse action and carry out relative response
  241. //
  242. // Return : <int> >0 if the new current record number
  243. // =0 if no action
  244. //
  245. int VBrowse::detect()
  246. {
  247. int recNo=0, rc;
  248. double_click = 0;
  249. if( state == 0 || none_record ) // closed
  250. return 0;
  251. //-- Detect pulling on record if the browser is with frame --//
  252. if( detect_pull_flag && disp_frame && x_max_rec==1 ) // only pull when the vbrowser is vertical, horizontal is technically possible, but not used practically
  253. {
  254. if( detect_pull() )
  255. return rec_no;
  256. }
  257. //--------- Detect pressing on record if disp_frame is 1 ---------//
  258. if( disp_frame )
  259. {
  260. if( mouse.any_click(ix1, iy1, ix2, iy2) )
  261. {
  262. recNo = top_rec_no +
  263. (mouse.click_y()-iy1) / (rec_height+rec_y_space) * x_max_rec +
  264. (mouse.click_x()-ix1) / (rec_width +rec_x_space);
  265. if( detect_pull_flag )
  266. press_record = 1;
  267. press_vbrowse_ptr = this;
  268. }
  269. if( mouse.press_area(ix1, iy1, ix2, iy2) )
  270. {
  271. recNo = top_rec_no +
  272. (mouse.cur_y-iy1) / (rec_height+rec_y_space) * x_max_rec +
  273. (mouse.cur_x-ix1) / (rec_width +rec_x_space);
  274. if( detect_pull_flag )
  275. press_record = 1;
  276. press_vbrowse_ptr = this;
  277. }
  278. if( recNo>0 && recNo<=top_rec_no-1+disp_max_rec ) // if it is not in the empty browser area
  279. {
  280. if( mouse.click_count()==2 ) // double clicked
  281. double_click = 1;
  282. if( recNo != rec_no ) // if user point to a new record
  283. {
  284. disp_one(rec_no, CLEAR_HIGH);
  285. disp_one(recNo , DISP_HIGH ); // 2 means display record content only
  286. rec_no = recNo;
  287. return rec_no;
  288. }
  289. if( double_click ) // even if current record no. doesn't change, return recno if double clicked
  290. return rec_no;
  291. }
  292. }
  293. else //---- when disp_frame is 0, fast scrolling is enabled ----//
  294. {
  295. if( mouse.any_click( ix1, iy1, ix2, iy2 ) )
  296. {
  297. int newTopRec;
  298. if( mouse.click_y() < iy1+ ( (iy2-iy1) >> 1 ) )
  299. newTopRec = scroll_bar.page_up(); // page up
  300. else
  301. newTopRec = scroll_bar.page_down(); // page down
  302. if( top_rec_no != newTopRec )
  303. {
  304. double_click = mouse.click_count()==2; // double clicked
  305. rec_no = top_rec_no = newTopRec;
  306. disp_all();
  307. return rec_no;
  308. }
  309. }
  310. }
  311. //------- detect for pressing on scroll bar -----//
  312. if( ( rc=scroll_bar.detect() ) > 0 )
  313. {
  314. disp_one(rec_no,CLEAR_HIGH);
  315. rec_no = rc;
  316. if( disp_frame && x_max_rec==1 ) // only use record as scroller unit when it's a vertical browser with frame, refer to scroll_bar.init() in VBrowse::init_var()
  317. {
  318. if( rec_no < top_rec_no )
  319. {
  320. top_rec_no = rec_no;
  321. disp_all();
  322. }
  323. else if( rec_no >= top_rec_no + disp_max_rec )
  324. {
  325. top_rec_no = rec_no - disp_max_rec + 1;
  326. if( top_rec_no < 1 )
  327. top_rec_no = 1;
  328. disp_all();
  329. }
  330. else
  331. disp_one(rec_no,DISP_HIGH);
  332. }
  333. else
  334. {
  335. top_rec_no = rc;
  336. disp_all();
  337. }
  338. return rec_no;
  339. }
  340. return 0;
  341. }
  342. //----------- End of function VBrowse::detect -------//
  343. //---------- Begin of function VBrowse::detect_pull ---------//
  344. //
  345. // Detect pulling on record if it is a vertical browser with frame.
  346. //
  347. int VBrowse::detect_pull()
  348. {
  349. if( press_record ) // test whether user continue pressing it
  350. {
  351. press_record = mouse.left_press;
  352. if( press_record )
  353. press_vbrowse_ptr = this;
  354. }
  355. if( !( mouse.left_press || mouse.click_count() ) )
  356. return 0;
  357. if( !press_record )
  358. return 0;
  359. //--------- detect for pulling record upwards ---------//
  360. if( ( x_max_rec==1 && mouse.press_area( x1, 0 , x2, y1 ) ) ||
  361. ( y_max_rec==1 && mouse.press_area( 0, y1, x1, y2 ) ) )
  362. {
  363. if( rec_no > 1 )
  364. {
  365. disp_one(rec_no, CLEAR_HIGH);
  366. rec_no--;
  367. if( rec_no < top_rec_no )
  368. top_rec_no--;
  369. disp_all();
  370. return 1;
  371. }
  372. }
  373. //---- detect for pressing down button or pulling record downwards ---//
  374. if( ( x_max_rec==1 && mouse.press_area( x1, y2, x2, VGA_HEIGHT-1 ) ) ||
  375. ( y_max_rec==1 && mouse.press_area( x2, y1, VGA_WIDTH-1, y2 ) ) )
  376. {
  377. if( rec_no < total_rec_num )
  378. {
  379. disp_one(rec_no, CLEAR_HIGH);
  380. rec_no++;
  381. if( rec_no >= top_rec_no+disp_max_rec )
  382. top_rec_no++;
  383. disp_all();
  384. return 1;
  385. }
  386. }
  387. return 0;
  388. }
  389. //---------- End of function VBrowse::detect_pull ---------//
  390. //--------- Begin of function VBrowse::detect_right ------//
  391. //
  392. // Detect for pressing right mouse button on the record
  393. //
  394. // Return : <int> >0 if the record number
  395. // =0 if no action
  396. //
  397. int VBrowse::detect_right()
  398. {
  399. if( state == 0 || none_record ) // closed
  400. return 0;
  401. if( mouse.single_click( ix1, iy1, ix2, iy2, 1 ) ) // 1-right mouse button
  402. {
  403. int recNo;
  404. recNo = top_rec_no +
  405. (mouse.click_y(1)-iy1) / (rec_height+rec_y_space) * x_max_rec +
  406. (mouse.click_x(1)-ix1) / (rec_width +rec_x_space);
  407. if( recNo <= top_rec_no-1+disp_max_rec )
  408. {
  409. disp_one(rec_no,CLEAR_HIGH);
  410. disp_one(recNo, DISP_HIGH); // 2 means display record content only
  411. rec_no = recNo;
  412. return recNo;
  413. }
  414. }
  415. return 0;
  416. }
  417. //----------- End of function VBrowse::detect_right -------//
  418. //-------- Begin of function VBrowse::disp_all ----------//
  419. //
  420. // Display all records on screen, highlight cur_rec_no
  421. //
  422. void VBrowse::disp_all()
  423. {
  424. int recNo;
  425. Vga::active_buf->bar( ix1, iy1, ix2, iy2, VBROWSE_COLOR_BACK ); // clear background
  426. int scrollRecno = (disp_frame && x_max_rec==1) ? rec_no : top_rec_no;
  427. scroll_bar.refresh( scrollRecno, 1, disp_max_rec,
  428. (disp_frame && x_max_rec==1 ? 1 : disp_max_rec),
  429. total_rec_num );
  430. for( recNo=top_rec_no ; recNo<=total_rec_num && recNo<top_rec_no+disp_max_rec ; recNo++ )
  431. {
  432. disp_one( recNo, DISP_REC );
  433. if( recNo == rec_no )
  434. disp_one( recNo, DISP_HIGH );
  435. }
  436. }
  437. //--------- End of function VBrowse::disp_all ----------//
  438. //-------- Begin of function VBrowse::disp_one ----------//
  439. //
  440. // <int> recNo = the no. of the record to display
  441. // <int> putType = DISP_REC - display record
  442. // DISP_HIGH - highlight rect
  443. // CLEAR_HIGH- clear highlight rect
  444. //
  445. void VBrowse::disp_one(int recNo, int dispType)
  446. {
  447. if( none_record )
  448. return;
  449. int x,y;
  450. y = iy1 + (recNo-top_rec_no)/x_max_rec * (rec_height+rec_y_space);
  451. x = ix1 + (recNo-top_rec_no)%x_max_rec * (rec_width+rec_x_space);
  452. //---- put a outline rect around the record if it is highlight ---//
  453. if( disp_frame && dispType == CLEAR_HIGH )
  454. Vga::active_buf->rect( x-2, y-2, x+rec_width+1, y+rec_height+1, 2, VBROWSE_COLOR_BACK );
  455. if( dispType == DISP_REC )
  456. disp_rec( recNo, x, y, INFO_REPAINT ); // call user defined function
  457. if( disp_frame && dispType == DISP_HIGH )
  458. {
  459. Vga::active_buf->rect( x-2, y-2, x+rec_width+1, y+rec_height+1, 2, VBROWSE_COLOR_HIGH );
  460. int scrollRecno = (disp_frame && x_max_rec==1) ? recNo : top_rec_no;
  461. scroll_bar.refresh( scrollRecno, 0, disp_max_rec,
  462. (disp_frame && x_max_rec==1 ? 1 : disp_max_rec),
  463. total_rec_num );
  464. }
  465. }
  466. //--------- End of function VBrowse::disp_one ----------//
  467. //-------- Begin of function VBrowse::disp_rec --------//
  468. //
  469. void VBrowse::disp_rec(int recNo, int x, int y, int refreshFlag)
  470. {
  471. (*disp_rec_func)( recNo, x, y, refreshFlag ); // call user defined function
  472. }
  473. //----------- End of function VBrowse::disp_rec -----------//