#ifndef __OPENGLPLAYGROUND_WIDGET_HH__ #define __OPENGLPLAYGROUND_WIDGET_HH__ #include #include #include #include "common.hh" #include "VBOManager.hh" /* Size the widget to wrap the content size */ static const int WRAP_CONTENT = -1; /* Size the widget to match the parent. If there is no parent, behaves like WRAP_CONTENT */ static const int MATCH_PARENT = -2; /* Size the widget to wrap the content size, expanding to fill parent when parent is larger */ static const int WRAP_CONTENT_FILL = -3; static const int ALIGN_TOP = 0; static const int ALIGN_BOTTOM = 1; static const int ALIGN_CENTER = 2; static const int ALIGN_LEFT = 0; static const int ALIGN_RIGHT = 1; class Texture2D; class Widget { public: Widget(int width = WRAP_CONTENT, int height = WRAP_CONTENT, std::string name = ""); Widget(Widget const& copy) = delete; Widget& operator=(Widget const& copy) = delete; virtual ~Widget(); std::string const& getName() const { return name_; } Widget* getParent() { return parent_; } int getWidth() const { return width_; } int getHeight() const { return height_; } int getRealWidth() const { return realWidth_; } int getRealHeight() const { return realHeight_; } virtual void setSize(int width, int height); /* Set background image. The image is scaled to the widgets actual size*/ void setBackground(SDL_Surface* surf); /* Set background color. Only takes effect when the background image is NULL */ void setBackgroundColor(SDL_Color bg); /* Set foreground color. Effect depends on widget type */ virtual void setForegroundColor(SDL_Color fg); /* Set the padding between the widget position and the content Exact effect depends on widget type. In general, when a widget is rendered the background is applied to the entire dstRect, and the content is rendered with padding*/ void setPadding(int left, int top, int right, int bottom); int getLeftPadding() const { return padLeft_; } int getTopPadding() const { return padTop_; } int getRightPadding() const { return padRight_; } int getBottomPadding() const { return padBottom_; } virtual void setAlignment(int horiz, int vert); void setContainerAlignment(int horiz, int vert); int getContainerAlignmentHoriz() const { return alignContHoriz_; } int getContainerAlignmentVert() const { return alignContVert_; } void setGLRenderPos(int left, int top); virtual void render(SDL_Surface *dst, SDL_Rect *dstRect) const; void renderToGL() const; protected: /* Update realWidth_ and realHeight_ where necessary (width_ or height_ == WRAP_CONTENT). Check caller to prevent recursion */ virtual void layout(Widget *caller = nullptr) = 0; /* Inform the renderToGL() code that any cached presentations are now invalid */ void invalidateGL(); /* Helper to calculate the SDL_Rect with which to render the content, respecting alignment and padding */ SDL_Rect calcContentRect(SDL_Surface *dst, SDL_Rect *dstRect, SDL_Rect contentRect) const; /* Helper to calculate layout height, width constraints Returns width, height tuple with with width/height > 0 if fixed or determined by parent layout, 0 if it should be based on widget contents. Checks caller to prevent recursion */ std::tuple baseLayout(Widget *caller); void setParent(Widget *parent); /* Helpers to allow Views to access protected methods of other Widgets */ void _setParent(Widget& child) { child.setParent(this); } void _clearParent(Widget& child) { child.setParent(nullptr); } void _layout(Widget& child) { child.layout(this); } std::string name_; int width_, height_; int realWidth_, realHeight_; SDL_Surface *background_; SDL_Color bg_, fg_; int padLeft_, padTop_, padRight_, padBottom_; int alignHoriz_, alignVert_; int alignContHoriz_, alignContVert_; Widget *parent_; private: struct VertexAttribs { int16_t vertex[2]; uint16_t texCoords[2]; } __attribute__((__packed__)); int renderTop_, renderLeft_; mutable bool renderTexValid_, renderAttribsValid_; mutable std::unique_ptr renderTex_; mutable VBOManager::VBOAlloc vbo_; mutable gl::GLuint vaID_; }; #endif