From a9e48a509a8ec312321e0ccb0cb3974c16546dc9 Mon Sep 17 00:00:00 2001 From: Brad Grantham Date: Mon, 15 Oct 2018 21:09:51 -0700 Subject: [PATCH] initial breakout of UI widget classes --- interface.cpp | 261 +----------------------------------------------- ui_widgets.h | 267 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 269 insertions(+), 259 deletions(-) create mode 100644 ui_widgets.h diff --git a/interface.cpp b/interface.cpp index 57461af..96a2c31 100644 --- a/interface.cpp +++ b/interface.cpp @@ -28,6 +28,8 @@ #define GLFW_INCLUDE_GLCOREARB #include +#include "ui_widgets.h" + #include "glwidget.h" #include "interface.h" @@ -601,265 +603,6 @@ void set_shader(float to_screen[9], DisplayMode display_mode, bool mixed_mode, i } } -typedef pair width_height; - -struct widget -{ - virtual width_height get_min_dimensions() const = 0; - virtual void draw(double now, float to_screen[9], float x, float y, float w, float h) {}; - virtual bool click(double now, float x, float y) { return false; }; - virtual void hover(double now, float x, float y) {}; - virtual void drag(double now, float x, float y) {}; - virtual void release(double now, float x, float y) {}; - virtual bool drop(double now, float x, float y, int count, const char** paths) { return false; }; -}; - -struct switcher -{ - float w, h; - int which; - vector children; - switcher(vector children_) : - w(0), - h(0), - which(0), - children(children_) - { - for(auto it : children) { - float cw, ch; - tie(cw, ch) = it->get_min_dimensions(); - w = max(w, cw); - h = max(h, ch); - } - } - virtual width_height get_min_dimensions() const - { - return {w, h}; - } - virtual void draw(double now, float to_screen[9], float x, float y, float w, float h) - { - children[which]->draw(now, to_screen, x, y, w, h); - } - virtual bool click(double now, float x, float y) - { - return children[which]->click(now, x, y); - } - virtual void hover(double now, float x, float y) - { - children[which]->hover(now, x, y); - } - virtual void drag(double now, float x, float y) - { - children[which]->drag(now, x, y); - } - virtual void release(double now, float x, float y) - { - children[which]->release(now, x, y); - } - virtual bool drop(double now, float x, float y, int count, const char** paths) - { - return children[which]->drop(now, x, y, count, paths); - } -}; - -struct spacer : public widget -{ - float w, h; - spacer(float w_, float h_) : - w(w_), - h(h_) - {} - virtual width_height get_min_dimensions() const - { - return {w, h}; - } -}; - -struct placed_widget -{ - widget *widg; - float x, y, w, h; -}; - -struct padding : public widget -{ - widget* child; - float w, h; - float left_pad, right_pad, top_pad, bottom_pad; - float cw, ch; - - padding(float left_pad_, float right_pad_, float top_pad_, float bottom_pad_, widget* child_) : - child(child_), - left_pad(left_pad_), - right_pad(right_pad_), - top_pad(top_pad_), - bottom_pad(bottom_pad_) - { - tie(cw, ch) = child->get_min_dimensions(); - w = cw + left_pad_ + right_pad_; - h = ch + top_pad_ + bottom_pad_; - } - - virtual width_height get_min_dimensions() const - { - return {w, h}; - } - virtual void draw(double now, float to_screen[9], float x, float y, float w_, float h_) - { - child->draw(now, to_screen, x + left_pad, y + top_pad, w_ - left_pad - right_pad, h_ - top_pad - bottom_pad); - } - virtual bool drop(double now, float x, float y, int count, const char **paths) - { - return child->drop(now, x + left_pad, y + top_pad, count, paths); - } - virtual bool click(double now, float x, float y) - { - return child->click(now, x + left_pad, y + top_pad); - } - virtual void hover(double now, float x, float y) - { - child->hover(now, x + left_pad, y + top_pad); - } - virtual void drag(double now, float x, float y) - { - child->drag(now, x + left_pad, y + top_pad); - } - virtual void release(double now, float x, float y) - { - child->release(now, x + left_pad, y + top_pad); - } -}; - -struct centering : public widget -{ - float w, h; - float cw, ch; - widget* child; - - centering(widget* child_) : child(child_) - { - tie(cw, ch) = child->get_min_dimensions(); - } - - virtual width_height get_min_dimensions() const - { - return {cw, ch}; - } - virtual void draw(double now, float to_screen[9], float x, float y, float w_, float h_) - { - w = w_; - h = h_; - child->draw(now, to_screen, x + (w - cw) / 2, y + (h - ch) / 2, cw, ch); - } - virtual bool drop(double now, float x, float y, int count, const char **paths) - { - return child->drop(now, x - (w - cw) / 2, y - (h - ch) / 2, count, paths); - } - virtual bool click(double now, float x, float y) - { - return child->click(now, x - (w - cw) / 2, y - (h - ch) / 2); // XXX should limit to cw,ch too - } - virtual void hover(double now, float x, float y) - { - child->hover(now, x - (w - cw) / 2, y - (h - ch) / 2); - } - virtual void drag(double now, float x, float y) - { - child->drag(now, x - (w - cw) / 2, y - (h - ch) / 2); - } - virtual void release(double now, float x, float y) - { - child->release(now, x - (w - cw) / 2, y - (h - ch) / 2); - } -}; - -struct widgetbox : public widget -{ - enum Direction {VERTICAL, HORIZONTAL} dir; - float w, h; - vector children; - placed_widget focus; - - widgetbox(Direction dir_, vector children_) : - dir(dir_), - w(0), - h(0), - focus({nullptr, 0, 0, 0, 0}) - { - for(auto it : children_) { - widget *child = it; - float cw, ch; - tie(cw, ch) = child->get_min_dimensions(); - if(dir == HORIZONTAL) { - w += cw; - h = std::max(h, ch); - } else { - w = std::max(w, cw); - h += ch; - } - } - float x = 0; - float y = 0; - for(auto it : children_) { - widget *child = it; - float cw, ch; - tie(cw, ch) = child->get_min_dimensions(); - if(dir == HORIZONTAL) { - children.push_back({child, x, y, cw, h}); - x += cw; - } else { - children.push_back({child, x, y, w, ch}); - y += ch; - } - } - } - virtual width_height get_min_dimensions() const - { - return {w, h}; - } - virtual void draw(double now, float to_screen[9], float x, float y, float w, float h) - { - for(auto child : children) { - child.widg->draw(now, to_screen, x + child.x, y + child.y, child.w, child.h); - } - } - virtual bool drop(double now, float x, float y, int count, const char **paths) - { - for(auto child : children) { - if(child.widg->drop(now, x - child.x, y - child.y, count, paths)) { - return true; - } - } - return false; - } - virtual bool click(double now, float x, float y) - { - for(auto child : children) { - if(child.widg->click(now, x - child.x, y - child.y)) { - focus = child; - return true; - } - } - return false; - } - virtual void hover(double now, float x, float y) - { - for(auto child : children) { - if(x >= child.x && x < child.x + child.w && y >= child.y && y < child.y + child.h) - child.widg->hover(now, x - child.x, y - child.y); - } - } - virtual void drag(double now, float x, float y) - { - focus.widg->click(now, x - focus.x, y - focus.y); - } - virtual void release(double now, float x, float y) - { - focus.widg->release(now, x - focus.x, y - focus.y); - focus = {nullptr, 0, 0}; - } -}; - void set(float v[4], float x, float y, float z, float w) { v[0] = x; diff --git a/ui_widgets.h b/ui_widgets.h new file mode 100644 index 0000000..74c96b5 --- /dev/null +++ b/ui_widgets.h @@ -0,0 +1,267 @@ +#ifndef _UI_WIDGETS_H_ +#define _UI_WIDGETS_H_ + +#include +#include +#include + +typedef std::pair width_height; + +struct widget +{ + virtual width_height get_min_dimensions() const = 0; + virtual void draw(double now, float to_screen[9], float x, float y, float w, float h) {}; + virtual bool click(double now, float x, float y) { return false; }; + virtual void hover(double now, float x, float y) {}; + virtual void drag(double now, float x, float y) {}; + virtual void release(double now, float x, float y) {}; + virtual bool drop(double now, float x, float y, int count, const char** paths) { return false; }; +}; + +struct switcher +{ + float w, h; + int which; + std::vector children; + switcher(std::vector children_) : + w(0), + h(0), + which(0), + children(children_) + { + for(auto it : children) { + float cw, ch; + std::tie(cw, ch) = it->get_min_dimensions(); + w = std::max(w, cw); + h = std::max(h, ch); + } + } + virtual width_height get_min_dimensions() const + { + return {w, h}; + } + virtual void draw(double now, float to_screen[9], float x, float y, float w, float h) + { + children[which]->draw(now, to_screen, x, y, w, h); + } + virtual bool click(double now, float x, float y) + { + return children[which]->click(now, x, y); + } + virtual void hover(double now, float x, float y) + { + children[which]->hover(now, x, y); + } + virtual void drag(double now, float x, float y) + { + children[which]->drag(now, x, y); + } + virtual void release(double now, float x, float y) + { + children[which]->release(now, x, y); + } + virtual bool drop(double now, float x, float y, int count, const char** paths) + { + return children[which]->drop(now, x, y, count, paths); + } +}; + +struct spacer : public widget +{ + float w, h; + spacer(float w_, float h_) : + w(w_), + h(h_) + {} + virtual width_height get_min_dimensions() const + { + return {w, h}; + } +}; + +struct placed_widget +{ + widget *widg; + float x, y, w, h; +}; + +struct padding : public widget +{ + widget* child; + float w, h; + float left_pad, right_pad, top_pad, bottom_pad; + float cw, ch; + + padding(float left_pad_, float right_pad_, float top_pad_, float bottom_pad_, widget* child_) : + child(child_), + left_pad(left_pad_), + right_pad(right_pad_), + top_pad(top_pad_), + bottom_pad(bottom_pad_) + { + std::tie(cw, ch) = child->get_min_dimensions(); + w = cw + left_pad_ + right_pad_; + h = ch + top_pad_ + bottom_pad_; + } + + virtual width_height get_min_dimensions() const + { + return {w, h}; + } + virtual void draw(double now, float to_screen[9], float x, float y, float w_, float h_) + { + child->draw(now, to_screen, x + left_pad, y + top_pad, w_ - left_pad - right_pad, h_ - top_pad - bottom_pad); + } + virtual bool drop(double now, float x, float y, int count, const char **paths) + { + return child->drop(now, x + left_pad, y + top_pad, count, paths); + } + virtual bool click(double now, float x, float y) + { + return child->click(now, x + left_pad, y + top_pad); + } + virtual void hover(double now, float x, float y) + { + child->hover(now, x + left_pad, y + top_pad); + } + virtual void drag(double now, float x, float y) + { + child->drag(now, x + left_pad, y + top_pad); + } + virtual void release(double now, float x, float y) + { + child->release(now, x + left_pad, y + top_pad); + } +}; + +struct centering : public widget +{ + float w, h; + float cw, ch; + widget* child; + + centering(widget* child_) : child(child_) + { + std::tie(cw, ch) = child->get_min_dimensions(); + } + + virtual width_height get_min_dimensions() const + { + return {cw, ch}; + } + virtual void draw(double now, float to_screen[9], float x, float y, float w_, float h_) + { + w = w_; + h = h_; + child->draw(now, to_screen, x + (w - cw) / 2, y + (h - ch) / 2, cw, ch); + } + virtual bool drop(double now, float x, float y, int count, const char **paths) + { + return child->drop(now, x - (w - cw) / 2, y - (h - ch) / 2, count, paths); + } + virtual bool click(double now, float x, float y) + { + return child->click(now, x - (w - cw) / 2, y - (h - ch) / 2); // XXX should limit to cw,ch too + } + virtual void hover(double now, float x, float y) + { + child->hover(now, x - (w - cw) / 2, y - (h - ch) / 2); + } + virtual void drag(double now, float x, float y) + { + child->drag(now, x - (w - cw) / 2, y - (h - ch) / 2); + } + virtual void release(double now, float x, float y) + { + child->release(now, x - (w - cw) / 2, y - (h - ch) / 2); + } +}; + +struct widgetbox : public widget +{ + enum Direction {VERTICAL, HORIZONTAL} dir; + float w, h; + std::vector children; + placed_widget focus; + + widgetbox(Direction dir_, std::vector children_) : + dir(dir_), + w(0), + h(0), + focus({nullptr, 0, 0, 0, 0}) + { + for(auto it : children_) { + widget *child = it; + float cw, ch; + std::tie(cw, ch) = child->get_min_dimensions(); + if(dir == HORIZONTAL) { + w += cw; + h = std::max(h, ch); + } else { + w = std::max(w, cw); + h += ch; + } + } + float x = 0; + float y = 0; + for(auto it : children_) { + widget *child = it; + float cw, ch; + std::tie(cw, ch) = child->get_min_dimensions(); + if(dir == HORIZONTAL) { + children.push_back({child, x, y, cw, h}); + x += cw; + } else { + children.push_back({child, x, y, w, ch}); + y += ch; + } + } + } + virtual width_height get_min_dimensions() const + { + return {w, h}; + } + virtual void draw(double now, float to_screen[9], float x, float y, float w, float h) + { + for(auto child : children) { + child.widg->draw(now, to_screen, x + child.x, y + child.y, child.w, child.h); + } + } + virtual bool drop(double now, float x, float y, int count, const char **paths) + { + for(auto child : children) { + if(child.widg->drop(now, x - child.x, y - child.y, count, paths)) { + return true; + } + } + return false; + } + virtual bool click(double now, float x, float y) + { + for(auto child : children) { + if(child.widg->click(now, x - child.x, y - child.y)) { + focus = child; + return true; + } + } + return false; + } + virtual void hover(double now, float x, float y) + { + for(auto child : children) { + if(x >= child.x && x < child.x + child.w && y >= child.y && y < child.y + child.h) + child.widg->hover(now, x - child.x, y - child.y); + } + } + virtual void drag(double now, float x, float y) + { + focus.widg->click(now, x - focus.x, y - focus.y); + } + virtual void release(double now, float x, float y) + { + focus.widg->release(now, x - focus.x, y - focus.y); + focus = {nullptr, 0, 0}; + } +}; + +#endif /* _UI_WIDGETS_H_ */