aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/base.h28
-rw-r--r--src/main.cpp7
-rw-r--r--src/ui/control.cpp18
-rw-r--r--src/ui/controls/linear_layout.h2
-rw-r--r--src/ui/layout_base.h17
5 files changed, 61 insertions, 11 deletions
diff --git a/src/base.h b/src/base.h
index c8866cf6..9b3b50a1 100644
--- a/src/base.h
+++ b/src/base.h
@@ -10,6 +10,7 @@
#include <memory>
#include <string_view>
#include <chrono>
+#include <optional>
namespace cru
{
@@ -63,4 +64,31 @@ namespace cru
if (!condition)
throw std::invalid_argument(error_message.data());
}
+
+ template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>>
+ float Coerce(const T n, const std::optional<T> min, const std::optional<T> max)
+ {
+ if (min.has_value() && n < min.value())
+ return min.value();
+ if (max.has_value() && n > max.value())
+ return max.value();
+ return n;
+ }
+
+ template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>>
+ float Coerce(const T n, const std::nullopt_t, const std::optional<T> max)
+ {
+ if (max.has_value() && n > max.value())
+ return max.value();
+ return n;
+ }
+
+ template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>>
+ float Coerce(const T n, const std::optional<T> min, const std::nullopt_t)
+ {
+ if (min.has_value() && n < min.value())
+ return min.value();
+ return n;
+ }
+
}
diff --git a/src/main.cpp b/src/main.cpp
index a15fa4da..5fd59ede 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -129,6 +129,13 @@ int APIENTRY wWinMain(
}
{
+ const auto text_box = TextBox::Create();
+ text_box->GetLayoutParams()->width.min = 50.0f;
+ text_box->GetLayoutParams()->width.max = 100.0f;
+ layout->AddChild(text_box);
+ }
+
+ {
const auto text_block = CreateWithLayout<TextBlock>(LayoutSideParams::Stretch(), LayoutSideParams::Stretch(), L"This is a very very very very very long sentence!!!");
text_block->SetSelectable(true);
layout->AddChild(text_block);
diff --git a/src/ui/control.cpp b/src/ui/control.cpp
index 79def066..9416d48a 100644
--- a/src/ui/control.cpp
+++ b/src/ui/control.cpp
@@ -689,11 +689,6 @@ namespace cru {
return value < 0 ? 0 : value;
}
- inline Size AtLeast0(const Size& size)
- {
- return Size(AtLeast0(size.width), AtLeast0(size.height));
- }
-
Size Control::OnMeasureCore(const Size& available_size)
{
const auto layout_params = GetLayoutParams();
@@ -715,11 +710,14 @@ namespace cru {
auto&& get_content_measure_length = [](const LayoutSideParams& layout_length, const float available_length, const float outer_length) -> float
{
+ float length;
if (layout_length.mode == MeasureMode::Exactly)
- return layout_length.length;
- if (available_length > outer_length)
- return available_length - outer_length;
- return 0.0;
+ length = layout_length.length;
+ else if (available_length > outer_length)
+ length = available_length - outer_length;
+ else
+ length = 0;
+ return Coerce(length, layout_length.min, layout_length.max);
};
// if padding, margin and border exceeded, then content size is 0.
@@ -735,7 +733,7 @@ namespace cru {
// only use measure length when stretch and actual length is smaller than measure length, that is "stretch"
if (layout_length.mode == MeasureMode::Stretch && actual_length < measure_length)
return measure_length;
- return actual_length;
+ return Coerce(actual_length, layout_length.min, std::nullopt);
};
const auto final_size = Size(
diff --git a/src/ui/controls/linear_layout.h b/src/ui/controls/linear_layout.h
index 1c2232bb..021f4b7d 100644
--- a/src/ui/controls/linear_layout.h
+++ b/src/ui/controls/linear_layout.h
@@ -4,6 +4,8 @@
namespace cru::ui::controls
{
+ // Min length of main side in layout params is of no meaning.
+ // All children will layout from start and redundant length is blank.
class LinearLayout : public Control
{
public:
diff --git a/src/ui/layout_base.h b/src/ui/layout_base.h
index 662210bd..4a4c09ea 100644
--- a/src/ui/layout_base.h
+++ b/src/ui/layout_base.h
@@ -101,12 +101,27 @@ namespace cru
constexpr bool Validate() const
{
- return length >= 0.0;
+ if (length < 0.0)
+ return false;
+ if (min.has_value() && min.value() < 0.0)
+ return false;
+ if (max.has_value() && max.value() < 0.0)
+ return false;
+ if (min.has_value() && max.has_value() && min.value() > max.value())
+ return false;
+ return true;
}
+ // only used in exactly mode, specify the exactly side length of content.
float length = 0.0;
MeasureMode mode = MeasureMode::Content;
Alignment alignment = Alignment::Center;
+
+ // min and max specify the min/max side length of content.
+ // they are used as hint and respect the actual size that content needs.
+ // when mode is exactly, length is coerced into the min-max range.
+ std::optional<float> min = std::nullopt;
+ std::optional<float> max = std::nullopt;
};
struct BasicLayoutParams final