| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783 |
- /*
- ** 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/dropdownctrl.cpp $*
- * *
- * Author:: Patrick Smith *
- * *
- * $Modtime:: 1/07/02 10:42a $*
- * *
- * $Revision:: 17 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- // Disable warning about exception handling not being enabled. It's used as part of STL - in a part of STL we don't use.
- #pragma warning(disable : 4530)
- #include "dropdownctrl.h"
- #include "comboboxctrl.h"
- #include "dialogbase.h"
- #include "assetmgr.h"
- #include "refcount.h"
- #include "font3d.h"
- #include "mousemgr.h"
- #include "ww3d.h"
- #include "dialogmgr.h"
- #include "stylemgr.h"
- ////////////////////////////////////////////////////////////////
- //
- // DropDownCtrlClass
- //
- ////////////////////////////////////////////////////////////////
- DropDownCtrlClass::DropDownCtrlClass (void) :
- CellSize (0, 0),
- CurrSel (-1),
- ComboBox (NULL),
- ScrollPos (0),
- CountPerPage (0),
- FullRect (0, 0, 0, 0),
- DisplayScrollBar (false)
- {
- //
- // Set the font for the text renderers
- //
- StyleMgrClass::Assign_Font (&TextRenderer, StyleMgrClass::FONT_LISTS);
- //
- // We don't want the scroll bar getting focus
- //
- ScrollBarCtrl.Set_Wants_Focus (false);
- ScrollBarCtrl.Set_Small_BMP_Mode (true);
- ScrollBarCtrl.Set_Advise_Sink (this);
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // ~DropDownCtrlClass
- //
- ////////////////////////////////////////////////////////////////
- DropDownCtrlClass::~DropDownCtrlClass (void)
- {
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Create_Text_Renderer
- //
- ////////////////////////////////////////////////////////////////
- void
- DropDownCtrlClass::Create_Text_Renderer (void)
- {
- HilightRenderer.Reset ();
- HilightRenderer.Set_Coordinate_Range (Render2DClass::Get_Screen_Resolution());
- StyleMgrClass::Configure_Hilighter (&HilightRenderer);
- //
- // Setup the coordinate system of the renderer
- //
- TextRenderer.Reset ();
- //
- // Add each string to the list
- //
- float curr_y_pos = ClientRect.Top;
- for (int index = ScrollPos; index < EntryList.Count (); index ++) {
- //
- // Get the width and height of the current entry
- //
- const WCHAR *text = EntryList[index].text;
- Vector2 text_extent = TextRenderer.Get_Text_Extents (text);
- //
- // Build a rectangle we'll draw the text into
- //
- RectClass text_rect;
- text_rect.Left = ClientRect.Left;
- text_rect.Top = curr_y_pos;
- text_rect.Right = text_rect.Left + CellSize.X;
- text_rect.Bottom = text_rect.Top + CellSize.Y;
- if (text_rect.Bottom <= ClientRect.Bottom) {
- //
- // Draw the text
- //
- StyleMgrClass::Render_Text (text, &TextRenderer, text_rect, true, true);
- //
- // Hilight this entry (if its the currently selected one)
- //
- if (index == CurrSel) {
- StyleMgrClass::Render_Hilight (&HilightRenderer, text_rect);
- }
- }
- //
- // Move on to the next y-position
- //
- curr_y_pos += CellSize.Y;
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Create_Control_Renderer
- //
- ////////////////////////////////////////////////////////////////
- void
- DropDownCtrlClass::Create_Control_Renderer (void)
- {
- //
- // Configure this renderer
- //
- ControlRenderer.Reset ();
- ControlRenderer.Enable_Texturing (false);
- ControlRenderer.Set_Coordinate_Range (Render2DClass::Get_Screen_Resolution());
- ControlRenderer.Add_Quad (FullRect, RGBA_TO_INT32 (0, 0, 0, 236));
- //
- // Lookup the colors to use
- //
- int color = StyleMgrClass::Get_Line_Color ();
- int bkcolor = StyleMgrClass::Get_Bk_Color ();
- //
- // Draw the control outline
- //
- RectClass rect = Rect;
- ControlRenderer.Add_Outline (rect, 1.0F, color);
- //
- // Now draw the background
- //
- rect.Right -= 1;
- rect.Bottom -= 1;
- ControlRenderer.Add_Quad (rect, bkcolor);
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // On_Set_Cursor
- //
- ////////////////////////////////////////////////////////////////
- void
- DropDownCtrlClass::On_Set_Cursor (const Vector2 &mouse_pos)
- {
- //
- // Change the mouse cursor if necessary
- //
- if (ClientRect.Contains (mouse_pos)) {
- MouseMgrClass::Set_Cursor (MouseMgrClass::CURSOR_ACTION);
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Update_Client_Rect
- //
- ////////////////////////////////////////////////////////////////
- void
- DropDownCtrlClass::Update_Client_Rect (void)
- {
- Rect = FullRect;
- //
- // Determine what one character spacing would be
- //
- Vector2 char_size = TextRenderer.Get_Text_Extents (L"W");
- float border_width = char_size.X + 2;
- float border_height = 2;
- //
- // Shrink the client area
- //
- ClientRect = Rect;
- ClientRect.Inflate (Vector2 (-border_width, -border_height));
- //
- // Calculate how each "text" cell should be
- //
- CellSize.X = int(ClientRect.Width ());
- CellSize.Y = int(char_size.Y * 1.5F);
- //
- // Update the number of entries we can display at one time
- //
- CountPerPage = int(ClientRect.Height () / CellSize.Y);
- //
- // Do we need to show a scroll bar?
- //
- if (CountPerPage < EntryList.Count ()) {
- float width = (char_size.X * 3);
- //
- // Calculate the width of the scroll bar
- //
- RectClass scroll_rect;
- scroll_rect.Left = Rect.Right - width;
- scroll_rect.Top = Rect.Top;
- scroll_rect.Right = Rect.Right;
- scroll_rect.Bottom = Rect.Bottom;
- //
- // Size the scroll bar
- //
- ScrollBarCtrl.Set_Window_Rect (scroll_rect);
- ScrollBarCtrl.Set_Page_Size (CountPerPage - 1);
- ScrollBarCtrl.Set_Range (0, EntryList.Count () - CountPerPage);
- DisplayScrollBar = true;
- //
- // Shrink the client area
- //
- float new_width = ScrollBarCtrl.Get_Window_Rect ().Left;
- ClientRect.Right = new_width;
- Rect.Right = new_width;
- CellSize.X = int(ClientRect.Width ());
- }
- Set_Dirty ();
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Render
- //
- ////////////////////////////////////////////////////////////////
- void
- DropDownCtrlClass::Render (void)
- {
- //
- // Recreate the renderers (if necessary)
- //
- if (IsDirty) {
- Create_Control_Renderer ();
- Create_Text_Renderer ();
- }
- //
- // Render the background and text for the current state
- //
- ControlRenderer.Render ();
- TextRenderer.Render ();
- HilightRenderer.Render ();
- DialogControlClass::Render ();
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // On_LButton_Down
- //
- ////////////////////////////////////////////////////////////////
- void
- DropDownCtrlClass::On_LButton_Down (const Vector2 &mouse_pos)
- {
- Set_Curr_Sel (Entry_From_Pos (mouse_pos));
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // On_LButton_Up
- //
- ////////////////////////////////////////////////////////////////
- void
- DropDownCtrlClass::On_LButton_Up (const Vector2 &mouse_pos)
- {
- Set_Curr_Sel (Entry_From_Pos (mouse_pos));
- if (ComboBox) {
- ComboBox->On_Drop_Down_End (CurrSel);
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // On_Mouse_Move
- //
- ////////////////////////////////////////////////////////////////
- void
- DropDownCtrlClass::On_Mouse_Move (const Vector2 &mouse_pos)
- {
- if (DialogMgrClass::Is_Button_Down (VK_LBUTTON)) {
- Set_Curr_Sel (Entry_From_Pos (mouse_pos));
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // On_Key_Down
- //
- ////////////////////////////////////////////////////////////////
- bool
- DropDownCtrlClass::On_Key_Down (uint32 key_id, uint32 key_data)
- {
- bool handled = true;
- switch (key_id)
- {
- case VK_HOME:
- Set_Curr_Sel (0);
- break;
- case VK_END:
- Set_Curr_Sel (EntryList.Count () - 1);
- break;
- case VK_UP:
- case VK_LEFT:
- Set_Curr_Sel (CurrSel - 1);
- break;
- case VK_DOWN:
- case VK_RIGHT:
- Set_Curr_Sel (CurrSel + 1);
- break;
- default:
- handled = false;
- break;
- }
- return handled;
- }
- ////////////////////////////////////////////////////////////////
- //
- // On_Create
- //
- ////////////////////////////////////////////////////////////////
- void
- DropDownCtrlClass::On_Create (void)
- {
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // On_Kill_Focus
- //
- ////////////////////////////////////////////////////////////////
- void
- DropDownCtrlClass::On_Kill_Focus (DialogControlClass *focus)
- {
- //
- // Noitify the combobox that we are done
- //
- if (ComboBox) {
- ComboBox->On_Drop_Down_End (CurrSel);
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Add_String
- //
- ////////////////////////////////////////////////////////////////
- int
- DropDownCtrlClass::Add_String (const WCHAR* string)
- {
- if (string == NULL) {
- return -1;
- }
- //
- // Add the entry to the list
- //
- EntryList.Add (ENTRY (string, 0));
- //
- // Force scrollbars, etc to be recalculated and painted
- //
- Update_Client_Rect ();
- Set_Dirty ();
- return (EntryList.Count () - 1);
- }
- ////////////////////////////////////////////////////////////////
- //
- // Delete_String
- //
- ////////////////////////////////////////////////////////////////
- void
- DropDownCtrlClass::Delete_String (int index)
- {
- if (index >= 0 && index < EntryList.Count ()) {
- //
- // Delete the entry
- //
- EntryList.Delete (index);
- Set_Curr_Sel (min (CurrSel, EntryList.Count () - 1));
- Set_Dirty ();
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Find_String
- //
- ////////////////////////////////////////////////////////////////
- int
- DropDownCtrlClass::Find_String (const WCHAR* string)
- {
- int retval = -1;
- if (string) {
- for (int index = 0; index < EntryList.Count (); index ++) {
- //
- // If this is the entry the user is requesting, then
- // return its index to the caller
- //
- if (EntryList[index].text.Compare_No_Case (string) == 0) {
- retval = index;
- break;
- }
- }
- }
- return retval;
- }
- int DropDownCtrlClass::Find_Closest_String(const WCHAR* string)
- {
- int retval = -1;
- if (string && (wcslen(string) > 0)) {
- for (int index = 0; index < EntryList.Count (); index ++) {
- int relation = EntryList[index].text.Compare_No_Case(string);
- if (relation == 0) {
- return index;
- } else if (relation < 0) {
- return index;
- }
- }
- }
- return retval;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Set_Item_Data
- //
- ////////////////////////////////////////////////////////////////
- void
- DropDownCtrlClass::Set_Item_Data (int index, uint32 data)
- {
- //
- // Index into the list and set the user data
- //
- if (index >= 0 && index < EntryList.Count ()) {
- EntryList[index].user_data = data;
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Get_Item_Data
- //
- ////////////////////////////////////////////////////////////////
- uint32
- DropDownCtrlClass::Get_Item_Data (int index)
- {
- uint32 retval = 0;
- //
- // Index into the list and return the user data to the caller
- //
- if (index >= 0 && index < EntryList.Count ()) {
- retval = EntryList[index].user_data;
- }
- return retval;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Reset_Content
- //
- ////////////////////////////////////////////////////////////////
- void
- DropDownCtrlClass::Reset_Content (void)
- {
- //
- // Remove everything from the list
- //
- EntryList.Delete_All ();
- Set_Curr_Sel (0);
- //
- // Repaint the control
- //
- Set_Dirty ();
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Entry_From_Pos
- //
- ////////////////////////////////////////////////////////////////
- int
- DropDownCtrlClass::Entry_From_Pos (const Vector2 &mouse_pos)
- {
- int retval = 0;
- //
- // Loop over all the entries in our current view
- //
- float curr_y_pos = ClientRect.Top;
- for (int index = ScrollPos; index < EntryList.Count (); index ++) {
- retval = index;
-
- //
- // Is ths mouse over this entry?
- //
- if ( (mouse_pos.Y >= curr_y_pos &&
- mouse_pos.Y <= (curr_y_pos + CellSize.Y)) ||
- mouse_pos.Y > ClientRect.Bottom)
- {
- break;
- }
- //
- // Move on to the next y-position
- //
- curr_y_pos += CellSize.Y;
- }
-
- return retval;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Set_Curr_Sel
- //
- ////////////////////////////////////////////////////////////////
- void
- DropDownCtrlClass::Set_Curr_Sel (int index)
- {
- if (index >= -1 && index < EntryList.Count () && CurrSel != index) {
-
- //
- // Change the selection
- //
- CurrSel = index;
- //
- // Update our current scroll position
- //
- Update_Scroll_Pos ();
- //
- // Repaint the view
- //
- Set_Dirty ();
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Get_String
- //
- ////////////////////////////////////////////////////////////////
- bool
- DropDownCtrlClass::Get_String (int index, WideStringClass &string) const
- {
- bool retval = false;
- if (index >= 0 && index < EntryList.Count ()) {
-
- //
- // Index into the entry list and return the string
- //
- string = EntryList[index].text;
- retval = true;
- }
- return retval;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Get_String
- //
- ////////////////////////////////////////////////////////////////
- const WCHAR *
- DropDownCtrlClass::Get_String (int index) const
- {
- const WCHAR *retval = NULL;
- if (index >= 0 && index < EntryList.Count ()) {
-
- //
- // Index into the entry list and return the string
- //
- retval = EntryList[index].text;
- }
- return retval;
- }
- ////////////////////////////////////////////////////////////////
- //
- // Update_Scroll_Pos
- //
- ////////////////////////////////////////////////////////////////
- void
- DropDownCtrlClass::Update_Scroll_Pos (void)
- {
- if (CurrSel == -1) {
- return;
- }
- if (CurrSel < ScrollPos) {
-
- //
- // Scroll up so the current selection is in view
- //
- ScrollPos = CurrSel;
- Set_Dirty ();
- } else if (CurrSel >= ScrollPos + CountPerPage) {
- //
- // Scroll down so the current selection is in view
- //
- ScrollPos = max (CurrSel - (CountPerPage - 1), 0);
- Set_Dirty ();
- }
- //
- // Update the scrollbar
- //
- ScrollBarCtrl.Set_Pos (ScrollPos, false);
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // On_Add_To_Dialog
- //
- ////////////////////////////////////////////////////////////////
- void
- DropDownCtrlClass::On_Add_To_Dialog (void)
- {
- if (DisplayScrollBar) {
- Parent->Add_Control (&ScrollBarCtrl);
- }
- TextColor.Set (0.35F, 1.0F, 0.35F);
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // On_Remove_From_Dialog
- //
- ////////////////////////////////////////////////////////////////
- void
- DropDownCtrlClass::On_Remove_From_Dialog (void)
- {
- if (DisplayScrollBar) {
- Parent->Remove_Control (&ScrollBarCtrl);
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////
- //
- // On_VScroll
- //
- ////////////////////////////////////////////////////////////////
- void
- DropDownCtrlClass::On_VScroll (ScrollBarCtrlClass *, int , int new_position)
- {
- ScrollPos = new_position;
- Set_Dirty ();
- return ;
- }
|