diff --git a/code/nel/include/nel/gui/group_html.h b/code/nel/include/nel/gui/group_html.h
index 576c54ca7..c4c6d6dbd 100644
--- a/code/nel/include/nel/gui/group_html.h
+++ b/code/nel/include/nel/gui/group_html.h
@@ -408,6 +408,7 @@ namespace NLGUI
// True when the element has been encountered
bool _ParsingLua;
bool _IgnoreText;
+ bool _IgnoreChildElements;
// the script to execute
std::string _LuaScript;
bool _LuaHrefHack;
@@ -466,6 +467,41 @@ namespace NLGUI
};
std::vector _UL;
+ class HTMLMeterElement {
+ public:
+ enum EValueRegion {
+ VALUE_OPTIMUM = 0,
+ VALUE_SUB_OPTIMAL,
+ VALUE_EVEN_LESS_GOOD
+ };
+ public:
+ HTMLMeterElement()
+ : value(0.f), min(0.f), max(1.f), low(0.f), high(1.f), optimum(0.5f)
+ {}
+
+ // read attributes from html element
+ void readValues(const CHtmlElement &elm);
+
+ // return value ratio to min-max
+ float getValueRatio() const;
+
+ // return optimum region based current value
+ EValueRegion getValueRegion() const;
+
+ // return meter bar color
+ NLMISC::CRGBA getBarColor(const CHtmlElement &elm, CCssStyle &style) const;
+
+ // return meter value bar color based value and optimum range
+ NLMISC::CRGBA getValueColor(const CHtmlElement &elm, CCssStyle &style) const;
+
+ float value;
+ float min;
+ float max;
+ float low;
+ float high;
+ float optimum;
+ };
+
// A mode
std::vector _A;
inline bool getA() const
@@ -894,6 +930,7 @@ namespace NLGUI
void htmlLUA(const CHtmlElement &elm);
void htmlLUAend(const CHtmlElement &elm);
void htmlMETA(const CHtmlElement &elm);
+ void htmlMETER(const CHtmlElement &elm);
void htmlOBJECT(const CHtmlElement &elm);
void htmlOBJECTend(const CHtmlElement &elm);
void htmlOL(const CHtmlElement &elm);
diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp
index 76a7d3c25..19162eeed 100644
--- a/code/nel/src/gui/group_html.cpp
+++ b/code/nel/src/gui/group_html.cpp
@@ -1102,6 +1102,7 @@ namespace NLGUI
case HTML_LI: htmlLI(elm); break;
case HTML_LUA: htmlLUA(elm); break;
case HTML_META: htmlMETA(elm); break;
+ case HTML_METER: htmlMETER(elm); break;
case HTML_OBJECT: htmlOBJECT(elm); break;
case HTML_OL: htmlOL(elm); break;
case HTML_OPTION: htmlOPTION(elm); break;
@@ -1162,6 +1163,7 @@ namespace NLGUI
case HTML_LI: htmlLIend(elm); break;
case HTML_LUA: htmlLUAend(elm); break;
case HTML_META: break;
+ case HTML_METER: break;
case HTML_OBJECT: htmlOBJECTend(elm); break;
case HTML_OL: htmlOLend(elm); break;
case HTML_OPTION: htmlOPTIONend(elm); break;
@@ -1337,12 +1339,16 @@ namespace NLGUI
beginElement(elm);
std::list::iterator it = elm.Children.begin();
- while(it != elm.Children.end())
+ if (!_IgnoreChildElements)
{
- renderDOM(*it);
+ while(it != elm.Children.end())
+ {
+ renderDOM(*it);
- ++it;
+ ++it;
+ }
}
+ _IgnoreChildElements = false;
endElement(elm);
}
@@ -1373,6 +1379,7 @@ namespace NLGUI
_ParsingLua = false;
_LuaHrefHack = false;
_IgnoreText = false;
+ _IgnoreChildElements = false;
_BrowseNextTime = false;
_PostNextTime = false;
_Browsing = false;
@@ -4876,7 +4883,12 @@ namespace NLGUI
// td { padding: 1px;} - overwrites cellpadding attribute
// table { border-spacing: 2px;} - overwrites cellspacing attribute
css += "table { border-collapse: separate;}";
-
+ // webkit pseudo elements
+ css += "meter::-webkit-meter-bar, meter::-webkit-optimum-value, meter::-webkit-suboptimum-value, meter::-webkit-even-less-good-value { background: none; }";
+ css += "meter::-webkit-meter-bar { background-color: rgb(100, 100, 100); width: 5em; height: 1em;}";
+ css += "meter::-webkit-meter-optimum-value { background-color: rgb(80, 220, 80); }";
+ css += "meter::-webkit-meter-suboptimum-value { background-color: rgb(220, 220, 80); }";
+ css += "meter::-webkit-meter-even-less-good-value { background-color: rgb(220, 80, 80); }";
_Style.parseStylesheet(css);
}
@@ -4981,6 +4993,129 @@ namespace NLGUI
return ret;
}
+ void CGroupHTML::HTMLMeterElement::readValues(const CHtmlElement &elm)
+ {
+ if (!elm.hasAttribute("value") || !fromString(elm.getAttribute("value"), value))
+ value = 0.f;
+ if (!elm.hasAttribute("min") || !fromString(elm.getAttribute("min"), min))
+ min = 0.f;
+ if (!elm.hasAttribute("max") || !fromString(elm.getAttribute("max"), max))
+ max = 1.f;
+
+ // ensure min < max
+ if (max < min)
+ std::swap(min, max);
+
+ if (!elm.hasAttribute("low") || !fromString(elm.getAttribute("low"), low))
+ low = min;
+ if (!elm.hasAttribute("high") || !fromString(elm.getAttribute("high"), high))
+ high = max;
+
+ if (!elm.hasAttribute("optimum") || !fromString(elm.getAttribute("optimum"), optimum))
+ optimum = (max - min) / 2.f;
+
+ // ensure low < high
+ if (high < low)
+ std::swap(low, high);
+ if (low < min)
+ low = min;
+ if (high > max)
+ max = max;
+ }
+
+ float CGroupHTML::HTMLMeterElement::getValueRatio() const
+ {
+ if (max <= min)
+ return 0.f;
+
+ return (value - min) / (max - min);
+ }
+
+ CGroupHTML::HTMLMeterElement::EValueRegion CGroupHTML::HTMLMeterElement::getValueRegion() const
+ {
+ if (optimum <= low)
+ {
+ // low region is optimum
+ if (value <= low)
+ return VALUE_OPTIMUM;
+ else if (value <= high)
+ return VALUE_SUB_OPTIMAL;
+
+ return VALUE_EVEN_LESS_GOOD;
+ }
+ else if (optimum >= high)
+ {
+ // high region is optimum
+ if (value >= high)
+ return VALUE_OPTIMUM;
+ else if (value >= low)
+ return VALUE_SUB_OPTIMAL;
+
+ return VALUE_EVEN_LESS_GOOD;
+ }
+
+ // middle region is optimum
+ if (value >= low && value <= high)
+ return VALUE_OPTIMUM;
+
+ return VALUE_SUB_OPTIMAL;
+ }
+
+ NLMISC::CRGBA CGroupHTML::HTMLMeterElement::getBarColor(const CHtmlElement &elm, CCssStyle &style) const
+ {
+ // color meter (inactive) bar segment
+ // firefox:: meter { background:none; background-color: #555; },
+ // webkit:: meter::-webkit-meter-bar { background:none; background-color: #555; }
+ // webkit makes background color visible when padding is added
+ CRGBA color(150, 150, 150, 255);
+
+ // use webkit pseudo elements as thats easier than firefox pseudo classes
+ // background-color is expected to be set from browser.css
+ style.pushStyle();
+ style.applyStyle(elm.getPseudo(":-webkit-meter-bar"));
+ if(style.hasStyle("background-color"))
+ color = style.Current.BackgroundColor;
+ style.popStyle();
+
+ return color;
+ }
+
+ NLMISC::CRGBA CGroupHTML::HTMLMeterElement::getValueColor(const CHtmlElement &elm, CCssStyle &style) const
+ {
+ // background-color is expected to be set from browser.css
+ CRGBA color;
+ style.pushStyle();
+ switch(getValueRegion())
+ {
+ case VALUE_OPTIMUM:
+ {
+ style.applyStyle(elm.getPseudo(":-webkit-meter-optimum-value"));
+ if (style.hasStyle("background-color"))
+ color = style.Current.BackgroundColor;
+ break;
+ }
+ case VALUE_SUB_OPTIMAL:
+ {
+ style.applyStyle(elm.getPseudo(":-webkit-meter-suboptimum-value"));
+ if (style.hasStyle("background-color"))
+ color = style.Current.BackgroundColor;
+ break;
+ }
+ case VALUE_EVEN_LESS_GOOD: // fall through
+ default:
+ {
+ style.applyStyle(elm.getPseudo(":-webkit-meter-even-less-good-value"));
+ if (style.hasStyle("background-color"))
+ color = style.Current.BackgroundColor;
+ break;
+ }
+ }//switch
+ style.popStyle();
+
+ return color;
+ }
+
+ // ****************************************************************************
void CGroupHTML::getCellsParameters(const CHtmlElement &elm, bool inherit)
{
CGroupHTML::CCellParams cellParams;
@@ -5963,6 +6098,50 @@ namespace NLGUI
}
}
+ // ***************************************************************************
+ void CGroupHTML::htmlMETER(const CHtmlElement &elm)
+ {
+ HTMLMeterElement meter;
+ meter.readValues(elm);
+
+ std::string id = "meter";
+ if (elm.hasAttribute("id"))
+ id = elm.getAttribute("id");
+
+ // width: 5em, height: 1em
+ uint32 width = _Style.Current.Width > -1 ? _Style.Current.Width : _Style.Current.FontSize * 5;
+ uint32 height = _Style.Current.Height > -1 ? _Style.Current.Height : _Style.Current.FontSize;
+ uint32 border = _Style.Current.BorderWidth > -1 ? _Style.Current.BorderWidth : 0;
+
+ uint barw = (uint) (width * meter.getValueRatio());
+ CRGBA bgColor = meter.getBarColor(elm, _Style);
+ CRGBA valueColor = meter.getValueColor(elm, _Style);
+
+ typedef pair TTmplParam;
+ vector tmplParams;
+ tmplParams.push_back(TTmplParam("id", id));
+ tmplParams.push_back(TTmplParam("active", "true"));
+ tmplParams.push_back(TTmplParam("w", toString(width)));
+ tmplParams.push_back(TTmplParam("h", toString(height)));
+ tmplParams.push_back(TTmplParam("border_x2", toString(border*2)));
+ tmplParams.push_back(TTmplParam("bgtexture", "blank.tga"));
+ tmplParams.push_back(TTmplParam("bgcolor", bgColor.toString()));
+ tmplParams.push_back(TTmplParam("value_w", toString(barw)));
+ tmplParams.push_back(TTmplParam("value_texture", "blank.tga"));
+ tmplParams.push_back(TTmplParam("value_color", valueColor.toString()));
+
+ CInterfaceGroup *gr = CWidgetManager::getInstance()->getParser()->createGroupInstance("html_meter", getParagraph()->getId(), &tmplParams[0], (uint)tmplParams.size());
+ if (gr)
+ {
+ renderPseudoElement(":before", elm);
+ getParagraph()->addChild(gr);
+ renderPseudoElement(":after", elm);
+
+ // ignore any inner elements
+ _IgnoreChildElements = true;
+ }
+ }
+
// ***************************************************************************
void CGroupHTML::htmlOBJECT(const CHtmlElement &elm)
{
diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/login_widgets.xml b/code/ryzom/client/data/gamedev/interfaces_v3/login_widgets.xml
index 6d7ac1fa7..c2182fd50 100644
--- a/code/ryzom/client/data/gamedev/interfaces_v3/login_widgets.xml
+++ b/code/ryzom/client/data/gamedev/interfaces_v3/login_widgets.xml
@@ -1025,4 +1025,17 @@
force_inside_screen="false">
+
+
+
+
+
+
+
+
+
diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/widgets.xml b/code/ryzom/client/data/gamedev/interfaces_v3/widgets.xml
index 10c36d6a4..16150c418 100644
--- a/code/ryzom/client/data/gamedev/interfaces_v3/widgets.xml
+++ b/code/ryzom/client/data/gamedev/interfaces_v3/widgets.xml
@@ -7252,4 +7252,17 @@
force_inside_screen="false">
+
+
+
+
+
+
+
+
+