/*
* 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 : OBUTTON.CPP
//Description : Button Object
#include
#include
#include
#include
#include
#include
#include
#include
#include
//----------- Begin of function Button::Button -----------//
//
Button::Button()
{
init_flag = 0;
x1 = -1;
enable_flag = 1;
button_key = 0; // set by set_key()
use_texture_flag = 0;
help_code[0] = NULL;
font_ptr = &font_san;
}
//-------------- End of function Button::Button ----------//
//-------- Begin of function Button::set_help_code -------//
//
void Button::set_help_code(char* helpCode)
{
strncpy( help_code, helpCode, HELP_CODE_LEN );
help_code[HELP_CODE_LEN] = NULL;
}
//--------- End of function Button::set_help_code --------//
//-------- Begin of function Button::set_font -------//
//
// Set the font of the button, if not set, default use font_san.
//
// fontPtr = pointer to the font
//
void Button::set_font(Font* fontPtr)
{
err_when(!fontPtr);
font_ptr = fontPtr;
}
//--------- End of function Button::set_font --------//
//-------- Begin of function Button::create_text -------//
//
// Given only the top left position of the button, it will calculate
// the width and height of the button based on the given text and
// current button font.
//
// Syntax : create(,,,,,,)
//
// x1, y1 = coordination of the button
// textPtr = text pointer, depended on the type of the button
//
// [int] elastic = Whether the button is elastic
// Elastic button will pop up immediately when button release
// Non-elastic button will remain pushed until pop() is called
// (default : 1)
//
// [int] defIsPushed = default is_pushed : 1-Pushed, 0-Non-pushed
// (default : 0)
//
void Button::create_text(int pX1, int pY1, char* textPtr, char pElastic, char defIsPushed)
{
int pX2, pY2;
pX2 = pX1 + font_ptr->text_width( textPtr ) + 9;
pY2 = pY1 + font_ptr->height() + 7;
create( BUTTON_TEXT,pX1,pY1,pX2,pY2,textPtr,pElastic,defIsPushed);
}
//-------- End of function Button::create_text -----//
//-------- Begin of function Button::paint_text -------//
//
// Given only the top left position of the button, it will calculate
// the width and height of the button based on the given text and
// current button font.
//
// Syntax : create(,,,,,,)
//
// x1, y1 = coordination of the button
// textPtr = text pointer, depended on the type of the button
//
// [int] elastic = Whether the button is elastic
// Elastic button will pop up immediately when button release
// Non-elastic button will remain pushed until pop() is called
// (default : 1)
//
// [int] defIsPushed = default is_pushed : 1-Pushed, 0-Non-pushed
// (default : 0)
//
// Note : it use the color setting in (vga) and (font_san)
//
void Button::paint_text(int pX1, int pY1, char* textPtr, char pElastic, char defIsPushed)
{
int pX2, pY2;
pX2 = pX1 + font_ptr->text_width( textPtr ) + 9;
pY2 = pY1 + font_ptr->height() + 7;
create( BUTTON_TEXT,pX1,pY1,pX2,pY2,textPtr,pElastic,defIsPushed);
paint();
}
//-------- End of function Button::paint_text -----//
//-------- Begin of function Button::create -------//
//
// Syntax : create(,,,,,,)
//
// buttonType = BUTTON_TEXT (1) - text button, BUTTON_BITMAP (2) - icon button
// x1, y1 = coordination of the button
// x2, y2 = coordination of the button
// bodyPtr = text or icon pointer or pointer to user defined function,
// depended on the type of the button allow NULL icon
// pointer, which no icon will be displayed
// [int] elastic = Whether the button is elastic
// Elastic button will pop up immediately when button release
// Non-elastic button will remain pushed until pop() is called
// (default : 1)
//
// [int] defIsPushed = default is_pushed : 1-Pushed, 0-Non-pushed
// (default : 0)
//
// Note : it use the color setting in (vga) and (font_san)
//
void Button::create(int buttonType, int pX1, int pY1, int pX2, int pY2,
void* bodyPtr, char pElastic, char defIsPushed)
{
int strLen;
init_flag = 1;
button_type = buttonType;
x1 = pX1;
y1 = pY1;
x2 = pX2;
y2 = pY2;
elastic = pElastic;
is_pushed = defIsPushed;
enable_flag = 1;
//------------------------------------//
if( buttonType == BUTTON_TEXT )
{
strLen = strlen((char*)bodyPtr); // copy the string to class member buffer
// some string are temporary, we need it for repaint
if( strLen > STR_BUF_LEN )
strLen = STR_BUF_LEN;
memcpy( str_buf, bodyPtr, strLen );
str_buf[strLen] = NULL;
}
else
body_ptr = bodyPtr;
}
//--------- End of function Button::create --------//
//-------- Begin of function Button::set_body -------//
//
// bodyPtr = text or icon pointer or pointer to user defined function,
//
void Button::set_body(void* bodyPtr)
{
if( button_type == BUTTON_TEXT )
{
int strLen = strlen((char*)bodyPtr); // copy the string to class member buffer
// some string are temporary, we need it for repaint
if( strLen > STR_BUF_LEN )
strLen = STR_BUF_LEN;
memcpy( str_buf, bodyPtr, strLen );
str_buf[strLen] = NULL;
}
else
body_ptr = bodyPtr;
}
//--------- End of function Button::set_body --------//
//--------- Begin of function Button::hide ----------//
//
// Hide and disable the button
//
// Syntax : hide(char)
//
// backColor = background color
//
void Button::hide(char backColor)
{
if( init_flag )
{
init_flag = 0;
if( x1 >= 0 ) // when create() hasn't been called x1 is -1
Vga::active_buf->bar( x1,y1,x2,y2,backColor );
}
}
//------------ End of function Button::hide ---------//
//--------- Begin of function Button::show ----------//
//
// Show a button hiden by hide().
//
void Button::show()
{
if( !init_flag )
{
init_flag = 1;
paint(0, 1);
}
}
//------------ End of function Button::show ---------//
//----------- Begin of function Button::paint -----------//
//
// [int] defIsPushed = default is_pushed : 1-Pushed, 0-Non-pushed
// (default : is_pushed)
//
// [int] repaintBody = repaint the button body or only repaint panel sides
// (default : 1), 0 when called by detect()
//
void Button::paint(int defIsPushed, int repaintBody)
{
if( !init_flag )
return;
int colorUp = Vga::active_buf->color_up;
int colorLight = Vga::active_buf->color_light;
Vga::active_buf->color_light = (char) V_WHITE; // don't use layer colors
if( enable_flag )
{
if( defIsPushed >= 0 )
is_pushed = defIsPushed;
if( !is_pushed )
{
if( use_texture_flag )
vga.d3_panel_up( x1, y1, x2, y2 );
else
{
Vga::active_buf->color_up = Vga::active_buf->color_down;
Vga::active_buf->d3_panel_up( x1, y1, x2, y2, 1, repaintBody || button_type==1 );
}
}
else
{
if( use_texture_flag )
{
vga.d3_panel_down( x1, y1, x2, y2 );
}
else
{
if( repaintBody || button_type==1 ) // text button
Vga::active_buf->d3_panel_up( x1, y1, x2, y2, 2 );
Vga::active_buf->d3_panel_down( x1,y1,x2,y2, 1, 0 );
}
}
}
else // button disabled
{
Vga::active_buf->color_up = Vga::active_buf->color_up+1;
Vga::active_buf->d3_panel_up( x1, y1, x2, y2, 1, repaintBody );
}
Vga::active_buf->color_up = colorUp;
Vga::active_buf->color_light = colorLight;
//--------- put button body -------------//
if( button_type == BUTTON_TEXT ) // text button
{
int tx = x1 + ((x2-x1) - font_ptr->text_width(str_buf))/2;
int ty = y1 + ((y2-y1) - font_ptr->height())/2 - 1;
tx = max( tx, x1+4 );
ty = max( ty, y1+1 );
font_ptr->put( tx, ty, str_buf, 0, x2-3 );
}
else if( button_type == BUTTON_BITMAP )
{
if( body_ptr && repaintBody )
{
int tx = x1 + ((x2-x1+1) - *((short*)body_ptr))/2;
int ty = y1 + ((y2-y1+1) - *((short*)body_ptr+1))/2;
Vga::active_buf->put_bitmap( tx, ty, (char*) body_ptr ); // 0 means not clear background
}
}
else // BUTTON_UDF, user defined function
{
if( body_ptr )
(*((ButtonFP*)body_ptr))(x1+3,x2+3,y1-3,y2-3);
}
}
//---------- End of function Button::paint -----------//
//-------- Begin of function Button::detect -----------//
//
// Detect whether the button has been pressed,
// if so, act correspondly.
// Check for left mouse button only
//
// [unsigned] keyCode1 = if the specified key is pressed, emulate button pressed
// (default : 0)
//
// [unsigned] keyCode2 = if the specified key is pressed, emulate button pressed
// (default : 0)
//
// [int] detectRight = whether also detect the right button or not
// (default : 0)
//
// [int] suspendPop = don't pop up the button even it should
// (defalut : 0)
//
// Return : 1 - if left mouse button pressed
// 2 - if right mouse button pressed
// 3 - the key is pressed (only when keyCode is specified)
// 0 - if not
//
int Button::detect(unsigned keyCode1, unsigned keyCode2, int detectRight, int suspendPop)
{
int rc=0;
if( !init_flag || !enable_flag )
return 0;
help.set_help( x1, y1, x2, y2, help_code );
if( mouse.any_click(x1,y1,x2,y2,LEFT_BUTTON) )
rc=1;
else if( detectRight && mouse.any_click(x1,y1,x2,y2,RIGHT_BUTTON) )
rc=2;
else if(mouse.key_code)
{
unsigned mouseKey=mouse.key_code;
if( mouseKey >= 'a' && mouseKey <= 'z' ) // non-case sensitive comparsion
mouseKey -= 32; // convert from lower case to upper case
if( mouseKey == keyCode1 || mouseKey == keyCode2 || mouseKey == button_key )
{
rc=3;
}
}
if( !rc )
return 0;
//----- paint the button with pressed shape ------//
#define PRESSED_TIMEOUT_SECONDS 1 // 1 seconds
DWORD timeOutTime = m.get_time()+PRESSED_TIMEOUT_SECONDS*1000;
if( elastic )
{
if( !is_pushed )
paint(1,0); // 0-no need to repaint button body (text or icon)
while( (rc==1 && mouse.left_press) || (rc==2 && mouse.right_press) )
{
sys.yield();
mouse.get_event();
if( m.get_time() >= timeOutTime )
break;
}
if( elastic )
paint(0,0);
}
else // inelastic button
{
if( suspendPop )
is_pushed = 1;
else
is_pushed = !is_pushed;
paint(is_pushed,0);
while( (rc==1 && mouse.left_press) || (rc==2 && mouse.right_press) )
{
sys.yield();
mouse.get_event();
if( m.get_time() >= timeOutTime )
break;
}
}
return rc;
}
//----------- End of function Button::detect -------------//
//--------- Begin of function Button::wait_press ----------//
//
// Wait for user to press the button
//
// [int] timeOut - 1=enable inactive timeout
// 0=disable inactive timeout
// (default : 1 )
//
void Button::wait_press(int timeOut)
{
#define INACTIVE_TIMEOUT_SECONDS 10 // 10 seconds
int lastMouseX= -1, lastMouseY;
DWORD timeOutTime = m.get_time()+INACTIVE_TIMEOUT_SECONDS*1000;
mouse.get_event(); // clean up previous mouse events
while( !detect(KEY_RETURN,KEY_ESC) && !mouse.any_click(1) ) // 1-only right mouse button
{
sys.yield();
mouse.get_event();
//--- when the user is inactive for a certain time, ----//
//--------- close the report automatically -------------//
if( timeOut )
{
if( lastMouseX == mouse.cur_x && lastMouseY == mouse.cur_y )
{
if( m.get_time() >= timeOutTime )
break;
}
else
{
lastMouseX = mouse.cur_x;
lastMouseY = mouse.cur_y;
timeOutTime = m.get_time()+INACTIVE_TIMEOUT_SECONDS*1000;
}
}
}
}
//----------- End of function Button::wait_press ----------//
//.........................................................//
//-------- Begin of function ButtonGroup::ButtonGroup -------//
ButtonGroup::ButtonGroup(int buttonNum)
{
button_pressed = 0;
button_num = buttonNum;
button_array = new Button[buttonNum];
}
//---------- End of function ButtonGroup::ButtonGroup -------//
//----------- Begin of function ButtonGroup::~ButtonGroup -----------//
//
ButtonGroup::~ButtonGroup()
{
delete[] button_array;
}
//-------------- End of function ButtonGroup::~ButtonGroup ----------//
//--------- Begin of function ButtonGroup::paint ----------//
//
// Paint all buttons in this button nation.
//
// [int] buttonPressed = the default pressed button
// (default no change to button_pressed)
//
void ButtonGroup::paint(int buttonPressed)
{
int i;
if( buttonPressed >= 0 )
button_pressed = buttonPressed;
for( i=0 ; i -1 - if no button pressed
// >=0 - the record no. of the button pressed
//
int ButtonGroup::detect()
{
int i;
for( i=0 ; i buttonId = Id. of the button.
//
void ButtonGroup::push(int buttonId)
{
int i;
button_pressed = buttonId;
for( i=0 ; i buttonId = Id. of the button, start from 0
//
Button& ButtonGroup::operator[](int buttonId)
{
err_when( buttonId<0 || buttonId >= button_num );
return button_array[buttonId];
}
//----------- End of function ButtonGroup::operator[] ----------//