mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-03-08 23:19:40 +00:00
Add: Widget layer container widget type, NWID_LAYER.
This widget allows child widgets to be overlaid on top of each other. Very similar to NWID_SELECTION except all layers are always visible.
This commit is contained in:
parent
1885bd7166
commit
60f1618cc7
@ -1342,6 +1342,70 @@ bool NWidgetStacked::SetDisplayedPlane(int plane)
|
||||
return true;
|
||||
}
|
||||
|
||||
class NWidgetLayer : public NWidgetContainer {
|
||||
public:
|
||||
NWidgetLayer(WidgetID index);
|
||||
|
||||
void SetupSmallestSize(Window *w) override;
|
||||
void AssignSizePosition(SizingType sizing, int x, int y, uint given_width, uint given_height, bool rtl) override;
|
||||
|
||||
void Draw(const Window *w) override;
|
||||
|
||||
const WidgetID index; ///< If non-negative, index in the #Window::widget_lookup.
|
||||
};
|
||||
|
||||
NWidgetLayer::NWidgetLayer(WidgetID index) : NWidgetContainer(NWID_LAYER), index(index) {}
|
||||
|
||||
void NWidgetLayer::SetupSmallestSize(Window *w)
|
||||
{
|
||||
/* First sweep, recurse down and compute minimal size and filling. */
|
||||
this->smallest_x = 0;
|
||||
this->smallest_y = 0;
|
||||
this->fill_x = this->IsEmpty() ? 0 : 1;
|
||||
this->fill_y = this->IsEmpty() ? 0 : 1;
|
||||
this->resize_x = this->IsEmpty() ? 0 : 1;
|
||||
this->resize_y = this->IsEmpty() ? 0 : 1;
|
||||
for (const auto &child_wid : this->children) {
|
||||
child_wid->SetupSmallestSize(w);
|
||||
|
||||
this->smallest_x = std::max(this->smallest_x, child_wid->smallest_x + child_wid->padding.Horizontal());
|
||||
this->smallest_y = std::max(this->smallest_y, child_wid->smallest_y + child_wid->padding.Vertical());
|
||||
this->fill_x = std::lcm(this->fill_x, child_wid->fill_x);
|
||||
this->fill_y = std::lcm(this->fill_y, child_wid->fill_y);
|
||||
this->resize_x = std::lcm(this->resize_x, child_wid->resize_x);
|
||||
this->resize_y = std::lcm(this->resize_y, child_wid->resize_y);
|
||||
this->ApplyAspectRatio();
|
||||
}
|
||||
}
|
||||
|
||||
void NWidgetLayer::AssignSizePosition(SizingType sizing, int x, int y, uint given_width, uint given_height, bool rtl)
|
||||
{
|
||||
assert(given_width >= this->smallest_x && given_height >= this->smallest_y);
|
||||
this->StoreSizePosition(sizing, x, y, given_width, given_height);
|
||||
|
||||
for (const auto &child_wid : this->children) {
|
||||
uint hor_step = (sizing == ST_SMALLEST) ? 1 : child_wid->GetHorizontalStepSize(sizing);
|
||||
uint child_width = ComputeMaxSize(child_wid->smallest_x, given_width - child_wid->padding.Horizontal(), hor_step);
|
||||
uint child_pos_x = (rtl ? child_wid->padding.right : child_wid->padding.left);
|
||||
|
||||
uint vert_step = (sizing == ST_SMALLEST) ? 1 : child_wid->GetVerticalStepSize(sizing);
|
||||
uint child_height = ComputeMaxSize(child_wid->smallest_y, given_height - child_wid->padding.Vertical(), vert_step);
|
||||
uint child_pos_y = child_wid->padding.top;
|
||||
|
||||
child_wid->AssignSizePosition(sizing, x + child_pos_x, y + child_pos_y, child_width, child_height, rtl);
|
||||
}
|
||||
}
|
||||
|
||||
void NWidgetLayer::Draw(const Window *w)
|
||||
{
|
||||
/* Draw in reverse order, as layers are arranged top-down. */
|
||||
for (auto it = std::rbegin(this->children); it != std::rend(this->children); ++it) {
|
||||
(*it)->Draw(w);
|
||||
}
|
||||
|
||||
DrawOutline(w, this);
|
||||
}
|
||||
|
||||
NWidgetPIPContainer::NWidgetPIPContainer(WidgetType tp, NWidContainerFlags flags) : NWidgetContainer(tp)
|
||||
{
|
||||
this->flags = flags;
|
||||
@ -3121,6 +3185,7 @@ static std::unique_ptr<NWidgetBase> MakeNWidget(const NWidgetPart &nwid)
|
||||
case NWID_SELECTION: return std::make_unique<NWidgetStacked>(nwid.u.widget.index);
|
||||
case NWID_MATRIX: return std::make_unique<NWidgetMatrix>(nwid.u.widget.colour, nwid.u.widget.index);
|
||||
case NWID_VIEWPORT: return std::make_unique<NWidgetViewport>(nwid.u.widget.index);
|
||||
case NWID_LAYER: return std::make_unique<NWidgetLayer>(nwid.u.widget.index);
|
||||
|
||||
case NWID_HSCROLLBAR: [[fallthrough]];
|
||||
case NWID_VSCROLLBAR: return std::make_unique<NWidgetScrollbar>(nwid.type, nwid.u.widget.colour, nwid.u.widget.index);
|
||||
@ -3176,7 +3241,7 @@ static std::span<const NWidgetPart>::iterator MakeNWidget(std::span<const NWidge
|
||||
bool IsContainerWidgetType(WidgetType tp)
|
||||
{
|
||||
return tp == NWID_HORIZONTAL || tp == NWID_HORIZONTAL_LTR || tp == NWID_VERTICAL || tp == NWID_MATRIX
|
||||
|| tp == WWT_PANEL || tp == WWT_FRAME || tp == WWT_INSET || tp == NWID_SELECTION;
|
||||
|| tp == WWT_PANEL || tp == WWT_FRAME || tp == WWT_INSET || tp == NWID_SELECTION || tp == NWID_LAYER;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -78,6 +78,7 @@ enum WidgetType {
|
||||
NWID_MATRIX, ///< Matrix container.
|
||||
NWID_SPACER, ///< Invisible widget that takes some space.
|
||||
NWID_SELECTION, ///< Stacked widgets, only one visible at a time (eg in a panel with tabs).
|
||||
NWID_LAYER, ///< Layered widgets, all visible together.
|
||||
NWID_VIEWPORT, ///< Nested widget containing a viewport.
|
||||
NWID_BUTTON_DROPDOWN, ///< Button with a drop-down.
|
||||
NWID_HSCROLLBAR, ///< Horizontal scrollbar
|
||||
|
Loading…
Reference in New Issue
Block a user