diff --git a/data/gui/screens/user_screen_tab.stkgui b/data/gui/screens/user_screen_tab.stkgui
index 75f7fd68b..878461b7d 100644
--- a/data/gui/screens/user_screen_tab.stkgui
+++ b/data/gui/screens/user_screen_tab.stkgui
@@ -7,7 +7,7 @@
-
+
-
+
diff --git a/data/skins/coal/glasstab.png b/data/skins/coal/glasstab.png
index 6f2f0e111..7900daba3 100644
Binary files a/data/skins/coal/glasstab.png and b/data/skins/coal/glasstab.png differ
diff --git a/data/skins/coal/glasstab_down.png b/data/skins/coal/glasstab_down.png
deleted file mode 100644
index be3eedbc4..000000000
Binary files a/data/skins/coal/glasstab_down.png and /dev/null differ
diff --git a/data/skins/coal/glasstab_focus.png b/data/skins/coal/glasstab_focus.png
index 6b6708c14..6cc679192 100644
Binary files a/data/skins/coal/glasstab_focus.png and b/data/skins/coal/glasstab_focus.png differ
diff --git a/data/skins/coal/glasstab_vert.png b/data/skins/coal/glasstab_vert.png
index b8abb0214..dc68c3586 100644
Binary files a/data/skins/coal/glasstab_vert.png and b/data/skins/coal/glasstab_vert.png differ
diff --git a/data/skins/coal/glasstab_vert_down.png b/data/skins/coal/glasstab_vert_down.png
deleted file mode 100644
index 641212f42..000000000
Binary files a/data/skins/coal/glasstab_vert_down.png and /dev/null differ
diff --git a/data/skins/coal/glasstab_vert_focus.png b/data/skins/coal/glasstab_vert_focus.png
index dc54862b6..b82d350fa 100644
Binary files a/data/skins/coal/glasstab_vert_focus.png and b/data/skins/coal/glasstab_vert_focus.png differ
diff --git a/data/skins/coal/stkskin.xml b/data/skins/coal/stkskin.xml
index 78e111290..93555b69c 100644
--- a/data/skins/coal/stkskin.xml
+++ b/data/skins/coal/stkskin.xml
@@ -118,29 +118,35 @@ when the border that intersect at this corner are enabled.
+ left_border="11" right_border="11" top_border="6" bottom_border="10"
+ preserve_h_aspect_ratios="false" hborder_out_portion="0.0" vborder_out_portion="0.0"
+ h_inner_padding="0" v_inner_padding="0" h_margin="0" v_margin="0" />
+ left_border="11" right_border="11" top_border="6" bottom_border="10"
+ preserve_h_aspect_ratios="false" hborder_out_portion="0.0" vborder_out_portion="0.0"
+ h_inner_padding="0" v_inner_padding="0" h_margin="0" v_margin="0" />
-
+
+ left_border="10" right_border="10" top_border="10" bottom_border="10"
+ preserve_h_aspect_ratios="false" hborder_out_portion="0.0" vborder_out_portion="0.0"
+ h_inner_padding="0" v_inner_padding="0" h_margin="0" v_margin="0" />
+ left_border="10" right_border="10" top_border="10" bottom_border="10"
+ preserve_h_aspect_ratios="false" hborder_out_portion="0.0" vborder_out_portion="0.0"
+ h_inner_padding="0" v_inner_padding="0" h_margin="0" v_margin="0" />
-
+
+ left_border="11" right_border="11" top_border="6" bottom_border="10"
+ preserve_h_aspect_ratios="false" hborder_out_portion="0.0" vborder_out_portion="0.0"
+ h_inner_padding="0" v_inner_padding="0" h_margin="0" v_margin="0" />
+ left_border="11" right_border="11" top_border="6" bottom_border="10"
+ preserve_h_aspect_ratios="false" hborder_out_portion="0.0" vborder_out_portion="0.0"
+ h_inner_padding="0" v_inner_padding="0" h_margin="0" v_margin="0" />
-
+
+ left_border="10" right_border="10" top_border="10" bottom_border="10"
+ preserve_h_aspect_ratios="false" hborder_out_portion="0.0" vborder_out_portion="0.0"
+ h_inner_padding="0" v_inner_padding="0" h_margin="0" v_margin="0" />
+ left_border="10" right_border="10" top_border="10" bottom_border="10"
+ preserve_h_aspect_ratios="false" hborder_out_portion="0.0" vborder_out_portion="0.0"
+ h_inner_padding="0" v_inner_padding="0" h_margin="0" v_margin="0" />
-
+
+ left_border="11" right_border="11" top_border="6" bottom_border="10"
+ preserve_h_aspect_ratios="false" hborder_out_portion="0.0" vborder_out_portion="0.0"
+ h_inner_padding="0" v_inner_padding="0" h_margin="0" v_margin="0" />
+ left_border="11" right_border="11" top_border="6" bottom_border="10"
+ preserve_h_aspect_ratios="false" hborder_out_portion="0.0" vborder_out_portion="0.0"
+ h_inner_padding="0" v_inner_padding="0" h_margin="0" v_margin="0" />
-
+
+ left_border="10" right_border="10" top_border="10" bottom_border="10"
+ preserve_h_aspect_ratios="false" hborder_out_portion="0.0" vborder_out_portion="0.0"
+ h_inner_padding="0" v_inner_padding="0" h_margin="0" v_margin="0" />
+ left_border="10" right_border="10" top_border="10" bottom_border="10"
+ preserve_h_aspect_ratios="false" hborder_out_portion="0.0" vborder_out_portion="0.0"
+ h_inner_padding="0" v_inner_padding="0" h_margin="0" v_margin="0" />
-
+
+ left_border="11" right_border="11" top_border="6" bottom_border="10"
+ preserve_h_aspect_ratios="false" hborder_out_portion="0.0" vborder_out_portion="0.0"
+ h_inner_padding="0" v_inner_padding="0" h_margin="0" v_margin="0" />
+ left_border="11" right_border="11" top_border="6" bottom_border="10"
+ preserve_h_aspect_ratios="false" hborder_out_portion="0.0" vborder_out_portion="0.0"
+ h_inner_padding="0" v_inner_padding="0" h_margin="0" v_margin="0" />
+ left_border="11" right_border="11" top_border="6" bottom_border="10"
+ preserve_h_aspect_ratios="false" hborder_out_portion="0.0" vborder_out_portion="0.0"
+ h_inner_padding="0" v_inner_padding="0" h_margin="0" v_margin="0" />
+ left_border="10" right_border="10" top_border="10" bottom_border="10"
+ preserve_h_aspect_ratios="false" hborder_out_portion="0.0" vborder_out_portion="0.0"
+ h_inner_padding="0" v_inner_padding="0" h_margin="0" v_margin="0" />
+ left_border="10" right_border="10" top_border="10" bottom_border="10"
+ preserve_h_aspect_ratios="false" hborder_out_portion="0.0" vborder_out_portion="0.0"
+ h_inner_padding="0" v_inner_padding="0" h_margin="0" v_margin="0" />
+ left_border="10" right_border="10" top_border="10" bottom_border="10"
+ preserve_h_aspect_ratios="false" hborder_out_portion="0.0" vborder_out_portion="0.0"
+ h_inner_padding="0" v_inner_padding="0" h_margin="0" v_margin="0" />
+ left_border="11" right_border="11" top_border="6" bottom_border="10"
+ preserve_h_aspect_ratios="false" hborder_out_portion="0.0" vborder_out_portion="0.0"
+ h_inner_padding="0" v_inner_padding="0" h_margin="0" v_margin="0" />
+ left_border="11" right_border="11" top_border="6" bottom_border="10"
+ preserve_h_aspect_ratios="false" hborder_out_portion="0.0" vborder_out_portion="0.0"
+ h_inner_padding="0" v_inner_padding="0" h_margin="0" v_margin="0" />
+ left_border="11" right_border="11" top_border="6" bottom_border="10"
+ preserve_h_aspect_ratios="false" hborder_out_portion="0.0" vborder_out_portion="0.0"
+ h_inner_padding="0" v_inner_padding="0" h_margin="0" v_margin="0" />
+ left_border="10" right_border="10" top_border="10" bottom_border="10"
+ preserve_h_aspect_ratios="false" hborder_out_portion="0.0" vborder_out_portion="0.0"
+ h_inner_padding="0" v_inner_padding="0" h_margin="0" v_margin="0" />
+ left_border="10" right_border="10" top_border="10" bottom_border="10"
+ preserve_h_aspect_ratios="false" hborder_out_portion="0.0" vborder_out_portion="0.0"
+ h_inner_padding="0" v_inner_padding="0" h_margin="0" v_margin="0" />
+ left_border="10" right_border="10" top_border="10" bottom_border="10"
+ preserve_h_aspect_ratios="false" hborder_out_portion="0.0" vborder_out_portion="0.0"
+ h_inner_padding="0" v_inner_padding="0" h_margin="0" v_margin="0" />
-1) self->m_absolute_h = texture_h;
else if (label_h > -1) self->m_absolute_h = label_h;
}
+
+ if (self->getType() != WTYPE_RIBBON) // Ribbons have their own handling
+ {
+ // Set vertical inner padding
+ self->m_absolute_h += self->m_absolute_h * SkinConfig::getVerticalInnerPadding(self->getType(), self);
+// self->m_relative_h += self->m_relative_h * SkinConfig::getVerticalInnerPadding(self->getType(), self);
+
+ // Set horizontal inner padding
+ self->m_absolute_w += self->m_absolute_w * SkinConfig::getHorizontalInnerPadding(self->getType(), self);
+// self->m_relative_w += self->m_relative_w * SkinConfig::getHorizontalInnerPadding(self->getType(), self);
+ }
+
}
// ----------------------------------------------------------------------------
diff --git a/src/guiengine/screen_keyboard.cpp b/src/guiengine/screen_keyboard.cpp
index 573de2028..8acc79492 100644
--- a/src/guiengine/screen_keyboard.cpp
+++ b/src/guiengine/screen_keyboard.cpp
@@ -197,8 +197,6 @@ void ScreenKeyboard::createButtons()
const int margin = 2;
int height = (m_area.getHeight() - 2 * pos_y) / rows_num - margin;
- char height_str[100];
- sprintf(height_str, "%i", height);
for (int i = 0; i < rows_num; i++)
{
@@ -225,17 +223,21 @@ void ScreenKeyboard::createButtons()
for (int j = 0; j < cols_num; j++)
{
+ ButtonWidget* button = new ButtonWidget();
+
float width = (float)total_width * layout_proportions[i][j]
/ total_proportions - margin;
char width_str[100];
- sprintf(width_str, "%i", (int)roundf(width));
+ sprintf(width_str, "%i", (int)roundf(width / (SkinConfig::getHorizontalInnerPadding(button->getType(), button)+1.0f)));
+
+ char height_str[100];
+ sprintf(height_str, "%i", (int)roundf(height / (SkinConfig::getVerticalInnerPadding(button->getType(), button)+1.0f)));
char tmp[100];
sprintf(tmp, "%i", (int)roundf(pos_x));
std::string pos_x_str = tmp;
- ButtonWidget* button = new ButtonWidget();
button->setParent(m_irrlicht_window);
button->m_properties[PROP_WIDTH] = width_str;
button->m_properties[PROP_HEIGHT] = height_str;
diff --git a/src/guiengine/skin.cpp b/src/guiengine/skin.cpp
index 8cd0be146..99ce65c97 100644
--- a/src/guiengine/skin.cpp
+++ b/src/guiengine/skin.cpp
@@ -68,6 +68,8 @@ namespace SkinConfig
bool common_img = false;
int leftborder = 0, rightborder=0, topborder=0, bottomborder=0;
float hborder_out_portion = 0.5f, vborder_out_portion = 1.0f;
+ float horizontal_inner_padding = 0.0f, vertical_inner_padding = 0.0f;
+ float horizontal_margin = 0.0f, vertical_margin = 0.0f;
bool preserve_h_aspect_ratios = false;
std::string areas;
@@ -92,6 +94,12 @@ namespace SkinConfig
node->get("hborder_out_portion", &hborder_out_portion);
node->get("vborder_out_portion", &vborder_out_portion);
+ node->get("h_inner_padding", &horizontal_inner_padding);
+ node->get("v_inner_padding", &vertical_inner_padding);
+
+ node->get("h_margin", &horizontal_margin);
+ node->get("v_margin", &vertical_margin);
+
node->get("preserve_h_aspect_ratios", &preserve_h_aspect_ratios);
node->get("areas", &areas);
@@ -104,6 +112,10 @@ namespace SkinConfig
new_param.m_bottom_border = bottomborder;
new_param.m_hborder_out_portion = hborder_out_portion;
new_param.m_vborder_out_portion = vborder_out_portion;
+ new_param.m_horizontal_inner_padding = horizontal_inner_padding;
+ new_param.m_vertical_inner_padding = vertical_inner_padding;
+ new_param.m_horizontal_margin = horizontal_margin;
+ new_param.m_vertical_margin = vertical_margin;
new_param.m_preserve_h_aspect_ratios = preserve_h_aspect_ratios;
// call last since it calculates coords considering all other
@@ -268,7 +280,113 @@ namespace SkinConfig
delete root;
} // loadFromFile
-}; // SkinConfig
+
+ // ------------------------------------------------------------------------
+ float getVerticalInnerPadding(int wtype, Widget* widget)
+ {
+ if (widget != nullptr)
+ {
+ RibbonWidget* ribbon = (RibbonWidget*)widget;
+ RibbonType rtype = ribbon->getRibbonType();
+
+ return getInnerPadding(wtype, rtype, VERTICAL);
+ }
+ else
+ return getInnerPadding(wtype, 0, VERTICAL);
+ } // getVerticalInnerPadding
+
+ // ------------------------------------------------------------------------
+ float getHorizontalInnerPadding(int wtype, Widget* widget)
+ {
+ if (widget != nullptr)
+ {
+ RibbonWidget* ribbon = (RibbonWidget*)widget;
+ RibbonType rtype = ribbon->getRibbonType();
+
+ return getInnerPadding(wtype, rtype, HORIZONTAL);
+ }
+ else
+ return getInnerPadding(wtype, 0, HORIZONTAL);
+ } // getHorizontalInnerPadding
+
+ // ------------------------------------------------------------------------
+ float getInnerPadding(int wtype, int rtype, int axis)
+ {
+ return getValue(PADDING, wtype, rtype, axis);
+ } // getInnerPadding
+
+ // ------------------------------------------------------------------------
+ float getValue(int value_type, int widget_type, int ribbon_type, int axis)
+ {
+ std::string state = "neutral"; //FIXME: support all states?
+ std::string type = "";
+
+ switch (widget_type)
+ {
+ case WTYPE_SPINNER: type = "spinner"; break;
+ case WTYPE_BUTTON: type = "button"; break;
+ case WTYPE_CHECKBOX: type = "checkbox"; state = "neutral+unchecked"; break;
+ case WTYPE_BUBBLE: type = "textbubble"; break;
+ case WTYPE_LIST: type = "list"; break;
+ case WTYPE_PROGRESS: type = "progress"; break;
+ case WTYPE_RATINGBAR: type = "rating"; break;
+ case WTYPE_RIBBON:
+ if (ribbon_type == RIBBON_VERTICAL_TABS)
+ type = "verticalTab";
+ else if (ribbon_type == RIBBON_TABS)
+ type = "tab";
+ break;
+ default: return 0.0f; // Widget type not supported
+ }
+
+ if (value_type == PADDING)
+ {
+ if (axis == HORIZONTAL)
+ return m_render_params[type+"::"+state].m_horizontal_inner_padding;
+ else if (axis == VERTICAL)
+ return m_render_params[type+"::"+state].m_vertical_inner_padding;
+ else
+ {
+ Log::error("GUI", "Invalid axis type passed to getValue!");
+ return 0.0f;
+ }
+ }
+ else if (value_type == BORDER)
+ {
+ if (axis == LEFT)
+ return m_render_params[type+"::"+state].m_left_border;
+ else if (axis == RIGHT)
+ return m_render_params[type+"::"+state].m_right_border;
+ else if (axis == TOP)
+ return m_render_params[type+"::"+state].m_top_border;
+ else if (axis == BOTTOM)
+ return m_render_params[type+"::"+state].m_bottom_border;
+ else
+ {
+ Log::error("GUI", "Invalid axis type passed to getValue!");
+ return 0.0f;
+ }
+ }
+ else if (value_type == MARGIN)
+ {
+ if (axis == HORIZONTAL)
+ return m_render_params[type+"::"+state].m_horizontal_margin;
+ else if (axis == VERTICAL)
+ return m_render_params[type+"::"+state].m_vertical_margin;
+ else
+ {
+ Log::error("GUI", "Invalid axis type passed to getValue!");
+ return 0.0f;
+ }
+ }
+ else
+ {
+ Log::error("GUI", "Invalid value_type passed to getValue!");
+ return 0.0f;
+ }
+ } // getValue
+
+}; // Namespace SkinConfig
namespace GUIEngine
{
@@ -295,6 +413,11 @@ BoxRenderParams::BoxRenderParams()
m_hborder_out_portion = 0.5;
m_vborder_out_portion = 1.0;
+ m_horizontal_margin = 0.0f;
+ m_vertical_margin = 0.0f;
+ m_horizontal_inner_padding = 0.0f;
+ m_vertical_inner_padding = 0.0f;
+
areas = BODY | LEFT | RIGHT | TOP | BOTTOM;
m_vertical_flip = false;
m_y_flip_set = false;
@@ -499,6 +622,12 @@ void Skin::drawMessage(SkinWidgetContainer* w, const core::recti &dest,
drawBoxFromStretchableTexture(w, dest, SkinConfig::m_render_params[type]);
} // drawMessage
+// ----------------------------------------------------------------------------
+float Skin::getScalingFactor(std::string params, float height)
+{
+ return height / SkinConfig::m_render_params[params].getImage()->getSize().Height;
+} // getScalingFactor
+
// ----------------------------------------------------------------------------
void Skin::drawBoxFromStretchableTexture(SkinWidgetContainer* w,
const core::recti &dest,
diff --git a/src/guiengine/skin.hpp b/src/guiengine/skin.hpp
index 4e2abdb29..b92a00475 100644
--- a/src/guiengine/skin.hpp
+++ b/src/guiengine/skin.hpp
@@ -208,6 +208,8 @@ namespace GUIEngine
int m_left_border, m_right_border, m_top_border, m_bottom_border;
bool m_preserve_h_aspect_ratios;
float m_hborder_out_portion, m_vborder_out_portion;
+ float m_horizontal_inner_padding, m_vertical_inner_padding;
+ float m_horizontal_margin, m_vertical_margin;
// this parameter is a bit special since it's the only one that can
// change at runtime
@@ -221,6 +223,7 @@ namespace GUIEngine
static const int RIGHT = 4;
static const int TOP = 8;
static const int BOTTOM = 16;
+ static const int ALL = BODY+LEFT+RIGHT+TOP+BOTTOM;
core::rect m_source_area_left;
core::rect m_source_area_center;
@@ -433,6 +436,27 @@ namespace GUIEngine
const std::string& getColorEmojiTTF() const;
std::string getThemedIcon(const std::string& relative_path) const;
+
+ float getScalingFactor(std::string params, float height);
}; // Skin
} // guiengine
+
+namespace SkinConfig
+{
+ enum options {
+ MARGIN,
+ BORDER,
+ PADDING,
+ TOP,
+ BOTTOM,
+ LEFT,
+ RIGHT,
+ HORIZONTAL,
+ VERTICAL
+ };
+ float getVerticalInnerPadding(int wtype, GUIEngine::Widget* widget);
+ float getHorizontalInnerPadding(int wtype, GUIEngine::Widget* widget);
+ float getInnerPadding(int wtype, int rtype, int axis);
+ float getValue(int value_type, int widget_type, int ribbon_type, int axis);
+}
#endif
diff --git a/src/guiengine/widgets/ribbon_widget.cpp b/src/guiengine/widgets/ribbon_widget.cpp
index c9aba096a..0ea125d47 100644
--- a/src/guiengine/widgets/ribbon_widget.cpp
+++ b/src/guiengine/widgets/ribbon_widget.cpp
@@ -23,6 +23,7 @@
#include "guiengine/engine.hpp"
#include "guiengine/layout_manager.hpp"
#include "guiengine/scalable_font.hpp"
+#include "guiengine/skin.hpp"
#include "guiengine/widgets/button_widget.hpp"
#include "input/input_manager.hpp"
#include "io/file_manager.hpp"
@@ -160,6 +161,18 @@ void RibbonWidget::add()
// so care must be taken to not break things
for (int i=0; i subsize = rect(widget_x - large_tab/2+2, 0,
- widget_x + large_tab/2-2, m_h);
+ IGUIButton * tab = NULL;
+
+ rect tab_rect_abs;
if (message.size() == 0)
{
- subsize = rect(widget_x - small_tab/2+2, 0,
- widget_x + small_tab/2-2, m_h);
+ tab_rect_abs = rect(widget_x - small_tab/2 + HORZ_MARGIN, VERT_MARGIN,
+ widget_x + small_tab/2 - HORZ_MARGIN, m_h - VERT_MARGIN);
+ }
+ else
+ {
+ tab_rect_abs = rect(widget_x - large_tab/2 + HORZ_MARGIN, VERT_MARGIN,
+ widget_x + large_tab/2 - HORZ_MARGIN, m_h - VERT_MARGIN);
}
- if (m_active_children[i].m_type == WTYPE_BUTTON)
- {
- subbtn = GUIEngine::getGUIEnv()
- ->addButton(subsize, btn, getNewNoFocusID(),
- message.c_str(), L"");
- subbtn->setTabStop(false);
- subbtn->setTabGroup(false);
+ // Once height is available to us, adjust for scaling
+ TOP_BORDER = round( GUIEngine::getSkin()->getScalingFactor("tab::neutral", tab_rect_abs.getHeight()) * (float)TOP_BORDER );
+ BOTTOM_BORDER = round( GUIEngine::getSkin()->getScalingFactor("tab::neutral", tab_rect_abs.getHeight()) * (float)BOTTOM_BORDER );
+ LEFT_BORDER = round( GUIEngine::getSkin()->getScalingFactor("tab::neutral", tab_rect_abs.getHeight()) * (float)LEFT_BORDER );
+ RIGHT_BORDER = round( GUIEngine::getSkin()->getScalingFactor("tab::neutral", tab_rect_abs.getHeight()) * (float)RIGHT_BORDER );
- if ((int)GUIEngine::getFont()->getDimension(message.c_str())
- .Width > subsize.getWidth() &&
- message.findFirst(L' ') == -1 &&
- message.findFirst(L'\u00AD') == -1 )
- {
- // if message too long and contains no space and no soft
- // hyphen, make the font smaller
- subbtn->setOverrideFont(GUIEngine::getSmallFont());
- }
- }
- else if (m_active_children[i].m_type == WTYPE_ICON_BUTTON)
+ HORZ_PADDING = round( GUIEngine::getSkin()->getScalingFactor("tab::neutral", tab_rect_abs.getHeight()) * (float)HORZ_PADDING );
+ VERT_PADDING = round( GUIEngine::getSkin()->getScalingFactor("tab::neutral", tab_rect_abs.getHeight()) * (float)VERT_PADDING );
+
+ // Automatically guess from position on-screen if tabs go up or down
+ RibbonFlip flip = getRibbonFlip();
+ bool vertical_flip = (unsigned int)widget_size.UpperLeftCorner.Y <
+ irr_driver->getActualScreenSize().Height / 2;
+ // Force flip direction when the direction is defined
+ if(flip == FLIP_UP_LEFT)
+ vertical_flip = true;
+ else if(flip == FLIP_DOWN_RIGHT)
+ vertical_flip = false;
+
+ if (vertical_flip)
+ swap(TOP_BORDER, BOTTOM_BORDER);
+
+ // Used to position sub-elements, coords needs to be relative to tab_rect_abs
+ rect tab_contents_rect = rect(LEFT_BORDER + HORZ_PADDING,
+ TOP_BORDER + VERT_PADDING,
+ tab_rect_abs.getWidth() - RIGHT_BORDER - HORZ_PADDING,
+ tab_rect_abs.getHeight() - BOTTOM_BORDER - VERT_PADDING);
+
+ if (m_active_children[i].m_type == WTYPE_ICON_BUTTON || m_active_children[i].m_type == WTYPE_BUTTON)
{
- rect icon_part = rect(15,
- 0,
- subsize.getHeight()+15,
- subsize.getHeight());
+ rect icon_part = rect(tab_contents_rect.UpperLeftCorner.X,
+ tab_contents_rect.UpperLeftCorner.Y,
+ tab_contents_rect.UpperLeftCorner.X + tab_contents_rect.getHeight(),
+ tab_contents_rect.UpperLeftCorner.Y + tab_contents_rect.getHeight());
if (message.size() == 0)
{
- const int x = subsize.getWidth()/2 - subsize.getHeight()/2;
+ const int x = tab_contents_rect.getWidth()/2 - tab_contents_rect.getHeight()/2;
// no label, only icon, so center the icon
- icon_part = rect(x,
- 0,
- x + subsize.getHeight(),
- subsize.getHeight());
+ icon_part = rect(tab_contents_rect.UpperLeftCorner.X + x,
+ tab_contents_rect.UpperLeftCorner.Y,
+ tab_contents_rect.UpperLeftCorner.X + x + tab_contents_rect.getHeight(),
+ tab_contents_rect.UpperLeftCorner.Y + tab_contents_rect.getHeight());
}
+ rect label_part = rect(tab_contents_rect.UpperLeftCorner.X,
+ tab_contents_rect.UpperLeftCorner.Y,
+ tab_contents_rect.LowerRightCorner.X,
+ tab_contents_rect.LowerRightCorner.Y);
+
// label at the *right* of the icon (for tabs)
- rect label_part = rect(subsize.getHeight()+15,
- 0,
- subsize.getWidth()-15,
- subsize.getHeight());
+ if (m_active_children[i].m_type == WTYPE_ICON_BUTTON)
+ label_part.UpperLeftCorner.X += icon_part.getWidth() + 15;
// use the same ID for all subcomponents; since event handling
// is done per-ID, no matter which one your hover, this
// widget will get it
int same_id = getNewNoFocusID();
- subbtn = GUIEngine::getGUIEnv()->addButton(subsize, btn,
+ tab = GUIEngine::getGUIEnv()->addButton(tab_rect_abs, btn,
same_id, L"", L"");
- IGUIButton* icon =
- GUIEngine::getGUIEnv()->addButton(icon_part, subbtn,
- same_id, L"");
- icon->setScaleImage(true);
- std::string filename = GUIEngine::getSkin()->getThemedIcon(
- m_active_children[i].m_properties[PROP_ICON]);
- icon->setImage( irr_driver->getTexture(filename.c_str()) );
- icon->setUseAlphaChannel(true);
- icon->setDrawBorder(false);
- icon->setTabStop(false);
+ if (m_active_children[i].m_type == WTYPE_ICON_BUTTON)
+ {
+ IGUIButton* icon =
+ GUIEngine::getGUIEnv()->addButton(icon_part, tab,
+ same_id, L"");
+ icon->setScaleImage(true);
+ std::string filename = GUIEngine::getSkin()->getThemedIcon(
+ m_active_children[i].m_properties[PROP_ICON]);
+ icon->setImage( irr_driver->getTexture(filename.c_str()) );
+ icon->setUseAlphaChannel(true);
+ icon->setDrawBorder(false);
+ icon->setTabStop(false);
+ }
IGUIStaticText* label =
GUIEngine::getGUIEnv()->addStaticText(message.c_str(),
label_part,
false /* border */,
true /* word wrap */,
- subbtn, same_id);
+ tab, same_id);
if ((int)GUIEngine::getFont()->getDimension(message.c_str())
.Width > label_part.getWidth()&&
@@ -272,15 +306,15 @@ void RibbonWidget::add()
label->setNotClipped(true);
m_labels.push_back(label);
- subbtn->setTabStop(false);
- subbtn->setTabGroup(false);
+ tab->setTabStop(false);
+ tab->setTabGroup(false);
}
else
{
Log::error("RibbonWidget", "Invalid tab bar contents");
}
- m_active_children[i].m_element = subbtn;
+ m_active_children[i].m_element = tab;
if (message.size() == 0) widget_x += small_tab/2;
else widget_x += large_tab/2;
@@ -303,42 +337,49 @@ void RibbonWidget::add()
else
widget_y += one_button_height;
- IGUIButton * subbtn = NULL;
+ IGUIButton * tab = NULL;
- // The buttons will overlap without this,
- // as drawBoxFromStretchableTexture draw the borders outside
- // of a widget's reserved area
- int VERT_BORDER_MARGIN = 8;
- rect subbtn_rec = rect(widget_x - tab_width/2+2, widget_y + VERT_BORDER_MARGIN,
- widget_x + tab_width/2-2, widget_y - VERT_BORDER_MARGIN + one_button_height);
+ rect tab_rect_abs = rect(widget_x - (tab_width/2) - HORZ_MARGIN, widget_y + VERT_MARGIN,
+ widget_x + (tab_width/2) + HORZ_MARGIN, widget_y + one_button_height - VERT_MARGIN);
+ // Once height is available to us, adjust for scaling
+ TOP_BORDER = round( GUIEngine::getSkin()->getScalingFactor("verticalTab::neutral", tab_rect_abs.getHeight()) * (float)TOP_BORDER );
+ BOTTOM_BORDER = round( GUIEngine::getSkin()->getScalingFactor("verticalTab::neutral", tab_rect_abs.getHeight()) * (float)BOTTOM_BORDER );
+ LEFT_BORDER = round( GUIEngine::getSkin()->getScalingFactor("verticalTab::neutral", tab_rect_abs.getHeight()) * (float)LEFT_BORDER );
+ RIGHT_BORDER = round( GUIEngine::getSkin()->getScalingFactor("verticalTab::neutral", tab_rect_abs.getHeight()) * (float)RIGHT_BORDER );
+
+ HORZ_PADDING = round( GUIEngine::getSkin()->getScalingFactor("verticalTab::neutral", tab_rect_abs.getHeight()) * (float)HORZ_PADDING );
+ VERT_PADDING = round( GUIEngine::getSkin()->getScalingFactor("verticalTab::neutral", tab_rect_abs.getHeight()) * (float)VERT_PADDING );
+
+ // Used to position sub-elements, coords needs to be relative to tab_rect_abs
+ rect tab_contents_rect = rect(LEFT_BORDER + HORZ_PADDING,
+ TOP_BORDER + VERT_PADDING,
+ tab_rect_abs.getWidth() - RIGHT_BORDER - HORZ_PADDING,
+ tab_rect_abs.getHeight() - BOTTOM_BORDER - VERT_PADDING);
// TODO Add support for BUTTON type when needed
if (m_active_children[i].m_type == WTYPE_ICON_BUTTON)
{
- // The icon will take 1/3rd of the tab width at most, less if height is lacking
- int icon_size = std::min(m_w/3, subbtn_rec.getHeight()+2*VERT_BORDER_MARGIN);
-
- rect icon_part = rect(5,
- one_button_height/2 - icon_size/2-VERT_BORDER_MARGIN,
- icon_size+5,
- one_button_height/2 + icon_size/2-VERT_BORDER_MARGIN);
+ rect icon_part = rect(tab_contents_rect.UpperLeftCorner.X,
+ tab_contents_rect.UpperLeftCorner.Y,
+ tab_contents_rect.UpperLeftCorner.X + tab_contents_rect.getHeight(),
+ tab_contents_rect.UpperLeftCorner.Y + tab_contents_rect.getHeight());
// label at the *right* of the icon (for tabs)
- rect label_part = rect(icon_size+5,
- 5-VERT_BORDER_MARGIN,
- subbtn_rec.getWidth()-5,
- one_button_height-5-VERT_BORDER_MARGIN);
+ rect label_part = rect(icon_part.LowerRightCorner.X+5,
+ tab_contents_rect.UpperLeftCorner.Y,
+ tab_contents_rect.LowerRightCorner.X,
+ tab_contents_rect.LowerRightCorner.Y);
// use the same ID for all subcomponents; since event handling
// is done per-ID, no matter which one your hover, this
// widget will get it
int same_id = getNewNoFocusID();
- subbtn = GUIEngine::getGUIEnv()->addButton(subbtn_rec, btn,
+ tab = GUIEngine::getGUIEnv()->addButton(tab_rect_abs, btn,
same_id, L"", L"");
IGUIButton* icon =
- GUIEngine::getGUIEnv()->addButton(icon_part, subbtn,
+ GUIEngine::getGUIEnv()->addButton(icon_part, tab,
same_id, L"");
icon->setScaleImage(true);
std::string filename = GUIEngine::getSkin()->getThemedIcon(
@@ -353,15 +394,19 @@ void RibbonWidget::add()
label_part,
false /* border */,
true /* word wrap */,
- subbtn, same_id);
+ tab, same_id);
- if ((int)GUIEngine::getFont()->getDimension(message.c_str())
- .Width > label_part.getWidth()&&
- message.findFirst(L' ') == -1 &&
- message.findFirst(L'\u00AD') == -1 )
+ if (((int)GUIEngine::getFont()->getDimension(message.c_str())
+ .Width > label_part.getWidth() &&
+ message.findFirst(L' ') == -1 &&
+ message.findFirst(L'\u00AD') == -1) ||
+ ((int)GUIEngine::getFont()->getDimension(message.c_str())
+ .Width > label_part.getWidth() &&
+ (int)GUIEngine::getFont()->getDimension(message.c_str())
+ .Height*2 > label_part.getHeight()))
{
- // if message too long and contains no space and no soft
- // hyphen, make the font smaller
+ // if message is too long and contains no space and no soft
+ // hyphen, or too tall, make the font smaller
label->setOverrideFont(GUIEngine::getSmallFont());
}
label->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER);
@@ -369,15 +414,15 @@ void RibbonWidget::add()
label->setNotClipped(true);
m_labels.push_back(label);
- subbtn->setTabStop(false);
- subbtn->setTabGroup(false);
+ tab->setTabStop(false);
+ tab->setTabGroup(false);
}
else
{
Log::error("RibbonWidget", "Invalid tab bar contents");
}
- m_active_children[i].m_element = subbtn;
+ m_active_children[i].m_element = tab;
} // vertical-tabs
@@ -405,6 +450,7 @@ void RibbonWidget::add()
// calculate the size of the image
std::string filename =
GUIEngine::getSkin()->getThemedIcon(m_active_children[i].m_properties[PROP_ICON]);
+
video::ITexture* image =
irr_driver->getTexture((filename).c_str());
if(!image)
@@ -413,7 +459,7 @@ void RibbonWidget::add()
image = irr_driver->getTexture(file);
if(!image)
Log::fatal("RibbonWidget",
- "Can't find fallback texture 'gui/icons/main_help.png, aborting.");
+ "Can't find fallback texture 'main_help.png', aborting.");
}
float image_h = (float)image->getSize().Height;
@@ -465,7 +511,7 @@ void RibbonWidget::add()
}
- //m_children[i].id = subbtn->getID();
+ //m_children[i].id = tab->getID();
m_active_children[i].m_event_handler = this;
}// next sub-button