Added: html meter element

--HG--
branch : develop
This commit is contained in:
Nimetu 2019-05-07 20:12:10 +03:00
parent afda48c597
commit cb0d6c74f3
4 changed files with 246 additions and 4 deletions

View file

@ -408,6 +408,7 @@ namespace NLGUI
// True when the <lua> 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<HTMLOListElement> _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<bool> _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);

View file

@ -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<CHtmlElement>::iterator it = elm.Children.begin();
if (!_IgnoreChildElements)
{
while(it != elm.Children.end())
{
renderDOM(*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<string, string> TTmplParam;
vector<TTmplParam> 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)
{

View file

@ -1025,4 +1025,17 @@
force_inside_screen="false"></group>
</template>
<template name="html_meter" keep="true"
id="meter" w="0" h="0" active="true" border_x2="0"
bgtexture="blank.tga" bgcolor="0 0 0 255"
value_w="0" value_texture="blank.tga" value_color="100 100 100 100"
>
<group id="#id" w="#w" h="#h" active="#active">
<view type="bitmap" id="bg" posref="MM MM" sizeref="wh" scale="true" texture="#bgtexture" color="#bgcolor" />
<group id="inner" posref="MM MM" sizeref="wh" w="-#border_x2" h="-#border_x2">
<view type="bitmap" id="gauge" posref="ML ML" posparent="bg" sizeref="h" sizeparent="bg" w="#value_w" scale="true" texture="#value_texture" color="#value_color" />
</group>
</group>
</template>
</interface_config>

View file

@ -7252,4 +7252,17 @@
force_inside_screen="false"></group>
</template>
<template name="html_meter" keep="true"
id="meter" w="0" h="0" active="true" border_x2="0"
bgtexture="blank.tga" bgcolor="0 0 0 255"
value_w="0" value_texture="blank.tga" value_color="100 100 100 100"
>
<group id="#id" w="#w" h="#h" active="#active">
<view type="bitmap" id="bg" posref="MM MM" sizeref="wh" scale="true" texture="#bgtexture" color="#bgcolor" />
<group id="inner" posref="MM MM" sizeref="wh" w="-#border_x2" h="-#border_x2">
<view type="bitmap" id="gauge" posref="ML ML" posparent="bg" sizeref="h" sizeparent="bg" w="#value_w" scale="true" texture="#value_texture" color="#value_color" />
</group>
</group>
</template>
</interface_config>