guistyle.h File Reference

Go to the documentation of this file. Source: include/ffw/gui/guistyle.h

/* This file is part of FineFramework project */
#ifndef FFW_GUI_STYLE
#define FFW_GUI_STYLE

#include <map>
#include <limits>
#include "./config.h"
#include "color.h"
#include "point.h"

namespace ffw {
    enum class GuiAlign {
        LEFT = 0,
        CENTER,
        RIGHT,
        TOP_LEFT,
        TOP_CENTER,
        TOP_RIGHT,
        BOTTOM_LEFT,
        BOTTOM_CENTER,
        BOTTOM_RIGHT,
    };
    class GuiUnits {
    public:
        enum Type {
            PERCENT,
            PIXELS,
            WRAP,
        };
        inline GuiUnits() :value(0) {
            
        }
        inline GuiUnits(float val, bool percentage) :value(percentage ? -val : val) {
            
        }
        inline GuiUnits(float val) :value(val) {
            
        }
        inline bool operator == (const GuiUnits& other) const {
            if (value == std::numeric_limits<float>::infinity() && other.value == std::numeric_limits<float>::infinity())return true;
            return std::fabs(value - other.value) < std::numeric_limits<float>::epsilon();
        }
        inline bool operator != (const GuiUnits& other) const {
            if (value == std::numeric_limits<float>::infinity() && other.value == std::numeric_limits<float>::infinity())return false;
            return std::fabs(value - other.value) >= std::numeric_limits<float>::epsilon();
        }
        inline bool operator == (float v) const {
            return std::fabs(value - v) < std::numeric_limits<float>::epsilon();
        }
        inline bool operator != (float v) const {
            return std::fabs(value - v) >= std::numeric_limits<float>::epsilon();
        }
        inline bool operator == (Type t) const {
            switch(t) {
                case Type::PIXELS: return value >= 0;
                case Type::PERCENT: return value < 0;
                case Type::WRAP: return value == std::numeric_limits<float>::infinity();
                default: break;
            }
            return false;
        }
        inline bool operator != (Type t) const {
            switch(t) {
                case Type::PIXELS: return value < 0;
                case Type::PERCENT: return value >= 0;
                case Type::WRAP: return value != std::numeric_limits<float>::infinity();
                default: break;
            }
            return false;
        }
        inline friend std::ostream& operator << (std::ostream& os, const GuiUnits& V) {
            os << (V.value < 0 ? -V.value : V.value) << (V.value < 0 ? "%" : "px");
            return os;
        }
        inline float toReal(float val) const {
            if (value == std::numeric_limits<float>::infinity())return 0;
            else if (value < 0) {
                return float((-value / 100.0f) * val);
            }
            else {
                return value;
            }
        }
        inline void setPixels(float px) {
            value = px;
        }
        inline void setPercent(float pc) {
            value = -pc;
        }
        inline Type getType() const {
            if (value == std::numeric_limits<float>::infinity())return Type::WRAP;
            if (value < 0)return Type::PERCENT;
            return Type::PIXELS;
        }
        float value;
    };
    inline bool operator == (float left, const GuiUnits& right){
        return std::fabs(right.value - left) < std::numeric_limits<float>::epsilon();
    }
    inline bool operator != (float left, const GuiUnits& right){
        return std::fabs(right.value - left) >= std::numeric_limits<float>::epsilon();
    }
    inline GuiUnits guiPixels(float pixels) {
        return GuiUnits(pixels, false);
    }
    inline GuiUnits guiPercent(float percent) {
        return GuiUnits(percent, true);
    }
    inline GuiUnits guiWrap() {
        return GuiUnits(std::numeric_limits<float>::infinity());
    }
    class GuiUnits2D: public ffw::Point<GuiUnits> {
    public:
        GuiUnits2D():ffw::Point<GuiUnits>(guiPixels(0), guiPixels(0)){
        }

        GuiUnits2D(const GuiUnits x, const GuiUnits y):ffw::Point<GuiUnits>(x, y) {
        }

        inline ffw::Pointf toReal(const ffw::Pointf& size) const {
            return ffw::Pointf(x.toReal(size.x), y.toReal(size.y));
        }
    };
    class GuiStyle {
    public:
        template <class T>
        class Attribute {
        public:
            inline Attribute() {
                val[0] = T(0);
                val[1] = T(0);
                val[2] = T(0);
                val[3] = T(0);
            }
            inline Attribute(T v) {
                val[0] = v;
                val[1] = v;
                val[2] = v;
                val[3] = v;
            }
            inline Attribute(T top, T right, T bottom, T left) {
                val[0] = top;
                val[1] = right;
                val[2] = bottom;
                val[3] = left;
            }
            inline Attribute(const Attribute& other) {
                val[0] = other.val[0];
                val[1] = other.val[1];
                val[2] = other.val[2];
                val[3] = other.val[3];
            }
            inline Attribute(const std::initializer_list<float>& list) {
                val[0] = *list.begin();
                val[1] = *(list.begin() +1);
                val[2] = *(list.begin() +2);
                val[3] = *(list.begin() +3);
            }
            inline Attribute& operator = (const T& value) {
                val[0] = val[1] = val[2] = val[3] = value;
                return *this;
            }
            inline T& operator [] (size_t i) {
                return val[i];
            }
            inline const T& operator [] (size_t i) const {
                return val[i];
            }
            inline bool operator == (const Attribute& other) const {
                return (val[0] == other.val[0] && val[1] == other.val[1] && val[2] == other.val[2] && val[3] == other.val[3]);
            }
            inline bool operator != (const Attribute& other) const {
                return !(*this == other);
            }
            inline friend std::ostream& operator << (std::ostream& os, const Attribute& a) {
                os << a.val[0] << ", " << a.val[1] << ", " << a.val[2] << ", " << a.val[3] << std::endl;
                return os;
            }
            T val[4];
        };
        class Border {
        public:
            typedef Attribute<float> Size;
            typedef Attribute<float> Radius;
            typedef Attribute<ffw::Color> Color;
            inline Border():
                size(0),radius(0),color(ffw::rgb(0xFFFFFF)) {
            }
            inline Border(const Attribute<float>& s, const Attribute<float>& r, const Attribute<ffw::Color>& c):
                size(s),radius(r),color(c) {
            }
            inline operator bool() const {
                return (size[0] > 0 || size[1] > 0 || size[2] > 0 || size[3] > 0);
            }
            Size size;
            Radius radius;
            Color color;
        };

        typedef Border Outline;
        typedef GuiStyle::Attribute<GuiUnits> Padding;
        typedef GuiStyle::Attribute<GuiUnits> Margin;

        class Background {
        public:
            typedef Attribute<float> Radius;
            enum class Type {
                NONE = 0,
                SIMPLE,
            };
            inline Background():
                radius(0),color(ffw::rgb(0x000000)),type(Type::NONE) {
            }
            inline Background(const ffw::Color& c) :
                radius(0), color(c), type(Type::SIMPLE) {
            }
            inline Background(const Attribute<float>& r, const ffw::Color& c):
                radius(r),color(c),type(Type::SIMPLE) {
            }
            Attribute<float> radius;
            ffw::Color color;
            Type type;
            inline operator bool() const {
                return type != Type::NONE;
            }
        };

        class Text {
        public:
            inline Text():
                color(ffw::rgb(0xFFFFFF)) {
            }
            inline Text(const ffw::Color& c):
                color(c) {
            }
            ffw::Color color;
        };

        class Function {
        public:
            inline Function() :
                color(ffw::rgb(0xFFFFFF)),secondary(ffw::rgb(0xFFFFFF)) {
            }
            inline Function(const ffw::Color& c):
                color(c),secondary(c) {
            }
            inline Function(const ffw::Color& c, const ffw::Color& s) :
                color(c), secondary(s) {
            }
            ffw::Color color;
            ffw::Color secondary;
        };
        inline GuiStyle() {
            
        }
        inline GuiStyle(const Background& b, const Border& br, const Outline& ou, const Text& t, const Function& f):
            background(b),border(br),outline(ou),text(t),function(f){
        }

        Background background;
        Border border;
        Outline outline;
        Text text;
        Function function;
    };
    class GuiDefaults {
    public:
        inline GuiDefaults() :
            margin(0), padding(0), align(GuiAlign::TOP_LEFT), size(GuiUnits2D(guiPercent(100), guiWrap())) {
        }
        inline GuiDefaults(const GuiStyle::Margin& m, const GuiStyle::Padding& p, GuiAlign a, const GuiUnits2D& s):
            margin(m),padding(p),align(a),size(s){
        }
        inline GuiDefaults(float m, float p, GuiAlign a, const GuiUnits2D& s) :
            margin(m), padding(p), align(a), size(s) {
        }
        GuiStyle::Margin margin;
        GuiStyle::Padding padding;
        GuiAlign align;
        GuiUnits2D size;
    };
};
#endif