/* * Seven Kingdoms: Ancient Adversaries * * Copyright 1997,1998 Enlight Software Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ //Filename : OVBROWSE.CPP //Description : Object Visual Browse #include #include #include #include #include #include #include //---------- Define static class variables -------// char VBrowse::press_record=0; // for detecting pulling records upwards and downloads VBrowse* VBrowse::press_vbrowse_ptr; //--------- Begin of function VBrowse::init --------// // // x1, y1, x2, y2 = the coordinations of the list box // rec_width = record area width // (0 if get the maximum width) // rec_height = record area height // totalRec = total no. of records (for generating scroll bar indicator) // // dispFunc = The pointer to function which will return the // content of the record. // When call this function a rec_no parameter // will pass to it. // [int] dispFrame = whether display a frame highlighting current // item or not // (default : 1) // [int] minInterSpace = minimum inter-record space // (default : MIN_SPACE) // void VBrowse::init(int inX1, int inY1, int inX2, int inY2, int recWidth, int recHeight, int totalRec, BrowDispFP dispFunc, int dispFrame, int minInterSpace) { x1 = inX1; y1 = inY1; x2 = inX2; y2 = inY2; ix1 = x1+6; // content area coordination iy1 = y1+6; ix2 = x2-6-SCROLL_BAR_WIDTH; iy2 = y2-6; //---------------------------------------------// if( recWidth <= 0 ) rec_width = ix2-ix1+1; else rec_width = recWidth; rec_height = recHeight; disp_rec_func = dispFunc; disp_frame = dispFrame; x_max_rec = (ix2-ix1+minInterSpace+1) / (rec_width +minInterSpace); y_max_rec = (iy2-iy1+minInterSpace+1) / (rec_height+minInterSpace); detect_pull_flag = 1; // whether detect pulling records or not err_if( x_max_rec <= 0 || y_max_rec <= 0 ) err_now( "VBrowse::init() error : disp_max_rec <= 0" ); //--- calculate the suitable inter-record space -------// if( x_max_rec > 1 ) rec_x_space = minInterSpace + (ix2-ix1+minInterSpace+1) % (rec_width +minInterSpace)/(x_max_rec-1); else rec_x_space = minInterSpace; if( y_max_rec > 1 ) rec_y_space = minInterSpace + (iy2-iy1+minInterSpace+1) % (rec_height+minInterSpace)/(y_max_rec-1); else rec_y_space = minInterSpace; init_var(totalRec,-1); init_flag = 1; //------- paint the list box --------// paint(); } //---------- End of function VBrowse::init ---------// //---------- Begin of function VBrowse::init_var -------// // // Initialize variables for visual browser // void VBrowse::init_var(int totalRec, int recNo) { if( totalRec >= 0 ) // if totalRec == -1, then no change { none_record = totalRec==0; if( totalRec == 0 ) total_rec_num = 1; // prevent divided by zero if it is a closed box else total_rec_num = totalRec; } //--- maximum records can be display on a browse box ---// disp_max_rec = x_max_rec * y_max_rec; if( disp_max_rec > total_rec_num ) disp_max_rec = total_rec_num; //------- changable variables --------// rec_no = recNo; top_rec_no = recNo - disp_max_rec/2; top_rec_no = max(1,top_rec_no); if( top_rec_no+disp_max_rec-1 > total_rec_num ) // if there is an empty area at the lower part of the browser { top_rec_no = total_rec_num-disp_max_rec+1; top_rec_no = max(top_rec_no,1); } //------------- initialize scroll bar ---------------// // // If display frame , then scroll unit is 1 record // If don't display frame, then the scroll unit is disp_max_rec record // //---------------------------------------------------// scroll_bar.init( 1, x2-SCROLL_BAR_WIDTH, y1, x2, y2, disp_max_rec, (disp_frame && x_max_rec==1 ? 1 : disp_max_rec), // only use record as scroller unit when it's a vertical browser with frame total_rec_num, 1 ); } //----------- End of function VBrowse::init_var ----------// //--------- Begin of function VBrowse::open ---------// // // Open the list box // // [int] recNo = the initial record no. // -1 if keep current record no. // (default : 1, the top record) // // [int] newTotalRec - new total record count. This is usually given // when in INFO_UPDATE mode. // (default: no change) // void VBrowse::open(int recNo, int newTotalRec) { state = 1; // state = OPENED if( newTotalRec >= 0 ) total_rec_num = newTotalRec; if( recNo > 0 ) // keep current record no. rec_no = recNo; if( rec_no<1 ) rec_no=1; if( rec_no > total_rec_num ) rec_no = total_rec_num; //------- set the top recno ----------// if( !newTotalRec ) { top_rec_no = rec_no - disp_max_rec/2; top_rec_no = max(1,top_rec_no); } else // keep the original top_rec_no { if( rec_no > top_rec_no+disp_max_rec-1 ) top_rec_no = rec_no-disp_max_rec+1; if( rec_no < top_rec_no ) top_rec_no = rec_no; } if( top_rec_no+disp_max_rec-1 > total_rec_num ) // if there is an empty area at the lower part of the browser { top_rec_no = total_rec_num-disp_max_rec+1; top_rec_no = max(top_rec_no,1); } //------- display all records -------// disp_all(); } //--------- End of function VBrowse::open ---------// //--------- Begin of function VBrowse::close ---------// // // Close the list box, disable scroll bar and list content // void VBrowse::close() { state = 0; // state = CLOSED //-------- paint the closed outlook of the list box -------// 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 } //--------- End of function VBrowse::close ---------// //--------- Begin of function VBrowse::paint ---------// // // Display the movie list box // void VBrowse::paint() { Vga::active_buf->d3_panel_down( x1, y1, x2-SCROLL_BAR_WIDTH-3, y2 ); // the list content box Vga::active_buf->bar( x2-SCROLL_BAR_WIDTH-2, y1, x2-SCROLL_BAR_WIDTH-1, y2, Vga::active_buf->color_up ); scroll_bar.paint(); } //--------- End of function VBrowse::paint ---------// //------- Begin of function VBrowse::refresh ---------// // // Reset the no. of record and current record pointer and cause displaying // // [int] newRecNo = new current record no. // (default : -1, no change) // [int] newTotalRec = new total no. of records // (default : -1, no change) // void VBrowse::refresh(int newRecNo, int newTotalRec) { disp_one(rec_no,CLEAR_HIGH); if( newRecNo>=0 || newTotalRec>=0 ) // if current recno and total recno has no change, don't do the recalculation { if( newRecNo >= 1 ) rec_no = newRecNo; if( newTotalRec != -1 && rec_no > newTotalRec ) rec_no = newTotalRec; 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 rec_no=1; init_var(newTotalRec,rec_no); } disp_all(); } //---------- End of function VBrowse::refresh ----------// //------- Begin of function VBrowse::update ---------// // // Yield all records which currently display in the vbrowse // void VBrowse::update() { int recNo, x, y; if( none_record ) return; for( recNo=top_rec_no ; recNo<=total_rec_num && recNo >0 if the new current record number // =0 if no action // int VBrowse::detect() { int recNo=0, rc; double_click = 0; if( state == 0 || none_record ) // closed return 0; //-- Detect pulling on record if the browser is with frame --// 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 { if( detect_pull() ) return rec_no; } //--------- Detect pressing on record if disp_frame is 1 ---------// if( disp_frame ) { if( mouse.any_click(ix1, iy1, ix2, iy2) ) { recNo = top_rec_no + (mouse.click_y()-iy1) / (rec_height+rec_y_space) * x_max_rec + (mouse.click_x()-ix1) / (rec_width +rec_x_space); if( detect_pull_flag ) press_record = 1; press_vbrowse_ptr = this; } if( mouse.press_area(ix1, iy1, ix2, iy2) ) { recNo = top_rec_no + (mouse.cur_y-iy1) / (rec_height+rec_y_space) * x_max_rec + (mouse.cur_x-ix1) / (rec_width +rec_x_space); if( detect_pull_flag ) press_record = 1; press_vbrowse_ptr = this; } if( recNo>0 && recNo<=top_rec_no-1+disp_max_rec ) // if it is not in the empty browser area { if( mouse.click_count()==2 ) // double clicked double_click = 1; if( recNo != rec_no ) // if user point to a new record { disp_one(rec_no, CLEAR_HIGH); disp_one(recNo , DISP_HIGH ); // 2 means display record content only rec_no = recNo; return rec_no; } if( double_click ) // even if current record no. doesn't change, return recno if double clicked return rec_no; } } else //---- when disp_frame is 0, fast scrolling is enabled ----// { if( mouse.any_click( ix1, iy1, ix2, iy2 ) ) { int newTopRec; if( mouse.click_y() < iy1+ ( (iy2-iy1) >> 1 ) ) newTopRec = scroll_bar.page_up(); // page up else newTopRec = scroll_bar.page_down(); // page down if( top_rec_no != newTopRec ) { double_click = mouse.click_count()==2; // double clicked rec_no = top_rec_no = newTopRec; disp_all(); return rec_no; } } } //------- detect for pressing on scroll bar -----// if( ( rc=scroll_bar.detect() ) > 0 ) { disp_one(rec_no,CLEAR_HIGH); rec_no = rc; 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() { if( rec_no < top_rec_no ) { top_rec_no = rec_no; disp_all(); } else if( rec_no >= top_rec_no + disp_max_rec ) { top_rec_no = rec_no - disp_max_rec + 1; if( top_rec_no < 1 ) top_rec_no = 1; disp_all(); } else disp_one(rec_no,DISP_HIGH); } else { top_rec_no = rc; disp_all(); } return rec_no; } return 0; } //----------- End of function VBrowse::detect -------// //---------- Begin of function VBrowse::detect_pull ---------// // // Detect pulling on record if it is a vertical browser with frame. // int VBrowse::detect_pull() { if( press_record ) // test whether user continue pressing it { press_record = mouse.left_press; if( press_record ) press_vbrowse_ptr = this; } if( !( mouse.left_press || mouse.click_count() ) ) return 0; if( !press_record ) return 0; //--------- detect for pulling record upwards ---------// if( ( x_max_rec==1 && mouse.press_area( x1, 0 , x2, y1 ) ) || ( y_max_rec==1 && mouse.press_area( 0, y1, x1, y2 ) ) ) { if( rec_no > 1 ) { disp_one(rec_no, CLEAR_HIGH); rec_no--; if( rec_no < top_rec_no ) top_rec_no--; disp_all(); return 1; } } //---- detect for pressing down button or pulling record downwards ---// if( ( x_max_rec==1 && mouse.press_area( x1, y2, x2, VGA_HEIGHT-1 ) ) || ( y_max_rec==1 && mouse.press_area( x2, y1, VGA_WIDTH-1, y2 ) ) ) { if( rec_no < total_rec_num ) { disp_one(rec_no, CLEAR_HIGH); rec_no++; if( rec_no >= top_rec_no+disp_max_rec ) top_rec_no++; disp_all(); return 1; } } return 0; } //---------- End of function VBrowse::detect_pull ---------// //--------- Begin of function VBrowse::detect_right ------// // // Detect for pressing right mouse button on the record // // Return : >0 if the record number // =0 if no action // int VBrowse::detect_right() { if( state == 0 || none_record ) // closed return 0; if( mouse.single_click( ix1, iy1, ix2, iy2, 1 ) ) // 1-right mouse button { int recNo; recNo = top_rec_no + (mouse.click_y(1)-iy1) / (rec_height+rec_y_space) * x_max_rec + (mouse.click_x(1)-ix1) / (rec_width +rec_x_space); if( recNo <= top_rec_no-1+disp_max_rec ) { disp_one(rec_no,CLEAR_HIGH); disp_one(recNo, DISP_HIGH); // 2 means display record content only rec_no = recNo; return recNo; } } return 0; } //----------- End of function VBrowse::detect_right -------// //-------- Begin of function VBrowse::disp_all ----------// // // Display all records on screen, highlight cur_rec_no // void VBrowse::disp_all() { int recNo; Vga::active_buf->bar( ix1, iy1, ix2, iy2, VBROWSE_COLOR_BACK ); // clear background int scrollRecno = (disp_frame && x_max_rec==1) ? rec_no : top_rec_no; scroll_bar.refresh( scrollRecno, 1, disp_max_rec, (disp_frame && x_max_rec==1 ? 1 : disp_max_rec), total_rec_num ); for( recNo=top_rec_no ; recNo<=total_rec_num && recNo recNo = the no. of the record to display // putType = DISP_REC - display record // DISP_HIGH - highlight rect // CLEAR_HIGH- clear highlight rect // void VBrowse::disp_one(int recNo, int dispType) { if( none_record ) return; int x,y; y = iy1 + (recNo-top_rec_no)/x_max_rec * (rec_height+rec_y_space); x = ix1 + (recNo-top_rec_no)%x_max_rec * (rec_width+rec_x_space); //---- put a outline rect around the record if it is highlight ---// if( disp_frame && dispType == CLEAR_HIGH ) Vga::active_buf->rect( x-2, y-2, x+rec_width+1, y+rec_height+1, 2, VBROWSE_COLOR_BACK ); if( dispType == DISP_REC ) disp_rec( recNo, x, y, INFO_REPAINT ); // call user defined function if( disp_frame && dispType == DISP_HIGH ) { Vga::active_buf->rect( x-2, y-2, x+rec_width+1, y+rec_height+1, 2, VBROWSE_COLOR_HIGH ); int scrollRecno = (disp_frame && x_max_rec==1) ? recNo : top_rec_no; scroll_bar.refresh( scrollRecno, 0, disp_max_rec, (disp_frame && x_max_rec==1 ? 1 : disp_max_rec), total_rec_num ); } } //--------- End of function VBrowse::disp_one ----------// //-------- Begin of function VBrowse::disp_rec --------// // void VBrowse::disp_rec(int recNo, int x, int y, int refreshFlag) { (*disp_rec_func)( recNo, x, y, refreshFlag ); // call user defined function } //----------- End of function VBrowse::disp_rec -----------//