diff options
Diffstat (limited to 'src/ui/controls/scroll_control.cpp')
-rw-r--r-- | src/ui/controls/scroll_control.cpp | 384 |
1 files changed, 0 insertions, 384 deletions
diff --git a/src/ui/controls/scroll_control.cpp b/src/ui/controls/scroll_control.cpp deleted file mode 100644 index a202e355..00000000 --- a/src/ui/controls/scroll_control.cpp +++ /dev/null @@ -1,384 +0,0 @@ -#include "scroll_control.hpp" - -#include <limits> - -#include "cru_debug.hpp" -#include "ui/d2d_util.hpp" -#include "exception.hpp" -#include "math_util.hpp" -#include "ui/ui_manager.hpp" -#include "ui/window.hpp" - -namespace cru::ui::controls -{ - constexpr auto scroll_bar_width = 15.0f; - - ScrollControl::ScrollControl(const bool container) - { - SetClipContent(true); - - draw_foreground_event.AddHandler([this](events::DrawEventArgs& args) - { - const auto device_context = args.GetDeviceContext(); - const auto predefined = UiManager::GetInstance()->GetPredefineResources(); - - if (is_horizontal_scroll_bar_visible_) - { - device_context->FillRectangle( - Convert(horizontal_bar_info_.border), - predefined->scroll_bar_background_brush.Get() - ); - - device_context->FillRectangle( - Convert(horizontal_bar_info_.bar), - predefined->scroll_bar_brush.Get() - ); - - device_context->DrawLine( - Convert(horizontal_bar_info_.border.GetLeftTop()), - Convert(horizontal_bar_info_.border.GetRightTop()), - predefined->scroll_bar_border_brush.Get() - ); - } - - if (is_vertical_scroll_bar_visible_) - { - device_context->FillRectangle( - Convert(vertical_bar_info_.border), - predefined->scroll_bar_background_brush.Get() - ); - - device_context->FillRectangle( - Convert(vertical_bar_info_.bar), - predefined->scroll_bar_brush.Get() - ); - - device_context->DrawLine( - Convert(vertical_bar_info_.border.GetLeftTop()), - Convert(vertical_bar_info_.border.GetLeftBottom()), - predefined->scroll_bar_border_brush.Get() - ); - } - }); - - mouse_down_event.tunnel.AddHandler([this](events::MouseButtonEventArgs& args) - { - if (args.GetMouseButton() == MouseButton::Left) - { - const auto point = args.GetPoint(this); - if (is_vertical_scroll_bar_visible_ && vertical_bar_info_.bar.IsPointInside(point)) - { - GetWindow()->CaptureMouseFor(this); - is_pressing_scroll_bar_ = Orientation::Vertical; - pressing_delta_ = point.y - vertical_bar_info_.bar.top; - args.SetHandled(); - return; - } - - if (is_horizontal_scroll_bar_visible_ && horizontal_bar_info_.bar.IsPointInside(point)) - { - GetWindow()->CaptureMouseFor(this); - pressing_delta_ = point.x - horizontal_bar_info_.bar.left; - is_pressing_scroll_bar_ = Orientation::Horizontal; - args.SetHandled(); - return; - } - } - }); - - mouse_move_event.tunnel.AddHandler([this](events::MouseEventArgs& args) - { - const auto mouse_point = args.GetPoint(this); - - if (is_pressing_scroll_bar_ == Orientation::Horizontal) - { - const auto new_head_position = mouse_point.x - pressing_delta_; - const auto new_offset = new_head_position / horizontal_bar_info_.border.width * view_width_; - SetScrollOffset(new_offset, std::nullopt); - args.SetHandled(); - return; - } - - if (is_pressing_scroll_bar_ == Orientation::Vertical) - { - const auto new_head_position = mouse_point.y - pressing_delta_; - const auto new_offset = new_head_position / vertical_bar_info_.border.height * view_height_; - SetScrollOffset(std::nullopt, new_offset); - args.SetHandled(); - return; - } - }); - - mouse_up_event.tunnel.AddHandler([this](events::MouseButtonEventArgs& args) - { - if (args.GetMouseButton() == MouseButton::Left && is_pressing_scroll_bar_.has_value()) - { - GetWindow()->ReleaseCurrentMouseCapture(); - is_pressing_scroll_bar_ = std::nullopt; - args.SetHandled(); - } - }); - - mouse_wheel_event.bubble.AddHandler([this](events::MouseWheelEventArgs& args) - { - constexpr const auto view_delta = 30.0f; - - if (args.GetDelta() == 0.0f) - return; - - const auto content_rect = GetRect(RectRange::Content); - if (IsVerticalScrollEnabled() && GetScrollOffsetY() != (args.GetDelta() > 0.0f ? 0.0f : AtLeast0(GetViewHeight() - content_rect.height))) - { - SetScrollOffset(std::nullopt, GetScrollOffsetY() - args.GetDelta() / WHEEL_DELTA * view_delta); - args.SetHandled(); - return; - } - - if (IsHorizontalScrollEnabled() && GetScrollOffsetX() != (args.GetDelta() > 0.0f ? 0.0f : AtLeast0(GetViewWidth() - content_rect.width))) - { - SetScrollOffset(GetScrollOffsetX() - args.GetDelta() / WHEEL_DELTA * view_delta, std::nullopt); - args.SetHandled(); - return; - } - }); - } - - ScrollControl::~ScrollControl() - { - - } - - StringView ScrollControl::GetControlType() const - { - return control_type; - } - - void ScrollControl::SetHorizontalScrollEnabled(const bool enable) - { - horizontal_scroll_enabled_ = enable; - InvalidateLayout(); - InvalidateDraw(); - } - - void ScrollControl::SetVerticalScrollEnabled(const bool enable) - { - vertical_scroll_enabled_ = enable; - InvalidateLayout(); - InvalidateDraw(); - } - - void ScrollControl::SetHorizontalScrollBarVisibility(const ScrollBarVisibility visibility) - { - if (visibility != horizontal_scroll_bar_visibility_) - { - horizontal_scroll_bar_visibility_ = visibility; - switch (visibility) - { - case ScrollBarVisibility::Always: - is_horizontal_scroll_bar_visible_ = true; - break; - case ScrollBarVisibility::None: - is_horizontal_scroll_bar_visible_ = false; - break; - case ScrollBarVisibility::Auto: - UpdateScrollBarVisibility(); - } - InvalidateDraw(); - } - } - - void ScrollControl::SetVerticalScrollBarVisibility(const ScrollBarVisibility visibility) - { - if (visibility != vertical_scroll_bar_visibility_) - { - vertical_scroll_bar_visibility_ = visibility; - switch (visibility) - { - case ScrollBarVisibility::Always: - is_vertical_scroll_bar_visible_ = true; - break; - case ScrollBarVisibility::None: - is_vertical_scroll_bar_visible_ = false; - break; - case ScrollBarVisibility::Auto: - UpdateScrollBarVisibility(); - } - InvalidateDraw(); - } - - } - - void ScrollControl::SetScrollOffset(std::optional<float> x, std::optional<float> y) - { - CoerceAndSetOffsets(x.value_or(GetScrollOffsetX()), y.value_or(GetScrollOffsetY())); - } - - void ScrollControl::SetViewWidth(const float length) - { - view_width_ = length; - } - - void ScrollControl::SetViewHeight(const float length) - { - view_height_ = length; - } - - Size ScrollControl::OnMeasureContent(const Size& available_size, const AdditionalMeasureInfo& additional_info) - { - const auto layout_params = GetLayoutParams(); - - auto available_size_for_children = available_size; - if (IsHorizontalScrollEnabled()) - { - if (layout_params->width.mode == MeasureMode::Content) - debug::DebugMessage(L"ScrollControl: Width measure mode is Content and horizontal scroll is enabled. So Stretch is used instead."); - - available_size_for_children.width = std::numeric_limits<float>::max(); - } - - if (IsVerticalScrollEnabled()) - { - if (layout_params->height.mode == MeasureMode::Content) - debug::DebugMessage(L"ScrollControl: Height measure mode is Content and vertical scroll is enabled. So Stretch is used instead."); - - available_size_for_children.height = std::numeric_limits<float>::max(); - } - - const auto child = GetChild(); - - auto size = Size::Zero(); - if (child) - { - child->Measure(available_size_for_children, AdditionalMeasureInfo{false, false}); - size = child->GetDesiredSize(); - } - - - auto result = size; - if (IsHorizontalScrollEnabled()) - { - SetViewWidth(size.width); - result.width = available_size.width; - } - if (IsVerticalScrollEnabled()) - { - SetViewHeight(size.height); - result.height = available_size.height; - } - - return result; - } - - void ScrollControl::OnLayoutContent(const Rect& rect, const AdditionalLayoutInfo& additional_info) - { - auto layout_rect = rect; - - if (IsHorizontalScrollEnabled()) - layout_rect.width = GetViewWidth(); - if (IsVerticalScrollEnabled()) - layout_rect.height = GetViewHeight(); - - const auto child = GetChild(); - - if (child) - { - const auto layout_params = child->GetLayoutParams(); - const auto size = child->GetDesiredSize(); - - auto&& calculate_anchor = [](const float anchor, const Alignment alignment, const float layout_length, const float control_length) -> float - { - switch (alignment) - { - case Alignment::Center: - return anchor + (layout_length - control_length) / 2; - case Alignment::Start: - return anchor; - case Alignment::End: - return anchor + layout_length - control_length; - default: - UnreachableCode(); - } - }; - - child->Layout(Rect(Point( - IsHorizontalScrollEnabled() ? layout_rect.left + offset_x_ : calculate_anchor(layout_rect.left, layout_params->width.alignment, layout_rect.width, size.width), - IsVerticalScrollEnabled() ? layout_rect.top + offset_y_ : calculate_anchor(layout_rect.top, layout_params->height.alignment, layout_rect.height, size.height) - ), size), additional_info); - } - } - - void ScrollControl::OnRectChange(const Rect& old_rect, const Rect& new_rect) - { - UpdateScrollBarBorderInfo(); - CoerceAndSetOffsets(offset_x_, offset_y_, false); - UpdateScrollBarVisibility(); - } - - void ScrollControl::CoerceAndSetOffsets(const float offset_x, const float offset_y, const bool update_children) - { - const auto old_offset_x = offset_x_; - const auto old_offset_y = offset_y_; - - const auto content_rect = GetRect(RectRange::Content); - offset_x_ = Coerce(offset_x, 0.0f, AtLeast0(view_width_ - content_rect.width)); - offset_y_ = Coerce(offset_y, 0.0f, AtLeast0(view_height_ - content_rect.height)); - UpdateScrollBarBarInfo(); - - if (update_children) - { - if (const auto child = GetChild()) - { - const auto old_position = child->GetOffset(); - child->SetRect(Rect(Point( - old_position.x + old_offset_x - offset_x_, - old_position.y + old_offset_y - offset_y_ - ), child->GetSize())); - child->RefreshDescendantPositionCache(); - } - } - InvalidateDraw(); - } - - void ScrollControl::UpdateScrollBarVisibility() - { - const auto content_rect = GetRect(RectRange::Content); - if (GetHorizontalScrollBarVisibility() == ScrollBarVisibility::Auto) - is_horizontal_scroll_bar_visible_ = view_width_ > content_rect.width; - if (GetVerticalScrollBarVisibility() == ScrollBarVisibility::Auto) - is_vertical_scroll_bar_visible_ = view_height_ > content_rect.height; - } - - void ScrollControl::UpdateScrollBarBorderInfo() - { - const auto content_rect = GetRect(RectRange::Content); - horizontal_bar_info_.border = Rect(content_rect.left, content_rect.GetBottom() - scroll_bar_width, content_rect.width, scroll_bar_width); - vertical_bar_info_.border = Rect(content_rect.GetRight() - scroll_bar_width , content_rect.top, scroll_bar_width, content_rect.height); - } - - void ScrollControl::UpdateScrollBarBarInfo() - { - const auto content_rect = GetRect(RectRange::Content); - { - const auto& border = horizontal_bar_info_.border; - if (view_width_ <= content_rect.width) - horizontal_bar_info_.bar = border; - else - { - const auto bar_length = border.width * content_rect.width / view_width_; - const auto offset = border.width * offset_x_ / view_width_; - horizontal_bar_info_.bar = Rect(border.left + offset, border.top, bar_length, border.height); - } - } - { - const auto& border = vertical_bar_info_.border; - if (view_height_ <= content_rect.height) - vertical_bar_info_.bar = border; - else - { - const auto bar_length = border.height * content_rect.height / view_height_; - const auto offset = border.height * offset_y_ / view_height_; - vertical_bar_info_.bar = Rect(border.left, border.top + offset, border.width, bar_length); - } - } - } -} |