/*
* 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 -----------//