diff --git a/src/app/ui/skin/skin_theme.cpp b/src/app/ui/skin/skin_theme.cpp index 0b5658b25..ab452b604 100644 --- a/src/app/ui/skin/skin_theme.cpp +++ b/src/app/ui/skin/skin_theme.cpp @@ -623,6 +623,31 @@ void SkinTheme::loadXml(BackwardCompatibility* backward) style->setPadding(padding); } + // Size + { + const char* width = xmlStyle->Attribute("width"); + const char* height = xmlStyle->Attribute("height"); + const char* minwidth = xmlStyle->Attribute("minwidth"); + const char* minheight = xmlStyle->Attribute("minheight"); + const char* maxwidth = xmlStyle->Attribute("maxwidth"); + const char* maxheight = xmlStyle->Attribute("maxheight"); + gfx::Size minSize = style->minSize(); + gfx::Size maxSize = style->maxSize(); + if (width) { + if (!minwidth) minwidth = width; + if (!maxwidth) maxwidth = width; + } + if (height) { + if (!minheight) minheight = height; + if (!maxheight) maxheight = height; + } + if (minwidth) minSize.w = scale*std::strtol(minwidth, nullptr, 10); + if (minheight) minSize.h = scale*std::strtol(minheight, nullptr, 10); + if (maxwidth) maxSize.w = scale*std::strtol(maxwidth, nullptr, 10); + if (maxheight) maxSize.h = scale*std::strtol(maxheight, nullptr, 10); + style->setMinSize(minSize); + style->setMaxSize(maxSize); + } // Font { const char* fontId = xmlStyle->Attribute("font"); diff --git a/src/ui/style.cpp b/src/ui/style.cpp index e2b73b516..3e119da81 100644 --- a/src/ui/style.cpp +++ b/src/ui/style.cpp @@ -21,11 +21,25 @@ gfx::Border Style::UndefinedBorder() return gfx::Border(-1, -1, -1, -1); } +// static +gfx::Size Style::MinSize() +{ + return gfx::Size(0, 0); +} + +// static +gfx::Size Style::MaxSize() +{ + return gfx::Size(std::numeric_limits::max(), std::numeric_limits::max()); +} + Style::Style(const Style* base) : m_insertionPoint(0) , m_margin(base ? base->margin(): Style::UndefinedBorder()) , m_border(base ? base->border(): Style::UndefinedBorder()) , m_padding(base ? base->padding(): Style::UndefinedBorder()) + , m_minSize(base ? base->minSize(): Style::MinSize()) + , m_maxSize(base ? base->maxSize(): Style::MaxSize()) , m_font(nullptr) , m_mnemonics(base ? base->mnemonics() : true) { @@ -33,6 +47,20 @@ Style::Style(const Style* base) m_layers = base->layers(); } +void Style::setMinSize(const gfx::Size& sz) +{ + ASSERT(sz.w <= m_maxSize.w); + ASSERT(sz.h <= m_maxSize.h); + m_minSize = sz; +} + +void Style::setMaxSize(const gfx::Size& sz) +{ + ASSERT(sz.w >= m_minSize.w); + ASSERT(sz.h >= m_minSize.h); + m_maxSize = sz; +} + void Style::setFont(const os::Ref& font) { m_font = font; diff --git a/src/ui/style.h b/src/ui/style.h index 64deada9e..8f3bbc5e5 100644 --- a/src/ui/style.h +++ b/src/ui/style.h @@ -98,12 +98,17 @@ namespace ui { static gfx::Border UndefinedBorder(); + static gfx::Size MinSize(); + static gfx::Size MaxSize(); + Style(const Style* base); const std::string& id() const { return m_id; } const gfx::Border& margin() const { return m_margin; } const gfx::Border& border() const { return m_border; } const gfx::Border& padding() const { return m_padding; } + const gfx::Size& minSize() const { return m_minSize; } + const gfx::Size& maxSize() const { return m_maxSize; } os::Font* font() const { return m_font.get(); } const bool mnemonics() const { return m_mnemonics; } const Layers& layers() const { return m_layers; } @@ -113,6 +118,8 @@ namespace ui { void setMargin(const gfx::Border& value) { m_margin = value; } void setBorder(const gfx::Border& value) { m_border = value; } void setPadding(const gfx::Border& value) { m_padding = value; } + void setMinSize(const gfx::Size& sz); + void setMaxSize(const gfx::Size& sz); void setFont(const os::FontRef& font); void setMnemonics(const bool enabled) { m_mnemonics = enabled; } void addLayer(const Layer& layer); @@ -124,6 +131,10 @@ namespace ui { gfx::Border m_margin; gfx::Border m_border; gfx::Border m_padding; + // Min width and height for the widget. + gfx::Size m_minSize; + // Max width and height for the widget. + gfx::Size m_maxSize; os::FontRef m_font; bool m_mnemonics; }; diff --git a/src/ui/theme.cpp b/src/ui/theme.cpp index d9c9a3601..8388aefed 100644 --- a/src/ui/theme.cpp +++ b/src/ui/theme.cpp @@ -663,6 +663,34 @@ gfx::Color Theme::calcBgColor(const Widget* widget, return bgColor; } +gfx::Size Theme::calcMinSize(const Widget* widget, + const Style* style) +{ + ASSERT(widget); + ASSERT(style); + + gfx::Size sz = widget->minSize(); + + if (sz.w == 0) sz.w = style->minSize().w; + if (sz.h == 0) sz.h = style->minSize().h; + + return sz; +} + +gfx::Size Theme::calcMaxSize(const Widget* widget, + const Style* style) +{ + ASSERT(widget); + ASSERT(style); + + gfx::Size sz = widget->maxSize(); + + if (sz.w == std::numeric_limits::max()) sz.w = style->maxSize().w; + if (sz.h == std::numeric_limits::max()) sz.h = style->maxSize().h; + + return sz; +} + void Theme::calcWidgetMetrics(const Widget* widget, const Style* style, gfx::Size& sizeHint, @@ -718,6 +746,9 @@ void Theme::calcWidgetMetrics(const Widget* widget, sizeHint.h += std::max(textHint.h, iconHint.h); else sizeHint.h += textHint.h + iconHint.h; + + sizeHint.w = std::clamp(sizeHint.w, widget->minSize().w, widget->maxSize().w); + sizeHint.h = std::clamp(sizeHint.h, widget->minSize().h, widget->maxSize().h); } ////////////////////////////////////////////////////////////////////// diff --git a/src/ui/theme.h b/src/ui/theme.h index fe5349af2..d1260834f 100644 --- a/src/ui/theme.h +++ b/src/ui/theme.h @@ -119,6 +119,10 @@ namespace ui { gfx::Rect& textBounds, int& textAlign); virtual gfx::Color calcBgColor(const Widget* widget, const Style* style); + virtual gfx::Size calcMinSize(const Widget* widget, + const Style* style); + virtual gfx::Size calcMaxSize(const Widget* widget, + const Style* style); static void drawSlices(Graphics* g, os::Surface* sheet, diff --git a/src/ui/widget.cpp b/src/ui/widget.cpp index 3bf495e0c..e538b2807 100644 --- a/src/ui/widget.cpp +++ b/src/ui/widget.cpp @@ -203,6 +203,8 @@ void Widget::setStyle(Style* style) m_style = style; m_border = m_theme->calcBorder(this, style); m_bgColor = m_theme->calcBgColor(this, style); + m_minSize = m_theme->calcMinSize(this, style); + m_maxSize = m_theme->calcMaxSize(this, style); if (style->font()) m_font = AddRef(style->font()); }