window_gui.h

Go to the documentation of this file.
00001 /* $Id: window_gui.h 24900 2013-01-08 22:46:42Z planetmaker $ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD 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, version 2.
00006  * OpenTTD 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.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #ifndef WINDOW_GUI_H
00013 #define WINDOW_GUI_H
00014 
00015 #include "vehicle_type.h"
00016 #include "viewport_type.h"
00017 #include "company_type.h"
00018 #include "tile_type.h"
00019 #include "widget_type.h"
00020 #include "core/smallvec_type.hpp"
00021 #include "core/smallmap_type.hpp"
00022 
00024 enum EventState {
00025   ES_HANDLED,     
00026   ES_NOT_HANDLED, 
00027 };
00028 
00032 enum FrameFlags {
00033   FR_NONE         =  0,
00034   FR_TRANSPARENT  =  1 << 0,  
00035   FR_BORDERONLY   =  1 << 4,  
00036   FR_LOWERED      =  1 << 5,  
00037   FR_DARKENED     =  1 << 6,  
00038 };
00039 
00040 DECLARE_ENUM_AS_BIT_SET(FrameFlags)
00041 
00042 
00043 enum WidgetDrawDistances {
00044   /* WWT_IMGBTN(_2) */
00045   WD_IMGBTN_LEFT    = 1,      
00046   WD_IMGBTN_RIGHT   = 2,      
00047   WD_IMGBTN_TOP     = 1,      
00048   WD_IMGBTN_BOTTOM  = 2,      
00049 
00050   /* WWT_INSET */
00051   WD_INSET_LEFT  = 2,         
00052   WD_INSET_RIGHT = 2,         
00053   WD_INSET_TOP   = 1,         
00054 
00055   WD_SCROLLBAR_LEFT   = 2,    
00056   WD_SCROLLBAR_RIGHT  = 2,    
00057   WD_SCROLLBAR_TOP    = 2,    
00058   WD_SCROLLBAR_BOTTOM = 2,    
00059 
00060   /* Size of the pure frame bevel without any padding. */
00061   WD_BEVEL_LEFT       = 1,    
00062   WD_BEVEL_RIGHT      = 1,    
00063   WD_BEVEL_TOP        = 1,    
00064   WD_BEVEL_BOTTOM     = 1,    
00065 
00066   /* FrameRect widgets, all text buttons, panel, editbox */
00067   WD_FRAMERECT_LEFT   = 2,    
00068   WD_FRAMERECT_RIGHT  = 2,    
00069   WD_FRAMERECT_TOP    = 1,    
00070   WD_FRAMERECT_BOTTOM = 1,    
00071 
00072   /* Extra space at top/bottom of text panels */
00073   WD_TEXTPANEL_TOP    = 6,    
00074   WD_TEXTPANEL_BOTTOM = 6,    
00075 
00076   /* WWT_FRAME */
00077   WD_FRAMETEXT_LEFT   = 6,    
00078   WD_FRAMETEXT_RIGHT  = 6,    
00079   WD_FRAMETEXT_TOP    = 6,    
00080   WD_FRAMETEXT_BOTTOM = 6,    
00081 
00082   /* WWT_MATRIX */
00083   WD_MATRIX_LEFT   = 2,       
00084   WD_MATRIX_RIGHT  = 2,       
00085   WD_MATRIX_TOP    = 3,       
00086   WD_MATRIX_BOTTOM = 1,       
00087 
00088   /* WWT_SHADEBOX */
00089   WD_SHADEBOX_WIDTH  = 12,    
00090   WD_SHADEBOX_LEFT   = 2,     
00091   WD_SHADEBOX_RIGHT  = 2,     
00092   WD_SHADEBOX_TOP    = 3,     
00093   WD_SHADEBOX_BOTTOM = 3,     
00094 
00095   /* WWT_STICKYBOX */
00096   WD_STICKYBOX_WIDTH  = 12,   
00097   WD_STICKYBOX_LEFT   = 2,    
00098   WD_STICKYBOX_RIGHT  = 2,    
00099   WD_STICKYBOX_TOP    = 3,    
00100   WD_STICKYBOX_BOTTOM = 3,    
00101 
00102   /* WWT_DEBUGBOX */
00103   WD_DEBUGBOX_WIDTH  = 12,    
00104   WD_DEBUGBOX_LEFT   = 2,     
00105   WD_DEBUGBOX_RIGHT  = 2,     
00106   WD_DEBUGBOX_TOP    = 3,     
00107   WD_DEBUGBOX_BOTTOM = 3,     
00108 
00109   /* WWT_RESIZEBOX */
00110   WD_RESIZEBOX_WIDTH  = 12,   
00111   WD_RESIZEBOX_LEFT   = 3,    
00112   WD_RESIZEBOX_RIGHT  = 2,    
00113   WD_RESIZEBOX_TOP    = 3,    
00114   WD_RESIZEBOX_BOTTOM = 2,    
00115 
00116   /* WWT_CLOSEBOX */
00117   WD_CLOSEBOX_WIDTH  = 11,    
00118   WD_CLOSEBOX_LEFT   = 2,     
00119   WD_CLOSEBOX_RIGHT  = 1,     
00120   WD_CLOSEBOX_TOP    = 2,     
00121   WD_CLOSEBOX_BOTTOM = 2,     
00122 
00123   /* WWT_CAPTION */
00124   WD_CAPTION_HEIGHT     = 14, 
00125   WD_CAPTIONTEXT_LEFT   = 2,  
00126   WD_CAPTIONTEXT_RIGHT  = 2,  
00127   WD_CAPTIONTEXT_TOP    = 2,  
00128   WD_CAPTIONTEXT_BOTTOM = 2,  
00129 
00130   /* Dropdown widget. */
00131   WD_DROPDOWN_HEIGHT     = 12, 
00132   WD_DROPDOWNTEXT_LEFT   = 2,  
00133   WD_DROPDOWNTEXT_RIGHT  = 14, 
00134   WD_DROPDOWNTEXT_TOP    = 1,  
00135   WD_DROPDOWNTEXT_BOTTOM = 1,  
00136 
00137   WD_SORTBUTTON_ARROW_WIDTH = 11, 
00138 
00139   WD_PAR_VSEP_NORMAL = 2,      
00140   WD_PAR_VSEP_WIDE   = 8,      
00141 };
00142 
00143 /* widget.cpp */
00144 void DrawFrameRect(int left, int top, int right, int bottom, Colours colour, FrameFlags flags);
00145 void DrawCaption(const Rect &r, Colours colour, Owner owner, StringID str);
00146 
00147 /* window.cpp */
00148 extern Window *_z_front_window;
00149 extern Window *_z_back_window;
00150 extern Window *_focused_window;
00151 
00152 
00154 enum WindowPosition {
00155   WDP_MANUAL,        
00156   WDP_AUTO,          
00157   WDP_CENTER,        
00158   WDP_ALIGN_TOOLBAR, 
00159 };
00160 
00161 Point GetToolbarAlignedWindowPosition(int window_width);
00162 
00166 struct WindowDesc : ZeroedMemoryAllocator {
00167 
00168   WindowDesc(WindowPosition default_pos, int16 def_width, int16 def_height,
00169       WindowClass window_class, WindowClass parent_class, uint32 flags,
00170       const NWidgetPart *nwid_parts, int16 nwid_length);
00171 
00172   ~WindowDesc();
00173 
00174   WindowPosition default_pos;    
00175   int16 default_width;           
00176   int16 default_height;          
00177   WindowClass cls;               
00178   WindowClass parent_cls;        
00179   uint32 flags;                  
00180   const NWidgetPart *nwid_parts; 
00181   int16 nwid_length;             
00182 };
00183 
00187 enum WindowDefaultFlag {
00188   WDF_CONSTRUCTION    =   1 << 0, 
00189   WDF_MODAL           =   1 << 1, 
00190   WDF_NO_FOCUS        =   1 << 2, 
00191 };
00192 
00196 struct ResizeInfo {
00197   uint step_width;  
00198   uint step_height; 
00199 };
00200 
00202 enum SortButtonState {
00203   SBS_OFF,  
00204   SBS_DOWN, 
00205   SBS_UP,   
00206 };
00207 
00211 enum WindowFlags {
00212   WF_TIMEOUT           = 1 <<  0, 
00213 
00214   WF_DRAGGING          = 1 <<  3, 
00215   WF_SIZING_RIGHT      = 1 <<  4, 
00216   WF_SIZING_LEFT       = 1 <<  5, 
00217   WF_SIZING            = WF_SIZING_RIGHT | WF_SIZING_LEFT, 
00218   WF_STICKY            = 1 <<  6, 
00219   WF_DISABLE_VP_SCROLL = 1 <<  7, 
00220   WF_WHITE_BORDER      = 1 <<  8, 
00221   WF_HIGHLIGHTED       = 1 <<  9, 
00222   WF_CENTERED          = 1 << 10, 
00223 };
00224 DECLARE_ENUM_AS_BIT_SET(WindowFlags)
00225 
00226 static const int TIMEOUT_DURATION = 7; 
00227 static const int WHITE_BORDER_DURATION = 3; 
00228 
00236 struct ViewportData : ViewPort {
00237   VehicleID follow_vehicle; 
00238   int32 scrollpos_x;        
00239   int32 scrollpos_y;        
00240   int32 dest_scrollpos_x;   
00241   int32 dest_scrollpos_y;   
00242 };
00243 
00244 struct QueryString;
00245 
00249 struct Window : ZeroedMemoryAllocator {
00250 protected:
00251   void InitializeData(const WindowDesc *desc, WindowNumber window_number);
00252   void InitializePositionSize(int x, int y, int min_width, int min_height);
00253   void FindWindowPlacementAndResize(int def_width, int def_height);
00254 
00255   SmallVector<int, 4> scheduled_invalidation_data;  
00256 
00257 public:
00258   Window();
00259 
00260   virtual ~Window();
00261 
00268   inline void *operator new[](size_t size)
00269   {
00270     NOT_REACHED();
00271   }
00272 
00278   inline void operator delete(void *ptr)
00279   {
00280   }
00281 
00282   WindowFlags flags;          
00283   WindowClass window_class;   
00284   WindowNumber window_number; 
00285 
00286   uint8 timeout_timer;      
00287   uint8 white_border_timer; 
00288 
00289   int left;   
00290   int top;    
00291   int width;  
00292   int height; 
00293 
00294   ResizeInfo resize;  
00295 
00296   Owner owner;        
00297 
00298   ViewportData *viewport;          
00299   uint32 desc_flags;               
00300   const NWidgetCore *nested_focus; 
00301   SmallMap<int, QueryString*> querystrings; 
00302   NWidgetBase *nested_root;        
00303   NWidgetBase **nested_array;      
00304   uint nested_array_size;          
00305   NWidgetStacked *shade_select;    
00306   Dimension unshaded_size;         
00307 
00308   int scrolling_scrollbar;         
00309 
00310   Window *parent;                  
00311   Window *z_front;                 
00312   Window *z_back;                  
00313 
00314   template <class NWID>
00315   inline const NWID *GetWidget(uint widnum) const;
00316   template <class NWID>
00317   inline NWID *GetWidget(uint widnum);
00318 
00319   const Scrollbar *GetScrollbar(uint widnum) const;
00320   Scrollbar *GetScrollbar(uint widnum);
00321 
00322   const QueryString *GetQueryString(uint widnum) const;
00323   QueryString *GetQueryString(uint widnum);
00324 
00325   void InitNested(const WindowDesc *desc, WindowNumber number = 0);
00326   void CreateNestedTree(const WindowDesc *desc, bool fill_nested = true);
00327   void FinishInitNested(const WindowDesc *desc, WindowNumber window_number = 0);
00328 
00332   inline void SetTimeout()
00333   {
00334     this->flags |= WF_TIMEOUT;
00335     this->timeout_timer = TIMEOUT_DURATION;
00336   }
00337 
00341   inline void SetWhiteBorder()
00342   {
00343     this->flags |= WF_WHITE_BORDER;
00344     this->white_border_timer = WHITE_BORDER_DURATION;
00345   }
00346 
00347   void DisableAllWidgetHighlight();
00348   void SetWidgetHighlight(byte widget_index, TextColour highlighted_colour);
00349   bool IsWidgetHighlighted(byte widget_index) const;
00350 
00358   inline void SetWidgetDisabledState(byte widget_index, bool disab_stat)
00359   {
00360     assert(widget_index < this->nested_array_size);
00361     if (this->nested_array[widget_index] != NULL) this->GetWidget<NWidgetCore>(widget_index)->SetDisabled(disab_stat);
00362   }
00363 
00368   inline void DisableWidget(byte widget_index)
00369   {
00370     SetWidgetDisabledState(widget_index, true);
00371   }
00372 
00377   inline void EnableWidget(byte widget_index)
00378   {
00379     SetWidgetDisabledState(widget_index, false);
00380   }
00381 
00387   inline bool IsWidgetDisabled(byte widget_index) const
00388   {
00389     assert(widget_index < this->nested_array_size);
00390     return this->GetWidget<NWidgetCore>(widget_index)->IsDisabled();
00391   }
00392 
00398   inline bool IsWidgetFocused(byte widget_index) const
00399   {
00400     return this->nested_focus != NULL && this->nested_focus->index == widget_index;
00401   }
00402 
00409   inline bool IsWidgetGloballyFocused(byte widget_index) const
00410   {
00411     return _focused_window == this && IsWidgetFocused(widget_index);
00412   }
00413 
00419   inline void SetWidgetLoweredState(byte widget_index, bool lowered_stat)
00420   {
00421     assert(widget_index < this->nested_array_size);
00422     this->GetWidget<NWidgetCore>(widget_index)->SetLowered(lowered_stat);
00423   }
00424 
00429   inline void ToggleWidgetLoweredState(byte widget_index)
00430   {
00431     assert(widget_index < this->nested_array_size);
00432     bool lowered_state = this->GetWidget<NWidgetCore>(widget_index)->IsLowered();
00433     this->GetWidget<NWidgetCore>(widget_index)->SetLowered(!lowered_state);
00434   }
00435 
00440   inline void LowerWidget(byte widget_index)
00441   {
00442     SetWidgetLoweredState(widget_index, true);
00443   }
00444 
00449   inline void RaiseWidget(byte widget_index)
00450   {
00451     SetWidgetLoweredState(widget_index, false);
00452   }
00453 
00459   inline bool IsWidgetLowered(byte widget_index) const
00460   {
00461     assert(widget_index < this->nested_array_size);
00462     return this->GetWidget<NWidgetCore>(widget_index)->IsLowered();
00463   }
00464 
00465   void UnfocusFocusedWidget();
00466   bool SetFocusedWidget(int widget_index);
00467 
00468   EventState HandleEditBoxKey(int wid, uint16 key, uint16 keycode);
00469 
00470   void HandleButtonClick(byte widget);
00471   int GetRowFromWidget(int clickpos, int widget, int padding, int line_height = -1) const;
00472 
00473   void RaiseButtons(bool autoraise = false);
00474   void CDECL SetWidgetsDisabledState(bool disab_stat, int widgets, ...);
00475   void CDECL SetWidgetsLoweredState(bool lowered_stat, int widgets, ...);
00476   void SetWidgetDirty(byte widget_index) const;
00477 
00478   void DrawWidgets() const;
00479   void DrawViewport() const;
00480   void DrawSortButtonState(int widget, SortButtonState state) const;
00481 
00482   void DeleteChildWindows(WindowClass wc = WC_INVALID) const;
00483 
00484   void SetDirty() const;
00485   void ReInit(int rx = 0, int ry = 0);
00486 
00488   inline bool IsShaded() const
00489   {
00490     return this->shade_select != NULL && this->shade_select->shown_plane == SZSP_HORIZONTAL;
00491   }
00492 
00493   void SetShaded(bool make_shaded);
00494 
00495   void InvalidateData(int data = 0, bool gui_scope = true);
00496   void ProcessScheduledInvalidations();
00497   void ProcessHighlightedInvalidations();
00498 
00499   /*** Event handling ***/
00500 
00505   virtual void OnInit() { }
00506 
00515   virtual Point OnInitialPosition(const WindowDesc *desc, int16 sm_width, int16 sm_height, int window_number);
00516 
00521   virtual void OnPaint()
00522   {
00523     this->DrawWidgets();
00524   }
00525 
00532   virtual void DrawWidget(const Rect &r, int widget) const {}
00533 
00546   virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) {}
00547 
00554   virtual void SetStringParameters(int widget) const {}
00555 
00559   virtual void OnFocus() {}
00560 
00564   virtual void OnFocusLost() {}
00565 
00573   virtual EventState OnKeyPress(uint16 key, uint16 keycode) { return ES_NOT_HANDLED; }
00574 
00580   virtual EventState OnCTRLStateChange() { return ES_NOT_HANDLED; }
00581 
00582 
00589   virtual void OnClick(Point pt, int widget, int click_count) {}
00590 
00598   virtual bool OnRightClick(Point pt, int widget) { return false; }
00599 
00605   virtual void OnHover(Point pt, int widget) {}
00606 
00612   virtual void OnMouseDrag(Point pt, int widget) {}
00613 
00619   virtual void OnDragDrop(Point pt, int widget) {}
00620 
00625   virtual void OnScroll(Point delta) {}
00626 
00633   virtual void OnMouseOver(Point pt, int widget) {}
00634 
00639   virtual void OnMouseWheel(int wheel) {}
00640 
00641 
00645   virtual void OnMouseLoop() {}
00646 
00650   virtual void OnTick() {}
00651 
00655   virtual void OnHundredthTick() {}
00656 
00660   virtual void OnTimeout() {}
00661 
00662 
00667   virtual void OnResize() {}
00668 
00674   virtual void OnDropdownSelect(int widget, int index) {}
00675 
00676   virtual void OnDropdownClose(Point pt, int widget, int index, bool instant_close);
00677 
00682   virtual void OnEditboxChanged(int widget) {}
00683 
00690   virtual void OnQueryTextFinished(char *str) {}
00691 
00697   virtual void OnInvalidateData(int data = 0, bool gui_scope = true) {}
00698 
00705   virtual void OnPlaceObject(Point pt, TileIndex tile) {}
00706 
00712   virtual bool OnVehicleSelect(const struct Vehicle *v) { return false; }
00713 
00717   virtual void OnPlaceObjectAbort() {}
00718 
00719 
00727   virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt) {}
00728 
00738   virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile) {}
00739 
00747   virtual void OnPlacePresize(Point pt, TileIndex tile) {}
00748 
00749   /*** End of the event handling ***/
00750 
00755   virtual bool IsNewGRFInspectable() const { return false; }
00756 
00763   virtual void ShowNewGRFInspectWindow() const { NOT_REACHED(); }
00764 };
00765 
00772 template <class NWID>
00773 inline NWID *Window::GetWidget(uint widnum)
00774 {
00775   if (widnum >= this->nested_array_size || this->nested_array[widnum] == NULL) return NULL;
00776   NWID *nwid = dynamic_cast<NWID *>(this->nested_array[widnum]);
00777   assert(nwid != NULL);
00778   return nwid;
00779 }
00780 
00782 template <>
00783 inline const NWidgetBase *Window::GetWidget<NWidgetBase>(uint widnum) const
00784 {
00785   if (widnum >= this->nested_array_size) return NULL;
00786   return this->nested_array[widnum];
00787 }
00788 
00795 template <class NWID>
00796 inline const NWID *Window::GetWidget(uint widnum) const
00797 {
00798   return const_cast<Window *>(this)->GetWidget<NWID>(widnum);
00799 }
00800 
00801 
00805 class PickerWindowBase : public Window {
00806 
00807 public:
00808   PickerWindowBase(Window *parent) : Window()
00809   {
00810     this->parent = parent;
00811   }
00812 
00813   virtual ~PickerWindowBase();
00814 };
00815 
00816 Window *BringWindowToFrontById(WindowClass cls, WindowNumber number);
00817 Window *FindWindowFromPt(int x, int y);
00818 
00825 template <typename Wcls>
00826 Wcls *AllocateWindowDescFront(const WindowDesc *desc, int window_number)
00827 {
00828   if (BringWindowToFrontById(desc->cls, window_number)) return NULL;
00829   return new Wcls(desc, window_number);
00830 }
00831 
00832 void RelocateAllWindows(int neww, int newh);
00833 
00834 /* misc_gui.cpp */
00835 enum TooltipCloseCondition {
00836   TCC_RIGHT_CLICK,
00837   TCC_LEFT_CLICK,
00838   TCC_HOVER,
00839 };
00840 
00841 void GuiShowTooltips(Window *parent, StringID str, uint paramcount = 0, const uint64 params[] = NULL, TooltipCloseCondition close_tooltip = TCC_HOVER);
00842 
00843 /* widget.cpp */
00844 int GetWidgetFromPos(const Window *w, int x, int y);
00845 
00847 #define FOR_ALL_WINDOWS_FROM_BACK_FROM(w, start)  for (w = start; w != NULL; w = w->z_front) if (w->window_class != WC_INVALID)
00848 #define FOR_ALL_WINDOWS_FROM_FRONT_FROM(w, start) for (w = start; w != NULL; w = w->z_back) if (w->window_class != WC_INVALID)
00849 #define FOR_ALL_WINDOWS_FROM_BACK(w)  FOR_ALL_WINDOWS_FROM_BACK_FROM(w, _z_back_window)
00850 #define FOR_ALL_WINDOWS_FROM_FRONT(w) FOR_ALL_WINDOWS_FROM_FRONT_FROM(w, _z_front_window)
00851 
00852 extern Point _cursorpos_drag_start;
00853 
00854 extern int _scrollbar_start_pos;
00855 extern int _scrollbar_size;
00856 extern byte _scroller_click_timeout;
00857 
00858 extern bool _scrolling_viewport;
00859 extern bool _mouse_hovering;
00860 
00862 enum SpecialMouseMode {
00863   WSM_NONE,     
00864   WSM_DRAGDROP, 
00865   WSM_SIZING,   
00866   WSM_PRESIZE,  
00867 };
00868 extern SpecialMouseMode _special_mouse_mode;
00869 
00870 void SetFocusedWindow(Window *w);
00871 
00872 void ScrollbarClickHandler(Window *w, NWidgetCore *nw, int x, int y);
00873 
00874 #endif /* WINDOW_GUI_H */