# window_gui.h

Go to the documentation of this file.

    00001 /* $Id$ */
    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 "core/geometry_func.hpp"
    00016 #include "core/math_func.hpp"
    00017 #include "vehicle_type.h"
    00018 #include "viewport_type.h"
    00019 #include "company_type.h"
    00020 #include "core/alloc_type.hpp"
    00021 #include "window_type.h"
    00022 #include "tile_type.h"
    00023 #include "widget_type.h"
    00024
    00028 enum FrameFlags {
    00029   FR_NONE         =  0,
    00030   FR_TRANSPARENT  =  1 << 0,
    00031   FR_BORDERONLY   =  1 << 4,
    00032   FR_LOWERED      =  1 << 5,
    00033   FR_DARKENED     =  1 << 6,
    00034 };
    00035
    00036 DECLARE_ENUM_AS_BIT_SET(FrameFlags);
    00037
    00039 enum WidgetDrawDistances {
    00040   /* WWT_IMGBTN(_2) */
    00041   WD_IMGBTN_LEFT    = 1,
    00042   WD_IMGBTN_RIGHT   = 2,
    00043   WD_IMGBTN_TOP     = 1,
    00044   WD_IMGBTN_BOTTOM  = 2,
    00045
    00046   /* WWT_INSET */
    00047   WD_INSET_LEFT  = 2,
    00048   WD_INSET_RIGHT = 2,
    00049   WD_INSET_TOP   = 1,
    00050
    00051   WD_VSCROLLBAR_WIDTH  = 12,
    00052
    00053   WD_HSCROLLBAR_HEIGHT = 12,
    00054
    00055   /* FrameRect widgets, all text buttons, panel, editbox */
    00056   WD_FRAMERECT_LEFT   = 2,
    00057   WD_FRAMERECT_RIGHT  = 2,
    00058   WD_FRAMERECT_TOP    = 1,
    00059   WD_FRAMERECT_BOTTOM = 1,
    00060
    00061   /* Extra space at top/bottom of text panels */
    00062   WD_TEXTPANEL_TOP    = 6,
    00063   WD_TEXTPANEL_BOTTOM = 6,
    00064
    00065   /* WWT_FRAME */
    00066   WD_FRAMETEXT_LEFT   = 6,
    00067   WD_FRAMETEXT_RIGHT  = 6,
    00068   WD_FRAMETEXT_TOP    = 6,
    00069   WD_FRAMETEXT_BOTTOM = 6,
    00070
    00071   /* WWT_MATRIX */
    00072   WD_MATRIX_LEFT   = 2,
    00073   WD_MATRIX_RIGHT  = 2,
    00074   WD_MATRIX_TOP    = 3,
    00075   WD_MATRIX_BOTTOM = 1,
    00076
    00077   /* WWT_SHADEBOX */
    00078   WD_SHADEBOX_WIDTH  = 12,
    00079   WD_SHADEBOX_LEFT   = 2,
    00080   WD_SHADEBOX_RIGHT  = 2,
    00081   WD_SHADEBOX_TOP    = 3,
    00082   WD_SHADEBOX_BOTTOM = 3,
    00083
    00084   /* WWT_STICKYBOX */
    00085   WD_STICKYBOX_WIDTH  = 12,
    00086   WD_STICKYBOX_LEFT   = 2,
    00087   WD_STICKYBOX_RIGHT  = 2,
    00088   WD_STICKYBOX_TOP    = 3,
    00089   WD_STICKYBOX_BOTTOM = 3,
    00090
    00091   /* WWT_RESIZEBOX */
    00092   WD_RESIZEBOX_WIDTH  = 12,
    00093   WD_RESIZEBOX_LEFT   = 3,
    00094   WD_RESIZEBOX_RIGHT  = 2,
    00095   WD_RESIZEBOX_TOP    = 3,
    00096   WD_RESIZEBOX_BOTTOM = 2,
    00097
    00098   /* WWT_CLOSEBOX */
    00099   WD_CLOSEBOX_WIDTH  = 11,
    00100   WD_CLOSEBOX_LEFT   = 2,
    00101   WD_CLOSEBOX_RIGHT  = 1,
    00102   WD_CLOSEBOX_TOP    = 2,
    00103   WD_CLOSEBOX_BOTTOM = 2,
    00104
    00105   /* WWT_CAPTION */
    00106   WD_CAPTION_HEIGHT     = 14,
    00107   WD_CAPTIONTEXT_LEFT   = 2,
    00108   WD_CAPTIONTEXT_RIGHT  = 2,
    00109   WD_CAPTIONTEXT_TOP    = 2,
    00110   WD_CAPTIONTEXT_BOTTOM = 2,
    00111
    00112   /* Dropdown widget. */
    00113   WD_DROPDOWN_HEIGHT     = 12,
    00114   WD_DROPDOWNTEXT_LEFT   = 2,
    00115   WD_DROPDOWNTEXT_RIGHT  = 14,
    00116   WD_DROPDOWNTEXT_TOP    = 1,
    00117   WD_DROPDOWNTEXT_BOTTOM = 1,
    00118
    00119   WD_SORTBUTTON_ARROW_WIDTH = 11,
    00120
    00121   WD_PAR_VSEP_NORMAL = 2,
    00122   WD_PAR_VSEP_WIDE   = 8,
    00123 };
    00124
    00125 /* wiget.cpp */
    00126 void DrawFrameRect(int left, int top, int right, int bottom, Colours colour, FrameFlags flags);
    00127
    00128 /* window.cpp */
    00129 extern Window *_z_front_window;
    00130 extern Window *_z_back_window;
    00131 extern Window *_focused_window;
    00132
    00133
    00135 enum WindowPosition {
    00136   WDP_MANUAL,
    00137   WDP_AUTO,
    00138   WDP_CENTER,
    00139   WDP_ALIGN_TOOLBAR,
    00140 };
    00141
    00142 Point GetToolbarAlignedWindowPosition(int window_width);
    00143
    00147 struct WindowDesc : ZeroedMemoryAllocator {
    00148
    00149   WindowDesc(WindowPosition default_pos, int16 def_width, int16 def_height,
    00150       WindowClass window_class, WindowClass parent_class, uint32 flags,
    00151       const NWidgetPart *nwid_parts, int16 nwid_length);
    00152
    00153   ~WindowDesc();
    00154
    00155   WindowPosition default_pos;
    00156   int16 default_width;
    00157   int16 default_height;
    00158   WindowClass cls;
    00159   WindowClass parent_cls;
    00160   uint32 flags;
    00161   const NWidgetPart *nwid_parts;
    00162   int16 nwid_length;
    00163 };
    00164
    00168 enum WindowDefaultFlag {
    00169   WDF_CONSTRUCTION    =   1 << 0,
    00170   WDF_UNCLICK_BUTTONS =   1 << 1,
    00171   WDF_MODAL           =   1 << 2,
    00172   WDF_NO_FOCUS        =   1 << 3,
    00173 };
    00174
    00178 class Scrollbar {
    00179 private:
    00180   const bool is_vertical;
    00181   uint16 count;
    00182   uint16 cap;
    00183   uint16 pos;
    00184
    00185 public:
    00186   Scrollbar(bool is_vertical) : is_vertical(is_vertical)
    00187   {
    00188   }
    00189
    00194   FORCEINLINE uint16 GetCount() const
    00195   {
    00196     return this->count;
    00197   }
    00198
    00203   FORCEINLINE uint16 GetCapacity() const
    00204   {
    00205     return this->cap;
    00206   }
    00207
    00212   FORCEINLINE uint16 GetPosition() const
    00213   {
    00214     return this->pos;
    00215   }
    00216
    00222   FORCEINLINE bool IsVisible(uint16 item) const
    00223   {
    00224     return IsInsideBS(item, this->GetPosition(), this->GetCapacity());
    00225   }
    00226
    00232   void SetCount(int num)
    00233   {
    00234     assert(num >= 0);
    00235     assert(num <= MAX_UVALUE(uint16));
    00236
    00237     this->count = num;
    00238     num -= this->cap;
    00239     if (num < 0) num = 0;
    00240     if (num < this->pos) this->pos = num;
    00241   }
    00242
    00248   void SetCapacity(int capacity)
    00249   {
    00250     assert(capacity > 0);
    00251     assert(capacity <= MAX_UVALUE(uint16));
    00252
    00253     this->cap = capacity;
    00254     if (this->cap + this->pos > this->count) this->pos = max(0, this->count - this->cap);
    00255   }
    00256
    00257   void SetCapacityFromWidget(Window *w, int widget, int padding = 0);
    00258
    00263   void SetPosition(int position)
    00264   {
    00265     assert(position >= 0);
    00266     assert(this->count <= this->cap ? (position == 0) : (position + this->cap <= this->count));
    00267     this->pos = position;
    00268   }
    00269
    00275   void UpdatePosition(int difference)
    00276   {
    00277     if (difference == 0) return;
    00278     this->SetPosition(Clamp(this->pos + difference, 0, max(this->count - this->cap, 0)));
    00279   }
    00280
    00287   void ScrollTowards(int position)
    00288   {
    00289     if (position < this->GetPosition()) {
    00290       /* scroll up to the item */
    00291       this->SetPosition(position);
    00292     } else if (position >= this->GetPosition() + this->GetCapacity()) {
    00293       /* scroll down so that the item is at the bottom */
    00294       this->SetPosition(position - this->GetCapacity() + 1);
    00295     }
    00296   }
    00297 };
    00298
    00302 struct ResizeInfo {
    00303   uint step_width;
    00304   uint step_height;
    00305 };
    00306
    00308 enum SortButtonState {
    00309   SBS_OFF,
    00310   SBS_DOWN,
    00311   SBS_UP,
    00312 };
    00313
    00321 struct ViewportData : ViewPort {
    00322   VehicleID follow_vehicle;
    00323   int32 scrollpos_x;
    00324   int32 scrollpos_y;
    00325   int32 dest_scrollpos_x;
    00326   int32 dest_scrollpos_y;
    00327 };
    00328
    00332 struct Window : ZeroedMemoryAllocator {
    00334   enum EventState {
    00335     ES_HANDLED,
    00336     ES_NOT_HANDLED,
    00337   };
    00338
    00339 protected:
    00340   void InitializeData(WindowClass cls, int window_number, uint32 desc_flags);
    00341   void InitializePositionSize(int x, int y, int min_width, int min_height);
    00342   void FindWindowPlacementAndResize(int def_width, int def_height);
    00343
    00344 public:
    00345   Window();
    00346
    00347   virtual ~Window();
    00348
    00355   FORCEINLINE void *operator new[](size_t size)
    00356   {
    00357     NOT_REACHED();
    00358   }
    00359
    00365   FORCEINLINE void operator delete(void *ptr)
    00366   {
    00367   }
    00368
    00369   uint16 flags4;
    00370   WindowClass window_class;
    00371   WindowNumber window_number;
    00372
    00373   int left;
    00374   int top;
    00375   int width;
    00376   int height;
    00377
    00378   Scrollbar hscroll;
    00379   Scrollbar vscroll;
    00380   Scrollbar vscroll2;
    00381   ResizeInfo resize;
    00382
    00383   Owner owner;
    00384
    00385   ViewportData *viewport;
    00386   uint32 desc_flags;
    00387   const NWidgetCore *nested_focus;
    00388   NWidgetBase *nested_root;
    00389   NWidgetBase **nested_array;
    00390   uint nested_array_size;
    00391   NWidgetStacked *shade_select;
    00392   Dimension unshaded_size;
    00393
    00394   Window *parent;
    00395   Window *z_front;
    00396   Window *z_back;
    00397
    00398   template <class NWID>
    00399   inline const NWID *GetWidget(uint widnum) const;
    00400   template <class NWID>
    00401   inline NWID *GetWidget(uint widnum);
    00402
    00403
    00404   void InitNested(const WindowDesc *desc, WindowNumber number = 0);
    00405   void CreateNestedTree(const WindowDesc *desc, bool fill_nested = true);
    00406   void FinishInitNested(const WindowDesc *desc, WindowNumber window_number);
    00407
    00415   inline void SetWidgetDisabledState(byte widget_index, bool disab_stat)
    00416   {
    00417     assert(widget_index < this->nested_array_size);
    00418     if (this->nested_array[widget_index] != NULL) this->GetWidget<NWidgetCore>(widget_index)->SetDisabled(disab_stat);
    00419   }
    00420
    00425   inline void DisableWidget(byte widget_index)
    00426   {
    00427     SetWidgetDisabledState(widget_index, true);
    00428   }
    00429
    00434   inline void EnableWidget(byte widget_index)
    00435   {
    00436     SetWidgetDisabledState(widget_index, false);
    00437   }
    00438
    00444   inline bool IsWidgetDisabled(byte widget_index) const
    00445   {
    00446     assert(widget_index < this->nested_array_size);
    00447     return this->GetWidget<NWidgetCore>(widget_index)->IsDisabled();
    00448   }
    00449
    00455   inline bool IsWidgetFocused(byte widget_index) const
    00456   {
    00457     return this->nested_focus != NULL && this->nested_focus->index == widget_index;
    00458   }
    00459
    00466   inline bool IsWidgetGloballyFocused(byte widget_index) const
    00467   {
    00468     return _focused_window == this && IsWidgetFocused(widget_index);
    00469   }
    00470
    00476   inline void SetWidgetLoweredState(byte widget_index, bool lowered_stat)
    00477   {
    00478     assert(widget_index < this->nested_array_size);
    00479     this->GetWidget<NWidgetCore>(widget_index)->SetLowered(lowered_stat);
    00480   }
    00481
    00486   inline void ToggleWidgetLoweredState(byte widget_index)
    00487   {
    00488     assert(widget_index < this->nested_array_size);
    00489     bool lowered_state = this->GetWidget<NWidgetCore>(widget_index)->IsLowered();
    00490     this->GetWidget<NWidgetCore>(widget_index)->SetLowered(!lowered_state);
    00491   }
    00492
    00497   inline void LowerWidget(byte widget_index)
    00498   {
    00499     SetWidgetLoweredState(widget_index, true);
    00500   }
    00501
    00506   inline void RaiseWidget(byte widget_index)
    00507   {
    00508     SetWidgetLoweredState(widget_index, false);
    00509   }
    00510
    00516   inline bool IsWidgetLowered(byte widget_index) const
    00517   {
    00518     assert(widget_index < this->nested_array_size);
    00519     return this->GetWidget<NWidgetCore>(widget_index)->IsLowered();
    00520   }
    00521
    00522   bool SetFocusedWidget(byte widget_index);
    00523
    00524   void HandleButtonClick(byte widget);
    00525
    00526   void RaiseButtons(bool autoraise = false);
    00527   void CDECL SetWidgetsDisabledState(bool disab_stat, int widgets, ...);
    00528   void CDECL SetWidgetsLoweredState(bool lowered_stat, int widgets, ...);
    00529   void SetWidgetDirty(byte widget_index) const;
    00530
    00531   void DrawWidgets() const;
    00532   void DrawViewport() const;
    00533   void DrawSortButtonState(int widget, SortButtonState state) const;
    00534
    00535   void DeleteChildWindows(WindowClass wc = WC_INVALID) const;
    00536
    00537   void SetDirty() const;
    00538   void ReInit(int rx = 0, int ry = 0);
    00539
    00541   inline bool IsShaded() const
    00542   {
    00543     return this->shade_select != NULL && this->shade_select->shown_plane == SZSP_HORIZONTAL;
    00544   }
    00545
    00546   void SetShaded(bool make_shaded);
    00547
    00552   void InvalidateData(int data = 0)
    00553   {
    00554     this->SetDirty();
    00555     this->OnInvalidateData(data);
    00556   }
    00557
    00558   /*** Event handling ***/
    00559
    00564   virtual void OnInit() { }
    00565
    00574   virtual Point OnInitialPosition(const WindowDesc *desc, int16 sm_width, int16 sm_height, int window_number);
    00575
    00580   virtual void OnPaint() {}
    00581
    00588   virtual void DrawWidget(const Rect &r, int widget) const {}
    00589
    00602   virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) {}
    00603
    00610   virtual void SetStringParameters(int widget) const {}
    00611
    00615   virtual void OnFocus() {}
    00616
    00620   virtual void OnFocusLost() {}
    00621
    00629   virtual EventState OnKeyPress(uint16 key, uint16 keycode) { return ES_NOT_HANDLED; }
    00630
    00636   virtual EventState OnCTRLStateChange() { return ES_NOT_HANDLED; }
    00637
    00638
    00644   virtual void OnClick(Point pt, int widget) {}
    00645
    00651   virtual void OnDoubleClick(Point pt, int widget) {}
    00652
    00658   virtual void OnRightClick(Point pt, int widget) {}
    00659
    00665   virtual void OnDragDrop(Point pt, int widget) {}
    00666
    00671   virtual void OnScroll(Point delta) {}
    00672
    00679   virtual void OnMouseOver(Point pt, int widget) {}
    00680
    00685   virtual void OnMouseWheel(int wheel) {}
    00686
    00687
    00691   virtual void OnMouseLoop() {}
    00692
    00696   virtual void OnTick() {}
    00697
    00701   virtual void OnHundredthTick() {}
    00702
    00706   virtual void OnTimeout() {}
    00707
    00708
    00713   virtual void OnResize() {}
    00714
    00720   virtual void OnDropdownSelect(int widget, int index) {}
    00721
    00727   virtual void OnQueryTextFinished(char *str) {}
    00728
    00733   virtual void OnInvalidateData(int data = 0) {}
    00734
    00735
    00742   virtual void OnPlaceObject(Point pt, TileIndex tile) {}
    00743
    00747   virtual void OnPlaceObjectAbort() {}
    00748
    00749
    00757   virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt) {}
    00758
    00768   virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile) {}
    00769
    00777   virtual void OnPlacePresize(Point pt, TileIndex tile) {}
    00778
    00779   /*** End of the event handling ***/
    00780 };
    00781
    00787 template <class NWID>
    00788 inline NWID *Window::GetWidget(uint widnum)
    00789 {
    00790   if (widnum >= this->nested_array_size || this->nested_array[widnum] == NULL) return NULL;
    00791   NWID *nwid = dynamic_cast<NWID *>(this->nested_array[widnum]);
    00792   assert(nwid != NULL);
    00793   return nwid;
    00794 }
    00795
    00797 template <>
    00798 inline const NWidgetBase *Window::GetWidget<NWidgetBase>(uint widnum) const
    00799 {
    00800   if (widnum >= this->nested_array_size) return NULL;
    00801   return this->nested_array[widnum];
    00802 }
    00803
    00809 template <class NWID>
    00810 inline const NWID *Window::GetWidget(uint widnum) const
    00811 {
    00812   return const_cast<Window *>(this)->GetWidget<NWID>(widnum);
    00813 }
    00814
    00815
    00819 class PickerWindowBase : public Window {
    00820
    00821 public:
    00822   PickerWindowBase(Window *parent) : Window()
    00823   {
    00824     this->parent = parent;
    00825   };
    00826
    00827   virtual ~PickerWindowBase();
    00828 };
    00829
    00833 enum WindowFlags {
    00834   WF_TIMEOUT_TRIGGER   = 1,
    00835   WF_TIMEOUT_BEGIN     = 7,
    00836   WF_TIMEOUT_MASK      = 7,
    00837   WF_DRAGGING          = 1 <<  3,
    00838   WF_SCROLL_UP         = 1 <<  4,
    00839   WF_SCROLL_DOWN       = 1 <<  5,
    00840   WF_SCROLL_MIDDLE     = 1 <<  6,
    00841   WF_SCROLL2           = 1 <<  7,
    00842   WF_HSCROLL           = 1 <<  8,
    00843   WF_SIZING_RIGHT      = 1 <<  9,
    00844   WF_SIZING_LEFT       = 1 << 10,
    00845   WF_SIZING            = WF_SIZING_RIGHT | WF_SIZING_LEFT,
    00846   WF_STICKY            = 1 << 11,
    00847
    00848   WF_DISABLE_VP_SCROLL = 1 << 12,
    00849
    00850   WF_WHITE_BORDER_ONE  = 1 << 13,
    00851   WF_WHITE_BORDER_MASK = 1 << 14 | WF_WHITE_BORDER_ONE,
    00852 };
    00853
    00854 Window *BringWindowToFrontById(WindowClass cls, WindowNumber number);
    00855 Window *FindWindowFromPt(int x, int y);
    00856
    00863 template <typename Wcls>
    00864 Wcls *AllocateWindowDescFront(const WindowDesc *desc, int window_number)
    00865 {
    00866   if (BringWindowToFrontById(desc->cls, window_number)) return NULL;
    00867   return new Wcls(desc, window_number);
    00868 }
    00869
    00870 void RelocateAllWindows(int neww, int newh);
    00871
    00872 /* misc_gui.cpp */
    00873 void GuiShowTooltips(StringID str, uint paramcount = 0, const uint64 params[] = NULL, bool use_left_mouse_button = false);
    00874
    00875 /* widget.cpp */
    00876 int GetWidgetFromPos(const Window *w, int x, int y);
    00877
    00879 #define FOR_ALL_WINDOWS_FROM_BACK_FROM(w, start)  for (w = start; w != NULL; w = w->z_front) if (w->window_class != WC_INVALID)
    00880 #define FOR_ALL_WINDOWS_FROM_FRONT_FROM(w, start) for (w = start; w != NULL; w = w->z_back) if (w->window_class != WC_INVALID)
    00881 #define FOR_ALL_WINDOWS_FROM_BACK(w)  FOR_ALL_WINDOWS_FROM_BACK_FROM(w, _z_back_window)
    00882 #define FOR_ALL_WINDOWS_FROM_FRONT(w) FOR_ALL_WINDOWS_FROM_FRONT_FROM(w, _z_front_window)
    00883
    00884 extern Point _cursorpos_drag_start;
    00885
    00886 extern int _scrollbar_start_pos;
    00887 extern int _scrollbar_size;
    00888 extern byte _scroller_click_timeout;
    00889
    00890 extern bool _scrolling_scrollbar;
    00891 extern bool _scrolling_viewport;
    00892
    00893 extern byte _special_mouse_mode;
    00894 enum SpecialMouseMode {
    00895   WSM_NONE     = 0,
    00896   WSM_DRAGDROP = 1,
    00897   WSM_SIZING   = 2,
    00898   WSM_PRESIZE  = 3,
    00899 };
    00900
    00901 Window *GetCallbackWnd();
    00902
    00903 void SetFocusedWindow(Window *w);
    00904 bool EditBoxInGlobalFocus();
    00905
    00906 void ScrollbarClickHandler(Window *w, const NWidgetCore *nw, int x, int y);
    00907
    00908 #endif /* WINDOW_GUI_H */