#include "pch.h" #include "node_panel_floating.h" #include "log.h" Node* NodePanelFloating::clone_instantiate() const { return new this_class; } void NodePanelFloating::clone_finalize(Node* dest) const { parent::clone_finalize(dest); auto n = static_cast(dest); n->init_controls(); } void NodePanelFloating::init() { parent::init(); init_template("tpl-panel-floating"); init_controls(); } void NodePanelFloating::init_controls() { SetPositioning(YGPositionTypeAbsolute); SetPosition({ 0, 0 }); m_mouse_ignore = false; m_flood_events = true; m_capture_children = true; m_container = find("container"); m_button_minimize = find("button-minimize"); m_button_minimize->on_click = [this](Node*) { m_container->ToggleVisibility(); if (m_container->m_display) { SetHeight(m_extended_size.y); } else { m_extended_size.y = GetHeight(); SetHeight(YGUndefined); } }; m_button_close = find("button-close"); m_button_close->on_click = [this](Node*) { m_container->remove_all_children(); destroy(); }; } void NodePanelFloating::handle_parent_resize(glm::vec2 old_size, glm::vec2 new_size) { if (m_dock.expired()) { auto newsize = glm::clamp(GetSize(), { 0, 0 }, m_parent->m_size); SetHeight(newsize.y); auto newpos = glm::clamp(GetPosition(), { 0, 0 }, m_parent->m_size - m_size); SetPosition(newpos); } } kEventResult NodePanelFloating::handle_event(Event* e) { parent::handle_event(e); kEventResult ret = kEventResult::Available; auto me = static_cast(e); switch (e->m_type) { case kEventType::MouseDownL: m_dragging = true; if (me->m_pos.y - m_pos.y > m_size.y - 20.f) { if (m_dock.expired() && me->m_pos.x - m_pos.x > m_size.x - 20.f) { m_action = kDragAction::Resize; } else { m_action = kDragAction::Reheight; } m_drag_start_pos = GetSize(); } else { m_drag_start_pos = GetPosition(); m_action = kDragAction::Move; m_outline = root()->add_child(); m_outline->SetPositioning(YGPositionTypeAbsolute); m_outline->SetPosition(m_pos); m_outline->SetSize(GetSize()); m_outline->m_color = { 0, 0, 0, 0.25 }; m_outline->m_thinkness = 1; m_drop_placeholder = std::make_shared(); m_drop_placeholder->SetSize(350, 10); m_drop_placeholder->m_color = { 0, 0, 0, 0.1 }; m_drop_placeholder->m_thinkness = 1; } m_drag_start_cur = me->m_pos; mouse_capture(); if (m_dock.expired()) m_parent->move_child_front(this); ret = kEventResult::Consumed; break; case kEventType::MouseMove: if (m_dragging) { if (m_action == kDragAction::Move) { auto newpos = glm::clamp(m_drag_start_pos + me->m_pos - m_drag_start_cur, { 0, 0 }, m_parent->m_size - m_size); if (m_dock.expired()) SetPosition(newpos); m_outline->SetPosition(m_parent->m_pos + m_drag_start_pos + me->m_pos - m_drag_start_cur); m_outline->SetSize(GetSize()); auto nodes = root()->find("ui-root")->get_children_at_point(me->m_pos); bool docked = false; for (auto const& c : nodes) { if (c->m_nodeID_s.find("drop") == 0) { m_outline->SetPosition(c->m_pos); m_outline->SetSize(c->m_size); m_drop_placeholder->remove_from_parent(); int i = 0; float y = 0; for (; i < c->m_children.size(); i++) { if (c->m_children[i] == m_drop_placeholder) continue; float y = c->m_children[i]->m_pos.y - c->m_pos.y + c->m_children[i]->m_size.y / 2.f; float my = me->m_pos.y - c->m_pos.y; if (my <= y) break; } i = std::min(i, (int)c->m_children.size()); if (/*m_parent != c.get() && */m_drop_placeholder->m_parent != c.get()) { c->add_child(m_drop_placeholder, i); } else { c->move_child(m_drop_placeholder.get(), i); } docked = true; break; } } if (!docked && m_drop_placeholder->m_parent) m_drop_placeholder->remove_from_parent(); } else if (m_action == kDragAction::Reheight) { auto newsize = glm::clamp(m_drag_start_pos + me->m_pos - m_drag_start_cur, { 0, 0 }, m_parent->m_size); SetHeight(newsize.y); } else if (m_action == kDragAction::Resize) { auto newsize = glm::clamp(m_drag_start_pos + me->m_pos - m_drag_start_cur, { 0, 0 }, m_parent->m_size); SetSize(newsize); } ret = kEventResult::Consumed; } break; case kEventType::MouseUpL: m_dragging = false; if (m_action == kDragAction::Move) { if (m_outline) m_outline->destroy(); int drop_pos = 0; if (m_drop_placeholder) { if (m_drop_placeholder->m_parent) drop_pos = std::max(0, m_drop_placeholder->m_parent->get_child_index(m_drop_placeholder.get())); m_drop_placeholder->destroy(); m_drop_placeholder->remove_from_parent(); } auto nodes = root()->find("ui-root")->get_children_at_point(me->m_pos); bool docked = false; auto ref = m_parent->m_children[m_parent->get_child_index(this)]; for (auto const& c : nodes) { if (c->m_nodeID_s.find("drop") == 0) { SetPositioning(YGPositionTypeRelative); SetPosition(0, 0); if (m_dock.lock() != c) { SetWidth(350); c->add_child(ref, drop_pos); m_dock = c; } else { c->move_child(ref.get(), std::min((int)c->m_children.size() - 1, drop_pos)); } docked = true; break; } } if (!docked && !m_dock.expired()) { auto cont = root()->find("floatings"); SetPositioning(YGPositionTypeAbsolute); auto newpos = glm::clamp(m_outline->m_pos - cont->m_pos, { 0, 0 }, cont->m_size - m_size); SetPosition(newpos); cont->add_child(ref); m_dock.reset(); } m_outline = nullptr; m_drop_placeholder = nullptr; } mouse_release(); ret = kEventResult::Consumed; break; default: break; } return ret; }