Merge with ComponentStackRework 4.x-dev

Thu, 17 Sep 2020 16:29:02 +0300

author
cemkalyoncu
date
Thu, 17 Sep 2020 16:29:02 +0300
branch
4.x-dev
changeset 1445
918fb4e78caa
parent 1421
417d828700b2 (current diff)
parent 1444
53e69f1cea46 (diff)
child 1446
b8ca90251339

Merge with ComponentStackRework

Source/Gorgon/Widgets/Generator.cpp file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/Generator.h file | annotate | diff | comparison | revisions
Source/Gorgon/Widgets/Registry.h file | annotate | diff | comparison | revisions
Testing/Source/Manual/UI_Generate.cpp file | annotate | diff | comparison | revisions
--- a/Source/Gorgon/CGI/Line.h	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/CGI/Line.h	Thu Sep 17 16:29:02 2020 +0300
@@ -24,7 +24,7 @@
         points.push_back({});
         
                                     // To ensure thickness is corrected for strictly inside
-        Float w = settings.width / 2 + 1.0f / (S_ * 2);
+        Float w = settings.width / 2/* + 1.0f / (S_ * 4)*/;
         
         Geometry::Line<P_> prev;
 		Geometry::Pointf prevoff;
--- a/Source/Gorgon/ConsumableEvent.h	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/ConsumableEvent.h	Thu Sep 17 16:29:02 2020 +0300
@@ -228,6 +228,9 @@
 
 			std::lock_guard<std::mutex> g(access);
 			handlers.Add(handler);
+            
+            if(NewHandler)
+                NewHandler();
 
 			return reinterpret_cast<Token>(&handler);
 		}
@@ -409,6 +412,8 @@
 		
 		/// value for an empty token
 		static const Token EmptyToken;
+        
+        std::function<void()> NewHandler;
 		
 	private:
 
--- a/Source/Gorgon/Geometry/Margin.h	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/Geometry/Margin.h	Thu Sep 17 16:29:02 2020 +0300
@@ -48,15 +48,26 @@
 			return str.str();
 		}
 		
-		/// Combines two margins that are inside each other, basically taking the maximum margin from each side
+		/// Combines two margins that are inside each other, basically taking the maximum margin from each side. Negative margins do
+		/// not collapse
 		basic_Margin CombinePadding(const basic_Margin &other) const {
-            return {std::max(Left, other.Left), std::max(Top, other.Top), std::max(Right, other.Right), std::max(Bottom, other.Bottom)};
+            return {
+				(Left < 0 || other.Left < 0) ? Left + other.Left : std::max(Left, other.Left),
+				(Top < 0 || other.Top < 0) ? Top + other.Top : std::max(Top, other.Top),
+				(Right < 0 || other.Right < 0) ? Right + other.Right : std::max(Right, other.Right),
+				(Bottom < 0 || other.Bottom < 0) ? Bottom + other.Bottom : std::max(Bottom, other.Bottom),
+			};
         }
 
 		/// Combines two margins that are next to each other, basically taking the maximum margin from each side with its opposite.
-		/// Only one of the values should be used.
+		/// Only one of the values should be used. Negative margins do not collapse
         basic_Margin CombineMargins(const basic_Margin &other) const {
-            return {std::max(Left, other.Right), std::max(Top, other.Bottom), std::max(Right, other.Left), std::max(Bottom, other.Top)};
+            return {
+				(Left < 0 || other.Right< 0) ? Left + other.Right : std::max(Left, other.Right),
+				(Top < 0 || other.Bottom < 0) ? Top + other.Bottom : std::max(Top, other.Bottom),
+				(Right < 0 || other.Left < 0) ? Right + other.Left : std::max(Right, other.Left),
+				(Bottom < 0 || other.Top < 0) ? Bottom + other.Top : std::max(Bottom, other.Top),
+			};
         }
 		
 		/// Calculates and returns the total Margin in X axis
--- a/Source/Gorgon/Graphics/BitmapFont.cpp	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/Graphics/BitmapFont.cpp	Thu Sep 17 16:29:02 2020 +0300
@@ -1048,14 +1048,14 @@
                     miny = int(g.offset.Y + firsty);
 
                 if(g.offset.Y + lasty > maxy)
-                    maxy = g.offset.Y + lasty;
+                    maxy = int(g.offset.Y + lasty);
             }
             else {
                 if(g.offset.Y < miny)
-                    miny = g.offset.Y;
+                    miny = int(g.offset.Y);
                 
                 if(g.offset.Y + g.image->GetHeight() > maxy)
-                    maxy = g.offset.Y + g.image->GetHeight();
+                    maxy = int(g.offset.Y + g.image->GetHeight());
             }
         }
 
--- a/Source/Gorgon/Graphics/BitmapFont.h	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/Graphics/BitmapFont.h	Thu Sep 17 16:29:02 2020 +0300
@@ -148,9 +148,9 @@
         ~BitmapFont() {
 			destroylist.Destroy();
         }
-                
+        
         /// Adds a new glyph bitmap to the list. If a previous one exists, it will be replaced.
-        /// Ownership of bitmap is not transferred.
+        /// Ownership of bitmap is not transferred. TODO: better baseline handling
         void AddGlyph(Glyph glyph, const RectangularDrawable &bitmap, int baseline = 0) {
             AddGlyph(glyph, bitmap, {0, this->baseline - baseline}, float(bitmap.GetWidth() + spacing));
         }
@@ -245,7 +245,7 @@
 		void DetermineDimensions();
         
         /// Changes the spacing between glyphs
-        void SetGlyphSpacing(int spacing) { this->spacing = spacing; }
+        void SetGlyphSpacing(int value) { spacing = value; }
 		
 		/// Returns the spacing between glyphs
 		int GetGlyphSpacing() const { return spacing; }
--- a/Source/Gorgon/Graphics/Color.h	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/Graphics/Color.h	Thu Sep 17 16:29:02 2020 +0300
@@ -246,28 +246,7 @@
 		/// Blends the given color into this one. This operation performs regular alpha blending with the current
 		/// color being blended over.
 		void Blend(const RGBA &color) {
-			if (color.A == 255) {
-				A = 255;
-				R = color.R;
-				G = color.G;
-				B = color.B;
-			}
-			else {
-				float alpha = (float)color.A / 255;
-				float alpham1 = (float)(255 - color.A) / 255;
-
-				if (A < 255) {
-					int aa = (int)A + color.A;
-					if (aa > 255)
-						A = 255;
-					else
-						A = aa;
-				}
-
-				R = (Byte)(R*alpham1 + color.R*alpha);
-				G = (Byte)(G*alpham1 + color.G*alpha);
-				B = (Byte)(B*alpham1 + color.B*alpha);
-			}
+			Blend(color, 1.0f);
 		}
 
 		/// Blends the given color into this one. This operation performs regular alpha blending with the current
@@ -281,19 +260,18 @@
 			}
 			else {
 				float a = color.A*alpha / 255;
-				float alpham1 = (float)(255 - color.A*alpha) / 255;
+				float alpham1 = (1 - a);
+
+                alpham1 *= A / 255.f;
+                    
+                float aa = a + A/255.f * (1 - a);
 
-				if (A < 255) {
-					int aa = A + int(color.A*alpha);
-					if (aa > 255)
-						A = 255;
-					else
-						A = aa;
-				}
-
-				R = (Byte)(R*alpham1 + color.R*a);
-				G = (Byte)(G*alpham1 + color.G*a);
-				B = (Byte)(B*alpham1 + color.B*a);
+				if(aa > 0) {
+                    R = Byte((R*alpham1 + color.R*a)/aa);
+                    G = Byte((G*alpham1 + color.G*a)/aa);
+                    B = Byte((B*alpham1 + color.B*a)/aa);
+                }
+                A = Byte(aa*255);
 			}
 		}
 		
@@ -538,29 +516,54 @@
 			else {
 				float alpham1=1.f-color.A;
 
-				A += color.A;
-				if(A > 1.f)
-					A=1.f;
-
-				R=R*alpham1 + color.R*color.A;
-				G=G*alpham1 + color.G*color.A;
-				B=B*alpham1 + color.B*color.A;
+                R=R*alpham1*A + color.R*color.A;
+				G=G*alpham1*A + color.G*color.A;
+				B=B*alpham1*A + color.B*color.A;
+                A = color.A + A * alpham1;
+                
+                R /= A;
+                G /= A;
+                B /= A;
 			}
 		}
 
-		/// Blends the given color into this one with the given factor that is applied to all channels
+		/// Blends the given color into this one with the given factor that is applied to all channels.
 		void Blend(const RGBAf &color, float factor) {
-			auto m = 1 - factor;
+			if(color.A==1.f) {
+				A=1.f;
+				R=color.R;
+				G=color.G;
+				B=color.B;
+			}
+			else {
+                float a = color.A*factor;
+				float alpham1=1.f-a;
 
-			R = m * R + factor * color.R;
-			G = m * G + factor * color.G;
-			B = m * B + factor * color.B;
-			A = m * A + factor * color.A;
+                R=R*alpham1 * A + color.R * a;
+				G=G*alpham1 * A + color.G * a;
+				B=B*alpham1 * A + color.B * a;
+                A = color.A + A * alpham1;
+                
+                R /= A;
+                G /= A;
+                B /= A;
+			}
 		}
 
 		/// Blends the given color into this one with the given factor that is applied to color and alpha
-		/// channels separately
-		void Blend(const RGBAf &color, float factor_color, float factor_alpha) {
+		/// channels separately. This is not regular alpha blending as source alpha is not used.
+		void Slide(const RGBAf &color, float factor) {
+			auto ma = 1 - factor;
+
+			R = ma * R + factor * color.R;
+			G = ma * G + factor * color.G;
+			B = ma * B + factor * color.B;
+			A = ma * A + factor * color.A;
+		}
+		
+		/// Blends the given color into this one with the given factor that is applied to color and alpha
+		/// channels separately. This is not regular alpha blending as source alpha is not used.
+		void Slide(const RGBAf &color, float factor_color, float factor_alpha) {
 			auto mc = 1 - factor_color;
 			auto ma = 1 - factor_alpha;
 
@@ -570,8 +573,9 @@
 			A = ma * A + factor_alpha * color.A;
 		}
 
-		/// Blends the given color into this one with the given color as blending factor
-		void Blend(const RGBAf &color, const RGBAf &factor) {
+		/// Blends the given color into this one with the given factor that is applied to color and alpha
+		/// channels separately. This is not regular alpha blending as source alpha is not used.
+		void Slide(const RGBAf &color, const RGBAf &factor) {
 			R = (1 - factor.R) * R + factor.R * color.R;
 			G = (1 - factor.G) * G + factor.G * color.G;
 			B = (1 - factor.B) * B + factor.B * color.B;
--- a/Source/Gorgon/Graphics/Font.cpp	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/Graphics/Font.cpp	Thu Sep 17 16:29:02 2020 +0300
@@ -481,6 +481,7 @@
 
                     autobreak=true;
                     lastbreak = 0;
+                    ind = 0;
                 }
                 //if we wrapped, ignore spaces at start
                 else if(!autobreak || ind != 0 || !isspace(g)) { 
@@ -640,6 +641,7 @@
                     
                     autobreak=true;
                     lastbreak = 0;
+                    ind = 0;
                 }
                 //if we wrapped, ignore spaces at start
                 else if(!autobreak || ind != 0 || !isspace(g)) { 
@@ -690,7 +692,7 @@
             [&](Glyph) { cur.Y += (int)renderer->GetLineGap(); if(maxx < cur.X) maxx = cur.X; cur.X = 0; }
         );
 
-        return{maxx, cur.Y + 1};
+        return{maxx, cur.Y};
     }
     
     Geometry::Size BasicFont::GetSize(const std::string& text, int w) const {
@@ -712,7 +714,7 @@
             std::bind(&internal::dodefaulttab<int>, 0, std::placeholders::_1, renderer->GetMaxWidth() * 8)
         );
 
-        return {w, y + 1};
+        return {w, y};
     }
     
     int BasicFont::GetCharacterIndex(const std::string &text, Geometry::Point location) const{ 
@@ -1048,7 +1050,7 @@
             [&](Glyph) { cur.Y += (int)std::round(renderer->GetLineGap() * vspace + pspace); if(maxx < cur.X) maxx = cur.X; cur.X = 0; }
         );
 
-        return{maxx > 0 ? maxx + 1 : 0, cur.Y + 1};
+        return{maxx > 0 ? maxx : 0, cur.Y > 0 ? (cur.Y - pspace + (int)std::round(renderer->GetLineGap() * (1 - vspace))) : 0};
     }
     
     Geometry::Size StyledRenderer::GetSize(const std::string &text, int width) const {
@@ -1062,7 +1064,10 @@
         internal::boundedprint(
             *renderer, text.begin(), text.end(), tot,
             [&](Glyph eol, internal::markvecit begin, internal::markvecit end, int width) {            
-                y += (int)std::round(renderer->GetLineGap() * vspace + pspace);
+                y += (int)std::round(renderer->GetLineGap() * vspace);
+                if(eol != 0)
+                    y += pspace;
+                
                 if(width > maxx)
                     maxx = width;
 
@@ -1076,7 +1081,7 @@
             std::bind(&internal::dodefaulttab<int>, 0, std::placeholders::_1, tabwidth ? tabwidth : 16)
         );
 
-        return {maxx > 0 ? maxx + 1 : 0, y + 1};
+        return {maxx > 0 ? maxx : 0, y > 0 ?  y - pspace + (int)std::round(renderer->GetLineGap() * (1 - vspace)) : 0};
     }
     
     int StyledRenderer::GetCharacterIndex(const std::string &text, Geometry::Point location) const{ 
@@ -1454,7 +1459,7 @@
             pos = {std::numeric_limits<int>::min(), std::numeric_limits<int>::min()};
 
         return {pos, size};
-   }
+    }
 
     void StyledRenderer::print(TextureTarget &target, const std::string &text, Geometry::Rectangle location, TextAlignment align_override) const {
         /*if(renderer->NeedsPrepare())
@@ -1592,7 +1597,6 @@
         );
     }
 
-
     void BasicFont::printnowrap(TextureTarget& target, const std::string& text, Geometry::Rectangle location, TextAlignment align, RGBAf color) const {
         switch(align) {
         case TextAlignment::Left:
@@ -1612,7 +1616,6 @@
         }
     }
 
-
     void StyledRenderer::printnowrap(TextureTarget& target, const std::string& text, Geometry::Rectangle location, TextAlignment align) const {
         switch(align) {
         case TextAlignment::Left:
--- a/Source/Gorgon/Graphics/Font.h	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/Graphics/Font.h	Thu Sep 17 16:29:02 2020 +0300
@@ -213,6 +213,12 @@
         /// Returns the size of the EM dash
         virtual int GetEMSize() const = 0;
         
+        /// Get the distance of baseline from the top of the text
+        virtual float GetBaseLine() const = 0;
+        
+        /// Get the distance of baseline from the top of the text
+        virtual int GetHeight() const = 0;
+        
         /// Returns the size of the given text
         virtual Geometry::Size GetSize(const std::string &text) const = 0;
         
@@ -346,7 +352,15 @@
         virtual int GetEMSize() const override {
             return renderer->GetEMSize();
         }
-
+        
+        virtual float GetBaseLine() const override {
+            return renderer->GetBaseLine();
+        }
+        
+        virtual int GetHeight() const override {
+            return renderer->GetHeight();
+        }
+        
         virtual Geometry::Size GetSize(const std::string &text) const override;
         
         virtual Geometry::Size GetSize(const std::string &text, int width) const override;
@@ -719,6 +733,14 @@
             return renderer->GetEMSize();
         }
         
+        virtual float GetBaseLine() const override {
+            return renderer->GetBaseLine();
+        }
+        
+        virtual int GetHeight() const override {
+            return renderer->GetHeight();
+        }
+        
         virtual const GlyphRenderer &GetGlyphRenderer() const override {
             return *renderer;
         }
--- a/Source/Gorgon/Graphics/FreeType.cpp	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/Graphics/FreeType.cpp	Thu Sep 17 16:29:02 2020 +0300
@@ -17,7 +17,7 @@
         if(delta || matrix)
             FT_Set_Transform(face, matrix, delta);
 
-        auto error = FT_Load_Glyph(face, index, FT_LOAD_RENDER|(aa ? 0 : FT_LOAD_MONOCHROME));
+        auto error = FT_Load_Glyph(face, index, FT_LOAD_RENDER|(aa ? FT_LOAD_TARGET_LIGHT : FT_LOAD_MONOCHROME));
 
         if(error != FT_Err_Ok)
             return nullptr;
--- a/Source/Gorgon/Graphics/Rectangle.cpp	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/Graphics/Rectangle.cpp	Thu Sep 17 16:29:02 2020 +0300
@@ -76,7 +76,7 @@
         tm.DrawIn(target, prov.GetSideTiling() ? Tiling::Horizontal : Tiling::None, 
                   Geometry::Rectanglef(r.X + maxl, r.Y + maxt - tm.GetHeight(), r.Width-maxl-maxr, (Float)tm.GetHeight()),
                   color);
-        tr.Draw(target, r.Right() - maxr, r.Y + maxt - tr.GetHeight());
+        tr.Draw(target, r.Right() - maxr, r.Y + maxt - tr.GetHeight(), color);
 
         ml.DrawIn(target, prov.GetSideTiling() ? Tiling::Vertical : Tiling::None, 
                   Geometry::Rectanglef(r.X + maxl - ml.GetWidth(), r.Y + maxt, (Float)ml.GetWidth(), r.Height-maxt-maxb),
@@ -93,7 +93,7 @@
         bm.DrawIn(target, prov.GetSideTiling() ? Tiling::Horizontal : Tiling::None, 
                   Geometry::Rectanglef(r.X + maxl, r.Bottom() - maxb, r.Width-maxl-maxr, (Float)bm.GetHeight()),
                   color);
-        br.Draw(target, r.Right() - maxr, r.Bottom() - maxb);
+        br.Draw(target, r.Right() - maxr, r.Bottom() - maxb, color);
 	}
 
 	void Rectangle::drawin(TextureTarget &target, const SizeController &controller, const Geometry::Rectanglef &r, RGBAf color) const {
--- a/Source/Gorgon/Graphics/Rectangle.h	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/Graphics/Rectangle.h	Thu Sep 17 16:29:02 2020 +0300
@@ -5,6 +5,8 @@
 #include "EmptyImage.h"
 #include "Bitmap.h"
 
+#include <set>
+
 namespace Gorgon { namespace Graphics {
 	/// Interface for RectangleProviders
 	class IRectangleProvider : public RectangularAnimationProvider {
@@ -213,6 +215,50 @@
 			own(true)
         { }
 
+		/// Filling constructor. The given object will be used for the borders. Center
+		/// will be empty
+		explicit basic_RectangleProvider(
+			A_  &border
+		) : 
+			tl(&border), tm(&border), tr(&border),
+			ml(&border), mm(nullptr), mr(&border),
+			bl(&border), bm(&border), br(&border) 
+        { }
+        
+		/// Filling constructor using move semantics, rectangle will create and own
+		/// new object. The given object will be moved to this new object. The given
+		/// object will be used for the borders
+		explicit basic_RectangleProvider(
+			A_  &&border
+		) : 
+			tl(new A_(std::move(border))), tm(tl), tr(tl),
+			ml(tl), mm(nullptr), mr(tl),
+			bl(tl), bm(tl), br(tl),
+			own(true)
+        { }
+
+		/// Filling constructor. The first given object will be used for the borders. The
+		/// second will be used for the center
+		basic_RectangleProvider(
+			A_  &border, A_ &center
+		) : 
+			tl(&border), tm(&border), tr(&border),
+			ml(&border), mm(&center), mr(&border),
+			bl(&border), bm(&border), br(&border) 
+        { }
+
+		/// Filling constructor using move semantics, rectangle will create and own
+		/// new objects. The given objects will be moved to these new objects. The first
+		/// object will be used for the borders, the second will be used for center
+		explicit basic_RectangleProvider(
+			A_  &&border, A_ &&center
+		) : 
+			tl(new A_(std::move(border))), tm(tl), tr(tl),
+			ml(tl), mm(new A_(std::move(center))), mr(tl),
+			bl(tl), bm(tl), br(tl),
+			own(true)
+        { }
+
 		/// Filling constructor, nullptr is acceptable
 		basic_RectangleProvider(
 			A_  *tl, A_ *tm, A_ *tr,
@@ -251,17 +297,12 @@
 
 		~basic_RectangleProvider() {
 			if(own) {
-				delete tl;
-				delete tm;
-				delete tr;
-
-                delete ml;
-				delete mm;
-				delete mr;
-    
-                delete bl;
-				delete bm;
-				delete br;
+                //delete unique ones
+                std::set<A_*> ptrs = {tl, tm, tr, ml, mm, mr, bl, bm, br};
+                
+                for(auto ptr : ptrs) {
+                    delete ptr;
+                }
             }
 		}
 		
--- a/Source/Gorgon/Graphics/TextureTargets.h	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/Graphics/TextureTargets.h	Thu Sep 17 16:29:02 2020 +0300
@@ -43,6 +43,11 @@
 		}
 
 		/// Draws a textureless solid colored rectangle on the screen.
+		virtual void Draw(int x, int y, int w, int h, RGBAf color = RGBAf(1.f)) {
+			Draw({float(x), float(y), float(w), float(h)}, color);
+		}
+
+		/// Draws a textureless solid colored rectangle on the screen.
 		virtual void Draw(const Geometry::Pointf &location, const Geometry::Sizef &size, RGBAf color = RGBAf(1.f)) {
 			Draw({location, size}, color);
 		}
--- a/Source/Gorgon/Input.h	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/Input.h	Thu Sep 17 16:29:02 2020 +0300
@@ -12,6 +12,12 @@
 	namespace Input {
 		/// A type to represent an input key
 		typedef int Key;
+        
+        
+        /// During keyevent this variable can be set to true, if done so, it
+        /// will allow character events even if key event is handled. However,
+        /// doing so will not direct the up event to the handler directly.
+        extern bool AllowCharEvent;
 		
 	}
 }
--- a/Source/Gorgon/Input/Input.cpp	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/Input/Input.cpp	Thu Sep 17 16:29:02 2020 +0300
@@ -5,5 +5,8 @@
 	
 	namespace Keyboard {
 		Modifier CurrentModifier=Modifier::None;
+        
 	}
+	
+    bool AllowCharEvent = false;
 } }
--- a/Source/Gorgon/Input/KeyRepeater.h	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/Input/KeyRepeater.h	Thu Sep 17 16:29:02 2020 +0300
@@ -105,6 +105,16 @@
             registeredkeys.insert(key);
         }
         
+        /// Registers the given keys to be repeated. Registering keys are necessary only for
+        /// automatic key acquisition from an event.
+        template<class ... T_>
+        void Register(Key key, T_ &&... args) {
+            registeredkeys.insert(key);
+            
+            this->Register(std::forward<T_>(args)...);
+        }
+        
+        
         /// Unregisters a key from this repeater. Unregistering a key will trigger a release
         /// if key is pressed. The key can be pressed again later on using Press function
         /// however, it will not automatically be acquired from the event that this repeater
@@ -250,7 +260,7 @@
         std::set<Key> registeredkeys;
         
         
-        bool repeatonpress    = false;
+        bool repeatonpress    = true;
         
         bool repeatonrelease  = false;
         
--- a/Source/Gorgon/Input/Keyboard.h	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/Input/Keyboard.h	Thu Sep 17 16:29:02 2020 +0300
@@ -276,6 +276,16 @@
 			return {Type(Key & r.Key)};
 		}
 		
+		/// Check modifier
+		explicit operator bool() const {
+            return Key != None;
+        }
+		
+		/// Check modifier
+		bool operator !() const {
+            return Key == None;
+        }
+		
 		/// The modifier key
 		Type Key;
 	};
--- a/Source/Gorgon/Main.cpp	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/Main.cpp	Thu Sep 17 16:29:02 2020 +0300
@@ -21,10 +21,23 @@
 #endif
 
 /**
- * @page GDB Pretty Printing
- * For GDB pretty printing to work with Gorgon objects
- * simply copy Resource/Gorgon-gdb.py file to the startup
- * directory of your program.
+ * @page programminghelpers Programming Utilities
+ * 
+ * Debugging Help
+ * ==============
+ * 
+ * GDB Pretty Printing
+ * -------------------
+ * 
+ * For GDB pretty printing to work with Gorgon objects simply copy `Resource/Gorgon-gdb.py`
+ * file to the startup directory of your program. You may need to allow script execution
+ * in GDB, when GDB is run, it will show you options on how to allow autoload scripts.
+ * 
+ * Adding the following to `~/.gdbinit` will allow script autoload in everywhere:
+ * 
+ * @code
+ * set auto-load safe-path /
+ * @endcode
  */
 
 #ifdef __GNUC__
--- a/Source/Gorgon/Resource/Font.cpp	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/Resource/Font.cpp	Thu Sep 17 16:29:02 2020 +0300
@@ -51,7 +51,7 @@
             writer.WriteInt32(bf->GetGlyphSpacing());
             writer.WriteFloat(bf->GetBaseLine());
             writer.WriteInt32(bf->GetHeight());
-            writer.WriteInt32(bf->GetLineThickness());
+            writer.WriteInt32((int)bf->GetLineThickness()); //this is stored as in for bitmap fonts
             writer.WriteInt32(bf->GetUnderlineOffset());
             writer.WriteInt32(bf->GetMaxWidth());
             
--- a/Source/Gorgon/UI.h	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/UI.h	Thu Sep 17 16:29:02 2020 +0300
@@ -7,8 +7,21 @@
     /// Initializes the UI system. Creates a simple widget template
     /// generator based on the primary monitor resolution. Density
     /// controls the size of the widgets. Increased density leads
-    /// to smaller widgets. 120 leads to 12pt/16px on a FullHD monitor.
-    /// This is a very relaxed and easy to use and read size.
-    void Initialize(std::string fontname = "", int density = 120, int min = 10);
+    /// to smaller widgets. 7.5 leads to 12pt/16px on a FullHD monitor.
+    /// This is a very relaxed and easy to use and read size. 10 is
+    /// more or less standard density.
+    void Initialize(std::string fontname = "", float density = 7.5, int min = 9);
+    
+    /// Initializes the UI system. Creates a simple widget template
+    /// generator based on the primary monitor resolution. Density
+    /// controls the size of the widgets. Increased density leads
+    /// to smaller widgets. 7.5 leads to 12pt/16px on a FullHD monitor.
+    /// This is a very relaxed and easy to use and read size. 10 is
+    /// more or less standard density.
+    inline void Initialize(float density, int min = 9) {
+        Initialize("", density, min);
+    }
+    
+    
     
 } }
--- a/Source/Gorgon/UI/Component.h	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/UI/Component.h	Thu Sep 17 16:29:02 2020 +0300
@@ -21,16 +21,6 @@
             return *temp;
         }
         
-        static void Swap(Component &left, Component &right) {
-            using std::swap;
-            
-            swap(left.temp     , right.temp     );
-            swap(left.location , right.location );
-            swap(left.size     , right.size     );
-            swap(left.innersize, right.innersize);
-        }
-        
-
         Geometry::Point location = {0, 0};
         
         Geometry::Size size = {-1, -1};
@@ -41,6 +31,8 @@
         //for horizontal this means right, for vertical this means bottom.
         bool anchorotherside = false;
         
+        bool anchtoparent = false;
+        
         bool reversed = false;
 
         int parent = -1;
--- a/Source/Gorgon/UI/ComponentStack.cpp	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/UI/ComponentStack.cpp	Thu Sep 17 16:29:02 2020 +0300
@@ -6,7 +6,7 @@
 
 #include "math.h"
 
-//NOTE if a transition does not exists, but it is in the stack, its completion will be counted as 100%
+//TODO:
 
 namespace Gorgon { namespace UI {
     
@@ -113,20 +113,27 @@
         //set our initial size
         Resize(size);
         
-        //search for emsize in textholders, use the first one found
+        //search for emsize in textholders, find the maximum ones to ensure 
+        //when the default is to be used as size, it will be able to contain
+        //any font within the stack.
         for(int i=0; i<temp.GetCount(); i++) {
             if(temp[i].GetType() == ComponentType::Textholder) {
                 const auto &th = dynamic_cast<const TextholderTemplate&>(temp[i]);
                 
                 if(th.IsReady()) {
-                    emsize = th.GetRenderer().GetEMSize();
-                    break;
+                    if(emsize < th.GetRenderer().GetEMSize())
+                        emsize = th.GetRenderer().GetEMSize();
+                    
+                    if(textheight < th.GetRenderer().GetHeight())
+                        textheight = th.GetRenderer().GetHeight();
+                    
+                    if(baseline < th.GetRenderer().GetBaseLine())
+                        baseline = (int)th.GetRenderer().GetBaseLine();
                 }
             }
         }
 
-        //this is here to simplify the update process, we are making sure that always is
-        //at the top of the stack
+        //Add all repeated components to the stack, ensuring always is at the top of the stack
         for(int i=0; i<temp.GetCount(); i++) {
             const auto &t = temp[i];
 
@@ -134,6 +141,13 @@
                 AddToStack(temp[i], false);
             }
         }
+        for(int i=0; i<temp.GetCount(); i++) {
+            const auto &t = temp[i];
+
+            if(t.GetRepeatMode() != ComponentTemplate::NoRepeat && t.GetCondition() == ComponentCondition::Always) {
+                AddToStack(temp[i], false);
+            }
+        }
     }
 
     ComponentStack::~ComponentStack() {
@@ -338,35 +352,33 @@
             //if an index does not contain condition in from field and an empty to field
             //it might still have it as a transition from the previous condition to our condition. 
             //In this case we should take this non-perfect fit.
-            if(!updatereq && hint != ComponentCondition::None) {
-                for(int i=0; i<temp.GetCount(); i++) {
-                    //do not use repeated components
-                    if(temp[i].GetRepeatMode() != ComponentTemplate::NoRepeat)
-                        continue;
-                    
-                    if(temp[i].GetCondition() == hint && temp[i].GetTargetCondition() == to) {
-                        updatereq = true;
-                        AddToStack(temp[i], false);
-                    }
+            for(int i=0; i<temp.GetCount(); i++) {
+                //do not use repeated components
+                if(temp[i].GetRepeatMode() != ComponentTemplate::NoRepeat)
+                    continue;
+                
+                if(temp[i].GetTargetCondition() == to && !indicesdone.count(temp[i].GetIndex()) && (hint == ComponentCondition::None || temp[i].GetCondition() == hint)) {
+                    updatereq = true;
+                    AddToStack(temp[i], false);
+                    indicesdone.insert(temp[i].GetIndex());
                 }
             }
             
             //once more, but this time reversed
-            if(!updatereq && hint != ComponentCondition::None) {
-                for(int i=0; i<temp.GetCount(); i++) {
-                    //do not use repeated components
-                    if(temp[i].GetRepeatMode() != ComponentTemplate::NoRepeat)
-                        continue;
-                    
-                    if(temp[i].GetCondition() == to && temp[i].GetTargetCondition() == hint) {
-                        updatereq = true;
-                        AddToStack(temp[i], true);
-                    }
+            for(int i=0; i<temp.GetCount(); i++) {
+                //do not use repeated components
+                if(temp[i].GetRepeatMode() != ComponentTemplate::NoRepeat)
+                    continue;
+                
+                if(temp[i].IsReversible() && temp[i].GetCondition() == to && !indicesdone.count(temp[i].GetIndex()) && (hint == ComponentCondition::None || temp[i].GetTargetCondition() == hint)) {
+                    updatereq = true;
+                    AddToStack(temp[i], true);
                 }
             }
         }
         //we are searching for transition
         else {
+            std::set<int> indicesdone;
             //perfect fit
             for(int i=0; i<temp.GetCount(); i++) {
                 //do not use repeated components
@@ -376,23 +388,19 @@
                 if(temp[i].GetCondition() == from && temp[i].GetTargetCondition() == to) {
                     updatereq = true;
                     AddToStack(temp[i], false);
-                    break;
+                    indicesdone.insert(temp[i].GetIndex());
                 }
             }
             
-            //not found
-            if(!updatereq) {
-                //search for reversed
-                for(int i=0; i<temp.GetCount(); i++) {
-                    //do not use repeated components
-                    if(temp[i].GetRepeatMode() != ComponentTemplate::NoRepeat)
-                        continue;
-                    
-                    if(temp[i].IsReversible() && temp[i].GetCondition() == to && temp[i].GetTargetCondition() == from) {
-                        updatereq = true;
-                        AddToStack(temp[i], true);
-                        break;
-                    }
+            //search for reversed
+            for(int i=0; i<temp.GetCount(); i++) {
+                //do not use repeated components
+                if(temp[i].GetRepeatMode() != ComponentTemplate::NoRepeat)
+                    continue;
+                
+                if(temp[i].IsReversible() && temp[i].GetCondition() == to && temp[i].GetTargetCondition() == from && !indicesdone.count(temp[i].GetIndex())) {
+                    updatereq = true;
+                    AddToStack(temp[i], true);
                 }
             }
         }
@@ -447,6 +455,20 @@
                             remove = temp.GetCondition() == from && temp.GetTargetCondition() == to;
                     }
                     
+                    //do not remove if this item can fill in for always and is the last item
+                    if(remove && stacksizes[temp.GetIndex()] <= 1) {
+                        if(temp.GetTargetCondition() == ComponentCondition::Always) {
+                            remove = false;
+                            comp.reversed = false;
+                            updatereq = true;
+                        }
+                        else if((temp.IsReversible() && temp.GetCondition() == ComponentCondition::Always)) {
+                            remove = false;
+                            comp.reversed = true;
+                            updatereq = true;
+                        }
+                    }
+                    
                     //if so
                     if(remove) {
                         //top of the stack
@@ -1321,6 +1343,10 @@
         if(!stacksizes[0]) 
             return -1;
 
+        //update needed?
+        if(updaterequired)
+            update();
+
         //this function will do a depth first search
         //this is the list that collects indexes that will be searched
         std::vector<std::pair<int, bool>> todo;
@@ -1446,10 +1472,46 @@
             }
         }
         
-        //otherwise return the global (first one found) emsize
+        //otherwise return the global (largest) emsize
         return emsize;
     }
 
+    int ComponentStack::getbaseline(const Component &comp) {
+        //if baseline exists, use it
+        if(comp.GetTemplate().GetBaseline() != 0)
+            return comp.GetTemplate().GetBaseline();
+        
+        //if the component is a text holder
+        if(comp.GetTemplate().GetType() == ComponentType::Textholder) {
+            const auto &th = dynamic_cast<const TextholderTemplate&>(comp.GetTemplate());
+            
+            //and ready
+            if(th.IsReady()) {
+                //return its own em size
+                return (int)th.GetRenderer().GetBaseLine();
+            }
+        }
+        
+        //otherwise return the global (first one found)
+        return baseline;
+    }
+
+    int ComponentStack::gettextheight(const Component &comp) {
+        //if the component is a text holder
+        if(comp.GetTemplate().GetType() == ComponentType::Textholder) {
+            const auto &th = dynamic_cast<const TextholderTemplate&>(comp.GetTemplate());
+            
+            //and ready
+            if(th.IsReady()) {
+                //return its own em size
+                return th.GetRenderer().GetHeight();
+            }
+        }
+        
+        //otherwise return the global (first one found)
+        return baseline;
+    }
+
     float ComponentStack::calculatevalue(const std::array<float, 4> &value, int channel, const Component &comp) const {
         //get the template
         const auto &temp = comp.GetTemplate();
@@ -1498,8 +1560,12 @@
             const auto valueordering = temp.GetValueOrdering();
             
             //transition is used as value 0
-            if(valueordering[channel] == 0)
-                v = float(cur) / dur; //normalize to the duration
+            if(valueordering[channel] == 0) {
+                if(dur == 0)
+                    v = 1;
+                else
+                    v = float(cur) / dur; //normalize to the duration
+            }
             
             //reverse if needed
             if(comp.reversed)
@@ -1639,14 +1705,22 @@
         return nullptr;
     }
     
-    void anchortoparent(Component &comp, const ComponentTemplate &temp, 
+    ///Determines the location of the component in relation to its parent. 
+    void ComponentStack::anchortoparent(Component &parent, Component &comp, const ComponentTemplate &temp, 
                         Geometry::Point offset, Geometry::Margin margin, Geometry::Size maxsize) {
         
+        //anchor on the parent
         Anchor pa = temp.GetContainerAnchor();
+        //component anchor
         Anchor ca = temp.GetMyAnchor();
         
+        //parent anchor point and component anchor point
         Geometry::Point pp, cp;
         
+        int bl = getbaseline(parent);
+        int th = gettextheight(parent);
+        
+        //determine parent anchor point
         switch(pa) {
             default:
             case Anchor::TopLeft:
@@ -1663,8 +1737,11 @@
                 
                 
             case Anchor::MiddleLeft:
+                pp = {margin.Left, margin.Top - margin.Bottom + maxsize.Height / 2};
+                break;
+                
             case Anchor::FirstBaselineLeft:
-                pp = {margin.Left, margin.Top - margin.Bottom + maxsize.Height / 2};
+                pp = {margin.Left, margin.Top + bl};
                 break;
                 
             case Anchor::MiddleCenter:
@@ -1672,14 +1749,19 @@
                 break;
                 
             case Anchor::MiddleRight:
-            case Anchor::FirstBaselineRight:
                 pp = { -margin.Right + maxsize.Width, margin.Top - margin.Bottom + maxsize.Height / 2};
                 break;
                 
+            case Anchor::FirstBaselineRight:
+                pp = {-margin.Right + maxsize.Width, margin.Top + bl};
+                break;
                 
             case Anchor::BottomLeft:
+                pp = {margin.Left, -margin.Bottom + maxsize.Height};
+                break;
+                
             case Anchor::LastBaselineLeft:
-                pp = {margin.Left, -margin.Bottom + maxsize.Height};
+                pp = {margin.Left, -margin.Bottom + maxsize.Height - th + bl};
                 break;
                 
             case Anchor::BottomCenter:
@@ -1687,44 +1769,22 @@
                 break;
                 
             case Anchor::BottomRight:
+                pp = { -margin.Right + maxsize.Width, -margin.Bottom + maxsize.Height};
+                break;
+                
             case Anchor::LastBaselineRight:
-                pp = { -margin.Right + maxsize.Width, -margin.Bottom + maxsize.Height};
+                pp = { -margin.Right + maxsize.Width, -margin.Bottom + maxsize.Height - th + bl};
                 break;
                 
         }
         
+        //component size
         auto csize = comp.size;
         
-        if(temp.GetType() == ComponentType::Textholder && 
-            (ca == Anchor::FirstBaselineLeft || ca == Anchor::FirstBaselineRight || ca == Anchor::LastBaselineLeft || ca == Anchor::LastBaselineRight)
-        ) {
-            const auto &th = dynamic_cast<const TextholderTemplate&>(temp);
-            
-            if(th.IsReady()) {
-                
-                switch(ca) {
-                    case Anchor::FirstBaselineLeft:
-                        cp = {-offset.X, int(-offset.Y-th.GetRenderer().GetGlyphRenderer().GetBaseLine())};
-                        break;
-                        
-                    case Anchor::FirstBaselineRight:
-                        cp = {-offset.X + csize.Width, int(-offset.Y-th.GetRenderer().GetGlyphRenderer().GetBaseLine())};
-                        break;
-                        
-                    case Anchor::LastBaselineLeft:
-                        cp = {-offset.X, int(offset.Y+th.GetRenderer().GetGlyphRenderer().GetBaseLine()-th.GetRenderer().GetGlyphRenderer().GetHeight()-csize.Height)};
-                        break;
-                        
-                    case Anchor::LastBaselineRight:
-                        cp = {-offset.X + csize.Width, int(offset.Y+th.GetRenderer().GetGlyphRenderer().GetBaseLine()-th.GetRenderer().GetGlyphRenderer().GetHeight()-csize.Height)};
-                        break;
-                    default: ;//to silence warnings
-                }
-                
-                ca = Anchor::None;
-            }
-        }
+        bl = getbaseline(comp);
+        th = gettextheight(comp);
         
+        //determine where the anchor point is on the component
         switch(ca) {
             default:
             case Anchor::TopLeft:
@@ -1741,8 +1801,11 @@
                 
                 
             case Anchor::MiddleLeft:
+                cp = {-offset.X, csize.Height / 2 - offset.Y};
+                break;
+                
             case Anchor::FirstBaselineLeft:
-                cp = {-offset.X, csize.Height / 2 - offset.Y};
+                cp = {-offset.X, bl - offset.Y};
                 break;
                 
             case Anchor::MiddleCenter:
@@ -1750,31 +1813,41 @@
                 break;
                 
             case Anchor::MiddleRight:
+                cp = { offset.X + csize.Width, csize.Height / 2 - offset.Y};
+                break;
+
             case Anchor::FirstBaselineRight:
-                cp = { offset.X + csize.Width, csize.Height / 2 - offset.Y};
+                cp = {offset.X + csize.Width, bl - offset.Y};
                 break;
                 
                 
             case Anchor::BottomLeft:
-            case Anchor::LastBaselineLeft:
                 cp = {-offset.X, csize.Height + offset.Y};
                 break;
-                
+
+            case Anchor::LastBaselineLeft:
+                cp = {-offset.X, csize.Height - th + bl + offset.Y};
+                break;
+
             case Anchor::BottomCenter:
                 cp = {-offset.X + csize.Width / 2, csize.Height + offset.Y};
                 break;
                 
             case Anchor::BottomRight:
+                cp = { offset.X + csize.Width, csize.Height + offset.Y};
+                break;
+                
             case Anchor::LastBaselineRight:
-                cp = { offset.X + csize.Width, csize.Height + offset.Y};
+                cp = {offset.X + csize.Width, csize.Height - th + bl + offset.Y};
                 break;
                 
         }
         
+        //calculate the final offset
         comp.location = pp - cp;
     }
 
-    void anchortoother(Component &comp, const ComponentTemplate &temp, 
+    void ComponentStack::anchortoother(Component &comp, const ComponentTemplate &temp, 
                         Geometry::Point offset, Geometry::Margin margin, Component &other, Graphics::Orientation orientation) {
         
         Anchor pa = temp.GetPreviousAnchor();
@@ -1793,35 +1866,8 @@
             margin.Left = margin.Right = 0;
         
         
-        if(other.GetTemplate().GetType() == ComponentType::Textholder && 
-            (ca == Anchor::FirstBaselineLeft || ca == Anchor::FirstBaselineRight || ca == Anchor::LastBaselineLeft || ca == Anchor::LastBaselineRight)
-        ) {
-            const auto &th = dynamic_cast<const TextholderTemplate&>(other.GetTemplate());
-            
-            if(th.IsReady()) {
-                
-                switch(ca) {
-                    case Anchor::FirstBaselineLeft:
-                        pp = {-margin.Right, int(-margin.Bottom+th.GetRenderer().GetGlyphRenderer().GetBaseLine())};
-                        break;
-                        
-                    case Anchor::FirstBaselineRight:
-                        pp = {margin.Left + asize.Width, int(-margin.Bottom+th.GetRenderer().GetGlyphRenderer().GetBaseLine())};
-                        break;
-                        
-                    case Anchor::LastBaselineLeft:
-                        cp = {-margin.Right, int(-margin.Bottom-th.GetRenderer().GetGlyphRenderer().GetBaseLine()+th.GetRenderer().GetGlyphRenderer().GetHeight()+asize.Height)};
-                        break;
-                        
-                    case Anchor::LastBaselineRight:
-                        cp = {margin.Left + asize.Width, int(-margin.Bottom-th.GetRenderer().GetGlyphRenderer().GetBaseLine()+th.GetRenderer().GetGlyphRenderer().GetHeight()+asize.Height)};
-                        break;
-                    default: ;//to silence warnings
-                }
-                
-                pa = Anchor::None;
-            }
-        }
+        int bl = getbaseline(other);
+        int th = gettextheight(other);
         
         switch(pa) {
             case Anchor::None: //do nothing
@@ -1841,8 +1887,16 @@
                 break;
                 
                 
+            case Anchor::FirstBaselineLeft:
+                pp = {-margin.Right, -margin.Bottom + bl};
+                break;
+                
+            case Anchor::FirstBaselineRight:
+                pp = {margin.Left + asize.Width, -margin.Bottom + bl};
+                break;
+                
+                
             case Anchor::MiddleLeft:
-            case Anchor::FirstBaselineLeft:
                 pp = {-margin.Right, asize.Height / 2};
                 break;
                 
@@ -1851,13 +1905,20 @@
                 break;
                 
             case Anchor::MiddleRight:
-            case Anchor::FirstBaselineRight:
                 pp = {margin.Left + asize.Width, asize.Height / 2};
                 break;
                 
                 
+            case Anchor::LastBaselineLeft:
+                pp = {-margin.Right, -margin.Bottom - bl + th + asize.Height};
+                break;
+                
+            case Anchor::LastBaselineRight:
+                pp = {margin.Left + asize.Width, -bl + th + asize.Height};
+                break;
+                
+                
             case Anchor::BottomLeft:
-            case Anchor::LastBaselineLeft:
                 pp = {-margin.Right, margin.Top + asize.Height};
                 break;
                 
@@ -1866,43 +1927,14 @@
                 break;
                 
             case Anchor::BottomRight:
-            case Anchor::LastBaselineRight:
                 pp = {margin.Left + asize.Width, margin.Top + asize.Height};
                 break;
-                
         }
         
         auto csize = comp.size;
         
-        if(temp.GetType() == ComponentType::Textholder && 
-            (ca == Anchor::FirstBaselineLeft || ca == Anchor::FirstBaselineRight || ca == Anchor::LastBaselineLeft || ca == Anchor::LastBaselineRight)
-        ) {
-            const auto &th = dynamic_cast<const TextholderTemplate&>(temp);
-            
-            if(th.IsReady()) {
-                
-                switch(ca) {
-                    case Anchor::FirstBaselineLeft:
-                        cp = {-offset.X, int(-offset.Y+th.GetRenderer().GetGlyphRenderer().GetBaseLine())};
-                        break;
-                        
-                    case Anchor::FirstBaselineRight:
-                        cp = {-offset.X + csize.Width, int(-offset.Y+th.GetRenderer().GetGlyphRenderer().GetBaseLine())};
-                        break;
-                        
-                    case Anchor::LastBaselineLeft:
-                        cp = {-offset.X, int(offset.Y+th.GetRenderer().GetGlyphRenderer().GetBaseLine()-th.GetRenderer().GetGlyphRenderer().GetHeight()-csize.Height)};
-                        break;
-                        
-                    case Anchor::LastBaselineRight:
-                        cp = {-offset.X + csize.Width, int(offset.Y+th.GetRenderer().GetGlyphRenderer().GetBaseLine()-th.GetRenderer().GetGlyphRenderer().GetHeight()-csize.Height)};
-                        break;
-                    default: ;//to silence warnings
-                }
-                
-                ca = Anchor::None;
-            }
-        }
+        bl = getbaseline(comp);
+        th = gettextheight(comp);
         
         switch(ca) {
             case Anchor::None: //do nothing
@@ -1922,8 +1954,16 @@
                 break;
                 
                 
+            case Anchor::FirstBaselineLeft:
+                cp = {-offset.X, -offset.Y + bl};
+                break;
+                
+            case Anchor::FirstBaselineRight:
+                cp = {-offset.X + csize.Width, -offset.Y + bl};
+                break;
+               
+                
             case Anchor::MiddleLeft:
-            case Anchor::FirstBaselineLeft:
                 cp = {-offset.X, csize.Height / 2 - offset.Y};
                 break;
                 
@@ -1932,13 +1972,20 @@
                 break;
                 
             case Anchor::MiddleRight:
-            case Anchor::FirstBaselineRight:
                 cp = { offset.X + csize.Width, csize.Height / 2 - offset.Y};
                 break;
                 
                 
+            case Anchor::LastBaselineLeft:
+                cp = {-offset.X, offset.Y + bl - th - csize.Height};
+                break;
+                
+            case Anchor::LastBaselineRight:
+                cp = {-offset.X + csize.Width, offset.Y + bl - th - csize.Height};
+                break;
+            
+                
             case Anchor::BottomLeft:
-            case Anchor::LastBaselineLeft:
                 cp = {-offset.X, csize.Height + offset.Y};
                 break;
                 
@@ -1947,7 +1994,6 @@
                 break;
                 
             case Anchor::BottomRight:
-            case Anchor::LastBaselineRight:
                 cp = { offset.X + csize.Width, csize.Height + offset.Y};
                 break;
                 
@@ -1957,738 +2003,1378 @@
     }
     
     void ComponentStack::update() {
-        if(!stacksizes[0]) return;
-        
+        //honor before update notification
         if(beforeupdate_fn)
             beforeupdate_fn();
-        
-        get(0).size = size;
-        get(0).location = {0,0};
-        get(0).parent = -1;
-        
-        //update repeat counts
-        for(auto &r : repeated) {
-            if(repeats.count(r.first->GetRepeatMode()))
-                r.second.resize(repeats[r.first->GetRepeatMode()].size(), Component(*r.first));
+
+        //clear everything
+        base.Clear();
+        for(auto &s : storage) {
+            if(s.second->layer)
+                s.second->layer->Hide();
         }
         
-        //calculate common emsize        
-        for(int i=0; i<indices; i++) {
-            if(stacksizes[i] > 0) {
-                if(get(i).GetTemplate().GetType() == ComponentType::Textholder) {
-                    const auto &th = dynamic_cast<const TextholderTemplate&>(get(i).GetTemplate());
-                    
-                    if(th.IsReady()) {
-                        emsize = th.GetRenderer().GetEMSize();
-                        break;
+        //update is no longer required, set beforehand so that
+        //if necessary can be set again during update to
+        //run update next frame
+        updaterequired = false;
+
+        //if root has something to be displayed
+        if(stacksizes[0]) {
+            //initial states
+            get(0).size = size;
+            get(0).location = {0,0};
+            get(0).parent = -1;
+            
+            //update the component storage for repeated components
+            for(auto &r : repeated) {
+                r.second.resize(
+                    repeats[r.first->GetRepeatMode()].size(), //size will be number of repeats
+                    Component(*r.first) //the components will be instantiated from the repeat template
+                );
+            }
+            
+            //search for emsize in textholders, find the maximum ones to ensure 
+            //when the default is to be used as size, it will be able to contain
+            //any font within the stack.
+            for(int i=0; i<indices; i++) {
+                if(stacksizes[i] > 0) {
+                    if(get(i).GetTemplate().GetType() == ComponentType::Textholder) {
+                        const auto &th = dynamic_cast<const TextholderTemplate&>(get(i).GetTemplate());
+                        
+                        if(th.IsReady()) {
+                            if(emsize < th.GetRenderer().GetEMSize())
+                                emsize = th.GetRenderer().GetEMSize();
+                            
+                            if(textheight < th.GetRenderer().GetHeight())
+                                textheight = th.GetRenderer().GetHeight();
+                            
+                            if(baseline < th.GetRenderer().GetBaseLine())
+                                baseline = (int)th.GetRenderer().GetBaseLine();
+                        }
                     }
                 }
             }
+            
+            //start the update from the root
+            update(get(0), value, -1);
         }
         
-        update(get(0));
-        
-        updaterequired = false;
+        //update is complete
+        if(update_fn)
+            update_fn();
         
-        base.Clear();
-        for(auto &s : storage) 
-            if(s.second->layer)
-                s.second->layer->Hide();
-            
-            if(update_fn)
-                update_fn();
-            
+        //if root has something to be displayed
+        if(stacksizes[0]) {
             //draw everything
-            render(get(0), base, {0,0});
+            render(get(0), base, {0,0}, value);
+        }
         
+        //this is called after the render
         if(render_fn)
             render_fn();
     }
     
+    int calculatemargin(int l, int r) {
+        if(l<0 || r<0)
+            return l+r;
+        else
+            return std::max(l, r);
+    }
+    
     //location depends on the container location
-    void ComponentStack::update(Component &parent) {
+    void ComponentStack::update(Component &parent, const std::array<float, 4> &value, int ind, int textwidth) {
+        //get the template
         const ComponentTemplate &ctemp = parent.GetTemplate();
 
-        if(ctemp.GetType() != ComponentType::Container) return;
+        //just in case
+        ASSERT(ctemp.GetType() == ComponentType::Container, "Only containers are needed to be updated") ;
 
+        //get the container
         const ContainerTemplate &cont = dynamic_cast<const ContainerTemplate&>(ctemp);
         
+        //we need the innersize to arrange components
         parent.innersize = parent.size - cont.GetBorderSize();
         
-        if(cont.GetHorizontalSizing() == cont.Fixed && parent.innersize.Width <= 0) return;
-        if(cont.GetVerticalSizing() == cont.Fixed && parent.innersize.Height <= 0) return;
+        //if sizing is fixed and the size is 0 and clipping is on, nothing can be displayed
+        if(cont.GetClip() && cont.GetHorizontalSizing() == cont.Fixed && parent.innersize.Width <= 0) 
+            return;
+        
+        //if sizing is fixed and the size is 0 and clipping is on, nothing can be displayed
+        if(cont.GetClip() && cont.GetVerticalSizing() == cont.Fixed && parent.innersize.Height <= 0) 
+            return;
+
+        //this function will loop through all components, including the repeats and calls the given
+        //function for each component
+        auto forallcomponents = [&](auto fn) {
+            for(int i=0; i<cont.GetCount(); i++) {
+                
+                //get the component index
+                int ci = cont[i];
+
+                //just in case
+                if(ci >= indices) continue;
+                
+                //if empty, this index is not currently available
+                //this is not an edge case
+                if(!stacksizes[ci]) continue;
+
+                //original component, used to distinguish from repeats
+                auto &comporg = get(cont[i]);
+
+                //original template
+                const auto &temporg = comporg.GetTemplate();
+                
+                int j = 0;
+                int jtarget = 1;
+                if(temporg.GetRepeatMode() != temporg.NoRepeat) {
+                    if(temporg.GetRepeatMode() == ctemp.GetRepeatMode()) {
+                        j = ind;
+                        jtarget = ind+1;
+                    }
+                    else {
+                        if(repeats.count(temporg.GetRepeatMode())) {
+                            jtarget = int(repeats[temporg.GetRepeatMode()].size());
+                        }
+                        else {
+                            jtarget = 0;
+                        }
+                    }
+                }
+                
+                while(j < jtarget) {
+                    Component *compptr;
+                    const ComponentTemplate *tempptr;
+                    
+                    //stores the reference value for this component
+                    const std::array<float, 4> *val;
 
-        bool requiresrepass = false;
-        bool repassdone = false;
+                    //if not to be repeated
+                    if(temporg.GetRepeatMode() == temporg.NoRepeat) {
+                        //use originals
+                        compptr = &comporg;
+                        tempptr = &temporg;
+                        val     = &value;
+                    }
+                    else {
+                        //get the repeated component
+                        compptr = &repeated[&temporg][j];
+                        
+                        //determine condition of the repeat, default is always
+                        ComponentCondition rc = ComponentCondition::Always;
+
+                        //if condition is set
+                        if(repeatconditions[temporg.GetRepeatMode()].count(j))
+                            rc = repeatconditions[temporg.GetRepeatMode()][j]; //use it
+
+                        //get the template depending on the condition
+                        tempptr = &get(ci, rc).GetTemplate();
+                        val     = &repeats[temporg.GetRepeatMode()][j];
+                    }
+                    
+                    //call the function
+                    fn(*compptr, *tempptr, *val, getemsize(*compptr), j);
+                    
+                    j++;
+                }
+            }
+        };
+        
+        //whether there is something requires a final pass
+        bool finalpass = false;
         
+        //middle pass is necessary if there is an grow/shrink only auto sized component
+        //which uses relative sizing
+        bool middlepass = false;
+        
+        //there are three stages, if there are relatively sized fixed components a final
+        //stage is necessary. Middle stage will be performed if there are grow/shrink only
+        //automatic sized components with relative sizing.
+        enum Stage {
+            initial,
+            middle,
+            final
+        } stage = initial;
+        
+        //space left after the absolutely sized components are placed, will be used for percentage based
+        //components
         int spaceleft = 0;
+        int textspaceleft = 0;
+        
+        //for easy access
+        auto ishor = cont.GetOrientation() == Graphics::Orientation::Horizontal;
 
+        //offsets will be stored here
+        std::map<Component *, Geometry::Point> offsets;
+
+        //reset all components
+        forallcomponents([&](Component &comp, const ComponentTemplate &temp, const std::array<float, 4> &val, int emsize, int) {
+            comp.location = {0, 0};
+            comp.size = {0, 0};
+            comp.innersize = {0, 0};
+            offsets[&comp] = {0, 0};
+        });
+
+        
 realign:
-        // first pass for size, second pass will cover the sizes that are percent based.
-        for(int i=0; i<cont.GetCount(); i++) {
-            
-            int ci = cont[i];
 
-            if(ci >= indices) continue;
-            if(!stacksizes[ci]) continue;
-
-
-            auto &compparent = get(cont[i]);
-
-            const auto &tempparent = compparent.GetTemplate();
+        // first operation is for size. Second pass will cover the sizes that are percent based.
+        forallcomponents([&](Component &comp, const ComponentTemplate &temp, const std::array<float, 4> &val, int emsize, int index) {
+            //set the index to be accessed later
+            comp.parent = cont.GetIndex();
             
             
-            for(int j = 0; tempparent.GetRepeatMode() == tempparent.NoRepeat ? j == 0 : repeats.count(tempparent.GetRepeatMode()) && j < repeats[tempparent.GetRepeatMode()].size(); j++) {
-                Component *compptr;
-                const ComponentTemplate *tempptr;
+            //***** Calculating maximum usable size.
+            
+            //axis that are not bound to other components
+            bool xfree = false, yfree = false;
+    
+            //calculate maximum size for non-oriented direction and oriented direction for absolutely placed
+            //components.
+            auto parentmargin = Convert(
+                temp.GetMargin(), parent.innersize, emsize
+                ).CombinePadding(
+                    Convert(cont.GetPadding(), parent.innersize, emsize)
+                ) + 
+                Convert(temp.GetIndent(), parent.innersize, emsize);
+            
+            auto maxsize = parent.innersize - parentmargin;
+            int  curtw   = (textwidth == -1 ? maxsize.Width : textwidth) - parentmargin.TotalX();
+            
+            //Determine sides that are free to move
+            if(temp.GetPositioning() != temp.Relative) {
+                xfree = yfree = true;
+            }
+            else if(!ishor) {
+                xfree = true;
+            }            
+            else {
+                yfree = true;
+            }
+
+            //***** Left/top, right/bottom to center/middle alignment
+            
+            //to be attached to left or right of the center reduces the effective size by half,
+            //this will work automatically with non-free direction
+            if(xfree && IsCenter(temp.GetContainerAnchor()) && !IsCenter(temp.GetMyAnchor())) {
+                maxsize.Width = 
+                    parent.innersize.Width/2 - 
+                    (IsLeft(temp.GetMyAnchor()) ? 
+                        parentmargin.Right : 
+                        parentmargin.Left
+                    )
+                ;
+            }
+
+            //if there is an offset in the free direction, reduce it from the maximum size
+            if(xfree) {
+                maxsize.Width -= offsets[&comp].X;
+            }
+            
+            //to be attached to top or bottom of the middle reduces the effective size by half,
+            //this will work automatically with non-free direction
+            if(yfree && IsMiddle(temp.GetContainerAnchor()) && !IsMiddle(temp.GetMyAnchor())) {
+                maxsize.Height = 
+                    parent.innersize.Height/2 - 
+                    (IsTop(temp.GetMyAnchor()) ? 
+                        parentmargin.Bottom : 
+                        parentmargin.Top
+                    )
+                ;
+            }
 
-                const std::array<float, 4> *val;
+            //if there is an offset in the free direction, reduce it from the maximum size
+            if(yfree) {
+                maxsize.Height -= offsets[&comp].Y;
+            }
+            
+            //****** Max size calculation (cont.)
+            
+            //defined size of the component
+            auto size = temp.GetSize();
+            
+            //ensure unused size will not cause a repass except for text component which requires width
+            //to calculate exact text size.
+            if(temp.GetType() != ComponentType::Textholder && temp.GetType() != ComponentType::Container) {
+                if(temp.GetHorizontalSizing() == ComponentTemplate::Automatic) {
+                    size.Width = 0; //will not be used, set to 0px
+                }
+                if(temp.GetVerticalSizing() == ComponentTemplate::Automatic) {
+                    size.Height = 0; //will not be used, set to 0px
+                }
+            }
+            
+            //if relatively positioned, then the space left will be used. Space left will not
+            //be available in the first pass.
+            if(!xfree) {
+                if(stage == middle) {
+                    //automatic cannot be relative, if sizing is not fixed and relative, this is the
+                    //stage where we determine if we are going to use content size in pixels or
+                    //relative size.
+                    if(temp.GetHorizontalSizing() != ComponentTemplate::Fixed && size.Width.IsRelative()) {
+                        maxsize.Width = spaceleft;
+                        curtw         = textspaceleft;
+                    }
+                    else {
+                        maxsize.Width = 0;
+                        curtw         = 0;
+                    }
+                }
+                else {
+                    maxsize.Width = spaceleft;
+                    curtw         = textspaceleft;
+                }
+                
+                if(size.Width.IsRelative())
+                    finalpass = true;
+                
+                if(comp.anchtoparent && IsCenter(temp.GetContainerAnchor()) && IsCenter(temp.GetMyAnchor())) {
+                    maxsize.Width *= 2;
+                    curtw         *= 2;
+                }
+            }
+            
+            if(!yfree) {
+                if(stage == middle) {
+                    //automatic cannot be relative, if sizing is not fixed and relative, this is the
+                    //stage where we determine if we are going to use content size in pixels or
+                    //relative size.
+                    if(temp.GetVerticalSizing() != ComponentTemplate::Fixed && size.Height.IsRelative()) {
+                        maxsize.Height = spaceleft;
+                    }
+                    else {
+                        maxsize.Height = 0;
+                    }
+                }
+                else {
+                    maxsize.Height = spaceleft;
+                }
 
-                if(tempparent.GetRepeatMode() == tempparent.NoRepeat) {
-                    compptr = &compparent;
-                    tempptr = &tempparent;
-                    val     = &value;
+                if(size.Height.IsRelative())
+                    finalpass = true;
+                
+                if(comp.anchtoparent && IsMiddle(temp.GetContainerAnchor()) && IsMiddle(temp.GetMyAnchor())) {
+                    maxsize.Width *= 2;
+                }
+            }
+            
+            
+            //****** Value modification
+            
+            //determine the channel each dimension is affected by, -1: value has no effect
+            int widthch = -1, heightch = -1;
+            if(temp.GetValueModification() == temp.ModifySize) {
+                if(NumberOfSetBits(temp.GetValueSource()) == 1) {
+                    (ishor ? widthch : heightch) = 0;
                 }
                 else {
-                    compptr = &repeated[&tempparent][j];
-                    ComponentCondition rc = ComponentCondition::Always;
+                    widthch  = 0;
+                    heightch = 1;
+                }
+            }
+            else if(temp.GetValueModification() == temp.ModifyWidth) {
+                widthch = 0;
+            }
+            else if(temp.GetValueModification() == temp.ModifyHeight) {
+                heightch = 0;
+            }
+            
+            
+            //****** Tag size
+            
+            //if tag size is given, use it additively to the size,
+            //restricting the maximum size as necessary
+            Geometry::Size tagsize = {0, 0};
+            if(tagsizes.count(temp.GetTag())) {
+                tagsize = tagsizes[temp.GetTag()];
+            }
+            
+            
+            //***** Pixel conversion
+            
+            //this will convert width to pixels
+            if(widthch == -1) { //value channel is not in effect
+                comp.size.Width = size.Width(maxsize.Width - tagsize.Width, emsize) + tagsize.Width;
+                curtw = size.Width(curtw - tagsize.Width, emsize) + tagsize.Width;
+            }
+            else {//calculate and use value channel
+                //original width will be used as minimum size
+                auto min = size.Width(maxsize.Width, emsize) + tagsize.Width;
+                
+                //calculate value and use it as basis point as relative size, then covert to pixels
+                comp.size.Width = 
+                    Dimension{
+                        int(calculatevalue(val, widthch, comp)*10000), Dimension::BasisPoint
+                    } (maxsize.Width - min, emsize)
+                    + min;
+                    
+                min = size.Width(curtw, emsize) + tagsize.Width;
+                curtw = 
+                    Dimension{
+                        int(calculatevalue(val, widthch, comp)*10000), Dimension::BasisPoint
+                    } (curtw - min, emsize)
+                    + min;
+            }
+            
+            //this will convert height to pixels
+            if(heightch == -1) { //value channel is not in effect
+                comp.size.Height = size.Height(maxsize.Height - tagsize.Height, emsize) + tagsize.Height;
+            }
+            else {//calculate and use value channel
+                //original height will be used as minimum size
+                auto min = size.Height(maxsize.Height, emsize) + tagsize.Height;
+                
+                //calculate value and use it as basis point as relative size, then covert to pixels
+                comp.size.Height = 
+                    Dimension{
+                        int(calculatevalue(val, heightch, comp)*10000), Dimension::BasisPoint
+                    } (maxsize.Height - min, emsize)
+                    + min;
+            }
+            
+            if(comp.size.Width < 0)
+                comp.size.Width = 0;
+            
+            if(comp.size.Height < 0)
+                comp.size.Height = 0;
+            
+            
+            //**** Automatic sizing
+            if((temp.GetHorizontalSizing() != temp.Fixed || temp.GetVerticalSizing() != temp.Fixed)
+            ) {
+                auto &st = *storage[&temp];
+
+                //original size, will be used for grow/shrink only
+                auto orgsize = comp.size;
+
+                //if the component is a container, it should be updated with size of 0.
+                if(temp.GetType() == ComponentType::Container) {
+                    if(temp.GetSize().Width.IsRelative() || temp.GetSize().Height.IsRelative())
+                        finalpass = true;
 
-                    if(repeatconditions[tempparent.GetRepeatMode()].count(j))
-                        rc = repeatconditions[tempparent.GetRepeatMode()][j];
+                    if(!size.Width.IsRelative() || stage==final) {
+                        int textwidth = -1;
+                        
+                        //set the dimensions that are not fixed to 0.
+                        if(temp.GetHorizontalSizing() != ComponentTemplate::Fixed) {
+                            textwidth = comp.size.Width;
+                            comp.size.Width = 0;
+                        }
+                        
+                        if(temp.GetVerticalSizing() != ComponentTemplate::Fixed)
+                            comp.size.Height = 0;
+                        
+                        //do an update
+                        update(comp, val, index, textwidth);
+                    }
+                }
+                else if(temp.GetType() == ComponentType::Graphics) {
+                    if(imagedata.Exists(temp.GetDataEffect())) {
+                        auto rectangular = dynamic_cast<const Graphics::RectangularDrawable*>(&imagedata[temp.GetDataEffect()]);
+                        
+                        if(rectangular) {
+                            comp.size = rectangular->GetSize();
+                        }
+                    }
+                    else if(st.primary) {
+                        auto rectangular = dynamic_cast<const Graphics::RectangularDrawable*>(st.primary);
+                        
+                        //if we have a rectangular graphic, get its size
+                        if(rectangular)
+                            comp.size = rectangular->GetSize();
+                        else
+                            comp.size = {0, 0};
+                    }
+                }
+                else if(temp.GetType() == ComponentType::Textholder) {
+                    if(temp.GetSize().Width.IsRelative() || temp.GetSize().Height.IsRelative())
+                        finalpass = true;
+
+                    if(!size.Width.IsRelative() || stage==final) {
+                        const auto &th = dynamic_cast<const TextholderTemplate&>(temp);
+                        
+                        //get width for word wrapping
+                        auto width = textwidth == -1 ? comp.size.Width : curtw;
+                        comp.size = {0, 0};
 
-                    tempptr = &get(ci, rc).GetTemplate();
-                    val     = &repeats[tempparent.GetRepeatMode()][j];
+                        //if there is a renderer ready
+                        if(th.IsReady()) {
+                            std::string text;
+                            auto d = temp.GetDataEffect();
+                            
+                            //try to get the data
+                            if(stringdata.count(d)) {
+                                text = stringdata[d];
+                            }
+                            //try to convert value to data
+                            else if(valuetotext && d >= ComponentTemplate::AutoStart && d <= ComponentTemplate::AutoEnd) {
+                                text = valuetotext(temp.GetIndex(), d, value);
+                            }
+                            else {
+                                text = th.GetText();
+                            }
+                            
+                            //if there is some text data
+                            if(text != "") {
+                                //if not to be wrapped
+                                if(tagnowrap.count(temp.GetTag()) || width == 0)
+                                    comp.size = th.GetRenderer().GetSize(text);
+                                else
+                                    comp.size = th.GetRenderer().GetSize(text, width);
+                            }
+                        }
+                    }
+                }
+                else if(temp.GetType() == ComponentType::Placeholder) {
+                    const auto &ph = dynamic_cast<const PlaceholderTemplate&>(temp);
+
+                    //if there is an image data use it
+                    if(imagedata.Exists(ph.GetDataEffect())) {
+                        auto rectangular = dynamic_cast<const Graphics::RectangularDrawable*>(&imagedata[ph.GetDataEffect()]);
+                        
+                        if(rectangular) {
+                            comp.size = rectangular->GetSize();
+                        }
+                    }
+                    //otherwise check if there is a substack for this placeholder
+                    else if(substacks.Exists(&temp)) {
+                        //use substack size, as of now, this will only display
+                        //either set size, or initially set size. Once stacks can
+                        //automatically size themselves, then this will be more useful
+                        comp.size = substacks[&temp].GetSize();
+                    }
+                    else {
+                        //nothing found, reset to zero
+                        comp.size = {0, 0};
+                    }
+                }
+                
+                //automatic sizing restrictions
+                //TODO: if relative size turns to content size, this should adjust maximum usable width
+                if(temp.GetHorizontalSizing() == ComponentTemplate::GrowOnly) {
+                    if(comp.size.Width < orgsize.Width && orgsize.Width > 0)
+                        comp.size.Width = orgsize.Width;
+                }
+                else if(temp.GetHorizontalSizing() == ComponentTemplate::ShrinkOnly) {
+                    if(comp.size.Width > orgsize.Width && orgsize.Width > 0)
+                        comp.size.Width = orgsize.Width;
+                }
+
+                if(temp.GetVerticalSizing() == ComponentTemplate::GrowOnly) {
+                    if(comp.size.Height < orgsize.Height && orgsize.Height > 0)
+                        comp.size.Height = orgsize.Height;
+                }
+                else if(temp.GetVerticalSizing() == ComponentTemplate::ShrinkOnly) {
+                    if(comp.size.Height > orgsize.Height && orgsize.Height > 0)
+                        comp.size.Height = orgsize.Height;
                 }
 
-                auto &comp = *compptr;
-                const auto &temp = *tempptr;
+                //ensure size can never be negative.
+                if(comp.size.Width < 0)
+                    comp.size.Width = 0;
+                if(comp.size.Height < 0)
+                    comp.size.Height = 0;
+            }
+        }); //for size
 
-                comp.parent = cont.GetIndex();
+        //anchor compontents for left/top (start) and right/bottom (end)
+        Component *startanch = nullptr, *endanch = nullptr;
 
-                //check if textholder and if so use emsize from the font
-                int emsize = getemsize(comp);
-        
-                auto parentmargin = Convert(
-                        temp.GetMargin(), parent.innersize, emsize
-                    ).CombinePadding(
-                        Convert(cont.GetPadding(), parent.size, emsize)
-                    ) + 
-                    Convert(temp.GetIndent(), parent.innersize, emsize);
+        //Positioning stage
+        forallcomponents([&](Component &comp, const ComponentTemplate &temp, const std::array<float, 4> &val, int emsize, int) {
+            //check anchor object by observing temp.GetPreviousAnchor and direction
+            Component *anch = nullptr;
+            
+            //**** Find anchor
             
-                auto maxsize = parent.innersize - parentmargin;
-            
-                if(temp.GetPositioning() != temp.Absolute && temp.GetPositioning() != temp.PolarAbsolute) {
-                    if(cont.GetOrientation() == Graphics::Orientation::Horizontal) {
-                        maxsize.Width = spaceleft - parentmargin.TotalX();
-                        if(maxsize.Width < 0) 
-                            maxsize.Width = 0;
+            //if absolute, nothing to anchor to but to parent
+            if(temp.GetPositioning() == temp.Relative && temp.GetPreviousAnchor() != Anchor::None) {
+                if(ishor) {
+                    if(
+                        IsRight(temp.GetMyAnchor()) && ( //if my anchor is on the right
+                            IsLeft(temp.GetPreviousAnchor()) || //and previous anchor exists and on the left
+                            (temp.GetPreviousAnchor() == Anchor::None && IsRight(temp.GetContainerAnchor())) //or parent anchor is on the right
+                        ) 
+                    ) {
+                        anch = endanch;
+                        comp.anchorotherside = true;
+                    }
+                    else {
+                        anch = startanch;
+                    }
+                }
+                else {
+                    if(
+                        IsBottom(temp.GetMyAnchor()) && ( //if my anchor is on bottom
+                            IsTop(temp.GetPreviousAnchor()) || //and previous anchor exists and on the top
+                            (temp.GetPreviousAnchor() == Anchor::None && IsBottom(temp.GetContainerAnchor())) //or parent anchor is on the bottom
+                        ) 
+                    ) {
+                        anch = endanch;
+                        comp.anchorotherside = true;
                     }
                     else {
-                        maxsize.Height = spaceleft - parentmargin.TotalY();
-                        if(maxsize.Height < 0) 
-                            maxsize.Height = 0;
+                        anch = startanch;
                     }
                 }
-            
-                auto size = temp.GetSize();
+            }
             
             
-                if(temp.GetValueModification() == temp.ModifySize) {
-                    if(NumberOfSetBits(temp.GetValueSource()) == 1) {
-                        if(cont.GetOrientation() == Graphics::Orientation::Horizontal) {
-                            size = {
-                                {int(calculatevalue(*val, 0, comp)*10000), Dimension::BasisPoint}, 
-                                size.Height
-                            };
+           
+            //***** Calculating maximum usable size.
+            
+            //axis that are not bound to other components
+            bool xfree = false, yfree = false;
+    
+            //calculate maximum size for non-oriented direction and oriented direction for absolutely placed
+            //components.
+            auto parentmargin = Convert(
+                temp.GetMargin(), parent.innersize, emsize
+                ).CombinePadding(
+                    Convert(cont.GetPadding(), parent.innersize, emsize)
+                ) + 
+                Convert(temp.GetIndent(), parent.innersize, emsize);
+            
+            auto maxsize = parent.innersize - parentmargin;
+            
+            //Determine sides that are free to move
+            if(temp.GetPositioning() != temp.Relative) {
+                xfree = yfree = true;
+            }
+            else if(!ishor) {
+                xfree = true;
+            }            
+            else {
+                yfree = true;
+            }
+
+            //defined position
+            auto pos = temp.GetPosition();
+
+
+
+            //if relatively positioned, then the space left will be used. Space left will not
+            //be available in the first pass.
+            if(!xfree) {
+                //there is no middle stage for position pass
+                if(stage == middle) {
+                    maxsize.Width = 0;
+                }
+                else {
+                    maxsize.Width = spaceleft;
+                }
+
+                if(pos.X.IsRelative())
+                    finalpass = true;
+            }
+
+            if(!yfree) {
+                //there is no middle stage for position pass
+                if(stage == middle) {
+                    maxsize.Height = 0;
+                }
+                else {
+                    maxsize.Height = spaceleft;
+                }
+
+                if(pos.Y.IsRelative())
+                    finalpass = true;
+            }
+
+            //position dictated by tag
+            Geometry::Point tagpos = {0, 0};
+
+            //tag location
+            if(taglocations.count(temp.GetTag())) {
+                tagpos = taglocations[temp.GetTag()];
+            }
+
+            //margin calculation. 
+            Geometry::Margin margin;
+
+            //if to be anchored
+            if(anch) {
+                //use the margin from the component to be anchored. All sides are calculated, one will be used.
+                margin = Convert(temp.GetMargin(), parent.innersize, emsize).CombineMargins(Convert(anch->GetTemplate().GetMargin(), parent.innersize, getemsize(*anch)));
+
+                //revert back the unoriented direction
+                if(ishor) {
+                    margin.Top = parentmargin.Top;
+                    margin.Bottom = parentmargin.Bottom;
+                }
+                else {
+                    margin.Left = parentmargin.Left;
+                    margin.Right = parentmargin.Right;
+                }
+            }
+            else {
+                //no other component to anchor to, so anchor to parent
+                margin = parentmargin;
+            }
+
+            
+
+            //**** Value modification
+
+            //determine the channel each dimension is affected by, -1: value has no effect
+            int xch = -1, ych = -1;
+            if(temp.GetValueModification() == temp.ModifyPosition) {
+                if(NumberOfSetBits(temp.GetValueSource()) == 1) {
+                    (ishor ? xch : ych) = 0;
+                }
+                else {
+                    xch = 0;
+                    ych = 1;
+                }
+            }
+            else if(temp.GetValueModification() == temp.ModifyX) {
+                xch = 0;
+            }
+            else if(temp.GetValueModification() == temp.ModifyY) {
+                ych = 0;
+            }
+
+            //****** Pixel conversion
+            
+            if(temp.GetPositioning() == temp.PolarAbsolute) {
+                //center of parent
+                auto pcenter = Geometry::Pointf(
+                    cont.GetCenter().X.CalculateFloat((float)maxsize.Width, (float)emsize), 
+                    cont.GetCenter().Y.CalculateFloat((float)maxsize.Height, (float)emsize));
+
+                //center of object
+                auto center  = Geometry::Pointf(
+                    temp.GetCenter().X.CalculateFloat((float)comp.size.Width, (float)emsize), 
+                    temp.GetCenter().Y.CalculateFloat((float)comp.size.Height, (float)emsize)
+                );
+
+                pcenter += parentmargin.TopLeft();
+
+                //anchor point of the object.
+                auto panch = temp.GetContainerAnchor();
+
+                //maximum x and y axis radii
+                float xrad = 0, yrad = 0;
+
+                //determine xrad and xoff according to the anchor point
+                if(IsLeft(panch)) {
+                    xrad = maxsize.Width - pcenter.X - comp.size.Width;
+                }
+                else if(IsCenter(panch)) {
+                    xrad = std::min(pcenter.X - center.X, maxsize.Width - pcenter.X - (comp.size.Width - center.X));
+                }
+                else {
+                    xrad = pcenter.X - comp.size.Width;
+                }
+                
+                //determine yrad and yoff according to the anchor point
+                if(IsTop(panch)) {
+                    yrad = maxsize.Height - pcenter.Y - comp.size.Height;
+                }
+                else if(IsMiddle(panch)) {
+                    yrad = std::min(pcenter.Y - center.Y, maxsize.Height - pcenter.Y - (comp.size.Height - center.Y));
+                }
+                else {
+                    yrad = pcenter.Y - comp.size.Height;
+                }
+                
+                int maxang = 360, stang = 0;
+                
+                switch(panch) {
+                case Anchor::TopLeft:
+                case Anchor::FirstBaselineLeft:
+                    maxang = 90;
+                    stang = 270;
+                    break;
+                case Anchor::TopCenter:
+                    maxang = 180;
+                    stang = 180;
+                    break;
+                case Anchor::TopRight:
+                case Anchor::FirstBaselineRight:
+                    maxang = 90;
+                    stang = 180;
+                    break;
+                case Anchor::MiddleLeft:
+                    maxang = 180;
+                    stang = 270;
+                    break;
+                default:
+                    maxang = 360;
+                    stang = 0;
+                    break;
+                case Anchor::MiddleRight:
+                    maxang = 180;
+                    stang = 90;
+                    break;
+                case Anchor::BottomLeft:
+                case Anchor::LastBaselineLeft:
+                    maxang = 90;
+                    stang = 0;
+                    break;
+                case Anchor::BottomCenter:
+                    maxang = 180;
+                    stang = 0;
+                    break;
+                case Anchor::BottomRight:
+                case Anchor::LastBaselineRight:
+                    maxang = 90;
+                    stang = 90;
+                    break;
+                }
+
+                //calculate radius
+                auto r = pos.X.CalculateFloat(std::min(xrad, yrad), (float)emsize);
+                
+                auto a = pos.Y.CalculateFloat(float(maxang), 45) + stang; //em size for angle is 45
+                
+                //convert to radians
+                a *= -PI / 180.0f;
+
+                comp.location = {int(std::round(r * cos(a) + pcenter.X - center.X)), int(std::round(r * sin(a) + pcenter.Y - center.Y))};
+            }
+            else {
+                bool sliding = temp.GetPositioning() == temp.AbsoluteSliding;
+
+                Geometry::Point offset;
+
+                //this will convert x to pixels
+                if(xch == -1) { //value channel is not in effect
+                    offset.X = pos.X(
+                        maxsize.Width - (sliding ? tagpos.X + comp.size.Width : 0), emsize
+                    ) + tagpos.X;
+                }
+                else {//calculate and use value channel
+                    //original width will be used as minimum size
+                    offset.X = pos.X(
+                        maxsize.Width - (sliding ? tagpos.X + comp.size.Width : 0), emsize
+                    ) + tagpos.X;
+
+                    //calculate value and use it as basis point as relative size, then covert to pixels
+                    offset.X +=
+                        Dimension{
+                            int(calculatevalue(val, xch, comp)*10000), Dimension::BasisPoint
+                    } (maxsize.Width - (sliding ? offset.X + comp.size.Width : 0), emsize);
+                }
+
+                //this will convert y to pixels
+                if(ych == -1) { //value channel is not in effect
+                    offset.Y = pos.Y(
+                        maxsize.Height - (sliding ? tagpos.Y + comp.size.Height : 0), emsize
+                    ) + tagpos.Y;
+                }
+                else {//calculate and use value channel
+                    //original width will be used as minimum size
+                    offset.Y = pos.Y(
+                        maxsize.Height - (sliding ? tagpos.Y + comp.size.Height : 0), emsize
+                    ) + tagpos.Y;
+
+                    //calculate value and use it as basis point as relative size, then covert to piyels
+                    offset.Y +=
+                        Dimension{
+                            int(calculatevalue(val, ych, comp)*10000), Dimension::BasisPoint
+                    } (maxsize.Height - (sliding ? offset.Y + comp.size.Height : 0), emsize);
+                }
+
+                offsets[&comp] = offset;
+        
+                //if there is an offset in a relatively sized sub-component, final pass might be necessary.
+                if(
+                    (offset.X != 0 && temp.GetSize().Width.IsRelative()) ||
+                    (offset.Y != 0 && temp.GetSize().Height.IsRelative())
+                    )
+                    finalpass = true;
+
+                if(taglocations.count(temp.GetTag())) {
+                    comp.location = offset;
+                    comp.anchtoparent = true;
+                }
+                else if(anch) {
+                    anchortoother(comp, temp, offset, margin, *anch, cont.GetOrientation());
+                    comp.anchtoparent = false;
+                }
+                else {
+                    anchortoparent(parent, comp, temp, offset, margin, parent.innersize);
+                    comp.anchtoparent = true;
+                }
+            }
+
+
+            //Which anchor side is to be changed
+            if(temp.GetPositioning() == temp.Relative) {
+                if(cont.GetOrientation() == Graphics::Orientation::Horizontal) {
+                    if(IsRight(temp.GetMyAnchor())) {
+                        endanch = &comp;
+                    }
+                    else {
+                        startanch = &comp;
+                    }
+                }
+                else {
+                    if(IsBottom(temp.GetMyAnchor())) {
+                        endanch = &comp;
+                    }
+                    else {
+                        startanch = &comp;
+                    }
+                }
+            }
+        }); //position pass
+        
+        if((finalpass && stage != final) || (middlepass && stage == initial)) {
+            int startused = 0, endused = 0;
+            
+            Component *startmost = nullptr, *endmost = nullptr;
+            
+            //go through the components to see where they end
+            forallcomponents([&](Component &comp, const ComponentTemplate &temp, const std::array<float, 4> &, int, int ind) {
+                //only relatively sided components take up space
+                if(temp.GetPositioning() == temp.Relative) {
+                    //the values will be overwritten successively to find the last ones
+                    if(ishor) {
+                        if(comp.anchorotherside) { //anchored to right
+                            startmost = &comp;
                         }
-                        else {
-                            size = {
-                                size.Width, 
-                                {int(calculatevalue(*val, 0, comp)*10000), Dimension::BasisPoint}
-                            };
+                        else { //to left
+                            startmost = &comp;
                         }
                     }
                     else {
-                        size ={
-                            {int(calculatevalue(*val, 0, comp)*10000), Dimension::BasisPoint}, 
-                            {int(calculatevalue(*val, 1, comp)*10000), Dimension::BasisPoint}
-                        };
-                    }
-                }
-                else if(temp.GetValueModification() == temp.ModifyWidth) {
-                    size ={{int(calculatevalue(*val, 0, comp)*10000), Dimension::BasisPoint}, size.Height};
-                }
-                else if(temp.GetValueModification() == temp.ModifyHeight) {
-                    size ={size.Width, {int(calculatevalue(*val, 0, comp)*10000), Dimension::BasisPoint}};
-                }
-                
-                if(temp.GetValueModification() == temp.ModifySize && NumberOfSetBits(temp.GetValueSource()) > 1) {
-                    auto minimum = Convert(temp.GetSize(), maxsize, emsize);
-                    
-                    comp.size = Convert(size, maxsize - minimum, emsize) + minimum;
-                }
-                else if(temp.GetValueModification() == temp.ModifyWidth || (temp.GetValueModification() == temp.ModifySize && cont.GetOrientation() == Graphics::Orientation::Horizontal)) {
-                    auto minimum = Convert(temp.GetSize(), maxsize, emsize);
-                                        
-                    comp.size = Convert(size, {maxsize.Width - minimum.Width, maxsize.Height}, emsize) + Geometry::Size(minimum.Width, 0);
-                }
-                else if(temp.GetValueModification() == temp.ModifyHeight || (temp.GetValueModification() == temp.ModifySize && cont.GetOrientation() == Graphics::Orientation::Vertical)) {
-                    auto minimum = Convert(temp.GetSize(), maxsize, emsize);
-                                        
-                    comp.size = Convert(size, {maxsize.Width, maxsize.Height - minimum.Height}, emsize) + Geometry::Size(0, minimum.Height);
-                }
-                else if(tagsizes.count(temp.GetTag())) {
-                    comp.size = tagsizes[temp.GetTag()];
-                }
-                else {
-                    comp.size = Convert(size, maxsize, emsize);
-                }
-                
-                if(
-                    (temp.GetPositioning() == temp.Relative || temp.GetPositioning() == temp.AbsoluteSliding) && 
-                    (
-                        (cont.GetOrientation() == Graphics::Orientation::Horizontal && 
-                            (size.Width.GetUnit() == Dimension::Percent || size.Width.GetUnit() == Dimension::BasisPoint)) ||
-                        (cont.GetOrientation() == Graphics::Orientation::Vertical && 
-                            (size.Height.GetUnit() == Dimension::Percent || size.Height.GetUnit() == Dimension::BasisPoint))
-                    )
-                )
-                    requiresrepass = true;
-                
-                if(!(tagsizes.count(temp.GetTag())) && 
-                    (temp.GetHorizontalSizing() != temp.Fixed || temp.GetVerticalSizing() != temp.Fixed) &&
-                   !(temp.GetValueModification() == temp.ModifySize &&  NumberOfSetBits(temp.GetValueSource()) > 1)
-                ) {
-                    auto &st = *storage[&temp];
-
-                    auto orgsize = comp.size;
-
-                    if(temp.GetType() == ComponentType::Container) {
-                        comp.size = {0, 0};
-                        update(comp);
-                    }
-                    else if(temp.GetType() == ComponentType::Graphics) {
-                        if(st.primary) {
-                            auto rectangular = dynamic_cast<const Graphics::RectangularDrawable*>(st.primary);
-                            if(rectangular)
-                                comp.size = rectangular->GetSize() + dynamic_cast<const GraphicsTemplate&>(temp).GetPadding();
-                        }
-                        else {
-                            comp.size = dynamic_cast<const GraphicsTemplate&>(temp).GetPadding().Total();
-                        }
-                    }
-                    else if(temp.GetType() == ComponentType::Textholder) {
-                        const auto &th = dynamic_cast<const TextholderTemplate&>(temp);
-
-                        if(th.IsReady() && stringdata[temp.GetDataEffect()] != "") {
-                            auto s = size.Width(maxsize.Width, emsize);
-                            
-                            if(tagnowrap.count(temp.GetTag()))
-                                s = 0;
-
-                            if(s > 0)
-                                comp.size = th.GetRenderer().GetSize(stringdata[temp.GetDataEffect()], s);
-                            else
-                                comp.size = th.GetRenderer().GetSize(stringdata[temp.GetDataEffect()]);
-
-                        }
-                    }
-                    else if(temp.GetType() == ComponentType::Placeholder) {
-                        const auto &ph = dynamic_cast<const PlaceholderTemplate&>(temp);
-
-                        if(imagedata.Exists(ph.GetDataEffect())) {
-                            auto rectangular = dynamic_cast<const Graphics::RectangularDrawable*>(&imagedata[ph.GetDataEffect()]);
-                            if(rectangular) {
-                                comp.size = rectangular->GetSize();
-                            }
-                        }
-                        else {
-                            comp.size = {0, 0};
+                        if(comp.anchorotherside) { //to bottom
+                            endmost = &comp;
                         }
-                    }
-
-                    if(temp.GetHorizontalSizing() == ComponentTemplate::GrowOnly) {
-                        if(comp.size.Width < orgsize.Width)
-                            comp.size.Width = orgsize.Width;
-                    }
-                    else if(temp.GetHorizontalSizing() == ComponentTemplate::ShrinkOnly) {
-                        if(comp.size.Width > orgsize.Width)
-                            comp.size.Width = orgsize.Width;
-                    }
-
-                    if(temp.GetHorizontalSizing() == ComponentTemplate::GrowOnly) {
-                        if(comp.size.Height < orgsize.Height)
-                            comp.size.Height = orgsize.Height;
-                    }
-                    else if(temp.GetHorizontalSizing() == ComponentTemplate::ShrinkOnly) {
-                        if(comp.size.Height > orgsize.Height)
-                            comp.size.Height = orgsize.Height;
-                    }
-
-                    if(temp.GetValueModification() == temp.ModifySize) {
-                        if(cont.GetOrientation() == Graphics::Orientation::Horizontal)
-                            comp.size.Width = orgsize.Width;
-                        else
-                            comp.size.Height = orgsize.Height;
-                    }
-                    else if(temp.GetValueModification() == temp.ModifyWidth) {
-                        comp.size.Width = orgsize.Width;
-                    }
-                    else if(temp.GetValueModification() == temp.ModifyHeight) {
-                        comp.size.Height = orgsize.Height;
-                    }
-
-                    if(
-                        (cont.GetOrientation() == Graphics::Orientation::Horizontal &&
-                        (size.Width.GetUnit() == Dimension::Percent || size.Width.GetUnit() == Dimension::BasisPoint)) ||
-                        (cont.GetOrientation() == Graphics::Orientation::Vertical &&
-                        (size.Height.GetUnit() == Dimension::Percent || size.Height.GetUnit() == Dimension::BasisPoint))
-                        )
-                    {
-                        if(maxsize.Width == 0)
-                            comp.size.Width = 0;
-                        if(maxsize.Height == 0)
-                            comp.size.Height = 0;
-                    }
-
-                    if(comp.size.Width < 0)
-                        comp.size.Width = 0;
-                    if(comp.size.Height < 0)
-                        comp.size.Height = 0;
-                }
-            }
-        }
-
-        Component *prev = nullptr, *next = nullptr;
-
-        //second pass will align everything
-        for(int i=0; i<cont.GetCount(); i++) {
-            
-            int ci = cont[i];
-
-            if(ci >= indices) continue;
-            if(!stacksizes[ci]) continue;
-
-
-            auto &compparent = get(cont[i]);
-            
-            const auto &temp = compparent.GetTemplate();
-
-            for(int j = 0; temp.GetRepeatMode() == temp.NoRepeat ? j == 0 : repeats.count(temp.GetRepeatMode()) && j < repeats[temp.GetRepeatMode()].size(); j++) {
-                Component *compptr;
-                const std::array<float, 4> *val;
-
-                if(temp.GetRepeatMode() == temp.NoRepeat) {
-                    compptr = &compparent;
-                    val     = &value;
-                }
-                else {
-                    compptr = &repeated[&temp][j];
-                    val     = &repeats[temp.GetRepeatMode()][j];
-                }
-
-                auto &comp = *compptr;
-
-                //check if textholder and if so use emsize from the font
-                int emsize = getemsize(comp);
-            
-                //check anchor object by observing temp.GetPreviousAnchor and direction
-                Component *anch = nullptr;
-            
-            
-                //if absolute, nothing to anchor to but to parent
-                if(temp.GetPositioning() == temp.Relative && temp.GetPreviousAnchor() != Anchor::None) {
-                    if(cont.GetOrientation() == Graphics::Orientation::Horizontal) {
-                        if((IsLeft(temp.GetPreviousAnchor()) && IsRight(temp.GetMyAnchor())) || 
-                            (temp.GetPreviousAnchor() == Anchor::None && IsRight(temp.GetContainerAnchor()))) 
-                        {
-                            anch = prev;
-                            comp.anchorotherside = true;
-                        }
-                        else {
-                            anch = next;
-                        }
-                    }
-                    else {
-                        if((IsTop(temp.GetPreviousAnchor()) && IsBottom(temp.GetMyAnchor())) || 
-                            (temp.GetPreviousAnchor() == Anchor::None && IsBottom(temp.GetContainerAnchor()))) 
-                        {
-                            anch = prev;
-                            comp.anchorotherside = true;
-                        }
-                        else {
-                            anch = next;
+                        else { //to top
+                            startmost = &comp;
                         }
                     }
                 }
-            
-                auto parentmargin = Convert(temp.GetMargin(), parent.innersize, emsize).CombinePadding(Convert(cont.GetPadding(), parent.size, emsize)) + Convert(temp.GetIndent(), parent.innersize, emsize);
-            
-                Geometry::Margin margin;
+            });
             
-                if(anch) {
-                    margin = Convert(temp.GetMargin(), parent.innersize, emsize).CombineMargins(Convert(anch->GetTemplate().GetMargin(), parent.innersize, emsize));
-                }
-                else {
-                    margin = parentmargin;
-                }
-            
-                auto maxsize = parent.innersize - parentmargin;
+            //this will calculate the necessary spacing between the last item(s)
+            int lastspacing = 0;
             
-                auto pos = temp.GetPosition();
-            
-                if(temp.GetValueModification() == temp.ModifyPosition) {
-                    if(NumberOfSetBits(temp.GetValueSource()) == 1) {
-                        if(cont.GetOrientation() == Graphics::Orientation::Horizontal) {
-                            pos = {{int(calculatevalue(*val, 0, comp)*10000), Dimension::BasisPoint}, pos.Y};
-                        }
-                        else {
-                            pos = {pos.X, {int(calculatevalue(*val, 0, comp)*10000), Dimension::BasisPoint}};
-                        }
+            if(ishor) {
+                if(startmost) {
+                    //calculate the used space on the left
+                    startused = startmost->location.X + startmost->size.Width;
+                    
+                    //both sides exist, so we will be using the margins between them
+                    if(endmost) {
+                        //calculate the used space on the right
+                        endused = parent.innersize.Width - endmost->location.X;
+                        
+                        //calculate margin
+                        auto s = startmost->GetTemplate().GetMargin().Right(parent.innersize.Width, getemsize(*startmost));
+                        auto e = endmost->GetTemplate().GetMargin().Left(parent.innersize.Width, getemsize(*endmost));
+                        
+                        //add indent
+                        lastspacing = calculatemargin(s, e);
+                    }
+                    else { //only start side is there
+                        //calculate margin
+                        auto s = startmost->GetTemplate().GetMargin().Right(parent.innersize.Width, getemsize(*startmost));
+                        auto e = cont.GetPadding().Right(parent.innersize.Width, getemsize(*startmost));
+                        
+                        //add indent
+                        lastspacing = calculatemargin(s, e) + startmost->GetTemplate().GetIndent().Right(parent.innersize.Width, getemsize(*startmost));
                     }
-                    else {
-                        pos ={{int(calculatevalue(*val, 0, comp)*10000), Dimension::BasisPoint}, {int(calculatevalue(*val, 1, comp)*10000), Dimension::BasisPoint}};
+                }
+                else if(endmost) { //only end side is there
+                    //calculate the used space on the right
+                    endused = parent.innersize.Width - endmost->location.X;
+                    
+                    //calculate margin
+                    auto s = cont.GetPadding().Left(parent.innersize.Width, getemsize(*endmost));
+                    auto e = endmost->GetTemplate().GetMargin().Left(parent.innersize.Width, getemsize(*endmost));
+                    
+                    //add indent
+                    lastspacing = calculatemargin(s, e) + endmost->GetTemplate().GetIndent().Left(parent.innersize.Width, getemsize(*endmost));
+                }
+            }
+            else { //vertical
+                if(startmost) {
+                    //calculate the space used on the top side
+                    startused = startmost->location.Y + startmost->size.Height;
+                    
+                    //both sides exist, so we will be using the margins between them
+                    if(endmost) {
+                        //calculate the space used on the bottom side
+                        endused = parent.innersize.Height - endmost->location.Y;
+                        
+                        //calculate margin
+                        auto s = startmost->GetTemplate().GetMargin().Bottom(parent.innersize.Height, getemsize(*startmost));
+                        auto e = endmost->GetTemplate().GetMargin().Top(parent.innersize.Height, getemsize(*endmost));
+                        
+                        lastspacing = calculatemargin(s, e);
+                    }
+                    else { //only start side is there
+                        //calculate margin
+                        auto s = startmost->GetTemplate().GetMargin().Bottom(parent.innersize.Height, getemsize(*startmost));
+                        auto e = cont.GetPadding().Bottom(parent.innersize.Height, getemsize(*startmost));
+                        
+                        //add indent
+                        lastspacing = calculatemargin(s, e) + startmost->GetTemplate().GetIndent().Bottom(0, getemsize(*startmost));
                     }
                 }
-                else if(temp.GetValueModification() == temp.ModifyX) {
-                    pos = {{int(calculatevalue(*val, 0, comp)*10000), Dimension::BasisPoint}, pos.Y};
+                else if(endmost) { //only end side is there
+                    //calculate the space used on the bottom side
+                    endused = parent.innersize.Height - endmost->location.Y;
+                    
+                    //calculate margin
+                    auto s = cont.GetPadding().Top(parent.innersize.Height, getemsize(*endmost));
+                    auto e = endmost->GetTemplate().GetMargin().Top(0, getemsize(*endmost));
+                    
+                    //add indent
+                    lastspacing = calculatemargin(s, e) + endmost->GetTemplate().GetIndent().Top(0, getemsize(*endmost));
                 }
-                else if(temp.GetValueModification() == temp.ModifyY) {
-                    pos = {pos.X, {int(calculatevalue(*val, 0, comp)*10000), Dimension::BasisPoint}};
-                }
-                else if(taglocations.count(temp.GetTag())) {
-                    pos = {taglocations[temp.GetTag()]};
-                }
+            }
+            
+            //calculate remaining space for percent based components
+            spaceleft     = parent.innersize.Width - startused - endused - lastspacing;
+            textspaceleft = textwidth - startused - endused - lastspacing;
+
+            if(middlepass && stage != middle)
+                stage = middle;
+            else
+                stage = final;
+
+            goto realign;
+        }
+
+        //Width should be autosized
+        if(parent.size.Width == 0) {
+            int w = 0;
+            
+            //calculate max right as width
+            forallcomponents([&](Component &comp, const ComponentTemplate &, const std::array<float, 4> &, int, int) {
+                int r = comp.size.Width + std::max(0, comp.location.X);
+                
+                auto m = Convert(
+                        comp.GetTemplate().GetMargin(), parent.innersize, emsize
+                    ).CombinePadding(
+                        Convert(cont.GetPadding(), parent.innersize, emsize)
+                    ) + 
+                    Convert(comp.GetTemplate().GetIndent(), parent.innersize, emsize)
+                ;
+                
+                r += m.Right;
                 
-                if(temp.GetPositioning() == temp.PolarAbsolute) {
-                    auto pcenter = Geometry::Pointf(cont.GetCenter().X.CalculateFloat((float)maxsize.Width, (float)emsize), cont.GetCenter().Y.CalculateFloat((float)maxsize.Height, (float)emsize));
-                    auto center  = Geometry::Pointf(temp.GetCenter().X.CalculateFloat((float)comp.size.Width, (float)emsize), temp.GetCenter().Y.CalculateFloat((float)comp.size.Height, (float)emsize));
+                if(w < r)
+                    w = r;
+            });
+            
+            parent.size.Width = w + cont.GetBorderSize().TotalX();
+        }
 
-                    pcenter += parentmargin.TopLeft();
+        //Height should be autosized
+        if(parent.size.Height == 0) {
+            int h = 0;
+            //calculate max right as width
+            forallcomponents([&](Component &comp, const ComponentTemplate &, const std::array<float, 4> &, int, int) {
+                int b = comp.size.Height + std::max(0, comp.location.Y);
+                
+                auto m = Convert(
+                        comp.GetTemplate().GetMargin(), parent.innersize, emsize
+                    ).CombinePadding(
+                        Convert(cont.GetPadding(), parent.innersize, emsize)
+                    ) + 
+                    Convert(comp.GetTemplate().GetIndent(), parent.innersize, emsize)
+                ;
+                
+                b += m.Bottom;
+                
+                if(h < b) {
+                    h = b;
+                }
+            });
+            
+            parent.size.Height = h + cont.GetBorderSize().TotalY();
+        }
+        
+        
+        forallcomponents([&](Component &comp, const ComponentTemplate &temp, const std::array<float, 4> &val, int, int index) {
+            if(temp.GetType() == ComponentType::Container) {
+                update(comp, val, index);
+            }
+        });
+    }
 
-                    auto r = pos.X.CalculateFloat(Geometry::Point(maxsize).Distance()/(float)sqrt(2), (float)emsize);
+    
+    void ComponentStack::render(Component &comp, Graphics::Layer &parent, Geometry::Point offset, const std::array<float, 4> &value, Graphics::RGBAf color, int ind) {
+        //parent template, used in determining repeat mode condition
+        const ComponentTemplate &tempp = comp.GetTemplate();
+        
+        //pointer to the template
+        auto tempptr = &tempp;
+        
+        //value for the current component
+        const std::array<float, 4> *valptr = &value;
 
-                    auto a = pos.Y.CalculateFloat(360, PI);
+        //if a repeated component, find its state through repeated component states
+        if(tempp.GetRepeatMode() != ComponentTemplate::NoRepeat) {
+            //if not found use Always
+            ComponentCondition rc = ComponentCondition::Always;
+            
+            //check and set repeat condition
+            if(repeatconditions[tempp.GetRepeatMode()].count(ind))
+                rc = repeatconditions[tempp.GetRepeatMode()][ind];
 
-                    a *= PI / 180.0f;
+            //update template
+            tempptr = &get(tempp.GetIndex(), rc).GetTemplate();
+            
+            //change the value to the repeat value
+            valptr = &repeats[tempp.GetRepeatMode()][ind];
+        }
+        
+        auto val = *valptr;
+
+        //obtain reference for the template
+        const auto &temp = *tempptr;
 
-                    comp.location = {int(std::round(r * cos(a) + pcenter.X - center.X)), int(std::round(r * sin(a) + pcenter.Y - center.Y))};
-                }
-                else {
-                    auto offset = Convert(pos, (temp.GetPositioning() == temp.AbsoluteSliding ?  maxsize - comp.size : comp.size), emsize);
+        //this is the target layer to draw on
+        Graphics::Layer *target = nullptr;
+        
+        //storage for this component
+        auto &st = *storage[&temp];
+        
+        //if component has its own layer
+        if(st.layer) {
+            //change target layer
+            target = st.layer;
+            
+            //add it to the parent
+            parent.Add(*target);
+            
+            //set the size and location of this layer
+            target->Resize(comp.size);
+            target->Move(comp.location+offset);
+            
+            //show the layer
+            st.layer->Show();
+            
+            //clear it
+            st.layer->Clear();
             
-                    if(anch) {
-                        anchortoother(comp, temp, offset, margin, *anch, cont.GetOrientation());
+            //offset should now be relative to the layer
+            offset = -comp.location;
+        }
+        else {
+            //use parent layer
+            target = &parent;
+        }
+        
+        //if there is color modification tint the color based on values
+        if(temp.GetValueModification() == ComponentTemplate::ModifyColor) {
+            //act depending on the number of set bits
+            if(NumberOfSetBits(temp.GetValueSource()) == 1) { //use the value as gray
+                color *= Graphics::RGBAf(calculatevalue(val, 0, comp));
+            }
+            else if(NumberOfSetBits(temp.GetValueSource()) == 2) { //use gray + alpha
+                color *= Graphics::RGBAf(calculatevalue(val, 0, comp), calculatevalue(val, 1, comp));
+            }
+            else if(NumberOfSetBits(temp.GetValueSource()) == 3) { //use RGB
+                color *= Graphics::RGBAf(calculatevalue(val, 0, comp), calculatevalue(val, 1, comp), calculatevalue(val, 2, comp), 1.f);
+            }
+            else //use RGBA
+                color *= Graphics::RGBAf(calculatevalue(val, 0, comp), calculatevalue(val, 1, comp), calculatevalue(val, 2, comp), calculatevalue(val, 3, comp));
+        }
+        else if(temp.GetValueModification() == ComponentTemplate::ModifyAlpha) //use alpha
+            color *= Graphics::RGBAf(1.f, calculatevalue(val, 0, comp));
+
+        
+        //Rendering container
+        if(temp.GetType() == ComponentType::Container) {
+            //get specific template
+            const auto &cont = dynamic_cast<const ContainerTemplate&>(temp);
+            
+            //modify the offset so its children will inherit the same offset
+            offset += comp.location;
+
+            //if there is primary image
+            if(st.primary) {
+                
+                //test if it is RectangularDrawable to force the size of the container
+                auto rectangular = dynamic_cast<const Graphics::RectangularDrawable*>(st.primary);
+                if(rectangular)
+                    rectangular->DrawIn(*target, offset, comp.size, color);
+                else //not rectangular means we cannot control size, directly draw on the layer
+                    st.primary->Draw(*target, offset, color);
+            }
+            
+            //offset the children further by border size
+            offset += cont.GetBorderSize().TopLeft();
+            
+            //render children, go through indexes
+            for(int i=0; i<cont.GetCount(); i++) {
+                //should not happen but we don't want to crash as it is possible to continue without issues
+                if(cont[i] >= indices) continue;
+                
+                //if a component exists at the location
+                if(stacksizes[cont[i]]) {
+                    //this is the child component, parent of repeats if it is repeated
+                    auto &compparent = get(cont[i]);
+                    //get the template
+                    auto &temp       = compparent.GetTemplate();
+                    
+                    //if not repeating
+                    if(temp.GetRepeatMode() == ComponentTemplate::NoRepeat) {
+                        //render this component
+                        render(compparent, *target, offset, val, color);
                     }
-                    else {
-                        anchortoparent(comp, temp, offset, margin, parent.innersize);
-                    }
-                }
-
-                //Which anchor side is to be changed
-                if(temp.GetPositioning() == temp.Relative) {
-                    if(cont.GetOrientation() == Graphics::Orientation::Horizontal) {
-                        if(IsRight(temp.GetMyAnchor())) {
-                            prev = &comp;
+                    //if repeating
+                    else if(repeats.count(temp.GetRepeatMode())) {
+                        //if we are also repeating and the repeat modes match, we will not further repeat these elements
+                        if(ind > -1 && temp.GetRepeatMode() == comp.GetTemplate().GetRepeatMode()) {
+                            render(repeated[&temp][ind], *target, offset, val, color, ind);
                         }
                         else {
-                            next = &comp;
-                        }
-                    }
-                    else {
-                        if(IsBottom(temp.GetMyAnchor())) {
-                            prev = &comp;
-                        }
-                        else {
-                            next = &comp;
+                            //call render for each repeat
+                            int index = 0;
+                            for(auto &r : repeated[&temp])
+                                render(r, *target, offset, val, color, index++);
                         }
                     }
                 }
             }
-        }//for indices
-        
-        if(requiresrepass && !repassdone) {
-            if(cont.GetOrientation() == Graphics::Orientation::Horizontal) {
-                int rightused = 0, leftused = 0;
-                
-                for(int i=0; i<cont.GetCount(); i++) {
-                    
-                    int ci = cont[i];
-
-                    if(ci >= indices) continue;
-                    if(!stacksizes[ci]) continue;
-
-                    auto &compparent = get(cont[i]);
-                    const auto &temp = compparent.GetTemplate();
-
-                    for(int j = 0; temp.GetRepeatMode() == temp.NoRepeat ? j == 0 : repeats.count(temp.GetRepeatMode()) && j < repeats[temp.GetRepeatMode()].size(); j++) {
-                        Component *compptr;
-                        const std::array<float, 4> *val;
-
-                        if(temp.GetRepeatMode() == temp.NoRepeat) {
-                            compptr = &compparent;
-                            val     = &value;
-                        }
-                        else {
-                            compptr = &repeated[&temp][j];
-                            val     = &repeats[temp.GetRepeatMode()][j];
-                        }
-
-                        auto &comp = *compptr;
-
-                        //check if textholder and if so use emsize from the font
-                        int emsize = getemsize(comp);
-
-                        if(temp.GetPositioning() != temp.Absolute && temp.GetPositioning() != temp.PolarAbsolute) {
-                            if(comp.anchorotherside) {
-                                rightused = parent.innersize.Width - comp.location.X;
-                            }
-                            else if(comp.size.Width > 0) {
-                                leftused = (   
-                                    comp.location.X + comp.size.Width + 
-                                    std::max(temp.GetMargin().Right(parent.innersize.Width, emsize), cont.GetPadding().Right(parent.size.Width, emsize))
-                                
-                                );
-                            }
-                        }
-                    }
-                }
-                
-                spaceleft = parent.innersize.Width - rightused - leftused;
+            
+            //get offset back by border size
+            offset -= cont.GetBorderSize().TopLeft();
+            
+            //secondary is overlay image
+            if(st.secondary) {
+                //if rectangular force the size
+                auto rectangular = dynamic_cast<const Graphics::RectangularDrawable*>(st.secondary);
+                if(rectangular)
+                    rectangular->DrawIn(*target, offset+cont.GetOverlayExtent().TopLeft(), comp.size-cont.GetOverlayExtent(), color);
+                else //if not simply draw it
+                    st.secondary->Draw(*target, offset+cont.GetOverlayExtent().TopLeft(), color);
             }
-            else {
-                int bottomused = 0, topused = 0;
-                
-                for(int i=0; i<cont.GetCount(); i++) {
-                    
-                    int ci = cont[i];
-
-                    if(ci >= indices) continue;
-                    if(!stacksizes[ci]) continue;
-
-                    auto &comp = get(cont[i]);
-                    const auto &temp = comp.GetTemplate();
-                    
-                    //check if textholder and if so use emsize from the font
-                    int emsize = getemsize(comp);
-
-                    if(temp.GetPositioning() != temp.Absolute && temp.GetPositioning() != temp.PolarAbsolute) {
-                        if(comp.anchorotherside) {
-                            bottomused = parent.innersize.Height - comp.location.X;
-                        }
-                        else if(comp.size.Height) {
-                            topused = (   
-                                comp.location.X + comp.size.Height + 
-                                std::max(temp.GetMargin().Right(parent.innersize.Height, emsize), cont.GetPadding().Right(parent.size.Height, emsize))
-                                
-                            );
-                        }
-                    }
-                }
-                
-                spaceleft = parent.innersize.Height - bottomused - topused;
-            }
-
-            repassdone = true;
-            goto realign;
+            
+            //we are done, no need to undo the offset further
         }
-
-
-        for(int i=0; i<cont.GetCount(); i++) {
-
-            int ci = cont[i];
-
-            if(ci >= indices) continue;
-            if(!stacksizes[ci]) continue;
-
-
-            auto &comp = get(cont[i]);
-
-            const auto &temp = comp.GetTemplate();
-
-            if(temp.GetType() == ComponentType::Container) {
-                update(comp);
-            }
-        }
-    }
-
-        
-    void ComponentStack::render(Component &comp, Graphics::Layer &parent, Geometry::Point offset, Graphics::RGBAf color, int ind) {
-        const ComponentTemplate &tempp = comp.GetTemplate();
-        auto tempptr = &tempp;
-        std::array<float, 4> val = value;
-
-        if(tempp.GetRepeatMode() != ComponentTemplate::NoRepeat) {
-            ComponentCondition rc = ComponentCondition::Always;
-            if(repeatconditions[tempp.GetRepeatMode()].count(ind))
-                rc = repeatconditions[tempp.GetRepeatMode()][ind];
-
-            tempptr = &get(tempp.GetIndex(), rc).GetTemplate();
-            
-            val = repeats[tempp.GetRepeatMode()][ind];
+        //rendering graphics template
+        else if(temp.GetType() == ComponentType::Graphics) {
+            //get specialized template
+            const auto &gt = dynamic_cast<const GraphicsTemplate&>(temp);
             
-        }
-
-        const auto &temp = *tempptr;
-
-        Graphics::Layer *target = nullptr;
-        auto &st = *storage[&temp];
-        
-        if(st.layer) {
-            target = st.layer;
-            parent.Add(*target);
-            target->Resize(comp.size);
-            target->Move(comp.location);
-            if(st.layer) {
-                st.layer->Show();
-                st.layer->Clear();
-            }
-
-            offset -= comp.location;
-        }
-        else {
-            target = &parent;
-        }
-
-        if(temp.GetValueModification() == ComponentTemplate::ModifyColor) {
-            if(NumberOfSetBits(temp.GetValueSource()) == 1) {
-                color *= Graphics::RGBAf(calculatevalue(val, 0, comp));
-            }
-            else if(NumberOfSetBits(temp.GetValueSource()) == 2) {
-                color *= Graphics::RGBAf(calculatevalue(val, 0, comp), calculatevalue(val, 1, comp));
-            }
-            else if(NumberOfSetBits(temp.GetValueSource()) == 3) {
-                color *= Graphics::RGBAf(calculatevalue(val, 0, comp), calculatevalue(val, 1, comp), calculatevalue(val, 2, comp), 1.f);
-            }
-            else
-                color *= Graphics::RGBAf(calculatevalue(val, 0, comp), calculatevalue(val, 1, comp), calculatevalue(val, 2, comp), calculatevalue(val, 3, comp));
-        }
-        else if(temp.GetValueModification() == ComponentTemplate::ModifyAlpha)
-            color *= Graphics::RGBAf(1.f, calculatevalue(val, 0, comp));
-
-        if(temp.GetType() == ComponentType::Container) {
-            const auto &cont = dynamic_cast<const ContainerTemplate&>(temp);
+            auto img = st.primary;
             
-            offset += cont.GetBorderSize().TopLeft();
-            offset += comp.location;
-
-            if(st.primary && target) {
-                auto rectangular = dynamic_cast<const Graphics::RectangularDrawable*>(st.primary);
-                if(rectangular)
-                    rectangular->DrawIn(*target, offset-cont.GetBorderSize().TopLeft(), comp.size, color);
-                else
-                    st.primary->Draw(*target, offset-cont.GetBorderSize().TopLeft(), color);
+            //allow overriding the image
+            if(imagedata.Exists(gt.GetDataEffect())) {
+                img = &imagedata[gt.GetDataEffect()];
             }
             
-            for(int i=0; i<cont.GetCount(); i++) {
-                if(cont[i] >= indices) continue;
-                if(stacksizes[cont[i]]) {
-                    auto &compparent = get(cont[i]);
-                    auto &temp       = compparent.GetTemplate();
-                    if(temp.GetRepeatMode() == ComponentTemplate::NoRepeat) {
-                        render(compparent, target ? *target : parent, offset, color);
-                    }
-                    else if(repeats.count(temp.GetRepeatMode())) {
-                        int index = 0;
-                        for(auto &r : repeated[&temp])
-                            render(r, target ? *target : parent, offset, color, index++);
-                    }
-                }
-            }
-            
-            if(st.secondary && target) {
-                auto rectangular = dynamic_cast<const Graphics::RectangularDrawable*>(st.secondary);
-                if(rectangular)
-                    rectangular->DrawIn(*target, offset-cont.GetBorderSize().TopLeft()+cont.GetOverlayExtent().TopLeft(), comp.size, color);
-                else
-                    st.secondary->Draw(*target, offset-cont.GetBorderSize().TopLeft()+cont.GetOverlayExtent().TopLeft(), color);
-            }
-            
-            offset -= cont.GetBorderSize().TopLeft();
-        }
-        else if(temp.GetType() == ComponentType::Graphics) {
-            if(st.primary && target) {
-                auto rectangular = dynamic_cast<const Graphics::RectangularDrawable*>(st.primary);
-                const auto &gt = dynamic_cast<const GraphicsTemplate&>(temp);
-
+            //if has an image to be drawn
+            if(img) {
+                
+                //set tint
                 auto c = gt.GetColor();
-
+                
+                //if blend modification is set then perform blending using target color
                 if(temp.GetValueModification() == temp.BlendColor)  {
+                    //get target color
                     auto c2 = gt.GetTargetColor();
+                    
+                    //blend to tint that is set
                     switch(NumberOfSetBits(temp.GetValueSource())) {
-                        case 1:
-                            c.Blend(c2, calculatevalue(val, 0, comp));
+                        case 1: //single alpha blending
+                            c.Slide(c2, calculatevalue(val, 0, comp));
                             break;
 
-                        case 2:
-                            c.Blend(c2, calculatevalue(val, 0, comp), calculatevalue(val, 1, comp));
+                        case 2: //alpha and grayscale has different blending factors
+                            c.Slide(c2, calculatevalue(val, 0, comp), calculatevalue(val, 1, comp));
                             break;
 
-                        case 3:
-                            c.Blend(c2, {calculatevalue(val, 0, comp), calculatevalue(val, 1, comp), calculatevalue(val, 2, comp), 0});
+                        case 3: //separate blending factors for RGB
+                            c.Slide(c2, {calculatevalue(val, 0, comp), calculatevalue(val, 1, comp), calculatevalue(val, 2, comp), 0.0});
                             break;
 
-                        case 4:
-                            c.Blend(c2, {calculatevalue(val, 0, comp), calculatevalue(val, 1, comp), calculatevalue(val, 2, comp), calculatevalue(val, 3, comp)});
+                        case 4: //separate blending factors for all channels
+                            c.Slide(c2, {calculatevalue(val, 0, comp), calculatevalue(val, 1, comp), calculatevalue(val, 2, comp), calculatevalue(val, 3, comp)});
                             break;
 
+                        //to silence warnings
                         default:
                             break;
                     }
                 }
                 
-                if(rectangular && gt.GetFillArea())
-                    rectangular->DrawIn(*target, comp.location+offset+gt.GetPadding().TopLeft(), comp.size, color * c);
-                else
-                    st.primary->Draw(*target, comp.location+offset+gt.GetPadding().TopLeft(), color * c);
+                //check if set image is rectangular and filling is requested
+                auto rectangular = dynamic_cast<const Graphics::RectangularDrawable*>(img);
+                if(rectangular && gt.GetFillArea()) // ask image to fill the area, multiply tint and parent color
+                    rectangular->DrawIn(*target, comp.location+offset, comp.size, color * c);
+                else //directly draw to the location, multiply tint and parent color
+                    img->Draw(*target, comp.location+offset, color * c);
             }
         }
+        //render text
         else if(temp.GetType() == ComponentType::Textholder) {
+            //get specific template
             const auto &th = dynamic_cast<const TextholderTemplate&>(temp);
 
-            auto c = th.GetColor();
-
-            if(temp.GetValueModification() == temp.BlendColor) {
-                auto c2 = th.GetTargetColor();
-                switch(NumberOfSetBits(temp.GetValueSource())) {
-                    case 1:
-                        c.Blend(c2, calculatevalue(val, 0, comp));
-                        break;
-
-                    case 2:
-                        c.Blend(c2, calculatevalue(val, 0, comp), calculatevalue(val, 1, comp));
-                        break;
-
-                    case 3:
-                        c.Blend(c2, {calculatevalue(val, 0, comp), calculatevalue(val, 1, comp), calculatevalue(val, 2, comp), 0});
-                        break;
-
-                    case 4:
-                        c.Blend(c2, {calculatevalue(val, 0, comp), calculatevalue(val, 1, comp), calculatevalue(val, 2, comp), calculatevalue(val, 3, comp)});
-                        break;
-
-                    default:
-                        break;
+            //find the text to be printed
+            std::string text;
+            
+            if(th.IsReady()) { //if th is not ready do not bother finding the text
+                if(stringdata.count(temp.GetDataEffect())) {
+                    text = stringdata[temp.GetDataEffect()];
+                }
+                else if(valuetotext && (ind != -1 || !stringdata.count(temp.GetDataEffect())) ) {
+                    text = valuetotext(temp.GetTag(), temp.GetDataEffect(), val);
+                }
+                else {
+                    text = th.GetText();
                 }
             }
+            
+            //only perform operations if renderer is ready
+            if(th.IsReady() && !text.empty()) {
+                //get text color
+                auto c = th.GetColor();
 
-            target->SetColor(color * c);
-            if(th.IsReady()) {
-                if(valuetotext && (ind != -1 || !stringdata.count(temp.GetDataEffect())) ) {
-                    if(tagnowrap.count(temp.GetTag()))
-                        th.GetRenderer().PrintNoWrap(*target, valuetotext(temp.GetTag(), temp.GetDataEffect(), val), comp.location+offset, comp.size.Width);
-                    else
-                        th.GetRenderer().Print(*target, valuetotext(temp.GetTag(), temp.GetDataEffect(), val), comp.location+offset, comp.size.Width);
+                //if color blending is set
+                if(temp.GetValueModification() == temp.BlendColor) {
+                    //get target color
+                    auto c2 = th.GetTargetColor();
+                    
+                    //blend to tint that is set
+                    switch(NumberOfSetBits(temp.GetValueSource())) {
+                        case 1: //single alpha blending
+                            c.Slide(c2, calculatevalue(val, 0, comp));
+                            break;
+
+                        case 2: //alpha and grayscale has different blending factors
+                            c.Slide(c2, calculatevalue(val, 0, comp), calculatevalue(val, 1, comp));
+                            break;
+
+                        case 3: //separate blending factors for RGB
+                            c.Slide(c2, {calculatevalue(val, 0, comp), calculatevalue(val, 1, comp), calculatevalue(val, 2, comp), 0.0});
+                            break;
+
+                        case 4: //separate blending factors for all channels
+                            c.Slide(c2, {calculatevalue(val, 0, comp), calculatevalue(val, 1, comp), calculatevalue(val, 2, comp), calculatevalue(val, 3, comp)});
+                            break;
+
+                        //to silence warnings
+                        default:
+                            break;
+                    }
                 }
-                else if(stringdata.count(temp.GetDataEffect())) {
-                    if(tagnowrap.count(temp.GetTag()))
-                        th.GetRenderer().PrintNoWrap(*target, stringdata[temp.GetDataEffect()], comp.location+offset, comp.size.Width);
-                    else
-                        th.GetRenderer().Print(*target, stringdata[temp.GetDataEffect()], comp.location+offset, comp.size.Width);
-                }
+
+                //save current tint and change it
+                auto old = target->GetColor();
+                target->SetColor(color * c);
+                
+                //target->Draw(comp.location+offset, comp.size, 0x80000000); //for debugging
+                if(tagnowrap.count(temp.GetTag()))
+                    th.GetRenderer().PrintNoWrap(*target, text, comp.location+offset, comp.size.Width);
+                else
+                    th.GetRenderer().Print(*target, text, comp.location+offset, comp.size.Width);
+                
+                target->SetColor(old);
             }
-            target->SetColor(1.f);
         }
+        //render placeholder
         else if(temp.GetType() == ComponentType::Placeholder && comp.size.Area() > 0) {
             const auto &ph = dynamic_cast<const PlaceholderTemplate&>(temp);
             
@@ -2698,7 +3384,7 @@
                 stack.Move(comp.location + offset);
                 stack.Resize(comp.size);
             }
-
+            
             if(imagedata.Exists(ph.GetDataEffect())) {
                 auto rectangular = dynamic_cast<const Graphics::RectangularDrawable*>(&imagedata[ph.GetDataEffect()]);
                 if(rectangular) {
--- a/Source/Gorgon/UI/ComponentStack.h	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/UI/ComponentStack.h	Thu Sep 17 16:29:02 2020 +0300
@@ -62,6 +62,16 @@
         /// the stack for condition changes. This variant supports image based data.
         /// Ownership of the image stays with the caller.
         void SetData(ComponentTemplate::DataEffect effect, const Graphics::Drawable &image);
+        
+        /// Returns the text data. If data is not set, this will return empty string.
+        std::string GetTextData(ComponentTemplate::DataEffect effect) {
+            return stringdata.count(effect) ? stringdata[effect] : "";
+        }
+        
+        /// Returns the image data. If data is not set, this will return nullptr.
+        const Graphics::Drawable *GetImageData(ComponentTemplate::DataEffect effect) {
+            return imagedata.Exists(effect) ? &imagedata[effect] : nullptr;
+        }
 
         /// Removes the data associated with data effect. This will remove all data
         /// variants together.
@@ -98,6 +108,9 @@
 
         /// Sets the value for the stack using a color
         void SetValue(Graphics::RGBA color) { SetValue((Graphics::RGBAf)color); }
+        
+        /// Returns the value of the stack
+        std::array<float, 4> GetValue() const { return returntarget ? targetvalue : value; }
 
         /// Changes the value transition speed. A speed of 0 will disable smooth transition.
         /// The unit is values per second
@@ -105,13 +118,13 @@
             valuespeed = val;
         }
 
-        /// GetValue returns the current transitional value, this will also enable value event
+        /// Whether GetValue returns the current transitional value, this will also enable value event
         /// to be called every time transitional value is updated
         void ReturnTransitionalValue() {
             returntarget = false;
         }
 
-        /// GetValue returns the target value. This is the default mode.
+        /// Whether GetValue returns the target value. This is the default mode.
         void ReturnTargetValue() {
             returntarget = true;
         }
@@ -121,8 +134,6 @@
             value_fn = handler;
         }
 
-        /// Returns the value of the stack
-        std::array<float, 4> GetValue() const { return returntarget ? targetvalue : value; }
 
         /// Sets the function that will be used to convert a value to a string. The handler will receive the value channel, data effect
         /// that is causing the translation and the value that needs to be transformed.
@@ -325,38 +336,56 @@
             return get(ind).GetTemplate();
         }
 
+        /// Set a fixed location for a tagged component
+        void SetTagLocation(ComponentTemplate::Tag tag, Geometry::Point location) {
+            taglocations[tag] = location;
+            Update();
+        }
+        
+        Geometry::Point GetTagLocation(ComponentTemplate::Tag tag) const {
+            auto f = taglocations.find(tag);
+            
+            if(f == taglocations.end())
+                return {0, 0};
+            else
+                return f->second;
+        }
+
+        /// Removes the fixed location for a set tagged component
+        void RemoveTagLocation(ComponentTemplate::Tag tag) {
+            taglocations.erase(tag);
+        }
+
         /// Set a fixed size for a tagged component
         void SetTagSize(ComponentTemplate::Tag tag, Geometry::Size size) {
             tagsizes[tag] = size;
             Update();
         }
 
+        Geometry::Size GetTagSize(ComponentTemplate::Tag tag) const {
+            auto f = tagsizes.find(tag);
+            
+            if(f == tagsizes.end())
+                return {0, 0};
+            else
+                return f->second;
+        }
+
         /// Removes the fixed size for a set tagged component
         void RemoveTagSize(ComponentTemplate::Tag tag) {
             tagsizes.erase(tag);
         }
         
+        /// Enables text wrapping on a specific tag, default is enabled.
+        void EnableTagWrap(ComponentTemplate::Tag tag) {
+            tagnowrap.erase(tag);
+        }
+        
         /// Disables text wrapping on a specific tag, default is enabled.
         void DisableTagWrap(ComponentTemplate::Tag tag) {
             tagnowrap.insert(tag);
         }
 
-        /// Enables text wrapping on a specific tag, default is enabled.
-        void EnableTagWrap(ComponentTemplate::Tag tag) {
-            tagnowrap.erase(tag);
-        }
-
-
-        /// Set a fixed location for a tagged component
-        void SetTagLocation(ComponentTemplate::Tag tag, Geometry::Point location) {
-            taglocations[tag] = location;
-            Update();
-        }
-
-        /// Removes the fixed location for a set tagged component
-        void RemoveTagLocation(ComponentTemplate::Tag tag) {
-            taglocations.erase(tag);
-        }
 
         /// Sets a function to be called before update check
         void SetFrameEvent(std::function<void()> handler) {
@@ -432,7 +461,7 @@
                     up_fn(stack.first->GetTag() == ComponentTemplate::NoTag ? ComponentTemplate::UnknownTag : stack.first->GetTag(), point, btn);
                 });
             }
-    }
+        }
         
         /// Sets the mouse down event. If HandleMouse function is called, this function will first
         /// perform mouse event transition, then it will call this handler.
@@ -517,23 +546,39 @@
 
         ///Return the component at the given index with the requested condition. Returns top of stack if condition does not exist.
         Component &get(int ind, ComponentCondition condition) const;
-
-        ///starts update chain
+        
+        ///Calculates the position results from the anchoring the given component to the area determined by the
+        ///given size and margin. Offset is used to move away from the anchor and may result reversing of direction.
+        void anchortoparent(Component &parent, Component &comp, const ComponentTemplate &temp, 
+                                Geometry::Point offset, Geometry::Margin margin, Geometry::Size maxsize);
+        
+        
+        ///Calculates the position results from the anchoring the given component to another component
+        void anchortoother(Component &comp, const ComponentTemplate &temp, 
+                        Geometry::Point offset, Geometry::Margin margin, Component &other, Graphics::Orientation orientation);
+        
+        ///starts the update chain
         void update();
 
         ///updates a specific container component
-        void update(Component &parent);
+        void update(Component &parent, const std::array<float, 4> &value, int ind, int textwidth = -1);
 
         ///renders the given component, rendering will use parent layer if the component does not have its own layer. Index is for
         ///repeated components, it is the index of the repeat to be rendered. Unlike Layer::Render function, this function does not
         ///run every frame.
-        void render(Component &component, Graphics::Layer &parentlayer, Geometry::Point offset, Graphics::RGBAf color = 1.f, int ind = -1);
+        void render(Component &component, Graphics::Layer &parentlayer, Geometry::Point offset, const std::array<float, 4> &value, Graphics::RGBAf color = 1.f, int ind = -1);
 
         ///grows the size of the stack
         void grow();
         
         ///returns the size of the emdash
         int getemsize(const Component &comp);
+        
+        ///returns the baseline point of the component
+        int getbaseline(const Component &comp);
+        
+        ///returns the height of the component
+        int gettextheight(const Component &comp);
 
         ///Calculates the value of the given channel for the given component. Uses stored value
         float calculatevalue(int channel, const Component &comp) const { return calculatevalue(value, channel, comp); }
@@ -556,7 +601,13 @@
         Component *gettag(ComponentTemplate::Tag tag) const;
 
         ///ComponentStack wide emsize
-        int emsize = 10;
+        int emsize = 0;
+        
+        ///ComponentStack wide baseline
+        int baseline = 0;
+        
+        ///ComponentStack wide baseline
+        int textheight = 0;
         
         ///This vector contains data for components. This piece of memory will be managed by the stack
         Component *data = nullptr;
--- a/Source/Gorgon/UI/Dimension.h	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/UI/Dimension.h	Thu Sep 17 16:29:02 2020 +0300
@@ -79,6 +79,11 @@
                     return (float)value;
             }
         }
+        
+        /// Returns if the dimension is relative to the parentwidth
+        bool IsRelative() const {
+            return unit == Percent || unit == BasisPoint;
+        }
 
         /// Returns the value of the dimension, should not be considered as
         /// pixels
--- a/Source/Gorgon/UI/Template.cpp	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/UI/Template.cpp	Thu Sep 17 16:29:02 2020 +0300
@@ -4,6 +4,351 @@
 
 namespace Gorgon { namespace UI {
 
+    /**
+    * @page ui User interface
+    * 
+    * The user interface in Gorgon Library is based on the components system and is highly
+    * customizable. ComponentStack manages these components within a widget. There are
+    * different component types: containers (see @ref ContainerTemplate), placeholders (see
+    * @ref PlaceholderTemplate), graphics (see @ref GraphicsTemplate), and textholder (see 
+    * @ref TextholderTemplate). All subcomponents should be created from the main Template.
+    * 
+    * Each component has an index and containers have the index of the components that resides
+    * in them. There can be multiple components with the same index. ComponentCondition system
+    * is used to decide which components will exist at a given time. 
+    * 
+    * It is possible to control the transition of the widget from state to state by giving
+    * a specific component for the transition. This is generally used to animate state changes.
+    * It is also possible to use transition value channel to have value based animations. These
+    * animations can be reversed, even at the middle. In fact, even for regular bitmap
+    * animations, this is recommended as it can time the animation perfectly, allow it to be
+    * reversed at the middle of the transition (imagine mouse over). 
+    * 
+    * Components can be modified by ValueModification system. There are 4 widget controlled
+    * value channels and a fifth controlled by the transition. Values are expected to be in
+    * range from 0 to 1. But this can be changed by modifying value ranges. The aspect of the
+    * component that the value affects can also be controlled. Channels can be reordered to
+    * fit into the necessary order. Value changes can also be asked to be applied smoothly. But
+    * this is controlled through the widget.
+    * 
+    * Component data can be obtained by DataEffect. Data can currently be a text or an image.
+    * There are various data effects that can be used by graphics and textholder templates. 
+    * There are also conditions that trigger if a data channel has any data in it.
+    * 
+    * Components can be repeated. The repeats are controlled by the widget. Containers are 
+    * supported to be repeating structures, however, if it has subcomponents they should also
+    * set to repeat with the same repeat mode. This will not duplicate subcomponents into the
+    * container but rather uses the parent component's information in the subcomponents. Each
+    * repeat can have a different set value and condition. There are different repeating
+    * systems (such as minor and major) and each of these can be adjusted separately.
+    * 
+    * Components can have tags to be accessed from the widgets. Some widgets needs specific
+    * tags to exist in the template to work. 
+    * 
+    * Components are placed according to a series of complicated but intuitive rules. For 
+    * details of this system see @ref boxmodel.
+    * 
+    *
+    * @subpage components
+    * 
+    * @subpage boxmodel
+    * 
+    * @subpage uiconditions
+    * 
+    * @subpage valuechannels
+    * 
+    * @subpage componentexample
+    * 
+    * @subpage validators
+    */
+    
+
+    /**
+    * @page components Components
+    * 
+    * Components are the building blocks of widgets. They are the visual elements
+    * that makes up most of the visual aspect of a widget. Components have templates,
+    * which they use as basis for their placement and drawing. ComponentTemplate is 
+    * the base class for all component templates. Components have component index
+    * and component condition (see ComponentCondition) to control which components
+    * will be visible at a given instance. Components have the same component indices
+    * but only one will be shown at a time. The components that have more specific
+    * condition will have precedence. For instance, if two components have index of 2
+    * and one has condition of ComponentCondition::Always and the other has condition
+    * of ComponentCondition::Focused, first component will be displayed unless the
+    * widget has received focus, in that case the second one will be shown.
+    * 
+    * 
+    * Every widget requires a container component at index 0 as the root. If this
+    * component has a non-0 size, the widget size will be fixed [this might change
+    * in the future].
+    * 
+    * 
+    * Components can be modified by the widget data. This is controlled through data
+    * effect. Various data effects exist to suit different type of widgets. See the
+    * widget documentation for specific data exported by them.
+    * 
+    * See @ref boxmodel to learn how the components are spaced out.
+    * 
+    * See @ref componentexample to learn how to create a simple button
+    * 
+    */
+    
+    /**
+    * @page componentexample Component Example
+    * 
+    * This example shows how to create a simple button. Create the following templates:
+    * 
+    * @code
+    * ContainerTemplate, index = 0, background = bg image, set size, children = 1, 2
+    * TextholderTemplate, index = 2, set font, data effect = Text
+    * @endcode
+    * 
+    * These two templates will create a very simple button that has the background and
+    * it will display the text that is set by the programmer. If you wish to change the
+    * color of the text when the user moves mouse into the button, add the following
+    * template as well:
+    * 
+    * @code
+    * TextholderTemplate index = 2, set font, data effect = Text, condition = Hover
+    * @endcode
+    * 
+    * This component will override the previous if the mouse is over the button. In order
+    * to change the background when the user clicks the button, add the following:
+    * 
+    * @code
+    * ContainerTemplate, index = 0, background = pressed, set size, condition = Down, 
+    * children = 1, 2
+    * @endcode
+    * 
+    * This will change the background when the user presses the mouse button. Both hover and
+    * down conditions can occur at the same time. If user uses mouse to press the button
+    * they will both be active at the same time, however, if the user uses space bar to
+    * press the button when it is focused, only Down condition will be satisfied. In addition
+    * to these, it is helpful to provide a visual clue when the widget is focused. This
+    * is generally done by adding a focus rectangle like the following:
+    * 
+    * @code
+    * GraphicsTemplate, index = 1, Drawable = focus rectangle, Positioning = Absolute, 
+    * Size = 100, 100, Unit::Percent, set margin, condition = Focused
+    * @endcode
+    * 
+    * This last piece will only be shown when the button is focused. There will be no errors
+    * when it is invisible even when the container lists this template as its child.
+    * 
+    */
+
+
+    /**
+    * @page boxmodel Component placement
+    * 
+    * Apart from the top level container, each component should be in container. Components
+    * arrangement in a container first depends on component positioning. If a component is 
+    * relatively positioned, then it will follow the container orientation to be stacked with 
+    * the other relatively positioned components.
+    * 
+    * Sizing
+    * ======
+    * Components have multiple sizing modes. The first set of options control how the component
+    * will be sized in case it contains an image, text, or another component stack. If the size
+    * is Fixed, the size of the contents is ignored. Automatic uses the size of the contents.
+    * GrowOnly, ShrinkOnly options allow component to grow/shrink if the contents is larger/
+    * smaller than the given size. Sizing can be adjusted separately for X and Y axis. When
+    * grow only and shrink only options are combined with relative sizing the size calculation
+    * is performed between fixed and always relative size calculation time. Mixing multiple
+    * automatic grow/shrink only, relatively sized components in the same container is not 
+    * recommended. The system will try to fit automatic grow/shrink relatively sized components
+    * as best as possible with a single pass. Ex: There are two components, both are 50% in
+    * width and one of them is shrink only, container has 100px usable size. If the shrink only
+    * component has a content of 40px, the other component will be grown to fill the remaining
+    * 60px, even though it will be more than 50%. If this is not desired, shrink only component
+    * can be placed inside a 50% sized container, and its relative size should be set 100%.
+    * 
+    * Component size can also be relative. In this case, container orientation plays an 
+    * important role. If the relatively sized axis is not in the oriented direction, then the 
+    * entire usable size of the parent is used for the calculation. However, if the axis is the
+    * oriented direction, then only the unused space is considered during the relative size
+    * calculation. For instance, in a horizontally oriented container, assume there are two
+    * components. One has a fixed width of 50px and the other is set to 100% and the container
+    * has 200px usable width. Assuming no additional spacing, second component will have 150px
+    * width. This calculation depends on how the components are anchored and margin/padding/
+    * indent/border size.
+    * 
+    * Size of the component can be influenced by the value channels. In this case, the size of
+    * component is used as additional size on top of the relative size depending on the channel
+    * value. 
+    *
+    * It is possible for widgets to specify additional size to tags. In these cases, the given
+    * size will be used as an addition to the original size. It is not recommended to use
+    * automatic sizing with tags that the widgets can use (e.g., ContentsTag).
+    * 
+    * 
+    * Spacing
+    * =======
+    * In this system 4 spacing methods are used. First method is border size. Border size is
+    * excluded from the internal area of a container. Thus (0, 0), does not include the border.
+    * In this system, borders are not drawn automatically, they are a part of the background
+    * image, therefore, border size is not calculated. It should be supplied.
+    * 
+    * The second spacing is provided by the padding of the container. Main difference of
+    * padding is that it collapses with the margin of the components as well as being counted
+    * in the container. If the padding for any edge is negative, it will not be collapsed.
+    * 
+    * Margins are spacing around the components. Unless negative, they collapse. This means if
+    * two components are anchored together, the margin between them is the maximum of the
+    * margin their touching edges. Negative margins are always added. 
+    * 
+    * Indent is the last spacing. It is additive and only used if a component is anchored to
+    * its parent. This is very useful in repeated or conditional components. For instance, if
+    * a button can have icon with text. You may want extra spacing on the text if there is no
+    * icon. This can be facilitated using Icon1IsSet condition and indent.
+    * 
+    * All spacing except for border size can be relative. For padding, the size of the
+    * component excluding the borders is used. For margin and indent, size of the parent 
+    * excluding the borders is used. 50% margin left will effectively start a component from 
+    * the center. However, anchoring should be used for this case.
+    * 
+    * 
+    * Anchoring
+    * =========
+    * All components are placed according to their anchor points. Relatively positioned 
+    * components can be anchored to another component, but absolutely positioned components
+    * are always anchored to their parent. Depending on the orientation, relative anchoring
+    * will be done to left/right or top/bottom. It is possible for anchoring to cause 
+    * artifacts, thus it should be used properly. 
+    * 
+    * Absolute anchoring is simple. It uses parent and anchor point. In this anchoring, the 
+    * component should be inside the parent. This means, if horizontal part of the anchor point
+    * is left, then parent anchor should either be left or center, so that the component will
+    * be placed in the parent. Otherwise the component will be placed outside the parent. If
+    * an absolutely positioned object is attached to left/top or right/bottom of its parent's
+    * center/middle, then the effective size of the container if only include right/bottom or
+    * left/top portion of the container. If spacing for both sides are equal, this will cut the
+    * usable size by half. This feature makes it easier to deal with center starting 
+    * components.
+    * 
+    * Relative anchoring requires previous component anchor dictated by the current component
+    * and parent anchor. These target anchor points should match. Following previous example,
+    * where anchor point was left, parent anchor should again either be left or center.
+    * Assuming orientation is horizontal, previous anchor should be right, anchoring the
+    * component to the end of the previous one. In a container, there can be two separate
+    * anchor stacks, one starting from left to right and the other starting from right to
+    * left. This also works with vertical layouts (top to bottom and bottom to top). This is
+    * controlled by the combination of the anchor and previous component anchor. If anchor is
+    * specified as right and previous anchor is left (or none and parent anchor is right),
+    * then the component will be anchored from the right. If previous anchor is none, component
+    * is always anchored to the parent. This may cause components to overlap. Components can
+    * only be anchored to their parents or other relative components.
+    * 
+    * First baseline anchor uses the baseline of the first text line. In the calculations, it
+    * is considered top aligned. Last baseline uses the baseline of the last text line. It is 
+    * considered as bottom alignment. If there is no text, first baseline is calculated from
+    * the top, last baseline is calculated from the bottom. Baseline can be specified in 
+    * template. When it is specified, that value will be used instead of calculated baseline.
+    * Last baseline alignments should only be used for textholders.
+    * 
+    * Positioning
+    * ===========
+    * The position of the component effects its place from the anchor. If anchored by left/top
+    * or center/middle x/y position is added to the anchor point. If anchored by right/bottom, 
+    * x/y position is subtracted. 
+    *
+    * In AbsoluteSliding positioning the component anchors to its parent. For relative size, 
+    * entire usable area of the parent is used. If the position is specified as percentage,
+    * remaining area after the component is placed is used. Ex: parent width: 100, component 
+    * width: 50, parent padding: 10, component x position: 50%, margin: 0. In this case,
+    * component width and padding is subtracted from parent width, 30px remains. This size is 
+    * used to calculate percentage position, which is 15px. If an component's size is 100%, 
+    * percentage base positioning will not have any effect on the position of the component.
+    * 
+    * Relative positioning is very similar to absolute positioning except the component can be
+    * anchored to other components and its percent based metrics uses remaining size of the
+    * parent in the oriented direction.
+    * 
+    * Absolute positioning is classical absolute positioning in many systems. It uses entirety 
+    * of the parent size to calculate percentage based positioning. In other aspects, it is 
+    * same with absolute sliding positioning.
+    * 
+    * PolarAbsolute changes coordinate system to polar coordinates. X axis becomes radius and
+    * Y axis becomes angle in degrees. Center is used to calculate transformation point. While
+    * calculating center point Absolute positioning is used. If radius is percentage based, the
+    * maximum size that will ensure component will stay within the parent will be used. Parent
+    * anchor is used to decide how to calculate this length. For instance, if the anchor point
+    * is TopCenter, then the max radius calculation assumes angle will change from 180-360. 
+    * This currently does not take value range into consideration. If desired, em size could 
+    * also be used for angle, which is set to 45deg. Component is then placed according to its
+    * center point. To use PolarAbsolute correctly, you should set center of parent, center of 
+    * component as well as parent anchor of the component (not self anchor) correctly. Setting
+    * parent anchor also adjusts maximum and starting angle so that the both radius 0-100% and 
+    * angle 0-100% will stay within the container. Angle always works counter clockwise. Angle 
+    * EM size is not changed by the anchor point, however, it is also affected by the starting 
+    * point. Also, when percentages or value modification is involved, it is advised to set 
+    * center point of the component so that it will be within the object. This offset will not
+    * be automatically done and will leave portions of the object outside its parent.
+    * 
+    * Position can be affected by the value modification system. In this case specified
+    * position is used as an addition with a percentage based value. 
+    * 
+    * It is possible for widgets to specify additional position for a specific tag. It is
+    * recommended to anchor such components to top left and instead of using position to place
+    * them, use spacing. Only one tag currently is used for position modification: ContentsTag.
+    * 
+    *  
+    */
+    
+    
+    /**
+     * @page uiconditions Conditions
+     * 
+     * There are many conditions that will effect the visibility/selection of each components.
+     * Using conditions, visuals of widgets can be modified. Conditions are supplied by the 
+     * widgets depending on their states. A simple example will be mouse over. 
+     * 
+     * Only one component can be present for every index. When there are multiple components 
+     * for the same index is present, the component to be shown is determined by the active
+     * conditions. If there are no conditions present, only components with Always condition
+     * will be visible. If there is a condition that matches a component, that particular
+     * component will be visible for that index. If there are multiple conditions active for 
+     * the same index, the last condition applied will take precedence. Not all conditions are
+     * supported by all widgets. For the list of conditions see @ref ComponentCondition.
+     * 
+     * Combining multiple conditions can be done by using containers. Containers could be set
+     * to obtain the size of its contents, with no spacing, it will not effect anything 
+     * visually. Having separate conditions for the container and the component will act as and
+     * operation as both conditions should be present for the component to be visible. For or
+     * operation, you can have two containers containing the same index with different 
+     * conditions. Indexes are global, therefore, if one of the containers is visible on the
+     * screen, component will be visible. A component cannot be in two separate containers at
+     * the *same* time. Thus the containers should have the same index for exclusivity.
+     * 
+     * Conditions can transition from one to another. These are also controlled by widgets. For
+     * transitions to work, it should be adjusted from the Template. First the transition 
+     * duration should be set. Then if the transition can be reversed, which is recommended, it
+     * should be set as well. Finally, there should be a component with transition from first
+     * condition to the second. This can be done by supplying two conditions to Add component
+     * functions. With reversed transition and using transition value channel to control the
+     * effect, one component can handle both conditions and the transition to both directions.
+     * 
+     * For instance, for a checkbox, an animation from unchecked to checked can be used for
+     * unchecked (Always), checked (State2), Always > State2, State2 > Always by waiting at
+     * first frame, waiting at last frame, running the animation forwards and running the 
+     * animation backwards. All of which can easily be handled by setting value source to
+     * Transition, value modification to ModifyAnimation, condition should be set to Always >
+     * State2 and finally, the durations for Always > State2 and State2 > Always transitions
+     * should be set.
+     * 
+     */
+    
+    /**
+     * @page valuechannels Value channels and modification
+     * 
+     * Value modification is an integral part of the UI mechanics. It allows widgets to specify
+     * values up to 4 channels. The components can be setup to be modified by these channels by
+     * various effects. In addition to these standard 4 channels, there is also transition
+     * channel, the value of which changes with the transition of the conditions.
+     * 
+     */
+
     PlaceholderTemplate& Template::AddPlaceholder(int index, ComponentCondition from, ComponentCondition to){ 
         auto obj = new PlaceholderTemplate();
         components.Add(obj);
--- a/Source/Gorgon/UI/Template.h	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/UI/Template.h	Thu Sep 17 16:29:02 2020 +0300
@@ -11,137 +11,21 @@
 #include "../Graphics/Animations.h"
 #include "Dimension.h"
 
+//TODO: Add baseline for all components
+
 namespace Gorgon { 
     namespace Graphics {
         class TextRenderer;
     }
     
-    /**
-    * @page ui User interface
-    *
-    * @subpage components
-    * 
-    * @subpage boxmodel
-    * 
-    * @subpage validators
-    */
-    
     /// This namespace contains User interface related functionality. This namespace
     /// does not contain the actual widgets that can be used. For that purpose, use
     /// Gorgon::Widgets namespace.
     namespace UI {
 
-
-    /**
-    * @page components Components
-    * 
-    * Components are the building blocks of widgets. They are the visual elements
-    * that makes up most of the visual aspect of a widget. Components have templates,
-    * which they use as basis for their placement and drawing. ComponentTemplate is 
-    * the base class for all component templates. Components have component index
-    * and component condition (see ComponentCondition) to control which components
-    * will be visible at a given instance. Components have the same component indices
-    * but only one will be shown at a time. The components that have more specific
-    * condition will have precedence. For instance, if two components have index of 2
-    * and one has condition of ComponentCondition::Always and the other has condition
-    * of ComponentCondition::Focused, first component will be displayed unless the
-    * widget has received focus, in that case the second one will be shown.
-    * 
-    * 
-    * Every widget requires a container component at index 0 as the root. If this
-    * component has a non-0 size, the widget size will be fixed [this might change
-    * in the future].
-    * 
-    * 
-    * Components can be modified by the widget data. This is controlled through data
-    * effect. Various data effects exist to suit different type of widgets. See the
-    * widget documentation for specific data exported by them.
-    * 
-    * See @ref boxmodel to learn how the components are spaced out.
-    * 
-    * 
-    * ### How to create a simple button using components
-    * Create the following templates:
-    * 
-    * @code
-    * ContainerTemplate, index = 0, background = bg image, set size, children = 1, 2
-    * TextholderTemplate, index = 2, set font, data effect = Text
-    * @endcode
-    * 
-    * These two templates will create a very simple button that has the background and
-    * it will display the text that is set by the programmer. If you wish to change the
-    * color of the text when the user moves mouse into the button, add the following
-    * template as well:
-    * 
-    * @code
-    * TextholderTemplate index = 2, set font, data effect = Text, condition = Hover
-    * @endcode
-    * 
-    * This component will override the previous if the mouse is over the button. In order
-    * to change the background when the user clicks the button, add the following:
-    * 
-    * @code
-    * ContainerTemplate, index = 0, background = pressed, set size, condition = Down, 
-    * children = 1, 2
-    * @endcode
-    * 
-    * This will change the background when the user presses the mouse button. Both hover and
-    * down conditions can occur at the same time. If user uses mouse to press the button
-    * they will both be active at the same time, however, if the user uses space bar to
-    * press the button when it is focused, only Down condition will be satisfied. In addition
-    * to these, it is helpful to provide a visual clue when the widget is focused. This
-    * is generally done by adding a focus rectangle like the following:
-    * 
-    * @code
-    * VisualTemplate, index = 1, Drawable = focus rectangle, Positioning = Absolute, 
-    * Size = 100, 100, Unit::Percent, set margin, condition = Focused
-    * @endcode
-    * 
-    * This last piece will only be shown when the button is focused. There will be no errors
-    * when it is invisible even when the container lists this template as its child.
-    * 
-    * 
-    * ###See also:
-    * 
-    * @ref boxmodel
-    */
-
-
-    /**
-    * @page boxmodel Box Model
-    * 
-    * Component template defines any component that can be placed on a widget. This includes
-    * non-visual elements, fixed and user defined visual elements, and containers.
-    * Container components defines an area that can contain more objects and optionally 
-    * has a background and an overlay. This object also has margin to control how it
-    * will be placed in relation to other objects at the same level. Shadow extension
-    * control the drawing of background, while overlay extension controls the drawing
-    * of the overlay image. Positive extension will enlarge the image in that
-    * direction. Negative extensions also work. Extensions should not cover the border
-    * size, border margin should be within the object, extensions can be used to align
-    * overlay to background and to ignore shadows, which should stay outside the
-    * object. Border size controls the size of the border. (0, 0) of the object
-    * starts from this point. Padding controls the distance of the sub-objects from
-    * the border. Padding and the margin collapse on edge, the maximum value of
-    * margin or the padding is used. However, negative values are always subtracted.
-    * Finally, indent offsets the object from edges of its container. This offset is
-    * calculated after margin and padding is applied and only to the edges touching to
-    * its container.
-    *
-    * Objects are aligned and placed using anchor points. 
-    *
-    * This system is quite close to HTML box model, however, there are differences:
-    * background and overlay can be extended beyond the area, margin collapses with
-    * padding of container and there is indent to control distance from edges. 
-    * All objects have margin and indent while only containers have extensions, 
-    * border size, and padding.
-    * 
-    * [Might need rewording.]
-    */
-
     // TextPlaceholder
     // TextPlaceholder should have its own layer (same for others?)
-    // Obtained size, position, think about animation frame
+    // Obtained size, position
     // 
 
     /// Anchor position
@@ -149,18 +33,19 @@
         /// This anchor position should is only used to denote object will
         /// not be anchored to a previous object, only to its parent. If
         /// used as parent anchor it will be ignored and default anchor
-        /// will be used instead.
+        /// will be used instead. This should be paired with absolute 
+        /// positioning.
         None = 0,
         
         /// Top left
-        TopLeft,
+        TopLeft = 1,
         /// Top center
         TopCenter,
         /// Top right
         TopRight,
 
         /// Middle left
-        MiddleLeft,
+        MiddleLeft = 4,
         /// Middle center, using this position ensures that the
         /// components will be inside each other.
         MiddleCenter,
@@ -168,30 +53,26 @@
         MiddleRight,
         
         /// Bottom left
-        BottomLeft,
+        BottomLeft = 7,
         /// Bottom center
         BottomCenter,
         /// Bottom right
         BottomRight,
         
         /// Baseline left, for text, this aligns to the baseline of
-        /// the last line; if there is no text related data, this will
-        /// align to the middle left.
+        /// the first line
         FirstBaselineLeft,
         /// Baseline right, for text, this aligns to the baseline of
-        /// the last line; if there is no text related data, this will
-        /// align to the middle right.
+        /// the first line
         FirstBaselineRight,
         
         /// Baseline left, for text, this aligns to the baseline of
-        /// the last line; if there is no text related data, this will
-        /// align to the bottom left. This mode only works properly if
+        /// the last line. This mode only works properly if
         /// Sizing is set to automatic.
         LastBaselineLeft,
         
         /// Baseline right, for text, this aligns to the baseline of
-        /// the last line; if there is no text related data, this will
-        /// align to the bottom right. This mode only works properly if
+        /// the last line. This mode only works properly if
         /// Sizing is set to automatic.
         LastBaselineRight,
     };
@@ -242,6 +123,8 @@
             case Anchor::TopRight:
             case Anchor::TopLeft:
             case Anchor::TopCenter:
+            case Anchor::FirstBaselineLeft:
+            case Anchor::FirstBaselineRight:
                 return true;
             default:
                 return false;
@@ -268,8 +151,6 @@
             case Anchor::MiddleLeft:
             case Anchor::MiddleRight:
             case Anchor::MiddleCenter:
-            case Anchor::FirstBaselineLeft:
-            case Anchor::FirstBaselineRight:
                 return true;
             default:
                 return false;
@@ -304,10 +185,10 @@
         /// Component is visible when the widget is readonly.
         Readonly,
 
-        
+        /// Widget has the focus
         Focused,
 
-        
+        /// Mouse is over the widget, or over a particular repeat
         Hover,
         
         /// This is activated when the mouse is pressed on the component stack. However,
@@ -315,10 +196,13 @@
         Down,
         
 
+        /// Second state of the widget, first state is Always
         State2,
 
+        /// Third state of the widget, first state is Always
         State3,
 
+        /// Fourth state of the widget, first state is Always
         State4,
 
         /// This condition is triggered when the widget is opened like a combobox
@@ -334,12 +218,16 @@
         /// for the base state.
         Closed,
         
+        /// This is for widgets that can be activated, like a count down timer
         Active,
         
+        /// There is space horizontally to be scrolled
         HScroll,
         
+        /// There is space vertically to be scrolled.
         VScroll,
         
+        /// There is space both horizontally and vertically to be scrolled.
         HVScroll,
 
         /// Channel 1 value is 0, the value will be
@@ -644,11 +532,26 @@
             else
                 return 0;
         }
+        
+        /// Sets the spacing required for this template. Organizer widgets
+        /// uses this spacing in order to layout the widgets.
+        void SetSpacing(int value) {
+            spacing = value;
+            ChangedEvent();
+        }
+        
+        /// Returns the spacing required for this template. Organizer widgets
+        /// uses this spacing in order to layout the widgets.
+        int GetSpacing() const {
+            return spacing;
+        }
 
 
         /// This event is fired whenever template or its components are changed.
         Event<Template> ChangedEvent = Event<Template>{*this};
         
+        std::string Name;
+        
     private:
         Containers::Collection<ComponentTemplate> components;
         std::vector<Event<ComponentTemplate>::Token> tokens;
@@ -657,6 +560,7 @@
         SizeMode xsizing = Free, ysizing = Free;
         Geometry::Size size;
         Geometry::Size additional = {0, 0};
+        int spacing = 4;
     };
 
     /// Defines an object according to the Box Model.
@@ -717,18 +621,25 @@
             
             Label,
 
+            //Value texts can automatically be calculated depending on the widget
             ValueText1,
 
+            //Value texts can automatically be calculated depending on the widget
             ValueText2,
 
+            //Value texts can automatically be calculated depending on the widget
             ValueText3,
 
+            //Value texts can automatically be calculated depending on the widget
             ValueText4,
             
             State1Text,
             State2Text,
             State3Text,
             State4Text,
+            
+            AutoStart = ValueText1,
+            AutoEnd   = State4Text,
 
             /// Data will effect the displayed graphics
             Icon,
@@ -1112,7 +1023,7 @@
         /// Returns how the data will affect this component
         DataEffect GetDataEffect() const { return dataeffect; }
         
-        /// Changes the ordering of the values. This allows swaps like X-Y. 
+        /// Changes the ordering of the values. This allows swaps like X-Y. You should specify which channel will receive which value. 
         void SetValueOrdering(int first, int second, int third, int fourth) {
             valueordering = {{first, second, third, fourth}};
             
@@ -1249,6 +1160,14 @@
 
 
 
+        /// Changes the baseline of the current component. If set to 0, it will be determined automatically.
+        void SetBaseline(int value) { baseline = value; ChangedEvent(); } 
+
+        /// Returns the baseline. If set to 0, it will be detected automatically
+        int GetBaseline() const { return baseline; }
+
+
+
         /// Changes the index of the current component. Only one component can be rendered at an index which is
         /// determined by the component condition. See component indexing for more information.
         void SetIndex(int value) { index = value; ChangedEvent(); } 
@@ -1348,7 +1267,7 @@
         SizingMode sizingw = Fixed, sizingh = Fixed;
 
         /// Size of the object.
-        Size size = {0, 0};
+        Size size = {{100, Dimension::Percent}, {100, Dimension::Percent}};
 
         /// Margin around the object, will be collapsed with other object margins
         /// and padding
@@ -1358,20 +1277,23 @@
         Margin indent = {0};
         
         /// Center point for rotation
-        Point center = {0, 0};
+        Point center = {{50, Dimension::Percent}, {50, Dimension::Percent}};
 
         /// Anchor point of the previous component that this component will be attached
         /// to. If the component positioning is absolute or this is the first component, 
         /// it will be anchored to the container and parent anchor point will be used.
-        Anchor previous = Anchor::FirstBaselineRight;
+        Anchor previous = Anchor::TopRight;
         
         /// Anchor point of the container that this component will be attached to, if it
         /// is attaching to its parent.
-        Anchor container = Anchor::MiddleLeft;
+        Anchor container = Anchor::TopLeft;
 
         /// Anchor point of the current component. This point will be matched to the
         /// previous component's anchor point
-        Anchor my = Anchor::FirstBaselineLeft;
+        Anchor my = Anchor::TopLeft;
+        
+        /// Manually set baseline for this component. When 0, it will not be effective.
+        int baseline = 0;
 
         /// Component index. Only one component can exist for a specific index position.
         /// The ordering and visibility of the components will be determined from the condition.
@@ -1421,9 +1343,18 @@
         const Template *temp = nullptr;
     };
 
+    /**
+     * Textholder is designed to hold text data. This data is set by the widget through
+     * DataEffect. Alignment for this component uses baseline and it is automatically sized.
+     */
     class TextholderTemplate : public ComponentTemplate {
     public:
-        
+        TextholderTemplate() {
+            my = Anchor::FirstBaselineLeft;
+            previous = Anchor::FirstBaselineRight;
+            container = Anchor::FirstBaselineLeft;
+            SetSizing(Automatic);
+        }
 
         /// Returns the type of the component.
         virtual ComponentType GetType() const noexcept override {
@@ -1469,11 +1400,25 @@
         Graphics::RGBAf GetTargetColor() const {
             return targetcolor;
         }
+        
+        /// Sets the default text for the textholder. This text can be overriden
+        /// by DataEffect
+        void SetText(const std::string &value) {
+            text = value;
+            
+            ChangedEvent();
+        }
+        
+        /// Returns the default text for the textholder.
+        std::string GetText() const {
+            return text;
+        }
     
     private:
         const Graphics::TextRenderer *renderer = nullptr;
         Graphics::RGBAf color = 1.0f;
         Graphics::RGBAf targetcolor = 0.f;
+        std::string text;
     };
 
     class VisualProvider {
@@ -1584,24 +1529,7 @@
             return ComponentType::Graphics;
         }
         
-        /// Changes the padding of the component. Padding is the minimum spacing inside the component.
-        void SetPadding(int value) { padding = {value}; ChangedEvent(); }
-
-        /// Changes the padding of the component. Padding is the minimum spacing inside the component.
-        void SetPadding(int hor, int ver) { padding = {hor, ver}; ChangedEvent(); }
-
-        /// Changes the padding of the component. Padding is the minimum spacing inside the component.
-        void SetPadding(int left, int top, int right, int bottom) {
-            padding ={left, top, right, bottom};
-            ChangedEvent();
-        }
-
-        /// Changes the padding of the component. Padding is the minimum spacing inside the component.
-        void SetPadding(Geometry::Margin value) { padding = value; ChangedEvent(); }
-
-        /// Returns the padding.
-        Geometry::Margin GetPadding() const { return padding; }
-
+        /// TODO: add size controller
         
         /// Set to true if you want to fill the region with the given graphics. This will
         /// only work if the given animation/drawable is rectangular
@@ -1732,7 +1660,7 @@
 
         /// Changes the overlay extent of the component. Overlay extent stays within the object area, but excluded
         /// from the interior area.
-        void SetOverlayExtent(int value) { padding ={value}; ChangedEvent(); }
+        void SetOverlayExtent(int value) { overlayextent ={value}; ChangedEvent(); }
 
         /// Changes the overlay extent of the component. Overlay extent stays within the object area, but excluded
         /// from the interior area.
@@ -1758,9 +1686,11 @@
         /// Adds an index to the container. The components will be drawn in order. Thus the components that are added
         /// later will be drawn on top. Multiple indexes will not cause any crashes, however, same component might be drawn 
         /// multiple times on top of itself.
-        void AddIndex(int componentindex) {
+        ContainerTemplate &AddIndex(int componentindex) {
             indices.push_back(componentindex);
             ChangedEvent();
+            
+            return *this;
         }
 
         /// Insert an index to the specified location in the container. The components will be drawn in order. Thus the 
--- a/Source/Gorgon/UI/UI.cpp	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/UI/UI.cpp	Thu Sep 17 16:29:02 2020 +0300
@@ -9,13 +9,13 @@
     Widgets::Generator *generator = nullptr;
     
     //create a default widget registry.
-    void Initialize(std::string fontname, int density, int min) {
-        int fh = WindowManager::Monitor::Primary().GetSize().Width / density;
+    void Initialize(std::string fontname, float density, int min) {
+        int fh = int(std::round(sqrt(WindowManager::Monitor::Primary().GetSize().Width / (density+0.6f))));
         
         if(fh < min) 
             fh = min;
         
-        generator = new Widgets::SimpleGenerator(fh, fontname);
+        generator = new Widgets::SimpleGenerator(fh, fontname, true, density);
     }
     
 }
--- a/Source/Gorgon/UI/Window.h	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/UI/Window.h	Thu Sep 17 16:29:02 2020 +0300
@@ -27,9 +27,26 @@
         Window() : Gorgon::Window() {
         }
         
-        Window(Window &&) = default;
+        Window(Window &&other) : Gorgon::Window(std::move(other)), WidgetContainer(std::move(other)) {
+            KeyEvent.Unregister(inputtoken);
+            CharacterEvent.Unregister(chartoken);
+            
+            inputtoken = keyinit();
+            chartoken  = charinit();
+        }
         
-        Window &operator=(Window &&) = default;
+        Window &operator=(Window &&other) {
+            Gorgon::Window::operator =(std::move(other));
+            WidgetContainer::operator =(std::move(other));
+            
+            KeyEvent.Unregister(inputtoken);
+            CharacterEvent.Unregister(chartoken);
+            
+            inputtoken = keyinit();
+            chartoken  = charinit();
+            
+            return *this;
+        }
         
         virtual Geometry::Size GetInteriorSize() const override {
             return Gorgon::Window::GetSize();
@@ -81,16 +98,28 @@
 
 		decltype(KeyEvent)::Token keyinit() {
 			inputtoken = KeyEvent.Register([this](Input::Key key, float amount) {
-				return WidgetContainer::KeyEvent(key, amount);
+                return WidgetContainer::KeyEvent(key, amount);
 			});
+            
+            KeyEvent.NewHandler = [this]{
+                RegisterOnce([this] {
+                    this->KeyEvent.MoveToTop(this->inputtoken);
+                });
+            };
 
 			return inputtoken;
 		}
 
-		decltype(KeyEvent)::Token charinit() {
+		decltype(CharacterEvent)::Token charinit() {
 			chartoken = CharacterEvent.Register([this](Char c) {
 				return WidgetContainer::CharacterEvent(c);
 			});
+            
+            CharacterEvent.NewHandler = [this]{
+                RegisterOnce([this] {
+                    this->CharacterEvent.MoveToTop(this->chartoken);
+                });
+            };
 
 			return chartoken;
 		}
--- a/Source/Gorgon/Utils/Assert.h	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/Utils/Assert.h	Thu Sep 17 16:29:02 2020 +0300
@@ -159,7 +159,7 @@
 		 * skip defaults to 1, depth defaults to 4, expanded defaults to false, original defaults to false
 		 */
 		#define ASSERT(expression, message, ...) do { if(!bool(expression)) { \
-			(Gorgon::Utils::CrashHandler(#expression, message, ##__VA_ARGS__)); } } while(0)
+			auto temp = Gorgon::Utils::CrashHandler(#expression, message, ##__VA_ARGS__); } } while(0)
 		
 		/** 
 		 * Replaces regular assert to allow messages and backtrace. Has four additional parameters:
@@ -169,7 +169,7 @@
 		 * skip defaults to 1, depth defaults to 4, expanded defaults to true, original defaults to true
 		 */
 		#define ASSERT_ALL(expression, message, ...) do { if(!bool(expression)) { \
-			(Gorgon::Utils::CrashHandler(Gorgon::Utils::CrashHandler::AllTag, #expression, message, ##__VA_ARGS__)); } } while(0)
+			auto temp = Gorgon::Utils::CrashHandler(Gorgon::Utils::CrashHandler::AllTag, #expression, message, ##__VA_ARGS__); } } while(0)
 
 		/** 
 		 * Replaces regular assert to allow messages and backtrace.  This variant does not crash or exit the 
@@ -180,7 +180,7 @@
 		 * skip defaults to 1, depth defaults to 4, expanded defaults to false, original defaults to false
 		 */
 		#define ASSERT_DUMP(expression, message, ...) do { if(!bool(expression)) { \
-			(Gorgon::Utils::CrashHandler(Gorgon::Utils::CrashHandler::DumpOnlyTag,#expression, message, ##__VA_ARGS__)); } } while(0)
+			auto temp = Gorgon::Utils::CrashHandler(Gorgon::Utils::CrashHandler::DumpOnlyTag,#expression, message, ##__VA_ARGS__); } } while(0)
 			
 #	endif			
 		
--- a/Source/Gorgon/Utils/ConsumableEvent.h	Wed Aug 12 16:03:46 2020 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1082 +0,0 @@
-//DESCRIPTION
-//	This file allows exposing event objects. Supports multiple events
-//	to be registered, unregister and different function signatures
-//	Event handlers are ordered and this order can be changed moreover
-//	handlers can stop chaining of the event. This system is suitable
-//	for events like mouse and keyboard events
-//	If C++0x feature lambda functionality is causing problems, define
-//	NOLAMBDA
-
-//REQUIRES:
-//	gge::utils::SortedCollection
-//	gge::utils::Any
-//	std::unordered_map
-
-//LICENSE
-//	This program is free software: you can redistribute it and/or modify
-//	it under the terms of the Lesser GNU General Public License as published by
-//	the Free Software Foundation, either version 3 of the License, or
-//	(at your option) any later version.
-//
-//	This program is distributed in the hope that it will be useful,
-//	but WITHOUT ANY WARRANTY; without even the implied warranty of
-//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-//	Lesser GNU General Public License for more details.
-//
-//	You should have received a copy of the Lesser GNU General Public License
-//	along with this program. If not, see < http://www.gnu.org/licenses/ >.
-
-//COPYRIGHT
-//	Cem Kalyoncu, DarkGaze.Org (cemkalyoncu[at]gmail[dot]com)
-
-#pragma once
-
-
-#define CONSUMABLEEVENT_EXIST
-
-
-
-#include <string>
-
-#ifndef NOLAMBDA
-#	include <functional>
-#endif
-
-
-#include "UtilsBase.h"
-#include "Any.h"
-#include "SortedCollection.h"
-#include "EventChain.h"
-#include <unordered_map>
-
-
-
-namespace gge { namespace utils {
-
-
-
-
-	template<class O_, class P_> class ConsumableEvent;
-
-
-	namespace prvt { namespace consumableevent {
-
-		////Base of an event handler
-		template <class P_, class O_>
-		struct EventHandler {
-			Any data;
-
-			bool enabled;
-
-			EventHandler(Any data) : data(data), enabled(true) {}
-
-			virtual ~EventHandler() {}
-
-			virtual bool Fire(P_ params, O_ &caller, std::string eventname)=0;
-		};
-
-		//These template functions provide pseudo inheritance for these functions
-		//every handler type must implement their of specialization
-		template <class F_,class P_, class O_>
-		EventHandler<P_, O_> *CreateEventHandler(F_ function, Any data) {
-			return NULL;
-		}
-		template <class F_, class R_, class P_, class O_>
-		EventHandler<P_, O_> *CreateEventHandler(R_ *object, F_ function, Any data) {
-			return NULL;
-		}
-
-		template <class F_,class P_, class O_>
-		bool Compare(EventHandler<P_, O_> *obj, F_ function) {
-			return false;
-		}
-		template <class F_, class R_, class P_, class O_>
-		bool Compare(EventHandler<P_,O_> *obj, R_ *object, F_ function) {
-			return false;
-		}
-		template <class F_, class R_, class P_, class O_>
-		bool Compare(EventHandler<P_,O_> *obj, R_ &object, F_ function) {
-			return Compare(obj, &object, function);
-		}
-
-
-
-		////This is private event object that is used to
-		/// store function event handlers
-		template<class P_, class O_>
-		struct EventHandlerFunction : public EventHandler<P_, O_> {
-			bool(*handler)(P_, O_ &, Any Data, std::string);
-
-			EventHandlerFunction(bool(*handler)(P_, O_ &, Any Data, std::string), Any data) : EventHandler<P_, O_>(data), handler(handler) {}
-
-			virtual bool Fire(P_ params, O_ &caller, std::string eventname) {
-				return (*handler)(params, caller, EventHandler<P_, O_>::data, eventname);
-			}
-
-		};
-		template <class P_, class O_>
-		EventHandler<P_, O_> *CreateEventHandler( bool(*function)(P_, O_ &, Any Data, std::string), Any data) {
-			return new EventHandlerFunction<P_, O_>(function, data);
-		}
-
-		template <class P_, class O_>
-		bool Compare(EventHandler<P_, O_> *obj, bool(*function)(P_, O_ &, Any Data, std::string)) {
-			if(!dynamic_cast<EventHandlerFunction<P_,O_>*>(obj))
-				return false;
-
-			return function==dynamic_cast<EventHandlerFunction<P_,O_>*>(obj)->handler;
-		}
-		////This is private event object that is used to
-		/// store function event handlers
-		template<class P_, class O_>
-		struct EventHandlerFunctionPlain : public EventHandler<P_, O_> {
-			bool(*handler)(P_, O_ &);
-
-			EventHandlerFunctionPlain(bool(*handler)(P_, O_ &)) : EventHandler<P_, O_>(NULL), handler(handler) {}
-
-			virtual bool Fire(P_ params, O_ &caller, std::string eventname) {
-				return (*handler)(params, caller);
-			}
-
-			bool Compare(bool(*function)(P_, O_ &), void*) {
-				if(handler==function)
-					return true;
-			}
-		};
-
-		template <class P_, class O_>
-		EventHandler<P_, O_> *CreateEventHandler( bool(*function)(P_, O_ &), Any data) {
-			return new EventHandlerFunctionPlain<P_, O_>(function);
-		}
-
-		template <class P_, class O_>
-		bool Compare(EventHandler<P_, O_> *obj, bool(*function)(P_, O_ &)) {
-			if(!dynamic_cast<EventHandlerFunctionPlain<P_,O_>*>(obj))
-				return false;
-
-			return function==dynamic_cast<EventHandlerFunctionPlain<P_,O_>*>(obj)->handler;
-		}
-
-		////This is private event object that is used to
-		/// store function event handlers
-		template<class P_, class O_>
-		struct EventHandlerFunctionEmpty : public EventHandler<P_, O_> {
-			bool(*handler)();
-
-			EventHandlerFunctionEmpty(bool(*handler)()) : EventHandler<P_, O_>(Any()), handler(handler) {}
-
-			virtual bool Fire(P_ params, O_ &caller, std::string eventname) {
-				return (*handler)();
-			}
-
-			bool Compare(bool(*function)(), void*) {
-				if(handler==function)
-					return true;
-			}
-		};
-
-
-		template <class P_, class O_>
-		EventHandler<P_, O_> *CreateEventHandler( bool(*function)(), Any data) {
-			return new EventHandlerFunctionEmpty<P_, O_>(function);
-		}
-		template <class P_, class O_>
-		bool Compare(EventHandler<P_, O_> *obj, bool(*function)()) {
-			if(!dynamic_cast<EventHandlerFunctionEmpty<P_,O_>*>(obj))
-				return false;
-
-			return function==dynamic_cast<EventHandlerFunctionEmpty<P_,O_>*>(obj)->handler;
-		}
-		////This is private event object that is used to
-		/// store function event handlers
-		template<class P_, class O_>
-		struct EventHandlerFunctionObjectOnly : public EventHandler<P_, O_> {
-			bool(*handler)(O_ &);
-
-			EventHandlerFunctionObjectOnly(bool(*handler)(O_ &)) : EventHandler<P_, O_>(Any()), handler(handler) {}
-
-			virtual bool Fire(P_ params, O_ &caller, std::string eventname) {
-				return (*handler)(caller);
-			}
-
-			bool Compare(bool(*function)(O_ &), void*) {
-				if(handler==function)
-					return true;
-			}
-		};
-
-
-		template <class P_, class O_>
-		EventHandler<P_, O_> *CreateEventHandler( bool(*function)(O_ &), Any data) {
-			return new EventHandlerFunctionObjectOnly<P_, O_>(function);
-		}
-		template <class P_, class O_>
-		bool Compare(EventHandler<P_, O_> *obj, bool(*function)(O_ &)) {
-			if(!dynamic_cast<EventHandlerFunctionObjectOnly<P_,O_>*>(obj))
-				return false;
-
-			return function==dynamic_cast<EventHandlerFunctionObjectOnly<P_,O_>*>(obj)->handler;
-		}
-		////This is private event object that is used to
-		/// store function event handlers
-		template<class P_, class O_>
-		struct EventHandlerFunctionParamOnly : public EventHandler<P_, O_> {
-			bool(*handler)(P_);
-
-			EventHandlerFunctionParamOnly(bool(*handler)(P_)) : EventHandler<P_, O_>(Any()), handler(handler) {}
-
-			virtual bool Fire(P_ params, O_ &caller, std::string eventname) {
-				return (*handler)(params);
-			}
-
-			bool Compare(bool(*function)(P_), void*) {
-				if(handler==function)
-					return true;
-			}
-		};
-		template <class P_, class O_>
-		EventHandler<P_, O_> *CreateEventHandler( bool(*function)(P_), Any data) {
-			return new EventHandlerFunctionParamOnly<P_, O_>(function);
-		}
-
-		template <class P_, class O_>
-		bool Compare(EventHandler<P_, O_> *obj, bool(*function)(P_)) {
-			if(!dynamic_cast<EventHandlerFunctionParamOnly<P_,O_>*>(obj))
-				return false;
-
-			return function==dynamic_cast<EventHandlerFunctionParamOnly<P_,O_>*>(obj)->handler;
-		}
-		////This is private event object that is used to
-		/// store function event handlers
-		template<class P_, class O_>
-		struct EventHandlerFunctionDataOnly : public EventHandler<P_, O_> {
-			bool(*handler)(Any);
-
-			EventHandlerFunctionDataOnly(bool(*handler)(Any), Any data) : EventHandler<P_, O_>(data), handler(handler) {}
-
-			virtual bool Fire(P_ params, O_ &caller, std::string eventname) {
-				return (*handler)(EventHandler<P_, O_>::data);
-			}
-
-		};
-		template <class P_, class O_>
-		EventHandler<P_, O_> *CreateEventHandler( bool(*function)(Any Data), Any data) {
-			return new EventHandlerFunctionDataOnly<P_, O_>(function, data);
-		}
-
-		template <class P_, class O_>
-		bool Compare(EventHandler<P_, O_> *obj, bool(*function)(Any Data)) {
-			if(!dynamic_cast<EventHandlerFunctionDataOnly<P_,O_>*>(obj))
-				return false;
-
-			return function==dynamic_cast<EventHandlerFunctionDataOnly<P_,O_>*>(obj)->handler;
-		}
-
-		////This is private event object that is used to
-		/// store function event handlers
-		template<class P_, class O_>
-		struct EventHandlerFunctionObjectAndData : EventHandler<P_, O_> {
-			bool(*handler)(O_ &, Any);
-
-			EventHandlerFunctionObjectAndData(bool(*handler)(O_ &, Any), Any data) : EventHandler<P_, O_>(data), handler(handler) {}
-
-			virtual bool Fire(P_ params, O_ &caller, std::string eventname) {
-				return (*handler)(caller,EventHandler<P_, O_>::data);
-			}
-
-			bool Compare(bool(*function)(O_ &, Any), void*) {
-				if(handler==function)
-					return true;
-			}
-		};
-
-		template <class P_, class O_>
-		EventHandler<P_, O_> *CreateEventHandler( bool(*function)(O_ &, Any), Any data) {
-			return new EventHandlerFunctionObjectAndData<P_, O_>(function,data);
-		}
-		template <class P_, class O_>
-		bool Compare(EventHandler<P_, O_> *obj, bool(*function)(O_ &, Any)) {
-			if(!dynamic_cast<EventHandlerFunctionObjectAndData<P_,O_>*>(obj))
-				return false;
-
-			return function==dynamic_cast<EventHandlerFunctionObjectAndData<P_,O_>*>(obj)->handler;
-		}
-
-		////This is private event object that is used to
-		/// store function event handlers
-		template<class R_, class P_, class O_>
-		struct EventHandlerClass : public EventHandler<P_,O_> {
-			bool(R_::*handler)(P_, O_ &, Any, std::string);
-
-			R_ *object;
-
-			EventHandlerClass(R_ *object, bool(R_::*handler)(P_, O_ &, Any, std::string), Any data) : EventHandler<P_, O_>(data), object(object), handler(handler) {}
-
-			virtual bool Fire(P_ params, O_ &caller, std::string eventname) {
-				return (object->*handler)(params, caller, EventHandler<P_,O_>::data, eventname);
-			}
-
-		};
-
-		template <class R_, class P_, class O_>
-		EventHandler<P_, O_> *CreateEventHandler(R_ *object, bool(R_::*function)(P_, O_ &, Any, std::string), Any data) {
-			return new EventHandlerClass<R_, P_, O_>(object, function, data);
-		}
-		template <class R_, class P_, class O_>
-		bool Compare(EventHandler<P_,O_> *obj, R_ *object, bool(R_::*function)(P_, O_ &, Any, std::string)) {
-			if(!dynamic_cast<EventHandlerClass<R_, P_,O_>*>(obj))
-				return false;
-
-			return object==dynamic_cast<EventHandlerClass<R_, P_,O_>*>(obj)->object && function==dynamic_cast<EventHandlerClass<R_, P_,O_>*>(obj)->handler;
-		}
-		////This is private event object that is used to
-		/// store function event handlers
-		template<class R_, class P_, class O_>
-		struct EventHandlerClassPlain : public EventHandler<P_,O_> {
-			bool(R_::*handler)(P_, O_ &);
-
-			R_ *object;
-
-			EventHandlerClassPlain(R_ *object, bool(R_::*handler)(P_, O_ &)) : EventHandler<P_, O_>(Any()), object(object), handler(handler) {}
-
-			virtual bool Fire(P_ params, O_ &caller, std::string eventname) {
-				return (object->*handler)(params, caller);
-			}
-
-			bool Compare(bool(R_::*function)(P_, O_ &), void* object) {
-				if((void*)handler==function && this->object==object)
-					return true;
-			}
-		};
-
-
-
-		template <class R_, class P_, class O_>
-		EventHandler<P_, O_> *CreateEventHandler(R_ *object, bool(R_::*function)(P_, O_ &), Any data) {
-			return new EventHandlerClassPlain<R_, P_, O_>(object, function);
-		}
-		template <class R_, class P_, class O_>
-		bool Compare(EventHandler<P_,O_> *obj, R_ *object, bool(R_::*function)(P_, O_ &)) {
-			if(!dynamic_cast<EventHandlerClassPlain<R_, P_,O_>*>(obj))
-				return false;
-
-			return object==dynamic_cast<EventHandlerClassPlain<R_, P_,O_>*>(obj)->object && function==dynamic_cast<EventHandlerClassPlain<R_, P_,O_>*>(obj)->handler;
-		}
-		////This is private event object that is used to
-		/// store function event handlers
-		template<class R_, class P_, class O_>
-		struct EventHandlerClassEmpty : public EventHandler<P_,O_> {
-			bool(R_::*handler)();
-
-			R_ *object;
-
-			EventHandlerClassEmpty(R_ *object, bool(R_::*handler)()) : EventHandler<P_, O_>(Any()), object(object), handler(handler) {}
-
-			virtual bool Fire(P_ params, O_ &caller, std::string eventname) {
-				return (object->*handler)();
-			}
-
-			bool Compare(bool(R_::*function)(), void* object) {
-				if((void*)handler==function && this->object==object)
-					return true;
-			}
-		};
-
-		template <class R_, class P_, class O_>
-		EventHandler<P_, O_> *CreateEventHandler(R_ *object, bool(R_::*function)(), Any data) {
-			return new EventHandlerClassEmpty<R_, P_, O_>(object, function);
-		}
-		template <class R_, class P_, class O_>
-		bool Compare(EventHandler<P_,O_> *obj, R_ *object, bool(R_::*function)()) {
-			if(!dynamic_cast<EventHandlerClassEmpty<R_, P_,O_>*>(obj))
-				return false;
-
-			return object==dynamic_cast<EventHandlerClassEmpty<R_, P_,O_>*>(obj)->object && function==dynamic_cast<EventHandlerClassEmpty<R_, P_,O_>*>(obj)->handler;
-		}
-		////This is private event object that is used to
-		/// store function event handlers
-		template<class R_, class P_, class O_>
-		struct EventHandlerClassObjectOnly : public EventHandler<P_,O_> {
-			bool(R_::*handler)(O_ &);
-
-			R_ *object;
-
-			EventHandlerClassObjectOnly(R_ *object, bool(R_::*handler)(O_ &)) : EventHandler<P_, O_>(Any()), object(object), handler(handler) {}
-
-			virtual bool Fire(P_ params, O_ &caller, std::string eventname) {
-				return (object->*handler)(caller);
-			}
-
-			bool Compare(bool(R_::*function)(O_ &), void* object) {
-				if((void*)handler==function && this->object==object)
-					return true;
-			}
-		};
-
-		template <class R_, class P_, class O_>
-		EventHandler<P_, O_> *CreateEventHandler(R_ *object, bool(R_::*function)(O_ &), Any data) {
-			return new EventHandlerClassObjectOnly<R_, P_, O_>(object, function);
-		}
-
-		template <class R_, class P_, class O_>
-		bool Compare(EventHandler<P_,O_> *obj, R_ *object, bool(R_::*function)(O_ &)) {
-			if(!dynamic_cast<EventHandlerClassObjectOnly<R_, P_,O_>*>(obj))
-				return false;
-
-			return object==dynamic_cast<EventHandlerClassObjectOnly<R_, P_,O_>*>(obj)->object && function==dynamic_cast<EventHandlerClassObjectOnly<R_, P_,O_>*>(obj)->handler;
-		}
-		////This is private event object that is used to
-		/// store function event handlers
-		template<class R_, class P_, class O_>
-		struct EventHandlerClassParamOnly : public EventHandler<P_,O_> {
-			bool(R_::*handler)(P_);
-
-			R_ *object;
-
-			EventHandlerClassParamOnly(R_ *object, bool(R_::*handler)(P_ )) : EventHandler<P_, O_>(Any()), object(object), handler(handler) {}
-
-			virtual bool Fire(P_ params, O_ &caller, std::string eventname) {
-				return (object->*handler)(params);
-			}
-
-			bool Compare(bool(R_::*function)(P_), void* object) {
-				if((void*)handler==function && this->object==object)
-					return true;
-			}
-		};
-
-
-		template <class R_, class P_, class O_>
-		EventHandler<P_, O_> *CreateEventHandler(R_ *object, bool(R_::*function)(P_), Any data) {
-			return new EventHandlerClassParamOnly<R_, P_, O_>(object, function);
-		}
-		template <class R_, class P_, class O_>
-		bool Compare(EventHandler<P_,O_> *obj, R_ *object, bool(R_::*function)(P_)) {
-			if(!dynamic_cast<EventHandlerClassParamOnly<R_, P_,O_>*>(obj))
-				return false;
-
-			return object==dynamic_cast<EventHandlerClassParamOnly<R_, P_,O_>*>(obj)->object && function==dynamic_cast<EventHandlerClassParamOnly<R_, P_,O_>*>(obj)->handler;
-		}
-		////This is private event object that is used to
-		/// store function event handlers
-		template<class R_, class P_, class O_>
-		struct EventHandlerClassDataOnly : public EventHandler<P_,O_> {
-			bool(R_::*handler)(Any);
-
-			R_ *object;
-
-			EventHandlerClassDataOnly(R_ *object, bool(R_::*handler)(Any), Any data) : EventHandler<P_, O_>(data), object(object), handler(handler) {}
-
-			virtual bool Fire(P_ params, O_ &caller, std::string eventname) {
-				return (object->*handler)(EventHandler<P_, O_>::data);
-			}
-
-			bool Compare(bool(R_::*function)(Any), void* object) {
-				if((void*)handler==function && this->object==object)
-					return true;
-			}
-		};
-
-
-		template <class R_, class P_, class O_>
-		EventHandler<P_, O_> *CreateEventHandler(R_ *object, bool(R_::*function)(Any), Any data) {
-			return new EventHandlerClassDataOnly<R_, P_, O_>(object, function, data);
-		}
-		template <class R_, class P_, class O_>
-		bool Compare(EventHandler<P_,O_> *obj, R_ *object, bool(R_::*function)(Any)) {
-			if(!dynamic_cast<EventHandlerClassDataOnly<R_, P_,O_>*>(obj))
-				return false;
-
-			return object==dynamic_cast<EventHandlerClassDataOnly<R_, P_,O_>*>(obj)->object && function==dynamic_cast<EventHandlerClassDataOnly<R_, P_,O_>*>(obj)->handler;
-		}
-
-
-#ifndef NOLAMBDA
-		////This is private event object that is used to
-		/// store function event handlers
-		template<class P_, class O_>
-		struct EventHandlerLambdaEmpty : public EventHandler<P_, O_> {
-			std::function<bool()> handler;
-
-			EventHandlerLambdaEmpty(std::function<bool()> handler) : EventHandler<P_, O_>(Any()), handler(handler) {}
-
-			virtual bool Fire(P_ params, O_ &caller, std::string eventname) {
-				return (handler)();
-			}
-
-			bool Compare(std::function<bool()> function, void*) {
-				return false;
-			}
-		};
-
-
-		template <class P_, class O_>
-		EventHandler<P_, O_> *CreateEventHandler( std::function<bool()> function, Any data) {
-			return new EventHandlerLambdaEmpty<P_, O_>(function);
-		}
-		template <class P_, class O_>
-		bool Compare(EventHandler<P_, O_> *obj, std::function<bool()> function) {
-			return false;
-		}
-
-		////This is private event object that is used to
-		/// store function event handlers
-		template<class P_, class O_>
-		struct EventHandlerLambdaParamOnly : public EventHandler<P_, O_> {
-			std::function<bool(P_)> handler;
-
-			EventHandlerLambdaParamOnly(std::function<bool(P_)> handler) : EventHandler<P_, O_>(Any()), handler(handler) {}
-
-			virtual bool Fire(P_ params, O_ &caller, std::string eventname) {
-				return (handler)(params);
-			}
-
-			bool Compare(std::function<bool(P_)> function, void*) {
-				return false;
-			}
-		};
-
-
-		template <class P_, class O_>
-		EventHandler<P_, O_> *CreateEventHandler( std::function<bool(P_)> function, Any data) {
-			return new EventHandlerLambdaParamOnly<P_, O_>(function);
-		}
-		template <class P_, class O_>
-		bool Compare(EventHandler<P_, O_> *obj, std::function<bool(P_)> function) {
-			return false;
-		}
-#endif
-
-	} }
-
-
-	////ConsumableEvent class is used to create event objects
-	/// that can be multi-handled. It is a template
-	/// so an event definer can define parameters
-	/// that can be used. Every event has an object
-	/// that is the source of the event and a name
-	/// for the event. This information is given
-	/// in constructor.
-	template<class O_=Empty, class P_=empty_event_params>
-	class ConsumableEvent {
-		template<class O2_, class P2_> friend class ConsumableEvent;
-	public:
-
-#ifdef LINUX
-		typedef std::intptr_t Token;
-#else
-		typedef int Token;
-#endif
-		static const Token NullToken = 0;
-
-		//To be used by owner
-		std::vector<std::pair<P_, Token>> TokenList;
-
-		////Constructor
-		///@Name	: Name of the event
-		///@Object	: Source of the event
-		ConsumableEvent(std::string Name,O_ *Object=NULL) :
-		eventname(Name), object(Object)
-		{ }
-
-		////Constructor
-		///@Name	: Name of the event
-		///@Object	: Source of the event
-		ConsumableEvent(O_ *Object=NULL) :
-		eventname(""), object(Object)
-		{ }
-
-		////Constructor
-		///@Name	: Name of the event
-		///@Object	: Source of the event
-		ConsumableEvent(std::string Name,O_ &Object) :
-		eventname(Name), object(&Object)
-		{ }
-
-		////Constructor
-		///@Name	: Name of the event
-		///@Object	: Source of the event
-		ConsumableEvent(O_ &Object) :
-		eventname(""), object(&Object)
-		{ }
-
-		void SetToken(P_ params, Token t) {
-			for(auto it=TokenList.begin(); it!=TokenList.end(); ++it) {
-				if(it->first==params) {
-					it->second=t;
-					return;
-				}
-			}
-
-			TokenList.push_back(std::pair<P_, Token>(params, t));
-		}
-
-		Token FindToken(P_ params) const {
-			for(auto it=TokenList.begin(); it!=TokenList.end(); ++it) {
-				if(it->first==params) {
-					return it->second;
-				}
-			}
-
-			return NullToken;
-		}
-
-		void RemoveToken(P_ params) {
-			for(auto it=TokenList.begin(); it!=TokenList.end(); ++it) {
-				if(it->first==params) {
-					TokenList.erase(it);
-					return;
-				}
-			}
-		}
-
-		////Registers an event handler. Every event handler
-		/// can specify EventHandler<P_, O_>::data to be passed to handler
-		/// that can be used to identify who is registered
-		/// the event. This function returns event token
-		/// that can be used to remove this handler. The
-		/// token is not an id or sequential number
-		/// therefore, it should not be altered to find other
-		/// handlers. Handler function template is
-		/// void Handler(Parameters params, CallerObject* object, any EventHandler<P_, O_>::data, std::string eventname)
-		///@handler	: handler function
-		///@data	: data to be passed to handler
-		template<class F_>
-		Token Register(F_ *handler, Any data=Any()) {
-			return AddHandler(
-				prvt::consumableevent::CreateEventHandler<P_, O_>(handler, data)
-			);
-		}
-
-		////Registers an event handler. Every event handler
-		/// can specify EventHandler<P_, O_>::data to be passed to handler
-		/// that can be used to identify who is registered
-		/// the event. This function returns event token
-		/// that can be used to remove this handler. The
-		/// token is not an id or sequential number
-		/// therefore, it should not be altered to find other
-		/// handlers. Handler function template is
-		/// void Handler(Parameters params, CallerObject* object, any EventHandler<P_, O_>::data, std::string eventname)
-		///@handler	: handler function
-		///@data	: data to be passed to handler
-		template<class F_>
-		Token Register(F_ *handler, int order, Any data=Any()) {
-			return AddHandler(
-				prvt::consumableevent::CreateEventHandler<P_, O_>(handler, data),
-				order
-			);
-		}
-
-
-		////Registers a class event handler. This handler
-		/// should be a non static function of
-		/// the given object. Event handler
-		/// can specify EventHandler<P_, O_>::data to be passed to handler
-		/// that can be used to identify who is registered
-		/// the event. This function returns event token
-		/// that can be used to remove this handler. The
-		/// token is not an id or sequential number
-		/// therefore, it should not be altered to find other
-		/// handlers. Handler function full template is
-		/// void Handler(Parameters params, CallerObject* object, any EventHandler<P_, O_>::data, std::string eventname)
-		/// EventParams parameters)
-		///@receiver: handler object
-		///@handler	: handler function
-		///@data	: data to be passed to handler
-		template<class R_, class F_>
-		Token Register(R_ *receiver, F_ handler, Any data=Any()) {
-			return AddHandler(
-				prvt::consumableevent::CreateEventHandler<R_, P_, O_>(receiver, handler, data)
-			);
-		}
-		template<class R_, class F_>
-		Token Register(R_ *receiver, F_ handler, int order, Any data=Any()) {
-			return AddHandler(
-				prvt::consumableevent::CreateEventHandler<R_, P_, O_>(receiver, handler, data),
-				order
-			);
-		}
-
-		////Registers a class event handler. This handler
-		/// should be a non static function of
-		/// the given object. Event handler
-		/// can specify data to be passed to handler
-		/// that can be used to identify who is registered
-		/// the event. This function returns event token
-		/// that can be used to remove this handler. The
-		/// token is not an id or sequential number
-		/// therefore, it should not be altered to find other
-		/// handlers. Handler function full template is
-		/// void Handler(Parameters params, CallerObject* object, any data, std::string eventname)
-		/// EventParams parameters)
-		///@receiver: handler object
-		///@handler	: handler function
-		///@data	: EventHandler<P_, O_>::data to be passed to handler
-		template<class R_, class F_>
-		Token Register(R_ &receiver, F_ handler, Any data=Any()) {
-			return Register(&receiver, handler, data);
-		}
-		template<class R_, class F_>
-		Token Register(R_ &receiver, F_ handler, int order, Any data=Any()) {
-			return Register(&receiver, handler, order, data);
-		}
-
-		template<class R_, class F_>
-		Token RegisterClass(R_ *receiver, F_ handler, Any data=Any()) {
-			return AddHandler(
-				prvt::consumableevent::CreateEventHandler<R_, P_, O_>(receiver, handler, data)
-			);
-		}
-
-		template<class R_, class F_>
-		Token RegisterClass(R_ *receiver, F_ handler, int order, Any data=Any()) {
-			return AddHandler(
-				prvt::consumableevent::CreateEventHandler<R_, P_, O_>(receiver, handler, data),
-				order
-			);
-		}
-
-		template<class R_, class F_>
-		Token RegisterClass(R_ &receiver, F_ handler, Any data=Any()) {
-			return RegisterClass(receiver, handler, data);
-		}
-
-		template<class R_, class F_>
-		Token RegisterClass(R_ &receiver, F_ handler, int order, Any data=Any()) {
-			return RegisterClass(receiver, handler, order, data);
-		}
-
-#ifndef NOLAMBDA
-		template <class F_>
-		typename count_arg<F_, 0, Token>::type RegisterLambda(F_ handler, int order) {
-			return AddHandler(
-				prvt::consumableevent::CreateEventHandler<P_, O_>(std::function<bool()>(handler), Any()),
-				order
-			);
-		}
-		template <class F_>
-		typename count_arg<F_, 1, Token>::type RegisterLambda(F_ handler, int order) {
-			return AddHandler(
-				prvt::consumableevent::CreateEventHandler<P_, O_>(std::function<bool(P_)>(handler), Any()),
-				order
-			);
-		}
-		template <class F_>
-		typename count_arg<F_, 0, Token>::type RegisterLambda(F_ handler) {
-			return AddHandler(
-				prvt::consumableevent::CreateEventHandler<P_, O_>(std::function<bool()>(handler), Any())
-			);
-		}
-		template <class F_>
-		typename count_arg<F_, 1, Token>::type RegisterLambda(F_ handler) {
-			return AddHandler(
-				prvt::consumableevent::CreateEventHandler<P_, O_>(std::function<bool(P_)>(handler), Any())
-			);
-		}
-#endif
-
-		template<class R_>
-		Token LinkTo(ConsumableEvent<R_, P_> &target) {
-			return AddHandler(
-				prvt::consumableevent::CreateEventHandler<ConsumableEvent<R_, P_>, P_, O_>(
-					&target,
-					(bool(ConsumableEvent<R_,P_>::*)(P_))&ConsumableEvent<R_, P_>::Fire,
-					Any()
-				)
-			);
-		}
-
-		template<class R_>
-		Token LinkTo(ConsumableEvent<R_, P_> &target, int order) {
-			return AddHandler(
-				prvt::consumableevent::CreateEventHandler<ConsumableEvent<R_, P_>, P_, O_>(
-					&target,
-					(bool(ConsumableEvent<R_,P_>::*)(P_))&ConsumableEvent<R_, P_>::Fire,
-					Any()
-				),
-				order
-			);
-		}
-
-		template<class R_>
-		Token DoubleLink(ConsumableEvent<R_, P_> &target) {
-			typedef bool(ConsumableEvent<O_,P_>::*MyFire	)(P_) ;
-			typedef bool(ConsumableEvent<R_,P_>::*TargetFire)(P_);
-
-			target.RegisterClass< ConsumableEvent<O_, P_>, MyFire >(
-				this,
-				(MyFire) &ConsumableEvent<R_, P_>::linkedfire,
-				NULL
-			);
-
-			return AddHandler(
-				prvt::consumableevent::CreateEventHandler<ConsumableEvent<R_, P_>, P_, O_>(
-					&target,
-					(TargetFire) &ConsumableEvent<R_, P_>::linkedfire,
-					NULL
-				)
-			);
-		}
-
-		template<class R_>
-
-		Token DoubleLink(ConsumableEvent<R_, P_> &target, int order) {
-			typedef bool(ConsumableEvent<O_,P_>::*MyFire	)(P_) ;
-			typedef bool(ConsumableEvent<R_,P_>::*TargetFire)(P_);
-
-			target.RegisterClass< ConsumableEvent<O_, P_>, MyFire >(
-				this,
-				(MyFire) &ConsumableEvent<R_, P_>::linkedfire,
-				order,
-				Any()
-			);
-
-			return AddHandler(
-				prvt::consumableevent::CreateEventHandler<ConsumableEvent<R_, P_>, P_, O_>(
-					&target,
-					(TargetFire) &ConsumableEvent<R_, P_>::linkedfire,
-					Any()
-				), order
-			);
-		}
-
-		////Unregisters the given event handler using handler function
-		template<class F_>
-		Token Find(F_ handler) {
-			for(auto it=events.First(); it.IsValid(); it.Next()) {
-				if(Compare(&(*it), handler)) {
-
-					return reinterpret_cast<Token> (&it.GetWrapper());
-				}
-			}
-		}
-
-		////Unregisters the given handler referenced by the object and function
-		template<class R_, class F_>
-		Token Find(R_ *obj, F_ handler) {
-			for(auto it=events.First(); it.IsValid(); it.Next()) {
-				if(Compare(&(*it), obj, handler)) {
-
-					return reinterpret_cast<Token> (&it.GetWrapper());
-				}
-			}
-		}
-
-		////Unregisters the given event handler using handler function
-		template<class F_>
-		void Unregister(F_ handler) {
-			for(auto it=events.First(); it.IsValid(); it.Next()) {
-				if(Compare(&(*it), handler)) {
-					Unregister(reinterpret_cast<Token>(&it.GetWrapper()));
-					return;
-				}
-			}
-		}
-
-		////Unregisters the given handler referenced by the object and function
-		template<class R_, class F_>
-		void Unregister(R_ *obj, F_ handler) {
-			for(auto it=events.First(); it.IsValid(); it.Next()) {
-				if(Compare(&(*it),obj, handler)) {
-					Unregister(reinterpret_cast<Token>(&it.GetWrapper()));
-					return;
-				}
-			}
-		}
-
-		template<class R_, class F_>
-		void UnregisterClass(R_ &obj, F_ handler) {
-			Unregister(&obj, handler);
-		}
-
-		////Unregisters the given handler referenced by the object and function
-		template<class R_, class F_>
-		void UnregisterClass(R_ *obj, F_ handler) {
-			for(auto it=events.First(); it.IsValid(); it.Next()) {
-				if(Compare(&(*it), obj, handler)) {
-					Unregister(reinterpret_cast<Token>(&it.GetWrapper()));
-					return;
-				}
-			}
-		}
-
-		////Unregisters the given handler referenced by the object and function
-		template<class R_, class F_>
-		void Unregister(R_ &obj, F_ handler) {
-			Unregister(&obj, handler);
-		}
-
-		////Unregisters a given handler token
-		void Unregister(Token token) {
-			for(auto i=TokenList.begin();i!=TokenList.end();++i) {
-				if(i->second==token)
-					i->second=NullToken;
-			}
-
-			reinterpret_cast< ITEMTYPE_* >(token)->Delete();
-		}
-
-		void MakeFirst(Token token) {
-			ITEMTYPE_ *item=reinterpret_cast<ITEMTYPE_*>(token);
-
-			item->setOrder(events.LowestOrder()-1);
-		}
-
-		void MakeLast(Token token) {
-			ITEMTYPE_ *item=reinterpret_cast<ITEMTYPE_*>(token);
-
-			item->setOrder(events.HighestOrder()-1);
-		}
-
-		int GetOrder(Token token) {
-			ITEMTYPE_ *item=reinterpret_cast<ITEMTYPE_*>(token);
-
-			return item->getOrder();
-		}
-
-		bool IsFirst(Token token) {
-			ITEMTYPE_ *item=reinterpret_cast<ITEMTYPE_*>(token);
-
-			return item==events.getOrderedFirst();
-		}
-
-		bool IsLast(Token token) {
-			ITEMTYPE_ *item=reinterpret_cast<ITEMTYPE_*>(token);
-
-			return item==events.getOrderedLast();
-		}
-
-		void SetOrder(Token token, int order) {
-			ITEMTYPE_ *item=reinterpret_cast<ITEMTYPE_*>(token);
-
-			item->Reorder(order);
-		}
-
-		void Enable(Token token) {
-			ITEMTYPE_ *item=reinterpret_cast<ITEMTYPE_*>(token);
-
-			item->Get().enabled=true;
-		}
-
-		void Disable(Token token) {
-			ITEMTYPE_ *item=reinterpret_cast<ITEMTYPE_*>(token);
-
-			item->Get().enabled=false;
-		}
-
-		bool IsEnabled(Token token) {
-			ITEMTYPE_ *item=reinterpret_cast<ITEMTYPE_*>(token);
-
-			return item->Get().enabled;
-		}
-
-		bool Fire(Token token, P_ params) {
-			if(token==NullToken)
-				return false;
-
-			return reinterpret_cast< ITEMTYPE_* >(token)->Get().Fire(params, *this->object, eventname);
-		}
-
-		bool Fire(Token token) {
-			return Fire(token, P_());
-		}
-
-		////This function triggers the event causing all
-		/// handlers to be called
-		Token operator()(P_ params) {
-			return Fire(params);
-		}
-
-		////This function triggers the event causing all
-		/// handlers to be called
-		Token operator()() {
-			return Fire();
-		}
-
-		////This function triggers the event causing all
-		/// handlers to be called
-		Token Fire(P_ params) {
-			for(auto it=events.First();it.IsValid();it.Next()) {
-				if(it->enabled)
-					if(it->Fire(params, *this->object, eventname))
-						return reinterpret_cast<Token>(&it.GetWrapper());
-			}
-
-			return 0;
-		}
-
-		////This function triggers the event causing all
-		/// handlers to be called
-		Token Fire() {
-			return Fire(P_());
-		}
-
-		const std::string &GetName() const { return eventname; }
-
-		void SetName(const std::string &name) {
-			eventname=name;
-		}
-
-		~ConsumableEvent() {
-			events.Destroy();
-
-		}
-
-	protected:
-		typedef typename SortedCollection<prvt::consumableevent::EventHandler<P_, O_>, int>::Wrapper ITEMTYPE_ ;
-		typedef prvt::consumableevent::EventHandler<P_, O_> HANDLER_;
-		////Name of the event
-		std::string eventname;
-		////Source of the events
-		O_ *object;
-		////Collection of event handlers
-		SortedCollection<HANDLER_,int> events;
-
-		////Unregisters a given handler token
-		void RemoveHandler(ITEMTYPE_ *object) {
-			object->Delete();
-		}
-		Token AddHandler(HANDLER_ *object) {
-			ITEMTYPE_ *item = &events.Add(object);
-
-			return reinterpret_cast<Token>(item);
-		}
-		Token AddHandler(HANDLER_ *object, int order) {
-			ITEMTYPE_ *item = &events.Add(object, order);
-
-			return reinterpret_cast<Token>(item);
-		}
-
-
-	private:
-		//copy constructor is disabled
-		ConsumableEvent(const ConsumableEvent<O_, P_> &);
-
-		//assignment operator is disabled
-		ConsumableEvent<O_,P_> operator =(const ConsumableEvent<O_, P_> &);
-
-		bool checklinkedfire(HANDLER_ *object) {
-			prvt::consumableevent::EventHandlerClassParamOnly<ConsumableEvent, P_, O_> *obj=dynamic_cast<prvt::consumableevent::EventHandlerClassParamOnly<ConsumableEvent, P_, O_> *>(object);
-
-			if(obj!=NULL) {
-				ConsumableEvent *ec;
-				ec=dynamic_cast<ConsumableEvent*>(obj->object);
-				if(ec!=NULL && obj->handler == &ConsumableEvent::linkedfire)
-					return true;
-			}
-
-			return false;
-		}
-
-		bool linkedfire(P_ params) {
-			for(auto it=events.First;it.IsValid();it.Next()) {
-				if(it->enabled && !checklinkedfire(it))
-					if(it->Fire(params, *this->object, eventname))
-						return true;
-			}
-
-			return false;
-		}
-
-	};
-} }
--- a/Source/Gorgon/Widgets/Generator.cpp	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/Widgets/Generator.cpp	Thu Sep 17 16:29:02 2020 +0300
@@ -23,7 +23,7 @@
 
 namespace Gorgon { namespace Widgets { 
 
-    SimpleGenerator::SimpleGenerator(int fontsize, std::string fontname, bool activate) : Generator(activate) {
+    SimpleGenerator::SimpleGenerator(int fontsize, std::string fontname, bool activate, float density) : Generator(activate), Density(density) {
         Init(fontsize, fontname);
     }
     
@@ -70,6 +70,8 @@
         regular.LoadFile(fontname, fontsize);
 
         RegularFont.SetGlyphRenderer(regular);
+        CenteredFont.SetGlyphRenderer(regular);
+        CenteredFont.AlignCenter();
 
         /*if(!regular.HasKerning()) {
             auto &bmpfnt = *new Graphics::BitmapFont(regular.MoveOutBitmap());
@@ -119,28 +121,40 @@
     void SimpleGenerator::UpdateDimensions() {
         lettervsize = regularrenderer->GetLetterHeight();
         asciivsize = regularrenderer->GetLetterHeight(true);
-        int totalh = lettervsize.first + lettervsize.second;
-
-        Spacing = (int)std::round((float)totalh / 4);
+        
+        int totalh = regularrenderer->GetLineGap();
+        
+        Spacing = (int)std::round((float)totalh / (2 * Density / 3));
+        Focus.Spacing = std::max(1, Spacing / 2);
 
-        WidgetWidth = regularrenderer->GetDigitWidth() * 8 + Border.Width * 2 + Border.Radius + Spacing * 3;
-        BorderedWidgetHeight = totalh + Border.Radius / 2 + Spacing * 2 + Border.Width * 2;
-        WidgetHeight = totalh + Focus.Width * 2;
+        BorderedWidgetHeight = 
+            totalh + Border.Width * 2 + 
+            std::max(Border.Radius/2, Focus.Spacing) * 2 + 
+            Focus.Width * 2 + Focus.Spacing * 2
+        ;
         
-        ObjectHeight = asciivsize.second;
+        WidgetHeight = totalh + Focus.Width * 2 + Focus.Spacing * 2;
+        
+        WidgetWidth = 3 * BorderedWidgetHeight + 2 * Spacing;
+        
+        ObjectHeight = totalh;
     }
     
     void SimpleGenerator::UpdateBorders(bool smooth) {
         Border.Width  = (int)std::max(std::round(regularrenderer->GetLineThickness()*2.6f), 1.f);
+        ShapeBorder   = std::max(regularrenderer->GetLineThickness()*2.6f, 1.f);
 
         //limit the thickness after 2.
         if(Border.Width > 2) {
             Border.Width = (int)std::max(std::round(regularrenderer->GetLineThickness()*2.4f), 1.f);
+            ShapeBorder  = std::max(regularrenderer->GetLineThickness()*2.4f, 1.f);
         }
 
         ObjectBorder  = Border.Width;
         Border.Radius = (int)std::round(asciivsize.second / 4.f);
         Border.Divisions = smooth * Border.Radius  / 2;
+        
+        Focus.Width = std::max(1, Border.Width / 2);
     }
     
     Graphics::BitmapRectangleProvider &SimpleGenerator::NormalBorder() {
@@ -172,10 +186,8 @@
 
     Graphics::BitmapRectangleProvider &SimpleGenerator::DisabledBorder() {
         if(!disabledborder) {
-            auto c = Background.Regular;
-            c.Blend(Background.Disabled);
-            auto c2 = Border.Color;
-            c2.Blend(Border.Disabled);
+            auto c = Background.Disabled;
+            auto c2 = Border.Disabled;
 
             disabledborder = makeborder(c2, c);
         }
@@ -300,7 +312,7 @@
             r = Border.Radius;
         
         int bsize = (w + r + 2) * 2 + 16;
-        float off = float((w + 1) / 2 + 1); //prefer integers
+        float off = float(w / 2.0f); //prefer integers
         
         auto &bi = *new Graphics::Bitmap({bsize, bsize}, Graphics::ColorMode::RGBA);
         bi.Clear();
@@ -322,7 +334,8 @@
                 list.Pop();
             }
             
-            CGI::DrawLines(bi.GetData(), list, (float)w, CGI::SolidFill<>(border));
+            if(border.A != 0)
+                CGI::DrawLines(bi.GetData(), list, (float)w, CGI::SolidFill<>(border));
         }
         else {
             Geometry::PointList<Geometry::Pointf> list;
@@ -371,7 +384,8 @@
                 list.Push(list.Front());
             }
             
-            CGI::DrawLines(bi.GetData(), list, (float)w, CGI::SolidFill<>(border));
+            if(border.A != 0)
+                CGI::DrawLines(bi.GetData(), list, (float)w, CGI::SolidFill<>(border));
         }
         
         if(missingedge == 2) {
@@ -385,12 +399,13 @@
         }
         
         drawables.Add(bi);
+        
 
         auto ret = new Graphics::BitmapRectangleProvider(Graphics::Slice(bi, {
-            int(r+w+1), 
-            int(r+w+1), 
-            int(bsize-r-w-1),
-            int(bsize-r-w-1)
+            int(r+w+2), 
+            int(r+w+2), 
+            int(bsize-r-w-2),
+            int(bsize-r-w-2)
         }));
         
         ret->Prepare();
@@ -420,114 +435,100 @@
         return new Graphics::RectangleProvider(cri, hi, cri, vi, ci, vi, cri, hi, cri);
     }
     
+    void SimpleGenerator::setupfocus(UI::GraphicsTemplate &foc) {
+        foc.Content.SetAnimation(FocusBorder());
+        foc.SetSize(100, 100, UI::Dimension::Percent);
+        foc.SetPositioning(UI::ComponentTemplate::Absolute);
+        foc.SetAnchor(UI::Anchor::None, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
+    }
+    
     UI::Template SimpleGenerator::Button() {
         Geometry::Size defsize = {WidgetWidth, BorderedWidgetHeight};
         
         UI::Template temp;
+        temp.SetSpacing(Spacing);
         temp.SetSize(defsize);
-
-        {
-            auto &bg_n = temp.AddContainer(0, UI::ComponentCondition::Always);
-            bg_n.SetSizing(UI::ComponentTemplate::Automatic);
-
-            bg_n.Background.SetAnimation(NormalBorder());
-            bg_n.SetPadding(Spacing);
-            bg_n.AddIndex(1);
-            bg_n.AddIndex(2);
-        }
-
-        {
-            auto &txt_n = temp.AddTextholder(1, UI::ComponentCondition::Always);
-            txt_n.SetRenderer(RegularFont);
-            txt_n.SetColor(Forecolor.Regular);
-            txt_n.SetAnchor(UI::Anchor::None, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
-            txt_n.SetDataEffect(UI::ComponentTemplate::Text);
-            txt_n.SetClip(true);
-            txt_n.SetSize(100, 100, UI::Dimension::Percent);
-            txt_n.SetSizing(UI::ComponentTemplate::ShrinkOnly);
-        }
-
-        {
-            auto &bg_h = temp.AddContainer(0, UI::ComponentCondition::Hover);
-            bg_h.SetSizing(UI::ComponentTemplate::Automatic);
-            
-            bg_h.Background.SetAnimation(HoverBorder());
-            bg_h.SetPadding(Spacing);
-            bg_h.AddIndex(1);
-            bg_h.AddIndex(2);
-        }
-
-        {
-            auto &txt_h = temp.AddTextholder(1, UI::ComponentCondition::Hover);
-            
-            auto c = Forecolor.Regular;
-            c.Blend(Forecolor.Hover);
-            txt_h.SetRenderer(RegularFont);
-            txt_h.SetColor(c);
-            txt_h.SetAnchor(UI::Anchor::None, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
-            txt_h.SetDataEffect(UI::ComponentTemplate::Text);
-            txt_h.SetClip(true);
-            txt_h.SetSize(100, 100, UI::Dimension::Percent);
-            txt_h.SetSizing(UI::ComponentTemplate::ShrinkOnly, UI::ComponentTemplate::ShrinkOnly);
-        }
-
-        {
-            auto &bg_d = temp.AddContainer(0, UI::ComponentCondition::Down);
-            bg_d.SetSizing(UI::ComponentTemplate::Automatic);
+        
+        
+        temp.AddContainer(0, UI::ComponentCondition::Always)
+            .AddIndex(1) //border
+            .AddIndex(2) //boxed content
+        ;
+        
+        auto setupborder = [&](auto &anim, UI::ComponentCondition condition) {
+            auto &bg = temp.AddContainer(1, condition);
+            bg.Background.SetAnimation(anim);
+            bg.SetSize(100, 100, UI::Dimension::Percent);
+            bg.SetPositioning(UI::ComponentTemplate::Absolute);
+        };
 
-            bg_d.Background.SetAnimation(DownBorder());
-            bg_d.SetPadding(Spacing);
-            bg_d.AddIndex(1);
-            bg_d.AddIndex(2);
-        }
-
-        {
-            auto &txt_d = temp.AddTextholder(1, UI::ComponentCondition::Down);
-
-            auto c = Forecolor.Regular;
-            c.Blend(Forecolor.Down);
-            txt_d.SetRenderer(RegularFont);
-            txt_d.SetColor(c);
-            txt_d.SetAnchor(UI::Anchor::None, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
-            txt_d.SetDataEffect(UI::ComponentTemplate::Text);
-            txt_d.SetClip(true);
-            txt_d.SetSize(100, 100, UI::Dimension::Percent);
-            txt_d.SetSizing(UI::ComponentTemplate::ShrinkOnly, UI::ComponentTemplate::ShrinkOnly);
-        }
-
-        {
-            auto &bg_d = temp.AddContainer(0, UI::ComponentCondition::Disabled);
-            bg_d.SetSizing(UI::ComponentTemplate::Automatic);
+        setupborder(NormalBorder(), UI::ComponentCondition::Always);
+        setupborder(HoverBorder(), UI::ComponentCondition::Hover);
+        setupborder(DownBorder(), UI::ComponentCondition::Down);
+        setupborder(DisabledBorder(), UI::ComponentCondition::Disabled);
+        
+        auto &boxed = temp.AddContainer(2, UI::ComponentCondition::Always)
+            .AddIndex(3) //clip
+            .AddIndex(4) //focus
+        ;
+        boxed.SetSize(100, 100, UI::Dimension::Percent);
+        boxed.SetBorderSize(Border.Width);
+        boxed.SetPadding(std::max(Border.Radius / 2, Focus.Spacing));
+        boxed.SetPositioning(UI::ComponentTemplate::Absolute);
+        
+        auto &clip = temp.AddContainer(3, UI::ComponentCondition::Always)
+            .AddIndex(5)
+        ;
+        clip.SetClip(true);
+        clip.SetPadding(Focus.Spacing + Focus.Width);
+        clip.SetSize(100, 100, UI::Dimension::Percent);
+        
+        //Contents
+        auto &content = temp.AddContainer(5, UI::ComponentCondition::Always)
+            .AddIndex(6) //icon
+            .AddIndex(7) //text
+        ;
+        content.SetSize(100, 100, UI::Dimension::Percent);
+        content.SetSize(100, 100, UI::Dimension::Percent);
+        content.SetSizing(UI::ComponentTemplate::Automatic);
+        content.SetPositioning(UI::ComponentTemplate::Absolute);
+        content.SetAnchor(UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
+        
+        //Icon container
+        auto &iconcont = temp.AddContainer(6, UI::ComponentCondition::Icon1IsSet)
+            .AddIndex(8)
+        ;
+        iconcont.SetMargin(0, 0, Spacing, 0);
+        iconcont.SetAnchor(UI::Anchor::MiddleRight, UI::Anchor::MiddleLeft, UI::Anchor::MiddleLeft);
+        iconcont.SetSizing(UI::ComponentTemplate::Automatic);
+        
+        auto setupicon = [&](auto &icon) -> auto& {
+            icon.SetDataEffect(UI::ComponentTemplate::Icon1);
+            icon.SetSizing(UI::ComponentTemplate::Automatic);
+            
+            return icon;
+        };
+        
+        setupicon(temp.AddGraphics(8, UI::ComponentCondition::Always));
+        setupicon(temp.AddGraphics(8, UI::ComponentCondition::Disabled)).SetColor({1.0f, 0.5f});
+        
+        //Text
+        auto setuptext = [&](Graphics::RGBA color, UI::ComponentCondition condition) {
+            auto &txt = temp.AddTextholder(7, condition);
+            txt.SetRenderer(CenteredFont);
+            txt.SetColor(color);
+            txt.SetAnchor(UI::Anchor::MiddleRight, UI::Anchor::MiddleLeft, UI::Anchor::MiddleLeft);
+            txt.SetDataEffect(UI::ComponentTemplate::Text);
+            txt.SetSize(100, 100, UI::Dimension::Percent);
+            txt.SetSizing(UI::ComponentTemplate::ShrinkOnly);
+        };
+        
+        setuptext(Forecolor.Regular, UI::ComponentCondition::Always);
+        setuptext(Forecolor.Regular.BlendWith(Forecolor.Hover), UI::ComponentCondition::Hover);
+        setuptext(Forecolor.Regular.BlendWith(Forecolor.Down), UI::ComponentCondition::Down);
+        setuptext(Forecolor.Regular.BlendWith(Forecolor.Disabled), UI::ComponentCondition::Disabled);
 
-            bg_d.Background.SetAnimation(DisabledBorder());
-            bg_d.SetPadding(Spacing);
-            bg_d.AddIndex(1);
-            bg_d.AddIndex(2);
-        }
-
-        {
-            auto &txt_d = temp.AddTextholder(1, UI::ComponentCondition::Disabled);
-
-            auto c = Forecolor.Regular;
-            c.Blend(Forecolor.Disabled);
-            txt_d.SetRenderer(RegularFont);
-            txt_d.SetColor(c);
-            txt_d.SetAnchor(UI::Anchor::None, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
-            txt_d.SetDataEffect(UI::ComponentTemplate::Text);
-            txt_d.SetClip(true);
-            txt_d.SetSize(100, 100, UI::Dimension::Percent);
-            txt_d.SetSizing(UI::ComponentTemplate::ShrinkOnly, UI::ComponentTemplate::ShrinkOnly);
-        }
-
-        {
-            auto &foc = temp.AddContainer(2, UI::ComponentCondition::Focused);
-
-            foc.Background.SetAnimation(FocusBorder());
-            foc.SetMargin(Border.Width + Border.Radius / 2);
-            foc.SetSize(100, 100, UI::Dimension::Percent);
-            foc.SetPositioning(foc.Absolute);
-            foc.SetAnchor(UI::Anchor::None, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
-        }
+        setupfocus(temp.AddGraphics(4, UI::ComponentCondition::Focused));
 
         return temp;
     }
@@ -535,107 +536,106 @@
     UI::Template SimpleGenerator::IconButton(Geometry::Size iconsize) {
         
         if(iconsize.Width == -1) {
-            iconsize.Width = BorderedWidgetHeight - Spacing * 2;
+            iconsize.Width = WidgetHeight;
+        }
+        else {
+            iconsize.Width += Focus.Spacing * 2 + Focus.Width * 2;
         }
         
         if(iconsize.Height == -1) {
-            iconsize.Height = BorderedWidgetHeight - Spacing * 2;
+            iconsize.Height = WidgetHeight;
         }
-        
-        
-        UI::Template temp;
-        
-        auto bgsize = iconsize + Geometry::Size(Spacing * 2, Spacing * 2);
-        temp.SetSize(bgsize);
-        {
-            auto &bg = temp.AddContainer(0, UI::ComponentCondition::Always);
-            
-            bg.SetPadding(Spacing);
-            bg.Background.SetAnimation(NormalBG());
-            bg.AddIndex(1);
-            bg.AddIndex(2);
-            bg.AddIndex(3);
-        }
-        
-        {
-            auto &bg = temp.AddContainer(0, UI::ComponentCondition::Hover);
-            
-            bg.SetPadding(Spacing);
-            bg.Background.SetAnimation(HoverBG());
-            bg.AddIndex(1);
-            bg.AddIndex(2);
-            bg.AddIndex(3);
+        else {
+            iconsize.Height += Focus.Spacing * 2 + Focus.Width * 2;
         }
         
-        {
-            auto &bg = temp.AddContainer(0, UI::ComponentCondition::Down);
+        auto externalspacing = Border.Width + std::max(Border.Radius / 2, Focus.Spacing);
+        
+        iconsize += Geometry::Size(externalspacing) * 2;
+        
+        UI::Template temp;
+        temp.SetSpacing(Spacing);
+        
+        temp.SetSize(iconsize);
+        
+        temp.AddContainer(0, UI::ComponentCondition::Always)
+            .AddIndex(1) //background
+            .AddIndex(2) //boxed content
+        ;
+        
+        //background
+        auto setupbg = [&](auto &anim, UI::ComponentCondition condition) {
+            auto &bg = temp.AddContainer(1, condition);
+            bg.Background.SetAnimation(anim);
+            bg.SetSize(100, 100, UI::Dimension::Percent);
+            bg.SetPositioning(UI::ComponentTemplate::Absolute);
+        };
+        
+        setupbg(NormalBG(), UI::ComponentCondition::Always);
+        setupbg(HoverBG(), UI::ComponentCondition::Hover);
+        setupbg(DownBG(), UI::ComponentCondition::Down);
+        setupbg(DisabledBG(), UI::ComponentCondition::Disabled);
+        
+        //boxed content
+        auto &boxed = temp.AddContainer(2, UI::ComponentCondition::Always)
+            .AddIndex(3) //contents
+            .AddIndex(4) //focus
+        ;
+        boxed.SetBorderSize(Border.Width);
+        boxed.SetPadding(std::max(Border.Radius / 2, Focus.Spacing));
+        boxed.SetPositioning(UI::ComponentTemplate::Absolute);
+        
+        setupfocus(temp.AddGraphics(4, UI::ComponentCondition::Focused));
+        
+        //contents
+        auto &contents = temp.AddContainer(3, UI::ComponentCondition::Always)
+            .AddIndex(5) //Icon or text, if icon exists text will not be displayed
+        ;
+        contents.SetClip(true);
+        contents.SetPadding(Focus.Spacing + Focus.Width);
+        
+        //Icon container
+        temp.AddContainer(5, UI::ComponentCondition::Icon1IsSet)
+            .AddIndex(6)
+        ;
+        
+        //Icon
+        auto setupicon = [&](auto &icon) -> auto& {
+            icon.SetDataEffect(icon.Icon);
+            icon.SetAnchor(UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
+            icon.SetSize(100, 100, UI::Dimension::Percent);
+            icon.SetPositioning(icon.Absolute);
+            icon.SetSizing(icon.ShrinkOnly);
+            icon.SetFillArea(false);
             
-            bg.SetPadding(Spacing);
-            bg.Background.SetAnimation(DownBG());
-            bg.AddIndex(1);
-            bg.AddIndex(2);
-            bg.AddIndex(3);
-        }
-
-        {
-            auto &bg = temp.AddContainer(0, UI::ComponentCondition::Disabled);
-
-            bg.SetPadding(Spacing);
-            bg.Background.SetAnimation(DisabledBG());
-            bg.AddIndex(1);
-            bg.AddIndex(2);
-            bg.AddIndex(3);
-            bg.AddIndex(4);
-        }
-
-        {
-            auto &overlay = temp.AddContainer(4, UI::ComponentCondition::Disabled);
-
-            auto c = Forecolor.Regular;
-            c.Blend(Forecolor.Disabled);
-            c.A /= 2;
-
-            auto &im = *new Graphics::BlankImage(bgsize, c);
-            drawables.Add(im);
-
-            overlay.Background.SetDrawable(im);
-            overlay.SetPositioning(overlay.Absolute);
-            overlay.SetSize(100, 100, UI::Dimension::Percent);
-            overlay.SetSizing(overlay.Fixed);
-            overlay.SetAnchor(UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
-            overlay.SetClip(true);
-        }
-
-        auto &icon = temp.AddPlaceholder(1, UI::ComponentCondition::Always);
-        icon.SetDataEffect(icon.Icon);
-        icon.SetAnchor(UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
-        icon.SetSize(100, 100, UI::Dimension::Percent);
-        icon.SetPositioning(icon.Absolute);
-        icon.SetSizing(icon.Fixed);
-        icon.SetClip(true);
-
-        {
-            auto &txt_n = temp.AddTextholder(3, UI::ComponentCondition::Always);
-            txt_n.SetRenderer(RegularFont);
-            txt_n.SetColor(Forecolor.Regular);
-            txt_n.SetAnchor(UI::Anchor::None, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
-            txt_n.SetDataEffect(UI::ComponentTemplate::Text);
-            txt_n.SetClip(true);
-            txt_n.SetSize(100, 100, UI::Dimension::Percent);
-            txt_n.SetSizing(UI::ComponentTemplate::ShrinkOnly);
-            txt_n.SetPositioning(txt_n.Absolute);
-        }
+            return icon;
+        };
+        
+        setupicon(temp.AddGraphics(6, UI::ComponentCondition::Always));
+        setupicon(temp.AddGraphics(6, UI::ComponentCondition::Disabled)).SetColor({1.0f, 0.5f});
 
         
-        {
-            auto &foc = temp.AddContainer(2, UI::ComponentCondition::Focused);
-            foc.Background.SetAnimation(FocusBorder());
-            foc.SetMargin(1);
-            foc.SetSize(100, 100, UI::Dimension::Percent);
-            foc.SetPositioning(foc.Absolute);
-            foc.SetAnchor(UI::Anchor::None, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
-        }
+        //Text container
+        temp.AddContainer(5, UI::ComponentCondition::Always)
+            .AddIndex(7)
+        ;
         
+        //Text only visible when no icon is set
+        auto setuptext = [&](Graphics::RGBA color, UI::ComponentCondition condition) {
+            auto &txt = temp.AddTextholder(7, condition);
+            txt.SetRenderer(CenteredFont);
+            txt.SetColor(color);
+            txt.SetAnchor(UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
+            txt.SetDataEffect(UI::ComponentTemplate::Text);
+            txt.SetSize(100, 100, UI::Dimension::Percent);
+            txt.SetSizing(UI::ComponentTemplate::ShrinkOnly);
+        };
+        
+        setuptext(Forecolor.Regular, UI::ComponentCondition::Always);
+        setuptext(Forecolor.Regular.BlendWith(Forecolor.Hover), UI::ComponentCondition::Hover);
+        setuptext(Forecolor.Regular.BlendWith(Forecolor.Down), UI::ComponentCondition::Down);
+        setuptext(Forecolor.Regular.BlendWith(Forecolor.Disabled), UI::ComponentCondition::Disabled);
+
         return temp;
     }
 
@@ -643,23 +643,33 @@
         Geometry::Size defsize = {WidgetWidth * 2 + Spacing, WidgetHeight};
         
         UI::Template temp;
+        temp.SetSpacing(Spacing);
         temp.SetSize(defsize);
         
-        {
-            auto &cont = temp.AddContainer(0, UI::ComponentCondition::Always);
-            cont.SetPadding(Focus.Width);
-            cont.AddIndex(1);
-            cont.AddIndex(3);
-            cont.AddIndex(4);
-        }
+        temp.AddContainer(0, UI::ComponentCondition::Always)
+            .AddIndex(1) //Content
+            .AddIndex(2) //Focus
+        ;
+        
         
-        {
-            auto &cont = temp.AddContainer(0, UI::ComponentCondition::State2);
-            cont.SetPadding(Focus.Width);
-            cont.AddIndex(2);
-            cont.AddIndex(3);
-            cont.AddIndex(4);
-        }
+        auto &cont = temp.AddContainer(1, UI::ComponentCondition::Always)
+            .AddIndex(3) //Box symbol
+            .AddIndex(4) //Tick
+            .AddIndex(5) //Text
+        ;
+        cont.SetClip(true);
+        cont.SetPadding(Focus.Spacing + Focus.Width);
+        cont.SetSizing(UI::ComponentTemplate::Fixed);
+        cont.SetSize(100, 100, UI::Dimension::Percent);
+        
+        //tick container, will be used for animation
+        auto &state2 = temp.AddContainer(4, UI::ComponentCondition::Always, UI::ComponentCondition::State2)
+            .AddIndex(6) //Tick
+        ;
+        state2.SetValueModification(UI::ComponentTemplate::ModifyAlpha, UI::ComponentTemplate::UseTransition);
+        state2.SetReversible(true);
+        state2.SetPositioning(UI::ComponentTemplate::Absolute);
+        state2.SetAnchor(UI::Anchor::None, UI::Anchor::MiddleLeft, UI::Anchor::MiddleLeft);
         
         auto box = [&](auto color) {
             auto icon = new Graphics::Bitmap({ObjectHeight, ObjectHeight});
@@ -687,38 +697,52 @@
         };
         
         auto tick = [&](auto color) {
-            auto icon = box(color);
+            auto icon = new Graphics::Bitmap({ObjectHeight, ObjectHeight});
             
+            icon->ForAllPixels([&](auto x, auto y) {
+                icon->SetRGBAAt(x, y, 0x0);
+            });
+            
+            //these coordinates are designed to look good across many different
+            //sizes covering a wide range
             Geometry::PointList<Geometry::Pointf> tick ={
-                {ObjectBorder*2.f, ObjectHeight/2.f},
-                {ObjectHeight/2.f, ObjectHeight-ObjectBorder*2.f},
-                {ObjectHeight-ObjectBorder*2.f, ObjectBorder*2.f}
+                {ShapeBorder*2.4f, ObjectHeight/2.f},
+                {ObjectHeight*0.45f, ObjectHeight-ShapeBorder*2.4f},
+                {ObjectHeight-ShapeBorder*2.5f, ShapeBorder*2.4f}
             };
             
-            CGI::DrawLines(*icon, tick, (float)ObjectBorder, CGI::SolidFill<>(color));
+            if(ObjectHeight - ShapeBorder*4.8f < 3) {
+                CGI::Polyfill(*icon, Geometry::PointList<Geometry::Pointf>{
+                    {ObjectBorder*2.f, ObjectBorder*2.f},
+                    {ObjectHeight - ObjectBorder*2.f, ObjectBorder*2.f},
+                    {ObjectHeight - ObjectBorder*2.f, ObjectHeight - ObjectBorder*2.f},
+                    {ObjectBorder*2.f, ObjectHeight - ObjectBorder*2.f},
+                }, CGI::SolidFill<>(color));
+            }
+            else {
+                CGI::DrawLines(*icon, tick, 1.2*ShapeBorder, CGI::SolidFill<>(color));
+            }
             icon->Prepare();
             
             return icon;
         };
         
         auto makestate = [&](auto color, UI::ComponentCondition condition) {
-            auto &it = temp.AddGraphics(1, condition);
-            it.Content.SetDrawable(*box(color));
-            it.SetSizing(it.Automatic);
-            it.SetIndent(Spacing, 0, 0, 0);
+            //box
+            auto &bx = temp.AddGraphics(3, condition);
+            bx.Content.SetDrawable(*box(color));
+            bx.SetAnchor(UI::Anchor::MiddleRight, UI::Anchor::MiddleLeft, UI::Anchor::MiddleLeft);
             
-            auto &it2 = temp.AddGraphics(2, condition);
-            it2.Content.SetDrawable(*tick(color));
-            it2.SetSizing(it2.Automatic);
-            it2.SetIndent(Spacing, 0, 0, 0);
+            auto &tic = temp.AddGraphics(6, condition);
+            tic.Content.SetDrawable(*tick(color));
+            tic.SetAnchor(UI::Anchor::MiddleRight, UI::Anchor::MiddleLeft, UI::Anchor::MiddleLeft);
             
-            auto &tt = temp.AddTextholder(3, condition);
+            auto &tt = temp.AddTextholder(5, condition);
             tt.SetRenderer(RegularFont);
             tt.SetColor(color);
             tt.SetMargin(Spacing, 0, 0, 0);
             tt.SetAnchor(UI::Anchor::MiddleRight, UI::Anchor::MiddleLeft, UI::Anchor::MiddleLeft);
             tt.SetDataEffect(UI::ComponentTemplate::Text);
-            tt.SetClip(true);
             tt.SetSize(100, 100, UI::Dimension::Percent);
             tt.SetSizing(UI::ComponentTemplate::ShrinkOnly, UI::ComponentTemplate::ShrinkOnly);
         };
@@ -728,117 +752,104 @@
         makestate(Forecolor.Regular.BlendWith(Forecolor.Down), UI::ComponentCondition::Down);
         makestate(Forecolor.Regular.BlendWith(Forecolor.Disabled), UI::ComponentCondition::Disabled);
         
-        {
-            auto &foc = temp.AddContainer(4, UI::ComponentCondition::Focused);
-            foc.Background.SetAnimation(FocusBorder());
-            foc.SetSize(100, 100, UI::Dimension::Percent);
-            foc.SetIndent(-Focus.Width);
-            foc.SetPositioning(foc.Absolute);
-            foc.SetAnchor(UI::Anchor::None, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
-        }
+        setupfocus(temp.AddGraphics(2, UI::ComponentCondition::Focused));
+        
         return temp;
     }
     
     UI::Template SimpleGenerator::CheckboxButton() {
         
         UI::Template temp;
-        temp.SetSize((WidgetWidth-Spacing*3)/4, BorderedWidgetHeight);
-        
-        auto bgsize = temp.GetSize();
-        
-        {
-            auto &bg = temp.AddContainer(0, UI::ComponentCondition::Always);
-            
-            bg.Background.SetAnimation(NormalBG());
-            bg.AddIndex(1);
-            bg.AddIndex(2);
-            bg.AddIndex(3);
-        }
+        temp.SetSpacing(Spacing);
+        temp.SetSize(BorderedWidgetHeight, BorderedWidgetHeight);
         
-        {
-            auto &bg = temp.AddContainer(0, UI::ComponentCondition::Hover);
-            
-            bg.Background.SetAnimation(HoverBG());
-            bg.AddIndex(1);
-            bg.AddIndex(2);
-            bg.AddIndex(3);
-        }
-
-        {
-            auto &bg = temp.AddContainer(0, UI::ComponentCondition::Down);
-
-            bg.Background.SetAnimation(DownBG());
-            bg.AddIndex(1);
-            bg.AddIndex(2);
-            bg.AddIndex(3);
-        }
-
-        {
-            auto &bg = temp.AddContainer(0, UI::ComponentCondition::Disabled);
 
-            bg.Background.SetAnimation(DisabledBG());
-            bg.AddIndex(1);
-            bg.AddIndex(2);
-            bg.AddIndex(3);
-            bg.AddIndex(4);
-        }
-
-        {
-            auto &overlay = temp.AddContainer(4, UI::ComponentCondition::Disabled);
-
-            auto c = Forecolor.Regular;
-            c.Blend(Forecolor.Disabled);
-            c.A /= 2;
-
-            auto &im = *new Graphics::BlankImage(bgsize, c);
-            drawables.Add(im);
-
-            overlay.Background.SetDrawable(im);
-            overlay.SetPositioning(overlay.Absolute);
-            overlay.SetSize(100, 100, UI::Dimension::Percent);
-            overlay.SetSizing(overlay.Fixed);
-            overlay.SetAnchor(UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
-            overlay.SetClip(true);
-        }
-
-        auto &icon = temp.AddPlaceholder(1, UI::ComponentCondition::Always);
-        icon.SetDataEffect(icon.Icon);
-        icon.SetAnchor(UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
-        icon.SetSize(100, 100, UI::Dimension::Percent);
-        icon.SetPositioning(icon.Absolute);
-        icon.SetSizing(icon.Fixed);
-        icon.SetClip(true);
-
-        {
-            auto &txt_n = temp.AddTextholder(3, UI::ComponentCondition::Always);
-            txt_n.SetRenderer(RegularFont);
-            txt_n.SetColor(Forecolor.Regular);
-            txt_n.SetAnchor(UI::Anchor::None, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
-            txt_n.SetDataEffect(UI::ComponentTemplate::Text);
-            txt_n.SetClip(true);
-            txt_n.SetSize(100, 100, UI::Dimension::Percent);
-            txt_n.SetSizing(UI::ComponentTemplate::ShrinkOnly);
-            txt_n.SetPositioning(txt_n.Absolute);
-        }
+        temp.AddContainer(0, UI::ComponentCondition::Always)
+            .AddIndex(1) //background
+            .AddIndex(8) //checked border
+            .AddIndex(2) //boxed content
+        ;
+        
+        //background
+        auto setupbg = [&](auto &anim, UI::ComponentCondition condition) {
+            auto &bg = temp.AddContainer(1, condition);
+            bg.Background.SetAnimation(anim);
+            bg.SetSize(100, 100, UI::Dimension::Percent);
+            bg.SetPositioning(UI::ComponentTemplate::Absolute);
+        };
+        
+        setupbg(NormalBG(), UI::ComponentCondition::Always);
+        setupbg(HoverBG(), UI::ComponentCondition::Hover);
+        setupbg(DownBG(), UI::ComponentCondition::Down);
+        setupbg(DisabledBG(), UI::ComponentCondition::Disabled);
+        
+        //checked border
+        auto &border = temp.AddContainer(8, UI::ComponentCondition::Always, UI::ComponentCondition::State2);
+        border.SetValueModification(UI::ComponentTemplate::ModifyAlpha, UI::ComponentTemplate::UseTransition);
+        border.SetValueRange(0, 0.5, 1);
+        border.SetReversible(true);
+        border.Background.SetAnimation(NormalEmptyBorder());        
+        
+        //boxed content
+        auto &boxed = temp.AddContainer(2, UI::ComponentCondition::Always)
+            .AddIndex(3) //contents
+            .AddIndex(4) //focus
+        ;
+        boxed.SetBorderSize(Border.Width);
+        boxed.SetPadding(std::max(Border.Radius / 2, Focus.Spacing));
+        boxed.SetPositioning(UI::ComponentTemplate::Absolute);
+        
+        setupfocus(temp.AddGraphics(4, UI::ComponentCondition::Focused));
+        
+        //contents
+        auto &contents = temp.AddContainer(3, UI::ComponentCondition::Always)
+            .AddIndex(5) //Icon or text, if icon exists text will not be displayed
+        ;
+        contents.SetClip(true);
+        contents.SetPadding(Focus.Spacing + Focus.Width);
+        
+        //Icon container
+        temp.AddContainer(5, UI::ComponentCondition::Icon1IsSet)
+            .AddIndex(6)
+        ;
+        
+        //Icon
+        auto setupicon = [&](auto &icon) -> auto& {
+            icon.SetDataEffect(icon.Icon);
+            icon.SetAnchor(UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
+            icon.SetSize(100, 100, UI::Dimension::Percent);
+            icon.SetPositioning(icon.Absolute);
+            icon.SetSizing(icon.ShrinkOnly);
+            icon.SetFillArea(false);
+            
+            return icon;
+        };
+        
+        setupicon(temp.AddGraphics(6, UI::ComponentCondition::Always));
+        setupicon(temp.AddGraphics(6, UI::ComponentCondition::Disabled)).SetColor({1.0f, 0.5f});
 
         
-        {
-            auto &foc = temp.AddContainer(2, UI::ComponentCondition::Focused);
-            foc.Background.SetAnimation(FocusBorder());
-            foc.SetMargin(1);
-            foc.SetSize(100, 100, UI::Dimension::Percent);
-            foc.SetPositioning(foc.Absolute);
-            foc.SetAnchor(UI::Anchor::None, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
-        }
+        //Text container
+        temp.AddContainer(5, UI::ComponentCondition::Always)
+            .AddIndex(7)
+        ;
         
-        {
-            auto &sel = temp.AddContainer(2, UI::ComponentCondition::State2);
-            sel.Background.SetAnimation(NormalEmptyBorder());
-            sel.SetSize(100, 100, UI::Dimension::Percent);
-            sel.SetPositioning(sel.Absolute);
-            sel.SetAnchor(UI::Anchor::None, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
-        }
+        //Text only visible when no icon is set
+        auto setuptext = [&](Graphics::RGBA color, UI::ComponentCondition condition) {
+            auto &txt = temp.AddTextholder(7, condition);
+            txt.SetRenderer(CenteredFont);
+            txt.SetColor(color);
+            txt.SetAnchor(UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
+            txt.SetDataEffect(UI::ComponentTemplate::Text);
+            txt.SetSize(100, 100, UI::Dimension::Percent);
+            txt.SetSizing(UI::ComponentTemplate::ShrinkOnly);
+        };
         
+        setuptext(Forecolor.Regular, UI::ComponentCondition::Always);
+        setuptext(Forecolor.Regular.BlendWith(Forecolor.Hover), UI::ComponentCondition::Hover);
+        setuptext(Forecolor.Regular.BlendWith(Forecolor.Down), UI::ComponentCondition::Down);
+        setuptext(Forecolor.Regular.BlendWith(Forecolor.Disabled), UI::ComponentCondition::Disabled);
+
         return temp;
     }
     
@@ -846,42 +857,59 @@
         Geometry::Size defsize = {WidgetWidth * 2 + Spacing, WidgetHeight};
         
         UI::Template temp;
+        temp.SetSpacing(Spacing);
         temp.SetSize(defsize);
         
-        auto &cont = temp.AddContainer(0, UI::ComponentCondition::Always);
-        cont.AddIndex(1);
-        cont.AddIndex(3);
-        cont.AddIndex(4);
-        cont.SetPadding(Focus.Width);
+        temp.AddContainer(0, UI::ComponentCondition::Always)
+            .AddIndex(1) //Content
+            .AddIndex(2) //Focus
+        ;
         
-        auto &cont2 = temp.AddContainer(0, UI::ComponentCondition::State2);
-        cont2.AddIndex(2);
-        cont2.AddIndex(3);
-        cont2.AddIndex(4);
-        cont2.SetPadding(Focus.Width);
+        auto &cont = temp.AddContainer(1, UI::ComponentCondition::Always)
+            .AddIndex(3) //Box symbol
+            .AddIndex(4) //Tick
+            .AddIndex(5) //Text
+        ;
+        cont.SetClip(true);
+        cont.SetPadding(Focus.Spacing + Focus.Width);
+        cont.SetSizing(UI::ComponentTemplate::Fixed);
+        cont.SetSize(100, 100, UI::Dimension::Percent);
         
-        int outer_r = ObjectHeight / 2;
-        int borderstart_r = outer_r - ObjectBorder;
-        int inner_r = borderstart_r - Spacing / 2;
+        //tick container, will be used for animation
+        auto &state2 = temp.AddContainer(4, UI::ComponentCondition::Always, UI::ComponentCondition::State2)
+            .AddIndex(6) //Tick
+        ;
+        state2.SetValueModification(UI::ComponentTemplate::ModifyAlpha, UI::ComponentTemplate::UseTransition);
+        state2.SetReversible(true);
+        state2.SetPositioning(UI::ComponentTemplate::Absolute);
+        state2.SetAnchor(UI::Anchor::None, UI::Anchor::MiddleLeft, UI::Anchor::MiddleLeft);
+        
+        float outer_r = ObjectHeight / 2.f - 0.5;
+        int borderstart_r = int(ceil(outer_r - ObjectBorder));
+        float inner_r = std::max(outer_r - ObjectBorder - std::max(Spacing / 2.f, 1.5f), 1.5f);
         
         Geometry::Size bmpsize = {ObjectHeight + 2, ObjectHeight + 2};
-        Geometry::Pointf center = {float(outer_r + 1), float(outer_r + 1)};
+        Geometry::Pointf center = {float(outer_r + 1.5f), float(outer_r + 1.5f)};
         
-        auto blank = [&](auto border) {
+        auto box = [&](auto color) {
             auto icon = new Graphics::Bitmap(bmpsize);
             
             icon->Clear();
             
-            CGI::Circle<16>(*icon, center, outer_r - 0.5f, CGI::SolidFill<>(Background.Regular));
-            CGI::Circle<16>(*icon, center, (float)borderstart_r, (float)ObjectBorder, CGI::SolidFill<>(border));
+            CGI::Circle<16>(*icon, center, (float)borderstart_r, (float)ObjectBorder, CGI::SolidFill<>(color));
+
             icon->Prepare();
             drawables.Add(icon);
             
             return icon;
         };
         
-        auto filled = [&](auto color) {
-            auto icon = blank( color);
+        auto tick = [&](auto color) {
+            auto icon = new Graphics::Bitmap(bmpsize);
+            
+            icon->ForAllPixels([&](auto x, auto y) {
+                icon->SetRGBAAt(x, y, 0x0);
+            });
             
             CGI::Circle<16>(*icon, center, (float)inner_r, CGI::SolidFill<>(color));
             icon->Prepare();
@@ -890,40 +918,34 @@
         };
         
         auto makestate = [&](auto color, UI::ComponentCondition condition) {
-            auto &it = temp.AddGraphics(1, condition);
-            it.Content.SetDrawable(*blank(color));
-            it.SetSizing(it.Automatic);
-            it.SetIndent(Spacing, 0, 0, 0);
+            //box
+            auto &bx = temp.AddGraphics(3, condition);
+            bx.Content.SetDrawable(*box(color));
+            bx.SetAnchor(UI::Anchor::MiddleRight, UI::Anchor::MiddleLeft, UI::Anchor::MiddleLeft);
+            bx.SetMargin(-1, 0, -1, 0);
             
-            auto &it2 = temp.AddGraphics(2, condition);
-            it2.Content.SetDrawable(*filled(color));
-            it2.SetSizing(it2.Automatic);
-            it2.SetIndent(Spacing, 0, 0, 0);
+            auto &tic = temp.AddGraphics(6, condition);
+            tic.Content.SetDrawable(*tick(color));
+            tic.SetAnchor(UI::Anchor::MiddleRight, UI::Anchor::MiddleLeft, UI::Anchor::MiddleLeft);
+            tic.SetMargin(-1, 0, 0, 0);
             
-            auto &tt = temp.AddTextholder(3, condition);
+            auto &tt = temp.AddTextholder(5, condition);
             tt.SetRenderer(RegularFont);
             tt.SetColor(color);
             tt.SetMargin(Spacing, 0, 0, 0);
             tt.SetAnchor(UI::Anchor::MiddleRight, UI::Anchor::MiddleLeft, UI::Anchor::MiddleLeft);
             tt.SetDataEffect(UI::ComponentTemplate::Text);
-            tt.SetClip(true);
             tt.SetSize(100, 100, UI::Dimension::Percent);
             tt.SetSizing(UI::ComponentTemplate::ShrinkOnly, UI::ComponentTemplate::ShrinkOnly);
         };
-
+        
         makestate(Forecolor.Regular, UI::ComponentCondition::Always);
         makestate(Forecolor.Regular.BlendWith(Forecolor.Hover), UI::ComponentCondition::Hover);
         makestate(Forecolor.Regular.BlendWith(Forecolor.Down), UI::ComponentCondition::Down);
         makestate(Forecolor.Regular.BlendWith(Forecolor.Disabled), UI::ComponentCondition::Disabled);
-
-        {
-            auto &foc = temp.AddContainer(4, UI::ComponentCondition::Focused);
-            foc.Background.SetAnimation(FocusBorder());
-            foc.SetSize(100, 100, UI::Dimension::Percent);
-            foc.SetIndent(-Focus.Width);
-            foc.SetPositioning(foc.Absolute);
-            foc.SetAnchor(UI::Anchor::None, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
-        }
+        
+        setupfocus(temp.AddGraphics(2, UI::ComponentCondition::Focused));
+        
         return temp;
     }
     
@@ -931,63 +953,33 @@
         Geometry::Size defsize = {WidgetWidth * 2 + Spacing, WidgetHeight};
         
         UI::Template temp;
+        temp.SetSpacing(Spacing);
         temp.SetSize(defsize);
         
-        auto &bi = *new Graphics::BlankImage({Border.Width, Border.Width}, Border.Color);
-        drawables.Add(bi);
-        
-        {
-            auto &bg_n = temp.AddContainer(0, UI::ComponentCondition::Always);
-            bg_n.SetSizing(UI::ComponentTemplate::Automatic);
-            //assuming border radius = 0
-            bg_n.SetPadding(0);
-            bg_n.AddIndex(1);
-            bg_n.AddIndex(2);
-            bg_n.AddIndex(3);
-        }
-        
-        {
-            auto &icon = temp.AddPlaceholder(1, UI::ComponentCondition::Icon1IsSet);
-            icon.SetDataEffect(UI::ComponentTemplate::Icon);
-            icon.SetAnchor(UI::Anchor::MiddleRight, UI::Anchor::MiddleLeft, UI::Anchor::MiddleLeft);
-            icon.SetSize(100, 100, UI::Dimension::Percent);
-            icon.SetSizing(UI::ComponentTemplate::ShrinkOnly);
-            icon.SetMargin(0, 0, Spacing, 0);
-        }
+        auto &cont = temp.AddContainer(0, UI::ComponentCondition::Always, UI::ComponentCondition::Disabled)
+            .AddIndex(1) //icon
+            .AddIndex(2) //text
+        ;
+        cont.SetValueModification(UI::ComponentTemplate::ModifyAlpha, UI::ComponentTemplate::UseTransition);
+        cont.SetValueRange(0, 1, 0.5);
+        cont.SetReversible(true);
+        cont.SetClip(true);
         
-        {
-            auto &foc = temp.AddContainer(2, UI::ComponentCondition::Focused);
-            foc.Background.SetAnimation(FocusBorder());
-            foc.SetMargin(Spacing / 2);
-            foc.SetSize(100, 100, UI::Dimension::Percent);
-            foc.SetPositioning(foc.Absolute);
-            foc.SetAnchor(UI::Anchor::None, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
-        }
-
-        {
-            auto &txt_n = temp.AddTextholder(3, UI::ComponentCondition::Always);
-            txt_n.SetRenderer(RegularFont);
-            txt_n.SetColor(Forecolor.Regular);
-            txt_n.SetAnchor(UI::Anchor::MiddleRight, UI::Anchor::MiddleLeft, UI::Anchor::MiddleLeft);
-            txt_n.SetDataEffect(UI::ComponentTemplate::Text);
-            txt_n.SetClip(true);
-            txt_n.SetSize(100, 100, UI::Dimension::Percent);
-            txt_n.SetSizing(UI::ComponentTemplate::ShrinkOnly);
-        }
-
-        {
-            auto &txt_n = temp.AddTextholder(3, UI::ComponentCondition::Disabled);
-            txt_n.SetRenderer(RegularFont);
-            auto c = Forecolor.Regular;
-            c.Blend(Forecolor.Disabled);
-            txt_n.SetColor(c);
-            txt_n.SetAnchor(UI::Anchor::MiddleRight, UI::Anchor::MiddleLeft, UI::Anchor::MiddleLeft);
-            txt_n.SetDataEffect(UI::ComponentTemplate::Text);
-            txt_n.SetClip(true);
-            txt_n.SetSize(100, 100, UI::Dimension::Percent);
-            txt_n.SetSizing(UI::ComponentTemplate::ShrinkOnly);
-        }
-
+        auto &icon = temp.AddPlaceholder(1, UI::ComponentCondition::Icon1IsSet);
+        icon.SetDataEffect(UI::ComponentTemplate::Icon);
+        icon.SetAnchor(UI::Anchor::MiddleRight, UI::Anchor::MiddleLeft, UI::Anchor::MiddleLeft);
+        icon.SetSize(100, 100, UI::Dimension::Percent);
+        icon.SetSizing(UI::ComponentTemplate::ShrinkOnly);
+        icon.SetMargin(0, 0, Spacing, 0);
+        
+        auto &txt = temp.AddTextholder(2, UI::ComponentCondition::Always);
+        txt.SetRenderer(RegularFont);
+        txt.SetColor(Forecolor.Regular);
+        txt.SetAnchor(UI::Anchor::MiddleRight, UI::Anchor::MiddleLeft, UI::Anchor::MiddleLeft);
+        txt.SetDataEffect(UI::ComponentTemplate::Text);
+        txt.SetSize(100, 100, UI::Dimension::Percent);
+        txt.SetSizing(UI::ComponentTemplate::ShrinkOnly);
+        
         return temp;
     }
 
@@ -995,103 +987,61 @@
         Geometry::Size defsize = {WidgetWidth * 2 + Spacing, WidgetHeight};
         
         UI::Template temp;
+        temp.SetSpacing(Spacing);
         temp.SetSize(defsize);
-
-        auto &bi = *new Graphics::BlankImage({ Border.Width, Border.Width }, Border.Color);
-        drawables.Add(bi);
-
-        {
-            auto &bg_n = temp.AddContainer(0, UI::ComponentCondition::Always);
-            bg_n.SetSizing(UI::ComponentTemplate::Automatic);
-            //assuming border radius = 0
-            bg_n.SetPadding(0);
-            bg_n.AddIndex(1);
-            bg_n.AddIndex(2);
-            bg_n.AddIndex(3);
-        }
-
-        {
-            auto &icon = temp.AddPlaceholder(1, UI::ComponentCondition::Icon1IsSet);
-            icon.SetDataEffect(UI::ComponentTemplate::Icon);
-            icon.SetAnchor(UI::Anchor::MiddleRight, UI::Anchor::MiddleLeft, UI::Anchor::MiddleLeft);
-            icon.SetSize(100, 100, UI::Dimension::Percent);
-            icon.SetSizing(UI::ComponentTemplate::ShrinkOnly);
-            icon.SetMargin(0, 0, Spacing, 0);
-        }
-
-        {
-            auto &foc = temp.AddContainer(2, UI::ComponentCondition::Focused);
-
-            auto &ci = Graphics::EmptyImage::Instance();
-
-
-            auto &hi = *new Graphics::Bitmap({ 2, Focus.Width });
-            hi.Clear();
-            for (auto i = 0; i < Focus.Width; i++)
-                hi.SetRGBAAt(0, i, Focus.Color);
-            hi.Prepare();
-            drawables.Add(hi);
-
-            auto &vi = *new Graphics::Bitmap({ Focus.Width, 2 });
-            vi.Clear();
-            for (auto i = 0; i < Focus.Width; i++)
-                vi.SetRGBAAt(i, 0, Focus.Color);
-            vi.Prepare();
-            drawables.Add(vi);
-
-            auto &cri = *new Graphics::BlankImage(Focus.Width, Focus.Width, Focus.Color);
-
-            auto &rect = *new Graphics::RectangleProvider(cri, hi, cri, vi, ci, vi, cri, hi, cri);
-
-            foc.Background.SetAnimation(rect);
-            providers.Add(rect);
-            foc.SetMargin(Spacing / 2);
-            foc.SetSize(100, 100, UI::Dimension::Percent);
-            foc.SetPositioning(foc.Absolute);
-            foc.SetAnchor(UI::Anchor::None, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
-        }
-
-        {
-            auto &txt_n = temp.AddTextholder(3, UI::ComponentCondition::Always);
-            txt_n.SetRenderer(RegularFont);
-            txt_n.SetColor(Forecolor.Error);
-            txt_n.SetAnchor(UI::Anchor::MiddleRight, UI::Anchor::MiddleLeft, UI::Anchor::MiddleLeft);
-            txt_n.SetDataEffect(UI::ComponentTemplate::Text);
-            txt_n.SetClip(true);
-            txt_n.SetSize(100, 100, UI::Dimension::Percent);
-            txt_n.SetSizing(UI::ComponentTemplate::ShrinkOnly);
-        }
-
+        
+        auto &cont = temp.AddContainer(0, UI::ComponentCondition::Always, UI::ComponentCondition::Disabled)
+            .AddIndex(1) //icon
+            .AddIndex(2) //text
+        ;
+        cont.SetValueModification(UI::ComponentTemplate::ModifyAlpha, UI::ComponentTemplate::UseTransition);
+        cont.SetValueRange(0, 1, 0.5);
+        cont.SetReversible(true);
+        cont.SetClip(true);
+        
+        auto &icon = temp.AddPlaceholder(1, UI::ComponentCondition::Icon1IsSet);
+        icon.SetDataEffect(UI::ComponentTemplate::Icon);
+        icon.SetAnchor(UI::Anchor::MiddleRight, UI::Anchor::MiddleLeft, UI::Anchor::MiddleLeft);
+        icon.SetSize(100, 100, UI::Dimension::Percent);
+        icon.SetSizing(UI::ComponentTemplate::ShrinkOnly);
+        icon.SetMargin(0, 0, Spacing, 0);
+        
+        auto &txt = temp.AddTextholder(2, UI::ComponentCondition::Always);
+        txt.SetRenderer(RegularFont);
+        txt.SetColor(Forecolor.Regular.BlendWith(Forecolor.Error));
+        txt.SetAnchor(UI::Anchor::MiddleRight, UI::Anchor::MiddleLeft, UI::Anchor::MiddleLeft);
+        txt.SetDataEffect(UI::ComponentTemplate::Text);
+        txt.SetSize(100, 100, UI::Dimension::Percent);
+        txt.SetSizing(UI::ComponentTemplate::ShrinkOnly);
+        
         return temp;
     }
     
     UI::Template SimpleGenerator::BlankPanel() {
-        Geometry::Size defsize = {WidgetWidth * 4 + Spacing * 5, WidgetHeight * 10 + Spacing * 11};
+        Geometry::Size defsize = {WidgetWidth * 2 + Spacing, BorderedWidgetHeight * 10 + Spacing * 9};
         
         UI::Template temp;
+        temp.SetSpacing(Spacing);
         temp.SetSize(defsize);
         
-        
-        auto &bg = temp.AddContainer(0, UI::ComponentCondition::Always);
-        bg.SetClip(true);
-        
-        bg.AddIndex(1);
+        temp.AddContainer(0, UI::ComponentCondition::Always)
+            .AddIndex(1)
+            .SetClip(true)
+        ;
         
         auto &cont = temp.AddContainer(1, UI::ComponentCondition::Always);
         cont.SetTag(UI::ComponentTemplate::ContentsTag);
-        cont.SetValueModification(cont.ModifyPosition, cont.UseXY);
-        cont.SetSize(100, 100, UI::Dimension::Percent);
+        cont.SetSize(0, 0, UI::Dimension::Percent);
         cont.SetPositioning(cont.Absolute);
         cont.SetAnchor(UI::Anchor::TopLeft, UI::Anchor::TopLeft, UI::Anchor::TopLeft);
         cont.SetPosition(0, 0);
-        //bg.Background.SetAnimation(NormalBorder());
         
         return temp;
     }
     
     UI::Template SimpleGenerator::makepanel(int missingedge) {
         Geometry::Size defsize = {
-            WidgetWidth * 4 + Spacing * 3 + Border.Width * 2 + Spacing * 2, 
+            WidgetWidth * 2 + Spacing + Border.Width * 2 + Spacing * 2, 
             BorderedWidgetHeight * 10 + Spacing * 9 + Border.Width * 2 + Spacing * 2
         };
         
@@ -1104,6 +1054,7 @@
         }
         
         UI::Template temp;
+        temp.SetSpacing(Spacing);
         temp.SetSize(defsize);
         
         
@@ -1135,18 +1086,17 @@
         vp.SetSize(100, 100, UI::Dimension::Percent);
         vp.SetPositioning(vp.Absolute);
         vp.SetAnchor(UI::Anchor::TopLeft, UI::Anchor::TopLeft, UI::Anchor::TopLeft);
-        vp.SetPosition(0, 0);
         vp.SetClip(true);
         vp.AddIndex(2);
+        //vp.Background.SetAnimation(HoverBorder());
         
         auto &cont = temp.AddContainer(2, UI::ComponentCondition::Always);
         cont.SetTag(UI::ComponentTemplate::ContentsTag);
-        //cont.SetValueModification(cont.ModifyPosition, cont.UseXY);
-        cont.SetSize(100, 100, UI::Dimension::Percent);
+        cont.SetSize(0, 0, UI::Dimension::Percent);
         cont.SetSizing(UI::ComponentTemplate::Fixed);
         cont.SetPositioning(cont.Absolute);
         cont.SetAnchor(UI::Anchor::TopLeft, UI::Anchor::TopLeft, UI::Anchor::TopLeft);
-        cont.SetPosition(0, 0);
+        //cont.Background.SetAnimation(DownBorder());
         
         return temp;
     }
@@ -1172,125 +1122,84 @@
     }
     
     UI::Template SimpleGenerator::Inputbox() {
-        Geometry::Size defsize = {WidgetWidth * 2 + Spacing, BorderedWidgetHeight};
+        Geometry::Size defsize = {WidgetWidth, BorderedWidgetHeight};
         
         UI::Template temp;
+        temp.SetSpacing(Spacing);
         temp.SetSize(defsize);
+        
+        
+        temp.AddContainer(0, UI::ComponentCondition::Always)
+            .AddIndex(1) //border
+            .AddIndex(2) //boxed content
+        ;
+        
+        auto setupborder = [&](auto &anim, UI::ComponentCondition condition) {
+            auto &bg = temp.AddContainer(1, condition);
+            bg.Background.SetAnimation(anim);
+            bg.SetSize(100, 100, UI::Dimension::Percent);
+            bg.SetPositioning(UI::ComponentTemplate::Absolute);
+        };
 
-        {
-            auto &bg = temp.AddContainer(0, UI::ComponentCondition::Always);
-            bg.AddIndex(5);
-        }
-
-        {
-            auto &bg = temp.AddContainer(0, UI::ComponentCondition::Readonly);
-            bg.AddIndex(6);
-        }
+        setupborder(NormalEditBorder(), UI::ComponentCondition::Always);
+        setupborder(HoverEditBorder(), UI::ComponentCondition::Hover);
+        setupborder(NormalBorder(), UI::ComponentCondition::Readonly);
+        setupborder(DisabledBorder(), UI::ComponentCondition::Disabled);
+        
+        auto &boxed = temp.AddContainer(2, UI::ComponentCondition::Always)
+            .AddIndex(3) //clip
+            .AddIndex(4) //focus
+        ;
+        boxed.SetSize(100, 100, UI::Dimension::Percent);
+        boxed.SetBorderSize(Border.Width);
+        boxed.SetPadding(std::max(Border.Radius / 2, Focus.Spacing));
+        boxed.SetPositioning(UI::ComponentTemplate::Absolute);
+        
+        auto &clip = temp.AddContainer(3, UI::ComponentCondition::Always)
+            .AddIndex(5)
+        ;
+        clip.SetClip(true);
+        clip.SetPadding(Focus.Spacing + Focus.Width);
+        clip.SetSize(100, 100, UI::Dimension::Percent);
+        clip.SetAnchor(UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
+        
+        //Contents
+        auto &content = temp.AddContainer(5, UI::ComponentCondition::Always)
+            .AddIndex(6) //text
+            .AddIndex(7) //selection
+            .AddIndex(8) //caret
+        ;
+        content.SetSize(100, 100, UI::Dimension::Percent);
+        content.SetPositioning(UI::ComponentTemplate::Absolute);
+        content.SetAnchor(UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
+        content.SetTag(UI::ComponentTemplate::ViewPortTag);
+        
+        
+        //Text
+        auto setuptext = [&](Graphics::RGBA color, UI::ComponentCondition condition) {
+            auto &txt = temp.AddTextholder(6, condition);
+            txt.SetRenderer(RegularFont);
+            txt.SetColor(color);
+            txt.SetAnchor(UI::Anchor::MiddleRight, UI::Anchor::MiddleLeft, UI::Anchor::MiddleLeft);
+            txt.SetDataEffect(UI::ComponentTemplate::Text);
+            txt.SetSize(100, 100, UI::Dimension::Percent);
+            txt.SetPositioning(UI::ComponentTemplate::Absolute);
+            txt.SetTag(UI::ComponentTemplate::ContentsTag);
+        };
+        
+        setuptext(Forecolor.Regular, UI::ComponentCondition::Always);
+        setuptext(Forecolor.Regular.BlendWith(Forecolor.Hover), UI::ComponentCondition::Hover);
+        setuptext(Forecolor.Regular.BlendWith(Forecolor.Down), UI::ComponentCondition::Down);
+        setuptext(Forecolor.Regular.BlendWith(Forecolor.Disabled), UI::ComponentCondition::Disabled);
         
         {
-            auto &bg_n = temp.AddContainer(5, UI::ComponentCondition::Always);
-            bg_n.SetPadding(Spacing + Border.Width , UI::Dimension::Pixel);
-            bg_n.AddIndex(1);
-            bg_n.AddIndex(2);
-            bg_n.AddIndex(3);
-            bg_n.AddIndex(4);
-            bg_n.SetSize(100, 100, UI::Dimension::Percent);
-            bg_n.SetClip(true); //!Shadow
-            bg_n.Background.SetAnimation(NormalEditBorder());
-        }
-
-        {
-            auto &bg_h = temp.AddContainer(5, UI::ComponentCondition::Hover);
-            bg_h.SetPadding(Spacing + Border.Width);
-            bg_h.AddIndex(1);
-            bg_h.AddIndex(2);
-            bg_h.AddIndex(3);
-            bg_h.AddIndex(4);
-            bg_h.SetSize(100, 100, UI::Dimension::Percent);
-            bg_h.SetClip(true); //!Shadow
-            bg_h.Background.SetAnimation(HoverEditBorder());
-        }
-
-        {
-            auto &bg_r = temp.AddContainer(6, UI::ComponentCondition::Readonly);
-            bg_r.SetPadding(Spacing + Border.Width);
-            bg_r.AddIndex(1);
-            bg_r.AddIndex(2);
-            bg_r.AddIndex(3);
-            bg_r.AddIndex(4);
-            bg_r.SetSize(100, 100, UI::Dimension::Percent);
-            bg_r.SetClip(true); //!Shadow
-            bg_r.Background.SetAnimation(DisabledBorder());
-        }
-
-        {
-            auto &bg_d = temp.AddContainer(5, UI::ComponentCondition::Disabled);
-            bg_d.SetPadding(Spacing + Border.Width);
-            bg_d.AddIndex(1);
-            bg_d.AddIndex(2);
-            bg_d.AddIndex(3);
-            bg_d.AddIndex(4);
-            bg_d.SetSize(100, 100, UI::Dimension::Percent);
-            bg_d.SetClip(true); //!Shadow
-            bg_d.Background.SetAnimation(DisabledBorder());
-        }
-        
-        {
-            auto &foc = temp.AddContainer(1, UI::ComponentCondition::Focused);
-            foc.Background.SetAnimation(FocusBorder());
-            foc.SetIndent(-Focus.Width*2);
-            foc.SetSize(100, 100, UI::Dimension::Percent);
-            foc.SetPositioning(foc.Absolute);
-            foc.SetAnchor(UI::Anchor::None, UI::Anchor::MiddleCenter, UI::Anchor::MiddleCenter);
-        }
-
-        {
-            auto &txt_n = temp.AddTextholder(2, UI::ComponentCondition::Always);
-            txt_n.SetRenderer(RegularFont);
-            txt_n.SetColor(Forecolor.Regular);
-            txt_n.SetAnchor(UI::Anchor::MiddleRight, UI::Anchor::MiddleLeft, UI::Anchor::MiddleLeft);
-            txt_n.SetDataEffect(UI::ComponentTemplate::Text);
-            txt_n.SetTag(txt_n.ContentsTag);
-            txt_n.SetSize({100, UI::Dimension::Percent}, lettervsize.first+lettervsize.second);
-            txt_n.SetSizing(UI::ComponentTemplate::Fixed);
-        }
-
-        {
-            
-            auto c = Forecolor.Regular;
-            c.Blend(Forecolor.Hover);
-            auto &txt_h = temp.AddTextholder(2, UI::ComponentCondition::Hover);
-            txt_h.SetRenderer(RegularFont);
-            txt_h.SetColor(c);
-            txt_h.SetAnchor(UI::Anchor::MiddleRight, UI::Anchor::MiddleLeft, UI::Anchor::MiddleLeft);
-            txt_h.SetDataEffect(UI::ComponentTemplate::Text);
-            txt_h.SetTag(txt_h.ContentsTag);
-            txt_h.SetSize({100, UI::Dimension::Percent}, lettervsize.first+lettervsize.second);
-            txt_h.SetSizing(UI::ComponentTemplate::Fixed);
-        }
-
-        {
-            auto c = Forecolor.Regular;
-            c.Blend(Forecolor.Disabled);
-            auto &txt_d = temp.AddTextholder(2, UI::ComponentCondition::Disabled);
-            txt_d.SetRenderer(RegularFont);
-            txt_d.SetColor(c);
-            txt_d.SetAnchor(UI::Anchor::MiddleRight, UI::Anchor::MiddleLeft, UI::Anchor::MiddleLeft);
-            txt_d.SetDataEffect(UI::ComponentTemplate::Text);
-            txt_d.SetTag(txt_d.ContentsTag);
-            txt_d.SetSize({100, UI::Dimension::Percent}, lettervsize.first+lettervsize.second);
-            txt_d.SetSizing(UI::ComponentTemplate::Fixed);
-        }
-
-        {
             auto &anim = *new Graphics::BitmapAnimationProvider();
-            int h = lettervsize.first + lettervsize.second;
-            auto &img = *new Graphics::Bitmap({std::min((int)std::round(Border.Width/2.f), 1), h});
-            img.ForAllPixels([&img, this, h](int x, int y) {
+            auto &img = *new Graphics::Bitmap({std::min((int)std::round(Border.Width/2.f), 1), ObjectHeight});
+            img.ForAllPixels([&img, this](int x, int y) {
                 img(x, y, 0) = Border.Color.R;
                 img(x, y, 1) = Border.Color.G;
                 img(x, y, 2) = Border.Color.B;
-                img(x, y, 3) = (y >= (asciivsize.first - 1) && y <= (lettervsize.first + regularrenderer->GetBaseLine()+1)) * Border.Color.A;
+                img(x, y, 3) = /*(y >= (asciivsize.first - 1) && y <= (lettervsize.first + regularrenderer->GetBaseLine()+1)) **/ Border.Color.A;
             });
             drawables.Add(img);
             img.Prepare();
@@ -1303,7 +1212,7 @@
             anim.Add(img2, 300);
             providers.Add(anim);
             
-            auto &caret = temp.AddGraphics(3, UI::ComponentCondition::Focused);
+            auto &caret = temp.AddGraphics(8, UI::ComponentCondition::Focused);
             caret.Content.SetAnimation(anim);
             caret.SetPosition(0, 0, UI::Dimension::Pixel);
             caret.SetPositioning(caret.Absolute);
@@ -1316,18 +1225,18 @@
         {
             auto &img = *new Graphics::BlankImage(8, 8, Background.Selected);
             
-            int h = RegularFont.GetGlyphRenderer().GetHeight();
-            
-            auto &selection = temp.AddGraphics(4, UI::ComponentCondition::Focused);
+            auto &selection = temp.AddGraphics(7, UI::ComponentCondition::Focused);
             selection.Content.SetDrawable(img);
             selection.SetPosition(0, 0, UI::Dimension::Pixel);
             selection.SetPositioning(selection.Absolute);
             selection.SetAnchor(UI::Anchor::None, UI::Anchor::MiddleLeft, UI::Anchor::MiddleLeft);
             selection.SetTag(selection.SelectionTag);
-            selection.SetSize(10, lettervsize.second + lettervsize.first + 1);
+            selection.SetSize(0, ObjectHeight);
             selection.SetSizing(UI::ComponentTemplate::Fixed);
         }
         
+        setupfocus(temp.AddGraphics(4, UI::ComponentCondition::Focused));
+        
         return temp;
     }
 
@@ -1335,6 +1244,7 @@
         Geometry::Size defsize = {WidgetWidth * 2 + Spacing, WidgetHeight};
         
         UI::Template temp;
+        temp.SetSpacing(Spacing);
         temp.SetSize(defsize);
         
         {
--- a/Source/Gorgon/Widgets/Generator.h	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/Widgets/Generator.h	Thu Sep 17 16:29:02 2020 +0300
@@ -114,8 +114,8 @@
     class SimpleGenerator : public Generator {
     public:
         
-        /// Initializes the generator
-        explicit SimpleGenerator(int fontsize, std::string fontname = "", bool activate = true);
+        /// Initializes the generator. Density controls the spacing between elements
+        explicit SimpleGenerator(int fontsize, std::string fontname = "", bool activate = true, float density = 7.5);
         
         /// Creates a non-working simple generator. Calls to any function other than Init
         /// is undefined behaviour.
@@ -198,9 +198,10 @@
         
         Graphics::RectangleProvider &FocusBorder();
         
-        int Spacing      = 4;
-        int ObjectHeight = 15;
-        int ObjectBorder = 2;
+        int Spacing       = 4;
+        int ObjectHeight  = 15;
+        int ObjectBorder  = 2;
+        float ShapeBorder = 2;
         
         /// This function will update default widget dimensions. Call this function after
         /// setting up or changing borders, font size
@@ -210,10 +211,13 @@
         void UpdateBorders(bool smooth = true);
 
         Graphics::StyledRenderer RegularFont;
+        Graphics::StyledRenderer CenteredFont;
 
         struct FocusInfo {
-            Graphics::RGBA  Color = {Graphics::Color::Charcoal, 0.7};
-            int             Width = 1;
+            Graphics::RGBA  Color   = {Graphics::Color::Charcoal, 0.7};
+            int             Width   = 1;
+            //focus to content spacing
+            int             Spacing = 1;
         } Focus;
         
         struct BorderInfo {
@@ -221,12 +225,12 @@
             int Radius              = 0;
             int Divisions           = 1;
             Graphics::RGBA Color    = Graphics::Color::Charcoal;
-            Graphics::RGBA Disabled = {Graphics::Color::Grey, 0.5};
+            Graphics::RGBA Disabled = {Graphics::Color::Charcoal, 0.5};
         } Border;
         
         struct BackgroundInfo {
             Graphics::RGBA Regular = {Graphics::Color::Ivory, 0.8};
-            Graphics::RGBA Hover   = {Graphics::Color::LightTan, 0.5};
+            Graphics::RGBA Hover   = {Graphics::Color::Tan, 0.5};
             Graphics::RGBA Down    = {Graphics::Color::Crimson, 0.2};
             Graphics::RGBA Disabled=  Graphics::Color::LightGrey;
 
@@ -254,12 +258,18 @@
         
         /// This is the height of a non-bordered widget
         int WidgetHeight = 24;
+        
+        /// This controls the automatic spacing. After chaning this member
+        /// you need to call UpdateDimensions to get the desired effect.
+        float Density = 7.5;
 
     private:
         Graphics::BitmapRectangleProvider *makeborder(Graphics::RGBA border, Graphics::RGBA bg, int missingedge = 0, int borderwidth = -1, int borderradius = -1);
         Graphics::RectangleProvider *makefocusborder();
         UI::Template makepanel(int missingedge);
         
+        void setupfocus(UI::GraphicsTemplate &focus);
+        
         Graphics::GlyphRenderer *regularrenderer = nullptr;
         Containers::Collection<Graphics::Drawable> drawables;
         Containers::Collection<Graphics::AnimationProvider> providers;
--- a/Source/Gorgon/Widgets/Inputbox.cpp	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/Widgets/Inputbox.cpp	Thu Sep 17 16:29:02 2020 +0300
@@ -2,6 +2,7 @@
 
 #include "../Graphics/Font.h"
 #include "../WindowManager.h"
+#include "../UI.h"
 
 namespace Gorgon { namespace Widgets { namespace internal {
     
@@ -188,6 +189,10 @@
             return true;
 
         if(state) {
+            //tab and escape are always passed through
+            if(key == Keycodes::Tab || key == Keycodes::Escape)
+                return false;
+            
             if(Input::Keyboard::CurrentModifier == Modifier::None) {
                 switch(key) {
                 case Keycodes::Home:
@@ -262,8 +267,12 @@
                 }
             }
         }
+        
+        if(state && !Input::Keyboard::CurrentModifier.IsModified()) {
+            Input::AllowCharEvent = true;
+        }
 
-        return false;
+        return !Input::Keyboard::CurrentModifier.IsModified();
     }
 
     bool Inputbox_base::CharacterEvent(Char c) {
@@ -338,8 +347,6 @@
         else
             pos += sellen.glyph;
 
-        //std::cout<<selstart.glyph<<"\t"<<selstart.byte<<"\t|\t"<<sellen.glyph<<"\t"<<sellen.byte<<"\t|\t"<<glyphcount<<std::endl;
-
         Geometry::Point location;
         auto textsize = renderer.GetSize(display);
         
@@ -352,10 +359,13 @@
             targetsize = stack.TagBounds(UI::ComponentTemplate::ViewPortTag).GetSize();
         }
         
+        
+        bool inarea = false;
         if(targetsize.Width > textsize.Width) {
             scrolloffset = 0;
 
             stack.SetTagLocation(UI::ComponentTemplate::ContentsTag, {scrolloffset, 0});
+            inarea = true;
         }
         
         if(display == "") {
@@ -377,29 +387,32 @@
             stack.SetTagLocation(UI::ComponentTemplate::ContentsTag, {scrolloffset, 0});
         }
 
-        stack.SetTagLocation(UI::ComponentTemplate::CaretTag, {location.X + scrolloffset, location.Y});
+        if(display == "") {
+            stack.RemoveTagLocation(UI::ComponentTemplate::CaretTag);
+        }
+        else {
+            stack.SetTagLocation(UI::ComponentTemplate::CaretTag, {location.X + scrolloffset, location.Y});
+        }
         
         if(stack.IndexOfTag(UI::ComponentTemplate::SelectionTag) != -1) {
-            auto selbounds = stack.TagBounds(UI::ComponentTemplate::SelectionTag);
             if(sellen.byte == 0) {
-                stack.SetTagSize(UI::ComponentTemplate::SelectionTag, {0, selbounds.Height()});
+                stack.RemoveTagSize(UI::ComponentTemplate::SelectionTag);
             }
             else {
                 auto srclocation = renderer.GetPosition(display, stack.TagBounds(UI::ComponentTemplate::ContentsTag).Width(), selstart.glyph, false).BottomLeft();
                 
                 if(srclocation.X < location.X) {
                     stack.SetTagLocation(UI::ComponentTemplate::SelectionTag, {srclocation.X + scrolloffset, 0});
-                    stack.SetTagSize(UI::ComponentTemplate::SelectionTag, {location.X - srclocation.X, selbounds.Height()});
+                    stack.SetTagSize(UI::ComponentTemplate::SelectionTag, {location.X - srclocation.X, 0});
                 }
                 else {
                     stack.SetTagLocation(UI::ComponentTemplate::SelectionTag, {location.X + scrolloffset, 0});
-                    stack.SetTagSize(UI::ComponentTemplate::SelectionTag, {srclocation.X - location.X, selbounds.Height()});
+                    stack.SetTagSize(UI::ComponentTemplate::SelectionTag, {srclocation.X - location.X, 0});
                 }
             }
         }
     }
 
-
     void Inputbox_base::focused() {
         UI::ComponentStackWidget::focused();
         
--- a/Source/Gorgon/Widgets/Panel.cpp	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/Widgets/Panel.cpp	Thu Sep 17 16:29:02 2020 +0300
@@ -64,7 +64,6 @@
         SetSmoothScrollSpeed(scrollspeed);
     }
 
-    
     bool Panel::Activate() {
         if(!Focus())
             return false;
@@ -73,7 +72,6 @@
 
         return true;
     }
-
     
     bool Panel::KeyEvent(Input::Key key, float state) {
         if(UI::WidgetContainer::KeyEvent(key, state))
@@ -103,17 +101,14 @@
         
         return false;
     }
-
     
     bool Panel::CharacterEvent(Char c) {
         return UI::WidgetContainer::CharacterEvent(c);
     }
-
     
     bool Panel::IsVisible() const {
         return stack.IsVisible();
     }
-
     
     Geometry::Size Panel::GetInteriorSize() const {
         auto size = stack.TagBounds(UI::ComponentTemplate::ViewPortTag).GetSize();
@@ -124,7 +119,6 @@
         
         return size;
     }
-    
 
     bool Panel::ResizeInterior(Geometry::Size size) {
         Geometry::Size border = {0, 0};
@@ -158,32 +152,27 @@
         return false;
     }
     
-
     void Panel::focused() {
         if(!HasFocusedWidget())
             FocusFirst();
         WidgetBase::focused();
     }
     
-
     void Panel::focuslost() {
         RemoveFocus();
         WidgetBase::focuslost();
     }
-
     
     Gorgon::Layer &Panel::getlayer() {
         return stack.GetLayerOf(stack.IndexOfTag(UI::ComponentTemplate::ContentsTag));
     }
 
-
     void Panel::focuschanged() { 
         if(HasFocusedWidget() && !IsFocused())
             Focus();
         else if(!HasFocusedWidget() && IsFocused())
             RemoveFocus();
     }
-    
 
     void Panel::ScrollTo(int x, int y, bool clip){
         auto b = stack.TagBounds(UI::ComponentTemplate::ContentsTag);
@@ -211,6 +200,7 @@
         
         if(scrollspeed == 0) {
             stack.SetTagLocation(UI::ComponentTemplate::ContentsTag, {-x, -y});
+            scrolloffset = {x, y};
         }
         else {
             if(!isscrolling) {
@@ -261,6 +251,8 @@
         doaxis(cur.X, target.X);
         doaxis(cur.Y, target.Y);
         
+        scrolloffset = cur;
+        
         stack.SetTagLocation(UI::ComponentTemplate::ContentsTag, -cur);
         
         if(done == 2) {
@@ -270,14 +262,10 @@
         }
     }
     
-    
     Geometry::Point Panel::ScrollOffset() const {
-        auto b = stack.TagBounds(UI::ComponentTemplate::ContentsTag);
-
-        return -b.TopLeft();
+        return scrolloffset;
     }
     
-    
     void Panel::childboundschanged(WidgetBase *source) {
         WidgetContainer::childboundschanged(source);
         
@@ -319,7 +307,6 @@
         updaterequired = false;
     }
     
-    
     void Panel::SetOverscroll(int value) {
         overscroll = value;
         
@@ -348,7 +335,6 @@
         return {xscroll, yscroll};
     }
 
-
     void Panel::SetSmoothScrollSpeed(int value){
         auto b = stack.TagBounds(UI::ComponentTemplate::ContentsTag);
         auto s = b.GetSize();
@@ -369,8 +355,7 @@
             stack.SetValueTransitionSpeed({(float)value / s.Width, (float)value / s.Height, 0, 0});
     }
     
-    
-     bool Panel::EnsureVisible(const UI::WidgetBase &widget) {
+    bool Panel::EnsureVisible(const UI::WidgetBase &widget) {
         if(widgets.Find(widget) == widgets.end())
             return false;
         
@@ -381,11 +366,24 @@
         
         Geometry::Bounds cb = {target, GetInteriorSize()};
         
-        if(!Contains(cb, wb)) {
-            ScrollTo(wb.TopLeft());
+        bool doscroll = false;
+        auto scrollto = ScrollOffset();
+        
+        if(cb.Left > wb.Left || cb.Right < wb.Right) {
+            scrollto.X = wb.Left;
+            doscroll = true;
         }
         
+        if(cb.Top > wb.Top || cb.Bottom < wb.Bottom) {
+            scrollto.Y = wb.Top;
+            doscroll = true;
+        }
+        
+        if(doscroll)
+            ScrollTo(scrollto);
+        
         return true;
     }
     
 } }
+
--- a/Source/Gorgon/Widgets/Panel.h	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/Widgets/Panel.h	Thu Sep 17 16:29:02 2020 +0300
@@ -183,6 +183,7 @@
         int overscroll = 0;
         bool scrollclipped = true;
         Geometry::Point scrolldist = {80, 45};
+        Geometry::Point scrolloffset = {0, 0};
         int scrollspeed = 250;
         Geometry::Point target;
         bool isscrolling = false;
--- a/Source/Gorgon/Widgets/RadioButtons.h	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/Widgets/RadioButtons.h	Thu Sep 17 16:29:02 2020 +0300
@@ -20,9 +20,15 @@
     class RadioButtons : public UI::WidgetBase, protected UI::RadioControl<T_, W_>, public UI::WidgetContainer {
         friend class UI::WidgetContainer;
     public:
-        explicit RadioButtons(const UI::Template &temp) : temp(temp) { this->own = true; }
+        explicit RadioButtons(const UI::Template &temp) : temp(temp) { 
+            spacing = temp.GetSpacing();
+            this->own = true;
+        }
         
-        explicit RadioButtons(Registry::TemplateType type = Registry::Radio_Regular) : temp(Registry::Active()[type]) {  this->own = true; }
+        explicit RadioButtons(Registry::TemplateType type = Registry::Radio_Regular) : temp(Registry::Active()[type]) {  
+            spacing = temp.GetSpacing();
+            this->own = true; 
+        }
 
         
         /// Radio buttons height is automatically adjusted. Only width will be used.
@@ -77,10 +83,10 @@
             if(GetWidth() < c.GetWidth())
                 SetWidth(c.GetWidth());
             
-            contents.SetHeight(GetHeight() + c.GetHeight() + spacing);
-            
             if(IsVisible())
                 this->PlaceIn((UI::WidgetContainer&)*this, {0, 0}, spacing);
+                
+            contents.SetHeight(this->widgets.Last()->GetBounds().Bottom);
             
             boundschanged();
             childboundschanged(&c);
@@ -103,7 +109,7 @@
                 if(IsVisible())
                     this->PlaceIn((UI::WidgetContainer&)*this, {0, 0}, spacing);
                 
-                contents.SetHeight(this->widgets.Last()->GetBounds().Bottom + 1);
+                contents.SetHeight(this->widgets.Last()->GetBounds().Bottom);
                 
                 boundschanged();
                 childboundschanged(&elm);
--- a/Source/Gorgon/Widgets/Registry.h	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/Widgets/Registry.h	Thu Sep 17 16:29:02 2020 +0300
@@ -3,12 +3,12 @@
 #include "../UI/Template.h"
 
 namespace Gorgon { namespace Widgets {
-   
+
     
     /**
-     * This class stores templates for elements. Once a registry is active
-     * all created widgets will use the specified registry for templates.
-     */
+    * This class stores templates for elements. Once a registry is active
+    * all created widgets will use the specified registry for templates.
+    */
     class Registry {
     public:
         
@@ -77,11 +77,10 @@
             
             return *templates[type];
         }
-        
-	
-		virtual int GetSpacing()const = 0;
+    
+        virtual int GetSpacing()const = 0;
 
-		virtual int GetEmSize()const = 0;
+        virtual int GetEmSize()const = 0;
 
     protected:
 
@@ -104,9 +103,9 @@
     
     
     /**
-     * This registry contains preset templates. You are required to set all the templates
-     * otherwise, missing templates will be generated completely empty. 
-     */
+    * This registry contains preset templates. You are required to set all the templates
+    * otherwise, missing templates will be generated completely empty. 
+    */
     class PresetRegistry : public Registry {
     public:
         
@@ -118,33 +117,33 @@
             templates[type] = &temp;
         }
         
-		void SetSpacing(const int tspacing) {
-			spacing = tspacing;
-		}
+        void SetSpacing(const int tspacing) {
+            spacing = tspacing;
+        }
 
-		void SetEmSize(const int size) {
-			emsize = size;
+        void SetEmSize(const int size) {
+            emsize = size;
 
-		}
+        }
 
-		virtual int GetSpacing()const override {
-			return spacing;
-		}
+        virtual int GetSpacing()const override {
+            return spacing;
+        }
 
-		virtual int GetEmSize()const override {
-			return emsize;
-		}
+        virtual int GetEmSize()const override {
+            return emsize;
+        }
 
     protected:
         virtual UI::Template &generate(Gorgon::Widgets::Registry::TemplateType) override {
             return *new UI::Template();
         }
-		
-		int spacing = 5;
+        
+        int spacing = 5;
 
-		int emsize = 14;
+        int emsize = 14;
 
     };
     
-	
+    
 } }
--- a/Source/Gorgon/Window.cpp	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/Window.cpp	Thu Sep 17 16:29:02 2020 +0300
@@ -46,6 +46,27 @@
 		}
         else
             windows.Remove(other);
+        
+        //events
+		FocusedEvent.Swap(other.FocusedEvent);
+
+		LostFocusEvent.Swap(other.LostFocusEvent);
+
+		DestroyedEvent.Swap(other.DestroyedEvent);
+
+		ClosingEvent.Swap(other.ClosingEvent);
+
+		MovedEvent.Swap(other.MovedEvent);
+
+		ResizedEvent.Swap(other.ResizedEvent);
+
+		MinimizedEvent.Swap(other.MinimizedEvent);
+
+		RestoredEvent.Swap(other.RestoredEvent);
+		
+		KeyEvent.Swap(other.KeyEvent);
+
+		CharacterEvent.Swap(other.CharacterEvent);
 
 		updatedataowner();
 		other.updatedataowner();
--- a/Source/Gorgon/WindowManager/DWM/Input.cpp	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/WindowManager/DWM/Input.cpp	Thu Sep 17 16:29:02 2020 +0300
@@ -1,6 +1,7 @@
 #include "DWM.h"
 
 #include "../../Window.h"
+#include "../../Main.h"
 
 namespace Gorgon { 
 
@@ -325,8 +326,10 @@
 		//if the key is repeating, do not repeat keyevent.
 		if(!(lParam&1<<30)) {
 			data->pressedkeys.insert(key);
+            
+            Input::AllowCharEvent = false;
 			auto token = data->parent->KeyEvent(key, true);
-			if(token!=ConsumableEvent<Window, Input::Key, bool>::EmptyToken) {
+			if(token!=ConsumableEvent<Window, Input::Key, bool>::EmptyToken && !Input::AllowCharEvent) {
 				data->handlers[key] = token;
 
 				return;
@@ -525,4 +528,4 @@
 		}
 	}
 
-} }
\ No newline at end of file
+} }
--- a/Source/Gorgon/WindowManager/X11/Input.cpp	Wed Aug 12 16:03:46 2020 +0300
+++ b/Source/Gorgon/WindowManager/X11/Input.cpp	Thu Sep 17 16:29:02 2020 +0300
@@ -349,8 +349,9 @@
                 break;
         }
         auto ggekey = WindowManager::mapx11key(key, event.xkey.keycode);
+        Input::AllowCharEvent = false;
         auto token = wind.KeyEvent(ggekey, true);
-        if(token != wind.KeyEvent.EmptyToken) {
+        if(token != wind.KeyEvent.EmptyToken && !Input::AllowCharEvent) {
             data->handlers[ggekey]=token;
             
             return;
--- a/Testing/Source/Manual/GraphicsHelper.h	Wed Aug 12 16:03:46 2020 +0300
+++ b/Testing/Source/Manual/GraphicsHelper.h	Thu Sep 17 16:29:02 2020 +0300
@@ -26,45 +26,45 @@
 template<class W_>
 class basic_Application {
 public:
-	basic_Application(std::string appname, std::string title, std::string helptext, int tilesize=25, int colmod = 0x10) :
-		appname(appname)
-	{
-		std::cout<<"Current working directory: ";
+    basic_Application(std::string appname, std::string title, std::string helptext, int tilesize=25, int colmod = 0x10) :
+        appname(appname)
+    {
+        std::cout<<"Current working directory: ";
 #ifdef WIN32
-		system("cd");
+        system("cd");
 #else
-		system("pwd");
+        system("pwd");
 #endif
-		std::cout<<std::endl;
+        std::cout<<std::endl;
 
-		Gorgon::Initialize(appname);
+        Gorgon::Initialize(appname);
 
-		wind ={{800, 600}, appname, title, true};
+        wind ={{800, 600}, appname, title, true};
 
-		//Gorgon::GL::log.InitializeConsole();
+        //Gorgon::GL::log.InitializeConsole();
 
-		Graphics::Initialize();
+        Graphics::Initialize();
         UI::Initialize();
 
-
-		wind.ClosingEvent.Register([] { exit(0); });
+        wind.ClosingEvent.Register([] { exit(0); });
 
         l.setname("BG");
-		wind.Add(l);
+        wind.Add(l);
 
-		if(icon.Import("icon.png")) {
-			ico = WM::Icon{icon.GetData()};
-			wind.SetIcon(ico);
-		}
+        if(icon.Import("icon.png")) {
+            ico = WM::Icon{icon.GetData()};
+            wind.SetIcon(ico);
+        }
         wind.setname("Wind");
 
-		bgimage = BGImage(tilesize, tilesize, colmod, colmod*3);
-		bgimage.Prepare();
-		bgimage.DrawIn(l);
+        bgimage = BGImage(tilesize, tilesize, colmod, colmod*3);
+        bgimage.Prepare();
+        bgimage.DrawIn(l);
     
         int sz = 11;
 #ifdef WIN32
         fnt.LoadFile("C:/Windows/Fonts/tahoma.ttf", sz);
+        fntlarge.LoadFile("C:/Windows/Fonts/tahoma.ttf", int(std::round(sz*1.5)));
 #else
         bool found = false;
         std::streambuf *buf;
@@ -81,6 +81,8 @@
                     auto fname = String::Extract(line, '"', true);
                     std::cout<<fname<<std::endl;
                     found = fnt.LoadFile(fname, sz);
+                    if(found) 
+                        fntlarge.LoadFile(fname, sz*1.5);
                     break;
                 }
             }
@@ -88,8 +90,10 @@
             delete buf;
         }
         
-        if(!found)
+        if(!found) {
             fnt.LoadFile("/usr/share/fonts/gnu-free/FreeSans.ttf", sz);
+            fntlarge.LoadFile("/usr/share/fonts/gnu-free/FreeSans.ttf", sz*1.5);
+        }
 #endif
         if(!fnt.HasKerning()) {
             auto bmpfnt = new Graphics::BitmapFont(fnt.MoveOutBitmap());
@@ -97,33 +101,37 @@
             bmpfnt->AutoKern();
         }
         
-		sty.UseFlatShadow({0.f, 1.0f}, {1.f, 1.f});
-		sty.SetColor({0.6f, 1.f, 1.f});
-		sty.JustifyLeft();
+        sty.UseFlatShadow({0.f, 1.0f}, {1.f, 1.f});
+        sty.SetColor({0.6f, 1.f, 1.f});
+        sty.JustifyLeft();
 
-		sty.SetTabWidthInLetters(4);
-		sty.SetParagraphSpacing(4);
-		/*sty.Print(l,
-				  helptext
-				  , 500, 10, wind.GetWidth()-505
-		);*/
+        stylarge.UseFlatShadow({0.f, 1.0f}, {1.f, 1.f});
+        stylarge.SetColor({1.f, 1.f, 1.f});
+        stylarge.AlignCenter();
 
-		wind.KeyEvent.Register([this](Input::Key key, bool state) {
-			if(!state && (key == 27 || key == 65307))
-				exit(0);
+        sty.SetTabWidthInLetters(4);
+        sty.SetParagraphSpacing(4);
+        sty.Print(l,
+                helptext
+                , 600, 10, wind.GetWidth()-605
+        );
 
-			return false;
-		});
-	}
+        wind.KeyEvent.Register([](Input::Key key, bool state) {
+            if(!state && (key == 27 || key == 65307))
+                exit(0);
 
-	W_ wind;
-	Graphics::Layer l;
-	Bitmap bgimage, icon;
-	Graphics::FreeType fnt;
-    Graphics::StyledRenderer sty = {fnt};
+            return false;
+        });
+    }
+
+    W_ wind;
+    Graphics::Layer l;
+    Bitmap bgimage, icon;
+    Graphics::FreeType fnt, fntlarge;
+    Graphics::StyledRenderer sty = {fnt}, stylarge = {fntlarge};
     WM::Icon ico;
 
-	std::string appname;
+    std::string appname;
 };
 
 using Application = basic_Application<Gorgon::Window>;
@@ -280,44 +288,44 @@
 }
 
 inline Graphics::Bitmap Rectangle(int w, int h) {
-	Graphics::Bitmap b({w, h}, Graphics::ColorMode::Alpha);
+    Graphics::Bitmap b({w, h}, Graphics::ColorMode::Alpha);
 
-	for(int y=0; y<h; y++) {
-		for(int x=0; x<w; x++) {
-			b(x, y, 0) = 255;
-		}
-	}
+    for(int y=0; y<h; y++) {
+        for(int x=0; x<w; x++) {
+            b(x, y, 0) = 255;
+        }
+    }
 
-	return b;
+    return b;
 }
 
 inline Graphics::Bitmap Pattern(int f) {
-	Graphics::Bitmap b({2, 2}, Graphics::ColorMode::Alpha);
+    Graphics::Bitmap b({2, 2}, Graphics::ColorMode::Alpha);
 
-	b.Clear();
+    b.Clear();
 
-	if(f>0)
-		b(0, 0, 0) = 255;
-	if(f>1)
-		b(1, 1, 0) = 255;
-	if(f>2)
-		b(1, 0, 0) = 255;
-	if(f>3)
-		b(0, 1, 0) = 255;
+    if(f>0)
+        b(0, 0, 0) = 255;
+    if(f>1)
+        b(1, 1, 0) = 255;
+    if(f>2)
+        b(1, 0, 0) = 255;
+    if(f>3)
+        b(0, 1, 0) = 255;
 
-	return b;
+    return b;
 }
 
 inline Graphics::Bitmap BGImage(int w, int h, Byte col1, Byte col2) {
-	Graphics::Bitmap bgimage({w*2, h*2}, Graphics::ColorMode::Grayscale);
+    Graphics::Bitmap bgimage({w*2, h*2}, Graphics::ColorMode::Grayscale);
 
-	for(int x = 0; x<w*2; x++) {
-		for(int y = 0; y<h*2; y++) {
-			if((x/w) != (y/h))
-				bgimage({x, y}, 0) = col1;
-			else
-				bgimage({x, y}, 0) = col2;
-		}
+    for(int x = 0; x<w*2; x++) {
+        for(int y = 0; y<h*2; y++) {
+            if((x/w) != (y/h))
+                bgimage({x, y}, 0) = col1;
+            else
+                bgimage({x, y}, 0) = col2;
+        }
     }
     
     return bgimage;
--- a/Testing/Source/Manual/UI_Component.cpp	Wed Aug 12 16:03:46 2020 +0300
+++ b/Testing/Source/Manual/UI_Component.cpp	Thu Sep 17 16:29:02 2020 +0300
@@ -6,92 +6,3263 @@
 #include <Gorgon/Graphics/BlankImage.h>
 #include <Gorgon/Graphics/Rectangle.h>
 #include <Gorgon/Graphics/TintedObject.h>
-
+#include <Gorgon/Input/KeyRepeater.h>
 
 std::string helptext = 
     "Key list:\n"
     "d\tToggle disabled\n"
-    "1-2\tChange Values\n"
-	"esc\tClose\n"
+    "left\tPrevious\n"
+    "right\tNext test\n"
+    "home\tFirst\n"
+    "end\tLast\n"
+    "c\tCopy title of the active test\n"
+    "1234\tIncrease the value of the stack\n"
+    "qwer\tDecrease the value of the stack\n"
+    "Shift\tSlower value change\n"
+    "Ctrl\tFaster value change, snaps to nearest 20%\n"
+    "56\tChange text, title\n"
+    "78\tChange icon1, icon2\n"
+    "esc\tClose\n"
 ;
 
+using namespace Gorgon::UI;
+namespace Color = Gorgon::Graphics::Color;
+
+struct TestData {
+    std::string name, description;
+    ComponentStack &stack;
+};
+
+extern std::vector<std::function<TestData(Layer &)>> tests;
+
+Application &getapp() {
+    auto help = helptext + String::Concat("\nTotal tests:\t", tests.size());
+    static Application app("uitest", "UI Component Test", help, 10, 8);
+    
+    return app;
+}
+
+//BEGIN Helpers
+
+Graphics::RectangleProvider &coloredrect(Graphics::RGBA color) {
+    //this will not leak
+    auto &img = *new Graphics::BlankImage(10, 10, {color, 0.6});
+    
+    //as long as rectangle is destroyed
+    auto &ret = *new Graphics::RectangleProvider(img);
+    ret.OwnProviders();
+    
+    return ret;
+}
+
+Graphics::RectangleProvider &cyanrect() {
+    static auto &rect = coloredrect(Graphics::Color::Cyan);
+    
+    return rect;
+}
+
+Graphics::RectangleProvider &redrect() {
+    static auto &rect = coloredrect(Graphics::Color::Red);
+    
+    return rect;
+}
+
+Graphics::RectangleProvider &greenrect() {
+    static auto &rect = coloredrect(Graphics::Color::Green);
+    
+    return rect;
+}
+
+Graphics::BlankImage &blankimage(Graphics::RGBA color, Geometry::Size size = {1, 1}) {
+    auto &img = *new Graphics::BlankImage(size * 10, {color, 0.6});
+    
+    return img;
+}
+
+
+Graphics::BlankImage &whiteimg() {
+    static auto &img = blankimage(Graphics::Color::White);
+    
+    return img;
+}
+
+Graphics::BlankImage &greenimg2x1() {
+    static auto &img = blankimage(Graphics::Color::Green, {2, 1});
+    
+    return img;
+}
+
+Graphics::BlankImage &greenimg1x2() {
+    static auto &img = blankimage(Graphics::Color::Green, {1, 2});
+    
+    return img;
+}
+
+Graphics::BlankImage &greenimg2x2() {
+    static auto &img = blankimage(Graphics::Color::Green, {2, 2});
+    
+    return img;
+}
+
+Graphics::BlankImage &greenimg() {
+    static auto &img = blankimage(Graphics::Color::Green);
+    
+    return img;
+}
+
+Graphics::BlankImage &redimg() {
+    static auto &img = blankimage(Graphics::Color::Red);
+    
+    return img;
+}
+
+Graphics::BlankImage &blackimg() {
+    static auto &img = blankimage(Graphics::Color::Black);
+    
+    return img;
+}
+
+Graphics::BlankImage &brownimg() {
+    static auto &img = blankimage(Graphics::Color::Brown);
+    
+    return img;
+}
+
+
+Graphics::BlankImage &blueimg() {
+    static auto &img = blankimage(Graphics::Color::Blue);
+    
+    return img;
+}
+
+Graphics::BlankImage &yellowimg() {
+    static auto &img = blankimage(Graphics::Color::Yellow);
+    
+    return img;
+}
+
+Graphics::BlankImage &purpleimg() {
+    static auto &img = blankimage(Graphics::Color::Purple);
+    
+    return img;
+}
+
+Graphics::BlankImage &grayimg() {
+    static auto &img = blankimage(Graphics::Color::Grey);
+    
+    return img;
+}
+
+Graphics::BlankImage &orangeimg() {
+    static auto &img = blankimage(Graphics::Color::Orange);
+    
+    return img;
+}
+
+Graphics::BitmapAnimationProvider &makecoloranim() {
+    auto &anim = *new Graphics::BitmapAnimationProvider;
+    
+    static decltype(Color::Red) colors[] = {Color::Red, Color::Orange, Color::Yellow, Color::Green, Color::Cyan, Color::Blue, Color::Magenta, Color::White, Color::Grey, Color::Black};
+    
+    for(auto color : colors) {
+        auto &img = *new Graphics::Bitmap(10, 10, Gorgon::Graphics::ColorMode::RGBA);
+        
+        img.ForAllPixels([&](int x, int y) {
+            img.SetRGBAAt(x, y, color);
+        });
+        
+        img.Prepare();
+        anim.Add(img, 100);
+        anim.Own(img);
+    }
+    
+    return anim;
+}
+
+Graphics::BitmapAnimationProvider &coloranim() {
+    static auto &anim = makecoloranim();
+    
+    return anim;
+}
+
+
+const std::string teststrings[] = {
+    "Hi",
+    "Hello",
+    "Hello world!",
+    "This is a very long text."
+};
+
+const Graphics::BlankImage *testimages[] = {
+    &orangeimg(),
+    &greenimg1x2(),
+    &greenimg2x1(),
+    &greenimg2x2(),
+    &redimg()
+};
+
+//END helpers
+
+
+//BEGIN tests
+
+/***********
+ * Tests
+ * These functions will create their objects on the heap. They
+ * will live until the program ends. Create the function and
+ * add it to the tests vector.
+ ***********/
+
+TestData test_graphic(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(50, 50);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(whiteimg());
+    
+    auto &cont2 = temp.AddGraphics(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Content.SetAnimation(greenimg());
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Graphic component", "10x10 green object on a 50x50 white background, should be aligned to top left.", stack};
+}
+
+TestData test_text(Layer &layer) {
+    auto &app = getapp();
+
+    auto &temp = *new Template;
+    temp.SetSize(50, 50);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(whiteimg());
+    
+    auto &cont2 = temp.AddTextholder(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.SetText("Hello");
+    cont2.SetColor(Color::Brown);
+    cont2.SetRenderer(app.fntlarge);
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Text component", "Brown Hello on 50x50 white background, should be aligned to top left.", stack};
+}
+
+TestData test_setsize(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(50, 50);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(whiteimg());
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(greenimg());
+    cont2.SetSize(20, 30);
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Set size", "20x30 green object on a 50x50 white background, should be aligned to top left.", stack};
+}
+
+TestData test_setsizepercent(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(60, 60);
+
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(whiteimg());
+
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(greenimg());
+    cont2.SetSize(5000, 3333, Gorgon::UI::Dimension::BasisPoint);
+
+    auto &stack = *new ComponentStack(temp);
+
+    layer.Add(stack);
+
+    return {"Set size percent", "30x20 green object on a 60x60 white background, should be aligned to top left.", stack};
+}
+
+TestData test_setsizepercent_percent(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(60, 60);
+
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.AddIndex(2);
+    cont1.Background.SetAnimation(whiteimg());
+
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(greenimg());
+    cont2.SetSize(3333, 3333, Gorgon::UI::Dimension::BasisPoint);
+
+    auto &cont3 = temp.AddContainer(2, Gorgon::UI::ComponentCondition::Always);
+    cont3.Background.SetAnimation(redimg());
+    cont3.SetSize(50, 50, Gorgon::UI::Dimension::Percent);
+
+    auto &stack = *new ComponentStack(temp);
+
+    layer.Add(stack);
+
+    return {"Set size percent x2", "Size 20x20 and 30x30 objects on a 60x60 white background, should be aligned to top left. Objects are green and red and should be touching.", stack};
+}
+
+TestData test_setsizepercent_rel(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(60, 60);
+
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.AddIndex(2);
+    cont1.Background.SetAnimation(whiteimg());
+
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(greenimg());
+    cont2.SetSize(20, 20, Gorgon::UI::Dimension::Pixel);
+    cont2.SetPosition(0, 0);
+
+    auto &cont3 = temp.AddContainer(2, Gorgon::UI::ComponentCondition::Always);
+    cont3.Background.SetAnimation(redimg());
+    cont3.SetSize(50, 50, Gorgon::UI::Dimension::Percent);
+
+    auto &stack = *new ComponentStack(temp);
+
+    layer.Add(stack);
+
+    return {"Set size percent relative", "Size 20x20 and 20x30 objects on a 60x60 white background, should be aligned to top left. Objects are green and red and should be touching.", stack};
+}
+
+TestData test_sizepercent_center(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(80, 80);
+
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(whiteimg());
+
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(greenimg());
+    cont2.SetSize(50, 50, Gorgon::UI::Dimension::Percent);
+    cont2.SetAnchor(UI::Anchor::None, UI::Anchor::MiddleCenter, UI::Anchor::TopLeft);
+
+    auto &stack = *new ComponentStack(temp);
+
+    layer.Add(stack);
+
+    return {"Set size percent from center", "20x20 green object on a 80x80 white background, should be aligned to center from its top left.", stack};
+}
+
+TestData test_sizepercent_centerabs(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(80, 80);
+
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(whiteimg());
+
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(greenimg());
+    cont2.SetSize(50, 50, Gorgon::UI::Dimension::Percent);
+    cont2.SetAnchor(UI::Anchor::None, UI::Anchor::MiddleCenter, UI::Anchor::TopLeft);
+    cont2.SetPositioning(cont2.Absolute);
+
+    auto &stack = *new ComponentStack(temp);
+
+    layer.Add(stack);
+
+    return {"Set size percent from center absolute", "20x20 green object on a 80x80 white background, should be aligned to center from its top left.", stack};
+}
+
+TestData test_setborder(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(50, 50);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(whiteimg());
+    cont1.SetBorderSize(10);
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(greenrect());
+    cont2.SetSize(100, 100, Gorgon::UI::Dimension::Percent);
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Set border", "White background (50x50) and a green border (starting from 10,10, size of 30x30). Result should be concentric squares, 10px size difference, white, green, white.", stack};
+}
+
+TestData test_setborder2(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(70, 70);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(whiteimg());
+    cont1.SetBorderSize(10,20,30,40);
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(greenrect());
+    cont2.SetSize(100, 100, Gorgon::UI::Dimension::Percent);
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Set border", "This has a white border around a green rectangle 30x10 in size. Border size should be left: 10, top: 20, right: 30, bottom: 40", stack};
+}
+
+TestData test_setoverlay(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(50, 50);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.Background.SetAnimation(whiteimg());
+    cont1.SetOverlayExtent(10);
+    cont1.SetBorderSize(10);
+    cont1.Overlay.SetAnimation(greenrect());
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Set overlay", "White background (50x50) and a green border (starting from 10,10, size of 30x30). Result should be concentric squares, 10px size difference, white, green, white.", stack};
+}
+
+TestData test_setpadding(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(50, 50);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetPadding(10);
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redrect());
+    cont2.SetSize(100, 100, Gorgon::UI::Dimension::Percent);
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Set padding", "Two empty squares inside each other. Cyan on the outside, red inside. There should be 10x10 empty square at the middle. Borders should be 10px in size and should touch each other.", stack};
+}
+
+TestData test_setpadding2(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(70, 70);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetPadding(20, 10, 30, 40);
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redrect());
+    cont2.SetSize(100, 100, Gorgon::UI::Dimension::Percent);
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Set padding", "This has a cyan border around a green rectangle 20x20 in size. Padding should be left: 20, top: 10, right: 30, bottom: 40.", stack};
+}
+
+TestData test_setpadding_percent(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(100, 100);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetPadding(20, 10, 30, 40, Gorgon::UI::Dimension::Percent);
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redimg());
+    cont2.SetSize(100, 100, Gorgon::UI::Dimension::Percent);
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Set padding percent", "This has a cyan border around a red rectangle 50x50 in size. Padding should be left: 20, top: 10, right: 30, bottom: 40.", stack};
+}
+
+TestData test_setpadding_border(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(120, 120);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetBorderSize(10);
+    cont1.SetPadding(20, 10, 30, 40, Gorgon::UI::Dimension::Percent);
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redrect());
+    cont2.SetSize(100, 100, Gorgon::UI::Dimension::Percent);
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Set border and padding", "This has a cyan border around a red rectangle 50x50 in size. There is 10px border as well as padding. Padding should be left: 20, top: 10, right: 30, bottom: 40.", stack};
+}
+
+TestData test_setmargin_parent(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(50, 50);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redrect());
+    cont2.SetSize(100, 100, Gorgon::UI::Dimension::Percent);
+    cont2.SetMargin(10);
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Set margin", "Two empty squares inside each other. Cyan on the outside, red inside. There should be 10x10 empty square at the middle. Borders should be 10px in size and should touch each other.", stack};
+}
+
+TestData test_setmargin_parent_percent(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(50, 50);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redrect());
+    cont2.SetSize(100, 100, Gorgon::UI::Dimension::Percent);
+    cont2.SetMargin(20, Gorgon::UI::Dimension::Percent);
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Set margin percent", "Two empty squares inside each other. Cyan on the outside, red inside. There should be 10x10 empty square at the middle. Borders should be 10px in size and should touch each other.", stack};
+}
+
+TestData test_margin_parent_padding(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(50, 60);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetPadding(10,20,10,10);
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redrect());
+    cont2.SetSize(100, 100, Gorgon::UI::Dimension::Percent);
+    cont2.SetMargin(10);
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Margin padding collapse", "Two empty squares inside each other. Cyan on the outside, red inside. There should be 10x10 empty square at the middle. Borders should be 10px in size and should touch each other apart from the top where it should have 10px space between two borders..", stack};
+}
+
+TestData test_setindent(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(50, 50);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redrect());
+    cont2.SetSize(100, 100, Gorgon::UI::Dimension::Percent);
+    cont2.SetIndent(10);
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Set indent", "Two empty squares inside each other. Cyan on the outside, red inside. There should be 10x10 empty square at the middle. Borders should be 10px in size and should touch each other.", stack};
+}
+
+TestData test_indent_padding(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(50, 50);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetPadding(10);
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redrect());
+    cont2.SetSize(100, 100, Gorgon::UI::Dimension::Percent);
+    cont2.SetIndent(10);
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Set indent", "Two empty squares inside each other. Cyan on the outside, red inside. Inner border should be 10x10 and there should be 10px space between borders", stack};
+}
+
+TestData test_setpadding_negative(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(50, 50);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetPadding(0, -10, 0, 0);
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redrect());
+    cont2.SetSize(100, 100, Gorgon::UI::Dimension::Percent);
+    cont2.SetMargin(10);
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Set padding negative", "Two empty squares inside each other. Cyan on the outside, red inside. There should be 10x20 empty square at the middle. Borders should be 10px in size and should touch each other apart from top which they should be on top of each other.", stack};
+}
+
+TestData test_setmargin_negative(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(50, 50);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetPadding(10);
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redrect());
+    cont2.SetSize(100, 100, Gorgon::UI::Dimension::Percent);
+    cont2.SetMargin(-10, 0, -10, 0);
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Set margin negative", "Two empty squares inside each other. Cyan on the outside, red inside. There should be 30x10 empty square at the middle. Borders should be 10px in size and should touch each other apart from left and right which they should be on top of each other.", stack};
+}
+
+TestData test_border_padding_margin_size(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(120, 120);
+
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.AddIndex(2);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetBorderSize(10);
+    cont1.SetPadding(20, 10, 10, 40, Gorgon::UI::Dimension::Percent);
+
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redimg());
+    cont2.SetSize({50, Gorgon::UI::Dimension::Percent}, 40);
+    cont2.SetMargin(10, 20, 30, -10, Gorgon::UI::Dimension::Pixel);
+
+    auto &cont3 = temp.AddContainer(2, Gorgon::UI::ComponentCondition::Always);
+    cont3.Background.SetAnimation(greenimg());
+    cont3.SetSize(20, 60, Gorgon::UI::Dimension::Pixel);
+    cont3.SetMargin(30, -10, 0, 0, Gorgon::UI::Dimension::Pixel);
+
+    auto &stack = *new ComponentStack(temp);
+
+    layer.Add(stack);
+
+    return {"Set border, padding, margin and check relative sizing", "This has a cyan border around a 10x40 red object and 20x60 green object. There should be 30px between object. Red object should be 20px from top border, green object should be aligned to the red object from top.", stack};
+}
+
+TestData test_absanch_samepoint(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(70, 70);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    for(int i=1; i<=9; i++) 
+        cont1.AddIndex(i);
+    
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetPadding(10);
+    
+    Containers::Collection<Graphics::BlankImage> images = {
+        redimg(), yellowimg(), orangeimg(),
+        blueimg(), purpleimg(), brownimg(),
+        greenimg(), grayimg(), whiteimg(),
+    };
+    
+    for(int i=1; i<=9; i++) {
+        auto &cont = temp.AddContainer(i, Gorgon::UI::ComponentCondition::Always);
+        cont.Background.SetAnimation(images[i-1]);
+        cont.SetPositioning(Gorgon::UI::ComponentTemplate::Absolute);
+        cont.SetAnchor(Gorgon::UI::Anchor(i), Gorgon::UI::Anchor(i), Gorgon::UI::Anchor(i));
+        cont.SetSize(10, 10, Gorgon::UI::Dimension::Pixel);
+        cont.SetPosition(0,0);
+    }
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Absolute anchoring", "9 components will be anchored in a cyan rectangle. Colors at top from left: red, yellow, orange; middle: blue, purple, brown; bottom: green, gray, white. Apart from the center component, all component should touch cyan border. No component should touch (not even corner to corner) each other (10px space around all).", stack};
+}
+
+TestData test_paranch_samepoint(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(70, 70);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    for(int i=1; i<=9; i++) 
+        cont1.AddIndex(i);
+    
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetPadding(10);
+    
+    Containers::Collection<Graphics::BlankImage> images = {
+        redimg(), yellowimg(), orangeimg(),
+        blueimg(), purpleimg(), brownimg(),
+        greenimg(), grayimg(), whiteimg(),
+    };
+    
+    for(int i=1; i<=9; i++) {
+        auto &cont = temp.AddContainer(i, Gorgon::UI::ComponentCondition::Always);
+        cont.Background.SetAnimation(images[i-1]);
+        cont.SetAnchor(Gorgon::UI::Anchor::None, Gorgon::UI::Anchor(i), Gorgon::UI::Anchor(i));
+        cont.SetSize(10, 10, Gorgon::UI::Dimension::Pixel);
+        cont.SetPosition(0,0);
+    }
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Parent anchoring", "9 components will be anchored in a cyan rectangle. Colors at top from left: red, yellow, orange; middle: blue, purple, brown; bottom: green, gray, white. Apart from the center component, all component should touch cyan border. No component should touch (not even corner to corner) each other (10px space around all).", stack};
+}
+
+TestData test_absanch_centertopoint(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(80, 80);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    for(int i=1; i<=9; i++) 
+        cont1.AddIndex(i);
+    
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetPadding(10);
+    
+    Containers::Collection<Graphics::BlankImage> images = {
+        redimg(), yellowimg(), orangeimg(),
+        blueimg(), purpleimg(), brownimg(),
+        greenimg(), grayimg(), whiteimg(),
+    };
+    
+    for(int i=1; i<=9; i++) {
+        auto &cont = temp.AddContainer(i, Gorgon::UI::ComponentCondition::Always);
+        cont.Background.SetAnimation(images[i-1]);
+        cont.SetPositioning(Gorgon::UI::ComponentTemplate::Absolute);
+        cont.SetAnchor(Gorgon::UI::Anchor::None, Gorgon::UI::Anchor(i), Gorgon::UI::Anchor::MiddleCenter);
+        cont.SetSize(20, 20, Gorgon::UI::Dimension::Pixel);
+        cont.SetPosition(0,0);
+    }
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Absolute anchoring center to anchor", "9 components will be anchored in a cyan rectangle. Colors at top from left: red, yellow, orange; middle: blue, purple, brown; bottom: green, gray, white. Apart from the center component, all component should overlap cyan border. No component should touch (not even corner to corner) each other (10px space around all).", stack};
+}
+
+TestData test_absanchoff(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(60, 60);
+
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(whiteimg());
+
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(blueimg());
+    cont2.SetSize(20, 20, Gorgon::UI::Dimension::Pixel);
+    cont2.SetPosition(10, 20);
+
+    auto &stack = *new ComponentStack(temp);
+
+    layer.Add(stack);
+
+    return {"Absolute anchoring from top-left", "Blue object of size 20x20 on white background with 10, 20 pixel from top.", stack};
+}
+
+TestData test_absanchoffsize(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(60, 60);
+
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetBorderSize(10);
+
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(greenimg());
+    cont2.SetSize(100, 100, Gorgon::UI::Dimension::Percent);
+    cont2.SetPositioning(UI::ComponentTemplate::Absolute);
+    cont2.SetPosition(10, 20);
+
+    auto &stack = *new ComponentStack(temp);
+
+    layer.Add(stack);
+
+    return {"Absolute anchoring from top-left", "Green object in a cyan rectangle with 10, 20 pixel from border. It should fill the rest of the space.", stack};
+}
+
+TestData test_absanchoffrev(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(60, 60);
+
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(whiteimg());
+
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(blueimg());
+    cont2.SetSize(20, 20, Gorgon::UI::Dimension::Pixel);
+    cont2.SetAnchor(UI::Anchor::None, UI::Anchor::BottomRight, UI::Anchor::BottomRight);
+    cont2.SetPositioning(UI::ComponentTemplate::Absolute);
+    cont2.SetPosition(10, 20);
+
+    auto &stack = *new ComponentStack(temp);
+
+    layer.Add(stack);
+
+    return {"Absolute anchoring from bottom-right", "Blue object of size 20x20 on white background with 10, 20 pixel from bottom right.", stack};
+}
+
+TestData test_relanch(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(60, 60);
+
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.AddIndex(2);
+    cont1.Background.SetAnimation(whiteimg());
+
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(greenimg());
+    cont2.SetSize(20, 20, Gorgon::UI::Dimension::Pixel);
+
+    auto &cont3 = temp.AddContainer(2, Gorgon::UI::ComponentCondition::Always);
+    cont3.Background.SetAnimation(redimg());
+    cont3.SetSize(20, 20, Gorgon::UI::Dimension::Pixel);
+
+    auto &stack = *new ComponentStack(temp);
+
+    layer.Add(stack);
+
+    return {"Relative anchoring", "Size 20x20 and 20x20 objects on a 60x60 white background, first one should be aligned to top left, second should be left of first one. Objects are green and red and should be touching.", stack};
+}
+
+TestData test_relanchvert(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(60, 60);
+
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.AddIndex(2);
+    cont1.SetOrientation(Gorgon::Graphics::Orientation::Vertical);
+    cont1.Background.SetAnimation(whiteimg());
+
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(greenimg());
+    cont2.SetSize(20, 20, Gorgon::UI::Dimension::Pixel);
+
+    auto &cont3 = temp.AddContainer(2, Gorgon::UI::ComponentCondition::Always);
+    cont3.Background.SetAnimation(redimg());
+    cont3.SetSize(20, 20, Gorgon::UI::Dimension::Pixel);
+    cont3.SetAnchor(Gorgon::UI::Anchor::BottomLeft, Gorgon::UI::Anchor::TopLeft, Gorgon::UI::Anchor::TopLeft);
+
+    auto &stack = *new ComponentStack(temp);
+
+    layer.Add(stack);
+
+    return {"Relative anchoring vertical", "Size 20x20 and 20x20 objects on a 60x60 white background, first one should be aligned to top left, second should be under the first one. Objects are green and red and should be touching.", stack};
+}
+
+TestData test_relanch2(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(60, 60);
+
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.AddIndex(2);
+    cont1.Background.SetAnimation(whiteimg());
+
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(greenimg());
+    cont2.SetSize(20, 20, Gorgon::UI::Dimension::Pixel);
+
+    auto &cont3 = temp.AddContainer(2, Gorgon::UI::ComponentCondition::Always);
+    cont3.Background.SetAnimation(redimg());
+    cont3.SetSize(20, 20, Gorgon::UI::Dimension::Pixel);
+    cont3.SetAnchor(UI::Anchor::BottomRight, UI::Anchor::BottomLeft, UI::Anchor::TopLeft);
+
+    auto &stack = *new ComponentStack(temp);
+
+    layer.Add(stack);
+
+    return {"Relative anchoring", "Size 20x20 and 20x20 objects on a 60x60 white background, first should be aligned to top left. Objects are green and red and should be touching from the corners.", stack};
+}
+
+TestData test_anchbaseline(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(60, 60);
+
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.AddIndex(2);
+    cont1.AddIndex(3);
+    cont1.Background.SetAnimation(whiteimg());
+
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(greenimg());
+    cont2.SetSize(20, 20, Gorgon::UI::Dimension::Pixel);
+    cont2.SetAnchor(UI::Anchor::FirstBaselineRight, UI::Anchor::FirstBaselineLeft, UI::Anchor::FirstBaselineLeft);
+
+    auto &cont3 = temp.AddContainer(2, Gorgon::UI::ComponentCondition::Always);
+    cont3.Background.SetAnimation(redimg());
+    cont3.SetSize(20, 20, Gorgon::UI::Dimension::Pixel);
+    cont3.SetAnchor(UI::Anchor::FirstBaselineRight, UI::Anchor::FirstBaselineLeft, UI::Anchor::FirstBaselineLeft);
+    
+    static Graphics::BitmapFont fnt;
+    fnt.SetBaseline(20);
+    auto &cont4 = temp.AddTextholder(3, Gorgon::UI::ComponentCondition::Always);
+    cont4.SetRenderer(fnt);
+
+    auto &stack = *new ComponentStack(temp);
+
+    layer.Add(stack);
+
+    return {"Baseline anchoring", "Size 20x20 and 20x20 objects on a 60x60 white background, first should be aligned to top left. Objects are green and red and should be touching from the corners.", stack};
+}
+
+TestData test_anchsetbaseline(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(60, 60);
+
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.AddIndex(2);
+    cont1.AddIndex(3);
+    cont1.SetBaseline(30);
+    cont1.Background.SetAnimation(whiteimg());
+
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(greenimg());
+    cont2.SetSize(20, 20, Gorgon::UI::Dimension::Pixel);
+    cont2.SetBaseline(10);
+    cont2.SetAnchor(UI::Anchor::FirstBaselineRight, UI::Anchor::FirstBaselineLeft, UI::Anchor::FirstBaselineLeft);
+
+    auto &cont3 = temp.AddContainer(2, Gorgon::UI::ComponentCondition::Always);
+    cont3.Background.SetAnimation(redimg());
+    cont3.SetSize(20, 20, Gorgon::UI::Dimension::Pixel);
+    cont3.SetBaseline(20);
+    cont3.SetAnchor(UI::Anchor::FirstBaselineRight, UI::Anchor::FirstBaselineLeft, UI::Anchor::FirstBaselineLeft);
+    
+    static Graphics::BitmapFont fnt;
+    fnt.SetBaseline(20);
+    auto &cont4 = temp.AddTextholder(3, Gorgon::UI::ComponentCondition::Always);
+    cont4.SetRenderer(fnt);
+
+    auto &stack = *new ComponentStack(temp);
+
+    layer.Add(stack);
+
+    return {"Baseline anchoring using set baseline", "Size 20x20 and 20x20 objects on a 60x60 white background, first should be aligned to left, 20px from the top; second should be touching first object, should be from 10px from the top border. Objects are green and red.", stack};
+}
+
+TestData test_anchbaseline2(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(60, 60);
+
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.AddIndex(2);
+    cont1.SetBaseline(30);
+    cont1.Background.SetAnimation(whiteimg());
+
+    static Graphics::BitmapFont fnt;
+    fnt.AddGlyph(' ', redimg());
+    fnt.SetBaseline(10);
+    
+    static Graphics::BitmapFont fnt2;
+    fnt2.AddGlyph(' ', greenimg1x2());
+    fnt2.SetBaseline(20);
+    
+    auto &cont2 = temp.AddTextholder(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.SetRenderer(fnt);
+    cont2.SetAnchor(UI::Anchor::FirstBaselineRight, UI::Anchor::FirstBaselineLeft, UI::Anchor::FirstBaselineLeft);
+    cont2.SetText(" ");
+    cont2.SetSize(10,10);
+    
+    auto &cont3 = temp.AddTextholder(2, Gorgon::UI::ComponentCondition::Always);
+    cont3.SetRenderer(fnt2);
+    cont3.SetAnchor(UI::Anchor::FirstBaselineRight, UI::Anchor::FirstBaselineLeft, UI::Anchor::FirstBaselineLeft);
+    cont3.SetText(" ");
+    cont3.SetSize(10,10);
+    
+
+    auto &stack = *new ComponentStack(temp);
+
+    layer.Add(stack);
+
+    return {"Baseline anchoring between textholders", "Size 10x10 and 10x20 objects on a 60x60 white background, first should be aligned to left, 20px from the top; second should be touching first object, should be from 10px from the top border. Objects are red and green.", stack};
+}
+
+TestData test_abssliding(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(80, 40);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.AddIndex(2);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetBorderSize(10);
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redrect());
+    cont2.SetSize(10, 10, Gorgon::UI::Dimension::Pixel);
+    cont2.SetPositioning(Gorgon::UI::ComponentTemplate::AbsoluteSliding);
+    cont2.SetAnchor(Gorgon::UI::Anchor::None, Gorgon::UI::Anchor::TopLeft, Gorgon::UI::Anchor::TopLeft);
+    cont2.SetPosition(20, 0, Gorgon::UI::Dimension::Percent);
+    
+    
+    auto &cont3 = temp.AddContainer(2, Gorgon::UI::ComponentCondition::Always);
+    cont3.Background.SetAnimation(greenrect());
+    cont3.SetSize(10, 10, Gorgon::UI::Dimension::Pixel);
+    cont3.SetAnchor(Gorgon::UI::Anchor::None, Gorgon::UI::Anchor::TopLeft, Gorgon::UI::Anchor::TopLeft);
+    cont3.SetPositioning(Gorgon::UI::ComponentTemplate::AbsoluteSliding);
+    cont3.SetMargin(10, 0, 10, 0);
+    cont3.SetPosition(3333, 10000, Gorgon::UI::Dimension::BasisPoint);
+    
+    
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"AbsoluteSliding", "80x40 cyan rectangle contains 10x10 red and green rectangle. Red rectangle should be touching cyan from top, it should be 10px from the left border. Green rectangle should be touching to the bottom of cyan border, 20px from the left. Inner rectangles should be touching on the corners.", stack};
+}
+
+TestData test_abspolar(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(100, 60);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.AddIndex(2);
+    cont1.Background.SetAnimation(whiteimg());
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redrect());
+    cont2.SetSize(20, 20, Gorgon::UI::Dimension::Pixel);
+    cont2.SetPositioning(Gorgon::UI::ComponentTemplate::PolarAbsolute);
+    cont2.SetAnchor(Gorgon::UI::Anchor::None, Gorgon::UI::Anchor::MiddleCenter, Gorgon::UI::Anchor::TopLeft);
+    cont2.SetPosition(10, 90);
+    
+    
+    auto &cont3 = temp.AddContainer(2, Gorgon::UI::ComponentCondition::Always);
+    cont3.Background.SetAnimation(greenrect());
+    cont3.SetSize(20, 20, Gorgon::UI::Dimension::Pixel);
+    cont3.SetAnchor(Gorgon::UI::Anchor::None, Gorgon::UI::Anchor::MiddleCenter, Gorgon::UI::Anchor::TopLeft);
+    cont3.SetPositioning(Gorgon::UI::ComponentTemplate::PolarAbsolute);
+    cont3.SetMargin(10, 0, 10, 0);
+    cont3.SetPosition(50, 50, Gorgon::UI::Dimension::Percent);
+    
+    
+    
+    auto &stack = *new ComponentStack(temp);
+        
+    layer.Add(stack);
+    
+    return {"PolarAbsolute", "100x60 white background contains 20x20 red and green rectangle. Red rectangle should be 10px from top, centered. Green rectangle should be at the middle 30px from the left.", stack};
+}
+
+TestData test_abspolar2(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(120, 70);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.AddIndex(2);
+    cont1.SetCenter(50, 0, Gorgon::UI::Dimension::Percent);
+    cont1.Background.SetAnimation(whiteimg());
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redrect());
+    cont2.SetSize(20, 20, Gorgon::UI::Dimension::Pixel);
+    cont2.SetPositioning(Gorgon::UI::ComponentTemplate::PolarAbsolute);
+    cont2.SetAnchor(Gorgon::UI::Anchor::None, Gorgon::UI::Anchor::TopCenter, Gorgon::UI::Anchor::TopLeft);
+    cont2.SetPosition({40, UI::Dimension::Percent}, {200, UI::Dimension::EM});
+    cont2.SetCenter(50, 0, Gorgon::UI::Dimension::Percent);
+    
+    auto &cont3 = temp.AddContainer(2, Gorgon::UI::ComponentCondition::Always);
+    cont3.Background.SetAnimation(greenrect());
+    cont3.SetSize(20, 20, Gorgon::UI::Dimension::Pixel);
+    cont3.SetPositioning(Gorgon::UI::ComponentTemplate::PolarAbsolute);
+    cont3.SetAnchor(Gorgon::UI::Anchor::None, Gorgon::UI::Anchor::BottomCenter, Gorgon::UI::Anchor::TopLeft);
+    cont3.SetPosition(100, 100, Gorgon::UI::Dimension::Percent);
+    cont3.SetCenter(50, 100, Gorgon::UI::Dimension::Percent);
+    cont3.SetMargin(0, 100, Gorgon::UI::Dimension::Percent);
+    
+    
+    auto &stack = *new ComponentStack(temp);
+        
+    layer.Add(stack);
+    
+    return {"PolarAbsolute 2", "100x60 white background contains 20x20 red and green rectangle. Red rectangle should be 20px from top, in centered. Green rectangle should be at bottom left corner.", stack};
+}
+
+TestData test_modify_position_sliding(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(80, 40);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetBorderSize(10);
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redrect());
+    cont2.SetSize(10, 10, Gorgon::UI::Dimension::Pixel);
+    cont2.SetPositioning(Gorgon::UI::ComponentTemplate::AbsoluteSliding);
+    cont2.SetAnchor(Gorgon::UI::Anchor::None, Gorgon::UI::Anchor::TopLeft, Gorgon::UI::Anchor::TopLeft);
+    cont2.SetPosition(0, 0, Gorgon::UI::Dimension::Percent);
+    cont2.SetValueModification(Gorgon::UI::ComponentTemplate::ModifyPosition);
+    
+    
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Modify position sliding", "80x40 cyan rectangle contains 10x10 red rectangle. It should move from left to right with the change with the value of channel 1.", stack};
+}
+
+TestData test_modify_position_slidingvert(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(40, 80);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetBorderSize(10);
+    cont1.SetOrientation(Gorgon::Graphics::Orientation::Vertical);
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redrect());
+    cont2.SetSize(10, 10, Gorgon::UI::Dimension::Pixel);
+    cont2.SetPositioning(Gorgon::UI::ComponentTemplate::AbsoluteSliding);
+    cont2.SetAnchor(Gorgon::UI::Anchor::None, Gorgon::UI::Anchor::TopLeft, Gorgon::UI::Anchor::TopLeft);
+    cont2.SetPosition(0, 0, Gorgon::UI::Dimension::Percent);
+    cont2.SetValueModification(Gorgon::UI::ComponentTemplate::ModifyPosition);
+    
+    
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Modify position sliding vertical", "40x80 cyan rectangle contains 10x10 red rectangle. It should move from left to right with the change with the value of channel 1.", stack};
+}
+
+TestData test_modify_rev(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(80, 40);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetBorderSize(10);
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redrect());
+    cont2.SetSize(10, 10, Gorgon::UI::Dimension::Pixel);
+    cont2.SetPositioning(Gorgon::UI::ComponentTemplate::AbsoluteSliding);
+    cont2.SetAnchor(Gorgon::UI::Anchor::None, Gorgon::UI::Anchor::TopLeft, Gorgon::UI::Anchor::TopLeft);
+    cont2.SetPosition(0, 0, Gorgon::UI::Dimension::Percent);
+    cont2.SetValueModification(Gorgon::UI::ComponentTemplate::ModifyPosition);
+    cont2.SetValueRange(0, 1, 0);
+    
+    
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Reverse modify", "80x40 cyan rectangle contains 10x10 red rectangle. It should move from right to left with the change with the value of channel 1.", stack};
+}
+
+TestData test_modify_minmax(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(80, 40);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetBorderSize(10);
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redrect());
+    cont2.SetSize(10, 10, Gorgon::UI::Dimension::Pixel);
+    cont2.SetPositioning(Gorgon::UI::ComponentTemplate::AbsoluteSliding);
+    cont2.SetAnchor(Gorgon::UI::Anchor::None, Gorgon::UI::Anchor::TopLeft, Gorgon::UI::Anchor::TopLeft);
+    cont2.SetPosition(0, 0, Gorgon::UI::Dimension::Percent);
+    cont2.SetValueModification(Gorgon::UI::ComponentTemplate::ModifyPosition);
+    cont2.SetValueRange(0, 0.2, 0.8);
+    
+    
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Value range", "80x40 cyan rectangle contains 10x10 red rectangle. It should move from 10px left to 10px to right with the change with the value of channel 1.", stack};
+}
+
+TestData test_modify_chmap2(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(80, 40);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetBorderSize(10);
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redrect());
+    cont2.SetSize(10, 10, Gorgon::UI::Dimension::Pixel);
+    cont2.SetPositioning(Gorgon::UI::ComponentTemplate::AbsoluteSliding);
+    cont2.SetAnchor(Gorgon::UI::Anchor::None, Gorgon::UI::Anchor::TopLeft, Gorgon::UI::Anchor::TopLeft);
+    cont2.SetPosition(0, 0, Gorgon::UI::Dimension::Percent);
+    cont2.SetValueModification(Gorgon::UI::ComponentTemplate::ModifyPosition);
+    cont2.SetValueOrdering(1, 0, 0, 0);
+    
+    
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Channel mapping 2", "80x40 cyan rectangle contains 10x10 red rectangle. It should move from left to right with the change with the value of channel 2.", stack};
+}
+
+TestData test_modify_chmap3(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(80, 40);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetBorderSize(10);
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redrect());
+    cont2.SetSize(10, 10, Gorgon::UI::Dimension::Pixel);
+    cont2.SetPositioning(Gorgon::UI::ComponentTemplate::AbsoluteSliding);
+    cont2.SetAnchor(Gorgon::UI::Anchor::None, Gorgon::UI::Anchor::TopLeft, Gorgon::UI::Anchor::TopLeft);
+    cont2.SetPosition(0, 0, Gorgon::UI::Dimension::Percent);
+    cont2.SetValueModification(Gorgon::UI::ComponentTemplate::ModifyPosition);
+    cont2.SetValueOrdering(2, 0, 0, 0);
+    
+    
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Channel mapping 3", "80x40 cyan rectangle contains 10x10 red rectangle. It should move from left to right with the change with the value of channel 3.", stack};
+}
+
+TestData test_modify_chmap4(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(80, 40);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetBorderSize(10);
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redrect());
+    cont2.SetSize(10, 10, Gorgon::UI::Dimension::Pixel);
+    cont2.SetPositioning(Gorgon::UI::ComponentTemplate::AbsoluteSliding);
+    cont2.SetAnchor(Gorgon::UI::Anchor::None, Gorgon::UI::Anchor::TopLeft, Gorgon::UI::Anchor::TopLeft);
+    cont2.SetPosition(0, 0, Gorgon::UI::Dimension::Percent);
+    cont2.SetValueModification(Gorgon::UI::ComponentTemplate::ModifyPosition);
+    cont2.SetValueOrdering(3, 0, 0, 0);
+    
+    
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Channel mapping 4", "80x40 cyan rectangle contains 10x10 red rectangle. It should move from left to right with the change with the value of channel 4.", stack};
+}
+
+TestData test_modify_ch4_minmax(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(80, 40);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetBorderSize(10);
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redrect());
+    cont2.SetSize(10, 10, Gorgon::UI::Dimension::Pixel);
+    cont2.SetPositioning(Gorgon::UI::ComponentTemplate::AbsoluteSliding);
+    cont2.SetAnchor(Gorgon::UI::Anchor::None, Gorgon::UI::Anchor::TopLeft, Gorgon::UI::Anchor::TopLeft);
+    cont2.SetPosition(0, 0, Gorgon::UI::Dimension::Percent);
+    cont2.SetValueModification(Gorgon::UI::ComponentTemplate::ModifyPosition);
+    cont2.SetValueOrdering(3, 0, 0, 0);
+    cont2.SetValueRange(0, 0.2, 0.8);
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Channel map value range", "80x40 cyan rectangle contains 10x10 red rectangle. It should move from 10px left to 10px to right with the change with the value of channel 4.", stack};
+}
+
+TestData test_modify_position_2ch(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(80, 80);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetBorderSize(10);
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redrect());
+    cont2.SetSize(10, 10, Gorgon::UI::Dimension::Pixel);
+    cont2.SetPositioning(Gorgon::UI::ComponentTemplate::AbsoluteSliding);
+    cont2.SetAnchor(Gorgon::UI::Anchor::None, Gorgon::UI::Anchor::TopLeft, Gorgon::UI::Anchor::TopLeft);
+    cont2.SetPosition(0, 0, Gorgon::UI::Dimension::Percent);
+    cont2.SetValueModification(Gorgon::UI::ComponentTemplate::ModifyPosition);
+    cont2.SetValueSource(cont2.UseXY);
+    
+    
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Modify XY position sliding", "80x80 cyan rectangle contains 10x10 red rectangle. It should move from left to right with the change with the value of channel 1, top to bottom with 2.", stack};
+}
+
+TestData test_modify_position_absolute(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(70, 70);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetBorderSize(10);
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redrect());
+    cont2.SetSize(10, 10, Gorgon::UI::Dimension::Pixel);
+    cont2.SetPositioning(Gorgon::UI::ComponentTemplate::Absolute);
+    cont2.SetAnchor(Gorgon::UI::Anchor::None, Gorgon::UI::Anchor::TopLeft, Gorgon::UI::Anchor::TopLeft);
+    cont2.SetPosition(0, 0, Gorgon::UI::Dimension::Percent);
+    cont2.SetValueModification(Gorgon::UI::ComponentTemplate::ModifyPosition);
+    cont2.SetValueSource(cont2.UseXY);
+    
+    
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Modify XY position absolute", "70x70 cyan rectangle contains 10x10 red rectangle. It should move from left to right with the change with the value of channel 1, top to bottom with 2. At the right and bottom, component should pass the boundaries.", stack};
+}
+
+TestData test_modify_x(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(80, 80);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetBorderSize(10);
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redrect());
+    cont2.SetSize(10, 10, Gorgon::UI::Dimension::Pixel);
+    cont2.SetPositioning(Gorgon::UI::ComponentTemplate::AbsoluteSliding);
+    cont2.SetAnchor(Gorgon::UI::Anchor::None, Gorgon::UI::Anchor::TopLeft, Gorgon::UI::Anchor::TopLeft);
+    cont2.SetPosition(0, 0, Gorgon::UI::Dimension::Percent);
+    cont2.SetValueModification(Gorgon::UI::ComponentTemplate::ModifyX);
+    cont2.SetValueSource(cont2.UseX);
+    
+    
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Modify X", "80x80 cyan rectangle contains 10x10 red rectangle. It should move from left to right with the change with the value of channel 1. Other channel should not have any effect.", stack};
+}
+
+TestData test_modify_y(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(80, 80);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetBorderSize(10);
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redrect());
+    cont2.SetSize(10, 10, Gorgon::UI::Dimension::Pixel);
+    cont2.SetPositioning(Gorgon::UI::ComponentTemplate::AbsoluteSliding);
+    cont2.SetAnchor(Gorgon::UI::Anchor::None, Gorgon::UI::Anchor::TopLeft, Gorgon::UI::Anchor::TopLeft);
+    cont2.SetPosition(0, 0, Gorgon::UI::Dimension::Percent);
+    cont2.SetValueModification(Gorgon::UI::ComponentTemplate::ModifyY);
+    cont2.SetValueSource(cont2.UseX);
+    
+    
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Modify Y", "80x80 cyan rectangle contains 10x10 red rectangle. It should move from top to bottom with the change with the value of channel 1. Other channel should not have any effect.", stack};
+}
+
+TestData test_modify_size(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(80, 40);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetBorderSize(10);
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redimg());
+    cont2.SetSize(0, 10, Gorgon::UI::Dimension::Pixel);
+    cont2.SetPositioning(Gorgon::UI::ComponentTemplate::AbsoluteSliding);
+    cont2.SetAnchor(Gorgon::UI::Anchor::None, Gorgon::UI::Anchor::TopLeft, Gorgon::UI::Anchor::TopLeft);
+    cont2.SetPosition(0, 0, Gorgon::UI::Dimension::Percent);
+    cont2.SetValueModification(Gorgon::UI::ComponentTemplate::ModifySize);
+    
+    
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Modify size", "80x40 cyan rectangle contains 10px high red rectangle. It should scale from left to right with the change with the value of channel 1.", stack};
+}
+
+TestData test_modify_sizevert(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(40, 80);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetOrientation(Gorgon::Graphics::Orientation::Vertical);
+    cont1.SetBorderSize(10);
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redimg());
+    cont2.SetSize(10, 0, Gorgon::UI::Dimension::Pixel);
+    cont2.SetPositioning(Gorgon::UI::ComponentTemplate::AbsoluteSliding);
+    cont2.SetAnchor(Gorgon::UI::Anchor::None, Gorgon::UI::Anchor::TopLeft, Gorgon::UI::Anchor::TopLeft);
+    cont2.SetPosition(0, 0, Gorgon::UI::Dimension::Percent);
+    cont2.SetValueModification(Gorgon::UI::ComponentTemplate::ModifySize);
+    
+    
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Modify size vertical", "40x80 cyan rectangle contains 10px wide red rectangle. It should scale from top to bottom with the change with the value of channel 1.", stack};
+}
+
+TestData test_modify_sizemin(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(80, 40);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetBorderSize(10);
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redimg());
+    cont2.SetSize(10, 10, Gorgon::UI::Dimension::Pixel);
+    cont2.SetPositioning(Gorgon::UI::ComponentTemplate::AbsoluteSliding);
+    cont2.SetAnchor(Gorgon::UI::Anchor::None, Gorgon::UI::Anchor::TopLeft, Gorgon::UI::Anchor::TopLeft);
+    cont2.SetPosition(0, 0, Gorgon::UI::Dimension::Percent);
+    cont2.SetValueModification(Gorgon::UI::ComponentTemplate::ModifySize);
+    
+    
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Modify size set minimum", "80x40 cyan rectangle contains 10px high red rectangle. It should scale from left to right with the change with the value of channel 1 but it should have minimum of 10px.", stack};
+}
+
+TestData test_modify_sizexy(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(80, 40);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetBorderSize(10);
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redimg());
+    cont2.SetSize(0, 0, Gorgon::UI::Dimension::Pixel);
+    cont2.SetPositioning(Gorgon::UI::ComponentTemplate::AbsoluteSliding);
+    cont2.SetAnchor(Gorgon::UI::Anchor::None, Gorgon::UI::Anchor::TopLeft, Gorgon::UI::Anchor::TopLeft);
+    cont2.SetPosition(0, 0, Gorgon::UI::Dimension::Percent);
+    cont2.SetValueModification(Gorgon::UI::ComponentTemplate::ModifySize);
+    cont2.SetValueSource(Gorgon::UI::ComponentTemplate::UseSize);
+    
+    
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Modify size width & height", "80x40 cyan rectangle contains red rectangle. It should scale from left to right with the change with the value of channel 1 and top to bottom with the value of channel 2.", stack};
+}
+
+TestData test_modify_alpha(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(80, 80);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetBorderSize(10);
+    
+    auto &cont2 = temp.AddContainer(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Background.SetAnimation(redimg());
+    cont2.SetSize(60, 60, Gorgon::UI::Dimension::Pixel);
+    cont2.SetValueModification(Gorgon::UI::ComponentTemplate::ModifyAlpha);
+    cont2.SetValueSource(cont2.UseFirst);
+    
+    
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Modify blend", "80x80 cyan rectangle contains 60x60 red rectangle. It should appear with the change with the value of channel 1.", stack};
+}
+
+TestData test_modify_blend1(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(80, 80);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetBorderSize(10);
+    
+    auto &cont2 = temp.AddGraphics(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Content.SetAnimation(whiteimg());
+    cont2.SetSize(60, 60, Gorgon::UI::Dimension::Pixel);
+    cont2.SetValueModification(Gorgon::UI::ComponentTemplate::BlendColor);
+    cont2.SetValueSource(cont2.UseFirst);
+    cont2.SetColor(Color::Red);
+    cont2.SetTargetColor(Color::AppleGreen);
+    
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Blend", "80x80 cyan rectangle contains 60x60 red rectangle. Its color should change to green with the change with the value of channel 1.", stack};
+}
+
+TestData test_modify_blend2(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(80, 80);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetBorderSize(10);
+    
+    auto &cont2 = temp.AddGraphics(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Content.SetAnimation(whiteimg());
+    cont2.SetSize(60, 60, Gorgon::UI::Dimension::Pixel);
+    cont2.SetValueModification(Gorgon::UI::ComponentTemplate::BlendColor);
+    cont2.SetValueSource(cont2.UseRA);
+    cont2.SetColor(Color::Red);
+    cont2.SetTargetColor({Color::AppleGreen, 0.f});
+    
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Blend color & alpha", "80x80 cyan rectangle contains 60x60 red rectangle. Its color should change to green with the change with the value of channel 1, alpha will be modified from 60% to 0% with the value of channel 4.", stack};
+}
+
+TestData test_modify_blend4(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(80, 80);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetBorderSize(10);
+    
+    auto &cont2 = temp.AddGraphics(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Content.SetAnimation(whiteimg());
+    cont2.SetSize(60, 60, Gorgon::UI::Dimension::Pixel);
+    cont2.SetValueModification(Gorgon::UI::ComponentTemplate::BlendColor);
+    cont2.SetValueSource(cont2.UseRGBA);
+    cont2.SetColor(Color::Black);
+    cont2.SetTargetColor({Color::White, 0.f});
+    
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Blend color & alpha", "80x80 cyan rectangle contains 60x60 black rectangle. Its color should be controllable using all channels. Alpha is reversed.", stack};
+}
+
+TestData test_modify_animation(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(80, 80);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(cyanrect());
+    cont1.SetBorderSize(10);
+    
+    auto &cont2 = temp.AddGraphics(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.Content.SetAnimation(coloranim());
+    cont2.SetSize(60, 60, Gorgon::UI::Dimension::Pixel);
+    cont2.SetValueModification(Gorgon::UI::ComponentTemplate::ModifyAnimation);
+    cont2.SetValueSource(cont2.UseFirst);
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Animation", "80x80 cyan rectangle contains a 60x60 rectangle. It is an animation with 10 colors (red, orange, yellow, green, cyan, blue, magenta, white, grey, black), channel 1 can be used to control the animation frame. 0-10 should be red, orange starts from 11, yellow starts from 21 and so on.", stack};
+}
+
+TestData test_data_settext(Layer &layer) {
+    auto &app = getapp();
+
+    auto &temp = *new Template;
+    temp.SetSize(50, 50);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(whiteimg());
+    
+    auto &cont2 = temp.AddTextholder(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.SetDataEffect(Gorgon::UI::ComponentTemplate::Text);
+    cont2.SetColor(Color::Brown);
+    cont2.SetRenderer(app.fntlarge);
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Set text data", "Brown text obtained from text data on 50x50 white background, should be aligned to top left. Extra text should overflow.", stack};
+}
+
+TestData test_data_textwrap(Layer &layer) {
+    auto &app = getapp();
+
+    auto &temp = *new Template;
+    temp.SetSize(70, 50);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(whiteimg());
+    
+    auto &cont2 = temp.AddTextholder(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.SetDataEffect(Gorgon::UI::ComponentTemplate::Text);
+    cont2.SetColor(Color::Brown);
+    cont2.SetRenderer(app.fntlarge);
+    cont2.SetSize(100, 100, Gorgon::UI::Dimension::Percent);
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Text wrap", "Brown text obtained from text data on 70x50 white background, should be aligned to top left. Extra text should wrap but completely visible.", stack};
+}
+
+TestData test_data_textclip(Layer &layer) {
+    auto &app = getapp();
+
+    auto &temp = *new Template;
+    temp.SetSize(70, 50);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(whiteimg());
+    
+    auto &cont2 = temp.AddTextholder(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.SetDataEffect(Gorgon::UI::ComponentTemplate::Text);
+    cont2.SetColor(Color::Brown);
+    cont2.SetRenderer(app.fntlarge);
+    cont2.SetSize(100, 100, Gorgon::UI::Dimension::Percent);
+    cont2.SetClip(true);
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Text clipping", "Brown text obtained from text data on 70x50 white background, should be aligned to top left. Extra text should wrap and clipped.", stack};
+}
+
+TestData test_data_settitle(Layer &layer) {
+    auto &app = getapp();
+
+    auto &temp = *new Template;
+    temp.SetSize(50, 50);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(whiteimg());
+    
+    auto &cont2 = temp.AddTextholder(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.SetDataEffect(Gorgon::UI::ComponentTemplate::Title);
+    cont2.SetColor(Color::Brown);
+    cont2.SetRenderer(app.fntlarge);
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Set title data", "Brown text obtained from title data on 50x50 white background, should be aligned to top left. Extra text should overflow.", stack};
+}
+
+TestData test_data_settexttitle(Layer &layer) {
+    auto &app = getapp();
+
+    auto &temp = *new Template;
+    temp.SetSize(120, 50);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.AddIndex(2);
+    cont1.Background.SetAnimation(whiteimg());
+    
+    auto &cont2 = temp.AddTextholder(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.SetDataEffect(Gorgon::UI::ComponentTemplate::Title);
+    cont2.SetColor(Color::Brown);
+    cont2.SetRenderer(app.fntlarge);
+    
+    auto &cont3 = temp.AddTextholder(2, Gorgon::UI::ComponentCondition::Always);
+    cont3.SetDataEffect(Gorgon::UI::ComponentTemplate::Text);
+    cont3.SetColor(Color::DarkGreen);
+    cont3.SetRenderer(app.fnt);
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Set text data, title", "Brown text obtained from title data followed by small green text obtained from text on 120x50 white background, should be aligned to top left. Extra text should overflow. Two text components should be aligned from the baseline.", stack};
+}
+
+TestData test_data_setimage(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(50, 50);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(whiteimg());
+    
+    auto &cont2 = temp.AddPlaceholder(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.SetDataEffect(Gorgon::UI::ComponentTemplate::Icon1);
+    
+    auto &stack = *new ComponentStack(temp);
+    
+    layer.Add(stack);
+    
+    return {"Set image data", "Selected image obtained from icon 1 data on 50x50 white background, should be aligned to top left.", stack};
+}
+
+TestData test_data_setimagegt(Layer &layer) {
+    auto &temp = *new Template;
+    temp.SetSize(50, 50);
+    
+    auto &cont1 = temp.AddContainer(0, Gorgon::UI::ComponentCondition::Always);
+    cont1.AddIndex(1);
+    cont1.Background.SetAnimation(whiteimg());
+    
+    auto &cont2 = temp.AddGraphics(1, Gorgon::UI::ComponentCondition::Always);
+    cont2.SetDataEffect(Gorgon::UI::ComponentTemplate::Icon1);
+