Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/windowing/StarWidget.cpp
diff options
context:
space:
mode:
authorKae <80987908+Novaenia@users.noreply.github.com>2023-06-20 14:33:09 +1000
committerKae <80987908+Novaenia@users.noreply.github.com>2023-06-20 14:33:09 +1000
commit6352e8e3196f78388b6c771073f9e03eaa612673 (patch)
treee23772f79a7fbc41bc9108951e9e136857484bf4 /source/windowing/StarWidget.cpp
parent6741a057e5639280d85d0f88ba26f000baa58f61 (diff)
everything everywhere
all at once
Diffstat (limited to 'source/windowing/StarWidget.cpp')
-rw-r--r--source/windowing/StarWidget.cpp474
1 files changed, 474 insertions, 0 deletions
diff --git a/source/windowing/StarWidget.cpp b/source/windowing/StarWidget.cpp
new file mode 100644
index 0000000..b717797
--- /dev/null
+++ b/source/windowing/StarWidget.cpp
@@ -0,0 +1,474 @@
+#include "StarWidget.hpp"
+#include "StarPane.hpp"
+
+#include "StarLabelWidget.hpp"
+#include "StarFlowLayout.hpp"
+
+namespace Star {
+
+Widget::Widget() {
+ m_parent = nullptr;
+ m_context = GuiContext::singletonPtr();
+ m_visible = true;
+ m_focus = false;
+ m_doScissor = true;
+ m_container = false;
+ m_mouseTransparent = false;
+}
+
+Widget::~Widget() {
+ removeAllChildren();
+}
+
+void Widget::update() {
+ for (auto widget : m_members)
+ widget->update();
+}
+
+GuiContext* Widget::context() const {
+ return m_context;
+}
+
+void Widget::render(RectI const& region) {
+ if (!m_visible)
+ return;
+
+ if (!setupDrawRegion(region))
+ return;
+
+ renderImpl();
+ drawChildren();
+}
+
+void Widget::renderImpl() {}
+
+void Widget::drawChildren() {
+ for (auto child : m_members)
+ child->render(m_drawingArea);
+}
+
+Vec2I Widget::position() const {
+ return m_position + m_drawingOffset;
+}
+
+Vec2I Widget::relativePosition() const {
+ return m_position;
+}
+
+bool Widget::setupDrawRegion(RectI const& region) {
+ RectI scissorRect;
+ if (m_doScissor) {
+ scissorRect = getScissorRect();
+ } else {
+ scissorRect = noScissor();
+ }
+ m_drawingArea = scissorRect.limited(region);
+ if (m_drawingArea.isEmpty())
+ return false;
+
+ m_context->setInterfaceScissorRect(m_drawingArea);
+ return true;
+}
+
+Vec2I Widget::drawingOffset() const {
+ return m_drawingOffset;
+}
+
+void Widget::setDrawingOffset(Vec2I const& offset) {
+ m_drawingOffset = offset;
+}
+
+RectI Widget::getScissorRect() const {
+ return screenBoundRect();
+}
+
+RectI Widget::noScissor() const {
+ return RectI::inf();
+}
+
+void Widget::disableScissoring() {
+ m_doScissor = false;
+}
+
+void Widget::enableScissoring() {
+ m_doScissor = true;
+}
+
+void Widget::setPosition(Vec2I const& position) {
+ m_position = position;
+}
+
+Vec2I Widget::size() const {
+ return m_size;
+}
+
+void Widget::setSize(Vec2I const& size) {
+ m_size = size;
+}
+
+RectI Widget::relativeBoundRect() const {
+ return RectI::withSize(relativePosition(), size());
+}
+
+RectI Widget::screenBoundRect() const {
+ return relativeBoundRect().translated(screenPosition() - relativePosition());
+}
+
+void Widget::determineSizeFromChildren() {
+ Vec2I max;
+
+ for (auto& child : m_members) {
+ Vec2I childMax = child->position() + child->size();
+ max = max.piecewiseMax(childMax);
+ }
+
+ setSize(max);
+}
+
+void Widget::markAsContainer() {
+ m_container = true;
+}
+
+KeyboardCaptureMode Widget::keyboardCaptured() const {
+ if (active()) {
+ for (auto const& member : m_members) {
+ auto mode = member->keyboardCaptured();
+ if (mode != KeyboardCaptureMode::None)
+ return mode;
+ }
+ }
+ return KeyboardCaptureMode::None;
+}
+
+void Widget::setData(Json const& data) {
+ m_data = data;
+}
+
+Json const& Widget::data() {
+ return m_data;
+}
+
+Vec2I Widget::screenPosition() const {
+ if (m_parent) {
+ return m_parent->screenPosition() + position();
+ } else {
+ return position();
+ }
+}
+
+bool Widget::inMember(Vec2I const& position) const {
+ if (!m_visible)
+ return false;
+
+ if (m_mouseTransparent)
+ return false;
+
+ if (!m_drawingArea.isNull() && !m_drawingArea.contains(Vec2I::floor(position)))
+ return false;
+
+ if (m_container) {
+ for (auto child : m_members)
+ if (child->inMember(position))
+ return true;
+ } else {
+ return screenBoundRect().contains(position);
+ }
+
+ return false;
+}
+
+bool Widget::sendEvent(InputEvent const& event) {
+ if (!m_visible)
+ return false;
+
+ for (auto child : reverseIterate(m_members)) {
+ if (child->sendEvent(event))
+ return true;
+ }
+
+ return false;
+}
+
+void Widget::mouseOver() {}
+
+void Widget::mouseOut() {}
+
+void Widget::mouseReturnStillDown() {}
+
+void Widget::setMouseTransparent(bool transparent) {
+ m_mouseTransparent = transparent;
+}
+
+bool Widget::mouseTransparent() {
+ return m_mouseTransparent;
+}
+
+Widget* Widget::parent() const {
+ return m_parent;
+}
+
+void Widget::setParent(Widget* parent) {
+ m_parent = parent;
+}
+
+void Widget::show() {
+ m_visible = true;
+}
+
+void Widget::hide() {
+ m_visible = false;
+}
+
+void Widget::toggleVisibility() {
+ m_visible = !m_visible;
+}
+
+void Widget::setVisibility(bool visibility) {
+ if (visibility)
+ show();
+ else
+ hide();
+}
+
+bool Widget::active() const {
+ return m_visible;
+}
+
+bool Widget::interactive() const {
+ return true;
+}
+
+bool Widget::hasFocus() const {
+ return m_focus;
+}
+
+void Widget::focus() {
+ m_focus = true;
+ if (auto w = window())
+ w->setFocus(this);
+}
+
+void Widget::blur() {
+ m_focus = false;
+ if (window())
+ window()->removeFocus(this);
+}
+
+unsigned Widget::windowHeight() const {
+ return context()->windowHeight();
+}
+
+unsigned Widget::windowWidth() const {
+ return context()->windowWidth();
+}
+
+Vec2I Widget::windowSize() const {
+ return Vec2I(context()->windowSize());
+}
+
+Pane* Widget::window() {
+ if (m_parent)
+ return m_parent->window();
+ return nullptr;
+}
+
+Pane const* Widget::window() const {
+ if (m_parent)
+ return m_parent->window();
+ return nullptr;
+}
+
+void Widget::addChild(String const& name, WidgetPtr member) {
+ member->setName(name);
+ m_members.push_back(member);
+ m_memberHash[member->name()] = member;
+ member->setParent(this);
+}
+
+void Widget::addChildAt(String const& name, WidgetPtr member, size_t at) {
+ if (at > m_members.size())
+ throw GuiException("Attempted to insert item after the end of the list.");
+
+ m_members.insert(m_members.begin() + at, member);
+ m_memberHash[name] = member;
+ member->setName(name);
+ member->setParent(this);
+}
+
+bool Widget::removeChild(Widget* member) {
+ m_memberHash.erase(member->name());
+ for (auto child = m_members.begin(); child != m_members.end(); ++child) {
+ if (child->get() == member) {
+ (*child)->setParent(nullptr);
+ m_members.erase(child);
+ return true;
+ } else {
+ if ((*child)->removeChild(member))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool Widget::removeChild(String const& name) {
+ m_memberHash.erase(name);
+ for (auto child = m_members.begin(); child != m_members.end(); ++child) {
+ auto ptr = *child;
+ if (ptr->name() == name) {
+ m_members.erase(child);
+ ptr->setParent(nullptr);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool Widget::removeChildAt(size_t at) {
+ if (at >= m_members.size())
+ return false;
+
+ m_memberHash.erase(m_members.at(at)->name());
+
+ m_members.at(at)->setParent(nullptr);
+ m_members.erase(m_members.begin() + at);
+ return true;
+}
+
+void Widget::removeAllChildren() {
+ for (auto child : m_members)
+ child->setParent(nullptr);
+
+ m_members.clear();
+ m_memberHash.clear();
+}
+
+bool Widget::containsChild(String const& name) {
+ if (fetchChild(name))
+ return true;
+ return false;
+}
+
+WidgetPtr Widget::fetchChild(String const& name) {
+ WidgetPtr res;
+ if (name.contains(".")) {
+ StringList nameList = name.split(".", 1);
+ if (auto child = m_memberHash.value(nameList[0], {}))
+ return child->fetchChild(nameList[1]);
+ } else {
+ if (auto child = m_memberHash.value(name, {}))
+ return child;
+ }
+ return {};
+}
+
+WidgetPtr Widget::findChild(String const& name) {
+ if (auto found = fetchChild(name))
+ return found;
+ for (auto const& child : m_members) {
+ if (auto found = child->findChild(name))
+ return found;
+ }
+ return {};
+}
+
+WidgetPtr Widget::childPtr(Widget const* child) const {
+ for (auto const& m : m_members) {
+ if (m.get() == child)
+ return m;
+ if (auto c = m->childPtr(child))
+ return c;
+ }
+ return {};
+}
+
+WidgetPtr Widget::getChildAt(Vec2I const& pos) {
+ for (auto child : reverseIterate(m_members)) {
+ if (child->inMember(pos)) {
+ auto res = child->getChildAt(pos);
+ if (res) {
+ return res;
+ }
+ return child;
+ }
+ }
+
+ return {};
+}
+
+size_t Widget::numChildren() const {
+ return m_members.size();
+}
+
+WidgetPtr Widget::getChildNum(size_t num) const {
+ return m_members.at(num);
+}
+
+String const& Widget::name() const {
+ return m_name;
+}
+
+void Widget::setName(String const& name) {
+ m_name = name;
+}
+
+String Widget::fullName() const {
+ if (m_parent) {
+ return m_parent->fullName() + "." + name();
+ }
+
+ return name();
+}
+
+String Widget::toStringImpl(int indentLevel) const {
+ auto leader = String(" ") * indentLevel;
+ String childrenString;
+ for (auto child : m_members) {
+ childrenString.append(child->toStringImpl(indentLevel + 4));
+ }
+ String output = strf(R"OUTPUT(%s%s : {
+%s address : %p,
+%s visible : %s,
+%s position : %s,
+%s size : %s,
+%s children : {
+%s
+%s }
+%s}
+)OUTPUT",
+ leader,
+ m_name,
+ leader,
+ this,
+ leader,
+ m_visible ? "true" : "false",
+ leader,
+ m_position,
+ leader,
+ m_size,
+ leader,
+ childrenString,
+ leader,
+ leader);
+
+ return output;
+}
+
+bool Widget::setLabel(String const& name, String const& value) {
+ if (containsChild(name)) {
+ auto child = fetchChild(name);
+ if (auto label = as<LabelWidget>(child)) {
+ label->setText(value);
+ return true;
+ }
+ }
+ return false;
+}
+
+std::ostream& operator<<(std::ostream& os, Widget const& widget) {
+ os << widget.toStringImpl(0);
+ return os;
+}
+
+}