From 9dfb33f2ed28a77c2e740f5ccb32b5aa81c328c1 Mon Sep 17 00:00:00 2001
From: Eduardo Bart <edub4rt@gmail.com>
Date: Sat, 16 Apr 2011 21:36:58 -0300
Subject: [PATCH] info window

---
 data/fonts/tibia-10px-antialised.yml      |  2 +-
 data/skins/tibiaskin.yml                  | 16 +++++++-
 data/ui/infoWindow.yml                    | 37 +++++++++----------
 src/framework/graphics/borderedimage.cpp  | 14 +++----
 src/framework/graphics/font.cpp           | 10 ++---
 src/framework/graphics/graphics.cpp       |  4 +-
 src/framework/graphics/textarea.cpp       |  2 +-
 src/framework/ui/ui.h                     |  2 +
 src/framework/ui/uiconstants.h            |  3 +-
 src/framework/ui/uielement.cpp            | 10 +----
 src/framework/ui/uielement.h              |  1 -
 src/framework/ui/uielementskin.cpp        | 17 ++++++---
 src/framework/ui/uielementskin.h          |  2 +-
 src/framework/ui/uilabel.cpp              | 10 -----
 src/framework/ui/uilabel.h                | 12 +++++-
 src/framework/ui/uilabelskin.cpp          | 11 ++++--
 src/framework/ui/uilabelskin.h            |  9 +++--
 src/framework/ui/uilinedecoration.cpp     | 24 ++++++++++++
 src/framework/ui/uilinedecoration.h       | 34 ++++++++++++++++-
 src/framework/ui/uilinedecorationskin.cpp | 28 ++++++++++++++
 src/framework/ui/uilinedecorationskin.h   | 34 ++++++++++++++++-
 src/framework/ui/uiloader.cpp             | 45 ++++++++++++++---------
 src/framework/ui/uiskins.cpp              | 14 +++++++
 src/framework/ui/uitexteditskin.cpp       |  1 +
 src/menustate.cpp                         | 21 +++++++++--
 src/menustate.h                           |  1 +
 26 files changed, 267 insertions(+), 97 deletions(-)

diff --git a/data/fonts/tibia-10px-antialised.yml b/data/fonts/tibia-10px-antialised.yml
index da60a5b5..ba2c0db9 100644
--- a/data/fonts/tibia-10px-antialised.yml
+++ b/data/fonts/tibia-10px-antialised.yml
@@ -1,5 +1,5 @@
 glyph height: 10
-glyph spacing: [1, 1]
+glyph spacing: [1, 4]
 top margin: 3
 image: tibia-10px-antialised.png
 image glyph size: [8, 16]
diff --git a/data/skins/tibiaskin.yml b/data/skins/tibiaskin.yml
index 9d1da26f..ccfa41a8 100644
--- a/data/skins/tibiaskin.yml
+++ b/data/skins/tibiaskin.yml
@@ -48,8 +48,16 @@ panels:
   
   flatPanel:
     bordered image:
-    
-      
+      left border: [275,0,1,96]
+      right border: [276,0,1,96]
+      top border: [2,210,91,1]
+      bottom border: [2,211,91,1]
+      top left corner: [275,0,1,1]
+      top right corner: [276,0,1,1]
+      bottom left corner: [2,210,1,1]
+      bottom right corner: [276,95,1,1]
+      center: [0, 0, 96, 96]
+  
 labels:
   default:
     font: tibia-10px-antialised
@@ -96,4 +104,8 @@ text edits:
       bottom right corner: [319,107,1,1]
       center: [309,97,10,10]
   
+line decorations:
+  default:
+    bordered image:
+      top border: [2,210,96,2]
     
\ No newline at end of file
diff --git a/data/ui/infoWindow.yml b/data/ui/infoWindow.yml
index 960322d6..a492ab78 100644
--- a/data/ui/infoWindow.yml
+++ b/data/ui/infoWindow.yml
@@ -10,20 +10,20 @@ window#infoWindow:
     anchors.left: parent.left
     anchors.top: parent.top
     margin.top: 32
-    margin.left: 24
+    margin.left: 18
     
     label#infoLabel:
-      size: [218, 83]
+      size: [208, 84]
       align: center
-      text: |
+      text: |-
             OTClient
             Version 0.2.0
-            Copyright (C) 2011
-            Developed by edubart
+            Created by edubart
+      anchors.left: parent.left
+      anchors.top: parent.top
             
-    separator#bottomSeparator:
-      orientation: horizontal
-      width: 190
+    lineDecoration#bottomSeparator:
+      size: [190,2]
       anchors.left: parent.left
       anchors.top: parent.top
       margin.top: 83
@@ -32,20 +32,19 @@ window#infoWindow:
     label#websiteLabel:
       text: Official Website
       anchors.left: parent.left
-      anchors.top: parent.top
-      margin.top: 105
-      margin.left: 8
+      anchors.bottom: parent.bottom
+      margin.bottom: 14
+      margin.left: 9
       
     button#websiteButton:
-      text: github.com/otclient
-      anchors.left: parent.left
-      anchors.top: parent.top
-      margin.top: 99
-      margin.left: 131
+      text: Github Page
+      anchors.right: parent.right
+      anchors.bottom: parent.bottom
+      margin.bottom: 9
+      margin.right: 9
   
-  separator#bottomSeparator:
-    orientation: horizontal
-    width: 218
+  lineDecoration#bottomSeparator:
+    size: [218,2]
     anchors.left: parent.left
     anchors.top: parent.top
     margin.top: 181
diff --git a/src/framework/graphics/borderedimage.cpp b/src/framework/graphics/borderedimage.cpp
index 225ef356..95bcd6e2 100644
--- a/src/framework/graphics/borderedimage.cpp
+++ b/src/framework/graphics/borderedimage.cpp
@@ -80,18 +80,16 @@ void BorderedImage::setTexCoords(const Rect& left,
 
 void BorderedImage::draw(const Rect& screenCoords)
 {
-    // check minumim size
-    if(screenCoords.size() <= m_cornersSize)
-        return;
-
     Rect rectCoords;
     Size centerSize = screenCoords.size() - m_cornersSize;
 
     // first the center
-    rectCoords = Rect(screenCoords.left() + m_leftBorderTexCoords.width(),
-                      screenCoords.top() + m_topBorderTexCoords.height(),
-                      centerSize);
-    g_graphics.drawRepeatedTexturedRect(rectCoords, m_texture, m_centerTexCoords);
+    if(centerSize.area() > 0) {
+        rectCoords = Rect(screenCoords.left() + m_leftBorderTexCoords.width(),
+                        screenCoords.top() + m_topBorderTexCoords.height(),
+                        centerSize);
+        g_graphics.drawRepeatedTexturedRect(rectCoords, m_texture, m_centerTexCoords);
+    }
 
     // top left corner
     rectCoords = Rect(screenCoords.topLeft(),
diff --git a/src/framework/graphics/font.cpp b/src/framework/graphics/font.cpp
index baa32415..ada2122e 100644
--- a/src/framework/graphics/font.cpp
+++ b/src/framework/graphics/font.cpp
@@ -223,7 +223,7 @@ const std::vector<Point>& Font::calculateGlyphsPositions(const std::string& text
         return glyphsPositions;
     }
 
-    // resize glyphsPositions vector, if needed
+    // resize glyphsPositions vector when needed
     if(textLength > (int)glyphsPositions.size())
         glyphsPositions.resize(textLength);
 
@@ -250,9 +250,6 @@ const std::vector<Point>& Font::calculateGlyphsPositions(const std::string& text
     for(i = 0; i < textLength; ++i) {
         glyph = (uchar)text[i];
 
-        // store current glyph topLeft
-        glyphsPositions[i] = virtualPos;
-
         // new line or first glyph
         if(glyph == (uchar)'\n' || i == 0) {
             if(glyph == (uchar)'\n') {
@@ -270,6 +267,9 @@ const std::vector<Point>& Font::calculateGlyphsPositions(const std::string& text
             }
         }
 
+        // store current glyph topLeft
+        glyphsPositions[i] = virtualPos;
+
         // render only if the glyph is valid
         if(glyph >= 32 && glyph != (uchar)'\n') {
             virtualPos.x += m_glyphsSize[glyph].width() + m_glyphSpacing.width();
@@ -278,7 +278,7 @@ const std::vector<Point>& Font::calculateGlyphsPositions(const std::string& text
 
     if(textBoxSize) {
         textBoxSize->setWidth(maxLineWidth);
-        textBoxSize->setHeight(virtualPos.y + m_glyphHeight);
+        textBoxSize->setHeight(virtualPos.y + m_glyphHeight + m_glyphSpacing.height());
     }
 
     return glyphsPositions;
diff --git a/src/framework/graphics/graphics.cpp b/src/framework/graphics/graphics.cpp
index 2cd05681..bfafd079 100644
--- a/src/framework/graphics/graphics.cpp
+++ b/src/framework/graphics/graphics.cpp
@@ -139,7 +139,7 @@ void Graphics::disableDrawing()
 
 void Graphics::drawTexturedRect(const Rect& screenCoords, const TexturePtr& texture, const Rect& textureCoords, const Color& color)
 {
-    if(screenCoords.isEmpty())
+    if(screenCoords.isEmpty() || textureCoords.isEmpty())
         return;
 
     // rect correction for opengl
@@ -170,7 +170,7 @@ void Graphics::drawTexturedRect(const Rect& screenCoords, const TexturePtr& text
 
 void Graphics::drawRepeatedTexturedRect(const Rect& screenCoords, const TexturePtr& texture, const Rect& textureCoords, const Color& color)
 {
-    if(screenCoords.isEmpty())
+    if(screenCoords.isEmpty() || textureCoords.isEmpty())
         return;
 
     // render many repeated texture rects
diff --git a/src/framework/graphics/textarea.cpp b/src/framework/graphics/textarea.cpp
index 192861fa..5d984dc3 100644
--- a/src/framework/graphics/textarea.cpp
+++ b/src/framework/graphics/textarea.cpp
@@ -293,7 +293,7 @@ void TextArea::appendCharacter(char c)
 
 void TextArea::removeCharacter(bool right)
 {
-    if(m_cursorPos >= 0) {
+    if(m_cursorPos >= 0 && m_text.length() > 0) {
         if(right && (uint)m_cursorPos < m_text.length())
             m_text.erase(m_text.begin() + m_cursorPos);
         else if((uint)m_cursorPos == m_text.length()) {
diff --git a/src/framework/ui/ui.h b/src/framework/ui/ui.h
index fad828b6..a161ddc1 100644
--- a/src/framework/ui/ui.h
+++ b/src/framework/ui/ui.h
@@ -37,5 +37,7 @@
 #include "uiwindow.h"
 #include "uitextedit.h"
 #include "uiloader.h"
+#include "uilinedecoration.h"
+#include "uicheckbox.h"
 
 #endif // UI_H
diff --git a/src/framework/ui/uiconstants.h b/src/framework/ui/uiconstants.h
index 66d34923..7c596d96 100644
--- a/src/framework/ui/uiconstants.h
+++ b/src/framework/ui/uiconstants.h
@@ -60,7 +60,8 @@ namespace UI {
         Label,
         TextEdit,
         Button,
-        CheckBox
+        CheckBox,
+        LineDecoration
     };
 }
 
diff --git a/src/framework/ui/uielement.cpp b/src/framework/ui/uielement.cpp
index 4338e380..65b2e39a 100644
--- a/src/framework/ui/uielement.cpp
+++ b/src/framework/ui/uielement.cpp
@@ -49,19 +49,11 @@ void UIElement::destroy()
     assert(asUIElement().use_count() == 4);
 }
 
-bool UIElement::setSkin(const std::string& skinName)
-{
-    setSkin(g_uiSkins.getElementSkin(m_type, skinName));
-    return m_skin != NULL;
-}
-
 void UIElement::setSkin(UIElementSkin* skin)
 {
     m_skin = skin;
-    if(skin && !getRect().isValid()) {
-        setSize(skin->getDefaultSize());
+    if(skin)
         skin->apply(this);
-    }
 }
 
 void UIElement::render()
diff --git a/src/framework/ui/uielement.h b/src/framework/ui/uielement.h
index 23d3c0f7..516271dd 100644
--- a/src/framework/ui/uielement.h
+++ b/src/framework/ui/uielement.h
@@ -60,7 +60,6 @@ public:
 
     void moveTo(Point pos);
 
-    bool setSkin(const std::string& skinName);
     void setSkin(UIElementSkin *skin);
     UIElementSkin *getSkin() { return m_skin; }
 
diff --git a/src/framework/ui/uielementskin.cpp b/src/framework/ui/uielementskin.cpp
index cbd50f31..66c55a34 100644
--- a/src/framework/ui/uielementskin.cpp
+++ b/src/framework/ui/uielementskin.cpp
@@ -28,12 +28,6 @@
 #include "graphics/textures.h"
 #include "uiskins.h"
 
-void UIElementSkin::draw(UIElement *element)
-{
-    if(m_defaultImage)
-        m_defaultImage->draw(element->getRect());
-}
-
 void UIElementSkin::load(const YAML::Node& node)
 {
     if(node.FindValue("default size"))
@@ -41,6 +35,17 @@ void UIElementSkin::load(const YAML::Node& node)
     m_defaultImage = loadImage(node);
 }
 
+void UIElementSkin::apply(UIElement* element)
+{
+    if(!element->getRect().isValid() && m_defaultSize.isValid())
+        element->setSize(m_defaultSize);
+}
+
+void UIElementSkin::draw(UIElement *element)
+{
+    if(m_defaultImage)
+        m_defaultImage->draw(element->getRect());
+}
 ImagePtr UIElementSkin::loadImage(const YAML::Node& node)
 {
     ImagePtr image;
diff --git a/src/framework/ui/uielementskin.h b/src/framework/ui/uielementskin.h
index 42787ca2..1078e437 100644
--- a/src/framework/ui/uielementskin.h
+++ b/src/framework/ui/uielementskin.h
@@ -40,7 +40,7 @@ public:
     virtual ~UIElementSkin() { }
 
     virtual void load(const YAML::Node& node);
-    virtual void apply(UIElement *element) { }
+    virtual void apply(UIElement *element);
     virtual void draw(UIElement *element);
 
     const std::string& getName() const { return m_name; }
diff --git a/src/framework/ui/uilabel.cpp b/src/framework/ui/uilabel.cpp
index d9fb6083..123124ee 100644
--- a/src/framework/ui/uilabel.cpp
+++ b/src/framework/ui/uilabel.cpp
@@ -23,13 +23,3 @@
 
 
 #include "uilabel.h"
-#include "graphics/fonts.h"
-#include "uilabelskin.h"
-
-void UILabel::setText(const std::string& text)
-{
-    UILabelSkin *skin = static_cast<UILabelSkin*>(getSkin());
-    setSize(skin->getFont()->calculateTextRectSize(text));
-    m_text = text;
-}
-
diff --git a/src/framework/ui/uilabel.h b/src/framework/ui/uilabel.h
index 380e0b05..29358d21 100644
--- a/src/framework/ui/uilabel.h
+++ b/src/framework/ui/uilabel.h
@@ -27,18 +27,26 @@
 
 #include "prerequisites.h"
 #include "uielement.h"
+#include "graphics/font.h"
 
 class UILabel : public UIElement
 {
 public:
     UILabel() :
-        UIElement(UI::Label) { }
+        UIElement(UI::Label),
+        m_align(ALIGN_TOP_LEFT),
+        m_color(Color::white) { }
 
-    void setText(const std::string& text);
+    void setText(const std::string& text) { m_text = text; }
     const std::string& getText() const { return m_text; }
 
+    void setAlign(int align) { m_align = align; }
+    int getAlign() const { return m_align; }
+
 private:
     std::string m_text;
+    int m_align;
+    Color m_color;
 };
 
 typedef boost::shared_ptr<UILabel> UILabelPtr;
diff --git a/src/framework/ui/uilabelskin.cpp b/src/framework/ui/uilabelskin.cpp
index b8dc291d..4dfcd93d 100644
--- a/src/framework/ui/uilabelskin.cpp
+++ b/src/framework/ui/uilabelskin.cpp
@@ -41,11 +41,16 @@ void UILabelSkin::load(const YAML::Node& node)
         m_textColor = Color::white;
 }
 
+void UILabelSkin::apply(UIElement* element)
+{
+    UIElementSkin::apply(element);
+    UILabel *label = static_cast<UILabel*>(element);
+    label->setSize(m_font->calculateTextRectSize(label->getText()));
+}
+
 void UILabelSkin::draw(UIElement *element)
 {
     UIElementSkin::draw(element);
-
     UILabel *label = static_cast<UILabel*>(element);
-
-    m_font->renderText(label->getText(), label->getRect(), ALIGN_TOP_LEFT, m_textColor);
+    m_font->renderText(label->getText(), label->getRect(), label->getAlign(), m_textColor);
 }
diff --git a/src/framework/ui/uilabelskin.h b/src/framework/ui/uilabelskin.h
index 94041c59..8ec9af97 100644
--- a/src/framework/ui/uilabelskin.h
+++ b/src/framework/ui/uilabelskin.h
@@ -26,24 +26,25 @@
 #define UILABELSKIN_H
 
 #include "prerequisites.h"
-#include "uiconstants.h"
 #include "uielementskin.h"
-
-class Font;
+#include "graphics/font.h"
 
 class UILabelSkin : public UIElementSkin
 {
 public:
     UILabelSkin(const std::string& name) :
-        UIElementSkin(name, UI::Label) { }
+        UIElementSkin(name, UI::Label),
+        m_align(ALIGN_TOP_LEFT) { }
 
     void load(const YAML::Node& node);
+    void apply(UIElement *element);
     void draw(UIElement *element);
 
     Font *getFont() const { return m_font; }
 
 private:
     Font *m_font;
+    int m_align;
     Color m_textColor;
 };
 
diff --git a/src/framework/ui/uilinedecoration.cpp b/src/framework/ui/uilinedecoration.cpp
index 5082632e..cdb2a112 100644
--- a/src/framework/ui/uilinedecoration.cpp
+++ b/src/framework/ui/uilinedecoration.cpp
@@ -1,2 +1,26 @@
+/* The MIT License
+ *
+ * Copyright (c) 2010 OTClient, https://github.com/edubart/otclient
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+
 #include "uilinedecoration.h"
 
diff --git a/src/framework/ui/uilinedecoration.h b/src/framework/ui/uilinedecoration.h
index 4f6f64ab..389ff181 100644
--- a/src/framework/ui/uilinedecoration.h
+++ b/src/framework/ui/uilinedecoration.h
@@ -1,8 +1,40 @@
+/* The MIT License
+ *
+ * Copyright (c) 2010 OTClient, https://github.com/edubart/otclient
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+
 #ifndef UILINEDECORATION_H
 #define UILINEDECORATION_H
 
-class UILineDecoration
+#include "prerequisites.h"
+#include "uielement.h"
+
+class UILineDecoration : public UIElement
 {
+public:
+    UILineDecoration() :
+        UIElement(UI::LineDecoration) { }
 };
 
+typedef boost::shared_ptr<UILineDecoration> UILineDecorationPtr;
+
 #endif // UILINEDECORATION_H
diff --git a/src/framework/ui/uilinedecorationskin.cpp b/src/framework/ui/uilinedecorationskin.cpp
index 04748efb..ee7ab729 100644
--- a/src/framework/ui/uilinedecorationskin.cpp
+++ b/src/framework/ui/uilinedecorationskin.cpp
@@ -1,2 +1,30 @@
+/* The MIT License
+ *
+ * Copyright (c) 2010 OTClient, https://github.com/edubart/otclient
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+
 #include "uilinedecorationskin.h"
 
+void UILineDecorationSkin::draw(UIElement* element)
+{
+    UIElementSkin::draw(element);
+}
diff --git a/src/framework/ui/uilinedecorationskin.h b/src/framework/ui/uilinedecorationskin.h
index 21ea5510..fa009160 100644
--- a/src/framework/ui/uilinedecorationskin.h
+++ b/src/framework/ui/uilinedecorationskin.h
@@ -1,8 +1,40 @@
+/* The MIT License
+ *
+ * Copyright (c) 2010 OTClient, https://github.com/edubart/otclient
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+
 #ifndef UILINEDECORATIONSKIN_H
 #define UILINEDECORATIONSKIN_H
 
-class UILineDecorationSkin
+#include "prerequisites.h"
+#include "uielementskin.h"
+
+class UILineDecorationSkin : public UIElementSkin
 {
+public:
+    UILineDecorationSkin(const std::string& name) :
+        UIElementSkin(name, UI::LineDecoration) { }
+
+    void draw(UIElement *element);
 };
 
 #endif // UILINEDECORATIONSKIN_H
diff --git a/src/framework/ui/uiloader.cpp b/src/framework/ui/uiloader.cpp
index 033c3d7b..da3fc4ea 100644
--- a/src/framework/ui/uiloader.cpp
+++ b/src/framework/ui/uiloader.cpp
@@ -48,13 +48,14 @@ UIElementPtr UILoader::createElementFromId(const std::string& id)
         element = UIElementPtr(new UIWindow);
     } else if(elementType == "textEdit") {
         element = UIElementPtr(new UITextEdit);
+    } else if(elementType == "lineDecoration") {
+        element = UIElementPtr(new UILineDecoration);
+    } else if(elementType == "checkBox") {
+        element = UIElementPtr(new UICheckBox);
     }
 
     if(element) {
         element->setId(elementId);
-
-        // apply default skin
-        element->setSkin(g_uiSkins.getElementSkin(element->getElementType()));
     }
 
     return element;
@@ -146,9 +147,33 @@ void UILoader::loadElements(const UIElementPtr& parent, const YAML::Node& node)
 
 void UILoader::loadElement(const UIElementPtr& element, const YAML::Node& node)
 {
+    // load specific element type
+    if(element->getElementType() == UI::Button) {
+        UIButtonPtr button = boost::static_pointer_cast<UIButton>(element);
+        button->setText(node["text"].Read<std::string>());
+    }
+    else if(element->getElementType() == UI::Window) {
+        UIWindowPtr window = boost::static_pointer_cast<UIWindow>(element);
+        window->setTitle(node["title"].Read<std::string>());
+    }
+    else if(element->getElementType() == UI::Label) {
+        UILabelPtr label = boost::static_pointer_cast<UILabel>(element);
+        label->setText(node["text"].Read<std::string>());
+        if(node.FindValue("align")) {
+            std::string alignDesc;
+            node["align"] >> alignDesc;
+            if(alignDesc == "center")
+                label->setAlign(ALIGN_CENTER);
+        }
+    }
+
+    // set element skin
     if(node.FindValue("skin"))
         element->setSkin(g_uiSkins.getElementSkin(element->getElementType(), node["skin"]));
+    else // apply default skin
+        element->setSkin(g_uiSkins.getElementSkin(element->getElementType(), "default"));
 
+    // load elements common proprieties
     if(node.FindValue("size")) {
         Size size;
         node["size"] >> size;
@@ -193,20 +218,6 @@ void UILoader::loadElement(const UIElementPtr& element, const YAML::Node& node)
 
     if(node.FindValue("anchors.verticalCenter"))
         loadElementAnchor(element, ANCHOR_VERTICAL_CENTER, node["anchors.verticalCenter"]);
-
-    // load specific element type
-    if(element->getElementType() == UI::Button) {
-        UIButtonPtr button = boost::static_pointer_cast<UIButton>(element);
-        button->setText(node["text"].Read<std::string>());
-    }
-    else if(element->getElementType() == UI::Window) {
-        UIWindowPtr window = boost::static_pointer_cast<UIWindow>(element);
-        window->setTitle(node["title"].Read<std::string>());
-    }
-    else if(element->getElementType() == UI::Label) {
-        UILabelPtr label = boost::static_pointer_cast<UILabel>(element);
-        label->setText(node["text"].Read<std::string>());
-    }
 }
 
 void UILoader::loadElementAnchor(const UIElementPtr& element, EAnchorType type, const YAML::Node& node)
diff --git a/src/framework/ui/uiskins.cpp b/src/framework/ui/uiskins.cpp
index 72e2ce4b..b5cd0e34 100644
--- a/src/framework/ui/uiskins.cpp
+++ b/src/framework/ui/uiskins.cpp
@@ -30,6 +30,7 @@
 #include "uiwindowskin.h"
 #include "uitexteditskin.h"
 #include "uilabelskin.h"
+#include "uilinedecorationskin.h"
 
 UISkins g_uiSkins;
 
@@ -111,6 +112,19 @@ void UISkins::load(const std::string& skinsFile)
                 m_elementSkins.push_back(skin);
             }
         }
+
+
+        {
+            const YAML::Node& node = doc["line decorations"];
+            for(auto it = node.begin(); it != node.end(); ++it) {
+                std::string name;
+                it.first() >> name;
+
+                UIElementSkin *skin = new UILineDecorationSkin(name);
+                skin->load(it.second());
+                m_elementSkins.push_back(skin);
+            }
+        }
     } catch (YAML::Exception& e) {
         logFatal("Malformed skin file \"%s\":\n  %s", skinsFile.c_str(), e.what());
     }
diff --git a/src/framework/ui/uitexteditskin.cpp b/src/framework/ui/uitexteditskin.cpp
index b0b22bf6..9da33b4f 100644
--- a/src/framework/ui/uitexteditskin.cpp
+++ b/src/framework/ui/uitexteditskin.cpp
@@ -48,6 +48,7 @@ void UITextEditSkin::load(const YAML::Node& node)
 
 void UITextEditSkin::apply(UIElement* element)
 {
+    UIElementSkin::apply(element);
     UITextEdit *textEdit = static_cast<UITextEdit*>(element);
     textEdit->getTextArea().setFont(m_font);
 }
diff --git a/src/menustate.cpp b/src/menustate.cpp
index 08f6c582..c7daf5c9 100644
--- a/src/menustate.cpp
+++ b/src/menustate.cpp
@@ -46,6 +46,9 @@ void MenuState::onEnter()
 
     button = boost::static_pointer_cast<UIButton>(mainMenuPanel->getChildById("enterGameButton"));
     button->setOnClick(boost::bind(&MenuState::enterGameButton_clicked, this));
+
+    button = boost::static_pointer_cast<UIButton>(mainMenuPanel->getChildById("infoButton"));
+    button->setOnClick(boost::bind(&MenuState::infoButton_clicked, this));
 }
 
 void MenuState::onLeave()
@@ -86,13 +89,25 @@ void MenuState::render()
 void MenuState::enterGameButton_clicked()
 {
     UIWindowPtr window = boost::static_pointer_cast<UIWindow>(UILoader::loadFile("ui/enterGameWindow.yml"));
-    UIContainerPtr windowParent = window->getParent();
-    windowParent->lockElement(window);
+    window->getParent()->lockElement(window);
 
     UIButtonPtr button = boost::static_pointer_cast<UIButton>(window->getChildById("cancelButton"));
     button->setOnClick([] {
         UIWindowPtr window = boost::static_pointer_cast<UIWindow>(UIContainer::getRootContainer()->getChildById("enterGameWindow"));
-        UIContainer::getRootContainer()->unlockElement();
+        window->getParent()->unlockElement();
         window->destroy();
     });
 }
+
+void MenuState::infoButton_clicked()
+{
+    UIWindowPtr window = boost::static_pointer_cast<UIWindow>(UILoader::loadFile("ui/infoWindow.yml"));
+    window->getParent()->lockElement(window);
+    UIButtonPtr button = boost::static_pointer_cast<UIButton>(window->getChildById("okButton"));
+    button->setOnClick([] {
+        UIWindowPtr window = boost::static_pointer_cast<UIWindow>(UIContainer::getRootContainer()->getChildById("infoWindow"));
+        window->getParent()->unlockElement();
+        window->destroy();
+    });
+}
+
diff --git a/src/menustate.h b/src/menustate.h
index 1f3c35f8..b8813f39 100644
--- a/src/menustate.h
+++ b/src/menustate.h
@@ -47,6 +47,7 @@ public:
 
 private:
     void enterGameButton_clicked();
+    void infoButton_clicked();
 
     UIPanelPtr m_menuPanel;
     TexturePtr m_background;