/* ** 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 . */ /*********************************************************************************************** *** 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 : wwui * * * * $Archive:: /Commando/Code/wwui/multilinetextctrl.cpp $* * * * Author:: Patrick Smith * * * * $Modtime:: 1/09/02 5:57p $* * * * $Revision:: 6 $* * * *---------------------------------------------------------------------------------------------* * Functions: * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "multilinetextctrl.h" #include "assetmgr.h" #include "stylemgr.h" #include "dialogbase.h" #include ////////////////////////////////////////////////////////////////////// // // MultiLineTextCtrlClass // ////////////////////////////////////////////////////////////////////// MultiLineTextCtrlClass::MultiLineTextCtrlClass (void) : ScrollPos (0), IsScrollBarDisplayed (false), IsInitialized (false), RowCount (0), RowsPerPage (0) { UINT scrolllines; // // Configure the renderers // StyleMgrClass::Assign_Font (&TextRenderer, StyleMgrClass::FONT_CONTROLS); StyleMgrClass::Configure_Renderer (&ControlRenderer); TextRenderer.Set_Texture_Size_Hint (256); // // We don't want the scroll bar getting focus // ScrollBarCtrl.Set_Wants_Focus (false); ScrollBarCtrl.Set_Advise_Sink (this); ScrollBarCtrl.Set_Is_Embedded (true); // Calculate the no. of lines to scroll for each mouse wheel increment. SystemParametersInfo (SPI_GETWHEELSCROLLLINES, 0, &scrolllines, 0); MouseWheelIncrement = ((float) scrolllines) / ((float) WHEEL_DELTA); return ; } ////////////////////////////////////////////////////////////////////// // // ~MultiLineTextCtrlClass // ////////////////////////////////////////////////////////////////////// MultiLineTextCtrlClass::~MultiLineTextCtrlClass (void) { ScrollBarCtrl.Set_Advise_Sink (NULL); if (Parent != NULL) { Parent->Remove_Control (&ScrollBarCtrl); } return ; } ////////////////////////////////////////////////////////////////////// // // Create_Control_Renderer // ////////////////////////////////////////////////////////////////////// void MultiLineTextCtrlClass::Create_Control_Renderer (void) { Render2DClass &renderer = ControlRenderer; // // Configure this renderer // renderer.Reset (); renderer.Enable_Texturing (false); // // Determine which color to draw the outline in // int color = StyleMgrClass::Get_Line_Color (); int bkcolor = StyleMgrClass::Get_Bk_Color (); if (IsEnabled == false) { color = StyleMgrClass::Get_Disabled_Line_Color (); bkcolor = StyleMgrClass::Get_Disabled_Bk_Color (); } // // Draw the control's outline // renderer.Add_Outline (Rect, 1.0F, color); return ; } ////////////////////////////////////////////////////////////////////// // // Create_Text_Renderer // ////////////////////////////////////////////////////////////////////// void MultiLineTextCtrlClass::Create_Text_Renderer (void) { TextRenderer.Reset (); // // Handy macro // #define COPY_LINE(dest, src_start, src_end) \ if (src_end == NULL) { \ dest = src_start; \ } else { \ uint32 bytes = ((uint32)src_end - (uint32)src_start); \ uint32 len = bytes / sizeof (WCHAR); \ ::memcpy (dest.Get_Buffer (len + 1), src_start, bytes); \ dest.Peek_Buffer ()[len] = 0; \ } // // Determine where to start drawing the text from // const WCHAR *text_start = TextRenderer.Find_Row_Start (Title, ScrollPos); const WCHAR *text_end = TextRenderer.Find_Row_Start (Title, ScrollPos+RowsPerPage); if (text_start != NULL) { // // Should we draw the text centered? // if ((Style & ES_CENTER) == ES_CENTER) { float char_height = TextRenderer.Peek_Font ()->Get_Char_Height (); RectClass text_rect = ClientRect; // // Render each line separately // const WCHAR *line_start = text_start; const WCHAR *line_end = TextRenderer.Find_Row_Start (Title, ScrollPos + 1); for (int index = 0; index < RowsPerPage; index ++) { // // Copy this line of text into a buffer // WideStringClass text; COPY_LINE (text, line_start, line_end); // // Render this line of text centered // TextRenderer.Set_Wrapping_Width (0); StyleMgrClass::Render_Text (text, &TextRenderer, text_rect, true, true, StyleMgrClass::CENTER_JUSTIFY, IsEnabled, false); text_rect.Top = int (text_rect.Top + char_height); TextRenderer.Set_Wrapping_Width (ClientRect.Width ()); if (line_end == NULL) { break; } // // Advance to the next line... // line_start = line_end; line_end = TextRenderer.Find_Row_Start (line_start, 1); } } else { WideStringClass text; COPY_LINE (text, text_start, text_end); // // Draw the text // StyleMgrClass::Render_Wrapped_Text (text, &TextRenderer, ClientRect, true, false, IsEnabled); } } return ; } //////////////////////////////////////////////////////////////// // // Render // //////////////////////////////////////////////////////////////// void MultiLineTextCtrlClass::Render (void) { // // Recreate the renderers (if necessary) // if (IsDirty) { Update_Scroll_Bar_Visibility (); Create_Control_Renderer (); Create_Text_Renderer (); } // // Render the image... // ControlRenderer.Render (); TextRenderer.Render (); DialogControlClass::Render (); return ; } //////////////////////////////////////////////////////////////// // // Update_Client_Rect // //////////////////////////////////////////////////////////////// void MultiLineTextCtrlClass::Update_Client_Rect (void) { // // Set the client area // ClientRect = Rect; ClientRect.Inflate (Vector2 (-5.0F * StyleMgrClass::Get_X_Scale (), -3.75F * StyleMgrClass::Get_Y_Scale ())); ClientRect.Left = int(ClientRect.Left); ClientRect.Top = int(ClientRect.Top); ClientRect.Right = int(ClientRect.Right); ClientRect.Bottom = int(ClientRect.Bottom); // // Determine how many rows we can fit on one page // float char_height = TextRenderer.Peek_Font ()->Get_Char_Height (); RowsPerPage = ClientRect.Height () / char_height; IsInitialized = true; // // Choose an arbitrary width, the scroll bar // will snap to the only width it supports // float width = 10; // // Calculate the scroll bar's rectangle // 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_Small_BMP_Mode ((Rect.Height () < (StyleMgrClass::Get_Y_Scale () * 100.0F))); //Update_Scroll_Bar_Visibility (); Set_Dirty (); return ; } //////////////////////////////////////////////////////////////// // // Update_Scroll_Bar_Visibility // //////////////////////////////////////////////////////////////// void MultiLineTextCtrlClass::Update_Scroll_Bar_Visibility (void) { if (IsInitialized == false ) { return ; } Calculate_Row_Count (); // // Determine if we have more entries then we can // display on one page // bool needs_scrollbar = (RowCount > RowsPerPage); float new_right = 0; if (needs_scrollbar != IsScrollBarDisplayed) { // // Do we need to show a scroll bar? // if (needs_scrollbar) { new_right = ScrollBarCtrl.Get_Window_Rect ().Left; IsScrollBarDisplayed = true; } else if (Parent != NULL) { new_right = ScrollBarCtrl.Get_Window_Rect ().Right; IsScrollBarDisplayed = false; } // // Reset our window size (as necessary) // Rect.Right = new_right; ClientRect = Rect; ClientRect.Inflate (Vector2 (-5.0F * StyleMgrClass::Get_X_Scale (), -3.75F * StyleMgrClass::Get_Y_Scale ())); ClientRect.Left = int(ClientRect.Left); ClientRect.Top = int(ClientRect.Top); ClientRect.Right = int(ClientRect.Right); ClientRect.Bottom = int(ClientRect.Bottom); Calculate_Row_Count (); // // Add or remove the scrollbar (as necessary) // if (IsScrollBarDisplayed) { Parent->Add_Control (&ScrollBarCtrl); } else { Parent->Remove_Control (&ScrollBarCtrl); } } // // Configure the scroll-bar's ranges // ScrollBarCtrl.Set_Page_Size (RowsPerPage); ScrollBarCtrl.Set_Range (0, RowCount - RowsPerPage); ScrollBarCtrl.Set_Pos (ScrollPos); ScrollPos = ScrollBarCtrl.Get_Pos (); return ; } //////////////////////////////////////////////////////////////// // // Calculate_Row_Count // //////////////////////////////////////////////////////////////// void MultiLineTextCtrlClass::Calculate_Row_Count (void) { TextRenderer.Set_Wrapping_Width (ClientRect.Width ()); // // Get the number of rows we'll need to display // RowCount = 0; TextRenderer.Get_Formatted_Text_Extents (Title, &RowCount); return ; } //////////////////////////////////////////////////////////////// // // On_Key_Down // //////////////////////////////////////////////////////////////// bool MultiLineTextCtrlClass::On_Key_Down (uint32 key_id, uint32 key_data) { switch (key_id) { case VK_UP: Set_Scroll_Pos (ScrollPos - 1); break; case VK_DOWN: Set_Scroll_Pos (ScrollPos + 1); break; case VK_PRIOR: Set_Scroll_Pos (ScrollPos - RowsPerPage); break; case VK_NEXT: Set_Scroll_Pos (ScrollPos + RowsPerPage); break; case VK_HOME: Set_Scroll_Pos (0); break; case VK_END: Set_Scroll_Pos (RowCount); break; } return true; } //////////////////////////////////////////////////////////////// // // On_VScroll // //////////////////////////////////////////////////////////////// void MultiLineTextCtrlClass::On_VScroll (ScrollBarCtrlClass *, int , int new_position) { Set_Scroll_Pos (new_position); return ; } //////////////////////////////////////////////////////////////// // // On_Mouse_Wheel // //////////////////////////////////////////////////////////////// void MultiLineTextCtrlClass::On_Mouse_Wheel (int direction) { int lineoffset = direction * MouseWheelIncrement; Set_Scroll_Pos (ScrollPos + lineoffset); return ; } //////////////////////////////////////////////////////////////// // // Set_Scroll_Pos // //////////////////////////////////////////////////////////////// void MultiLineTextCtrlClass::Set_Scroll_Pos (int new_position) { if (ScrollPos != new_position) { ScrollPos = new_position; ScrollPos = min (ScrollPos, RowCount - RowsPerPage); ScrollPos = max (ScrollPos, 0); ScrollBarCtrl.Set_Pos (ScrollPos, false); Set_Dirty (); } return ; } //////////////////////////////////////////////////////////////// // // Set_Text // //////////////////////////////////////////////////////////////// void MultiLineTextCtrlClass::Set_Text (const WCHAR *title) { DialogControlClass::Set_Text (title); ScrollPos = 0; RowCount = 0; //Update_Scroll_Bar_Visibility (); return ; }