diff options
-rw-r--r-- | src/widget.cpp | 76 | ||||
-rw-r--r-- | src/widget_type.h | 92 |
2 files changed, 142 insertions, 26 deletions
diff --git a/src/widget.cpp b/src/widget.cpp index c4cccf490..4a716ce21 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -876,12 +876,19 @@ int NWidgetHorizontal::ComputeMinimalSize() this->resize_x = 0; // smallest non-zero child widget resize step. this->resize_y = 1; // smallest common child resize step + if (this->head != NULL) this->head->padding_left += this->pip_pre; for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) { int idx = child_wid->ComputeMinimalSize(); biggest_index = max(biggest_index, idx); - this->min_x += child_wid->min_x; - this->min_y = max(this->min_y, child_wid->min_y); + if (child_wid->next != NULL) { + child_wid->padding_right += this->pip_inter; + } else { + child_wid->padding_right += this->pip_post; + } + + this->min_x += child_wid->min_x + child_wid->padding_left + child_wid->padding_right; + this->min_y = max(this->min_y, child_wid->min_y + child_wid->padding_top + child_wid->padding_bottom); this->fill_x |= child_wid->fill_x; this->fill_y &= child_wid->fill_y; @@ -890,6 +897,8 @@ int NWidgetHorizontal::ComputeMinimalSize() } this->resize_y = LeastCommonMultiple(this->resize_y, child_wid->resize_y); } + /* We need to zero the PIP settings so we can re-initialize the tree. */ + this->pip_pre = this->pip_inter = this->pip_post = 0; return biggest_index; } @@ -918,15 +927,16 @@ void NWidgetHorizontal::AssignMinimalPosition(uint x, uint y, uint given_width, allow_resize_x = (this->resize_x > 0); child_wid = rtl ? this->tail : this->head; while (child_wid != NULL) { + assert(given_height >= child_wid->min_y + child_wid->padding_top + child_wid->padding_bottom); /* Decide about vertical filling of the child. */ uint child_height; // Height of the child widget. uint child_pos_y; // Vertical position of child relative to the top of the container. if (child_wid->fill_y) { - child_height = given_height; - child_pos_y = 0; + child_height = given_height - child_wid->padding_top - child_wid->padding_bottom; + child_pos_y = child_wid->padding_top; } else { child_height = child_wid->min_y; - child_pos_y = (given_height - child_height) / 2; + child_pos_y = (given_height - child_wid->padding_top - child_wid->padding_bottom - child_height) / 2 + child_wid->padding_top; } /* Decide about horizontal filling of the child. */ @@ -941,8 +951,8 @@ void NWidgetHorizontal::AssignMinimalPosition(uint x, uint y, uint given_width, child_width += increment; } - child_wid->AssignMinimalPosition(x + position, y + child_pos_y, child_width, child_height, allow_resize_x, (this->resize_y > 0), rtl); - position += child_width; + child_wid->AssignMinimalPosition(x + position + (rtl ? child_wid->padding_right : child_wid->padding_left), y + child_pos_y, child_width, child_height, allow_resize_x, (this->resize_y > 0), rtl); + position += child_width + child_wid->padding_right + child_wid->padding_left; if (child_wid->resize_x > 0) allow_resize_x = false; // Widget array allows only one child resizing child_wid = rtl ? child_wid->prev : child_wid->next; @@ -989,12 +999,19 @@ int NWidgetVertical::ComputeMinimalSize() this->resize_x = 1; // smallest common child resize step this->resize_y = 0; // smallest non-zero child widget resize step. + if (this->head != NULL) this->head->padding_top += this->pip_pre; for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) { int idx = child_wid->ComputeMinimalSize(); biggest_index = max(biggest_index, idx); - this->min_y += child_wid->min_y; - this->min_x = max(this->min_x, child_wid->min_x); + if (child_wid->next != NULL) { + child_wid->padding_bottom += this->pip_inter; + } else { + child_wid->padding_bottom += this->pip_post; + } + + this->min_y += child_wid->min_y + child_wid->padding_top + child_wid->padding_bottom; + this->min_x = max(this->min_x, child_wid->min_x + child_wid->padding_left + child_wid->padding_right); this->fill_y |= child_wid->fill_y; this->fill_x &= child_wid->fill_x; @@ -1003,6 +1020,8 @@ int NWidgetVertical::ComputeMinimalSize() } this->resize_x = LeastCommonMultiple(this->resize_x, child_wid->resize_x); } + /* We need to zero the PIP settings so we can re-initialize the tree. */ + this->pip_pre = this->pip_inter = this->pip_post = 0; return biggest_index; } @@ -1029,15 +1048,16 @@ void NWidgetVertical::AssignMinimalPosition(uint x, uint y, uint given_width, ui uint position = 0; // Place to put next child relative to origin of the container. allow_resize_y = (this->resize_y > 0); for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) { + assert(given_width >= child_wid->min_x + child_wid->padding_left + child_wid->padding_right); /* Decide about horizontal filling of the child. */ uint child_width; // Width of the child widget. uint child_pos_x; // Horizontal position of child relative to the left of the container. if (child_wid->fill_x) { - child_width = given_width; - child_pos_x = 0; + child_width = given_width - child_wid->padding_left - child_wid->padding_right; + child_pos_x = (rtl ? child_wid->padding_right : child_wid->padding_left); } else { child_width = child_wid->min_x; - child_pos_x = (given_width - child_width) / 2; + child_pos_x = (given_width - child_wid->padding_left - child_wid->padding_right - child_width) / 2 + (rtl ? child_wid->padding_right : child_wid->padding_left); } /* Decide about vertical filling of the child. */ @@ -1052,8 +1072,8 @@ void NWidgetVertical::AssignMinimalPosition(uint x, uint y, uint given_width, ui child_height += increment; } - child_wid->AssignMinimalPosition(x + child_pos_x, y + position, child_width, child_height, (this->resize_x > 0), allow_resize_y, rtl); - position += child_height; + child_wid->AssignMinimalPosition(x + child_pos_x, y + position + child_wid->padding_top, child_width, child_height, (this->resize_x > 0), allow_resize_y, rtl); + position += child_height + child_wid->padding_top + child_wid->padding_bottom; if (child_wid->resize_y > 0) allow_resize_y = false; // Widget array allows only one child resizing } } @@ -1153,7 +1173,12 @@ void NWidgetBackground::AssignMinimalPosition(uint x, uint y, uint given_width, if (!allow_resize_x) this->resize_x = 0; if (!allow_resize_y) this->resize_y = 0; - if (this->child != NULL) this->child->AssignMinimalPosition(x, y, given_width, given_height, (this->resize_x > 0), (this->resize_y > 0), rtl); + if (this->child != NULL) { + uint x_offset = (rtl ? this->child->padding_right : this->child->padding_left); + uint width = given_width - this->child->padding_right - this->child->padding_left; + uint height = given_height - this->child->padding_top - this->child->padding_bottom; + this->child->AssignMinimalPosition(x + x_offset, y + this->child->padding_top, width, height, (this->resize_x > 0), (this->resize_y > 0), rtl); + } } void NWidgetBackground::StoreWidgets(Widget *widgets, int length, bool left_moving, bool top_moving, bool rtl) @@ -1438,6 +1463,27 @@ static int MakeNWidget(const NWidgetPart *parts, int count, NWidgetBase **dest) break; } + case WPT_PADDING: { + NWidgetBase *nwb = *dest; + if (nwb != NULL) { + nwb->padding_top = parts->u.padding.top; + nwb->padding_right = parts->u.padding.right; + nwb->padding_bottom = parts->u.padding.bottom; + nwb->padding_left = parts->u.padding.left; + } + break; + } + + case WPT_PIPSPACE: { + NWidgetContainer *nwc = dynamic_cast<NWidgetContainer *>(*dest); + if (nwc != NULL) { + nwc->pip_pre = parts->u.pip.pre; + nwc->pip_inter = parts->u.pip.inter; + nwc->pip_post = parts->u.pip.post; + } + break; + } + case WPT_ENDCONTAINER: return num_used; diff --git a/src/widget_type.h b/src/widget_type.h index 903d908f2..87be3cea6 100644 --- a/src/widget_type.h +++ b/src/widget_type.h @@ -109,6 +109,8 @@ enum WidgetType { WPT_FILL, ///< Widget part for specifying fill. WPT_DATATIP, ///< Widget part for specifying data and tooltip. WPT_DATATIP_PTR, ///< Widget part for specifying data and tooltip via a pointer. + WPT_PADDING, ///< Widget part for specifying a padding. + WPT_PIPSPACE, ///< Widget part for specifying pre/inter/post space for containers. WPT_ENDCONTAINER, ///< Widget part to denote end of a container. /* Pushable window widget types. */ @@ -151,19 +153,24 @@ public: virtual void StoreWidgets(Widget *widgets, int length, bool left_moving, bool top_moving, bool rtl) = 0; - WidgetType type; ///< Type of the widget / nested widget. - uint min_x; ///< Minimal horizontal size. - uint min_y; ///< Minimal vertical size. - bool fill_x; ///< Allow horizontal filling from initial size. - bool fill_y; ///< Allow vertical filling from initial size. - uint resize_x; ///< Horizontal resize step (\c 0 means not resizable). - uint resize_y; ///< Vertical resize step (\c 0 means not resizable). + WidgetType type; ///< Type of the widget / nested widget. + uint min_x; ///< Minimal horizontal size. + uint min_y; ///< Minimal vertical size. + bool fill_x; ///< Allow horizontal filling from initial size. + bool fill_y; ///< Allow vertical filling from initial size. + uint resize_x; ///< Horizontal resize step (\c 0 means not resizable). + uint resize_y; ///< Vertical resize step (\c 0 means not resizable). - uint pos_x; ///< Horizontal position of top-left corner of the widget in the window. - uint pos_y; ///< Vertical position of top-left corner of the widget in the window. + uint pos_x; ///< Horizontal position of top-left corner of the widget in the window. + uint pos_y; ///< Vertical position of top-left corner of the widget in the window. - NWidgetBase *next; ///< Pointer to next widget in container. Managed by parent container widget. - NWidgetBase *prev; ///< Pointer to previous widget in container. Managed by parent container widget. + NWidgetBase *next; ///< Pointer to next widget in container. Managed by parent container widget. + NWidgetBase *prev; ///< Pointer to previous widget in container. Managed by parent container widget. + + uint8 padding_top; ///< Paddings added to the top of the widget. Managed by parent container widget. + uint8 padding_right; ///< Paddings added to the right of the widget. Managed by parent container widget. + uint8 padding_bottom; ///< Paddings added to the bottom of the widget. Managed by parent container widget. + uint8 padding_left; ///< Paddings added to the left of the widget. Managed by parent container widget. }; /** Base class for a resizable nested widget. */ @@ -202,6 +209,10 @@ public: ~NWidgetContainer(); void Add(NWidgetBase *wid); + + uint8 pip_pre; ///< Amount of space before first widget. + uint8 pip_inter; ///< Amount of space between widgets. + uint8 pip_post; ///< Amount of space after last widget. protected: NWidgetBase *head; ///< Pointer to first widget in container. NWidgetBase *tail; ///< Pointer to last widget in container. @@ -288,6 +299,16 @@ struct NWidgetPartWidget { int16 index; ///< Widget index in the widget array. }; +/** Widget part for storing padding. */ +struct NWidgetPartPaddings { + uint8 top, right, bottom, left; ///< Paddings for all directions. +}; + +/** Widget part for storing pre/inter/post spaces. */ +struct NWidgetPartPIP { + uint8 pre, inter, post; ///< Amount of space before/between/after child widgets. +}; + /** Partial widget specification to allow NWidgets to be written nested. */ struct NWidgetPart { WidgetType type; ///< Type of the part. @see NWidgetPartType. @@ -297,6 +318,8 @@ struct NWidgetPart { NWidgetPartDataTip data_tip; ///< Part with a data/tooltip. NWidgetPartDataTip *datatip_ptr; ///< Part with a pointer to data/tooltip. NWidgetPartWidget widget; ///< Part with a start of a widget. + NWidgetPartPaddings padding; ///< Part with paddings. + NWidgetPartPIP pip; ///< Part with pre/inter/post spaces. } u; }; @@ -419,6 +442,53 @@ static inline NWidgetPart SetDataTip(NWidgetPartDataTip *ptr) } /** + * Widget part function for setting a padding. + * @param top The padding above the widget. + * @param right The padding right of the widget. + * @param bottom The padding below the widget. + * @param left The padding left of the widget. + */ +static inline NWidgetPart SetPadding(uint8 top, uint8 right, uint8 bottom, uint8 left) +{ + NWidgetPart part; + + part.type = WPT_PADDING; + part.u.padding.top = top; + part.u.padding.right = right; + part.u.padding.bottom = bottom; + part.u.padding.left = left; + + return part; +} + +/** + * Widget part function for setting a padding. + * @param padding The padding to use for all directions. + */ +static inline NWidgetPart SetPadding(uint8 padding) +{ + return SetPadding(padding, padding, padding, padding); +} + +/** + * Widget part function for setting a pre/inter/post spaces. + * @param pre The amount of space before the first widget. + * @param inter The amount of space between widgets. + * @param post The amount of space after the last widget. + */ +static inline NWidgetPart SetPIP(uint8 pre, uint8 inter, uint8 post) +{ + NWidgetPart part; + + part.type = WPT_PIPSPACE; + part.u.pip.pre = pre; + part.u.pip.inter = inter; + part.u.pip.post = post; + + return part; +} + +/** * Widget part function for starting a new 'real' widget. * @param tp Type of the new nested widget. * @param col Colour of the new widget. |