| 1 | // Aseprite UI Library | 
|---|
| 2 | // Copyright (C) 2018-2022  Igara Studio S.A. | 
|---|
| 3 | // Copyright (C) 2001-2018  David Capello | 
|---|
| 4 | // | 
|---|
| 5 | // This file is released under the terms of the MIT license. | 
|---|
| 6 | // Read LICENSE.txt for more information. | 
|---|
| 7 |  | 
|---|
| 8 | #ifndef UI_WIDGET_H_INCLUDED | 
|---|
| 9 | #define UI_WIDGET_H_INCLUDED | 
|---|
| 10 | #pragma once | 
|---|
| 11 |  | 
|---|
| 12 | #include "gfx/border.h" | 
|---|
| 13 | #include "gfx/color.h" | 
|---|
| 14 | #include "gfx/point.h" | 
|---|
| 15 | #include "gfx/rect.h" | 
|---|
| 16 | #include "gfx/region.h" | 
|---|
| 17 | #include "gfx/size.h" | 
|---|
| 18 | #include "obs/signal.h" | 
|---|
| 19 | #include "os/font.h" | 
|---|
| 20 | #include "ui/base.h" | 
|---|
| 21 | #include "ui/component.h" | 
|---|
| 22 | #include "ui/graphics.h" | 
|---|
| 23 | #include "ui/widget_type.h" | 
|---|
| 24 | #include "ui/widgets_list.h" | 
|---|
| 25 |  | 
|---|
| 26 | #include <string> | 
|---|
| 27 |  | 
|---|
| 28 | #define ASSERT_VALID_WIDGET(widget) ASSERT((widget) != nullptr) | 
|---|
| 29 |  | 
|---|
| 30 | namespace ui { | 
|---|
| 31 |  | 
|---|
| 32 | class Display; | 
|---|
| 33 | class InitThemeEvent; | 
|---|
| 34 | class KeyMessage; | 
|---|
| 35 | class LoadLayoutEvent; | 
|---|
| 36 | class Manager; | 
|---|
| 37 | class Message; | 
|---|
| 38 | class MouseMessage; | 
|---|
| 39 | class PaintEvent; | 
|---|
| 40 | class ResizeEvent; | 
|---|
| 41 | class SaveLayoutEvent; | 
|---|
| 42 | class SizeHintEvent; | 
|---|
| 43 | class Style; | 
|---|
| 44 | class Theme; | 
|---|
| 45 | class Window; | 
|---|
| 46 |  | 
|---|
| 47 | class Widget : public Component { | 
|---|
| 48 | public: | 
|---|
| 49 |  | 
|---|
| 50 | // =============================================================== | 
|---|
| 51 | // CTOR & DTOR | 
|---|
| 52 | // =============================================================== | 
|---|
| 53 |  | 
|---|
| 54 | Widget(WidgetType type = kGenericWidget); | 
|---|
| 55 | virtual ~Widget(); | 
|---|
| 56 |  | 
|---|
| 57 | // Safe way to delete a widget when it is not in the manager message | 
|---|
| 58 | // queue anymore. | 
|---|
| 59 | void deferDelete(); | 
|---|
| 60 |  | 
|---|
| 61 | // Main properties. | 
|---|
| 62 |  | 
|---|
| 63 | WidgetType type() const { return m_type; } | 
|---|
| 64 | void setType(WidgetType type) { m_type = type; } // TODO remove this function | 
|---|
| 65 |  | 
|---|
| 66 | const std::string& id() const { return m_id; } | 
|---|
| 67 | void setId(const char* id) { m_id = id; } | 
|---|
| 68 |  | 
|---|
| 69 | int flags() const { return m_flags; } | 
|---|
| 70 | bool hasFlags(int flags) const { return ((m_flags & flags) == flags); } | 
|---|
| 71 | void enableFlags(int flags) { m_flags |= flags; } | 
|---|
| 72 | void disableFlags(int flags) { m_flags &= ~flags; } | 
|---|
| 73 |  | 
|---|
| 74 | int align() const { return (m_flags & ALIGN_MASK); } | 
|---|
| 75 | void setAlign(int align) { | 
|---|
| 76 | m_flags = ((m_flags & PROPERTIES_MASK) | | 
|---|
| 77 | (align & ALIGN_MASK)); | 
|---|
| 78 | } | 
|---|
| 79 |  | 
|---|
| 80 | // Text property. | 
|---|
| 81 |  | 
|---|
| 82 | bool hasText() const { return hasFlags(HAS_TEXT); } | 
|---|
| 83 |  | 
|---|
| 84 | const std::string& text() const { return m_text; } | 
|---|
| 85 | int textInt() const; | 
|---|
| 86 | double textDouble() const; | 
|---|
| 87 | void setText(const std::string& text); | 
|---|
| 88 | void setTextf(const char* text, ...); | 
|---|
| 89 | void setTextQuiet(const std::string& text); | 
|---|
| 90 |  | 
|---|
| 91 | int textWidth() const; | 
|---|
| 92 | int textHeight() const; | 
|---|
| 93 |  | 
|---|
| 94 | gfx::Size textSize() const { | 
|---|
| 95 | return gfx::Size(textWidth(), textHeight()); | 
|---|
| 96 | } | 
|---|
| 97 |  | 
|---|
| 98 | // =============================================================== | 
|---|
| 99 | // COMMON PROPERTIES | 
|---|
| 100 | // =============================================================== | 
|---|
| 101 |  | 
|---|
| 102 | // True if this widget and all its ancestors are visible. | 
|---|
| 103 | bool isVisible() const; | 
|---|
| 104 | void setVisible(bool state); | 
|---|
| 105 |  | 
|---|
| 106 | // True if this widget can receive user input (is not disabled). | 
|---|
| 107 | bool isEnabled() const; | 
|---|
| 108 | void setEnabled(bool state); | 
|---|
| 109 |  | 
|---|
| 110 | // True if this widget is selected (pushed in case of a button, or | 
|---|
| 111 | // checked in the case of a check-box). | 
|---|
| 112 | bool isSelected() const; | 
|---|
| 113 | void setSelected(bool state); | 
|---|
| 114 |  | 
|---|
| 115 | // True if this widget wants more space when it's inside a Box | 
|---|
| 116 | // parent. | 
|---|
| 117 | bool isExpansive() const; | 
|---|
| 118 | void setExpansive(bool state); | 
|---|
| 119 |  | 
|---|
| 120 | // True if this is a decorative widget created by the current | 
|---|
| 121 | // theme. Decorative widgets are arranged by the theme instead that | 
|---|
| 122 | // the parent's widget. | 
|---|
| 123 | bool isDecorative() const; | 
|---|
| 124 | void setDecorative(bool state); | 
|---|
| 125 |  | 
|---|
| 126 | // True if this widget can receive the keyboard focus. | 
|---|
| 127 | bool isFocusStop() const; | 
|---|
| 128 | void setFocusStop(bool state); | 
|---|
| 129 |  | 
|---|
| 130 | // True if this widget wants the focus by default when it's shown by | 
|---|
| 131 | // first time (e.g. when its parent window is opened). | 
|---|
| 132 | void setFocusMagnet(bool state); | 
|---|
| 133 | bool isFocusMagnet() const; | 
|---|
| 134 |  | 
|---|
| 135 | // =============================================================== | 
|---|
| 136 | // LOOK & FEEL | 
|---|
| 137 | // =============================================================== | 
|---|
| 138 |  | 
|---|
| 139 | os::Font* font() const; | 
|---|
| 140 |  | 
|---|
| 141 | // Gets the background color of the widget. | 
|---|
| 142 | gfx::Color bgColor() const { | 
|---|
| 143 | if (gfx::geta(m_bgColor) == 0 && m_parent) | 
|---|
| 144 | return m_parent->bgColor(); | 
|---|
| 145 | else | 
|---|
| 146 | return m_bgColor; | 
|---|
| 147 | } | 
|---|
| 148 |  | 
|---|
| 149 | // Sets the background color of the widget | 
|---|
| 150 | void setBgColor(gfx::Color color); | 
|---|
| 151 |  | 
|---|
| 152 | Theme* theme() const { return m_theme; } | 
|---|
| 153 | Style* style() const { return m_style; } | 
|---|
| 154 | void setTheme(Theme* theme); | 
|---|
| 155 | void setStyle(Style* style); | 
|---|
| 156 | void initTheme(); | 
|---|
| 157 |  | 
|---|
| 158 | // =============================================================== | 
|---|
| 159 | // PARENTS & CHILDREN | 
|---|
| 160 | // =============================================================== | 
|---|
| 161 |  | 
|---|
| 162 | Window* window() const; | 
|---|
| 163 | Widget* parent() const { return m_parent; } | 
|---|
| 164 | int parentIndex() const { return m_parentIndex; } | 
|---|
| 165 | Manager* manager() const; | 
|---|
| 166 | Display* display() const; | 
|---|
| 167 |  | 
|---|
| 168 | // Returns a list of children. | 
|---|
| 169 | const WidgetsList& children() const { return m_children; } | 
|---|
| 170 | bool hasChildren() const { return !m_children.empty(); } | 
|---|
| 171 |  | 
|---|
| 172 | Widget* at(int index) { return m_children[index]; } | 
|---|
| 173 | int getChildIndex(Widget* child); | 
|---|
| 174 |  | 
|---|
| 175 | // Returns the first/last child or nullptr if it doesn't exist. | 
|---|
| 176 | Widget* firstChild() { | 
|---|
| 177 | return (hasChildren() ? m_children.front(): nullptr); | 
|---|
| 178 | } | 
|---|
| 179 | Widget* lastChild() { | 
|---|
| 180 | return (hasChildren() ? m_children.back(): nullptr); | 
|---|
| 181 | } | 
|---|
| 182 |  | 
|---|
| 183 | // Returns the next or previous siblings. | 
|---|
| 184 | Widget* nextSibling(); | 
|---|
| 185 | Widget* previousSibling(); | 
|---|
| 186 |  | 
|---|
| 187 | Widget* pick(const gfx::Point& pt, | 
|---|
| 188 | const bool checkParentsVisibility = true) const; | 
|---|
| 189 | virtual Widget* pickFromScreenPos(const gfx::Point& screenPos) const; | 
|---|
| 190 |  | 
|---|
| 191 | bool hasChild(Widget* child); | 
|---|
| 192 | bool hasAncestor(Widget* ancestor); | 
|---|
| 193 | Widget* findChild(const char* id) const; | 
|---|
| 194 |  | 
|---|
| 195 | // Returns a widget in the same window that is located "sibling". | 
|---|
| 196 | Widget* findSibling(const char* id) const; | 
|---|
| 197 |  | 
|---|
| 198 | // Finds a child with the specified ID and dynamic-casts it to type | 
|---|
| 199 | // T. | 
|---|
| 200 | template<class T> | 
|---|
| 201 | T* findChildT(const char* id) const { | 
|---|
| 202 | return dynamic_cast<T*>(findChild(id)); | 
|---|
| 203 | } | 
|---|
| 204 |  | 
|---|
| 205 | template<class T> | 
|---|
| 206 | T* findFirstChildByType() const { | 
|---|
| 207 | for (auto child : m_children) { | 
|---|
| 208 | if (T* specificChild = dynamic_cast<T*>(child)) | 
|---|
| 209 | return specificChild; | 
|---|
| 210 | } | 
|---|
| 211 | return nullptr; | 
|---|
| 212 | } | 
|---|
| 213 |  | 
|---|
| 214 | void addChild(Widget* child); | 
|---|
| 215 | void removeChild(Widget* child); | 
|---|
| 216 | void removeAllChildren(); | 
|---|
| 217 | void replaceChild(Widget* oldChild, Widget* newChild); | 
|---|
| 218 | void insertChild(int index, Widget* child); | 
|---|
| 219 | void moveChildTo(Widget* thisChild, Widget* toThisPosition); | 
|---|
| 220 |  | 
|---|
| 221 | // =============================================================== | 
|---|
| 222 | // LAYOUT & CONSTRAINT | 
|---|
| 223 | // =============================================================== | 
|---|
| 224 |  | 
|---|
| 225 | void layout(); | 
|---|
| 226 | void loadLayout(); | 
|---|
| 227 | void saveLayout(); | 
|---|
| 228 |  | 
|---|
| 229 | void setDecorativeWidgetBounds(); | 
|---|
| 230 |  | 
|---|
| 231 | // =============================================================== | 
|---|
| 232 | // POSITION & GEOMETRY | 
|---|
| 233 | // =============================================================== | 
|---|
| 234 |  | 
|---|
| 235 | gfx::Rect bounds() const { return m_bounds; } | 
|---|
| 236 | gfx::Point origin() const { return m_bounds.origin(); } | 
|---|
| 237 | gfx::Size size() const { return m_bounds.size(); } | 
|---|
| 238 |  | 
|---|
| 239 | gfx::Rect clientBounds() const { | 
|---|
| 240 | return gfx::Rect(0, 0, m_bounds.w, m_bounds.h); | 
|---|
| 241 | } | 
|---|
| 242 |  | 
|---|
| 243 | gfx::Rect childrenBounds() const; | 
|---|
| 244 | gfx::Rect clientChildrenBounds() const; | 
|---|
| 245 |  | 
|---|
| 246 | // Bounds of this widget or window on native screen/desktop coordinates. | 
|---|
| 247 | gfx::Rect boundsOnScreen() const; | 
|---|
| 248 |  | 
|---|
| 249 | // Sets the bounds of the widget generating a onResize() event. | 
|---|
| 250 | void setBounds(const gfx::Rect& rc); | 
|---|
| 251 |  | 
|---|
| 252 | // Sets the bounds of the widget without generating any kind of | 
|---|
| 253 | // event. This member function must be used if you override | 
|---|
| 254 | // onResize() and want to change the size of the widget without | 
|---|
| 255 | // generating recursive onResize() events. | 
|---|
| 256 | void setBoundsQuietly(const gfx::Rect& rc); | 
|---|
| 257 | void offsetWidgets(int dx, int dy); | 
|---|
| 258 |  | 
|---|
| 259 | const gfx::Size& minSize() const { return m_minSize; } | 
|---|
| 260 | const gfx::Size& maxSize() const { return m_maxSize; } | 
|---|
| 261 | void setMinSize(const gfx::Size& sz); | 
|---|
| 262 | void setMaxSize(const gfx::Size& sz); | 
|---|
| 263 | void resetMinSize(); | 
|---|
| 264 | void resetMaxSize(); | 
|---|
| 265 |  | 
|---|
| 266 | const gfx::Border& border() const { return m_border; } | 
|---|
| 267 | void setBorder(const gfx::Border& border); | 
|---|
| 268 |  | 
|---|
| 269 | int childSpacing() const { return m_childSpacing; } | 
|---|
| 270 | void setChildSpacing(int childSpacing); | 
|---|
| 271 |  | 
|---|
| 272 | void noBorderNoChildSpacing(); | 
|---|
| 273 |  | 
|---|
| 274 | // Flags for getDrawableRegion() | 
|---|
| 275 | enum DrawableRegionFlags { | 
|---|
| 276 | kCutTopWindows = 1, // Cut areas where are windows on top. | 
|---|
| 277 | kUseChildArea = 2,  // Use areas where are children. | 
|---|
| 278 | kCutTopWindowsAndUseChildArea = kCutTopWindows | kUseChildArea, | 
|---|
| 279 | }; | 
|---|
| 280 |  | 
|---|
| 281 | void getRegion(gfx::Region& region); | 
|---|
| 282 | void getDrawableRegion(gfx::Region& region, DrawableRegionFlags flags); | 
|---|
| 283 |  | 
|---|
| 284 | gfx::Point toClient(const gfx::Point& pt) const { | 
|---|
| 285 | return pt - m_bounds.origin(); | 
|---|
| 286 | } | 
|---|
| 287 | gfx::Rect toClient(const gfx::Rect& rc) const { | 
|---|
| 288 | return gfx::Rect(rc).offset(-m_bounds.x, -m_bounds.y); | 
|---|
| 289 | } | 
|---|
| 290 |  | 
|---|
| 291 | void getTextIconInfo( | 
|---|
| 292 | gfx::Rect* box, | 
|---|
| 293 | gfx::Rect* text = nullptr, | 
|---|
| 294 | gfx::Rect* icon = nullptr, | 
|---|
| 295 | int icon_align = 0, int icon_w = 0, int icon_h = 0); | 
|---|
| 296 |  | 
|---|
| 297 | // =============================================================== | 
|---|
| 298 | // REFRESH ISSUES | 
|---|
| 299 | // =============================================================== | 
|---|
| 300 |  | 
|---|
| 301 | bool isDoubleBuffered() const; | 
|---|
| 302 | void setDoubleBuffered(bool doubleBuffered); | 
|---|
| 303 |  | 
|---|
| 304 | bool isTransparent() const; | 
|---|
| 305 | void setTransparent(bool transparent); | 
|---|
| 306 |  | 
|---|
| 307 | void invalidate(); | 
|---|
| 308 | void invalidateRect(const gfx::Rect& rect); | 
|---|
| 309 | void invalidateRegion(const gfx::Region& region); | 
|---|
| 310 |  | 
|---|
| 311 | // Returns the region to generate PaintMessages. It's cleared | 
|---|
| 312 | // after flushRedraw() is called. | 
|---|
| 313 | const gfx::Region& getUpdateRegion() const { | 
|---|
| 314 | return m_updateRegion; | 
|---|
| 315 | } | 
|---|
| 316 |  | 
|---|
| 317 | // Generates paint messages for the current update region. | 
|---|
| 318 | void flushRedraw(); | 
|---|
| 319 |  | 
|---|
| 320 | GraphicsPtr getGraphics(const gfx::Rect& clip); | 
|---|
| 321 |  | 
|---|
| 322 | // =============================================================== | 
|---|
| 323 | // GUI MANAGER | 
|---|
| 324 | // =============================================================== | 
|---|
| 325 |  | 
|---|
| 326 | bool sendMessage(Message* msg); | 
|---|
| 327 | void closeWindow(); | 
|---|
| 328 |  | 
|---|
| 329 | void broadcastMouseMessage(const gfx::Point& screenPos, | 
|---|
| 330 | WidgetsList& targets); | 
|---|
| 331 |  | 
|---|
| 332 | // =============================================================== | 
|---|
| 333 | // SIZE & POSITION | 
|---|
| 334 | // =============================================================== | 
|---|
| 335 |  | 
|---|
| 336 | gfx::Size sizeHint(); | 
|---|
| 337 | gfx::Size sizeHint(const gfx::Size& fitIn); | 
|---|
| 338 | void setSizeHint(const gfx::Size& fixedSize); | 
|---|
| 339 | void setSizeHint(int fixedWidth, int fixedHeight); | 
|---|
| 340 | void resetSizeHint(); | 
|---|
| 341 |  | 
|---|
| 342 | // =============================================================== | 
|---|
| 343 | // MOUSE, FOCUS & KEYBOARD | 
|---|
| 344 | // =============================================================== | 
|---|
| 345 |  | 
|---|
| 346 | void requestFocus(); | 
|---|
| 347 | void releaseFocus(); | 
|---|
| 348 | void captureMouse(); | 
|---|
| 349 | void releaseMouse(); | 
|---|
| 350 |  | 
|---|
| 351 | bool hasFocus() const { return hasFlags(HAS_FOCUS); } | 
|---|
| 352 | bool hasMouse() const { return hasFlags(HAS_MOUSE); } | 
|---|
| 353 | bool hasCapture() const { return hasFlags(HAS_CAPTURE); } | 
|---|
| 354 |  | 
|---|
| 355 | // Checking if the mouse is currently above the widget. | 
|---|
| 356 | bool hasMouseOver() const; | 
|---|
| 357 |  | 
|---|
| 358 | // Returns the mouse position relative to the top-left corner of | 
|---|
| 359 | // the ui::Display's client area/content rect. | 
|---|
| 360 | gfx::Point mousePosInDisplay() const; | 
|---|
| 361 |  | 
|---|
| 362 | // Returns the mouse position relative to the top-left cornder of | 
|---|
| 363 | // the widget bounds. | 
|---|
| 364 | gfx::Point mousePosInClientBounds() const { | 
|---|
| 365 | return toClient(mousePosInDisplay()); | 
|---|
| 366 | } | 
|---|
| 367 |  | 
|---|
| 368 | // Offer the capture to widgets of the given type. Returns true if | 
|---|
| 369 | // the capture was passed to other widget. | 
|---|
| 370 | bool offerCapture(ui::MouseMessage* mouseMsg, int widget_type); | 
|---|
| 371 |  | 
|---|
| 372 | // Returns lower-case letter that represet the mnemonic of the widget | 
|---|
| 373 | // (the underscored character, i.e. the letter after & symbol). | 
|---|
| 374 | int mnemonic() const { return m_mnemonic; } | 
|---|
| 375 | void setMnemonic(int mnemonic); | 
|---|
| 376 |  | 
|---|
| 377 | // Assigns mnemonic from the character preceded by the given | 
|---|
| 378 | // escapeChar ('&' by default). | 
|---|
| 379 | void processMnemonicFromText(int escapeChar = '&'); | 
|---|
| 380 |  | 
|---|
| 381 | // Returns true if the mnemonic character is pressed. | 
|---|
| 382 | bool isMnemonicPressed(const ui::KeyMessage* keyMsg) const; | 
|---|
| 383 |  | 
|---|
| 384 | // Signals | 
|---|
| 385 | obs::signal<void()> InitTheme; | 
|---|
| 386 |  | 
|---|
| 387 | protected: | 
|---|
| 388 | // =============================================================== | 
|---|
| 389 | // MESSAGE PROCESSING | 
|---|
| 390 | // =============================================================== | 
|---|
| 391 |  | 
|---|
| 392 | virtual bool onProcessMessage(Message* msg); | 
|---|
| 393 |  | 
|---|
| 394 | // =============================================================== | 
|---|
| 395 | // EVENTS | 
|---|
| 396 | // =============================================================== | 
|---|
| 397 |  | 
|---|
| 398 | virtual void onInvalidateRegion(const gfx::Region& region); | 
|---|
| 399 | virtual void onSizeHint(SizeHintEvent& ev); | 
|---|
| 400 | virtual void onLoadLayout(LoadLayoutEvent& ev); | 
|---|
| 401 | virtual void onSaveLayout(SaveLayoutEvent& ev); | 
|---|
| 402 | virtual void onResize(ResizeEvent& ev); | 
|---|
| 403 | virtual void onPaint(PaintEvent& ev); | 
|---|
| 404 | virtual void onBroadcastMouseMessage(const gfx::Point& screenPos, | 
|---|
| 405 | WidgetsList& targets); | 
|---|
| 406 | virtual void onInitTheme(InitThemeEvent& ev); | 
|---|
| 407 | virtual void onSetDecorativeWidgetBounds(); | 
|---|
| 408 | virtual void onVisible(bool visible); | 
|---|
| 409 | virtual void onEnable(bool enabled); | 
|---|
| 410 | virtual void onSelect(bool selected); | 
|---|
| 411 | virtual void onSetText(); | 
|---|
| 412 | virtual void onSetBgColor(); | 
|---|
| 413 | virtual int onGetTextInt() const; | 
|---|
| 414 | virtual double onGetTextDouble() const; | 
|---|
| 415 |  | 
|---|
| 416 | private: | 
|---|
| 417 | void removeChild(const WidgetsList::iterator& it); | 
|---|
| 418 | void paint(Graphics* graphics, | 
|---|
| 419 | const gfx::Region& drawRegion, | 
|---|
| 420 | const bool isBg); | 
|---|
| 421 | bool paintEvent(Graphics* graphics, | 
|---|
| 422 | const bool isBg); | 
|---|
| 423 | void setDirtyFlag(); | 
|---|
| 424 |  | 
|---|
| 425 | WidgetType m_type;           // Widget's type | 
|---|
| 426 | std::string m_id;            // Widget's id | 
|---|
| 427 | int m_flags;                 // Special boolean properties (see flags in ui/base.h) | 
|---|
| 428 | Theme* m_theme;              // Widget's theme | 
|---|
| 429 | Style* m_style; | 
|---|
| 430 | std::string m_text;          // Widget text | 
|---|
| 431 | mutable os::FontRef m_font;  // Cached font returned by the theme | 
|---|
| 432 | gfx::Color m_bgColor;        // Background color | 
|---|
| 433 | gfx::Rect m_bounds; | 
|---|
| 434 | gfx::Region m_updateRegion;   // Region to be redrawed. | 
|---|
| 435 | WidgetsList m_children;       // Sub-widgets | 
|---|
| 436 | Widget* m_parent;             // Who is the parent? | 
|---|
| 437 | int m_parentIndex;            // Location/index of this widget in the parent's Widget::m_children vector | 
|---|
| 438 | gfx::Size* m_sizeHint; | 
|---|
| 439 | int m_mnemonic;               // Keyboard shortcut to access this widget like Alt+mnemonic | 
|---|
| 440 |  | 
|---|
| 441 | // Widget size limits | 
|---|
| 442 | gfx::Size m_minSize, m_maxSize; | 
|---|
| 443 |  | 
|---|
| 444 | gfx::Border m_border;       // Border separation with the parent | 
|---|
| 445 | int m_childSpacing;         // Separation between children | 
|---|
| 446 | }; | 
|---|
| 447 |  | 
|---|
| 448 | WidgetType register_widget_type(); | 
|---|
| 449 |  | 
|---|
| 450 | } // namespace ui | 
|---|
| 451 |  | 
|---|
| 452 | #endif | 
|---|
| 453 |  | 
|---|