00001
00002
00003
00004
00005
00006
00007
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
00041 WD_IMGBTN_LEFT = 1,
00042 WD_IMGBTN_RIGHT = 2,
00043 WD_IMGBTN_TOP = 1,
00044 WD_IMGBTN_BOTTOM = 2,
00045
00046
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
00056 WD_FRAMERECT_LEFT = 2,
00057 WD_FRAMERECT_RIGHT = 2,
00058 WD_FRAMERECT_TOP = 1,
00059 WD_FRAMERECT_BOTTOM = 1,
00060
00061
00062 WD_TEXTPANEL_TOP = 6,
00063 WD_TEXTPANEL_BOTTOM = 6,
00064
00065
00066 WD_FRAMETEXT_LEFT = 6,
00067 WD_FRAMETEXT_RIGHT = 6,
00068 WD_FRAMETEXT_TOP = 6,
00069 WD_FRAMETEXT_BOTTOM = 6,
00070
00071
00072 WD_MATRIX_LEFT = 2,
00073 WD_MATRIX_RIGHT = 2,
00074 WD_MATRIX_TOP = 3,
00075 WD_MATRIX_BOTTOM = 1,
00076
00077
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
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
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
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
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
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
00126 void DrawFrameRect(int left, int top, int right, int bottom, Colours colour, FrameFlags flags);
00127
00128
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
00291 this->SetPosition(position);
00292 } else if (position >= this->GetPosition() + this->GetCapacity()) {
00293
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
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
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
00873 void GuiShowTooltips(StringID str, uint paramcount = 0, const uint64 params[] = NULL, bool use_left_mouse_button = false);
00874
00875
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