123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606 |
- /*
- * 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 <http://www.gnu.org/licenses/>.
- *
- */
- //Filename : OVBROWSE.CPP
- //Description : Object Visual Browse
- #include <ALL.h>
- #include <OINFO.h>
- #include <OMOUSE.h>
- #include <OVGA.h>
- #include <OFONT.h>
- #include <OPOWER.h>
- #include <OVBROWSE.h>
- //---------- 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 --------//
- //
- // <int> x1, y1, x2, y2 = the coordinations of the list box
- // <int> rec_width = record area width
- // (0 if get the maximum width)
- // <int> rec_height = record area height
- // <int> totalRec = total no. of records (for generating scroll bar indicator)
- //
- // <BrowDispFP> dispFunc = The pointer to function which will return the
- // content of the record.
- // When call this function a <int> 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<top_rec_no+disp_max_rec ; recNo++ )
- {
- 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);
- disp_rec( recNo, x, y, INFO_UPDATE ); // call user defined function
- }
- }
- //---------- End of function VBrowse::update ----------//
- //--------- Begin of function VBrowse::detect ------//
- //
- // Detect for any mouse action and carry out relative response
- //
- // Return : <int> >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 : <int> >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<top_rec_no+disp_max_rec ; recNo++ )
- {
- disp_one( recNo, DISP_REC );
- if( recNo == rec_no )
- disp_one( recNo, DISP_HIGH );
- }
- }
- //--------- End of function VBrowse::disp_all ----------//
- //-------- Begin of function VBrowse::disp_one ----------//
- //
- // <int> recNo = the no. of the record to display
- // <int> 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 -----------//
|