Merge with html-improvements

--HG--
branch : develop
feature/streamed-package
Nuno Gonçalves 5 years ago
commit 9a2e820495

@ -0,0 +1,94 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef NL_CSS_BORDER_RENDERER_H
#define NL_CSS_BORDER_RENDERER_H
#include "nel/misc/types_nl.h"
#include "nel/misc/rgba.h"
#include "nel/misc/geom_ext.h"
#include "nel/gui/css_types.h"
namespace NLGUI
{
/**
* \brief Border renderer for GUI classes
* \date 2019-09-03 10:50 GMT
* \author Meelis Mägi (Nimetu)
*/
class CSSBorderRenderer
{
private:
// parent element screen coordinates
sint32 _XReal, _YReal;
sint32 _WReal, _HReal;
NLMISC::CQuadUV _QuadT;
NLMISC::CQuadUV _QuadR;
NLMISC::CQuadUV _QuadB;
NLMISC::CQuadUV _QuadL;
uint8 _RenderLayer;
bool _ModulateGlobalColor;
// if true, then updateCoords() is called from draw()
bool _Dirty;
// if true, then at least one border is set
bool _Border;
bool _BorderTop, _BorderRight, _BorderBottom, _BorderLeft;
public:
uint32 TopWidth, RightWidth, BottomWidth, LeftWidth;
NLMISC::CRGBA TopColor, RightColor, BottomColor, LeftColor;
CSSLineStyle TopStyle, RightStyle, BottomStyle, LeftStyle;
// alpha value from parent
uint8 CurrentAlpha;
public:
CSSBorderRenderer();
void setRenderLayer(sint layer);
void setModulateGlobalColor(bool m);
void setRect(sint32 x, sint32 y, sint32 w, sint32 h);
void setWidth(uint32 top, uint32 right, uint32 bottom, uint32 left);
void setStyle(CSSLineStyle top, CSSLineStyle right, CSSLineStyle bottom, CSSLineStyle left);
void setColor(const NLMISC::CRGBA &top, const NLMISC::CRGBA &right, const NLMISC::CRGBA &bottom, const NLMISC::CRGBA &left);
void updateCoords();
void invalidateCoords() { _Dirty = _Border = true; }
void invalidateContent() { _Dirty = _Border = true; };
uint32 getTopWidth() const;
uint32 getRightWidth() const;
uint32 getBottomWidth() const;
uint32 getLeftWidth() const;
uint32 getLeftRightWidth() const;
uint32 getTopBottomWidth() const;
void draw();
}; // CSSBorderRenderer
}//namespace
#endif // NL_CSS_BORDER_RENDERER_H

@ -31,7 +31,7 @@ namespace NLGUI
class CCssParser {
public:
// parse style declaration, eg "color: red; font-size: 10px;"
static TStyle parseDecls(const std::string &styleString);
static TStyleVec parseDecls(const std::string &styleString);
// parse css stylesheet
void parseStylesheet(const std::string &cssString, std::vector<CCssStyle::SStyleRule> &rules);

@ -20,12 +20,15 @@
#include "nel/misc/types_nl.h"
#include "nel/misc/rgba.h"
#include "nel/gui/css_selector.h"
#include "nel/gui/css_types.h"
namespace NLGUI
{
class CHtmlElement;
typedef std::map<std::string, std::string> TStyle;
typedef std::pair<std::string, std::string> TStylePair;
typedef std::vector<TStylePair> TStyleVec;
/**
* \brief CSS style rules
@ -62,9 +65,14 @@ namespace NLGUI
Height=-1;
MaxWidth=-1;
MaxHeight=-1;
BorderWidth=-1;
// border style
BorderTopWidth = BorderRightWidth = BorderBottomWidth = BorderLeftWidth = CSSLineWidth::MEDIUM;
BorderTopStyle = BorderRightStyle = BorderBottomStyle = BorderLeftStyle = CSSLineStyle::NONE;
BorderTopColor = BorderRightColor = BorderBottomColor = BorderLeftColor = NLMISC::CRGBA::Transparent;
// background
BackgroundColor=NLMISC::CRGBA::Black;
BackgroundColorOver=NLMISC::CRGBA::Black;
PaddingTop = PaddingRight = PaddingBottom = PaddingLeft = 0;
}
bool hasStyle(const std::string &key) const
@ -93,9 +101,12 @@ namespace NLGUI
sint32 Height;
sint32 MaxWidth;
sint32 MaxHeight;
sint32 BorderWidth;
uint32 BorderTopWidth, BorderRightWidth, BorderBottomWidth, BorderLeftWidth;
CSSLineStyle BorderTopStyle, BorderRightStyle, BorderBottomStyle, BorderLeftStyle;
NLMISC::CRGBA BorderTopColor, BorderRightColor, BorderBottomColor, BorderLeftColor;
NLMISC::CRGBA BackgroundColor;
NLMISC::CRGBA BackgroundColorOver;
uint32 PaddingTop, PaddingRight, PaddingBottom, PaddingLeft;
std::string WhiteSpace;
std::string TextAlign;
@ -106,9 +117,10 @@ namespace NLGUI
class CCssStyle {
public:
struct SStyleRule {
std::vector<CCssSelector> Selector;
TStyle Properties;
TStyleVec Properties;
// pseudo element like ':before'
std::string PseudoElement;
@ -132,6 +144,9 @@ namespace NLGUI
// test if str is one of "thin/medium/thick" and return its pixel value
bool scanCssLength(const std::string& str, uint32 &px) const;
// split css properties string, ie '1px solid rgb(100, 100, 100)' split by ' ' returns 3 parts.
void splitParams(const std::string &str, char sep, std::vector<std::string> &result) const;
// read style attribute
void getStyleParams(const std::string &styleString, CStyleParams &style, const CStyleParams &current) const;
void getStyleParams(const TStyle &styleRules, CStyleParams &style, const CStyleParams &current) const;
@ -143,13 +158,35 @@ namespace NLGUI
void apply(CStyleParams &style, const CStyleParams &current) const;
// merge src into dest by overwriting key in dest
void merge(TStyle &dst, const TStyle &src) const;
void merge(TStyle &dst, const TStyleVec &src) const;
// match selector to dom path
bool match(const std::vector<CCssSelector> &selector, const CHtmlElement &elm) const;
// get shorthang 'top right bottom left' index values based size, ie 'padding' syntax
bool getShorthandIndices(const uint32 size, uint8 &t, uint8 &r, uint8 &b, uint8 &l) const;
// break 'border' into 'border-top-color', 'border-top-style', etc rules
bool tryBorderWidthShorthand(const std::string &prop, const std::string &value, TStyle &style) const;
bool tryBorderStyleShorthand(const std::string &prop, const std::string &value, TStyle &style) const;
bool tryBorderColorShorthand(const std::string &prop, const std::string &value, TStyle &style) const;
void expandBorderShorthand(const std::string &prop, const std::string &value, TStyle &style) const;
// parse 'background' into 'background-color', 'background-image', etc
void parseBackgroundShorthand(const std::string &value, CStyleParams &style) const;
void expandBackgroundShorthand(const std::string &value, TStyle &style) const;
// parse 'padding' into 'padding-top', 'padding-left', etc
void expandPaddingShorthand(const std::string &value, TStyle &style) const;
// expand shorthand rule, ie "border", into longhand names, ie "border-top-width"
// if shorthand is present in style, then its removed
void expandShorthand(const std::string &prop, const std::string &value, TStyle &style) const;
// parse string value into corresponding value
void applyBorderWidth(const std::string &value, uint32 *dest, const uint32 currentWidth, const uint32 fontSize) const;
void applyBorderColor(const std::string &value, NLMISC::CRGBA *dest, const NLMISC::CRGBA &currentColor, const NLMISC::CRGBA &textColor) const;
void applyLineStyle(const std::string &value, CSSLineStyle *dest, const CSSLineStyle &currentStyle) const;
void applyPaddingWidth(const std::string &value, uint32 *dest, const uint32 currentPadding, uint32 fontSize) const;
public:
void reset();
@ -171,12 +208,17 @@ namespace NLGUI
{
_StyleStack.push_back(Current);
Current.GlobalColor = false;
Current.DisplayBlock = false;
Current.Width=-1;
Current.Height=-1;
Current.MaxWidth=-1;
Current.MaxHeight=-1;
Current.BorderWidth=-1;
Current.BorderTopWidth = Current.BorderRightWidth = Current.BorderBottomWidth = Current.BorderLeftWidth = CSSLineWidth::MEDIUM;
Current.BorderTopStyle = Current.BorderRightStyle = Current.BorderBottomStyle = Current.BorderLeftStyle = CSSLineStyle::NONE;
Current.BorderTopColor = Current.BorderRightColor = Current.BorderBottomColor = Current.BorderLeftColor = Current.TextColor;
Current.PaddingTop = Current.PaddingRight = Current.PaddingBottom = Current.PaddingLeft = 0;
Current.StyleRules.clear();
}

@ -0,0 +1,39 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef CL_CSS_TYPES_H
#define CL_CSS_TYPES_H
#include "nel/misc/types_nl.h"
namespace NLGUI
{
/**
* \brief CSS types used in GUI classes
* \date 2019-09-03 10:50 GMT
* \author Meelis Mägi (Nimetu)
*/
// ie. border-style
enum CSSLineStyle { NONE = 0, HIDDEN, SOLID, INSET, OUTSET };
// ie, border-width (px)
enum CSSLineWidth { THIN = 1, MEDIUM = 3, THICK = 5 };
}//namespace
#endif // CL_CSS_TYPES_H

@ -124,7 +124,7 @@ namespace NLGUI
void endParagraph();
// add image download (used by view_bitmap.cpp to load web images)
void addImageDownload(const std::string &url, CViewBase *img, const CStyleParams &style = CStyleParams(), const TImageType type = NormalImage);
void addImageDownload(const std::string &url, CViewBase *img, const CStyleParams &style = CStyleParams(), const TImageType type = NormalImage, const std::string &placeholder = "web_del.tga");
// remove image from download list if present
void removeImageDownload(CViewBase *img);
std::string localImageName(const std::string &url);
@ -546,6 +546,11 @@ namespace NLGUI
// IL mode
bool _LI;
// style from browser.css
CCssStyle _BrowserStyle;
// local file for browser.css
std::string _BrowserCssFile;
// Keep track of current element style
CCssStyle _Style;
CHtmlElement _HtmlDOM;
@ -702,6 +707,7 @@ namespace NLGUI
VAlign = CGroupCell::Middle;
LeftMargin = 0;
NoWrap = false;
Height = 0;
}
NLMISC::CRGBA BgColor;
std::string Style;
@ -709,6 +715,7 @@ namespace NLGUI
CGroupCell::TVAlign VAlign;
sint32 LeftMargin;
bool NoWrap;
sint32 Height;
};
std::vector<CCellParams> _CellParams;

@ -357,7 +357,7 @@ namespace NLGUI
void setMinH(sint32 minH);
// change fontsize for new menu items
void setFontSize(uint32 fontSize);
void setFontSize(uint32 fontSize, bool coef = true);
// Gray a line on the RootMenu
void setGrayedLine(uint line, bool g);
@ -397,6 +397,7 @@ namespace NLGUI
bool _Formatted;
uint8 _Space;
sint32 _FontSize;
bool _FontSizeCoef;
NLMISC::CRGBA _ColorOver; // Color of the text when the mouse is over it
NLMISC::CRGBA _ShadowColorOver; // Color of the shadow when the mouse is over it

@ -23,9 +23,11 @@
#include "nel/gui/group_frame.h"
#include "nel/gui/view_text.h"
#include "nel/gui/ctrl_button.h"
#include "nel/gui/css_types.h"
namespace NLGUI
{
class CSSBorderRenderer;
/**
* This group is used to simulate HTML cells.
@ -39,6 +41,7 @@ namespace NLGUI
DECLARE_UI_CLASS( CGroupCell )
CGroupCell(const TCtorParam &param);
~CGroupCell();
enum TAlign
{
@ -91,11 +94,18 @@ namespace NLGUI
// The cell color
NLMISC::CRGBA BgColor;
CSSBorderRenderer* Border;
uint32 PaddingTop, PaddingRight, PaddingBottom, PaddingLeft;
// Texture
CViewRenderer::CTextureId _TextureId; /// Accelerator
bool _UserTexture;
CViewRenderer::CTextureId _TextureId;
bool _TextureTiled;
bool _TextureScaled;
// cached absolute coords for background texture
sint32 _TextureXReal;
sint32 _TextureYReal;
sint32 _TextureWReal;
sint32 _TextureHReal;
// Alignment
TAlign Align;
@ -112,10 +122,17 @@ namespace NLGUI
void setTextureTile(bool tiled);
void setTextureScale(bool scaled);
uint32 getPaddingLeftRight() const { return PaddingLeft + PaddingRight; };
uint32 getPaddingTopBottom() const { return PaddingTop + PaddingBottom; };
virtual void updateCoords();
static void setDebugUICell( bool d ){ DebugUICell = d; }
static bool getDebugUICell(){ return DebugUICell; }
private:
void updateTextureCoords();
void setEnclosedGroupDefaultParams();
static bool DebugUICell;
};
@ -143,9 +160,10 @@ namespace NLGUI
// The Width you want in pixel. This is the <table width="100"> parameter
sint32 ForceWidthMin;
// Table borders
sint32 Border;
NLMISC::CRGBA BorderColor;
CSSBorderRenderer* Border;
// Cell has 1px solid border when <table> has 'border' attribute with width > 0
bool CellBorder;
sint32 CellPadding;
sint32 CellSpacing;
@ -155,6 +173,10 @@ namespace NLGUI
bool ContinuousUpdate;
void setTexture(const std::string & TxName);
void setTextureTile(bool tiled);
void setTextureScale(bool scaled);
std::string getProperties( const std::string &name ) const;
void setProperty( const std::string &name, const std::string &value );
xmlNodePtr serialize( xmlNodePtr parentNode, const char *type ) const;
@ -176,6 +198,18 @@ namespace NLGUI
virtual bool parse (xmlNodePtr cur, CInterfaceGroup * parentGroup);
// Texture
CViewRenderer::CTextureId _TextureId;
bool _TextureTiled;
bool _TextureScaled;
// cached absolute coords for background texture
sint32 _TextureXReal;
sint32 _TextureYReal;
sint32 _TextureWReal;
sint32 _TextureHReal;
void updateTextureCoords();
// Content validated
bool _ContentValidated;

@ -101,6 +101,12 @@ namespace NLGUI
return _TextureId;
}
// Return true if TextureId is not set
bool empty() const { return _TextureId < 0; };
// delete TextureId if set
void clear();
void serial(NLMISC::IStream &f);
private:

@ -26,6 +26,7 @@
#include "nel/misc/types_nl.h"
#include "nel/gui/interface_common.h"
#include "nel/gui/interface_options.h"
#include "nel/gui/interface_group.h"
#include "nel/gui/event_descriptor.h"
#include "nel/3d/u_camera.h"
#include "nel/gui/parser.h"

@ -119,6 +119,11 @@ public: // Advanced Usage.
// return a string separated by \n or eof, used to parsing text file
void getline (char *buffer, uint32 bufferSize);
// read whole file into a string. resulting buffer may contain NULL chars.
// internal read position is modified.
// return true on success, false on failure.
bool readAll(std::string &buffer);
// return the size of the file
uint32 getFileSize () const { return _FileSize; }

@ -377,6 +377,7 @@ public:
static const CRGBA Magenta ;
static const CRGBA Cyan ;
static const CRGBA White ;
static const CRGBA Transparent ;
};

@ -0,0 +1,320 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdpch.h"
#include "nel/gui/css_border_renderer.h"
#include "nel/gui/view_renderer.h"
#include "nel/gui/widget_manager.h"
using namespace std;
using namespace NLMISC;
#ifdef DEBUG_NEW
#define new DEBUG_NEW
#endif
namespace NLGUI
{
// ----------------------------------------------------------------------------
CSSBorderRenderer::CSSBorderRenderer()
{
TopWidth = RightWidth = BottomWidth = LeftWidth = 0;
TopColor = RightColor = BottomColor = LeftColor = CRGBA(128, 128, 128, 255);
TopStyle = RightStyle = BottomStyle = LeftStyle = CSSLineStyle::SOLID;
CurrentAlpha = 255;
_RenderLayer = 0;
_ModulateGlobalColor = false;
_Border = true;
_Dirty = true;
_BorderTop = _BorderRight = _BorderBottom = _BorderLeft = false;
//
_QuadT.Uv0.set(0.f, 0.f);
_QuadT.Uv1.set(0.f, 0.f);
_QuadT.Uv2.set(1.f, 1.f);
_QuadT.Uv3.set(0.f, 1.f);
//
_QuadR.Uv0.set(0.f, 0.f);
_QuadR.Uv1.set(0.f, 0.f);
_QuadR.Uv2.set(1.f, 1.f);
_QuadR.Uv3.set(0.f, 1.f);
//
_QuadB.Uv0.set(0.f, 0.f);
_QuadB.Uv1.set(0.f, 0.f);
_QuadB.Uv2.set(1.f, 1.f);
_QuadB.Uv3.set(0.f, 1.f);
//
_QuadL.Uv0.set(0.f, 0.f);
_QuadL.Uv1.set(0.f, 0.f);
_QuadL.Uv2.set(1.f, 1.f);
_QuadL.Uv3.set(0.f, 1.f);
}
// ----------------------------------------------------------------------------
void CSSBorderRenderer::setRenderLayer(sint layer)
{
_RenderLayer = layer;
}
// ----------------------------------------------------------------------------
void CSSBorderRenderer::setModulateGlobalColor(bool s)
{
_ModulateGlobalColor = s;
}
// ----------------------------------------------------------------------------
void CSSBorderRenderer::setRect(sint32 x, sint32 y, sint32 w, sint32 h)
{
_XReal = x;
_YReal = y;
_WReal = w;
_HReal = h;
_Dirty = _Border = (w > 0 && h > 0);
}
// ----------------------------------------------------------------------------
void CSSBorderRenderer::setWidth(uint32 top, uint32 right, uint32 bottom, uint32 left)
{
TopWidth = top;
RightWidth = right;
BottomWidth = bottom;
LeftWidth = left;
_Dirty = _Border = (top > 0 || right > 0 || bottom > 0 || left > 0);
}
// ----------------------------------------------------------------------------
void CSSBorderRenderer::setStyle(CSSLineStyle top, CSSLineStyle right, CSSLineStyle bottom, CSSLineStyle left)
{
TopStyle = top;
RightStyle = right;
BottomStyle = bottom;
LeftStyle = left;
_Dirty = _Border = true;
}
// ----------------------------------------------------------------------------
void CSSBorderRenderer::setColor(const NLMISC::CRGBA &top, const NLMISC::CRGBA &right, const NLMISC::CRGBA &bottom, const NLMISC::CRGBA &left)
{
TopColor = top;
RightColor = right;
BottomColor = bottom;
LeftColor = left;
_Dirty = true;
}
// ----------------------------------------------------------------------------
uint32 CSSBorderRenderer::getTopWidth() const
{
if (TopStyle == CSSLineStyle::NONE || TopStyle == CSSLineStyle::HIDDEN)
return 0;
return TopWidth;
}
// ----------------------------------------------------------------------------
uint32 CSSBorderRenderer::getRightWidth() const
{
if (RightStyle == CSSLineStyle::NONE || RightStyle == CSSLineStyle::HIDDEN)
return 0;
return RightWidth;
}
// ----------------------------------------------------------------------------
uint32 CSSBorderRenderer::getBottomWidth() const
{
if (BottomStyle == CSSLineStyle::NONE || BottomStyle == CSSLineStyle::HIDDEN)
return 0;
return BottomWidth;
}
// ----------------------------------------------------------------------------
uint32 CSSBorderRenderer::getLeftWidth() const
{
if (LeftStyle == CSSLineStyle::NONE || LeftStyle == CSSLineStyle::HIDDEN)
return 0;
return LeftWidth;
}
// ----------------------------------------------------------------------------
uint32 CSSBorderRenderer::getLeftRightWidth() const
{
return getLeftWidth() + getRightWidth();
}
// ----------------------------------------------------------------------------
uint32 CSSBorderRenderer::getTopBottomWidth() const
{
return getTopWidth() + getBottomWidth();
}
// ----------------------------------------------------------------------------
void CSSBorderRenderer::updateCoords()
{
_Dirty = false;
if (!_Border) return;
sint dTop = getTopWidth(); _BorderTop = dTop > 0;
sint dRight = getRightWidth(); _BorderRight = dRight > 0;
sint dBottom = getBottomWidth(); _BorderBottom = dBottom > 0;
sint dLeft = getLeftWidth(); _BorderLeft = dLeft > 0;
_Border = _BorderTop || _BorderRight || _BorderBottom || _BorderLeft;
if (!_Border) return;
if (_BorderTop)
{
// top-left
_QuadT.V3.x = _XReal;
_QuadT.V3.y = _YReal + _HReal;
// top-right
_QuadT.V2.x = _XReal + _WReal;
_QuadT.V2.y = _YReal + _HReal;
// bottom-right
_QuadT.V1.x = _XReal + _WReal - dRight;
_QuadT.V1.y = _YReal + _HReal - dTop;
// bottom-left
_QuadT.V0.x = _XReal + dLeft;
_QuadT.V0.y = _YReal + _HReal - dTop;
}
if (_BorderRight)
{
// top-left
_QuadR.V3.x = _XReal + _WReal - dRight;
_QuadR.V3.y = _YReal + _HReal - dTop;
// top-right
_QuadR.V2.x = _XReal + _WReal;
_QuadR.V2.y = _YReal + _HReal;
// bottom-right
_QuadR.V1.x = _XReal + _WReal;
_QuadR.V1.y = _YReal;
// bottom-left
_QuadR.V0.x = _XReal + _WReal - dRight;
_QuadR.V0.y = _YReal + dBottom;
}
if (_BorderBottom)
{
// top-left
_QuadB.V3.x = _XReal + dLeft;
_QuadB.V3.y = _YReal + dBottom;
// top-right
_QuadB.V2.x = _XReal + _WReal - dRight;
_QuadB.V2.y = _YReal + dBottom;
// bottom-right
_QuadB.V1.x = _XReal + _WReal;
_QuadB.V1.y = _YReal;
// bottom-left
_QuadB.V0.x = _XReal;
_QuadB.V0.y = _YReal;
}
if (_BorderLeft)
{
// top-left
_QuadL.V3.x = _XReal;
_QuadL.V3.y = _YReal + _HReal;
// top-right
_QuadL.V2.x = _XReal + dLeft;
_QuadL.V2.y = _YReal + _HReal - dTop;
// bottom-right
_QuadL.V1.x = _XReal + dLeft;
_QuadL.V1.y = _YReal + dBottom;
// bottom-left
_QuadL.V0.x = _XReal;
_QuadL.V0.y = _YReal;
}
}
// ----------------------------------------------------------------------------
void CSSBorderRenderer::draw() {
if (_Dirty) updateCoords();
if (!_Border) return;
CViewRenderer &rVR = *CViewRenderer::getInstance();
// TODO: no need for widget manager, if global color is set from parent
CRGBA globalColor;
if (_ModulateGlobalColor)
globalColor = CWidgetManager::getInstance()->getGlobalColor();
// TODO: monitor ModulateGlobalColor and CurrentAlpha in table checkCoords and recalculate colors on change only
// OUTSET - bottom/right darker than normal (default table style)
// INSET - top/left darker than normal
if (_BorderTop)
{
CRGBA borderColorT = TopColor;
if (TopStyle == CSSLineStyle::INSET)
borderColorT = blend(borderColorT, CRGBA::Black, 0.5f);
if (_ModulateGlobalColor)
borderColorT.modulateFromColor (borderColorT, globalColor);
borderColorT.A = (uint8) (((uint16) CurrentAlpha * (uint16) borderColorT.A) >> 8);
rVR.drawQuad(_RenderLayer, _QuadT, rVR.getBlankTextureId(), borderColorT, false);
}
if (_BorderRight)
{
CRGBA borderColorR = RightColor;
if (RightStyle == CSSLineStyle::OUTSET)
borderColorR = blend(borderColorR, CRGBA::Black, 0.5f);
if (_ModulateGlobalColor)
borderColorR.modulateFromColor (borderColorR, globalColor);
borderColorR.A = (uint8) (((uint16) CurrentAlpha * (uint16) borderColorR.A) >> 8);
rVR.drawQuad(_RenderLayer, _QuadR, rVR.getBlankTextureId(), borderColorR, false);
}
if (_BorderBottom)
{
CRGBA borderColorB = BottomColor;
if (BottomStyle == CSSLineStyle::OUTSET)
borderColorB = blend(borderColorB, CRGBA::Black, 0.5f);
if (_ModulateGlobalColor)
borderColorB.modulateFromColor (borderColorB, globalColor);
borderColorB.A = (uint8) (((uint16) CurrentAlpha * (uint16) borderColorB.A) >> 8);
rVR.drawQuad(_RenderLayer, _QuadB, rVR.getBlankTextureId(), borderColorB, false);
}
if (_BorderLeft)
{
CRGBA borderColorL = LeftColor;
if (LeftStyle == CSSLineStyle::INSET)
borderColorL = blend(borderColorL, CRGBA::Black, 0.5f);
if (_ModulateGlobalColor)
borderColorL.modulateFromColor (borderColorL, globalColor);
borderColorL.A = (uint8) (((uint16) CurrentAlpha * (uint16) borderColorL.A) >> 8);
rVR.drawQuad(_RenderLayer, _QuadL, rVR.getBlankTextureId(), borderColorL, false);
}
}
}//namespace

@ -35,9 +35,9 @@ namespace NLGUI
//
// key is converted to lowercase
// value is left as is
TStyle CCssParser::parseDecls(const std::string &styleString)
TStyleVec CCssParser::parseDecls(const std::string &styleString)
{
TStyle styles;
TStyleVec styles;
std::vector<std::string> elements;
NLMISC::splitString(styleString, ";", elements);
@ -49,7 +49,7 @@ namespace NLGUI
{
std::string key = trim(toLower(elements[i].substr(0, pos)));
std::string value = trim(elements[i].substr(pos+1));
styles[key] = value;
styles.push_back(TStylePair(key, value));
}
}
@ -94,7 +94,7 @@ namespace NLGUI
std::vector<ucstring> selectors;
NLMISC::explode(selectorString, ucstring(","), selectors);
TStyle props;
TStyleVec props;
props = parseDecls(styleString.toUtf8());
// duplicate props to each selector in selector list,

@ -102,7 +102,9 @@ namespace NLGUI
}
else
{
elm.setPseudo(i->PseudoElement, i->Properties);
TStyle props;
merge(props, i->Properties);
elm.setPseudo(i->PseudoElement, props);
}
}
}
@ -110,17 +112,18 @@ namespace NLGUI
// style from "style" attribute overrides <style>
if (elm.hasNonEmptyAttribute("style"))
{
TStyle styles = CCssParser::parseDecls(elm.getAttribute("style"));
TStyleVec styles = CCssParser::parseDecls(elm.getAttribute("style"));
merge(elm.Style, styles);
}
}
void CCssStyle::merge(TStyle &dst, const TStyle &src) const
void CCssStyle::merge(TStyle &dst, const TStyleVec &src) const
{
// TODO: does not use '!important' flag
for(TStyle::const_iterator it = src.begin(); it != src.end(); ++it)
for(TStyleVec::const_iterator it = src.begin(); it != src.end(); ++it)
{
dst[it->first] = it->second;
expandShorthand(it->first, it->second, dst);
}
}
@ -304,6 +307,48 @@ namespace NLGUI
return false;
}
// ***************************************************************************
void CCssStyle::splitParams(const std::string &str, char sep, std::vector<std::string> &result) const
{
// TODO: does not handle utf8
uint32 pos = 0;
for(uint i = 0; i< str.size(); i++)
{
// split by separator first, then check if string or function
if (str[i] == sep)
{
std::string sub = trim(str.substr(pos, i - pos));
if (!sub.empty())
result.push_back(str.substr(pos, i - pos));
// skip sep
pos = i + 1;
}
else if (str[i] == '"' || str[i] == '(')
{
// string "this is string", or function rgb(1, 2, 3)
char endChar;
if (str[i] == '"')
endChar = '"';
else if (str[i] == '\'')
endChar = '\'';
else
endChar = ')';
// skip start
i++;
while(i < str.size() && str[i] != endChar)
{
if (str[i] == '\\')
i++;
i++;
}
}
}
if (pos < str.size())
result.push_back(str.substr(pos).c_str());
}
// ***************************************************************************
// CStyleParams style;
// style.FontSize; // font-size: 10px;
@ -312,7 +357,10 @@ namespace NLGUI
// style.StrikeThrough; // text-decoration: line-through; text-decoration-line: line-through;
void CCssStyle::getStyleParams(const std::string &styleString, CStyleParams &style, const CStyleParams &current) const
{
TStyle styles = CCssParser::parseDecls(styleString);
TStyleVec stylevec = CCssParser::parseDecls(styleString);
TStyle styles;
merge(styles, stylevec);
getStyleParams(styles, style, current);
}
@ -428,11 +476,6 @@ namespace NLGUI
}
}
else
if (it->first == "background")
{
parseBackgroundShorthand(it->second, style);
}
else
if (it->first == "background-repeat")
{
// old ryzom specific value
@ -440,23 +483,6 @@ namespace NLGUI
style.StyleRules[it->first] = "repeat";
}
else
if (it->first == "background-scale")
{
// replace old ryzom specific rule with background-size
if (it->second != "1")
{
style.StyleRules["background-size"] = "auto";
}
else
{
style.StyleRules["background-size"] = "100%";
}
TStyle::iterator pos = style.StyleRules.find(it->first);
if (pos != style.StyleRules.end())
style.StyleRules.erase(pos);
}
else
if (it->first == "display")
{
if (it->second == "inherit")
@ -467,6 +493,108 @@ namespace NLGUI
}
}
void CCssStyle::applyBorderWidth(const std::string &value, uint32 *dest, const uint32 currentWidth, const uint32 fontSize) const
{
if (!dest) return;
if (value == "inherit")
{
*dest = currentWidth;
}
else if (value == "thin")
{
*dest = 1;
}
else if (value == "medium")
{
*dest = 3;
}
else if (value == "thick")
{
*dest = 5;
}
else if (value == "0")
{
*dest = 0;
}
else
{
float tmpf;
std::string unit;
if (getCssLength(tmpf, unit, value.c_str()))
{
if (unit == "rem")
*dest = fontSize * tmpf;
else if (unit == "em")
*dest = fontSize * tmpf;
else if (unit == "pt")
*dest = tmpf / 0.75f;
else if (unit == "%")
*dest = 0; // no support for % in border width
else
*dest = tmpf;
}
}
}
void CCssStyle::applyBorderColor(const std::string &value, CRGBA *dest, const CRGBA &currentColor, const CRGBA &textColor) const
{
if (!dest) return;
if (value == "inherit")
*dest = currentColor;
else if (value == "transparent")
*dest = CRGBA::Transparent;
else if (value == "currentcolor")
*dest = textColor;
else
scanHTMLColor(value.c_str(), *dest);
}
void CCssStyle::applyLineStyle(const std::string &value, CSSLineStyle *dest, const CSSLineStyle &currentStyle) const
{
if (!dest) return;
if (value == "inherit")
*dest = currentStyle;
else if (value == "none")
*dest = CSSLineStyle::NONE;
else if (value == "hidden")
*dest = CSSLineStyle::HIDDEN;
else if (value == "inset")
*dest = CSSLineStyle::INSET;
else if (value == "outset")
*dest = CSSLineStyle::OUTSET;
else if (value == "solid")
*dest = CSSLineStyle::SOLID;
}
void CCssStyle::applyPaddingWidth(const std::string &value, uint32 *dest, const uint32 currentPadding, uint32 fontSize) const
{
if (!dest) return;
if (value == "inherit")
{
*dest = currentPadding;
return;
}
float tmpf;
std::string unit;
if (getCssLength(tmpf, unit, value.c_str()))
{
if (unit == "rem")
*dest = fontSize * tmpf;
else if (unit == "em")
*dest = fontSize * tmpf;
else if (unit == "pt")
*dest = tmpf / 0.75f;
else if (unit == "%")
*dest = 0; // TODO: requires content width, must remember 'unit' type
else
*dest = tmpf;
}
}
// apply style rules
void CCssStyle::apply(CStyleParams &style, const CStyleParams &current) const
{
@ -474,48 +602,22 @@ namespace NLGUI
TStyle::const_iterator it;
for (it=style.StyleRules.begin(); it != style.StyleRules.end(); ++it)
{
if (it->first == "border" || it->first == "border-width")
{
// TODO: border: 1px solid red;
if (it->second == "inherit")
{
style.BorderWidth = current.BorderWidth;
}
else if (it->second == "none")
{
style.BorderWidth = 0;
}
else if (it->second == "thin")
{
style.BorderWidth = 1;
}
else if (it->second == "medium")
{
style.BorderWidth = 3;
}
else if (it->second == "thick")
{
style.BorderWidth = 5;
}
else
{
float tmpf;
std::string unit;
if (getCssLength(tmpf, unit, it->second.c_str()))
{
if (unit == "rem")
style.BorderWidth = Root.FontSize * tmpf;
else if (unit == "em")
style.BorderWidth = current.FontSize * tmpf;
else if (unit == "pt")
style.BorderWidth = tmpf / 0.75f;
else if (unit == "%")
style.BorderWidth = 0; // no support for % in border width
else
style.BorderWidth = tmpf;
}
}
}
if (it->first == "border-top-width") applyBorderWidth(it->second, &style.BorderTopWidth, current.BorderTopWidth, current.FontSize);
else if (it->first == "border-top-color") applyBorderColor(it->second, &style.BorderTopColor, current.BorderTopColor, current.TextColor);
else if (it->first == "border-top-style") applyLineStyle(it->second, &style.BorderTopStyle, current.BorderTopStyle);
else if (it->first == "border-right-width") applyBorderWidth(it->second, &style.BorderRightWidth, current.BorderRightWidth, current.FontSize);
else if (it->first == "border-right-color") applyBorderColor(it->second, &style.BorderRightColor, current.BorderRightColor, current.TextColor);
else if (it->first == "border-right-style") applyLineStyle(it->second, &style.BorderRightStyle, current.BorderRightStyle);
else if (it->first == "border-bottom-width") applyBorderWidth(it->second, &style.BorderBottomWidth, current.BorderBottomWidth, current.FontSize);
else if (it->first == "border-bottom-color") applyBorderColor(it->second, &style.BorderBottomColor, current.BorderBottomColor, current.TextColor);
else if (it->first == "border-bottom-style") applyLineStyle(it->second, &style.BorderBottomStyle, current.BorderBottomStyle);
else if (it->first == "border-left-width") applyBorderWidth(it->second, &style.BorderLeftWidth, current.BorderLeftWidth, current.FontSize);
else if (it->first == "border-left-color") applyBorderColor(it->second, &style.BorderLeftColor, current.BorderLeftColor, current.TextColor);
else if (it->first == "border-left-style") applyLineStyle(it->second, &style.BorderLeftStyle, current.BorderLeftStyle);
else if (it->first == "padding-top") applyPaddingWidth(it->second, &style.PaddingTop, current.PaddingTop, current.FontSize);
else if (it->first == "padding-right") applyPaddingWidth(it->second, &style.PaddingRight, current.PaddingRight, current.FontSize);
else if (it->first == "padding-bottom") applyPaddingWidth(it->second, &style.PaddingBottom, current.PaddingBottom, current.FontSize);
else if (it->first == "padding-left") applyPaddingWidth(it->second, &style.PaddingLeft, current.PaddingLeft, current.FontSize);
else
if (it->first == "font-style")
{
@ -586,7 +688,7 @@ namespace NLGUI
uint px = 0;
CRGBA color;
std::vector<std::string> parts;
NLMISC::splitString(it->second, " ", parts);
splitParams(it->second, ' ', parts);
if (parts.size() == 1)
{
success = scanCssLength(parts[0], px);
@ -635,7 +737,7 @@ namespace NLGUI
prop = prop.substr(0, pos);
std::vector<std::string> parts;
NLMISC::splitString(prop, " ", parts);
splitParams(prop, ' ', parts);
switch(parts.size())
{
case 1:
@ -834,7 +936,7 @@ namespace NLGUI
// normalize
std::string val = toLower(trim(it->second));
std::vector<std::string> parts;
NLMISC::splitString(val, " ", parts);
splitParams(val, ' ', parts);
// check for "repeat repeat"
if (parts.size() == 2 && parts[0] == parts[1])
val = parts[0];
@ -847,7 +949,7 @@ namespace NLGUI
// normalize
std::string val = toLower(trim(it->second));
std::vector<std::string> parts;
NLMISC::splitString(val, " ", parts);
splitParams(val, ' ', parts);
if (parts.size() == 2 && parts[0] == parts[1])
val = parts[0];
@ -864,7 +966,8 @@ namespace NLGUI
style.StrikeThrough = current.StrikeThrough;
}
void CCssStyle::parseBackgroundShorthand(const std::string &value, CStyleParams &style) const
// ***************************************************************************
void CCssStyle::expandBackgroundShorthand(const std::string &value, TStyle &style) const
{
// background: url(image.jpg) top center / 200px 200px no-repeat fixed padding-box content-box red;
// background-image : url(image.jpg)
@ -889,9 +992,7 @@ namespace NLGUI
uint partIndex = 0;
std::vector<std::string> parts;
std::vector<std::string>::iterator it;
// FIXME: this will fail if url() contains ' ' chars
// FIXME: this will also fail on 'background: rgb(255, 0, 0)'
NLMISC::splitString(value, " ", parts);
splitParams(value, ' ', parts);
bool failed = false;
bool allowSize = false;
@ -1142,16 +1243,16 @@ namespace NLGUI
{
if (props[i] == "background-position")
{
style.StyleRules["background-position-x"] = bgPositionX;
style.StyleRules["background-position-y"] = bgPositionY;
style["background-position-x"] = bgPositionX;
style["background-position-y"] = bgPositionY;
}
else if (props[i] == "background-clip")
{
style.StyleRules["background-clip"] = bgClipValue;
style["background-clip"] = bgClipValue;
}
else
{
style.StyleRules[props[i]] = values[i];
style[props[i]] = values[i];
}
}
else
@ -1159,42 +1260,343 @@ namespace NLGUI
// fill in default if one is set
if (props[i] == "background-image")
{
style.StyleRules[props[i]] = "none";
style[props[i]] = "none";
}
else if (props[i] == "background-position")
{
style.StyleRules[props[i]] = "0% 0%";
style.StyleRules["background-position-x"] = "left 0%";
style.StyleRules["background-position-y"] = "top 0%";
style[props[i]] = "0% 0%";
style["background-position-x"] = "left 0%";
style["background-position-y"] = "top 0%";
}
else if (props[i] == "background-size")
{
style.StyleRules[props[i]] = "auto auto";
style[props[i]] = "auto auto";
}
else if (props[i] == "background-repeat")
{
style.StyleRules[props[i]] = "repeat";
style[props[i]] = "repeat";
}
else if(props[i] == "background-attachment")
{
style.StyleRules[props[i]] = "scroll";
style[props[i]] = "scroll";
}
else if(props[i] == "background-origin")
{
style.StyleRules[props[i]] = "padding-box";
style[props[i]] = "padding-box";
}
else if (props[i] == "background-clip")
{
if (bgClipFound)
style.StyleRules[props[i]] = bgClipValue;
style[props[i]] = bgClipValue;
else
style.StyleRules[props[i]] = "border-box";
style[props[i]] = "border-box";
}
else if (props[i] == "background-color")
{
style.StyleRules[props[i]] = "transparent";
style[props[i]] = "transparent";
}
}
}
}
// ***************************************************************************
bool CCssStyle::getShorthandIndices(const uint32 size, uint8 &t, uint8 &r, uint8 &b, uint8 &l) const
{
if (size == 0 || size > 4) return false;
if (size == 1)
{
t = r = b = l = 0;
}
else if (size == 2)
{
t = b = 0;
r = l = 1;
}
else if (size == 3)
{
t = 0;
r = l = 1;
b = 2;
}
else // size == 4
{
t = 0;
r = 1;
b = 2;
l = 3;
}
return true;
}
// ***************************************************************************
bool CCssStyle::tryBorderWidthShorthand(const std::string &prop, const std::string &value, TStyle &style) const
{
std::vector<std::string> parts;
splitParams(toLower(value), ' ', parts);
float tmpf;
std::string unit;
// verify that parts are valid
uint8 maxSize = (prop == "border" || prop == "border-width") ? 4 : 1;
bool hasTop = (prop == "border" || prop == "border-width" || prop == "border-top" || prop == "border-top-width");
bool hasRight = (prop == "border" || prop == "border-width" || prop == "border-right" || prop == "border-right-width");
bool hasBottom = (prop == "border" || prop == "border-width" || prop == "border-bottom" || prop == "border-bottom-width");
bool hasLeft = (prop == "border" || prop == "border-width" || prop == "border-left" || prop == "border-left-width");
if (parts.size() > maxSize || (!hasTop && !hasRight && !hasBottom && !hasLeft))
{
return false;
}
for(uint i = 0; i< parts.size(); ++i)
{
if (parts[i] != "inherit" && parts[i] != "thin" && parts[i] != "medium" && parts[i] != "thick"
&& !getCssLength(tmpf, unit, parts[i].c_str()))
{
return false;
}
}
uint8 t, r, b, l;
if (!getShorthandIndices(parts.size(), t, r, b, l)) return false;
if (hasTop) style["border-top-width"] = parts[t];
if (hasRight) style["border-right-width"] = parts[r];
if (hasBottom) style["border-bottom-width"] = parts[b];
if (hasLeft) style["border-left-width"] = parts[l];
return true;
}
// ***************************************************************************
bool CCssStyle::tryBorderStyleShorthand(const std::string &prop, const std::string &value, TStyle &style) const
{
std::vector<std::string> parts;
splitParams(toLower(value), ' ', parts);
// verify that parts are valid
uint8 maxSize = (prop == "border" || prop == "border-style") ? 4 : 1;
bool hasTop = (prop == "border" || prop == "border-style" || prop == "border-top" || prop == "border-top-style");
bool hasRight = (prop == "border" || prop == "border-style" || prop == "border-right" || prop == "border-right-style");
bool hasBottom = (prop == "border" || prop == "border-style" || prop == "border-bottom" || prop == "border-bottom-style");
bool hasLeft = (prop == "border" || prop == "border-style" || prop == "border-left" || prop == "border-left-style");
if (parts.size() > maxSize || (!hasTop && !hasRight && !hasBottom && !hasLeft))
{
return false;
}
const uint nbValues = 10;
std::string values[nbValues] = {"none", "hidden", "dotted", "dashed",
"solid", "double", "groove", "ridge", "inset", "outset"};
for(uint i = 0; i < parts.size(); ++i)
{
bool found = false;
for(uint iValue = 0; iValue < nbValues; ++iValue)
{
if (parts[i] == values[iValue])
{
found = true;
break;
}
}
if (!found)
{
// invalid rule
return false;
}
}
uint8 t, r, b, l;
if (!getShorthandIndices(parts.size(), t, r, b, l)) return false;
if (hasTop) style["border-top-style"] = parts[t];
if (hasRight) style["border-right-style"] = parts[r];
if (hasBottom) style["border-bottom-style"] = parts[b];
if (hasLeft) style["border-left-style"] = parts[l];
return true;
}
// ***************************************************************************
bool CCssStyle::tryBorderColorShorthand(const std::string &prop, const std::string &value, TStyle &style) const
{
std::vector<std::string> parts;
splitParams(toLower(value), ' ', parts);
CRGBA color;
// verify that parts are valid
uint8 maxSize = (prop == "border" || prop == "border-color") ? 4 : 1;
bool hasTop = (prop == "border" || prop == "border-color" || prop == "border-top" || prop == "border-top-color");
bool hasRight = (prop == "border" || prop == "border-color" || prop == "border-right" || prop == "border-right-color");
bool hasBottom = (prop == "border" || prop == "border-color" || prop == "border-bottom" || prop == "border-bottom-color");
bool hasLeft = (prop == "border" || prop == "border-color" || prop == "border-left" || prop == "border-left-color");
if (parts.size() > maxSize || (!hasTop && !hasRight && !hasBottom && !hasLeft))
{
return false;
}
for(uint i = 0; i< parts.size(); ++i)
{
if (!scanHTMLColor(parts[i].c_str(), color) && parts[i] != "currentcolor" && parts[i] != "inherit")
return false;
}
uint8 t, r, b, l;
if (!getShorthandIndices(parts.size(), t, r, b, l)) return false;
if (hasTop) style["border-top-color"] = parts[t];
if (hasRight) style["border-right-color"] = parts[r];
if (hasBottom) style["border-bottom-color"] = parts[b];
if (hasLeft) style["border-left-color"] = parts[l];
return true;
}
// ***************************************************************************
void CCssStyle::expandBorderShorthand(const std::string &prop, const std::string &value, TStyle &style) const
{
// border: 1px solid #000;
bool hasTop = (prop == "border" || prop == "border-top");
bool hasRight = (prop == "border" || prop == "border-right");
bool hasBottom = (prop == "border" || prop == "border-bottom");
bool hasLeft = (prop == "border" || prop == "border-left");
bool foundWidth = false;
bool foundStyle = false;
bool foundColor = false;
TStyle borderStyle;
std::vector<std::string> parts;
splitParams(toLower(value), ' ', parts);
for(uint index = 0; index < parts.size(); ++index)
{
bool matched = false;
if (!foundWidth)
{
matched = foundWidth = tryBorderWidthShorthand(prop, parts[index], borderStyle);
}
if (!matched && !foundStyle)
{
matched = foundStyle = tryBorderStyleShorthand(prop, parts[index], borderStyle);
}
if (!matched && !foundColor)
{
matched = foundColor = tryBorderColorShorthand(prop, parts[index], borderStyle);
}
// invalid rule if nothing gets matched
if (!matched)
{
return;
}
}
// apply rules that are present
TStyle::const_iterator it = borderStyle.begin();
while(it != borderStyle.end())
{
style[it->first] = it->second;
++it;
}
// reset those not present
if (!foundWidth)
{
if (hasTop) style["border-top-width"] = "medium";
if (hasRight) style["border-right-width"] = "medium";
if (hasBottom) style["border-bottom-width"] = "medium";
if (hasLeft) style["border-left-width"] = "medium";
}
//
if (!foundStyle)
{
if (hasTop) style["border-top-style"] = "none";
if (hasRight) style["border-right-style"] = "none";
if (hasBottom) style["border-bottom-style"] = "none";
if (hasLeft) style["border-left-style"] = "none";
}
//
if (!foundColor)
{
if (hasTop) style["border-top-color"] = "currentcolor";
if (hasRight) style["border-right-color"] = "currentcolor";
if (hasBottom) style["border-bottom-color"] = "currentcolor";
if (hasLeft) style["border-left-color"] = "currentcolor";
}
}
// ***************************************************************************
void CCssStyle::expandPaddingShorthand(const std::string &value, TStyle &style) const
{
std::vector<std::string> parts;
splitParams(toLower(value), ' ', parts);
uint8 t, r, b, l;
if (!getShorthandIndices(parts.size(), t, r, b, l))
return;
style["padding-top"] = parts[t];
style["padding-right"] = parts[r];
style["padding-bottom"] = parts[b];
style["padding-left"] = parts[l];
}
// ***************************************************************************
void CCssStyle::expandShorthand(const std::string &prop, const std::string &value, TStyle &style) const
{
// if shorthand matches, then remove it after expansion
bool keep = false;
if (prop == "background")
{
expandBackgroundShorthand(value, style);
}
else if (prop == "background-scale")
{
// replace old ryzom specific rule with background-size
if (value != "1")
{
style["background-size"] = "auto";
}
else
{
style["background-size"] = "100%";
}
}
else if (prop == "border"
|| prop == "border-top" || prop == "border-right"
|| prop == "border-bottom" || prop == "border-left")
{
// TODO: use enum or bitmap constant instead of passing a string name (prop)
expandBorderShorthand(prop, value, style);
}
else if (prop == "border-width")
{
tryBorderWidthShorthand(prop, value, style);
}
else if (prop == "border-style")
{
tryBorderStyleShorthand(prop, value, style);
}
else if (prop == "border-color")
{
tryBorderColorShorthand(prop, value, style);
}
else if (prop == "padding")
{
expandPaddingShorthand(value, style);
}
else
{
keep = true;
}
if (!keep)
{
TStyle::iterator pos = style.find(prop);
if (pos != style.end())
style.erase(pos);
}
}

@ -52,6 +52,7 @@
#include "nel/gui/html_element.h"
#include "nel/gui/css_style.h"
#include "nel/gui/css_parser.h"
#include "nel/gui/css_border_renderer.h"
#include <curl/curl.h>
@ -286,28 +287,38 @@ namespace NLGUI
{
btn->setTextureOver(file);
}
return;
}
else
CViewBitmap *btm = dynamic_cast<CViewBitmap*>(view);
if(btm)
{
CViewBitmap *btm = dynamic_cast<CViewBitmap*>(view);
if(btm)
{
btm->setTexture (file);
btm->invalidateCoords();
btm->invalidateContent();
paragraphChange();
}
else
{
CGroupCell *btgc = dynamic_cast<CGroupCell*>(view);
if(btgc)
{
btgc->setTexture (file);
btgc->invalidateCoords();
btgc->invalidateContent();
paragraphChange();
}
}
btm->setTexture (file);
btm->invalidateCoords();
btm->invalidateContent();
paragraphChange();
return;
}
CGroupCell *btgc = dynamic_cast<CGroupCell*>(view);
if(btgc)
{
btgc->setTexture (file);
btgc->invalidateCoords();
btgc->invalidateContent();
paragraphChange();
return;
}
CGroupTable *table = dynamic_cast<CGroupTable*>(view);
if (table)
{
table->setTexture(file);
return;
}
}
@ -433,10 +444,9 @@ namespace NLGUI
{
if (pVT)
{
pVT->setFontSize(style.FontSize);
pVT->setColor(style.TextColor);
pVT->setFontName(style.FontFamily);
pVT->setFontSize(style.FontSize);
pVT->setFontSize(style.FontSize, false);
pVT->setEmbolden(style.FontWeight >= FONT_WEIGHT_BOLD);
pVT->setOblique(style.FontOblique);
pVT->setUnderlined(style.Underlined);
@ -697,7 +707,7 @@ namespace NLGUI
}
// Add a image download request in the multi_curl
void CGroupHTML::addImageDownload(const string &url, CViewBase *img, const CStyleParams &style, TImageType type)
void CGroupHTML::addImageDownload(const string &url, CViewBase *img, const CStyleParams &style, TImageType type, const std::string &placeholder)
{
std::string finalUrl;
img->setModulateGlobalColor(style.GlobalColor);
@ -723,8 +733,7 @@ namespace NLGUI
std::string temp = dest;
if (!CFile::fileExists(temp))
{
// TODO: placeholder
temp = "web_del.tga";
temp = placeholder;
}
setImage(img, temp, type);
setImageSize(img, style);
@ -1144,8 +1153,10 @@ namespace NLGUI
case HTML_STRONG: renderPseudoElement(":before", elm); break;
case HTML_STYLE: htmlSTYLE(elm); break;
case HTML_TABLE: htmlTABLE(elm); break;
case HTML_TBODY: renderPseudoElement(":before", elm); break;
case HTML_TD: htmlTD(elm); break;
case HTML_TEXTAREA: htmlTEXTAREA(elm); break;
case HTML_TFOOT: renderPseudoElement(":before", elm); break;
case HTML_TH: htmlTH(elm); break;
case HTML_TITLE: htmlTITLE(elm); break;
case HTML_TR: htmlTR(elm); break;
@ -1206,7 +1217,9 @@ namespace NLGUI
case HTML_STYLE: htmlSTYLEend(elm); break;
case HTML_TABLE: htmlTABLEend(elm); break;
case HTML_TD: htmlTDend(elm); break;
case HTML_TBODY: renderPseudoElement(":after", elm); break;
case HTML_TEXTAREA: htmlTEXTAREAend(elm); break;
case HTML_TFOOT: renderPseudoElement(":after", elm); break;
case HTML_TH: htmlTHend(elm); break;
case HTML_TITLE: htmlTITLEend(elm); break;
case HTML_TR: htmlTRend(elm); break;
@ -1493,6 +1506,9 @@ namespace NLGUI
initImageDownload();
initBnpDownload();
// setup default browser style
setProperty("browser_css_file", "browser.css");
}
// ***************************************************************************
@ -1771,6 +1787,11 @@ namespace NLGUI
{
return toString( _TimeoutValue );
}
else
if( name == "browser_css_file" )
{
return _BrowserCssFile;
}
else
return CGroupScrollText::getProperty( name );
}
@ -2144,6 +2165,36 @@ namespace NLGUI
_TimeoutValue = d;
return;
}
else
if( name == "browser_css_file")
{
_BrowserStyle.reset();
_BrowserCssFile = value;
if (!_BrowserCssFile.empty())
{
std::string filename = CPath::lookup(_BrowserCssFile, false, true, true);
if (!filename.empty())
{
CIFile in;
if (in.open(filename))
{
std::string css;
if (in.readAll(css))
_BrowserStyle.parseStylesheet(css);
else
nlwarning("Failed to read browser css from '%s'", filename.c_str());
}
else
{
nlwarning("Failed to open browser css file '%s'", filename.c_str());
}
}
else
{
nlwarning("Browser css file '%s' not found", _BrowserCssFile.c_str());
}
}
}
else
CGroupScrollText::setProperty( name, value );
}
@ -2217,6 +2268,7 @@ namespace NLGUI
xmlSetProp( node, BAD_CAST "browse_redo", BAD_CAST _BrowseRedoButton.c_str() );
xmlSetProp( node, BAD_CAST "browse_refresh", BAD_CAST _BrowseRefreshButton.c_str() );
xmlSetProp( node, BAD_CAST "timeout", BAD_CAST toString( _TimeoutValue ).c_str() );
xmlSetProp( node, BAD_CAST "browser_css_file", BAD_CAST _BrowserCssFile.c_str() );
return node;
}
@ -2400,6 +2452,12 @@ namespace NLGUI
if(ptr)
fromString((const char*)ptr, _TimeoutValue);
ptr = xmlGetProp (cur, (xmlChar*)"browser_css_file");
if (ptr)
{
setProperty("browser_css_file", (const char *)ptr);
}
return true;
}
@ -2597,31 +2655,49 @@ namespace NLGUI
// Keep this char ?
bool keep = true;
// char is between table elements
// TODO: only whitespace is handled, text is added to either TD, or after TABLE (should be before)
bool tableWhitespace = getTable() && (_Cells.empty() || _Cells.back() == NULL);
switch (input)
{
// Return / tab only in <PRE> mode
case '\t':
case '\n':
{
// Get the last char
ucchar lastChar = lastCharParam;
if (lastChar == 0)
lastChar = getLastChar();
keep = ((lastChar != (ucchar)' ') &&
(lastChar != 0)) || getPRE() || (_CurrentViewImage && (lastChar == 0));
if(!getPRE())
input = ' ';
if (tableWhitespace)
{
keep = false;
}
else
{
// Get the last char
ucchar lastChar = lastCharParam;
if (lastChar == 0)
lastChar = getLastChar();
keep = ((lastChar != (ucchar)' ') &&
(lastChar != 0)) || getPRE() || (_CurrentViewImage && (lastChar == 0));
if(!getPRE())
input = ' ';
}
}
break;
case ' ':
{
// Get the last char
ucchar lastChar = lastCharParam;
if (lastChar == 0)
lastChar = getLastChar();
keep = ((lastChar != (ucchar)' ') &&
(lastChar != (ucchar)'\n') &&
(lastChar != 0)) || getPRE() || (_CurrentViewImage && (lastChar == 0));
if (tableWhitespace)
{
keep = false;
}
else
{
// Get the last char
ucchar lastChar = lastCharParam;
if (lastChar == 0)
lastChar = getLastChar();
keep = ((lastChar != (ucchar)' ') &&
(lastChar != (ucchar)'\n') &&
(lastChar != 0)) || getPRE() || (_CurrentViewImage && (lastChar == 0));
}
}
break;
case 0xd:
@ -3407,6 +3483,7 @@ namespace NLGUI
CViewBitmap *bitmap = dynamic_cast<CViewBitmap*> (view);
if (bitmap)
{
// TODO: background color should have separate bitmap from background texture
// Change the background color
bitmap->setColor (bgcolor);
bitmap->setModulateGlobalColor(false);
@ -3429,6 +3506,7 @@ namespace NLGUI
bitmap->setPosRef(Hotspot_TL);
bitmap->setX(0);
bitmap->setY(0);
// FIXME: renders behind container background
bitmap->setRenderLayer(-2);
bitmap->setScale(scale);
bitmap->setTile(tile);
@ -3439,7 +3517,7 @@ namespace NLGUI
else
bitmap->setSizeRef("");
addImageDownload(bgtex, view);
addImageDownload(bgtex, view, CStyleParams(), TImageType::NormalImage, "");
}
}
}
@ -4924,49 +5002,7 @@ namespace NLGUI
_WaitingForStylesheet = false;
_StylesheetQueue.clear();
_Style.reset();
std::string css;
// TODO: browser css
css += "html { background-color: " + getRGBAString(BgColor) + "; color: " + getRGBAString(TextColor) + "; font-size: " + toString(TextFontSize) + "px;}";
css += "a { color: " + getRGBAString(LinkColor) + "; text-decoration: underline; -ryzom-modulate-color: "+toString(LinkColorGlobalColor)+";}";
css += "h1 { color: " + getRGBAString(H1Color) + "; font-size: "+ toString("%d", H1FontSize) + "px; -ryzom-modulate-color: "+toString(H1ColorGlobalColor)+";}";
css += "h2 { color: " + getRGBAString(H2Color) + "; font-size: "+ toString("%d", H2FontSize) + "px; -ryzom-modulate-color: "+toString(H2ColorGlobalColor)+";}";
css += "h3 { color: " + getRGBAString(H3Color) + "; font-size: "+ toString("%d", H3FontSize) + "px; -ryzom-modulate-color: "+toString(H3ColorGlobalColor)+";}";
css += "h4 { color: " + getRGBAString(H4Color) + "; font-size: "+ toString("%d", H4FontSize) + "px; -ryzom-modulate-color: "+toString(H4ColorGlobalColor)+";}";
css += "h5 { color: " + getRGBAString(H5Color) + "; font-size: "+ toString("%d", H5FontSize) + "px; -ryzom-modulate-color: "+toString(H5ColorGlobalColor)+";}";
css += "h6 { color: " + getRGBAString(H6Color) + "; font-size: "+ toString("%d", H6FontSize) + "px; -ryzom-modulate-color: "+toString(H6ColorGlobalColor)+";}";
css += "input[type=\"text\"] { color: " + getRGBAString(TextColor) + "; font-size: " + toString("%d", TextFontSize) + "px; font-weight: normal; text-shadow: 1px 1px #000;}";
css += "pre { font-family: monospace;}";
// th { text-align: center; } - overwrites align property
css += "th { font-weight: bold; }";
css += "textarea { color: " + getRGBAString(TextColor) + "; font-weight: normal; font-size: " + toString("%d", TextFontSize) + "px; text-shadow: 1px 1px #000;}";
css += "del { text-decoration: line-through;}";
css += "u { text-decoration: underline;}";
css += "em { font-style: italic; }";
css += "strong { font-weight: bold; }";
css += "small { font-size: smaller;}";
css += "dt { font-weight: bold; }";
css += "hr { color: rgb(120, 120, 120);}";
// block level elements
css += "address, article, aside, blockquote, details, dialog, dd, div, dl, dt, fieldset, figcaption, figure,";
css += "footer, form, h1, h2, h3, h4, h5, h6, header, hgroup, hr, li, main, nav, ol, p, pre, section, table,";
css += "ul { display: block; }";
css += "table { display: table; }";
// 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); }";
// webkit pseudo elements
css += "progress::-webkit-progress-bar, progress::-webkit-progress-value { background: none; }";
css += "progress::-webkit-progress-bar { background-color: rgb(230, 230, 230); width: 10em; height: 1em; }";
css += "progress::-webkit-progress-value { background-color: rgb(0, 100, 180);}";
_Style.parseStylesheet(css);
_Style = _BrowserStyle;
}
// ***************************************************************************
@ -5245,9 +5281,7 @@ namespace NLGUI
{
CGroupHTML::CCellParams cellParams;
if (!_CellParams.empty() && inherit)
{
cellParams = _CellParams.back();
}
if (_Style.hasStyle("background-color"))
cellParams.BgColor = _Style.Current.BackgroundColor;
@ -5260,6 +5294,11 @@ namespace NLGUI
if (elm.hasNonEmptyAttribute("l_margin"))
fromString(elm.getAttribute("l_margin"), cellParams.LeftMargin);
if (_Style.hasStyle("height"))
cellParams.Height = _Style.Current.Height;
else if (elm.hasNonEmptyAttribute("height"))
fromString(elm.getAttribute("height"), cellParams.Height);
{
std::string align;
// having text-align on table/tr should not override td align attribute
@ -5989,16 +6028,20 @@ namespace NLGUI
ucstring ucValue;
ucValue.fromUtf8(elm.getAttribute("value"));
uint size = 120;
uint size = 20;
uint maxlength = 1024;
if (elm.hasNonEmptyAttribute("size"))
fromString(elm.getAttribute("size"), size);
if (elm.hasNonEmptyAttribute("maxlength"))
fromString(elm.getAttribute("maxlength"), maxlength);
// ryzom client used to have 'size' attribute in pixels, (12 == was default font size)
if (_Style.hasStyle("-ryzom-input-size-px") && _Style.getStyle("-ryzom-input-size-px") == "true")
size = size / 12;
string textTemplate(!templateName.empty() ? templateName : DefaultFormTextGroup);
// Add the editbox
CInterfaceGroup *textArea = addTextArea (textTemplate, name.c_str (), 1, size/12, false, ucValue, maxlength);
CInterfaceGroup *textArea = addTextArea (textTemplate, name.c_str (), 1, size, false, ucValue, maxlength);
if (textArea)
{
// Add the text area to the form
@ -6213,7 +6256,8 @@ namespace NLGUI
// 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;
// FIXME: only using border-top
uint32 border = _Style.Current.BorderTopWidth > -1 ? _Style.Current.BorderTopWidth : 0;
uint barw = (uint) (width * meter.getValueRatio());
CRGBA bgColor = meter.getBarColor(elm, _Style);
@ -6428,7 +6472,8 @@ namespace NLGUI
// width: 10em, height: 1em
uint32 width = _Style.Current.Width > -1 ? _Style.Current.Width : _Style.Current.FontSize * 10;
uint32 height = _Style.Current.Height > -1 ? _Style.Current.Height : _Style.Current.FontSize;
uint32 border = _Style.Current.BorderWidth > -1 ? _Style.Current.BorderWidth : 0;
// FIXME: only using border-top
uint32 border = _Style.Current.BorderTopWidth > -1 ? _Style.Current.BorderTopWidth : 0;
uint barw = (uint) (width * progress.getValueRatio());
CRGBA bgColor = progress.getBarColor(elm, _Style);
@ -6503,7 +6548,7 @@ namespace NLGUI
sb->setMinH(_Style.Current.Height);
sb->setMaxVisibleLine(size);
sb->setFontSize(_Style.Current.FontSize);
sb->setFontSize(_Style.Current.FontSize, false);
}
entry.SelectBox = sb;
@ -6576,36 +6621,82 @@ namespace NLGUI
fromString(elm.getAttribute("cellpadding"), table->CellPadding);
if (_Style.hasStyle("width"))
getPercentage(table->ForceWidthMin, table->TableRatio, _Style.getStyle("width").c_str());
else if (elm.hasNonEmptyAttribute("width"))
getPercentage (table->ForceWidthMin, table->TableRatio, elm.getAttribute("width").c_str());
if (_Style.hasStyle("border") || _Style.hasStyle("border-width"))
{
table->Border = _Style.Current.BorderWidth;
// _Style.Width does not handle '%' unit currently
if (_Style.Current.Width > 0)
{
table->ForceWidthMin = _Style.Current.Width;
table->TableRatio = 0;
}
else
{
getPercentage (table->ForceWidthMin, table->TableRatio, _Style.getStyle("width").c_str());
}
}
else if (elm.hasAttribute("border"))
else if (elm.hasNonEmptyAttribute("width"))
{
std::string s = elm.getAttribute("border");
if (s.empty())
table->Border = 1;
else
fromString(elm.getAttribute("border"), table->Border);
getPercentage (table->ForceWidthMin, table->TableRatio, elm.getAttribute("width").c_str());
}
if (_Style.hasStyle("border-color"))
// border from css or from attribute
{
std::string s = toLower(_Style.getStyle("border-color"));
if (s == "currentcolor")
table->BorderColor = _Style.Current.TextColor;
uint32 borderWidth = 0;
CRGBA borderColor = CRGBA::Transparent;
if (elm.hasAttribute("border"))
{
std::string s = elm.getAttribute("border");
if (s.empty())
borderWidth = 1;
else
fromString(elm.getAttribute("border"), borderWidth);
if (elm.hasNonEmptyAttribute("bordercolor"))
scanHTMLColor(elm.getAttribute("bordercolor").c_str(), borderColor);
else
borderColor = CRGBA(128, 128, 128, 255);
table->CellBorder = (borderWidth > 0);
table->Border->setWidth(borderWidth, borderWidth, borderWidth, borderWidth);
table->Border->setColor(borderColor, borderColor, borderColor, borderColor);
table->Border->setStyle(CSSLineStyle::OUTSET, CSSLineStyle::OUTSET, CSSLineStyle::OUTSET, CSSLineStyle::OUTSET);
}
else
scanHTMLColor(s.c_str(), table->BorderColor);
{
table->CellBorder = false;
}
if (_Style.hasStyle("border-top-width")) table->Border->TopWidth = _Style.Current.BorderTopWidth;
if (_Style.hasStyle("border-right-width")) table->Border->RightWidth = _Style.Current.BorderRightWidth;
if (_Style.hasStyle("border-bottom-width")) table->Border->BottomWidth = _Style.Current.BorderBottomWidth;
if (_Style.hasStyle("border-left-width")) table->Border->LeftWidth = _Style.Current.BorderLeftWidth;
if (_Style.hasStyle("border-top-color")) table->Border->TopColor = _Style.Current.BorderTopColor;
if (_Style.hasStyle("border-right-color")) table->Border->RightColor = _Style.Current.BorderRightColor;
if (_Style.hasStyle("border-bottom-color")) table->Border->BottomColor = _Style.Current.BorderBottomColor;
if (_Style.hasStyle("border-left-color")) table->Border->LeftColor = _Style.Current.BorderLeftColor;
if (_Style.hasStyle("border-top-style")) table->Border->TopStyle = _Style.Current.BorderTopStyle;
if (_Style.hasStyle("border-right-style")) table->Border->RightStyle = _Style.Current.BorderRightStyle;
if (_Style.hasStyle("border-bottom-style")) table->Border->BottomStyle = _Style.Current.BorderBottomStyle;
if (_Style.hasStyle("border-left-style")) table->Border->LeftStyle = _Style.Current.BorderLeftStyle;
}
else if (elm.hasNonEmptyAttribute("bordercolor"))
if (_Style.hasStyle("background-image"))
{
scanHTMLColor(elm.getAttribute("bordercolor").c_str(), table->BorderColor);
if (_Style.checkStyle("background-repeat", "repeat"))
table->setTextureTile(true);
if (_Style.checkStyle("background-size", "100%"))
table->setTextureScale(true);
string image = _Style.getStyle("background-image");
addImageDownload(image, table, CStyleParams(), TImageType::NormalImage, "");
}
// setting ModulateGlobalColor must be after addImageDownload
if (_Style.checkStyle("-ryzom-modulate-bgcolor", "true"))
table->setModulateGlobalColor(true);
table->setMarginLeft(getIndent());
addHtmlGroup (table, 0);
@ -6633,9 +6724,21 @@ namespace NLGUI
// ***************************************************************************
void CGroupHTML::htmlTD(const CHtmlElement &elm)
{
CRGBA rowColor = CRGBA::Transparent;
// remember row color so we can blend it with cell color
if (!_CellParams.empty())
rowColor = _CellParams.back().BgColor;
// Get cells parameters
getCellsParameters(elm, true);
// if cell has own background,then it must be blended with row
if (rowColor.A > 0 && (elm.hasNonEmptyAttribute("bgcolor") || _Style.hasStyle("background-color")))
{
if (_CellParams.back().BgColor.A < 255)
_CellParams.back().BgColor.blendFromui(rowColor, _CellParams.back().BgColor, _CellParams.back().BgColor.A);
}
if (elm.ID == HTML_TH)
{
if (!_Style.hasStyle("font-weight"))
@ -6658,14 +6761,6 @@ namespace NLGUI
return;
}
if (_Style.hasStyle("padding"))
{
uint32 a;
// TODO: cssLength
if (fromString(_Style.getStyle("padding"), a))
table->CellPadding = a;
}
_Cells.back() = new CGroupCell(CViewBase::TCtorParam());
if (_Style.checkStyle("background-repeat", "repeat"))
@ -6677,7 +6772,7 @@ namespace NLGUI
if (_Style.hasStyle("background-image"))
{
string image = _Style.getStyle("background-image");
addImageDownload(image, _Cells.back());
addImageDownload(image, _Cells.back(), CStyleParams(), TImageType::NormalImage, "");
}
if (elm.hasNonEmptyAttribute("colspan"))
@ -6692,19 +6787,70 @@ namespace NLGUI
_Cells.back()->NoWrap = _CellParams.back().NoWrap;
_Cells.back()->ColSpan = std::max(1, _Cells.back()->ColSpan);
_Cells.back()->RowSpan = std::max(1, _Cells.back()->RowSpan);
_Cells.back()->Height = _CellParams.back().Height;
float temp;
if (_Style.hasStyle("width"))
getPercentage (_Cells.back()->WidthWanted, _Cells.back()->TableRatio, _Style.getStyle("width").c_str());
{
// _Style.Width does not handle '%' unit currently
if (_Style.Current.Width > 0)
{
_Cells.back()->WidthWanted = _Style.Current.Width;
_Cells.back()->TableRatio = 0;
}
else
{
getPercentage (_Cells.back()->WidthWanted, _Cells.back()->TableRatio, _Style.getStyle("width").c_str());
}
}
else if (elm.hasNonEmptyAttribute("width"))
{
getPercentage (_Cells.back()->WidthWanted, _Cells.back()->TableRatio, elm.getAttribute("width").c_str());
if (_Style.hasStyle("height"))
getPercentage (_Cells.back()->Height, temp, _Style.getStyle("height").c_str());
else if (elm.hasNonEmptyAttribute("height"))
getPercentage (_Cells.back()->Height, temp, elm.getAttribute("height").c_str());
}
_Cells.back()->NewLine = getTR();
// setting ModulateGlobalColor must be after addImageDownload
if (_Style.checkStyle("-ryzom-modulate-bgcolor", "true"))
_Cells.back()->setModulateGlobalColor(true);
// border from <table border="1">
if (table->CellBorder)
{
_Cells.back()->Border->setWidth(1, 1, 1, 1);
_Cells.back()->Border->setColor(table->Border->TopColor, table->Border->RightColor, table->Border->BottomColor, table->Border->LeftColor);
_Cells.back()->Border->setStyle(CSSLineStyle::INSET, CSSLineStyle::INSET, CSSLineStyle::INSET, CSSLineStyle::INSET);
}
if (_Style.hasStyle("border-top-width")) _Cells.back()->Border->TopWidth = _Style.Current.BorderTopWidth;
if (_Style.hasStyle("border-right-width")) _Cells.back()->Border->RightWidth = _Style.Current.BorderRightWidth;
if (_Style.hasStyle("border-bottom-width")) _Cells.back()->Border->BottomWidth = _Style.Current.BorderBottomWidth;
if (_Style.hasStyle("border-left-width")) _Cells.back()->Border->LeftWidth = _Style.Current.BorderLeftWidth;
if (_Style.hasStyle("border-top-color")) _Cells.back()->Border->TopColor = _Style.Current.BorderTopColor;
if (_Style.hasStyle("border-right-color")) _Cells.back()->Border->RightColor = _Style.Current.BorderRightColor;
if (_Style.hasStyle("border-bottom-color")) _Cells.back()->Border->BottomColor = _Style.Current.BorderBottomColor;
if (_Style.hasStyle("border-left-color")) _Cells.back()->Border->LeftColor = _Style.Current.BorderLeftColor;
if (_Style.hasStyle("border-top-style")) _Cells.back()->Border->TopStyle = _Style.Current.BorderTopStyle;
if (_Style.hasStyle("border-right-style")) _Cells.back()->Border->RightStyle = _Style.Current.BorderRightStyle;
if (_Style.hasStyle("border-bottom-style")) _Cells.back()->Border->BottomStyle = _Style.Current.BorderBottomStyle;
if (_Style.hasStyle("border-left-style")) _Cells.back()->Border->LeftStyle = _Style.Current.BorderLeftStyle;
// padding from <table cellpadding="1">
if (table->CellPadding)
{
_Cells.back()->PaddingTop = table->CellPadding;
_Cells.back()->PaddingRight = table->CellPadding;
_Cells.back()->PaddingBottom = table->CellPadding;
_Cells.back()->PaddingLeft = table->CellPadding;
}
if (_Style.hasStyle("padding-top")) _Cells.back()->PaddingTop = _Style.Current.PaddingTop;
if (_Style.hasStyle("padding-right")) _Cells.back()->PaddingRight = _Style.Current.PaddingRight;
if (_Style.hasStyle("padding-bottom")) _Cells.back()->PaddingBottom = _Style.Current.PaddingBottom;
if (_Style.hasStyle("padding-left")) _Cells.back()->PaddingLeft = _Style.Current.PaddingLeft;
table->addChild (_Cells.back());
// reusing indent pushed by table
@ -6813,6 +6959,13 @@ namespace NLGUI
// ***************************************************************************
void CGroupHTML::htmlTR(const CHtmlElement &elm)
{
// prevent inheriting from table
if (!_CellParams.empty())
{
_CellParams.back().BgColor = CRGBA::Transparent;
_CellParams.back().Height = 0;
}
// Get cells parameters
getCellsParameters(elm, true);

@ -1221,7 +1221,7 @@ namespace NLGUI
pV->setText (name);
}
pV->setColor (_GroupMenu->_Color);
pV->setFontSize (_GroupMenu->_FontSize);
pV->setFontSize (_GroupMenu->_FontSize, _GroupMenu->_FontSizeCoef);
pV->setShadow (_GroupMenu->_Shadow);
pV->setShadowOutline (_GroupMenu->_ShadowOutline);
pV->setCheckable(checkable);
@ -1310,7 +1310,7 @@ namespace NLGUI
}
pV->setColor (_GroupMenu->_Color);
pV->setFontSize (_GroupMenu->_FontSize);
pV->setFontSize (_GroupMenu->_FontSize, _GroupMenu->_FontSizeCoef);
pV->setShadow (_GroupMenu->_Shadow);
pV->setShadowOutline (_GroupMenu->_ShadowOutline);
pV->setCheckable(checkable);
@ -1990,6 +1990,7 @@ namespace NLGUI
_ShadowColorGrayed = CRGBA::Black;
_HighLightOver.set(128, 0, 0, 255);
_FontSize = 12;
_FontSizeCoef = true;
_Shadow = false;
_ShadowOutline = false;
_ResizeFromChildH = _ResizeFromChildW = true;
@ -2584,9 +2585,10 @@ namespace NLGUI
}
// ------------------------------------------------------------------------------------------------
void CGroupMenu::setFontSize(uint fontSize)
void CGroupMenu::setFontSize(uint fontSize, bool coef)
{
_FontSize = fontSize;
_FontSizeCoef = coef;
}
// ------------------------------------------------------------------------------------------------

@ -25,6 +25,7 @@
#include "nel/misc/i_xml.h"
#include "nel/misc/i18n.h"
#include "nel/misc/xml_auto_ptr.h"
#include "nel/gui/css_border_renderer.h"
using namespace std;
using namespace NLMISC;
@ -52,6 +53,9 @@ namespace NLGUI
RowSpan = 1;
TableColumnIndex = 0;
Group = new CInterfaceGroup(CViewBase::TCtorParam());
// TODO: only initialize if border is set
Border = new CSSBorderRenderer();
PaddingTop = PaddingRight = PaddingBottom = PaddingLeft = 0;
Align = Left;
VAlign = Middle;
LeftMargin = 0;
@ -59,13 +63,26 @@ namespace NLGUI
IgnoreMaxWidth = false;
IgnoreMinWidth = false;
AddChildW = false;
_UserTexture = false;
_TextureTiled = false;
_TextureScaled = false;
_TextureXReal = 0;
_TextureYReal = 0;
_TextureWReal = 0;
_TextureHReal = 0;
setEnclosedGroupDefaultParams();
addGroup (Group);
}
// ----------------------------------------------------------------------------
CGroupCell::~CGroupCell()
{
if (Border)
{
delete Border;
Border = NULL;
}
}
// ----------------------------------------------------------------------------
void CGroupCell::setEnclosedGroupDefaultParams()
{
@ -481,85 +498,72 @@ namespace NLGUI
rVR.drawRotFlipBitmap (_RenderLayer, _XReal+_WReal-1, _YReal, 1, _HReal, 0, false, rVR.getBlankTextureId(), CRGBA(0,255,255,255) );
}
uint8 CurrentAlpha = 255;
CGroupTable *table = NULL;
if (getParent ())
{
table = static_cast<CGroupTable*> (getParent ());
CurrentAlpha = table->CurrentAlpha;
}
// Draw the background
if (_UserTexture || BgColor.A != 0)
if (BgColor.A > 0 || !_TextureId.empty())
{
CViewRenderer &rVR = *CViewRenderer::getInstance();
if (_UserTexture)
bool flush = false;
if (CurrentAlpha > 0 && !_TextureId.empty())
{
CRGBA col;
if (BgColor.A == 0 )
col = CRGBA(255,255,255,255);
else
col = BgColor;
CRGBA col = CRGBA::White;
col.A = CurrentAlpha;
sint32 oldSciX, oldSciY, oldSciW, oldSciH;
makeNewClip (oldSciX, oldSciY, oldSciW, oldSciH);
if (_TextureScaled && !_TextureTiled)
{
rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal,
_WReal, _HReal,
0, false,
_TextureId,
col );
rVR.drawRotFlipBitmap(_RenderLayer, _TextureXReal, _TextureYReal, _WReal, _HReal, 0, false, _TextureId, col);
}
else
{
if (!_TextureTiled)
{
rVR.draw11RotFlipBitmap (_RenderLayer, _XReal, _YReal,
0, false,
_TextureId,
col);
}
rVR.drawRotFlipBitmap(_RenderLayer, _TextureXReal, _TextureYReal, _TextureWReal, _TextureHReal, 0, false, _TextureId, col);
else
{
rVR.drawRotFlipBitmapTiled(_RenderLayer, _XReal, _YReal,
_WReal, _HReal,
0, false,
_TextureId,
0,
col);
}
rVR.drawRotFlipBitmapTiled(_RenderLayer, _TextureXReal, _TextureYReal, _WReal, _TextureHReal, 0, false, _TextureId, 0, col);
}
restoreClip (oldSciX, oldSciY, oldSciW, oldSciH);
flush = true;
}
else
if (BgColor.A > 0)
{
CRGBA finalColor;
finalColor.modulateFromColor (BgColor, CWidgetManager::getInstance()->getGlobalColor());
CRGBA finalColor = BgColor;
if (_ModulateGlobalColor)
finalColor.modulateFromColor (finalColor, CWidgetManager::getInstance()->getGlobalColor());
finalColor.A = (uint8) (((uint16) CurrentAlpha * (uint16) finalColor.A) >> 8);
// Get the parent table
if (getParent ())
{
CGroupTable *table = static_cast<CGroupTable*> (getParent ());
finalColor.A = (uint8) (((uint16) table->CurrentAlpha * (uint16) finalColor.A) >> 8);
}
if (finalColor.A > 0)
rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, _WReal, _HReal, 0, false, rVR.getBlankTextureId(), finalColor);
//nlinfo("Blank Texture");
rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, _WReal, _HReal, 0, false, rVR.getBlankTextureId(), finalColor);
flush = true;
}
if (flush)
rVR.flush();
}
// Get the parent table
if (getParent ())
if (Border)
{
CGroupTable *table = static_cast<CGroupTable*> (getParent ());
if (table->Border) {
CRGBA lighter = blend(table->BorderColor, CRGBA::White, 0.5f);
CRGBA borderColorTL;
borderColorTL.modulateFromColor (lighter, CWidgetManager::getInstance()->getGlobalColor());
borderColorTL.A = (uint8) (((uint16) table->CurrentAlpha * (uint16) borderColorTL.A) >> 8);
CRGBA borderColorBR;
borderColorBR.modulateFromColor (table->BorderColor, CWidgetManager::getInstance()->getGlobalColor());
borderColorBR.A = (uint8) (((uint16) table->CurrentAlpha * (uint16) borderColorBR.A) >> 8);
CViewRenderer &rVR = *CViewRenderer::getInstance();
rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, _WReal, 1, 0, false, rVR.getBlankTextureId(), borderColorTL );
rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, 1, _HReal, 0, false, rVR.getBlankTextureId(), borderColorBR );
rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+_HReal-1, _WReal, 1, 0, false, rVR.getBlankTextureId(), borderColorBR );
rVR.drawRotFlipBitmap (_RenderLayer, _XReal+_WReal-1, _YReal, 1, _HReal, 0, false, rVR.getBlankTextureId(), borderColorTL );
// TODO: monitor these in checkCoords and update when changed
uint8 contentAlpha = CWidgetManager::getInstance()->getGlobalColorForContent().A;
if (contentAlpha > 0)
{
Border->CurrentAlpha = contentAlpha;
Border->setRenderLayer(_RenderLayer);
Border->setModulateGlobalColor(_ModulateGlobalColor);
Border->draw();
}
}
@ -569,13 +573,19 @@ namespace NLGUI
// ----------------------------------------------------------------------------
sint32 CGroupCell::getMaxUsedW() const
{
return Group->getMaxUsedW();
sint32 result = getPaddingLeftRight() + Group->getMaxUsedW();
if (Border)
result += Border->getLeftRightWidth();
return result;
}
// ------------------------------------------------------------------------------------------------
sint32 CGroupCell::getMinUsedW() const
{
return Group->getMinUsedW();
sint32 result = getPaddingLeftRight() + Group->getMinUsedW();
if (Border)
result += Border->getLeftRightWidth();
return result;
}
@ -584,14 +594,13 @@ namespace NLGUI
{
if (TxName.empty() || TxName == "none")
{
_UserTexture = false;
nlinfo("Set no texture");
_TextureId.clear();
}
else
{
nlinfo("Set texture to cell : %s", TxName.c_str());
_UserTexture = true;
_TextureId.setTexture (TxName.c_str (), 0, 0, -1, -1, false);
updateTextureCoords();
}
}
@ -611,6 +620,31 @@ namespace NLGUI
_TextureScaled = scaled;
}
// ----------------------------------------------------------------------------
void CGroupCell::updateTextureCoords()
{
if (_TextureId.empty()) return;
CViewRenderer &rVR = *CViewRenderer::getInstance();
rVR.getTextureSizeFromId (_TextureId, _TextureWReal, _TextureHReal);
_TextureXReal = _XReal;
_TextureYReal = _YReal + _HReal - _TextureHReal;
if (_TextureTiled && _TextureHReal > 0)
{
sint diff = (_HReal / _TextureHReal) * _TextureHReal;
_TextureYReal -= diff;
_TextureHReal += diff;
}
}
// ----------------------------------------------------------------------------
void CGroupCell::updateCoords()
{
CInterfaceGroup::updateCoords();
updateTextureCoords();
}
// ----------------------------------------------------------------------------
NLMISC_REGISTER_OBJECT(CViewBase, CGroupTable, std::string, "table");
@ -622,11 +656,21 @@ namespace NLGUI
_ContentValidated = false;
TableRatio = 0.f;
ForceWidthMin = 0;
Border=0;
BorderColor = CRGBA(32, 32, 32, 255);
// TODO: only initialize when needed
Border = new CSSBorderRenderer();
CellBorder = false;
CellPadding=1;
CellSpacing=2;
ContinuousUpdate = false;
_TextureTiled = false;
_TextureScaled = false;
_TextureXReal = 0;
_TextureYReal = 0;
_TextureWReal = 0;
_TextureHReal = 0;
}
// ----------------------------------------------------------------------------
@ -688,13 +732,62 @@ namespace NLGUI
// ----------------------------------------------------------------------------
CGroupTable::~CGroupTable()
{
if (Border)
{
delete Border;
Border = NULL;
}
/* uint i;
for (i=0; i<_Cells.size(); i++)
delete _Cells[i];
_Cells.clear ();*/
}
// ----------------------------------------------------------------------------
void CGroupTable::setTexture(const std::string & TxName)
{
if (TxName.empty() || TxName == "none")
{
_TextureId.clear();
}
else
{
_TextureId.setTexture (TxName.c_str (), 0, 0, -1, -1, false);
updateTextureCoords();
}
}
// ----------------------------------------------------------------------------
void CGroupTable::setTextureTile(bool tiled)
{
_TextureTiled = tiled;
}
// ----------------------------------------------------------------------------
void CGroupTable::setTextureScale(bool scaled)
{
_TextureScaled = scaled;
}
// ----------------------------------------------------------------------------
void CGroupTable::updateTextureCoords()
{
if (_TextureId.empty()) return;
CViewRenderer &rVR = *CViewRenderer::getInstance();
rVR.getTextureSizeFromId (_TextureId, _TextureWReal, _TextureHReal);
_TextureXReal = _XReal;
_TextureYReal = _YReal + _HReal - _TextureHReal;
if (_TextureTiled && _TextureHReal > 0)
{
sint diff = (_HReal / _TextureHReal) * _TextureHReal;
_TextureYReal -= diff;
_TextureHReal += diff;
}
}
// ----------------------------------------------------------------------------
void CGroupTable::updateCoords()
@ -738,21 +831,22 @@ namespace NLGUI
// Get width min and max
if( !cell->IgnoreMaxWidth)
{
cell->WidthMax = cell->getMaxUsedW() + cell->LeftMargin;
}
else
{
cell->WidthMax = cell->WidthWanted + additionnalWidth + cell->LeftMargin;
}
sint32 cellWidth;
if(!cell->IgnoreMinWidth)
{
cellWidth = cell->NoWrap ? cell->WidthMax : cell->getMinUsedW() + cell->LeftMargin;
}
else
{
cellWidth = cell->NoWrap ? cell->WidthMax : cell->LeftMargin;
{
sint32 cellBorderPadding = cell->getPaddingLeftRight();
if (cell->Border)
cellBorderPadding += cell->Border->getLeftRightWidth();
if (cellWidth < cellBorderPadding)
cellWidth = cellBorderPadding;
}
// New cell ?
@ -795,11 +889,11 @@ namespace NLGUI
_Columns[column].WidthMax = (sint32)(cell->WidthMax*colspan);
if (cell->TableRatio*colspan > _Columns[column].TableRatio)
_Columns[column].TableRatio = cell->TableRatio*colspan;
if (cell->WidthWanted*colspan + additionnalWidth > _Columns[column].WidthWanted)
_Columns[column].WidthWanted = (sint32)(cell->WidthWanted*colspan) + additionnalWidth;
if ((cell->WidthWanted + additionnalWidth)*colspan > _Columns[column].WidthWanted)
_Columns[column].WidthWanted = (sint32)((cell->WidthWanted + additionnalWidth)*colspan);
if (_Columns[column].WidthWanted + additionnalWidth)
_Columns[column].WidthMax = _Columns[column].WidthWanted + additionnalWidth;
if (_Columns[column].WidthWanted > _Columns[column].WidthMax)
_Columns[column].WidthMax = _Columns[column].WidthWanted;
if (_Columns[column].WidthWanted > _Columns[column].Width)
_Columns[column].Width = _Columns[column].WidthWanted;
@ -821,15 +915,23 @@ namespace NLGUI
column++;
}
// Width of cells and table borders
sint32 padding = CellPadding + (Border ? 1 : 0);
sint32 borderWidth = 2*Border + ((sint32)_Columns.size()+1) * CellSpacing + ((sint32)_Columns.size()*2) * padding;
// Additional space contributing to table width
sint32 tableBorderSpacing = 0;
if (Border)
tableBorderSpacing += Border->getLeftRightWidth();
tableBorderSpacing += ((sint32)_Columns.size()+1) * CellSpacing;;
sint32 innerForceWidthMin = ForceWidthMin;
if (innerForceWidthMin < tableBorderSpacing)
innerForceWidthMin = 0;
else
innerForceWidthMin -= tableBorderSpacing;
// Get the width
sint32 tableWidthMax = ForceWidthMin?ForceWidthMin:_LastParentW; // getWReal();
sint32 tableWidthMin = std::max(ForceWidthMin, (sint32)((float)tableWidthMax*TableRatio));
tableWidthMax = std::max ((sint32)0, tableWidthMax-borderWidth);
tableWidthMin = std::max ((sint32)0, tableWidthMin-borderWidth);
sint32 tableWidthMax = innerForceWidthMin ? innerForceWidthMin : _LastParentW - tableBorderSpacing; // getWReal();
sint32 tableWidthMin = std::max(innerForceWidthMin, (sint32)((float)tableWidthMax*TableRatio));
tableWidthMax = std::max ((sint32)0, tableWidthMax);
tableWidthMin = std::max ((sint32)0, tableWidthMin);
// Get the width of the table and normalize percent of the cell (sum of TableRatio must == 1)
sint32 tableWidth = 0;
@ -845,10 +947,10 @@ namespace NLGUI
// force table width to fit all columns
// if width is set, then use column min width
if (ForceWidthMin > 0)
tableWidthMax = std::min(_LastParentW - borderWidth, std::max(tableWidthMax, tableWidth));
if (innerForceWidthMin > 0)
tableWidthMax = std::min(_LastParentW - tableBorderSpacing, std::max(tableWidthMax, tableWidth));
else
tableWidthMax = std::min(_LastParentW - borderWidth, std::max(tableWidthMax, tableMaxContentWidth));
tableWidthMax = std::min(_LastParentW - tableBorderSpacing, std::max(tableWidthMax, tableMaxContentWidth));
if (tableWidthMax < 0)
tableWidthMax = 0;
@ -857,6 +959,7 @@ namespace NLGUI
std::swap(tableWidthMin, tableWidthMax);
// Eval table size with all percent cells resized
// TODO: _Columns[i].TableRatio is for outer width
sint32 tableWidthSizeAfterPercent = tableWidth;
for (i=0; i<_Columns.size(); i++)
{
@ -1029,7 +1132,7 @@ namespace NLGUI
column = 0;
sint32 row = 0;
sint32 currentX = Border + CellSpacing + padding;
sint32 currentX = 0;
_Rows.clear ();
for (i=0; i<_Cells.size(); i++)
@ -1039,7 +1142,9 @@ namespace NLGUI
if (cell->NewLine)
{
column = 0;
currentX = Border + CellSpacing + padding;
currentX = CellSpacing;
if (Border)
currentX += Border->getLeftWidth();
_Rows.push_back(CRow());
}
@ -1048,7 +1153,7 @@ namespace NLGUI
{
// we have active rowspan, must add up 'skipped' columns
for( ; column < (uint)cell->TableColumnIndex; ++column)
currentX += _Columns[column].Width + padding*2 + CellSpacing;
currentX += _Columns[column].Width + CellSpacing;
}
// Set the x and width
@ -1057,11 +1162,19 @@ namespace NLGUI
sint32 alignmentX = 0;
sint32 widthReduceX = 0;
sint32 columnWidth = _Columns[column].Width;
sint32 cellBorderPaddingLeft = cell->PaddingLeft;
sint32 cellBorderPaddingRight = cell->PaddingRight;
if (cell->Border)
{
cellBorderPaddingLeft += cell->Border->getLeftWidth();
cellBorderPaddingRight += cell->Border->getRightWidth();
}
if (cell->ColSpan > 1)
{
// scan ahead and add up column widths as they might be different
for(int j = 1; j<cell->ColSpan; j++)
columnWidth += CellSpacing + padding*2 + _Columns[column+j].Width;
columnWidth += CellSpacing + _Columns[column+j].Width;
}
if (cell->WidthMax < columnWidth)
@ -1081,11 +1194,13 @@ namespace NLGUI
}
}
cell->setX(currentX - padding);
cell->setW(columnWidth + padding*2);
// outer
cell->setX(currentX);
cell->setW(columnWidth);
cell->Group->setX(alignmentX + cell->LeftMargin + padding);
cell->Group->setW(columnWidth - widthReduceX);
// inner
cell->Group->setX(cellBorderPaddingLeft + alignmentX + cell->LeftMargin);
cell->Group->setW(columnWidth - widthReduceX - cellBorderPaddingLeft - cellBorderPaddingRight);
cell->Group->CInterfaceElement::updateCoords();
// Update coords to get H
@ -1094,16 +1209,23 @@ namespace NLGUI
// Resize the row array
float rowspan = 1.f / (float)cell->RowSpan;
_Rows.back().Height = std::max((sint32)(cell->Height*rowspan), std::max(_Rows.back().Height, (sint32)(cell->Group->getH()*rowspan)));
uint cellBorderPadding = cell->getPaddingTopBottom();
if (cell->Border)
cellBorderPadding += cell->Border->getTopBottomWidth();
sint32 cellHeight = std::max((sint32)(cell->Height*rowspan), (sint32)(cell->Group->getH()*rowspan + cellBorderPadding));
_Rows.back().Height = std::max(_Rows.back().Height, (sint32)cellHeight);
// Next column
currentX += columnWidth + 2*padding + CellSpacing;
currentX += columnWidth + CellSpacing;
column += cell->ColSpan;
}
// Set cell Y
row = 0;
sint32 currentY = -(Border + CellSpacing + padding);
sint32 currentY = -CellSpacing;
if (Border)
currentY -= Border->getTopWidth();
for (i=0; i<_Cells.size(); i++)
{
// New cell ?
@ -1112,7 +1234,7 @@ namespace NLGUI
{
if (_Rows[row].Height != 0)
{
currentY -= _Rows[row].Height + 2*padding + CellSpacing;
currentY -= _Rows[row].Height + CellSpacing;
}
row++;
}
@ -1120,12 +1242,19 @@ namespace NLGUI
// Check align
sint32 alignmentY = 0;
sint32 rowHeight = _Rows[row].Height;
sint32 cellBorderPaddingTop = cell->PaddingTop;
sint32 cellBorderPaddingBottom = cell->PaddingBottom;
if (cell->Border)
{
cellBorderPaddingTop += cell->Border->getTopWidth();
cellBorderPaddingBottom += cell->Border->getBottomWidth();
}
if (cell->RowSpan > 1)
{
// we need to scan down and add up row heights
int k = std::min((sint32)_Rows.size(), row + cell->RowSpan);
for(int j=row+1; j<k; j++)
rowHeight += CellSpacing + padding*2 + _Rows[j].Height;
rowHeight += CellSpacing + _Rows[j].Height;
}
if ((sint32)cell->Group->getH() < rowHeight)
{
@ -1142,15 +1271,26 @@ namespace NLGUI
}
}
cell->setY(currentY + padding);
cell->setH (rowHeight + 2*padding);
cell->Group->setY(-(alignmentY + padding));
// outer
cell->setY(currentY);
cell->setH (rowHeight);
// inner
cell->Group->setY(-(alignmentY + cellBorderPaddingTop - cellBorderPaddingBottom));
}
// Resize the table
setW(finalWidth+borderWidth-_LastParentW);
// final row
if (!_Rows.empty())
currentY -= _Rows[row].Height + padding + CellSpacing + Border;
currentY -= _Rows.back().Height;
currentY -= CellSpacing;
finalWidth += ((sint)_Columns.size() + 1) * CellSpacing;
if (Border)
{
currentY -= Border->getBottomWidth();
finalWidth += Border->getLeftRightWidth();
}
// Resize the table
setW(finalWidth-_LastParentW);
setH(-currentY);
// All done
@ -1160,8 +1300,22 @@ namespace NLGUI
CInterfaceGroup::updateCoords();
updateTextureCoords();
// update borders if present
if (Border)
{
Border->setRect(_XReal + _MarginLeft, _YReal, _WReal, _HReal);
}
// update cell borders if present
for (uint32 i=0; i<_Cells.size(); i++)
{
if (_Cells[i]->Border)
{
_Cells[i]->Border->setRect(_Cells[i]->_XReal, _Cells[i]->_YReal, _Cells[i]->_WReal, _Cells[i]->_HReal);
}
}
// Validated
_ContentValidated = true;
@ -1267,7 +1421,9 @@ namespace NLGUI
for (i=0; i<columns.size(); i++)
maxWidth += columns[i];
maxWidth += 2*Border + ((sint32)columns.size()+1) * CellSpacing + ((sint32)columns.size()*2) * CellPadding;
maxWidth += ((sint32)columns.size()+1) * CellSpacing;
if (Border)
maxWidth += Border->getLeftRightWidth();
return maxWidth;
}
@ -1312,7 +1468,9 @@ namespace NLGUI
for (i=0; i<columns.size(); i++)
maxWidth += columns[i];
maxWidth += 2*Border + ((sint32)columns.size()+1) * CellSpacing + ((sint32)columns.size()*2) * CellPadding;
maxWidth += ((sint32)columns.size()+1) * CellSpacing;
if (Border)
maxWidth += Border->getLeftRightWidth();
return maxWidth;
}
@ -1342,64 +1500,62 @@ namespace NLGUI
if (!_Columns.empty() && !_Rows.empty())
{
sint32 border = Border + CellSpacing;
if (border && BgColor.A)
bool flush = false;
CViewRenderer &rVR = *CViewRenderer::getInstance();
if (BgColor.A > 0)
{
CRGBA finalColor;
finalColor.modulateFromColor (BgColor, CWidgetManager::getInstance()->getGlobalColor());
finalColor.A = CurrentAlpha;
CRGBA finalColor = BgColor;
if (_ModulateGlobalColor)
finalColor.modulateFromColor (finalColor, CWidgetManager::getInstance()->getGlobalColor());
finalColor.A = (uint8) (((uint16) CurrentAlpha * (uint16) finalColor.A) >> 8);
// Draw the top line
CViewRenderer &rVR = *CViewRenderer::getInstance();
rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal-border+_HReal, _WReal, border, 0, false, rVR.getBlankTextureId(), finalColor);
rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, _WReal, _HReal, 0, false, rVR.getBlankTextureId(), finalColor);
// Draw the left line
sint32 insideHeight = std::max((sint32)0, (sint32)_HReal - (sint32)border);
rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, border, insideHeight, 0, false, rVR.getBlankTextureId(), finalColor);
flush = true;
}
// Draw the inside borders
if (CellSpacing)
// Draw the background
if (CurrentAlpha > 0 && !_TextureId.empty())
{
sint32 oldSciX, oldSciY, oldSciW, oldSciH;
makeNewClip (oldSciX, oldSciY, oldSciW, oldSciH);
CRGBA col = CRGBA::White;
col.A = CurrentAlpha;
if (_TextureScaled && !_TextureTiled)
{
uint i;
sint32 x, y;
for (i=0; i<_Cells.size(); i++)
{
CGroupCell *cell = _Cells[i];
x = cell->getXReal();
y = cell->getYReal() - CellSpacing;
// right
rVR.drawRotFlipBitmap (_RenderLayer, x + cell->getW(), y, CellSpacing, cell->getH() + CellSpacing, 0, false, rVR.getBlankTextureId(), finalColor);
// bottom
rVR.drawRotFlipBitmap (_RenderLayer, x, y, cell->getW(), CellSpacing, 0, false, rVR.getBlankTextureId(), finalColor);
}
rVR.drawRotFlipBitmap(_RenderLayer, _TextureXReal, _TextureYReal, _WReal, _HReal, 0, false, _TextureId, col);
}
else
{
if (!_TextureTiled)
rVR.drawRotFlipBitmap(_RenderLayer, _TextureXReal, _TextureYReal, _TextureWReal, _TextureHReal, 0, false, _TextureId, col);
else
rVR.drawRotFlipBitmapTiled(_RenderLayer, _TextureXReal, _TextureYReal, _WReal, _TextureHReal, 0, false, _TextureId, 0, col);
}
restoreClip (oldSciX, oldSciY, oldSciW, oldSciH);
flush = true;
}
if (Border)
{
CViewRenderer &rVR = *CViewRenderer::getInstance();
CRGBA borderColorTL;
CRGBA lighter = blend(BorderColor, CRGBA::White, 0.5f);
borderColorTL.modulateFromColor (lighter, CWidgetManager::getInstance()->getGlobalColor());
borderColorTL.A = CurrentAlpha;
// flush background color and image
if (flush)
rVR.flush();
CRGBA borderColorBR;
borderColorBR.modulateFromColor (BorderColor, CWidgetManager::getInstance()->getGlobalColor());
borderColorBR.A = CurrentAlpha;
// beveled table border
for (sint32 i=0; i<Border; i++)
if (Border)
{
// TODO: monitor these in checkCoords and update when changed
uint8 contentAlpha = CWidgetManager::getInstance()->getGlobalColorForContent().A;
if (contentAlpha > 0)
{
// bottom, left, top, right
rVR.drawRotFlipBitmap (_RenderLayer, _XReal+i, _YReal+i, _WReal-i*2, 1, 0, false, rVR.getBlankTextureId(), borderColorBR);
rVR.drawRotFlipBitmap (_RenderLayer, _XReal+i, _YReal+i, 1, _HReal-i*2, 0, false, rVR.getBlankTextureId(), borderColorTL);
rVR.drawRotFlipBitmap (_RenderLayer, _XReal+i, _YReal+_HReal-i-1, _WReal-i*2, 1, 0, false, rVR.getBlankTextureId(), borderColorTL);
rVR.drawRotFlipBitmap (_RenderLayer, _XReal+_WReal-i-1, _YReal+i, 1, _HReal-i*2, 0, false, rVR.getBlankTextureId(), borderColorBR);
Border->CurrentAlpha = CurrentAlpha;
Border->setRenderLayer(_RenderLayer);
Border->setModulateGlobalColor(_ModulateGlobalColor);
Border->draw();
}
}
}
CInterfaceGroup::draw ();
@ -1412,12 +1568,16 @@ namespace NLGUI
{
if( name == "border" )
{
return toString( Border );
if (Border)
return toString( Border->TopWidth );
return "0";
}
else
if( name == "bordercolor" )
{
return toString( BorderColor );
if (Border)
return toString( Border->TopColor );
return toString(CRGBA::Transparent);
}
else
if( name == "cellpadding" )
@ -1452,7 +1612,14 @@ namespace NLGUI
{
sint32 i;
if( fromString( value, i ) )
Border = i;
{
if (!Border)
Border = new CSSBorderRenderer();
Border->TopWidth = i;
Border->RightWidth = i;
Border->BottomWidth = i;
Border->LeftWidth = i;
}
return;
}
else
@ -1460,7 +1627,14 @@ namespace NLGUI
{
CRGBA c;
if( fromString( value, c ) )
BorderColor = c;
{
if (!Border)
Border = new CSSBorderRenderer();
Border->TopColor = c;
Border->RightColor = c;
Border->BottomColor = c;
Border->LeftColor = c;
}
return;
}
else
@ -1505,8 +1679,11 @@ namespace NLGUI
return NULL;
xmlSetProp( node, BAD_CAST "type", BAD_CAST "table" );
xmlSetProp( node, BAD_CAST "border", BAD_CAST toString( Border ).c_str() );
xmlSetProp( node, BAD_CAST "bordercolor", BAD_CAST toString( BorderColor ).c_str() );
if (Border)
{
xmlSetProp( node, BAD_CAST "border", BAD_CAST toString( Border->TopWidth ).c_str() );
xmlSetProp( node, BAD_CAST "bordercolor", BAD_CAST toString( Border->TopColor ).c_str() );
}
xmlSetProp( node, BAD_CAST "cellpadding", BAD_CAST toString( CellPadding ).c_str() );
xmlSetProp( node, BAD_CAST "cellspacing", BAD_CAST toString( CellSpacing ).c_str() );
xmlSetProp( node, BAD_CAST "bgcolor", BAD_CAST toString( BgColor ).c_str() );
@ -1528,13 +1705,20 @@ namespace NLGUI
ptr = (char*) xmlGetProp( cur, (xmlChar*)"border" );
if (ptr)
{
fromString((const char*)ptr, Border);
uint32 w;
fromString((const char*)ptr, w);
if (!Border)
Border = new CSSBorderRenderer();
Border->setWidth(w, w, w, w);
}
//
ptr = (char*) xmlGetProp( cur, (xmlChar*)"bordercolor" );
if (ptr)
{
BorderColor = convertColor((const char*)ptr);
CRGBA c = convertColor((const char*)ptr);
if (!Border)
Border = new CSSBorderRenderer();
Border->setColor(c, c, c, c);
}
//
ptr = (char*) xmlGetProp( cur, (xmlChar*)"cellpadding" );

@ -190,6 +190,35 @@ namespace NLGUI
elm.reindexChilds();
parent.reindexChilds();
}
// move all <tr> directly under <table> to its own <tbody> ("table > tbody > tr" selector).
// TODO: move first real <thead> to front, move first real <tfoot> at the end
if (elm.ID == HTML_TABLE)
{
std::list<CHtmlElement>::iterator it = elm.Children.begin();
std::list<CHtmlElement>::iterator tbody = elm.Children.end();
for(it = elm.Children.begin(); it != elm.Children.end(); ++it)
{
if (it->ID == HTML_TR)
{
if (tbody == elm.Children.end())
{
tbody = elm.Children.insert(it, CHtmlElement(CHtmlElement::ELEMENT_NODE, "tbody"));
tbody->ID = HTML_TBODY;
tbody->parent = &elm;
}
tbody->Children.splice(tbody->Children.end(), elm.Children, it);
it = tbody;
}
else if (tbody != elm.Children.end())
{
tbody->reindexChilds();
tbody = elm.Children.end();
}
}
elm.reindexChilds();
}
}
}

@ -1932,6 +1932,16 @@ namespace NLGUI
return _TextureId >= 0;
}
// ***************************************************************************
void CViewRenderer::CTextureId::clear()
{
if (_TextureId >= 0)
{
CViewRenderer::getInstance()->deleteTexture(_TextureId);
_TextureId = -1;
}
}
// ***************************************************************************
void CViewRenderer::CTextureId::serial(NLMISC::IStream &f)
{

@ -361,6 +361,37 @@ void CIFile::flush()
}
}
// ======================================================================================================
bool CIFile::readAll(std::string &buffer)
{
try
{
uint32 remaining = _FileSize;
buffer.clear();
buffer.reserve(_FileSize);
while(!eof() && remaining > 0)
{
const static uint bufsize = 1024;
char buf[bufsize];
uint32 readnow = bufsize;
if (readnow > remaining)
readnow = remaining;
serialBuffer((uint8 *)&buf[0], readnow);
buffer.append(buf, readnow);
remaining -= readnow;
}
}
catch (const EFile &)
{
// buffer state is unknown
return false;
}
return true;
}
// ======================================================================================================
void CIFile::getline (char *buffer, uint32 bufferSize)
{

@ -48,6 +48,7 @@ const CRGBA CRGBA::Blue(0, 0, 255) ;
const CRGBA CRGBA::Magenta(255, 0, 255) ;
const CRGBA CRGBA::Cyan(0, 255, 255) ;
const CRGBA CRGBA::White(255, 255, 255) ;
const CRGBA CRGBA::Transparent(0, 0, 0, 0);
// ***************************************************************************
void CRGBA::serial(NLMISC::IStream &f)

Loading…
Cancel
Save