1582 lines
40 KiB
C++
1582 lines
40 KiB
C++
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
|
// Copyright (C) 2010 Winch Gate Property Limited
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as
|
|
// published by the Free Software Foundation, either version 3 of the
|
|
// License, or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
#include "stdpch.h"
|
|
#include "nel/gui/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;
|
|
ColSpan = 1;
|
|
RowSpan = 1;
|
|
TableColumnIndex = 0;
|
|
Group = new CInterfaceGroup(CViewBase::TCtorParam());
|
|
Align = Left;
|
|
VAlign = Middle;
|
|
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);
|
|
}
|
|
|
|
std::string CGroupCell::getProperty( const std::string &name ) const
|
|
{
|
|
if( name == "align" )
|
|
{
|
|
switch( Align )
|
|
{
|
|
case Right:
|
|
return "right";
|
|
|
|
case Center:
|
|
return "center";
|
|
|
|
case Left:
|
|
return "left";
|
|
}
|
|
|
|
nlassert(false);
|
|
|
|
return "";
|
|
}
|
|
else
|
|
if( name == "valign" )
|
|
{
|
|
switch( VAlign )
|
|
{
|
|
case Middle:
|
|
return "middle";
|
|
|
|
case Bottom:
|
|
return "bottom";
|
|
|
|
case Top:
|
|
return "top";
|
|
}
|
|
|
|
nlassert(false);
|
|
|
|
return "";
|
|
}
|
|
else
|
|
if( name == "left_margin" )
|
|
{
|
|
return toString( LeftMargin );
|
|
}
|
|
else
|
|
if( name == "nowrap" )
|
|
{
|
|
return toString( NoWrap );
|
|
}
|
|
else
|
|
if( name == "bgcolor" )
|
|
{
|
|
return toString( BgColor );
|
|
}
|
|
else
|
|
if( name == "width" )
|
|
{
|
|
if( WidthWanted != 0 )
|
|
return toString( WidthWanted );
|
|
else
|
|
return toString( TableRatio * 100.0f );
|
|
}
|
|
else
|
|
if( name == "height" )
|
|
{
|
|
return toString( Height );
|
|
}
|
|
else
|
|
if( name == "ignore_max_width" )
|
|
{
|
|
return toString( IgnoreMaxWidth );
|
|
}
|
|
else
|
|
if( name == "ignore_min_width" )
|
|
{
|
|
return toString( IgnoreMinWidth );
|
|
}
|
|
else
|
|
if( name == "add_child_w" )
|
|
{
|
|
return toString( AddChildW );
|
|
}
|
|
else
|
|
return CInterfaceGroup::getProperty( name );
|
|
}
|
|
|
|
void CGroupCell::setProperty( const std::string &name, const std::string &value )
|
|
{
|
|
if( name == "align" )
|
|
{
|
|
if( value == "right" )
|
|
Align = Right;
|
|
else
|
|
if( value == "center" )
|
|
Align = Center;
|
|
else
|
|
if( value == "left" )
|
|
Align = Left;
|
|
|
|
return;
|
|
}
|
|
else
|
|
if( name == "valign" )
|
|
{
|
|
if( value == "top" )
|
|
VAlign = Top;
|
|
else
|
|
if( value == "middle" )
|
|
VAlign = Middle;
|
|
else
|
|
if( value == "bottom" )
|
|
VAlign = Bottom;
|
|
|
|
return;
|
|
}
|
|
else
|
|
if( name == "left_margin" )
|
|
{
|
|
sint32 i;
|
|
if( fromString( value, i ) )
|
|
LeftMargin = i;
|
|
return;
|
|
}
|
|
else
|
|
if( name == "nowrap" )
|
|
{
|
|
bool b;
|
|
if( fromString( value, b ) )
|
|
NoWrap = b;
|
|
return;
|
|
}
|
|
else
|
|
if( name == "bgcolor" )
|
|
{
|
|
CRGBA c;
|
|
if( fromString( value, c ) )
|
|
BgColor = c;
|
|
return;
|
|
}
|
|
else
|
|
if( name == "width" )
|
|
{
|
|
convertPixelsOrRatio( value.c_str(), WidthWanted, TableRatio );
|
|
return;
|
|
}
|
|
else
|
|
if( name == "height" )
|
|
{
|
|
sint32 i;
|
|
if( fromString( value, i ) )
|
|
Height = i;
|
|
return;
|
|
}
|
|
else
|
|
if( name == "ignore_max_width" )
|
|
{
|
|
bool b;
|
|
if( fromString( value, b ) )
|
|
IgnoreMaxWidth = b;
|
|
return;
|
|
}
|
|
else
|
|
if( name == "ignore_min_width" )
|
|
{
|
|
bool b;
|
|
if( fromString( value, b ) )
|
|
IgnoreMinWidth = b;
|
|
return;
|
|
}
|
|
else
|
|
if( name == "add_child_w" )
|
|
{
|
|
bool b;
|
|
if( fromString( value, b ) )
|
|
AddChildW = b;
|
|
return;
|
|
}
|
|
else
|
|
if (name == "colspan" )
|
|
{
|
|
sint32 i;
|
|
if (fromString( value, i ) )
|
|
ColSpan = std::max(1, i);
|
|
return;
|
|
}
|
|
else
|
|
if (name == "rowspan" )
|
|
{
|
|
sint32 i;
|
|
if (fromString( value, i ) )
|
|
RowSpan = std::max(1, i);
|
|
return;
|
|
}
|
|
else
|
|
CInterfaceGroup::setProperty( name, value );
|
|
}
|
|
|
|
xmlNodePtr CGroupCell::serialize( xmlNodePtr parentNode, const char *type ) const
|
|
{
|
|
xmlNodePtr node = CInterfaceGroup::serialize( parentNode, type );
|
|
if( node == NULL )
|
|
return NULL;
|
|
|
|
xmlSetProp( node, BAD_CAST "type", BAD_CAST "cell" );
|
|
|
|
std::string align;
|
|
std::string valign;
|
|
|
|
switch( Align )
|
|
{
|
|
case Right:
|
|
align = "right";
|
|
break;
|
|
|
|
case Center:
|
|
align = "center";
|
|
break;
|
|
|
|
default:
|
|
align = "left";
|
|
break;
|
|
}
|
|
|
|
|
|
switch( VAlign )
|
|
{
|
|
case Middle:
|
|
valign = "middle";
|
|
break;
|
|
|
|
case Bottom:
|
|
valign = "bottom";
|
|
break;
|
|
|
|
default:
|
|
valign = "top";
|
|
break;
|
|
}
|
|
|
|
xmlSetProp( node, BAD_CAST "align", BAD_CAST "" );
|
|
xmlSetProp( node, BAD_CAST "valign", BAD_CAST "" );
|
|
xmlSetProp( node, BAD_CAST "left_margin", BAD_CAST toString( LeftMargin ).c_str() );
|
|
xmlSetProp( node, BAD_CAST "nowrap", BAD_CAST toString( NoWrap ).c_str() );
|
|
xmlSetProp( node, BAD_CAST "bgcolor", BAD_CAST toString( BgColor ).c_str() );
|
|
|
|
if( WidthWanted != 0 )
|
|
xmlSetProp( node, BAD_CAST "width", BAD_CAST toString( WidthWanted ).c_str() );
|
|
else
|
|
xmlSetProp( node, BAD_CAST "width", BAD_CAST toString( TableRatio * 100.0f ).c_str() );
|
|
|
|
xmlSetProp( node, BAD_CAST "height", BAD_CAST toString( Height ).c_str() );
|
|
xmlSetProp( node, BAD_CAST "ignore_max_width", BAD_CAST toString( IgnoreMaxWidth ).c_str() );
|
|
xmlSetProp( node, BAD_CAST "ignore_min_width", BAD_CAST toString( IgnoreMinWidth ).c_str() );
|
|
xmlSetProp( node, BAD_CAST "add_child_w", BAD_CAST toString( AddChildW ).c_str() );
|
|
xmlSetProp( node, BAD_CAST "colspan", BAD_CAST toString( ColSpan ).c_str() );
|
|
xmlSetProp( node, BAD_CAST "rowspan", BAD_CAST toString( RowSpan ).c_str() );
|
|
|
|
return node;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
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::getInstance()->getParser()->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("<CGroupCell::parse> 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("<CGroupCell::parse> 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);
|
|
}
|
|
//
|
|
ptr = (char*) xmlGetProp( cur, (xmlChar*)"colspan" );
|
|
if (ptr)
|
|
{
|
|
sint32 i;
|
|
if (fromString((const char*)ptr, i))
|
|
ColSpan = std::max(1, i);
|
|
}
|
|
//
|
|
ptr = (char*) xmlGetProp( cur, (xmlChar*)"rowspan" );
|
|
if (ptr)
|
|
{
|
|
sint32 i;
|
|
if (fromString((const char*)ptr, i))
|
|
RowSpan = std::max(1, i);
|
|
}
|
|
|
|
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<CGroupTable*> (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);
|
|
}
|
|
}
|
|
|
|
// Get the parent table
|
|
if (getParent ())
|
|
{
|
|
CGroupTable *table = static_cast<CGroupTable*> (getParent ());
|
|
if (table->Border) {
|
|
CRGBA lighter = blend(table->BorderColor, CRGBA::White, 0.5f);
|
|
|
|
CRGBA borderColorTL;
|
|
borderColorTL.modulateFromColor (lighter, CWidgetManager::getInstance()->getGlobalColor());
|
|
borderColorTL.A = (uint8) (((uint16) table->CurrentAlpha * (uint16) borderColorTL.A) >> 8);
|
|
|
|
CRGBA borderColorBR;
|
|
borderColorBR.modulateFromColor (table->BorderColor, CWidgetManager::getInstance()->getGlobalColor());
|
|
borderColorBR.A = (uint8) (((uint16) table->CurrentAlpha * (uint16) borderColorBR.A) >> 8);
|
|
|
|
CViewRenderer &rVR = *CViewRenderer::getInstance();
|
|
rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, _WReal, 1, 0, false, rVR.getBlankTextureId(), borderColorTL );
|
|
rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, 1, _HReal, 0, false, rVR.getBlankTextureId(), borderColorBR );
|
|
rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal+_HReal-1, _WReal, 1, 0, false, rVR.getBlankTextureId(), borderColorBR );
|
|
rVR.drawRotFlipBitmap (_RenderLayer, _XReal+_WReal-1, _YReal, 1, _HReal, 0, false, rVR.getBlankTextureId(), borderColorTL );
|
|
}
|
|
}
|
|
|
|
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;
|
|
BorderColor = CRGBA(32, 32, 32, 255);
|
|
CellPadding=1;
|
|
CellSpacing=2;
|
|
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)
|
|
{
|
|
while (column < _Columns.size())
|
|
{
|
|
if (_Columns[column].RowSpan > 1)
|
|
_Columns[column].RowSpan--;
|
|
column++;
|
|
}
|
|
column = 0;
|
|
}
|
|
|
|
// Resize the array
|
|
if (column>=_Columns.size())
|
|
_Columns.resize(column+1);
|
|
|
|
// Handle rowspan from previous row
|
|
while (_Columns[column].RowSpan > 1)
|
|
{
|
|
_Columns[column].RowSpan--;
|
|
column++;
|
|
// if previous row had less <TD> elements, then we missing columns
|
|
if (column>=_Columns.size())
|
|
_Columns.resize(column+1);
|
|
}
|
|
|
|
// remember column index for later use
|
|
cell->TableColumnIndex = column;
|
|
|
|
// new column, set rowspan from current <TD>
|
|
_Columns[column].RowSpan = cell->RowSpan;
|
|
float colspan = 1.f / cell->ColSpan;
|
|
float rowspan = 1.f / cell->RowSpan;
|
|
|
|
// Update sizes
|
|
if (cellWidth*colspan > _Columns[column].Width)
|
|
_Columns[column].Width = cellWidth*colspan;
|
|
if (cell->WidthMax*colspan > _Columns[column].WidthMax)
|
|
_Columns[column].WidthMax = cell->WidthMax*colspan;
|
|
if (cell->TableRatio*colspan > _Columns[column].TableRatio)
|
|
_Columns[column].TableRatio = cell->TableRatio*colspan;
|
|
if (cell->WidthWanted*colspan + additionnalWidth > _Columns[column].WidthWanted)
|
|
_Columns[column].WidthWanted = (sint32)(cell->WidthWanted*colspan) + additionnalWidth;
|
|
|
|
if (_Columns[column].WidthWanted + additionnalWidth)
|
|
_Columns[column].WidthMax = _Columns[column].WidthWanted + additionnalWidth;
|
|
if (_Columns[column].WidthWanted > _Columns[column].Width)
|
|
_Columns[column].Width = _Columns[column].WidthWanted;
|
|
|
|
if (cell->ColSpan > 1) {
|
|
// copy this info to all spanned columns, create new columns as needed
|
|
uint newsize = column + cell->ColSpan - 1;
|
|
if (newsize >= _Columns.size())
|
|
_Columns.resize(newsize+1);
|
|
for(uint span = 0; span < cell->ColSpan -1; span++){
|
|
column++;
|
|
_Columns[column].Width = _Columns[column-1].Width;
|
|
_Columns[column].WidthMax = _Columns[column-1].WidthMax;
|
|
_Columns[column].TableRatio = _Columns[column-1].TableRatio;
|
|
_Columns[column].WidthWanted = _Columns[column-1].WidthWanted;
|
|
_Columns[column].RowSpan = _Columns[column-1].RowSpan;
|
|
}
|
|
}
|
|
|
|
// Next column
|
|
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;
|
|
|
|
// 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
// If there is still space left, then sum up column widths
|
|
// and add all the remaining space to final column.
|
|
if (space > 0)
|
|
{
|
|
sint32 innerWidth = 0;
|
|
for(i=0;i<_Columns.size();i++)
|
|
innerWidth += _Columns[i].Width;
|
|
|
|
if (innerWidth > 0 && finalWidth > innerWidth)
|
|
_Columns[_Columns.size()-1].Width += finalWidth - innerWidth;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// *** Now we know each column width, resize cells and get the height for each row
|
|
|
|
column = 0;
|
|
sint32 row = 0;
|
|
sint32 currentX = Border + CellSpacing + padding;
|
|
|
|
_Rows.clear ();
|
|
for (i=0; i<_Cells.size(); i++)
|
|
{
|
|
CGroupCell *cell = _Cells[i];
|
|
// New cell ?
|
|
if (cell->NewLine)
|
|
{
|
|
column = 0;
|
|
currentX = Border + CellSpacing + padding;
|
|
|
|
_Rows.push_back(CRow());
|
|
}
|
|
|
|
if (cell->TableColumnIndex > 0)
|
|
{
|
|
// we have active rowspan, must add up 'skipped' columns
|
|
for( ; column<cell->TableColumnIndex; column++)
|
|
currentX += _Columns[column].Width + padding*2 + CellSpacing;
|
|
}
|
|
|
|
// Set the x and width
|
|
|
|
// Check align
|
|
sint32 alignmentX = 0;
|
|
sint32 widthReduceX = 0;
|
|
sint32 columnWidth = _Columns[column].Width;
|
|
if (cell->ColSpan > 1)
|
|
{
|
|
// scan ahead and add up column widths as they might be different
|
|
for(int j = 1; j<cell->ColSpan; j++)
|
|
columnWidth += CellSpacing + padding*2 + _Columns[column+j].Width;
|
|
}
|
|
|
|
if (cell->WidthMax < columnWidth)
|
|
{
|
|
switch (cell->Align)
|
|
{
|
|
case CGroupCell::Center:
|
|
alignmentX = (columnWidth - cell->WidthMax) / 2;
|
|
widthReduceX = alignmentX * 2;
|
|
break;
|
|
case CGroupCell::Right:
|
|
alignmentX = columnWidth - cell->WidthMax;
|
|
widthReduceX = alignmentX;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
cell->setX(currentX - padding);
|
|
cell->setW(columnWidth + padding*2);
|
|
|
|
cell->Group->setX(alignmentX + cell->LeftMargin + padding);
|
|
cell->Group->setW(columnWidth - widthReduceX);
|
|
cell->Group->CInterfaceElement::updateCoords();
|
|
|
|
// Update coords to get H
|
|
cell->Group->checkCoords();
|
|
cell->Group->updateCoords();
|
|
|
|
// Resize the row array
|
|
float rowspan = 1 / cell->RowSpan;
|
|
_Rows.back().Height = std::max((sint32)(cell->Height*rowspan), std::max(_Rows.back().Height, (sint32)(cell->Group->getH()*rowspan)));
|
|
|
|
// Next column
|
|
currentX += columnWidth + 2*padding + CellSpacing;
|
|
column += cell->ColSpan;
|
|
}
|
|
|
|
// Set cell Y
|
|
row = 0;
|
|
sint32 currentY = -(Border + CellSpacing + padding);
|
|
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*padding + CellSpacing;
|
|
}
|
|
row++;
|
|
}
|
|
|
|
// Check align
|
|
sint32 alignmentY = 0;
|
|
sint32 rowHeight = _Rows[row].Height;
|
|
if (cell->RowSpan > 1)
|
|
{
|
|
// we need to scan down and add up row heights
|
|
int k = std::min((sint32)_Rows.size(), row + cell->RowSpan);
|
|
for(int j=row+1; j<k; j++)
|
|
rowHeight += CellSpacing + padding*2 + _Rows[j].Height;
|
|
}
|
|
if ((sint32)cell->Group->getH() < rowHeight)
|
|
{
|
|
switch (cell->VAlign)
|
|
{
|
|
case CGroupCell::Middle:
|
|
alignmentY = (rowHeight - (sint32)cell->Group->getH()) / 2;
|
|
break;
|
|
case CGroupCell::Bottom:
|
|
alignmentY = rowHeight - (sint32)cell->Group->getH();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
cell->setY(currentY + padding);
|
|
cell->setH (rowHeight + 2*padding);
|
|
cell->Group->setY(-(alignmentY + padding));
|
|
}
|
|
|
|
// Resize the table
|
|
setW(finalWidth+borderWidth-_LastParentW);
|
|
if (!_Rows.empty())
|
|
currentY -= _Rows[row].Height + padding + 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<CCtrlResizer*>(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<sint32> 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.size(); i++)
|
|
maxWidth += columns[i];
|
|
|
|
maxWidth += 2*Border + ((sint32)columns.size()+1) * CellSpacing + ((sint32)columns.size()*2) * CellPadding;
|
|
|
|
return maxWidth;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
sint32 CGroupTable::getMinUsedW() const
|
|
{
|
|
uint i;
|
|
uint column = 0;
|
|
vector<sint32> 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; i<columns.size(); i++)
|
|
maxWidth += columns[i];
|
|
|
|
maxWidth += 2*Border + ((sint32)columns.size()+1) * CellSpacing + ((sint32)columns.size()*2) * CellPadding;
|
|
|
|
return maxWidth;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
void CGroupTable::draw ()
|
|
{
|
|
// search a parent container
|
|
CInterfaceGroup *gr = getParent();
|
|
while (gr)
|
|
{
|
|
if (gr->isGroupContainer())
|
|
{
|
|
CGroupContainer *gc = static_cast<CGroupContainer *>(gr);
|
|
CurrentAlpha = gc->getCurrentContainerAlpha();
|
|
break;
|
|
}
|
|
gr = gr->getParent();
|
|
}
|
|
|
|
// Not found ?
|
|
if (gr == NULL)
|
|
CurrentAlpha = 255;
|
|
|
|
if (!_Columns.empty() && !_Rows.empty())
|
|
{
|
|
sint32 border = Border + CellSpacing;
|
|
if (border && BgColor.A)
|
|
{
|
|
CRGBA finalColor;
|
|
finalColor.modulateFromColor (BgColor, CWidgetManager::getInstance()->getGlobalColor());
|
|
finalColor.A = CurrentAlpha;
|
|
|
|
// Draw the top line
|
|
CViewRenderer &rVR = *CViewRenderer::getInstance();
|
|
rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal-border+_HReal, _WReal, border, 0, false, rVR.getBlankTextureId(), finalColor);
|
|
|
|
// Draw the left line
|
|
sint32 insideHeight = std::max((sint32)0, (sint32)_HReal - (sint32)border);
|
|
rVR.drawRotFlipBitmap (_RenderLayer, _XReal, _YReal, border, insideHeight, 0, false, rVR.getBlankTextureId(), finalColor);
|
|
|
|
// Draw the inside borders
|
|
if (CellSpacing)
|
|
{
|
|
uint i;
|
|
sint32 x, y;
|
|
for (i=0; i<_Cells.size(); i++)
|
|
{
|
|
CGroupCell *cell = _Cells[i];
|
|
|
|
x = cell->getXReal();
|
|
y = cell->getYReal() - CellSpacing;
|
|
// right
|
|
rVR.drawRotFlipBitmap (_RenderLayer, x + cell->getW(), y, CellSpacing, cell->getH() + CellSpacing, 0, false, rVR.getBlankTextureId(), finalColor);
|
|
// bottom
|
|
rVR.drawRotFlipBitmap (_RenderLayer, x, y, cell->getW(), CellSpacing, 0, false, rVR.getBlankTextureId(), finalColor);
|
|
}
|
|
}
|
|
|
|
}
|
|
if (Border)
|
|
{
|
|
CViewRenderer &rVR = *CViewRenderer::getInstance();
|
|
|
|
CRGBA borderColorTL;
|
|
CRGBA lighter = blend(BorderColor, CRGBA::White, 0.5f);
|
|
borderColorTL.modulateFromColor (lighter, CWidgetManager::getInstance()->getGlobalColor());
|
|
borderColorTL.A = CurrentAlpha;
|
|
|
|
CRGBA borderColorBR;
|
|
borderColorBR.modulateFromColor (BorderColor, CWidgetManager::getInstance()->getGlobalColor());
|
|
borderColorBR.A = CurrentAlpha;
|
|
|
|
// beveled table border
|
|
for (sint32 i=0; i<Border; i++)
|
|
{
|
|
// bottom, left, top, right
|
|
rVR.drawRotFlipBitmap (_RenderLayer, _XReal+i, _YReal+i, _WReal-i*2, 1, 0, false, rVR.getBlankTextureId(), borderColorBR);
|
|
rVR.drawRotFlipBitmap (_RenderLayer, _XReal+i, _YReal+i, 1, _HReal-i*2, 0, false, rVR.getBlankTextureId(), borderColorTL);
|
|
rVR.drawRotFlipBitmap (_RenderLayer, _XReal+i, _YReal+_HReal-i-1, _WReal-i*2, 1, 0, false, rVR.getBlankTextureId(), borderColorTL);
|
|
rVR.drawRotFlipBitmap (_RenderLayer, _XReal+_WReal-i-1, _YReal+i, 1, _HReal-i*2, 0, false, rVR.getBlankTextureId(), borderColorBR);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
CInterfaceGroup::draw ();
|
|
}
|
|
|
|
std::string CGroupTable::getProperties( const std::string &name ) const
|
|
{
|
|
if( name == "border" )
|
|
{
|
|
return toString( Border );
|
|
}
|
|
else
|
|
if( name == "bordercolor" )
|
|
{
|
|
return toString( BorderColor );
|
|
}
|
|
else
|
|
if( name == "cellpadding" )
|
|
{
|
|
return toString( CellPadding );
|
|
}
|
|
else
|
|
if( name == "cellspacing" )
|
|
{
|
|
return toString( CellSpacing );
|
|
}
|
|
else
|
|
if( name == "bgcolor" )
|
|
{
|
|
return toString( BgColor );
|
|
}
|
|
else
|
|
if( name == "width" )
|
|
{
|
|
if( ForceWidthMin != 0 )
|
|
return toString( ForceWidthMin );
|
|
else
|
|
return toString( TableRatio * 100.0f );
|
|
}
|
|
else
|
|
return CInterfaceGroup::getProperty( name );
|
|
}
|
|
|
|
void CGroupTable::setProperty( const std::string &name, const std::string &value )
|
|
{
|
|
if( name == "border" )
|
|
{
|
|
sint32 i;
|
|
if( fromString( value, i ) )
|
|
Border = i;
|
|
return;
|
|
}
|
|
else
|
|
if( name == "bordercolor" )
|
|
{
|
|
CRGBA c;
|
|
if( fromString( value, c ) )
|
|
BorderColor = c;
|
|
return;
|
|
}
|
|
else
|
|
if( name == "cellpadding" )
|
|
{
|
|
sint32 i;
|
|
if( fromString( value, i ) )
|
|
CellPadding = i;
|
|
return;
|
|
}
|
|
else
|
|
if( name == "cellspacing" )
|
|
{
|
|
sint32 i;
|
|
if( fromString( value, i ) )
|
|
CellSpacing = i;
|
|
return;
|
|
}
|
|
else
|
|
if( name == "bgcolor" )
|
|
{
|
|
CRGBA c;
|
|
if( fromString( value, c ) )
|
|
BgColor = c;
|
|
return;
|
|
}
|
|
else
|
|
if( name == "width" )
|
|
{
|
|
convertPixelsOrRatio( value.c_str(), ForceWidthMin, TableRatio );
|
|
return;
|
|
}
|
|
else
|
|
CInterfaceGroup::setProperty( name, value );
|
|
}
|
|
|
|
|
|
xmlNodePtr CGroupTable::serialize( xmlNodePtr parentNode, const char *type ) const
|
|
{
|
|
xmlNodePtr node = CInterfaceGroup::serialize( parentNode, type );
|
|
if( node == NULL )
|
|
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 "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() );
|
|
|
|
if( ForceWidthMin != 0 )
|
|
xmlSetProp( node, BAD_CAST "width", BAD_CAST toString( ForceWidthMin ).c_str() );
|
|
else
|
|
xmlSetProp( node, BAD_CAST "width", BAD_CAST toString( TableRatio * 100.0f ).c_str() );
|
|
|
|
return node;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
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*)"bordercolor" );
|
|
if (ptr)
|
|
{
|
|
BorderColor = convertColor((const char*)ptr);
|
|
}
|
|
//
|
|
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;
|
|
}
|
|
|
|
}
|
|
|