aboutsummaryrefslogtreecommitdiff
path: root/src/ui/control.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/control.cpp')
-rw-r--r--src/ui/control.cpp402
1 files changed, 151 insertions, 251 deletions
diff --git a/src/ui/control.cpp b/src/ui/control.cpp
index 617c50c7..ee2abad0 100644
--- a/src/ui/control.cpp
+++ b/src/ui/control.cpp
@@ -3,292 +3,192 @@
#include <algorithm>
#include <cassert>
-#include "window.hpp"
#include "application.hpp"
-#include "graph/graph.hpp"
-#include "exception.hpp"
#include "cru_debug.hpp"
#include "d2d_util.hpp"
+#include "exception.hpp"
+#include "graph/graph.hpp"
#include "math_util.hpp"
+#include "window.hpp"
#ifdef CRU_DEBUG_LAYOUT
#include "ui_manager.hpp"
#endif
-namespace cru::ui
-{
-
- void Control::SetParent(Control* parent)
- {
- const auto old_parent = GetParent();
- parent_ = parent;
- const auto new_parent = GetParent();
- if (old_parent != new_parent)
- OnParentChanged(old_parent, new_parent);
- }
-
- void Control::SetDescendantWindow(Window* window)
- {
- if (window == nullptr && window_ == nullptr)
- return;
-
- //You can only attach or detach window.
- assert((window != nullptr && window_ == nullptr) || (window == nullptr && window_ != nullptr));
-
- if (window == nullptr)
- {
- const auto old = window_;
- TraverseDescendants([old](Control* control)
- {
- control->window_ = nullptr;
- control->OnDetachToWindow(old);
- });
- }
- else
- TraverseDescendants([window](Control* control)
- {
- control->window_ = window;
- control->OnAttachToWindow(window);
- });
- }
-
- void Control::TraverseDescendants(const std::function<void(Control*)>& predicate)
- {
- TraverseDescendantsInternal(this, predicate);
- }
-
- void Control::TraverseDescendantsInternal(Control * control, const std::function<void(Control*)>& predicate)
- {
- predicate(control);
- for (auto c: control->GetInternalChildren())
- TraverseDescendantsInternal(c, predicate);
- }
-
-
- Point Control::ControlToWindow(const Point& point) const
- {
- const auto position = GetPositionInWindow();
- return Point(point.x + position.x, point.y + position.y);
- }
-
- Point Control::WindowToControl(const Point & point) const
- {
- const auto position = GetPositionInWindow();
- return Point(point.x - position.x, point.y - position.y);
- }
-
- bool Control::RequestFocus()
- {
- auto window = GetWindow();
- if (window == nullptr)
- return false;
-
- return window->RequestFocusFor(this);
- }
-
- bool Control::HasFocus()
- {
- auto window = GetWindow();
- if (window == nullptr)
- return false;
-
- return window->GetFocusControl() == this;
- }
-
- void Control::SetCursor(const Cursor::Ptr& cursor)
- {
- if (cursor != cursor_)
- {
- cursor_ = cursor;
- const auto window = GetWindow();
- if (window && window->GetMouseHoverControl() == this)
- window->UpdateCursor();
- }
- }
-
- void Control::OnParentChanged(Control* old_parent, Control* new_parent)
- {
-
- }
-
- void Control::OnAttachToWindow(Window* window)
- {
-
- }
-
- void Control::OnDetachToWindow(Window * window)
- {
-
- }
-
- void Control::OnMouseClickBegin(MouseButton button)
- {
-
- }
-
- void Control::OnMouseClickEnd(MouseButton button)
- {
-
- }
-
-
- const std::vector<Control*> NoChildControl::empty_control_vector{};
+namespace cru::ui {
+void Control::_SetParent(Control* parent) {
+ const auto old_parent = GetParent();
+ parent_ = parent;
+ const auto new_parent = GetParent();
+ if (old_parent != new_parent) OnParentChanged(old_parent, new_parent);
+}
- ContentControl::ContentControl() : child_vector_{nullptr}, child_(child_vector_[0])
- {
+void Control::_SetDescendantWindow(Window* window) {
+ if (window == nullptr && window_ == nullptr) return;
+
+ // You can only attach or detach window.
+ assert((window != nullptr && window_ == nullptr) ||
+ (window == nullptr && window_ != nullptr));
+
+ if (window == nullptr) {
+ const auto old = window_;
+ TraverseDescendants([old](Control* control) {
+ control->window_ = nullptr;
+ control->OnDetachToWindow(old);
+ });
+ } else
+ TraverseDescendants([window](Control* control) {
+ control->window_ = window;
+ control->OnAttachToWindow(window);
+ });
+}
- }
+void Control::TraverseDescendants(
+ const std::function<void(Control*)>& predicate) {
+ TraverseDescendantsInternal(this, predicate);
+}
- ContentControl::~ContentControl()
- {
- delete child_;
- }
+void Control::TraverseDescendantsInternal(
+ Control* control, const std::function<void(Control*)>& predicate) {
+ predicate(control);
+ for (auto c : control->GetChildren())
+ TraverseDescendantsInternal(c, predicate);
+}
+bool Control::RequestFocus() {
+ auto window = GetWindow();
+ if (window == nullptr) return false;
- void ContentControl::SetChild(Control* child)
- {
- if (child == child_)
- return;
+ return window->RequestFocusFor(this);
+}
- const auto window = GetWindow();
- const auto old_child = child_;
- child_ = child;
- if (old_child)
- {
- old_child->SetParent(nullptr);
- old_child->SetDescendantWindow(nullptr);
- }
- if (child)
- {
- child->SetParent(this);
- child->SetDescendantWindow(window);
- }
- OnChildChanged(old_child, child);
- }
+bool Control::HasFocus() {
+ auto window = GetWindow();
+ if (window == nullptr) return false;
- void ContentControl::OnChildChanged(Control* old_child, Control* new_child)
- {
+ return window->GetFocusControl() == this;
+}
- }
+void Control::SetCursor(const Cursor::Ptr& cursor) {
+ if (cursor != cursor_) {
+ cursor_ = cursor;
+ const auto window = GetWindow();
+ if (window && window->GetMouseHoverControl() == this)
+ window->UpdateCursor();
+ }
+}
- void ControlAddChildCheck(Control* control)
- {
- if (control->GetParent() != nullptr)
- throw std::invalid_argument("The control already has a parent.");
+void Control::OnParentChanged(Control* old_parent, Control* new_parent) {}
- if (dynamic_cast<Window*>(control))
- throw std::invalid_argument("Can't add a window as child.");
- }
+void Control::OnAttachToWindow(Window* window) {}
- MultiChildControl::~MultiChildControl()
- {
- for (const auto child : children_)
- delete child;
- }
+void Control::OnDetachToWindow(Window* window) {}
- void MultiChildControl::AddChild(Control* control)
- {
- ControlAddChildCheck(control);
+void Control::OnMouseClickBegin(MouseButton button) {}
- children_.push_back(control);
+void Control::OnMouseClickEnd(MouseButton button) {}
- control->SetParent(this);
- control->SetDescendantWindow(GetWindow());
+const std::vector<Control*> NoChildControl::empty_control_vector{};
- OnAddChild(control);
- }
+ContentControl::ContentControl()
+ : child_vector_{nullptr}, child_(child_vector_[0]) {}
- void MultiChildControl::AddChild(Control* control, const int position)
- {
- ControlAddChildCheck(control);
+ContentControl::~ContentControl() { delete child_; }
- if (position < 0 || static_cast<decltype(children_.size())>(position) > this->children_.size())
- throw std::invalid_argument("The position is out of range.");
+void ContentControl::SetChild(Control* child) {
+ if (child == child_) return;
- children_.insert(this->children_.cbegin() + position, control);
+ const auto window = GetWindow();
+ const auto old_child = child_;
+ child_ = child;
+ if (old_child) {
+ old_child->_SetParent(nullptr);
+ old_child->_SetDescendantWindow(nullptr);
+ }
+ if (child) {
+ child->_SetParent(this);
+ child->_SetDescendantWindow(window);
+ }
+ OnChildChanged(old_child, child);
+}
- control->SetParent(this);
- control->SetDescendantWindow(GetWindow());
+void ContentControl::OnChildChanged(Control* old_child, Control* new_child) {}
- OnAddChild(control);
- }
+void ControlAddChildCheck(Control* control) {
+ if (control->GetParent() != nullptr)
+ throw std::invalid_argument("The control already has a parent.");
- void MultiChildControl::RemoveChild(Control* child)
- {
- const auto i = std::find(this->children_.cbegin(), this->children_.cend(), child);
- if (i == this->children_.cend())
- throw std::invalid_argument("The argument child is not a child of this control.");
+ if (dynamic_cast<Window*>(control))
+ throw std::invalid_argument("Can't add a window as child.");
+}
+
+MultiChildControl::~MultiChildControl() {
+ for (const auto child : children_) delete child;
+}
+
+void MultiChildControl::AddChild(Control* control, const int position) {
+ ControlAddChildCheck(control);
- children_.erase(i);
+ if (position < 0 || static_cast<decltype(children_.size())>(position) >
+ this->children_.size())
+ throw std::invalid_argument("The position is out of range.");
- child->SetParent(nullptr);
- child->SetDescendantWindow(nullptr);
+ children_.insert(this->children_.cbegin() + position, control);
+
+ control->_SetParent(this);
+ control->_SetDescendantWindow(GetWindow());
+
+ OnAddChild(control);
+}
- OnRemoveChild(child);
- }
+void MultiChildControl::RemoveChild(const int position) {
+ if (position < 0 || static_cast<decltype(this->children_.size())>(position) >=
+ this->children_.size())
+ throw std::invalid_argument("The position is out of range.");
- void MultiChildControl::RemoveChild(const int position)
- {
- if (position < 0 || static_cast<decltype(this->children_.size())>(position) >= this->children_.size())
- throw std::invalid_argument("The position is out of range.");
-
- const auto i = children_.cbegin() + position;
- const auto child = *i;
-
- children_.erase(i);
-
- child->SetParent(nullptr);
- child->SetDescendantWindow(nullptr);
-
- OnRemoveChild(child);
- }
-
- void MultiChildControl::OnAddChild(Control* child)
- {
-
- }
-
- void MultiChildControl::OnRemoveChild(Control* child)
- {
-
- }
-
- std::list<Control*> GetAncestorList(Control* control)
- {
- std::list<Control*> l;
- while (control != nullptr)
- {
- l.push_front(control);
- control = control->GetParent();
- }
- return l;
- }
+ const auto i = children_.cbegin() + position;
+ const auto child = *i;
- Control* FindLowestCommonAncestor(Control * left, Control * right)
- {
- if (left == nullptr || right == nullptr)
- return nullptr;
+ children_.erase(i);
- auto&& left_list = GetAncestorList(left);
- auto&& right_list = GetAncestorList(right);
-
- // the root is different
- if (left_list.front() != right_list.front())
- return nullptr;
+ child->_SetParent(nullptr);
+ child->_SetDescendantWindow(nullptr);
+
+ OnRemoveChild(child);
+}
+
+void MultiChildControl::OnAddChild(Control* child) {}
+
+void MultiChildControl::OnRemoveChild(Control* child) {}
+
+std::list<Control*> GetAncestorList(Control* control) {
+ std::list<Control*> l;
+ while (control != nullptr) {
+ l.push_front(control);
+ control = control->GetParent();
+ }
+ return l;
+}
- // find the last same control or the last control (one is ancestor of the other)
- auto left_i = left_list.cbegin();
- auto right_i = right_list.cbegin();
- while (true)
- {
- if (left_i == left_list.cend())
- return *(--left_i);
- if (right_i == right_list.cend())
- return *(--right_i);
- if (*left_i != *right_i)
- return *(--left_i);
- ++left_i;
- ++right_i;
- }
- }
+Control* FindLowestCommonAncestor(Control* left, Control* right) {
+ if (left == nullptr || right == nullptr) return nullptr;
+
+ auto&& left_list = GetAncestorList(left);
+ auto&& right_list = GetAncestorList(right);
+
+ // the root is different
+ if (left_list.front() != right_list.front()) return nullptr;
+
+ // find the last same control or the last control (one is ancestor of the
+ // other)
+ auto left_i = left_list.cbegin();
+ auto right_i = right_list.cbegin();
+ while (true) {
+ if (left_i == left_list.cend()) return *(--left_i);
+ if (right_i == right_list.cend()) return *(--right_i);
+ if (*left_i != *right_i) return *(--left_i);
+ ++left_i;
+ ++right_i;
+ }
}
+} // namespace cru::ui