From 24d03e9c268d982ce725800686a6ddd871c32db1 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sun, 8 Sep 2019 10:41:11 +0300 Subject: [PATCH] Added: Table/cell borders with independent size and color --HG-- branch : html-improvements --- .../nel/include/nel/gui/css_border_renderer.h | 94 +++++ code/nel/include/nel/gui/css_style.h | 6 +- code/nel/include/nel/gui/css_types.h | 39 +++ code/nel/include/nel/gui/group_table.h | 11 +- code/nel/src/gui/css_border_renderer.cpp | 320 ++++++++++++++++++ code/nel/src/gui/group_html.cpp | 87 +++-- code/nel/src/gui/group_table.cpp | 143 ++++---- 7 files changed, 610 insertions(+), 90 deletions(-) create mode 100644 code/nel/include/nel/gui/css_border_renderer.h create mode 100644 code/nel/include/nel/gui/css_types.h create mode 100644 code/nel/src/gui/css_border_renderer.cpp diff --git a/code/nel/include/nel/gui/css_border_renderer.h b/code/nel/include/nel/gui/css_border_renderer.h new file mode 100644 index 000000000..41ea3b7e6 --- /dev/null +++ b/code/nel/include/nel/gui/css_border_renderer.h @@ -0,0 +1,94 @@ +// Ryzom - MMORPG Framework +// 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 . + + + +#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 + + diff --git a/code/nel/include/nel/gui/css_style.h b/code/nel/include/nel/gui/css_style.h index c60d123c4..94d86bf5d 100644 --- a/code/nel/include/nel/gui/css_style.h +++ b/code/nel/include/nel/gui/css_style.h @@ -20,6 +20,7 @@ #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 { @@ -27,11 +28,6 @@ namespace NLGUI typedef std::map TStyle; - // ie. border-style - enum CSSLineStyle { NONE = 0, HIDDEN, SOLID }; - // ie, border-width (px) - enum CSSLineWidth { THIN = 1, MEDIUM = 3, THICK = 5 }; - /** * \brief CSS style rules * \date 2019-03-15 10:50 GMT diff --git a/code/nel/include/nel/gui/css_types.h b/code/nel/include/nel/gui/css_types.h new file mode 100644 index 000000000..aa673a63e --- /dev/null +++ b/code/nel/include/nel/gui/css_types.h @@ -0,0 +1,39 @@ +// Ryzom - MMORPG Framework +// 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 . + +#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 + + diff --git a/code/nel/include/nel/gui/group_table.h b/code/nel/include/nel/gui/group_table.h index 3782ccdb6..e45575e47 100644 --- a/code/nel/include/nel/gui/group_table.h +++ b/code/nel/include/nel/gui/group_table.h @@ -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. @@ -91,6 +93,8 @@ namespace NLGUI // The cell color NLMISC::CRGBA BgColor; + CSSBorderRenderer* Border; + // Texture CViewRenderer::CTextureId _TextureId; bool _TextureTiled; @@ -151,9 +155,10 @@ namespace NLGUI // The Width you want in pixel. This is the parameter sint32 ForceWidthMin; - // Table borders - sint32 Border; - NLMISC::CRGBA BorderColor; + CSSBorderRenderer* Border; + + // Cell has 1px solid border when
has 'border' attribute with width > 0 + bool CellBorder; sint32 CellPadding; sint32 CellSpacing; diff --git a/code/nel/src/gui/css_border_renderer.cpp b/code/nel/src/gui/css_border_renderer.cpp new file mode 100644 index 000000000..fd3ad569f --- /dev/null +++ b/code/nel/src/gui/css_border_renderer.cpp @@ -0,0 +1,320 @@ +// Ryzom - MMORPG Framework +// 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 . + + +#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 + diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index b95d645f7..1a129ebae 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -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 @@ -6556,31 +6557,50 @@ namespace NLGUI else if (elm.hasNonEmptyAttribute("width")) getPercentage (table->ForceWidthMin, table->TableRatio, elm.getAttribute("width").c_str()); - if (_Style.hasStyle("border") || _Style.hasStyle("border-width") || _Style.hasStyle("border-top-width")) + // border from css or from attribute { - // FIXME: only using border-top - table->Border = _Style.Current.BorderTopWidth; - } - else if (elm.hasAttribute("border")) - { - std::string s = elm.getAttribute("border"); - if (s.empty()) - table->Border = 1; - else - fromString(elm.getAttribute("border"), table->Border); - } + uint32 borderWidth = 0; + CRGBA borderColor = CRGBA::Transparent; - if (_Style.hasStyle("border-color")) - { - std::string s = toLower(_Style.getStyle("border-color")); - if (s == "currentcolor") - table->BorderColor = _Style.Current.TextColor; + // TODO: _Style->hasBorder() ?? + table->Border = new CSSBorderRenderer(); + 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); - } - else if (elm.hasNonEmptyAttribute("bordercolor")) - { - scanHTMLColor(elm.getAttribute("bordercolor").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; } if (_Style.hasStyle("background-image")) @@ -6714,6 +6734,29 @@ namespace NLGUI if (_Style.checkStyle("-ryzom-modulate-bgcolor", "true")) _Cells.back()->setModulateGlobalColor(true); + // border from
+ 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; + table->addChild (_Cells.back()); // reusing indent pushed by table diff --git a/code/nel/src/gui/group_table.cpp b/code/nel/src/gui/group_table.cpp index a99cbddeb..68f01b65d 100644 --- a/code/nel/src/gui/group_table.cpp +++ b/code/nel/src/gui/group_table.cpp @@ -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,8 @@ namespace NLGUI RowSpan = 1; TableColumnIndex = 0; Group = new CInterfaceGroup(CViewBase::TCtorParam()); + // TODO: only initialize if border is set + Border = new CSSBorderRenderer(); Align = Left; VAlign = Middle; LeftMargin = 0; @@ -541,26 +544,13 @@ namespace NLGUI } // Get the parent table - if (getParent ()) + if (CurrentAlpha > 0) { - CGroupTable *table = static_cast (getParent ()); - if (table->Border) { - CRGBA borderColorTL = blend(table->BorderColor, CRGBA::White, 0.5f); - if (_ModulateGlobalColor) - borderColorTL.modulateFromColor (borderColorTL, CWidgetManager::getInstance()->getGlobalColor()); - borderColorTL.A = (uint8) (((uint16) table->CurrentAlpha * (uint16) borderColorTL.A) >> 8); - - CRGBA borderColorBR = table->BorderColor; - if (_ModulateGlobalColor) - borderColorBR.modulateFromColor (borderColorBR, 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 + Border->CurrentAlpha = CurrentAlpha; + Border->setRenderLayer(_RenderLayer); + Border->setModulateGlobalColor(_ModulateGlobalColor); + Border->draw(); } CInterfaceGroup::draw (); @@ -646,8 +636,11 @@ 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; @@ -719,6 +712,12 @@ namespace NLGUI // ---------------------------------------------------------------------------- CGroupTable::~CGroupTable() { + if (Border) + { + delete Border; + Border = NULL; + } + /* uint i; for (i=0; i<_Cells.size(); i++) delete _Cells[i]; @@ -895,9 +894,9 @@ 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 borderWidth = Border->getLeftWidth() + Border->getRightWidth(); + borderWidth += ((sint32)_Columns.size()+1) * CellSpacing;// + ((sint32)_Columns.size()*2) * padding; // Get the width sint32 tableWidthMax = ForceWidthMin?ForceWidthMin:_LastParentW; // getWReal(); @@ -1102,8 +1101,10 @@ namespace NLGUI // *** Now we know each column width, resize cells and get the height for each row column = 0; + // FIXME: real cell padding + sint32 padding = CellPadding; sint32 row = 0; - sint32 currentX = Border + CellSpacing + padding; + sint32 currentX = Border->LeftWidth + CellSpacing + padding; _Rows.clear (); for (i=0; i<_Cells.size(); i++) @@ -1113,7 +1114,7 @@ namespace NLGUI if (cell->NewLine) { column = 0; - currentX = Border + CellSpacing + padding; + currentX = Border->LeftWidth + CellSpacing + padding; _Rows.push_back(CRow()); } @@ -1168,7 +1169,11 @@ 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 cellBorder = 0; + if (cell->Border) + cellBorder += cell->Border->TopWidth + cell->Border->BottomWidth; + sint32 cellHeight = std::max((sint32)(cell->Height*rowspan + cellBorder), (sint32)(cell->Group->getH()*rowspan + cellBorder)); + _Rows.back().Height = std::max(_Rows.back().Height, (sint32)cellHeight); // Next column currentX += columnWidth + 2*padding + CellSpacing; @@ -1177,7 +1182,10 @@ namespace NLGUI // Set cell Y row = 0; - sint32 currentY = -(Border + CellSpacing + padding); + sint32 currentY = -(CellSpacing + padding); + if (Border) + currentY -= Border->TopWidth; + for (i=0; i<_Cells.size(); i++) { // New cell ? @@ -1224,7 +1232,7 @@ namespace NLGUI // Resize the table setW(finalWidth+borderWidth-_LastParentW); if (!_Rows.empty()) - currentY -= _Rows[row].Height + padding + CellSpacing + Border; + currentY -= _Rows[row].Height + padding + CellSpacing + Border->BottomWidth; setH(-currentY); // All done @@ -1236,6 +1244,20 @@ namespace NLGUI 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; @@ -1341,7 +1363,8 @@ namespace NLGUI for (i=0; iLeftWidth + Border->RightWidth + ((sint32)columns.size()+1) * CellSpacing + ((sint32)columns.size()*2) * CellPadding; return maxWidth; } @@ -1386,7 +1409,8 @@ namespace NLGUI for (i=0; iLeftWidth + Border->RightWidth + ((sint32)columns.size()+1) * CellSpacing + ((sint32)columns.size()*2) * CellPadding; return maxWidth; } @@ -1460,29 +1484,15 @@ namespace NLGUI if (flush) rVR.flush(); - if (Border) + // TODO: monitor ModulateGlobalColor and CurrentAlpha in checkCoords and recalculate colors on change only + if (CurrentAlpha > 0 && Border) { - CRGBA borderColorTL = blend(BorderColor, CRGBA::White, 0.5f); - if (_ModulateGlobalColor) - borderColorTL.modulateFromColor (borderColorTL, CWidgetManager::getInstance()->getGlobalColor()); - borderColorTL.A = CurrentAlpha; - - CRGBA borderColorBR = BorderColor; - if (_ModulateGlobalColor) - borderColorBR.modulateFromColor (borderColorBR, CWidgetManager::getInstance()->getGlobalColor()); - borderColorBR.A = CurrentAlpha; - - // beveled table border - for (sint32 i=0; iCurrentAlpha = CurrentAlpha; + Border->setRenderLayer(_RenderLayer); + Border->setModulateGlobalColor(_ModulateGlobalColor); + Border->draw(); } - } CInterfaceGroup::draw (); @@ -1495,12 +1505,12 @@ namespace NLGUI { if( name == "border" ) { - return toString( Border ); + return toString( Border->TopWidth ); } else if( name == "bordercolor" ) { - return toString( BorderColor ); + return toString( Border->TopColor ); } else if( name == "cellpadding" ) @@ -1535,7 +1545,12 @@ namespace NLGUI { sint32 i; if( fromString( value, i ) ) - Border = i; + { + Border->TopWidth = i; + Border->RightWidth = i; + Border->BottomWidth = i; + Border->LeftWidth = i; + } return; } else @@ -1543,7 +1558,12 @@ namespace NLGUI { CRGBA c; if( fromString( value, c ) ) - BorderColor = c; + { + Border->TopColor = c; + Border->RightColor = c; + Border->BottomColor = c; + Border->LeftColor = c; + } return; } else @@ -1588,8 +1608,8 @@ 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() ); + 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() ); @@ -1611,13 +1631,16 @@ namespace NLGUI ptr = (char*) xmlGetProp( cur, (xmlChar*)"border" ); if (ptr) { - fromString((const char*)ptr, Border); + uint32 w; + fromString((const char*)ptr, w); + 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); + Border->setColor(c, c, c, c); } // ptr = (char*) xmlGetProp( cur, (xmlChar*)"cellpadding" );