This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/wwui/dialogbase.cpp

1640 lines
35 KiB
C++
Raw Permalink Normal View History

/*
** Command & Conquer Renegade(tm)
** Copyright 2025 Electronic Arts Inc.
**
** 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 3 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/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Combat *
* *
* $Archive:: /Commando/Code/wwui/dialogbase.cpp $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 1/09/02 5:48p $*
* *
* $Revision:: 38 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "dialogbase.h"
#include "dialogparser.h"
#include "dialogcontrol.h"
#include "buttonctrl.h"
#include "dialogtext.h"
#include "editctrl.h"
#include "dialogmgr.h"
#include "ww3d.h"
#include "vector4.h"
#include "assetmgr.h"
#include "texture.h"
#include "mousemgr.h"
#include "comboboxctrl.h"
#include "checkboxctrl.h"
#include "sliderctrl.h"
#include "scrollbarctrl.h"
#include "menuentryctrl.h"
#include "tabctrl.h"
#include "listctrl.h"
#include "childdialog.h"
#include "mapctrl.h"
#include "viewerctrl.h"
#include "inputctrl.h"
#include "shortcutbarctrl.h"
#include "merchandisectrl.h"
#include "imagectrl.h"
#include "multilinetextctrl.h"
#include "treectrl.h"
#include "textmarqueectrl.h"
#include "ProgressCtrl.h"
#include "healthbarctrl.h"
#include "systimer.h"
#define DIRECTINPUT_VERSION 0x0800
#include <dinput.h>
////////////////////////////////////////////////////////////////
// Constants
////////////////////////////////////////////////////////////////
const float RES_SCREEN_WIDTH = 400;
const float RES_SCREEN_HEIGHT = 300;
////////////////////////////////////////////////////////////////
// Static member initialization
////////////////////////////////////////////////////////////////
DEFAULT_DLG_CMD_HANDLER DialogBaseClass::DefaultCmdHandler = NULL;
////////////////////////////////////////////////////////////////
//
// DialogBaseClass
//
////////////////////////////////////////////////////////////////
DialogBaseClass::DialogBaseClass (int res_id) :
DialogResID (res_id),
AreControlsHidden (false),
LastFocusControl (NULL),
LastMouseClickTime (0),
IsVisible (true),
IsRunning (false)
{
return ;
}
////////////////////////////////////////////////////////////////
//
// ~DialogBaseClass
//
////////////////////////////////////////////////////////////////
DialogBaseClass::~DialogBaseClass (void)
{
Free_Controls ();
return ;
}
////////////////////////////////////////////////////////////////
//
// Start_Dialog
//
////////////////////////////////////////////////////////////////
void
DialogBaseClass::Start_Dialog (void)
{
int dlg_width = 0;
int dlg_height = 0;
DynamicVectorClass<ControlDefinitionStruct> control_list;
//
// Get all the information about the dialog that we'll need to create
// the dialog and its controls.
//
DialogParserClass::Parse_Template (DialogResID, &dlg_width, &dlg_height,
&Title, &control_list);
//
// Convert the dialog's width and height from dialog units to screen units
//
const RectClass &screen_rect = Render2DClass::Get_Screen_Resolution ();
int dlg_screen_width = int(((float)dlg_width / RES_SCREEN_WIDTH) * screen_rect.Width ());
int dlg_screen_height = int(((float)dlg_height / RES_SCREEN_HEIGHT) * screen_rect.Height ());
//
// Center the dialog on the screen
//
Rect.Left = int(screen_rect.Center ().X - ((float)dlg_screen_width * 0.5F));
Rect.Top = int(screen_rect.Center ().Y - ((float)dlg_screen_height * 0.5F));
Rect.Right = int(Rect.Left + dlg_screen_width);
Rect.Bottom = int(Rect.Top + dlg_screen_height);
//
// Now create the controls
//
for (int index = 0; index < control_list.Count (); index ++) {
ControlDefinitionStruct &info = control_list[index];
DialogControlClass *control = NULL;
switch (info.type)
{
case BUTTON:
if ( (info.style & 0xF) == BS_CHECKBOX ||
(info.style & 0xF) == BS_AUTOCHECKBOX)
{
control = new CheckBoxCtrlClass;
} else if (info.style & BS_FLAT) {
control = new MenuEntryCtrlClass;
} else {
control = new ButtonCtrlClass;
}
break;
case STATIC:
if ((info.style & 0xF) == SS_BITMAP) {
control = new ImageCtrlClass;
} else {
control = new DialogTextClass;
}
break;
case EDIT:
if (info.style & ES_MULTILINE) {
if (info.style & ES_AUTOVSCROLL) {
control = new TextMarqueeCtrlClass;
} else {
control = new MultiLineTextCtrlClass;
}
} else {
control = new EditCtrlClass;
}
break;
case COMBOBOX:
control = new ComboBoxCtrlClass;
break;
case SLIDER:
control = new SliderCtrlClass;
break;
case SCROLL_BAR:
control = new ScrollBarCtrlClass;
break;
case TAB:
control = new TabCtrlClass;
break;
case LIST_CTRL:
control = new ListCtrlClass;
break;
case TREE_CTRL:
control = new TreeCtrlClass;
break;
case MAP:
control = new MapCtrlClass;
break;
case VIEWER:
control = new ViewerCtrlClass;
break;
case HOTKEY:
control = new InputCtrlClass;
break;
case SHORTCUT_BAR:
control = new ShortcutBarCtrlClass;
break;
case MERCHANDISE_CTRL:
control = new MerchandiseCtrlClass;
break;
case PROGRESS_BAR:
control = new ProgressCtrlClass;
break;
case HEALTH_BAR:
control = new HealthBarCtrlClass;
break;
}
//
// Add the control to the list (if necessary)
//
if (control != NULL) {
//
// Set the generic control information
//
control->Set_Parent (this);
control->Set_Text (info.title);
control->Set_Style (info.style);
control->Set_ID (info.id);
int ctrl_width = int((((float)info.cx) / RES_SCREEN_WIDTH) * screen_rect.Width ());
int ctrl_height = int((((float)info.cy) / RES_SCREEN_HEIGHT) * screen_rect.Height ());
//
// Calculate the screen position of the control
//
RectClass rect;
rect.Left = int(Rect.Left + ((((float)info.x) / RES_SCREEN_WIDTH) * screen_rect.Width ()));
rect.Top = int(Rect.Top + ((((float)info.y) / RES_SCREEN_HEIGHT) * screen_rect.Height ()));
rect.Right = int(rect.Left + ctrl_width);
rect.Bottom = int(rect.Top + ctrl_height);
control->Set_Window_Rect (rect);
//
// Let the control know its been created
//
control->On_Create ();
ControlList.Add (control);
//
// Apply the disabled style (if necessary)
//
if (info.style & WS_DISABLED) {
control->Enable (false);
}
}
}
DialogMgrClass::Register_Dialog (this);
IsRunning = true;
DialogEvent dlgEvent(DialogEvent::STARTED, this);
NotifyObservers(dlgEvent);
//
// Allow derived clases to hook into this call
//
On_Init_Dialog ();
return ;
}
////////////////////////////////////////////////////////////////
//
// End_Dialog
//
////////////////////////////////////////////////////////////////
void
DialogBaseClass::End_Dialog (void)
{
DialogEvent dlgEvent(DialogEvent::DESTROY, this);
NotifyObservers(dlgEvent);
On_Destroy ();
//
// Noitify all controls
//
for (int index = 0; index < ControlList.Count (); index ++) {
ControlList[index]->On_Destroy ();
}
//
// Release all child dialogs
//
for (index = 0; index < ChildDialogList.Count (); index ++) {
ChildDialogList[index]->End_Dialog ();
ChildDialogList[index]->Set_Parent_Dialog (NULL);
ChildDialogList[index]->Release_Ref ();
}
//
// Free the dialog list
//
ChildDialogList.Delete_All ();
IsRunning = false;
DialogMgrClass::UnRegister_Dialog (this);
return ;
}
////////////////////////////////////////////////////////////////
//
// On_Frame_Update
//
////////////////////////////////////////////////////////////////
void
DialogBaseClass::On_Frame_Update (void)
{
Add_Ref ();
if (AreControlsHidden == false) {
//
// Only take input from the mouse or keyboard if this is the
// currently active dialog.
//
if (Is_Active ()) {
Update_Mouse_State ();
}
//
// Let each control "think"
//
for (int index = 0; index < ControlList.Count (); index ++) {
ControlList[index]->On_Frame_Update ();
}
//
// Let each control "think"
//
for (index = 0; index < ChildDialogList.Count (); index ++) {
ChildDialogList[index]->On_Frame_Update ();
}
}
Release_Ref ();
return ;
}
////////////////////////////////////////////////////////////////
//
// Render
//
////////////////////////////////////////////////////////////////
void
DialogBaseClass::Render (void)
{
Add_Ref ();
//
// Render each control
//
if (AreControlsHidden == false) {
for (int index = 0; index < ControlList.Count (); index ++) {
if (ControlList[index]->Is_Visible ()) {
ControlList[index]->Render ();
}
}
//
// Render each child - dialog
//
for (index = 0; index < ChildDialogList.Count (); index ++) {
if (ChildDialogList[index]->Is_Visible ()) {
ChildDialogList[index]->Render ();
}
}
}
Release_Ref ();
return ;
}
////////////////////////////////////////////////////////////////
//
// Enable_Dlg_Item
//
////////////////////////////////////////////////////////////////
void
DialogBaseClass::Enable_Dlg_Item (int id, bool onoff)
{
//
// Find the control
//
DialogControlClass *control = Get_Dlg_Item (id);
if (control != NULL) {
//
// Change the enable state of hte control
//
control->Enable (onoff);
}
return ;
}
////////////////////////////////////////////////////////////////
//
// Is_Dlg_Item_Enabled
//
////////////////////////////////////////////////////////////////
bool
DialogBaseClass::Is_Dlg_Item_Enabled (int id)
{
bool retval = false;
//
// Find the control
//
DialogControlClass *control = Get_Dlg_Item (id);
if (control != NULL) {
//
// Return the state of the control to the caller
//
retval = control->Is_Enabled ();
}
return retval;
}
////////////////////////////////////////////////////////////////
//
// Get_Dlg_Item
//
////////////////////////////////////////////////////////////////
DialogControlClass *
DialogBaseClass::Get_Dlg_Item (int id) const
{
DialogControlClass *retval = NULL;
//
// Simply loop over all the controls in our list until we
// find one with the matching ID.
//
for (int index = 0; index < ControlList.Count (); index ++) {
if (id == ControlList[index]->Get_ID ()) {
retval = ControlList[index];
break;
}
}
return retval;
}
////////////////////////////////////////////////////////////////
//
// Get_Dlg_Item_Text
//
////////////////////////////////////////////////////////////////
const WCHAR *
DialogBaseClass::Get_Dlg_Item_Text (int id) const
{
const WCHAR *retval = NULL;
//
// Find the control
//
DialogControlClass *control = Get_Dlg_Item (id);
if (control != NULL) {
//
// Return the control's text to the caller
//
retval = control->Get_Text ();
}
return retval;
}
////////////////////////////////////////////////////////////////
//
// Set_Dlg_Item_Text
//
////////////////////////////////////////////////////////////////
void
DialogBaseClass::Set_Dlg_Item_Text (int id, const WCHAR *text)
{
//
// Find the control
//
DialogControlClass *control = Get_Dlg_Item (id);
if (control != NULL) {
//
// Set the text of this control
//
control->Set_Text (text);
}
return ;
}
////////////////////////////////////////////////////////////////
//
// Get_Dlg_Item_Int
//
////////////////////////////////////////////////////////////////
int
DialogBaseClass::Get_Dlg_Item_Int (int id) const
{
int retval = 0;
//
// Find the control
//
DialogControlClass *control = Get_Dlg_Item (id);
if (control != NULL) {
//
// Get the text from the control
//
const WCHAR *text = control->Get_Text ();
//
// Convert the text to an integer
//
retval = _wtoi (text);
}
return retval;
}
////////////////////////////////////////////////////////////////
//
// Set_Dlg_Item_Int
//
////////////////////////////////////////////////////////////////
void
DialogBaseClass::Set_Dlg_Item_Int (int id, int value)
{
//
// Find the control
//
DialogControlClass *control = Get_Dlg_Item (id);
if (control != NULL) {
//
// Convert the value to a string
//
WideStringClass text;
text.Format (L"%d", value);
//
// Set the text of this control
//
control->Set_Text (text);
}
return ;
}
////////////////////////////////////////////////////////////////
//
// Get_Dlg_Item_Float
//
////////////////////////////////////////////////////////////////
float
DialogBaseClass::Get_Dlg_Item_Float (int id) const
{
float retval = 0;
//
// Find the control
//
DialogControlClass *control = Get_Dlg_Item (id);
if (control != NULL) {
//
// Get the text from the control
//
const WCHAR *text = control->Get_Text ();
//
// Convert the text to an float
//
swscanf (text, L"%f", &retval);
}
return retval;
}
////////////////////////////////////////////////////////////////
//
// Set_Dlg_Item_Float
//
////////////////////////////////////////////////////////////////
void
DialogBaseClass::Set_Dlg_Item_Float (int id, float value)
{
//
// Find the control
//
DialogControlClass *control = Get_Dlg_Item (id);
if (control != NULL) {
//
// Convert the value to a string
//
WideStringClass text;
text.Format (L"%.2f", value);
//
// Set the text of this control
//
control->Set_Text (text);
}
return ;
}
////////////////////////////////////////////////////////////////
//
// Check_Dlg_Button
//
////////////////////////////////////////////////////////////////
void
DialogBaseClass::Check_Dlg_Button (int id, bool onoff)
{
//
// Find the control
//
DialogControlClass *control = Get_Dlg_Item (id);
if (control != NULL && control->As_CheckBoxCtrlClass () != NULL) {
//
// Set the check state of this control
//
control->As_CheckBoxCtrlClass ()->Set_Check (onoff);
}
return ;
}
////////////////////////////////////////////////////////////////
//
// Is_Dlg_Button_Checked
//
////////////////////////////////////////////////////////////////
bool
DialogBaseClass::Is_Dlg_Button_Checked (int id) const
{
bool retval = false;
//
// Find the control
//
DialogControlClass *control = Get_Dlg_Item (id);
if (control != NULL && control->As_CheckBoxCtrlClass () != NULL) {
//
// Return the check state of this control to the caller
//
retval = control->As_CheckBoxCtrlClass ()->Get_Check ();
}
return retval;
}
////////////////////////////////////////////////////////////////
//
// Free_Controls
//
////////////////////////////////////////////////////////////////
void
DialogBaseClass::Free_Controls (void)
{
for (int index = 0; index < ControlList.Count (); index ++) {
if (ControlList[index]->Is_Embedded () == false) {
delete ControlList[index];
}
}
ControlList.Delete_All ();
//
// Reset our pointers
//
//FocusControl = NULL;
LastFocusControl = NULL;
return ;
}
////////////////////////////////////////////////////////////////
//
// Send_Mouse_Input
//
////////////////////////////////////////////////////////////////
void
DialogBaseClass::Send_Mouse_Input (DialogControlClass *control, const Vector2 &mouse_pos)
{
//
// Check to see if the mouse is moving or not
//
const Vector3 &last_mouse_pos = DialogMgrClass::Get_Last_Mouse_Pos ();
if (last_mouse_pos.X != mouse_pos.X || last_mouse_pos.Y != mouse_pos.Y) {
control->On_Mouse_Move (mouse_pos);
}
//
// Let the control change the mouse cursor
//
control->On_Set_Cursor (mouse_pos);
//
// Notify the control on button down or up
//
if (DialogMgrClass::Is_Button_Down (VK_LBUTTON) != DialogMgrClass::Was_Button_Down (VK_LBUTTON)) {
if (DialogMgrClass::Is_Button_Down (VK_LBUTTON)) {
int curr_time = TIMEGETTIME ();
//
// Did we just get a double-click?
//
if ((curr_time - LastMouseClickTime) < 300) {
control->On_LButton_DblClk (mouse_pos);
} else {
control->On_LButton_Down (mouse_pos);
}
LastMouseClickTime = TIMEGETTIME ();
} else {
//
// Notify the control
//
control->On_LButton_Up (mouse_pos);
}
}
//
// Notify the control on button down or up
//
if (DialogMgrClass::Is_Button_Down (VK_RBUTTON) != DialogMgrClass::Was_Button_Down (VK_RBUTTON)) {
if (DialogMgrClass::Is_Button_Down (VK_RBUTTON)) {
control->On_RButton_Down (mouse_pos);
} else {
control->On_RButton_Up (mouse_pos);
}
}
//
// Notify the control on button down or up
//
if (DialogMgrClass::Is_Button_Down (VK_MBUTTON) != DialogMgrClass::Was_Button_Down (VK_MBUTTON)) {
if (DialogMgrClass::Is_Button_Down (VK_MBUTTON)) {
control->On_MButton_Down (mouse_pos);
} else {
control->On_MButton_Up (mouse_pos);
}
}
return;
}
////////////////////////////////////////////////////////////////
//
// Update_Mouse_State
//
////////////////////////////////////////////////////////////////
void
DialogBaseClass::Update_Mouse_State (void)
{
//
// Get the cursor's position
//
Vector3 cursor_pos = DialogMgrClass::Get_Mouse_Pos ();
Vector2 screen_pos (cursor_pos.X, cursor_pos.Y);
DialogControlClass *current_control = NULL;
//
// Build a complete list of controls
//
CONTROL_LIST control_list;
Build_Control_List (control_list);
//
// Loop over all the controls on the dialog
//
bool mouse_over_control = false;
for (int index = control_list.Count () - 1; index >= 0; index --) {
const RectClass &rect = control_list[index]->Get_Window_Rect ();
//
// Is the mouse point inside this control?
//
if (rect.Contains (screen_pos)) {
//
// Check for "focus" change
//
if (DialogMgrClass::Is_Button_Down (VK_LBUTTON) != DialogMgrClass::Was_Button_Down (VK_LBUTTON)) {
if (DialogMgrClass::Is_Button_Down (VK_LBUTTON)) {
//
// Handle the focus change (if necessary)
//
if ( control_list[index]->Wants_Focus () &&
control_list[index]->Is_Enabled ())
{
DialogMgrClass::Set_Focus (control_list[index]);
}
}
}
current_control = control_list[index];
mouse_over_control = true;
break;
}
}
DialogControlClass *input_capture = DialogMgrClass::Get_Capture ();
DialogControlClass *control = input_capture ? input_capture : current_control;
if (control != NULL && control->Is_Enabled () && control->Is_Visible ()) {
//
// Send mouse input to the control
//
Send_Mouse_Input (control, screen_pos);
} else {
//
// Reset the mouse cursor to an arrow if no control changed it...
//
MouseMgrClass::Set_Cursor (MouseMgrClass::CURSOR_ARROW);
//
// If the user clicked in empty space, then NULL out the focus'd control
//
if ( DialogMgrClass::Is_Button_Down (VK_LBUTTON) &&
DialogMgrClass::Was_Button_Down (VK_LBUTTON))
{
DialogMgrClass::Set_Focus (NULL);
}
}
//
// Check for mouse wheel activity
//
const Vector3 &last_mouse_pos = DialogMgrClass::Get_Last_Mouse_Pos ();
if (last_mouse_pos.Z != cursor_pos.Z && DialogMgrClass::Get_Focus () != NULL) {
DialogMgrClass::Get_Focus ()->On_Mouse_Wheel ((int)(last_mouse_pos.Z - cursor_pos.Z));
}
//
// Store our cached button states
//
DialogMgrClass::Set_Last_Mouse_Pos (cursor_pos);
return ;
}
////////////////////////////////////////////////////////////////
//
// On_Command
//
////////////////////////////////////////////////////////////////
void
DialogBaseClass::On_Command (int ctrl_id, int message_id, DWORD param)
{
//
// Allow the default handler to process this command
//
if (DefaultCmdHandler != NULL) {
(*DefaultCmdHandler) (this, ctrl_id, message_id, param);
}
return ;
}
////////////////////////////////////////////////////////////////
//
// On_Activate
//
////////////////////////////////////////////////////////////////
void
DialogBaseClass::On_Activate (bool onoff)
{
if (onoff == false) {
//
// Cache the current focus control between dialogs (if possible)
//
for (int index = 0; index < ControlList.Count (); index ++) {
if (ControlList[index] == DialogMgrClass::Get_Focus ()) {
LastFocusControl = ControlList[index];
break;
}
}
//
// Let go of the currently focus'd control
//
DialogMgrClass::Set_Focus (NULL);
DialogEvent dlgEvent(DialogEvent::DEACTIVATED, this);
NotifyObservers(dlgEvent);
} else {
if (LastFocusControl != NULL) {
DialogMgrClass::Set_Focus (LastFocusControl);
} else {
Set_Default_Focus ();
}
DialogEvent dlgEvent(DialogEvent::ACTIVATED, this);
NotifyObservers(dlgEvent);
}
return ;
}
////////////////////////////////////////////////////////////////
//
// Is_Active
//
////////////////////////////////////////////////////////////////
bool
DialogBaseClass::Is_Active (void)
{
return (DialogMgrClass::Get_Active_Dialog () == this);
}
////////////////////////////////////////////////////////////////
//
// On_Key_Down
//
////////////////////////////////////////////////////////////////
bool
DialogBaseClass::On_Key_Down (uint32 key_id, uint32 key_data)
{
bool handled = false;
Add_Ref ();
//
// Determine what control to send the input to
//
DialogControlClass *input_capture = DialogMgrClass::Get_Capture ();
DialogControlClass *input = input_capture ? input_capture : DialogMgrClass::Get_Focus ();
//
// Special case some of the keys
//
if (key_id == VK_ESCAPE) {
On_Command (IDCANCEL, 0, 0);
handled = true;
} else if (key_id == VK_TAB) {
//
// Determine whether to go forward or backward through the controls
//
int inc = 1;
if ((DialogMgrClass::Get_VKey_State (VK_SHIFT) & VKEY_PRESSED) == VKEY_PRESSED) {
inc = -1;
}
//
// Find the next (or previous) control
//
DialogControlClass *control = Find_Next_Control (DialogMgrClass::Get_Focus (), inc);
//
// Set the new focus control
//
if (control != NULL) {
DialogMgrClass::Set_Focus (control);
handled = true;
}
} else if (input != NULL) {
//
// Send out the standard On_OK notification if the user
// pressed enter
//
if ( input->As_ButtonCtrlClass () == NULL &&
input->As_MenuEntryCtrlClass () == NULL &&
key_id == VK_RETURN)
{
On_Command (IDOK, 0, 0);
handled = true;
}
//
// Pass keyboard input onto the control
//
handled = input->On_Key_Down (key_id, key_data);
}
Release_Ref ();
return handled;
}
////////////////////////////////////////////////////////////////
//
// On_Key_Up
//
////////////////////////////////////////////////////////////////
bool
DialogBaseClass::On_Key_Up (uint32 key_id)
{
bool handled = false;
Add_Ref ();
DialogControlClass *input_capture = DialogMgrClass::Get_Capture ();
DialogControlClass *input = input_capture ? input_capture : DialogMgrClass::Get_Focus ();
//
// Pass keyboard input onto the control
//
if (input != NULL) {
handled = input->On_Key_Up (key_id);
}
Release_Ref ();
return handled;
}
////////////////////////////////////////////////////////////////
//
// On_Unicode_Char
//
////////////////////////////////////////////////////////////////
void
DialogBaseClass::On_Unicode_Char(uint16 unicode)
{
Add_Ref ();
//
// Determine what control to send the input to
//
DialogControlClass *input_capture = DialogMgrClass::Get_Capture ();
DialogControlClass *input = input_capture ? input_capture : DialogMgrClass::Get_Focus ();
if (input != NULL) {
//
// Pass keyboard input onto the control
//
input->On_Unicode_Char (unicode);
}
Release_Ref ();
return ;
}
////////////////////////////////////////////////////////////////
//
// Find_Next_Control
//
////////////////////////////////////////////////////////////////
DialogControlClass *
DialogBaseClass::Find_Next_Control
(
DialogControlClass * control,
int direction
)
{
DialogControlClass *retval = NULL;
//
// Build a complete list of controls
//
CONTROL_LIST control_list;
Build_Control_List (control_list);
//
// Find the index of the control
//
int focus_index = max (control_list.ID (control), 0);
int new_focus_index = -1;
int inc = (direction < 0) ? -1 : 1;
//
// Find the next control in the sequence
//
int count = control_list.Count ();
for (int index = focus_index; index >= 0 && index < count; index += inc) {
//
// Bound the index
//
new_focus_index = index + inc;
if (new_focus_index >= count) {
new_focus_index = 0;
} else if (new_focus_index < 0) {
new_focus_index = count - 1;
}
//
// Does this control want the focus?
//
if ( control_list[new_focus_index]->Wants_Focus () &&
control_list[new_focus_index]->Is_Enabled ())
{
break;
}
}
if (new_focus_index >= 0) {
retval = control_list[new_focus_index];
}
return retval;
}
////////////////////////////////////////////////////////////////
//
// Find_Next_Group_Control
//
////////////////////////////////////////////////////////////////
DialogControlClass *
DialogBaseClass::Find_Next_Group_Control
(
DialogControlClass * control,
int direction
)
{
//
// Build a complete list of controls
//
CONTROL_LIST control_list;
Build_Control_List (control_list);
//
// Remove any disabled controls
//
/*for (int index = control_list.Count () - 1; index >= 0; index --) {
if (control_list[index]->Is_Enabled () == false) {
control_list.Delete (index);
}
}*/
//
// Find the index of the control
//
int curr_index = max (control_list.ID (control), 0);
int new_index = -1;
if (direction < 0) {
if ( (control_list[curr_index]->Get_Style () & WS_GROUP) ||
(curr_index == 0))
{
//
// Wrap around to the last control in the group
//
for (int index = curr_index + 1; index < control_list.Count (); index ++) {
//
// Is this the start of the next group?
//
if (control_list[index]->Get_Style () & WS_GROUP) {
break;
}
new_index = index;
}
} else {
//
// Simply move to the previous control (its in the group)
//
new_index = curr_index - 1;
}
} else {
if ( curr_index == (control_list.Count () - 1) ||
(control_list[curr_index + 1]->Get_Style () & WS_GROUP))
{
//
// Wrap around to the first control in the group
//
for (int index = curr_index; index >= 0; index --) {
new_index = index;
//
// Is this the first control in the group?
//
if (control_list[index]->Get_Style () & WS_GROUP) {
break;
}
}
} else {
//
// Simply move to the next control (its in the group)
//
new_index = curr_index + 1;
}
}
//
// Index into the list and return the pointer to the caller
//
DialogControlClass *retval = NULL;
if (new_index >= 0) {
retval = control_list[new_index];
}
return retval;
}
////////////////////////////////////////////////////////////////
//
// Find_Control_Index
//
////////////////////////////////////////////////////////////////
int
DialogBaseClass::Find_Control_Index (DialogControlClass *control)
{
return ControlList.ID (control);
}
////////////////////////////////////////////////////////////////
//
// Add_Control
//
////////////////////////////////////////////////////////////////
void
DialogBaseClass::Add_Control (DialogControlClass *control)
{
//
// Simply add the control to the list
//
if (ControlList.ID (control) == -1) {
ControlList.Add (control);
control->Set_Parent (this);
control->On_Add_To_Dialog ();
}
return ;
}
////////////////////////////////////////////////////////////////
//
// Remove_Control
//
////////////////////////////////////////////////////////////////
void
DialogBaseClass::Remove_Control (DialogControlClass *control)
{
//
// Simply remove the control from the list
//
int index = ControlList.ID (control);
if (index != -1) {
control->On_Remove_From_Dialog ();
control->Set_Parent (NULL);
//
// Remove the control from the list (note: its possible
// the index might of changed since we last checked)
//
index = ControlList.ID (control);
if (index != -1) {
ControlList.Delete (index);
}
//
// Remove the capture if we just removed the control
//
if (control == DialogMgrClass::Get_Capture ()) {
DialogMgrClass::Release_Capture ();
}
}
return ;
}
////////////////////////////////////////////////////////////////
//
// Find_Control
//
////////////////////////////////////////////////////////////////
DialogControlClass *
DialogBaseClass::Find_Control (const Vector2 &mouse_pos)
{
DialogControlClass *retval = NULL;
//
// Build a complete list of controls
//
CONTROL_LIST control_list;
Build_Control_List (control_list);
//
// Loop over all the controls
//
for (int index = control_list.Count () - 1; index >= 0; index --) {
//
// Is the mouse over this control?
//
const RectClass &rect = control_list[index]->Get_Window_Rect ();
if (rect.Contains (mouse_pos)) {
//
// Return the control to the caller
//
retval = control_list[index];
break;
}
}
return retval;
}
////////////////////////////////////////////////////////////////
//
// Find_Focus_Control
//
////////////////////////////////////////////////////////////////
int
DialogBaseClass::Find_Focus_Control (void)
{
int focus_index = -1;
//
// Loop over all the controls in the list
//
for (int index = 0; index < ControlList.Count (); index ++) {
if (DialogMgrClass::Get_Focus () == ControlList[index]) {
focus_index = index;
break;
}
}
return focus_index;
}
////////////////////////////////////////////////////////////////
//
// Add_Child_Dialog
//
////////////////////////////////////////////////////////////////
void
DialogBaseClass::Add_Child_Dialog (ChildDialogClass *child)
{
//
// Simply add the dialog to our list
//
if (ChildDialogList.ID (child) == -1) {
ChildDialogList.Add (child);
child->Set_Parent_Dialog (this);
child->Add_Ref ();
}
return ;
}
////////////////////////////////////////////////////////////////
//
// Remove_Child_Dialog
//
////////////////////////////////////////////////////////////////
void
DialogBaseClass::Remove_Child_Dialog (ChildDialogClass *child)
{
bool reset_focus = false;
//
// Simply remove the control from the list
//
int index = ChildDialogList.ID (child);
if (index != -1) {
//
// Check to see if the current focus control belongs to this
// dialog
//
if ( DialogMgrClass::Get_Focus () != NULL &&
DialogMgrClass::Get_Focus ()->Peek_Parent () == child)
{
DialogMgrClass::Set_Focus (NULL);
reset_focus = true;
}
//
// Remove the control from the list
//
child->Set_Parent_Dialog (NULL);
child->Release_Ref ();
ControlList.Delete (index);
}
//
// Reset the focus to the first control we find that wants it
//
if (reset_focus) {
DialogMgrClass::Set_Focus (Find_Next_Control (NULL));
}
return ;
}
////////////////////////////////////////////////////////////////
//
// Build_Control_List
//
////////////////////////////////////////////////////////////////
void
DialogBaseClass::Build_Control_List (CONTROL_LIST &list)
{
//
// First off add all the controls on this dialog to the list
//
for (int index = 0; index < ControlList.Count (); index ++) {
if (ControlList[index]->Is_Enabled ()) {
list.Add (ControlList[index]);
}
}
//
// Next, add in the control from each dialog
//
for (index = 0; index < ChildDialogList.Count (); index ++) {
if (ChildDialogList[index]->Is_Visible ()) {
ChildDialogList[index]->Build_Control_List (list);
}
}
return ;
}
////////////////////////////////////////////////////////////////
//
// Set_Rect
//
////////////////////////////////////////////////////////////////
void
DialogBaseClass::Set_Rect (const RectClass &rect)
{
if (rect == Rect) {
return ;
}
Vector2 offset = rect.Upper_Left () - Rect.Upper_Left ();
//
// Move all the controls
//
for (int index = 0; index < ControlList.Count (); index ++) {
//
// Offset this control
//
if (ControlList[index]->Is_Embedded () == false) {
Vector2 old_pos = ControlList[index]->Get_Window_Pos ();
ControlList[index]->Set_Window_Pos (old_pos + offset);
}
}
//
// Move all the child dialogs
//
for (index = 0; index < ChildDialogList.Count (); index ++) {
//
// Offset this dialog
//
RectClass rect = ChildDialogList[index]->Get_Rect ();
rect.Left += offset.X;
rect.Right += offset.X;
rect.Top += offset.Y;
rect.Bottom += offset.Y;
ChildDialogList[index]->Set_Rect (rect);
}
Rect = rect;
return ;
}
////////////////////////////////////////////////////////////////
//
// On_Init_Dialog
//
////////////////////////////////////////////////////////////////
void
DialogBaseClass::On_Init_Dialog (void)
{
if (DialogMgrClass::Get_Focus () == NULL) {
Set_Default_Focus ();
} else {
//DialogMgrClass::Get_Focus ()->Center_Mouse ();
}
return ;
}
////////////////////////////////////////////////////////////////
//
// Set_Default_Focus
//
////////////////////////////////////////////////////////////////
void
DialogBaseClass::Set_Default_Focus (void)
{
//
// Build a complete list of controls
//
CONTROL_LIST control_list;
Build_Control_List (control_list);
//
// Set the focus to the first control that wants it
//
for (int index = 0; index < control_list.Count (); index ++) {
if (control_list[index]->Wants_Focus () && control_list[index]->Is_Enabled ()) {
DialogMgrClass::Set_Focus (control_list[index]);
//
// Put the mouse cursor in the middle of this control
//
//control_list[index]->Center_Mouse ();
break;
}
}
return ;
}
////////////////////////////////////////////////////////////////
//
// On_Mouse_Wheel
//
////////////////////////////////////////////////////////////////
void
DialogBaseClass::On_Mouse_Wheel (int direction)
{
if (DialogMgrClass::Get_Focus () != NULL) {
DialogMgrClass::Get_Focus ()->On_Mouse_Wheel (direction);
}
return ;
}
void DialogBaseClass::Set_Dirty(bool onoff)
{
for (int index = 0; index < ControlList.Count (); index ++) {
ControlList[index]->Set_Dirty();
}
//
// Render each child - dialog
//
for (index = 0; index < ChildDialogList.Count (); index ++) {
ChildDialogList[index]->Set_Dirty();
}
}