diff --git a/code/nel/include/nel/gui/group_table.h b/code/nel/include/nel/gui/group_table.h new file mode 100644 index 000000000..4fd0f86e0 --- /dev/null +++ b/code/nel/include/nel/gui/group_table.h @@ -0,0 +1,216 @@ +// 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_GROUP_TABLE_H +#define NL_GROUP_TABLE_H + +#include "nel/misc/types_nl.h" +#include "nel/gui/group_frame.h" +#include "nel/gui/view_text.h" +#include "nel/gui/ctrl_button.h" + +namespace NLGUI +{ + + /** + * This group is used to simulate HTML cells. + * They have specific parameters to be aligned like HTML cells. + * (Percent of the table size + */ + class CGroupCell: public CInterfaceGroup + { + friend class CGroupTable; + public: + CGroupCell(const TCtorParam ¶m); + + enum TAlign + { + Left, + Center, + Right + }; + + enum TVAlign + { + Top, + Middle, + Bottom + }; + + /// \from CInterfaceElement + virtual void draw(); + virtual sint32 getMaxUsedW() const; + virtual sint32 getMinUsedW() const; + + // to be called by CGroupTable + bool parse (xmlNodePtr cur, CInterfaceGroup * parentGroup, uint columnIndex, uint rowIndex); + + // If the cell is a new line. This is the first after a + bool NewLine; + bool IgnoreMaxWidth; + bool IgnoreMinWidth; + bool AddChildW; + + // The table width cell ratio. This is the parameter + float TableRatio; + + // The Width you want in pixel. This is the parameter + sint32 WidthWanted; + + + // The min height of the cell + sint32 Height; + + // Memorize max width + sint32 WidthMax; + + // The cell color + NLMISC::CRGBA BgColor; + + // Texture + CViewRenderer::CTextureId _TextureId; /// Accelerator + bool _UserTexture; + bool _TextureTiled; + bool _TextureScaled; + + // Alignment + TAlign Align; + TVAlign VAlign; + sint32 LeftMargin; + + // The cell group + CInterfaceGroup *Group; + + // The cell is nowrap + bool NoWrap; + + void setTexture(const std::string & TxName); + void setTextureTile(bool tiled); + void setTextureScale(bool scaled); + + static void setDebugUICell( bool d ){ DebugUICell = d; } + static bool getDebugUICell(){ return DebugUICell; } + + private: + void setEnclosedGroupDefaultParams(); + static bool DebugUICell; + }; + + /** + * This group is used to simulate HTML table. Support "percent of the parent width" sizeRef mode. + */ + class CGroupTable : public CInterfaceGroup + { + public: + + ///constructor + CGroupTable(const TCtorParam ¶m); + + // dtor + ~CGroupTable(); + + // Add a cell in the table + void addChild (CGroupCell* child); + + // The ratio you want [0 ~1]. This is the parameter + float TableRatio; + + // The Width you want in pixel. This is the
parameter + sint32 ForceWidthMin; + + // Table borders + sint32 Border; + sint32 CellPadding; + sint32 CellSpacing; + + // The table color + NLMISC::CRGBA BgColor; + uint8 CurrentAlpha; + + bool ContinuousUpdate; + + protected: + + /// \from CInterfaceElement + void onInvalidateContent(); + sint32 getMaxUsedW() const; + sint32 getMinUsedW() const; + void draw (); + + /** + * init or reset the children element coords. Orverloaded from CInterfaceGroup because we begin with the last inserted element here + */ + virtual void updateCoords(); + + virtual void checkCoords(); + + virtual bool parse (xmlNodePtr cur, CInterfaceGroup * parentGroup); + + // Content validated + bool _ContentValidated; + + // Last parent width + sint32 _LastParentW; + + // Children + std::vector _Cells; + + // Table column + class CColumn + { + public: + CColumn() + { + Width = 0; + WidthMax = 0; + WidthWanted = 0; + TableRatio = 0; + Height = 0; + } + sint32 Width; + sint32 Height; + sint32 WidthWanted; + sint32 WidthMax; + float TableRatio; + }; + + // Table row + class CRow + { + public: + CRow() + { + Height = 0; + } + sint32 Height; + }; + + // Column table + std::vector _Columns; + + // Column table + std::vector _Rows; + }; + +} + +#endif // NL_GROUP_TABLE_H + +/* End of group_table.h */ + + diff --git a/code/nel/include/nel/gui/widget_manager.h b/code/nel/include/nel/gui/widget_manager.h index 0083e20c0..df5fd5540 100644 --- a/code/nel/include/nel/gui/widget_manager.h +++ b/code/nel/include/nel/gui/widget_manager.h @@ -51,7 +51,7 @@ namespace NLGUI virtual void addLuaClassAssociation( CInterfaceGroup *group, const std::string &luaScript ) = 0; virtual CInterfaceGroup* createGroupInstance( const std::string &templateName, const std::string &parentID, const std::pair< std::string, std::string > *templateParams, uint numParams, bool updateLinks = true ) = 0; virtual CInterfaceGroup* createGroupInstance( const std::string &templateName, const std::string &parentID, std::vector< std::pair< std::string, std::string > > &templateParams, bool updateLinks = true ) = 0; - virtual bool parseGroupChildren( xmlNodePtr cur, CInterfaceGroup * parentGroup, bool reload ); + virtual bool parseGroupChildren( xmlNodePtr cur, CInterfaceGroup * parentGroup, bool reload ) = 0; }; /// Manages the GUI widgets diff --git a/code/nel/src/gui/group_table.cpp b/code/nel/src/gui/group_table.cpp new file mode 100644 index 000000000..4baa32ab1 --- /dev/null +++ b/code/nel/src/gui/group_table.cpp @@ -0,0 +1,1078 @@ +// 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 "nel/gui/group_table.h" +#include "nel/gui/widget_manager.h" +#include "nel/gui/interface_element.h" +#include "nel/gui/view_bitmap.h" +#include "nel/gui/view_text_id.h" +#include "nel/gui/group_container.h" +#include "nel/misc/i_xml.h" +#include "nel/misc/i18n.h" +#include "nel/misc/xml_auto_ptr.h" + +using namespace std; +using namespace NLMISC; + +namespace NLGUI +{ + + bool CGroupCell::DebugUICell = false; + + // ---------------------------------------------------------------------------- + CGroupCell::CGroupCell(const TCtorParam ¶m) + : CInterfaceGroup(param), + BgColor (0,0,0,0) + + { + NewLine = false; + TableRatio = 0.f; + WidthWanted = 0; + Height = 0; + Group = new CInterfaceGroup(CViewBase::TCtorParam()); + Align = Left; + VAlign = Top; + LeftMargin = 0; + NoWrap = false; + IgnoreMaxWidth = false; + IgnoreMinWidth = false; + AddChildW = false; + _UserTexture = false; + _TextureTiled = false; + _TextureScaled = false; + setEnclosedGroupDefaultParams(); + addGroup (Group); + } + + // ---------------------------------------------------------------------------- + void CGroupCell::setEnclosedGroupDefaultParams() + { + nlassert(Group); + // Cells are moved and resized by the table + Group->setParent(this); + Group->setParentPos(this); + Group->setPosRef(Hotspot_TL); + Group->setParentPosRef(Hotspot_TL); + Group->setResizeFromChildW(false); + Group->setResizeFromChildH(true); + } + + // ---------------------------------------------------------------------------- + bool CGroupCell::parse(xmlNodePtr cur, CInterfaceGroup * parentGroup, uint columnIndex, uint rowIndex) + { + CXMLAutoPtr ptr; + ptr = (char*) xmlGetProp( cur, (xmlChar*)"id"); + if (!ptr) + { + // no id was given, so create one + std::string newId = NLMISC::toString("cell_%d_%d", (int) columnIndex, (int) rowIndex); + xmlSetProp(cur, (const xmlChar*) "id", (const xmlChar*) newId.c_str()); + } + // parse enclosed group + if (!Group->parse(cur, this)) return false; + Group->setId(parentGroup->getId() + Group->getId()); + setEnclosedGroupDefaultParams(); + // parse the children + bool ok = CWidgetManager::parser->parseGroupChildren(cur, Group, false); + if (!ok) return false; + // align + ptr = (char*) xmlGetProp( cur, (xmlChar*)"align" ); + if (ptr) + { + if (strcmp((const char *) ptr, "left") == 0) + { + Align = Left; + } + else if (strcmp((const char *) ptr, "right") == 0) + { + Align = Right; + } + else if (strcmp((const char *) ptr, "center") == 0) + { + Align = Center; + } + else + { + nlwarning(" Unknwown or unsupported align mode : %s", (const char *) ptr); + } + } + // v-align + ptr = (char*) xmlGetProp( cur, (xmlChar*)"valign" ); + if (ptr) + { + if (strcmp((const char *) ptr, "top") == 0) + { + VAlign = Top; + } + else if (strcmp((const char *) ptr, "middle") == 0) + { + VAlign = Middle; + } + else if (strcmp((const char *) ptr, "bottom") == 0) + { + VAlign = Bottom; + } + else + { + nlwarning(" Unknwown or unsupported valign mode : %s", (const char *) ptr); + } + } + // left margin + ptr = (char*) xmlGetProp( cur, (xmlChar*)"left_margin" ); + if (ptr) + { + fromString((const char*)ptr, LeftMargin); + } + // + ptr = (char*) xmlGetProp( cur, (xmlChar*)"nowrap" ); + if (ptr) + { + NoWrap = convertBool(ptr); + } + // + ptr = (char*) xmlGetProp( cur, (xmlChar*)"bgcolor" ); + if (ptr) + { + BgColor = convertColor(ptr); + } + // + ptr = (char*) xmlGetProp( cur, (xmlChar*)"width" ); + if (ptr) + { + convertPixelsOrRatio((const char *) ptr, WidthWanted, TableRatio); + } + // + ptr = (char*) xmlGetProp( cur, (xmlChar*)"height" ); + if (ptr) + { + fromString((const char*)ptr, Height); + } + // + ptr = (char*) xmlGetProp( cur, (xmlChar*)"ignore_max_width" ); + if (ptr) + { + IgnoreMaxWidth = convertBool(ptr); + } + // + ptr = (char*) xmlGetProp( cur, (xmlChar*)"ignore_min_width" ); + if (ptr) + { + IgnoreMinWidth = convertBool(ptr); + } + // + ptr = (char*) xmlGetProp( cur, (xmlChar*)"add_child_w" ); + if (ptr) + { + AddChildW = convertBool(ptr); + } + + return true; + } + + + // ---------------------------------------------------------------------------- + void CGroupCell::draw () + { + if ( CGroupCell::DebugUICell ) + { + // Draw cell + CViewRenderer &rVR = *CViewRenderer::getInstance(); + rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, _WReal, 1, 0, false, rVR.getBlankTextureId(), CRGBA(0,255,255,255) ); + rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, 1, _HReal, 0, false, rVR.getBlankTextureId(), CRGBA(0,255,255,255) ); + rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+_HReal-1, _WReal, 1, 0, false, rVR.getBlankTextureId(), CRGBA(0,255,255,255) ); + rVR.drawRotFlipBitmap (_RenderLayer, _XReal+_WReal-1, _YReal, 1, _HReal, 0, false, rVR.getBlankTextureId(), CRGBA(0,255,255,255) ); + } + + // Draw the background + if (_UserTexture || BgColor.A != 0) + { + CViewRenderer &rVR = *CViewRenderer::getInstance(); + if (_UserTexture) + { + CRGBA col; + if (BgColor.A == 0 ) + col = CRGBA(255,255,255,255); + else + col = BgColor; + + + if (_TextureScaled && !_TextureTiled) + { + rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, + _WReal, _HReal, + 0, false, + _TextureId, + col ); + } + else + { + if (!_TextureTiled) + { + rVR.draw11RotFlipBitmap (_RenderLayer, _XReal, _YReal, + 0, false, + _TextureId, + col); + } + else + { + rVR.drawRotFlipBitmapTiled(_RenderLayer, _XReal, _YReal, + _WReal, _HReal, + 0, false, + _TextureId, + 0, + col); + } + } + + } + else + { + CRGBA finalColor; + finalColor.modulateFromColor (BgColor, CWidgetManager::getInstance()->getGlobalColor()); + + // Get the parent table + if (getParent ()) + { + CGroupTable *table = static_cast (getParent ()); + finalColor.A = (uint8) (((uint16) table->CurrentAlpha * (uint16) finalColor.A) >> 8); + } + + //nlinfo("Blank Texture"); + rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, _WReal, _HReal, 0, false, rVR.getBlankTextureId(), finalColor); + } + } + + CInterfaceGroup::draw (); + } + + // ---------------------------------------------------------------------------- + sint32 CGroupCell::getMaxUsedW() const + { + return Group->getMaxUsedW(); + } + + // ------------------------------------------------------------------------------------------------ + sint32 CGroupCell::getMinUsedW() const + { + return Group->getMinUsedW(); + } + + + // ---------------------------------------------------------------------------- + void CGroupCell::setTexture(const std::string & TxName) + { + if (TxName.empty() || TxName == "none") + { + _UserTexture = false; + nlinfo("Set no texture"); + } + else + { + nlinfo("Set texture to cell : %s", TxName.c_str()); + _UserTexture = true; + _TextureId.setTexture (TxName.c_str (), 0, 0, -1, -1, false); + } + } + + // ---------------------------------------------------------------------------- + void CGroupCell::setTextureTile(bool tiled) + { + if (tiled) + nlinfo("Set texture is Tiled"); + _TextureTiled = tiled; + } + + // ---------------------------------------------------------------------------- + void CGroupCell::setTextureScale(bool scaled) + { + if (scaled) + nlinfo("Set texture is Scaled : %s"); + _TextureScaled = scaled; + } + + + // ---------------------------------------------------------------------------- + NLMISC_REGISTER_OBJECT(CViewBase, CGroupTable, std::string, "table"); + + CGroupTable::CGroupTable(const TCtorParam ¶m) + : CInterfaceGroup(param), + BgColor(0,0,0,255) + { + _ContentValidated = false; + TableRatio = 0.f; + ForceWidthMin = 0; + Border=0; + CellPadding=0; + CellSpacing=0; + ContinuousUpdate = false; + } + + // ---------------------------------------------------------------------------- + void CGroupTable::addChild (CGroupCell* child) + { + // Cell empty ? + if (_Cells.empty()) + // New line + child->NewLine = true; + + // Cells are moved and resized by the table + child->setParent(this); + child->setParentPos(this); + child->setPosRef(Hotspot_TL); + child->setParentPosRef(Hotspot_TL); + child->setResizeFromChildW(false); + + // Child resize H for cells + child->setResizeFromChildH(false); + + /* // New line ? + if (child->NewLine) + { + // First element + if (_Cells.empty()) + { + child->setParentPos(NULL); + child->setPosRef(Hotspot_TL); + child->setParentPosRef(Hotspot_TL); + } + // New line + else + { + // Look for previous new line + uint i; + for (i=_Cells.size()-1; i>0; i--) + if (_Cells[i]->NewLine) + break; + + child->setParentPos(_Cells[i]); + child->setPosRef(Hotspot_TL); + child->setParentPosRef(Hotspot_BL); + } + } + else + { + nlassert(!_Cells.empty()); + child->setParentPos(_Cells.back()); + child->setPosRef(Hotspot_TL); + child->setParentPosRef(Hotspot_TR); + }*/ + + // Add the child + addGroup(child); + _Cells.push_back(child); + invalidateContent(); + } + + // ---------------------------------------------------------------------------- + CGroupTable::~CGroupTable() + { + /* uint i; + for (i=0; i<_Cells.size(); i++) + delete _Cells[i]; + _Cells.clear ();*/ + } + + + + // ---------------------------------------------------------------------------- + void CGroupTable::updateCoords() + { + if (_Parent) + { + if (ContinuousUpdate) + { + sint parentWidth = std::min(_Parent->getMaxWReal(), _Parent->getWReal()); + if (_LastParentW != (sint) parentWidth) + { + _LastParentW = parentWidth; + _ContentValidated = false; + } + } + if (!_ContentValidated) + { + // Update W and XReal + CInterfaceElement::updateCoords(); + + // *** For each children, update coords, gets min and max values + // *** Get the column sizes, we need to know min for the table + + uint i; + uint column = 0; + _Columns.clear (); + for (i=0; i<_Cells.size(); i++) + { + // Update coords to get XReal + CGroupCell *cell = _Cells[i]; + cell->checkCoords(); + cell->updateCoords(); + + sint32 additionnalWidth = 0; + if (cell->AddChildW) + { + sint width, height; + cell->Group->evalChildrenBBox(true, false, width, height); + additionnalWidth = (sint32) width; + } + + // 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; + } + + // New cell ? + if (cell->NewLine) + column = 0; + + // Resize the array + if (column>=_Columns.size()) + _Columns.resize(column+1); + + // Update sizes + if (cellWidth > _Columns[column].Width) + _Columns[column].Width = cellWidth; + if (cell->WidthMax > _Columns[column].WidthMax) + _Columns[column].WidthMax = cell->WidthMax; + if (cell->TableRatio > _Columns[column].TableRatio) + _Columns[column].TableRatio = cell->TableRatio; + if (cell->WidthWanted + additionnalWidth > _Columns[column].WidthWanted) + _Columns[column].WidthWanted = cell->WidthWanted + additionnalWidth; + if (cell->Height > _Columns[column].Height) + _Columns[column].Height = cell->Height; + + if (_Columns[column].WidthWanted + additionnalWidth) + _Columns[column].WidthMax = _Columns[column].WidthWanted + additionnalWidth; + if (_Columns[column].WidthWanted > _Columns[column].Width) + _Columns[column].Width = _Columns[column].WidthWanted; + + // Next column + column++; + } + + // Width of cells and table borders + sint32 borderWidth = 2*Border + ((sint32)_Columns.size()+1) * CellSpacing + ((sint32)_Columns.size()*2) * CellPadding; + + // 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); + + // Get the width of the table and normalize percent of the cell (sum of TableRatio must == 1) + sint32 tableWidth = 0; + sint32 tableMaxContentWidth = 0; + float ratio = 1; + for (i=0; i<_Columns.size(); i++) + { + tableWidth += _Columns[i].Width; + tableMaxContentWidth += _Columns[i].WidthMax; + _Columns[i].TableRatio = std::min(_Columns[i].TableRatio, ratio); + ratio -= _Columns[i].TableRatio; + } + + // Eval table size with all percent cells resized + sint32 tableWidthSizeAfterPercent = tableWidth; + for (i=0; i<_Columns.size(); i++) + { + if (_Columns[i].TableRatio > 0) + { + // Size of the cell with its percent + sint32 me = (sint32)((float)_Columns[i].Width / _Columns[i].TableRatio); + + tableWidthSizeAfterPercent = std::min(tableWidthMax, std::max(tableWidthSizeAfterPercent, me)); + } + } + for (i=0; i<_Columns.size(); i++) + { + if (_Columns[i].TableRatio > 0) + { + // Size of the other cells + sint32 cellSize; + if (_Columns[i].TableRatio < 1.f) + cellSize = (sint32)((float)tableWidthSizeAfterPercent*_Columns[i].TableRatio) + 1; + else + cellSize = 10000; + + sint32 diff = std::min(tableWidthMax, (std::max(_Columns[i].Width, cellSize) - _Columns[i].Width)+tableWidth) - tableWidth; + tableWidth += diff; + _Columns[i].Width += diff; + // tableMaxContentWidth = std::max(tableMaxContentWidth, (sint32)((float)_Columns[i].WidthMax / _Columns[i].TableRatio)); + } + } + sint32 space = tableWidthMax - tableWidth; + + // Normalize percent window + for (i=0; i<_Columns.size(); i++) + { + // Width for the cell + sint32 diff = (sint32)((float)tableWidth*_Columns[i].TableRatio) - _Columns[i].Width; + diff = std::min(diff, space); + if (diff > 0) + { + _Columns[i].Width += diff; + tableWidth += diff; + space -= diff; + } + } + + // Ok, now percent window are nomralized + // Evaluate space to put in windows + sint32 finalWidth = std::max(tableWidthMin, std::min(std::max(tableWidth, tableMaxContentWidth), tableWidthMax)); + space = finalWidth - tableWidth; + if (space > 0) + { + // First give to percent cells + for (i=0; i<_Columns.size(); i++) + { + // Width for the cell + sint32 dif = (sint32)((float)space*_Columns[i].TableRatio); + _Columns[i].Width += dif; + tableWidth += dif; + } + + // Some space ? + space = finalWidth - tableWidth; + + if (space > 0) + { + // Then add in wanted Width cells + for (i=0; i<_Columns.size(); i++) + { + // Width for the cell + if (_Columns[i].Width < _Columns[i].WidthWanted) + { + sint32 dif = std::min(space, _Columns[i].WidthWanted-_Columns[i].Width); + _Columns[i].Width += dif; + space -= dif; + } + } + + if (space > 0) + { + // All cells with sizewanted are full + // Distribute remaining space in resizable cells that have a WidthMax + sint32 sumDeltaWidth = 0; + for (i=0; i<_Columns.size(); i++) + { + if ((_Columns[i].TableRatio == 0) && (_Columns[i].WidthWanted == 0)) + sumDeltaWidth += std::max ((sint32)0, _Columns[i].WidthMax - _Columns[i].Width); + } + if (sumDeltaWidth) + { + sint32 toDistribute = space; + for (i=0; i<_Columns.size(); i++) + { + if ((_Columns[i].TableRatio == 0) && (_Columns[i].WidthWanted == 0)) + { + sint32 marge = std::max ((sint32)0, _Columns[i].WidthMax - _Columns[i].Width); + sint32 cellPart = std::min(marge, std::min(space, 1 + marge * toDistribute / sumDeltaWidth)); + if (cellPart) + { + _Columns[i].Width += cellPart; + space -= cellPart; + } + } + } + } + + if (space > 0) + { + // All cells with sizemax are full + // Distribute remaining space in others resizable cells + sumDeltaWidth = 0; + for (i=0; i<_Columns.size(); i++) + { + if ((_Columns[i].TableRatio == 0) && (_Columns[i].WidthWanted == 0)) + sumDeltaWidth++; + } + if (sumDeltaWidth) + { + sint32 toDistribute = space; + for (i=0; i<_Columns.size(); i++) + { + if ((_Columns[i].TableRatio == 0) && (_Columns[i].WidthWanted == 0)) + { + sint32 cellPart = std::min(space, 1 + toDistribute / sumDeltaWidth); + _Columns[i].Width += cellPart; + space -= cellPart; + } + } + } + + if (space > 0) + { + // No cells with sizemax not sizewanted, resize size wanted + // Distribute remaining space in others resizable cells + sumDeltaWidth = 0; + for (i=0; i<_Columns.size(); i++) + { + if ((_Columns[i].TableRatio == 0) && (_Columns[i].WidthWanted != 0)) + sumDeltaWidth++; + } + if (sumDeltaWidth) + { + sint32 toDistribute = space; + for (i=0; i<_Columns.size(); i++) + { + if ((_Columns[i].TableRatio == 0) && (_Columns[i].WidthWanted != 0)) + { + sint32 cellPart = std::min(space, 1 + toDistribute / sumDeltaWidth); + _Columns[i].Width += cellPart; + space -= cellPart; + } + } + } + } + } + } + } + } + + // *** Now we know each column width, resize cells and get the height for each row + + column = 0; + sint32 row = 0; + sint32 currentX = Border + CellSpacing + CellPadding; + _Rows.clear (); + for (i=0; i<_Cells.size(); i++) + { + CGroupCell *cell = _Cells[i]; + // New cell ? + if (cell->NewLine) + { + column = 0; + currentX = Border + CellSpacing + CellPadding; + _Rows.push_back(CRow()); + } + + // Set the x and width + + // Check align + sint32 alignmentX = 0; + sint32 widthReduceX = 0; + if (cell->WidthMax < _Columns[column].Width) + { + switch (cell->Align) + { + case CGroupCell::Center: + alignmentX = (_Columns[column].Width - cell->WidthMax) / 2; + widthReduceX = alignmentX * 2; + break; + case CGroupCell::Right: + alignmentX = _Columns[column].Width - cell->WidthMax; + widthReduceX = alignmentX; + break; + default: + break; + } + } + + cell->setX(currentX); + cell->setW(_Columns[column].Width); + + cell->Group->setX(alignmentX+cell->LeftMargin); + cell->Group->setW(_Columns[column].Width - widthReduceX); + cell->Group->CInterfaceElement::updateCoords(); + + // Update coords to get H + cell->Group->checkCoords(); + cell->Group->updateCoords(); + + // Resize the row array + _Rows.back().Height = std::max(cell->Height, std::max(_Rows.back().Height, (sint32)cell->Group->getH())); + + // Next column + currentX += _Columns[column].Width + 2*CellPadding + CellSpacing; + column ++; + } + + // Set cell Y + row = 0; + sint32 currentY = -(Border + CellSpacing + CellPadding); + for (i=0; i<_Cells.size(); i++) + { + // New cell ? + CGroupCell *cell = _Cells[i]; + if ((i != 0) && (cell->NewLine)) + { + if (_Rows[row].Height != 0) + { + currentY -= _Rows[row].Height + 2*CellPadding + CellSpacing; + } + row++; + } + + // Check align + sint32 alignmentY = 0; + if ((sint32)cell->Group->getH() < _Rows[row].Height) + { + switch (cell->VAlign) + { + case CGroupCell::Middle: + alignmentY = (_Rows[row].Height - (sint32)cell->Group->getH()) / 2; + break; + case CGroupCell::Bottom: + alignmentY = _Rows[row].Height - (sint32)cell->Group->getH(); + break; + default: + break; + } + } + + cell->setY(currentY); + cell->setH (_Rows[row].Height); + cell->Group->setY(-alignmentY); + } + + // Resize the table + setW(finalWidth+borderWidth-_LastParentW); + if (!_Rows.empty()) + currentY -= _Rows[row].Height + CellPadding + CellSpacing + Border; + setH(-currentY); + + // All done + } + } + + + CInterfaceGroup::updateCoords(); + + + + + // Validated + _ContentValidated = true; + } + + // ---------------------------------------------------------------------------- + void CGroupTable::checkCoords () + { + if (_Parent != NULL) + { + sint parentWidth = std::min(_Parent->getMaxWReal(), _Parent->getWReal()); + if (_LastParentW != (sint) parentWidth) + { + if (ContinuousUpdate) + { + _LastParentW = parentWidth; + invalidateContent(); + } + else + { + + CCtrlBase *pCB = CWidgetManager::getInstance()->getCapturePointerLeft(); + if (pCB != NULL) + { + CCtrlResizer *pCR = dynamic_cast(pCB); + if (pCR != NULL) + { + // We are resizing !!!! + } + else + { + _LastParentW = parentWidth; + invalidateContent(); + } + } + else + { + _LastParentW = parentWidth; + invalidateContent(); + } + } + } + } + CInterfaceGroup::checkCoords(); + } + + // ---------------------------------------------------------------------------- + void CGroupTable::onInvalidateContent() + { + _ContentValidated = false; + invalidateCoords(); + } + + // ---------------------------------------------------------------------------- + sint32 CGroupTable::getMaxUsedW() const + { + uint i; + uint column = 0; + vector columns; + columns.clear (); + for (i=0; i<_Cells.size(); i++) + { + // Update coords to get XReal + CGroupCell *cell = _Cells[i]; + cell->checkCoords(); + cell->updateCoords(); + + // Get width min and max + sint32 cellWidthMax = cell->getMaxUsedW(); + + // New cell ? + if (cell->NewLine) + column = 0; + + // Resize the array + if (column>=columns.size()) + columns.resize(column+1, 0); + + // Update sizes + if (cellWidthMax > columns[column]) + columns[column] = cellWidthMax; + if (cell->WidthWanted) + columns[column] = cell->WidthWanted; + + // Hack to force a table with ratio to be large + sint32 cellRatio = (sint32)ceil(cell->TableRatio * 1024.f); + if (cellRatio > columns[column]) + columns[column] = cellRatio; + + // Next column + column++; + } + + // Sum + sint32 maxWidth = 0; + for (i=0; i columns; + columns.clear (); + for (i=0; i<_Cells.size(); i++) + { + // Update coords to get XReal + CGroupCell *cell = _Cells[i]; + cell->checkCoords(); + cell->updateCoords(); + + // Get width min and max + sint32 cellWidthMin = cell->getMinUsedW(); + + // New cell ? + if (cell->NewLine) + column = 0; + + // Resize the array + if (column>=columns.size()) + columns.resize(column+1, 0); + + // Update sizes + if (cellWidthMin > columns[column]) + columns[column] = cellWidthMin; + if (cell->WidthWanted) + columns[column] = cell->WidthWanted; + + // Next column + column++; + } + + // Sum + sint32 maxWidth = 0; + for (i=0; iisGroupContainer()) + { + CGroupContainer *gc = static_cast(gr); + CurrentAlpha = gc->getCurrentContainerAlpha(); + break; + } + gr = gr->getParent(); + } + + // Not found ? + if (gr == NULL) + CurrentAlpha = 255; + + if (!_Columns.empty() && !_Rows.empty() && BgColor.A) + { + sint32 border = Border + CellSpacing + CellPadding; + if (border) + { + CRGBA finalColor; + finalColor.modulateFromColor (BgColor, CWidgetManager::getInstance()->getGlobalColor()); + finalColor.A = CurrentAlpha; + + // Draw the top and bottom lines + CViewRenderer &rVR = *CViewRenderer::getInstance(); + rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, _WReal, border, 0, false, rVR.getBlankTextureId(), finalColor); + rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal-border+_HReal, _WReal, border, 0, false, rVR.getBlankTextureId(), finalColor); + + // Draw the left and right lines + sint32 insideHeight = std::max((sint32)0, (sint32)_HReal - (sint32)2*border); + rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+border, border, insideHeight, 0, false, rVR.getBlankTextureId(), finalColor); + rVR.drawRotFlipBitmap (_RenderLayer, _XReal+_WReal-border, _YReal+border, border, insideHeight, 0, false, rVR.getBlankTextureId(), finalColor); + + // Draw the inside borders + sint32 insideWidth = 2*CellPadding + CellSpacing; + if (insideWidth) + { + // Draw the inside verticals + uint i; + sint32 x = _XReal + _Columns[0].Width + border; + for (i=1; i<_Columns.size(); i++) + { + rVR.drawRotFlipBitmap (_RenderLayer, x, _YReal+border, insideWidth, insideHeight, 0, false, rVR.getBlankTextureId(), finalColor); + x += _Columns[i].Width + insideWidth; + } + + // Draw the inside horizontals + sint32 y = _YReal + _HReal - border - _Rows[0].Height; + if (_Rows[0].Height != 0) + { + y -= insideWidth; + } + for (i=1; i<_Rows.size(); i++) + { + uint j; + x = _XReal + border; + if (_Rows[i].Height != 0) + { + for (j=0; j<_Columns.size(); j++) + { + rVR.drawRotFlipBitmap (_RenderLayer, x, y, _Columns[j].Width, insideWidth, 0, false, rVR.getBlankTextureId(), finalColor); + x += _Columns[j].Width + insideWidth; + } + y -= _Rows[i].Height+ insideWidth; + } + } + } + } + } + + CInterfaceGroup::draw (); + } + + // ------------------------------------------------------------------------------------------------ + bool CGroupTable::parse (xmlNodePtr cur, CInterfaceGroup * parentGroup) + { + if (!CInterfaceGroup::parse(cur, parentGroup)) return false; + // + CXMLAutoPtr ptr; + ptr = (char*) xmlGetProp( cur, (xmlChar*)"border" ); + if (ptr) + { + fromString((const char*)ptr, Border); + } + // + ptr = (char*) xmlGetProp( cur, (xmlChar*)"cellpadding" ); + if (ptr) + { + fromString((const char*)ptr, CellPadding); + } + // + ptr = (char*) xmlGetProp( cur, (xmlChar*)"cellspacing" ); + if (ptr) + { + fromString((const char*)ptr, CellSpacing); + } + // + ptr = (char*) xmlGetProp( cur, (xmlChar*)"bgcolor" ); + if (ptr) + { + BgColor = convertColor((const char *) ptr); + } + // + ptr = (char*) xmlGetProp( cur, (xmlChar*)"width" ); + if (ptr) + { + convertPixelsOrRatio(ptr, ForceWidthMin, TableRatio); + } + // + ptr = (char*) xmlGetProp( cur, (xmlChar*)"continuous_update" ); + if (ptr) + { + ContinuousUpdate = convertBool(ptr); + } + // parse cells + uint row = 0; + xmlNodePtr currRow = cur->children; + while (currRow != NULL) + { + // look for 'TR' markup + if (strcmp((char*)currRow->name,"TR") == 0) + { + // found a row, parse cells inside + xmlNodePtr currCol = currRow->children; + bool newLine = true; + uint column = 0; + while (currCol != NULL) + { + // look for 'TR' markup + if (strcmp((char*)currCol->name,"TD") == 0) + { + CGroupCell *cell = new CGroupCell(CViewBase::TCtorParam()); + if (cell->parse(currCol, this, column, row)) + { + cell->NewLine = newLine; + newLine = false; + addChild(cell); + } + else + { + delete cell; + } + ++ column; + } + currCol = currCol->next; + } + ++ row; + } + currRow = currRow->next; + } + + return true; + } + +} + diff --git a/code/ryzom/client/src/interface_v3/group_html.h b/code/ryzom/client/src/interface_v3/group_html.h index 9b21f01ed..d5c30cf1f 100644 --- a/code/ryzom/client/src/interface_v3/group_html.h +++ b/code/ryzom/client/src/interface_v3/group_html.h @@ -28,7 +28,7 @@ #include "nel/gui/group_scrolltext.h" #include "nel/gui/group_tree.h" #include "nel/gui/ctrl_button.h" -#include "group_table.h" +#include "nel/gui/group_table.h" typedef std::map TStyle; diff --git a/code/ryzom/client/src/interface_v3/group_table.cpp b/code/ryzom/client/src/interface_v3/group_table.cpp deleted file mode 100644 index 4711ed4ca..000000000 --- a/code/ryzom/client/src/interface_v3/group_table.cpp +++ /dev/null @@ -1,1074 +0,0 @@ -// 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 "group_table.h" -#include "nel/gui/widget_manager.h" -#include "nel/gui/interface_element.h" -#include "nel/gui/view_bitmap.h" -#include "nel/gui/view_text_id.h" -#include "nel/gui/group_container.h" -#include "nel/misc/i_xml.h" -#include "nel/misc/i18n.h" -#include "nel/misc/xml_auto_ptr.h" - -using namespace std; -using namespace NLMISC; - - -bool CGroupCell::DebugUICell = false; - -// ---------------------------------------------------------------------------- -CGroupCell::CGroupCell(const TCtorParam ¶m) -: CInterfaceGroup(param), - BgColor (0,0,0,0) - -{ - NewLine = false; - TableRatio = 0.f; - WidthWanted = 0; - Height = 0; - Group = new CInterfaceGroup(CViewBase::TCtorParam()); - Align = Left; - VAlign = Top; - LeftMargin = 0; - NoWrap = false; - IgnoreMaxWidth = false; - IgnoreMinWidth = false; - AddChildW = false; - _UserTexture = false; - _TextureTiled = false; - _TextureScaled = false; - setEnclosedGroupDefaultParams(); - addGroup (Group); -} - -// ---------------------------------------------------------------------------- -void CGroupCell::setEnclosedGroupDefaultParams() -{ - nlassert(Group); - // Cells are moved and resized by the table - Group->setParent(this); - Group->setParentPos(this); - Group->setPosRef(Hotspot_TL); - Group->setParentPosRef(Hotspot_TL); - Group->setResizeFromChildW(false); - Group->setResizeFromChildH(true); -} - -// ---------------------------------------------------------------------------- -bool CGroupCell::parse(xmlNodePtr cur, CInterfaceGroup * parentGroup, uint columnIndex, uint rowIndex) -{ - CXMLAutoPtr ptr; - ptr = (char*) xmlGetProp( cur, (xmlChar*)"id"); - if (!ptr) - { - // no id was given, so create one - std::string newId = NLMISC::toString("cell_%d_%d", (int) columnIndex, (int) rowIndex); - xmlSetProp(cur, (const xmlChar*) "id", (const xmlChar*) newId.c_str()); - } - // parse enclosed group - if (!Group->parse(cur, this)) return false; - Group->setId(parentGroup->getId() + Group->getId()); - setEnclosedGroupDefaultParams(); - // parse the children - bool ok = CWidgetManager::parser->parseGroupChildren(cur, Group, false); - if (!ok) return false; - // align - ptr = (char*) xmlGetProp( cur, (xmlChar*)"align" ); - if (ptr) - { - if (strcmp((const char *) ptr, "left") == 0) - { - Align = Left; - } - else if (strcmp((const char *) ptr, "right") == 0) - { - Align = Right; - } - else if (strcmp((const char *) ptr, "center") == 0) - { - Align = Center; - } - else - { - nlwarning(" Unknwown or unsupported align mode : %s", (const char *) ptr); - } - } - // v-align - ptr = (char*) xmlGetProp( cur, (xmlChar*)"valign" ); - if (ptr) - { - if (strcmp((const char *) ptr, "top") == 0) - { - VAlign = Top; - } - else if (strcmp((const char *) ptr, "middle") == 0) - { - VAlign = Middle; - } - else if (strcmp((const char *) ptr, "bottom") == 0) - { - VAlign = Bottom; - } - else - { - nlwarning(" Unknwown or unsupported valign mode : %s", (const char *) ptr); - } - } - // left margin - ptr = (char*) xmlGetProp( cur, (xmlChar*)"left_margin" ); - if (ptr) - { - fromString((const char*)ptr, LeftMargin); - } - // - ptr = (char*) xmlGetProp( cur, (xmlChar*)"nowrap" ); - if (ptr) - { - NoWrap = convertBool(ptr); - } - // - ptr = (char*) xmlGetProp( cur, (xmlChar*)"bgcolor" ); - if (ptr) - { - BgColor = convertColor(ptr); - } - // - ptr = (char*) xmlGetProp( cur, (xmlChar*)"width" ); - if (ptr) - { - convertPixelsOrRatio((const char *) ptr, WidthWanted, TableRatio); - } - // - ptr = (char*) xmlGetProp( cur, (xmlChar*)"height" ); - if (ptr) - { - fromString((const char*)ptr, Height); - } - // - ptr = (char*) xmlGetProp( cur, (xmlChar*)"ignore_max_width" ); - if (ptr) - { - IgnoreMaxWidth = convertBool(ptr); - } - // - ptr = (char*) xmlGetProp( cur, (xmlChar*)"ignore_min_width" ); - if (ptr) - { - IgnoreMinWidth = convertBool(ptr); - } - // - ptr = (char*) xmlGetProp( cur, (xmlChar*)"add_child_w" ); - if (ptr) - { - AddChildW = convertBool(ptr); - } - - return true; -} - - -// ---------------------------------------------------------------------------- -void CGroupCell::draw () -{ - if ( CGroupCell::DebugUICell ) - { - // Draw cell - CViewRenderer &rVR = *CViewRenderer::getInstance(); - rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, _WReal, 1, 0, false, rVR.getBlankTextureId(), CRGBA(0,255,255,255) ); - rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, 1, _HReal, 0, false, rVR.getBlankTextureId(), CRGBA(0,255,255,255) ); - rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+_HReal-1, _WReal, 1, 0, false, rVR.getBlankTextureId(), CRGBA(0,255,255,255) ); - rVR.drawRotFlipBitmap (_RenderLayer, _XReal+_WReal-1, _YReal, 1, _HReal, 0, false, rVR.getBlankTextureId(), CRGBA(0,255,255,255) ); - } - - // Draw the background - if (_UserTexture || BgColor.A != 0) - { - CViewRenderer &rVR = *CViewRenderer::getInstance(); - if (_UserTexture) - { - CRGBA col; - if (BgColor.A == 0 ) - col = CRGBA(255,255,255,255); - else - col = BgColor; - - - if (_TextureScaled && !_TextureTiled) - { - rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, - _WReal, _HReal, - 0, false, - _TextureId, - col ); - } - else - { - if (!_TextureTiled) - { - rVR.draw11RotFlipBitmap (_RenderLayer, _XReal, _YReal, - 0, false, - _TextureId, - col); - } - else - { - rVR.drawRotFlipBitmapTiled(_RenderLayer, _XReal, _YReal, - _WReal, _HReal, - 0, false, - _TextureId, - 0, - col); - } - } - - } - else - { - CRGBA finalColor; - finalColor.modulateFromColor (BgColor, CWidgetManager::getInstance()->getGlobalColor()); - - // Get the parent table - if (getParent ()) - { - CGroupTable *table = static_cast (getParent ()); - finalColor.A = (uint8) (((uint16) table->CurrentAlpha * (uint16) finalColor.A) >> 8); - } - - //nlinfo("Blank Texture"); - rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, _WReal, _HReal, 0, false, rVR.getBlankTextureId(), finalColor); - } - } - - CInterfaceGroup::draw (); -} - -// ---------------------------------------------------------------------------- -sint32 CGroupCell::getMaxUsedW() const -{ - return Group->getMaxUsedW(); -} - -// ------------------------------------------------------------------------------------------------ -sint32 CGroupCell::getMinUsedW() const -{ - return Group->getMinUsedW(); -} - - -// ---------------------------------------------------------------------------- -void CGroupCell::setTexture(const std::string & TxName) -{ - if (TxName.empty() || TxName == "none") - { - _UserTexture = false; - nlinfo("Set no texture"); - } - else - { - nlinfo("Set texture to cell : %s", TxName.c_str()); - _UserTexture = true; - _TextureId.setTexture (TxName.c_str (), 0, 0, -1, -1, false); - } -} - -// ---------------------------------------------------------------------------- -void CGroupCell::setTextureTile(bool tiled) -{ - if (tiled) - nlinfo("Set texture is Tiled"); - _TextureTiled = tiled; -} - -// ---------------------------------------------------------------------------- -void CGroupCell::setTextureScale(bool scaled) -{ - if (scaled) - nlinfo("Set texture is Scaled : %s"); - _TextureScaled = scaled; -} - - -// ---------------------------------------------------------------------------- -NLMISC_REGISTER_OBJECT(CViewBase, CGroupTable, std::string, "table"); - -CGroupTable::CGroupTable(const TCtorParam ¶m) -: CInterfaceGroup(param), - BgColor(0,0,0,255) -{ - _ContentValidated = false; - TableRatio = 0.f; - ForceWidthMin = 0; - Border=0; - CellPadding=0; - CellSpacing=0; - ContinuousUpdate = false; -} - -// ---------------------------------------------------------------------------- -void CGroupTable::addChild (CGroupCell* child) -{ - // Cell empty ? - if (_Cells.empty()) - // New line - child->NewLine = true; - - // Cells are moved and resized by the table - child->setParent(this); - child->setParentPos(this); - child->setPosRef(Hotspot_TL); - child->setParentPosRef(Hotspot_TL); - child->setResizeFromChildW(false); - - // Child resize H for cells - child->setResizeFromChildH(false); - -/* // New line ? - if (child->NewLine) - { - // First element - if (_Cells.empty()) - { - child->setParentPos(NULL); - child->setPosRef(Hotspot_TL); - child->setParentPosRef(Hotspot_TL); - } - // New line - else - { - // Look for previous new line - uint i; - for (i=_Cells.size()-1; i>0; i--) - if (_Cells[i]->NewLine) - break; - - child->setParentPos(_Cells[i]); - child->setPosRef(Hotspot_TL); - child->setParentPosRef(Hotspot_BL); - } - } - else - { - nlassert(!_Cells.empty()); - child->setParentPos(_Cells.back()); - child->setPosRef(Hotspot_TL); - child->setParentPosRef(Hotspot_TR); - }*/ - - // Add the child - addGroup(child); - _Cells.push_back(child); - invalidateContent(); -} - -// ---------------------------------------------------------------------------- -CGroupTable::~CGroupTable() -{ -/* uint i; - for (i=0; i<_Cells.size(); i++) - delete _Cells[i]; - _Cells.clear ();*/ -} - - - -// ---------------------------------------------------------------------------- -void CGroupTable::updateCoords() -{ - if (_Parent) - { - if (ContinuousUpdate) - { - sint parentWidth = std::min(_Parent->getMaxWReal(), _Parent->getWReal()); - if (_LastParentW != (sint) parentWidth) - { - _LastParentW = parentWidth; - _ContentValidated = false; - } - } - if (!_ContentValidated) - { - // Update W and XReal - CInterfaceElement::updateCoords(); - - // *** For each children, update coords, gets min and max values - // *** Get the column sizes, we need to know min for the table - - uint i; - uint column = 0; - _Columns.clear (); - for (i=0; i<_Cells.size(); i++) - { - // Update coords to get XReal - CGroupCell *cell = _Cells[i]; - cell->checkCoords(); - cell->updateCoords(); - - sint32 additionnalWidth = 0; - if (cell->AddChildW) - { - sint width, height; - cell->Group->evalChildrenBBox(true, false, width, height); - additionnalWidth = (sint32) width; - } - - // 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; - } - - // New cell ? - if (cell->NewLine) - column = 0; - - // Resize the array - if (column>=_Columns.size()) - _Columns.resize(column+1); - - // Update sizes - if (cellWidth > _Columns[column].Width) - _Columns[column].Width = cellWidth; - if (cell->WidthMax > _Columns[column].WidthMax) - _Columns[column].WidthMax = cell->WidthMax; - if (cell->TableRatio > _Columns[column].TableRatio) - _Columns[column].TableRatio = cell->TableRatio; - if (cell->WidthWanted + additionnalWidth > _Columns[column].WidthWanted) - _Columns[column].WidthWanted = cell->WidthWanted + additionnalWidth; - if (cell->Height > _Columns[column].Height) - _Columns[column].Height = cell->Height; - - if (_Columns[column].WidthWanted + additionnalWidth) - _Columns[column].WidthMax = _Columns[column].WidthWanted + additionnalWidth; - if (_Columns[column].WidthWanted > _Columns[column].Width) - _Columns[column].Width = _Columns[column].WidthWanted; - - // Next column - column++; - } - - // Width of cells and table borders - sint32 borderWidth = 2*Border + ((sint32)_Columns.size()+1) * CellSpacing + ((sint32)_Columns.size()*2) * CellPadding; - - // 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); - - // Get the width of the table and normalize percent of the cell (sum of TableRatio must == 1) - sint32 tableWidth = 0; - sint32 tableMaxContentWidth = 0; - float ratio = 1; - for (i=0; i<_Columns.size(); i++) - { - tableWidth += _Columns[i].Width; - tableMaxContentWidth += _Columns[i].WidthMax; - _Columns[i].TableRatio = std::min(_Columns[i].TableRatio, ratio); - ratio -= _Columns[i].TableRatio; - } - - // Eval table size with all percent cells resized - sint32 tableWidthSizeAfterPercent = tableWidth; - for (i=0; i<_Columns.size(); i++) - { - if (_Columns[i].TableRatio > 0) - { - // Size of the cell with its percent - sint32 me = (sint32)((float)_Columns[i].Width / _Columns[i].TableRatio); - - tableWidthSizeAfterPercent = std::min(tableWidthMax, std::max(tableWidthSizeAfterPercent, me)); - } - } - for (i=0; i<_Columns.size(); i++) - { - if (_Columns[i].TableRatio > 0) - { - // Size of the other cells - sint32 cellSize; - if (_Columns[i].TableRatio < 1.f) - cellSize = (sint32)((float)tableWidthSizeAfterPercent*_Columns[i].TableRatio) + 1; - else - cellSize = 10000; - - sint32 diff = std::min(tableWidthMax, (std::max(_Columns[i].Width, cellSize) - _Columns[i].Width)+tableWidth) - tableWidth; - tableWidth += diff; - _Columns[i].Width += diff; - // tableMaxContentWidth = std::max(tableMaxContentWidth, (sint32)((float)_Columns[i].WidthMax / _Columns[i].TableRatio)); - } - } - sint32 space = tableWidthMax - tableWidth; - - // Normalize percent window - for (i=0; i<_Columns.size(); i++) - { - // Width for the cell - sint32 diff = (sint32)((float)tableWidth*_Columns[i].TableRatio) - _Columns[i].Width; - diff = std::min(diff, space); - if (diff > 0) - { - _Columns[i].Width += diff; - tableWidth += diff; - space -= diff; - } - } - - // Ok, now percent window are nomralized - // Evaluate space to put in windows - sint32 finalWidth = std::max(tableWidthMin, std::min(std::max(tableWidth, tableMaxContentWidth), tableWidthMax)); - space = finalWidth - tableWidth; - if (space > 0) - { - // First give to percent cells - for (i=0; i<_Columns.size(); i++) - { - // Width for the cell - sint32 dif = (sint32)((float)space*_Columns[i].TableRatio); - _Columns[i].Width += dif; - tableWidth += dif; - } - - // Some space ? - space = finalWidth - tableWidth; - - if (space > 0) - { - // Then add in wanted Width cells - for (i=0; i<_Columns.size(); i++) - { - // Width for the cell - if (_Columns[i].Width < _Columns[i].WidthWanted) - { - sint32 dif = std::min(space, _Columns[i].WidthWanted-_Columns[i].Width); - _Columns[i].Width += dif; - space -= dif; - } - } - - if (space > 0) - { - // All cells with sizewanted are full - // Distribute remaining space in resizable cells that have a WidthMax - sint32 sumDeltaWidth = 0; - for (i=0; i<_Columns.size(); i++) - { - if ((_Columns[i].TableRatio == 0) && (_Columns[i].WidthWanted == 0)) - sumDeltaWidth += std::max ((sint32)0, _Columns[i].WidthMax - _Columns[i].Width); - } - if (sumDeltaWidth) - { - sint32 toDistribute = space; - for (i=0; i<_Columns.size(); i++) - { - if ((_Columns[i].TableRatio == 0) && (_Columns[i].WidthWanted == 0)) - { - sint32 marge = std::max ((sint32)0, _Columns[i].WidthMax - _Columns[i].Width); - sint32 cellPart = std::min(marge, std::min(space, 1 + marge * toDistribute / sumDeltaWidth)); - if (cellPart) - { - _Columns[i].Width += cellPart; - space -= cellPart; - } - } - } - } - - if (space > 0) - { - // All cells with sizemax are full - // Distribute remaining space in others resizable cells - sumDeltaWidth = 0; - for (i=0; i<_Columns.size(); i++) - { - if ((_Columns[i].TableRatio == 0) && (_Columns[i].WidthWanted == 0)) - sumDeltaWidth++; - } - if (sumDeltaWidth) - { - sint32 toDistribute = space; - for (i=0; i<_Columns.size(); i++) - { - if ((_Columns[i].TableRatio == 0) && (_Columns[i].WidthWanted == 0)) - { - sint32 cellPart = std::min(space, 1 + toDistribute / sumDeltaWidth); - _Columns[i].Width += cellPart; - space -= cellPart; - } - } - } - - if (space > 0) - { - // No cells with sizemax not sizewanted, resize size wanted - // Distribute remaining space in others resizable cells - sumDeltaWidth = 0; - for (i=0; i<_Columns.size(); i++) - { - if ((_Columns[i].TableRatio == 0) && (_Columns[i].WidthWanted != 0)) - sumDeltaWidth++; - } - if (sumDeltaWidth) - { - sint32 toDistribute = space; - for (i=0; i<_Columns.size(); i++) - { - if ((_Columns[i].TableRatio == 0) && (_Columns[i].WidthWanted != 0)) - { - sint32 cellPart = std::min(space, 1 + toDistribute / sumDeltaWidth); - _Columns[i].Width += cellPart; - space -= cellPart; - } - } - } - } - } - } - } - } - - // *** Now we know each column width, resize cells and get the height for each row - - column = 0; - sint32 row = 0; - sint32 currentX = Border + CellSpacing + CellPadding; - _Rows.clear (); - for (i=0; i<_Cells.size(); i++) - { - CGroupCell *cell = _Cells[i]; - // New cell ? - if (cell->NewLine) - { - column = 0; - currentX = Border + CellSpacing + CellPadding; - _Rows.push_back(CRow()); - } - - // Set the x and width - - // Check align - sint32 alignmentX = 0; - sint32 widthReduceX = 0; - if (cell->WidthMax < _Columns[column].Width) - { - switch (cell->Align) - { - case CGroupCell::Center: - alignmentX = (_Columns[column].Width - cell->WidthMax) / 2; - widthReduceX = alignmentX * 2; - break; - case CGroupCell::Right: - alignmentX = _Columns[column].Width - cell->WidthMax; - widthReduceX = alignmentX; - break; - default: - break; - } - } - - cell->setX(currentX); - cell->setW(_Columns[column].Width); - - cell->Group->setX(alignmentX+cell->LeftMargin); - cell->Group->setW(_Columns[column].Width - widthReduceX); - cell->Group->CInterfaceElement::updateCoords(); - - // Update coords to get H - cell->Group->checkCoords(); - cell->Group->updateCoords(); - - // Resize the row array - _Rows.back().Height = std::max(cell->Height, std::max(_Rows.back().Height, (sint32)cell->Group->getH())); - - // Next column - currentX += _Columns[column].Width + 2*CellPadding + CellSpacing; - column ++; - } - - // Set cell Y - row = 0; - sint32 currentY = -(Border + CellSpacing + CellPadding); - for (i=0; i<_Cells.size(); i++) - { - // New cell ? - CGroupCell *cell = _Cells[i]; - if ((i != 0) && (cell->NewLine)) - { - if (_Rows[row].Height != 0) - { - currentY -= _Rows[row].Height + 2*CellPadding + CellSpacing; - } - row++; - } - - // Check align - sint32 alignmentY = 0; - if ((sint32)cell->Group->getH() < _Rows[row].Height) - { - switch (cell->VAlign) - { - case CGroupCell::Middle: - alignmentY = (_Rows[row].Height - (sint32)cell->Group->getH()) / 2; - break; - case CGroupCell::Bottom: - alignmentY = _Rows[row].Height - (sint32)cell->Group->getH(); - break; - default: - break; - } - } - - cell->setY(currentY); - cell->setH (_Rows[row].Height); - cell->Group->setY(-alignmentY); - } - - // Resize the table - setW(finalWidth+borderWidth-_LastParentW); - if (!_Rows.empty()) - currentY -= _Rows[row].Height + CellPadding + CellSpacing + Border; - setH(-currentY); - - // All done - } - } - - - CInterfaceGroup::updateCoords(); - - - - - // Validated - _ContentValidated = true; -} - -// ---------------------------------------------------------------------------- -void CGroupTable::checkCoords () -{ - if (_Parent != NULL) - { - sint parentWidth = std::min(_Parent->getMaxWReal(), _Parent->getWReal()); - if (_LastParentW != (sint) parentWidth) - { - if (ContinuousUpdate) - { - _LastParentW = parentWidth; - invalidateContent(); - } - else - { - - CCtrlBase *pCB = CWidgetManager::getInstance()->getCapturePointerLeft(); - if (pCB != NULL) - { - CCtrlResizer *pCR = dynamic_cast(pCB); - if (pCR != NULL) - { - // We are resizing !!!! - } - else - { - _LastParentW = parentWidth; - invalidateContent(); - } - } - else - { - _LastParentW = parentWidth; - invalidateContent(); - } - } - } - } - CInterfaceGroup::checkCoords(); -} - -// ---------------------------------------------------------------------------- -void CGroupTable::onInvalidateContent() -{ - _ContentValidated = false; - invalidateCoords(); -} - -// ---------------------------------------------------------------------------- -sint32 CGroupTable::getMaxUsedW() const -{ - uint i; - uint column = 0; - vector columns; - columns.clear (); - for (i=0; i<_Cells.size(); i++) - { - // Update coords to get XReal - CGroupCell *cell = _Cells[i]; - cell->checkCoords(); - cell->updateCoords(); - - // Get width min and max - sint32 cellWidthMax = cell->getMaxUsedW(); - - // New cell ? - if (cell->NewLine) - column = 0; - - // Resize the array - if (column>=columns.size()) - columns.resize(column+1, 0); - - // Update sizes - if (cellWidthMax > columns[column]) - columns[column] = cellWidthMax; - if (cell->WidthWanted) - columns[column] = cell->WidthWanted; - - // Hack to force a table with ratio to be large - sint32 cellRatio = (sint32)ceil(cell->TableRatio * 1024.f); - if (cellRatio > columns[column]) - columns[column] = cellRatio; - - // Next column - column++; - } - - // Sum - sint32 maxWidth = 0; - for (i=0; i columns; - columns.clear (); - for (i=0; i<_Cells.size(); i++) - { - // Update coords to get XReal - CGroupCell *cell = _Cells[i]; - cell->checkCoords(); - cell->updateCoords(); - - // Get width min and max - sint32 cellWidthMin = cell->getMinUsedW(); - - // New cell ? - if (cell->NewLine) - column = 0; - - // Resize the array - if (column>=columns.size()) - columns.resize(column+1, 0); - - // Update sizes - if (cellWidthMin > columns[column]) - columns[column] = cellWidthMin; - if (cell->WidthWanted) - columns[column] = cell->WidthWanted; - - // Next column - column++; - } - - // Sum - sint32 maxWidth = 0; - for (i=0; iisGroupContainer()) - { - CGroupContainer *gc = static_cast(gr); - CurrentAlpha = gc->getCurrentContainerAlpha(); - break; - } - gr = gr->getParent(); - } - - // Not found ? - if (gr == NULL) - CurrentAlpha = 255; - - if (!_Columns.empty() && !_Rows.empty() && BgColor.A) - { - sint32 border = Border + CellSpacing + CellPadding; - if (border) - { - CRGBA finalColor; - finalColor.modulateFromColor (BgColor, CWidgetManager::getInstance()->getGlobalColor()); - finalColor.A = CurrentAlpha; - - // Draw the top and bottom lines - CViewRenderer &rVR = *CViewRenderer::getInstance(); - rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, _WReal, border, 0, false, rVR.getBlankTextureId(), finalColor); - rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal-border+_HReal, _WReal, border, 0, false, rVR.getBlankTextureId(), finalColor); - - // Draw the left and right lines - sint32 insideHeight = std::max((sint32)0, (sint32)_HReal - (sint32)2*border); - rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+border, border, insideHeight, 0, false, rVR.getBlankTextureId(), finalColor); - rVR.drawRotFlipBitmap (_RenderLayer, _XReal+_WReal-border, _YReal+border, border, insideHeight, 0, false, rVR.getBlankTextureId(), finalColor); - - // Draw the inside borders - sint32 insideWidth = 2*CellPadding + CellSpacing; - if (insideWidth) - { - // Draw the inside verticals - uint i; - sint32 x = _XReal + _Columns[0].Width + border; - for (i=1; i<_Columns.size(); i++) - { - rVR.drawRotFlipBitmap (_RenderLayer, x, _YReal+border, insideWidth, insideHeight, 0, false, rVR.getBlankTextureId(), finalColor); - x += _Columns[i].Width + insideWidth; - } - - // Draw the inside horizontals - sint32 y = _YReal + _HReal - border - _Rows[0].Height; - if (_Rows[0].Height != 0) - { - y -= insideWidth; - } - for (i=1; i<_Rows.size(); i++) - { - uint j; - x = _XReal + border; - if (_Rows[i].Height != 0) - { - for (j=0; j<_Columns.size(); j++) - { - rVR.drawRotFlipBitmap (_RenderLayer, x, y, _Columns[j].Width, insideWidth, 0, false, rVR.getBlankTextureId(), finalColor); - x += _Columns[j].Width + insideWidth; - } - y -= _Rows[i].Height+ insideWidth; - } - } - } - } - } - - CInterfaceGroup::draw (); -} - -// ------------------------------------------------------------------------------------------------ -bool CGroupTable::parse (xmlNodePtr cur, CInterfaceGroup * parentGroup) -{ - if (!CInterfaceGroup::parse(cur, parentGroup)) return false; - // - CXMLAutoPtr ptr; - ptr = (char*) xmlGetProp( cur, (xmlChar*)"border" ); - if (ptr) - { - fromString((const char*)ptr, Border); - } - // - ptr = (char*) xmlGetProp( cur, (xmlChar*)"cellpadding" ); - if (ptr) - { - fromString((const char*)ptr, CellPadding); - } - // - ptr = (char*) xmlGetProp( cur, (xmlChar*)"cellspacing" ); - if (ptr) - { - fromString((const char*)ptr, CellSpacing); - } - // - ptr = (char*) xmlGetProp( cur, (xmlChar*)"bgcolor" ); - if (ptr) - { - BgColor = convertColor((const char *) ptr); - } - // - ptr = (char*) xmlGetProp( cur, (xmlChar*)"width" ); - if (ptr) - { - convertPixelsOrRatio(ptr, ForceWidthMin, TableRatio); - } - // - ptr = (char*) xmlGetProp( cur, (xmlChar*)"continuous_update" ); - if (ptr) - { - ContinuousUpdate = convertBool(ptr); - } - // parse cells - uint row = 0; - xmlNodePtr currRow = cur->children; - while (currRow != NULL) - { - // look for 'TR' markup - if (strcmp((char*)currRow->name,"TR") == 0) - { - // found a row, parse cells inside - xmlNodePtr currCol = currRow->children; - bool newLine = true; - uint column = 0; - while (currCol != NULL) - { - // look for 'TR' markup - if (strcmp((char*)currCol->name,"TD") == 0) - { - CGroupCell *cell = new CGroupCell(CViewBase::TCtorParam()); - if (cell->parse(currCol, this, column, row)) - { - cell->NewLine = newLine; - newLine = false; - addChild(cell); - } - else - { - delete cell; - } - ++ column; - } - currCol = currCol->next; - } - ++ row; - } - currRow = currRow->next; - } - - return true; -} - diff --git a/code/ryzom/client/src/interface_v3/group_table.h b/code/ryzom/client/src/interface_v3/group_table.h deleted file mode 100644 index 77c3e507c..000000000 --- a/code/ryzom/client/src/interface_v3/group_table.h +++ /dev/null @@ -1,212 +0,0 @@ -// 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_GROUP_TABLE_H -#define NL_GROUP_TABLE_H - -#include "nel/misc/types_nl.h" -#include "nel/gui/group_frame.h" -#include "nel/gui/view_text.h" -#include "nel/gui/ctrl_button.h" - -/** - * This group is used to simulate HTML cells. - * They have specific parameters to be aligned like HTML cells. - * (Percent of the table size - */ -class CGroupCell: public CInterfaceGroup -{ - friend class CGroupTable; -public: - CGroupCell(const TCtorParam ¶m); - - enum TAlign - { - Left, - Center, - Right - }; - - enum TVAlign - { - Top, - Middle, - Bottom - }; - - /// \from CInterfaceElement - virtual void draw(); - virtual sint32 getMaxUsedW() const; - virtual sint32 getMinUsedW() const; - - // to be called by CGroupTable - bool parse (xmlNodePtr cur, CInterfaceGroup * parentGroup, uint columnIndex, uint rowIndex); - - // If the cell is a new line. This is the first - bool NewLine; - bool IgnoreMaxWidth; - bool IgnoreMinWidth; - bool AddChildW; - - // The table width cell ratio. This is the
after a
parameter - float TableRatio; - - // The Width you want in pixel. This is the parameter - sint32 WidthWanted; - - - // The min height of the cell - sint32 Height; - - // Memorize max width - sint32 WidthMax; - - // The cell color - NLMISC::CRGBA BgColor; - - // Texture - CViewRenderer::CTextureId _TextureId; /// Accelerator - bool _UserTexture; - bool _TextureTiled; - bool _TextureScaled; - - // Alignment - TAlign Align; - TVAlign VAlign; - sint32 LeftMargin; - - // The cell group - CInterfaceGroup *Group; - - // The cell is nowrap - bool NoWrap; - - void setTexture(const std::string & TxName); - void setTextureTile(bool tiled); - void setTextureScale(bool scaled); - - static void setDebugUICell( bool d ){ DebugUICell = d; } - static bool getDebugUICell(){ return DebugUICell; } - -private: - void setEnclosedGroupDefaultParams(); - static bool DebugUICell; -}; - -/** - * This group is used to simulate HTML table. Support "percent of the parent width" sizeRef mode. - */ -class CGroupTable : public CInterfaceGroup -{ -public: - - ///constructor - CGroupTable(const TCtorParam ¶m); - - // dtor - ~CGroupTable(); - - // Add a cell in the table - void addChild (CGroupCell* child); - - // The ratio you want [0 ~1]. This is the parameter - float TableRatio; - - // The Width you want in pixel. This is the
parameter - sint32 ForceWidthMin; - - // Table borders - sint32 Border; - sint32 CellPadding; - sint32 CellSpacing; - - // The table color - NLMISC::CRGBA BgColor; - uint8 CurrentAlpha; - - bool ContinuousUpdate; - -protected: - - /// \from CInterfaceElement - void onInvalidateContent(); - sint32 getMaxUsedW() const; - sint32 getMinUsedW() const; - void draw (); - - /** - * init or reset the children element coords. Orverloaded from CInterfaceGroup because we begin with the last inserted element here - */ - virtual void updateCoords(); - - virtual void checkCoords(); - - virtual bool parse (xmlNodePtr cur, CInterfaceGroup * parentGroup); - - // Content validated - bool _ContentValidated; - - // Last parent width - sint32 _LastParentW; - - // Children - std::vector _Cells; - - // Table column - class CColumn - { - public: - CColumn() - { - Width = 0; - WidthMax = 0; - WidthWanted = 0; - TableRatio = 0; - Height = 0; - } - sint32 Width; - sint32 Height; - sint32 WidthWanted; - sint32 WidthMax; - float TableRatio; - }; - - // Table row - class CRow - { - public: - CRow() - { - Height = 0; - } - sint32 Height; - }; - - // Column table - std::vector _Columns; - - // Column table - std::vector _Rows; -}; - - -#endif // NL_GROUP_TABLE_H - -/* End of group_table.h */ - - diff --git a/code/ryzom/client/src/interface_v3/interface_parser.cpp b/code/ryzom/client/src/interface_v3/interface_parser.cpp index 6dacf841a..440225f03 100644 --- a/code/ryzom/client/src/interface_v3/interface_parser.cpp +++ b/code/ryzom/client/src/interface_v3/interface_parser.cpp @@ -83,7 +83,7 @@ #include "group_in_scene_bubble.h" #include "group_phrase_skill_filter.h" #include "nel/gui/group_tab.h" -#include "group_table.h" +#include "nel/gui/group_table.h" // DBGroup #include "nel/gui/dbgroup_select_number.h" #include "dbgroup_list_sheet.h" diff --git a/code/ryzom/client/src/main_loop.cpp b/code/ryzom/client/src/main_loop.cpp index 1300de86d..bc78aa1ce 100644 --- a/code/ryzom/client/src/main_loop.cpp +++ b/code/ryzom/client/src/main_loop.cpp @@ -146,7 +146,7 @@ #include "string_manager_client.h" #include "nel/gui/lua_manager.h" -#include "interface_v3/group_table.h" +#include "nel/gui/group_table.h" /////////// @@ -4427,7 +4427,7 @@ NLMISC_COMMAND(debugUIGroup, "Debug the ui : show/hide quads of bboxs and hotspo // show hide the debuging of cells NLMISC_COMMAND(debugUICell, "Debug the ui : show/hide quads of bboxs for cells", "") { - CGroupCell::setDebugUICell( !CGroupCell::getDebugUICell() ) + CGroupCell::setDebugUICell( !CGroupCell::getDebugUICell() ); return true; }