CHANGED: #1471 CViewBitmapCombo is now part of NELGUI library, and is under NLGUI namespace.

This commit is contained in:
dfighter1985 2012-06-22 04:40:34 +02:00
parent 2231c934b9
commit 3d3185fcf1
6 changed files with 761 additions and 751 deletions

View file

@ -0,0 +1,174 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef NL_VIEW_BITMAP_COMBO_H
#define NL_VIEW_BITMAP_COMBO_H
#include "nel/misc/cdb.h"
#include "nel/gui/view_base.h"
#include "nel/3d/u_texture.h"
#include <string>
#include <vector>
namespace NLGUI
{
/** Description of a combo box, this can be parsed from an xml node
* The bitmap layout is as follow :
*
* I W I W I W
* t G t G t G
* e a e a e a
* m p m p m p
* W S W W
* i e i i
* d l d d
* t e t t
* h c h h
* t
* e
* d
* +----+---+----+---+---+---+---+--...
* |ssss| |****| |***| |***|
* ItemHeight |ssss| |****| |***| |***
* +----+---+----+---+---+---+---+--...
* | | | | | | | |
* HGapSeleted | | | | | | | |
* +----+---+----+---+---+---+---+--...
* |****| |****| |***| |***|
* ItemHeight |****| |****| |***| |***|
* +----+---+----+---+---+---+---+--...
* | | | | | | | |
* HGap | | | | | | | |
* +----+---+----+---+---+---+---+--...
* |****| |****| |***| |***|
* ItemHeight |****| |****| |***| |***|
* . . . . . . . .
* . . . . . . . .
* s : selected item. . . . . . .
* * : where bitmap are displayed
*/
struct CComboBoxDesc
{
bool parse(xmlNodePtr cur, CInterfaceElement *owner);
void addObserver(NLMISC::ICDBNode::IPropertyObserver *obs);
void getGridSize(uint &numRow,uint &numCol) const;
void getDimensions(uint &width, uint &height) const;
CInterfaceProperty NumRow;
CInterfaceProperty NumCol;
CInterfaceProperty CurrSelected;
CInterfaceProperty ItemWidth;
CInterfaceProperty ItemHeight;
CInterfaceProperty Unrolled;
CInterfaceProperty WGapSelected;
CInterfaceProperty WGap;
CInterfaceProperty HGapSelected;
CInterfaceProperty HGap;
CInterfaceProperty NumSel;
CInterfaceProperty Align;
};
/**
* A combo box with several bitmaps in it
* \author Nicolas Vizerie
* \author Nevrax France
* \date 2002
*/
class CViewBitmapCombo : public CViewBase, public NLMISC::ICDBNode::IPropertyObserver
{
public:
typedef std::vector<sint32> TIdArray;
typedef std::vector<std::string> TStringArray;
typedef std::vector<NLMISC::CRGBA> TColorArray;
public:
/// ctor
CViewBitmapCombo(const TCtorParam &param);
/**
* parse an xml node and initialize the base view members. Must call CViewBase::parse
* \param cur : pointer to the xml node to be parsed
* \param parentGroup : the parent group of the view
* \partam id : a refence to the string that will receive the view ID
* \return true if success
*/
bool parse(xmlNodePtr cur,CInterfaceGroup * parentGroup);
virtual uint32 getMemory() { return (uint32)(sizeof(*this)+_Id.size()); }
/**
* draw the view
*/
void draw();
// access to texture & colors
const TStringArray &getTexs() const { return _Texs; }
const TStringArray &getTexsOver() const { return _TexsOver; }
const TStringArray &getTexsPushed() const { return _TexsPushed; }
//
const TColorArray &getColors() const { return _Col; }
const TColorArray &getColorsOver() const { return _ColOver; }
const TColorArray &getColorsPushed() const { return _ColPushed; }
//
void setTexs(const char * const tex[], uint numTex);
void setTexsOver(const char * const tex[], uint numTex);
void setTexsPushed(const char * const tex[], uint numTex);
//
void setColors(const NLMISC::CRGBA colors[], uint numColors);
void setColorsOver(const NLMISC::CRGBA colors[], uint numColors);
void setColorsPushed(const NLMISC::CRGBA colors[], uint numColors);
///////////////////////////////////////////////////////////////////////////////////
private:
//
TStringArray _Texs;
TStringArray _TexsOver;
TStringArray _TexsPushed;
TIdArray _TexsId;
TIdArray _TexsOverId;
TIdArray _TexsPushedId;
TColorArray _Col;
TColorArray _ColOver;
TColorArray _ColPushed;
CComboBoxDesc _CD;
CInterfaceElement *_Owner;
private:
void parseTexList(const std::string &names, TStringArray &dest);
void parseColList(const std::string &names, TColorArray &dest);
void setupSize();
void getDimensions(uint &numRow, uint &numCol);
// From ICDBNode::IPropertyObserver
void update(NLMISC::ICDBNode *leaf);
// Return a color from the array, or white if it is empty
static NLMISC::CRGBA getCol(const TColorArray &array, uint index);
static const std::string *getTex(const TStringArray &array, uint index);
static sint32 getTexId(const TIdArray &array, uint index);
};
}
#endif

View file

@ -0,0 +1,585 @@
// 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 "nel/gui/view_bitmap_combo.h"
#include "nel/misc/xml_auto_ptr.h"
#include "nel/gui/db_manager.h"
#include "nel/gui/view_renderer.h"
#include "nel/gui/widget_manager.h"
#include "nel/gui/view_pointer_base.h"
#include "nel/gui/interface_group.h"
using namespace NLMISC;
namespace NLGUI
{
//=======================================================================================
bool CComboBoxDesc::parse(xmlNodePtr cur, CInterfaceElement*owner)
{
nlassert(owner);
const std::string &ownerId = owner->getId();
CXMLAutoPtr prop;
//
prop = xmlGetProp(cur, (const xmlChar *) "selected");
if (!prop)
{
nlwarning((ownerId + " : Couldn't read 'selected' field").c_str());
return false;
}
owner->relativeSInt64Read(CurrSelected, "selected", prop, "0");
//
prop = xmlGetProp(cur, (const xmlChar *) "num_row");
owner->relativeSInt64Read(NumRow, "num_row", prop, "1");
//
prop = xmlGetProp(cur, (const xmlChar *) "num_col");
owner->relativeSInt64Read(NumCol, "num_col", prop, "1");
//
prop = xmlGetProp(cur, (const xmlChar *) "itemw");
owner->relativeSInt64Read(ItemWidth, "itemw", prop, "32");
//
prop = xmlGetProp(cur, (const xmlChar *) "itemh");
owner->relativeSInt64Read(ItemHeight, "itemh", prop, "32");
//
prop = xmlGetProp(cur, (const xmlChar *) "unrolled");
owner->relativeBoolRead(Unrolled, "unrolled", prop, "false");
//
prop = xmlGetProp(cur, (xmlChar *) "wgap");
owner->relativeSInt64Read(WGap, "wgap", prop, "0");
//
prop = xmlGetProp(cur, (xmlChar *) "hgap");
owner->relativeSInt64Read(HGap, "hgap", prop, "0");
//
prop = xmlGetProp(cur, (xmlChar *) "wgap_selected");
owner->relativeSInt64Read(WGapSelected, "wgap_selected", prop, "0");
//
prop = xmlGetProp(cur, (xmlChar *) "hgap_selected");
owner->relativeSInt64Read(HGapSelected, "hgap_selected", prop, "0");
//
//
prop = xmlGetProp(cur, (xmlChar *) "num_sel");
owner->relativeSInt64Read(NumSel, "num_sel", prop, "1");
//
prop = (char*) xmlGetProp (cur, (xmlChar*)"align");
Align.readSInt32 ("0", ownerId + ":align");
if (prop)
{
const char *seekPtr = prop.getDatas();
while (*seekPtr != 0)
{
if ((*seekPtr=='l')||(*seekPtr=='L'))
{
Align.setSInt32 (Align.getSInt32()&(~1));
}
if ((*seekPtr=='r')||(*seekPtr=='R'))
{
Align.setSInt32 (Align.getSInt32()|1);
}
if ((*seekPtr=='b')||(*seekPtr=='B'))
{
Align.setSInt32 (Align.getSInt32()&(~2));
}
if ((*seekPtr=='t')||(*seekPtr=='T'))
{
Align.setSInt32 (Align.getSInt32()|2);
}
++seekPtr;
}
}
//
return true;
}
//=========================================================================================
void CComboBoxDesc::addObserver(ICDBNode::IPropertyObserver *obs)
{
// Add observers on dimensions
if (NumRow.getNodePtr())
{
ICDBNode::CTextId textId;
NumRow.getNodePtr()->addObserver(obs, textId);
}
if (NumCol.getNodePtr())
{
ICDBNode::CTextId textId;
NumCol.getNodePtr()->addObserver(obs, textId);
}
if (ItemWidth.getNodePtr())
{
ICDBNode::CTextId textId;
ItemWidth.getNodePtr()->addObserver(obs, textId);
}
if (ItemHeight.getNodePtr())
{
ICDBNode::CTextId textId;
ItemHeight.getNodePtr()->addObserver(obs, textId);
}
if (Unrolled.getNodePtr())
{
ICDBNode::CTextId textId;
Unrolled.getNodePtr()->addObserver(obs, textId);
}
}
//=======================================================================================
void CComboBoxDesc::getGridSize(uint &numRow, uint &numCol) const
{
numRow = NumRow.getSInt32();
numCol = NumCol.getSInt32();
if (numRow == 0 || numCol == 0) return;
if (!Unrolled.getBool())
{
numRow = numCol = 1;
}
}
//=======================================================================================
void CComboBoxDesc::getDimensions(uint &w, uint &h) const
{
uint numRow, numCol;
getGridSize(numRow, numCol);
w = numCol * (ItemWidth.getSInt32() + WGap.getSInt32());
h = numRow * (ItemHeight.getSInt32() + HGap.getSInt32());
//
if (numCol == 1) w -= WGap.getSInt32();
else w += WGapSelected.getSInt32() - WGap.getSInt32();
//
if (numRow == 1) h -= HGap.getSInt32();
else h += HGapSelected.getSInt32() - HGap.getSInt32();
}
//=======================================================================================
NLMISC_REGISTER_OBJECT(CViewBase, CViewBitmapCombo, std::string, "bitmap_combo");
CViewBitmapCombo::CViewBitmapCombo(const TCtorParam &param) : CViewBase(param)
{
}
//=======================================================================================
bool CViewBitmapCombo::parse(xmlNodePtr cur, CInterfaceGroup * parentGroup)
{
if (! CViewBase::parse(cur, parentGroup) )
{
parseError(parentGroup);
return false;
}
CXMLAutoPtr prop;
std::string texs;
prop = xmlGetProp(cur, (xmlChar *)"tx_normal");
if (prop) texs = (const char*)prop;
std::string texsOver;
prop = xmlGetProp(cur, (xmlChar *)"tx_over");
if (prop) texsOver = (const char*)prop;
std::string texsPushed;
prop = xmlGetProp(cur, (xmlChar *)"tx_pushed");
if (prop) texsPushed = (const char*)prop;
//
// for colors, an empty strings means all colors are white
//
std::string col;
prop = xmlGetProp(cur, (xmlChar *)"col_normal");
if (prop) col = (const char*)prop;
std::string colOver;
prop = xmlGetProp(cur, (xmlChar *)"col_over");
if (prop) colOver = (const char*)prop;
std::string colPushed;
prop = xmlGetProp(cur, (xmlChar *)"col_pushed");
if (prop) colPushed = (const char*)prop;
/* if (texs.empty() || texsOver.empty() || texsPushed.empty())
{
parseError(parentGroup, "Cannot read tx_normal, tx_over, or tx_pushed");
return false;
}*/
parseTexList(texs, _Texs);
parseTexList(texsOver, _TexsOver);
parseTexList(texsPushed, _TexsPushed);
parseColList(col, _Col);
parseColList(colOver, _ColOver);
parseColList(colPushed, _ColPushed);
//
/* if (_Texs.size() != _TexsOver.size() || _TexsOver.size() != _TexsPushed.size())
{
parseError(parentGroup, "Texture names arrays do not have the same size");
return false;
}
//
uint numCols = NLMISC::maxof(_Col.size(), _ColOver.size(), _ColPushed.size());
if (!
(
(_Col.empty() || _Col.size() == numCols)
&& (_ColOver.empty() || _ColOver.size() == numCols)
&& (_ColPushed.empty() || _ColPushed.size() == numCols)
)
)
{
parseError(parentGroup, "Color names arrays do not have the same size (note an empty array is valid, means all color are 255 255 255");
return false;
}*/
//
if (!_CD.parse(cur, this))
{
return false;
}
//
setupSize();
//
_CD.addObserver(this);
return true;
}
//=======================================================================================
NLMISC::CRGBA CViewBitmapCombo::getCol(const CViewBitmapCombo::TColorArray &array,uint index)
{
if (array.empty()) return CRGBA::White;
return array[index % array.size()];
}
//=======================================================================================
const std::string *CViewBitmapCombo::getTex(const TStringArray &array,uint index)
{
if (array.empty()) return NULL;
return &array[index % array.size()];
}
//=======================================================================================
sint32 CViewBitmapCombo::getTexId(const TIdArray &array, uint index)
{
if (array.empty()) return -1;
return array[index % array.size()];
}
//=======================================================================================
void CViewBitmapCombo::draw()
{
if (_Texs.empty()) return;
uint numRow, numCol;
_CD.getGridSize(numRow, numCol);
if (numRow == 0 || numCol == 0) return;
sint32 mx = 0, my = 0;
CViewRenderer &rVR = *CViewRenderer::getInstance();
const std::vector<CViewBase *> &rVB = CWidgetManager::getInstance()->getViewsUnderPointer();
if (!CWidgetManager::getInstance()->getPointer()) return;
CWidgetManager::getInstance()->getPointer()->getPointerDispPos(mx, my);
bool over = false;
uint32 i;
for (i = 0; i < rVB.size(); ++i)
{
if (rVB[i] == this)
{
over = true;
break;
}
}
if (_TexsId.size() == 0)
{
for (i = 0; i < _Texs.size(); ++i)
_TexsId.push_back(rVR.getTextureIdFromName(_Texs[i]));
for (i = 0; i < _TexsOver.size(); ++i)
_TexsOverId.push_back(rVR.getTextureIdFromName(_TexsOver[i]));
for (i = 0; i < _TexsPushed.size(); ++i)
_TexsPushedId.push_back(rVR.getTextureIdFromName(_TexsPushed[i]));
}
sint32 textId;
CRGBA color;
uint selectedTexIndex = _CD.CurrSelected.getSInt32();
uint itemw = _CD.ItemWidth.getSInt32() + _CD.WGap.getSInt32();
uint itemh = _CD.ItemHeight.getSInt32() + _CD.HGap.getSInt32();
uint counter = 0;
bool overItem = false;
for(uint x = 0; x < numCol; ++x)
{
for(uint y = 0; y < numRow; ++y)
{
uint texIndex = counter;
if (counter != 0)
{
if (counter == selectedTexIndex)
{
texIndex = 0;
}
sint px;
sint py;
// get the right position depending on alignment
if (_CD.Align.getSInt32() & 1) // right align ?
{
px = _XReal + _WReal - (x + 1) * itemw;
}
else
{
px = _XReal + x * itemw;
}
// top align ?
if (_CD.Align.getSInt32() & 2)
{
py = _YReal + _HReal - (y + 1) * itemh;
}
else
{
py = _YReal + y * itemh;
}
if (x != 0)
{
if (_CD.Align.getSInt32() & 1)
px -= _CD.WGapSelected.getSInt32() - _CD.WGap.getSInt32();
else px += _CD.WGapSelected.getSInt32() - _CD.WGap.getSInt32();
}
if (y != 0)
{
if (_CD.Align.getSInt32() & 2)
py -= _CD.HGapSelected.getSInt32() - _CD.HGap.getSInt32();
else py += _CD.HGapSelected.getSInt32() - _CD.HGap.getSInt32();
}
// is the mouse on current item ?
if (over
&& mx >= px
&& my >= py
&& mx < px + (sint32) itemw
&& my < py + (sint32) itemh)
{
overItem = true;
if ( CWidgetManager::getInstance()->getPointer()->getButtonState() & NLMISC::leftButton)
{
textId = getTexId(_TexsPushedId, texIndex);
color = getCol(_ColPushed, texIndex);
}
else
{
textId = getTexId(_TexsOverId, texIndex);
color = getCol(_ColOver, texIndex);
}
}
else
{
textId = getTexId(_TexsId, texIndex);
color = getCol(_Col, texIndex);
}
CViewRenderer::getInstance()->drawRotFlipBitmap (_RenderLayer, px, py, itemw, itemh, 0, false,
textId,
color);
}
++counter;
if ((sint32) counter == _CD.NumSel.getSInt32())
break;
}
}
if ((sint32) selectedTexIndex >= _CD.NumSel.getSInt32())
{
return;
}
// draw current selection
sint32 px;
sint32 py;
//
if (_CD.Align.getSInt32() & 1)
{
px = _XReal + _WReal - itemw;
}
else
{
px = _XReal;
}
//
if (_CD.Align.getSInt32() & 2)
{
py = _YReal + _HReal - itemh;
}
else
{
py = _YReal;
}
//
if (_CD.Unrolled.getBool())
{
if (overItem && CWidgetManager::getInstance()->getPointer()->getButtonState() & NLMISC::leftButton)
{
textId = getTexId(_TexsId, selectedTexIndex);
color = getCol(_Col, selectedTexIndex);
}
else
{
textId = getTexId(_TexsPushedId, selectedTexIndex);
color = getCol(_ColPushed, selectedTexIndex);
}
}
else
{
if (over
&& mx >= px
&& my >= py
&& mx < px + (sint32) itemw
&& my < py + (sint32) itemh
)
{
if ( CWidgetManager::getInstance()->getPointer()->getButtonState() & NLMISC::leftButton)
{
textId = getTexId(_TexsPushedId, selectedTexIndex);
color = getCol(_ColPushed, selectedTexIndex);
}
else
{
textId = getTexId(_TexsOverId, selectedTexIndex);
color = getCol(_ColOver, selectedTexIndex);
}
}
else
{
textId = getTexId(_TexsId, selectedTexIndex);
color = getCol(_Col, selectedTexIndex);
}
}
CViewRenderer::getInstance()->drawRotFlipBitmap (_RenderLayer, px, py, itemw, itemh, 0, false,
textId,
color);
}
//=======================================================================================
void CViewBitmapCombo::parseTexList(const std::string &names, TStringArray &dest)
{
static const char sep[] = " ,\t";
std::string::size_type pos = 0, nextPos;
dest.clear();
do
{
nextPos = names.find_first_of(sep, pos);
if (pos != nextPos)
{
dest.push_back(names.substr(pos, nextPos - pos));
}
pos = names.find_first_not_of(sep, nextPos);
}
while (pos != std::string::npos);
}
//=======================================================================================
void CViewBitmapCombo::parseColList(const std::string &names,TColorArray &dest)
{
static const char sep[] = ",\t";
std::string::size_type pos = 0, nextPos;
dest.clear();
std::string col;
do
{
nextPos = names.find_first_of(sep, pos);
if (pos != nextPos)
{
col = names.substr(pos, nextPos - pos);
int r = 0, g = 0, b = 0, a = 255;
sscanf (col.c_str(), "%d %d %d %d", &r, &g, &b, &a);
NLMISC::clamp (r, 0, 255);
NLMISC::clamp (g, 0, 255);
NLMISC::clamp (b, 0, 255);
NLMISC::clamp (a, 0, 255);
dest.push_back(NLMISC::CRGBA((uint8) r, (uint8) g, (uint8) b, (uint8) a));
}
pos = names.find_first_not_of(sep, nextPos);
}
while (pos != std::string::npos);
}
//=======================================================================================
void CViewBitmapCombo::setupSize()
{
uint w, h;
_CD.getDimensions(w, h);
setW(w);
setH(h);
invalidateCoords();
}
//=======================================================================================
void CViewBitmapCombo::update(ICDBNode * /* leaf */)
{
setupSize();
}
//=======================================================================================
/** copy an array of char * into an array of strings
*/
static void copyStrArrayFromChar(CViewBitmapCombo::TStringArray &dest, const char * const src[], uint numColor)
{
dest.resize(numColor);
for(uint k = 0; k < numColor; ++k)
{
dest[k] = src[k];
}
}
static void copyRGBAVectorFromRGBAArray(CViewBitmapCombo::TColorArray &dest, const NLMISC::CRGBA src[], uint numColor)
{
dest.resize(numColor);
std::copy(src, src + numColor, dest.begin());
}
//=======================================================================================
void CViewBitmapCombo::setTexs(const char * const tex[], uint numTex)
{
copyStrArrayFromChar(_Texs, tex, numTex);
}
//=======================================================================================
void CViewBitmapCombo::setTexsOver(const char * const tex[], uint numTex)
{
copyStrArrayFromChar(_TexsOver, tex, numTex);
}
//=======================================================================================
void CViewBitmapCombo::setTexsPushed(const char * const tex[], uint numTex)
{
copyStrArrayFromChar(_TexsPushed, tex, numTex);
}
//=======================================================================================
void CViewBitmapCombo::setColors(const NLMISC::CRGBA colors[], uint numColors)
{
copyRGBAVectorFromRGBAArray(_Col, colors, numColors);
}
//=======================================================================================
void CViewBitmapCombo::setColorsOver(const NLMISC::CRGBA colors[], uint numColors)
{
copyRGBAVectorFromRGBAArray(_ColOver, colors, numColors);
}
//=======================================================================================
void CViewBitmapCombo::setColorsPushed(const NLMISC::CRGBA colors[], uint numColors)
{
copyRGBAVectorFromRGBAArray(_ColPushed, colors, numColors);
}
}

View file

@ -49,7 +49,7 @@
#include "nel/gui/view_bitmap.h" #include "nel/gui/view_bitmap.h"
//#include "view_bitmap_progress.h" //#include "view_bitmap_progress.h"
#include "view_bitmap_faber_mp.h" #include "view_bitmap_faber_mp.h"
#include "view_bitmap_combo.h" #include "nel/gui/view_bitmap_combo.h"
#include "nel/gui/view_text.h" #include "nel/gui/view_text.h"
#include "nel/gui/view_text_id.h" #include "nel/gui/view_text_id.h"
#include "nel/gui/view_text_formated.h" #include "nel/gui/view_text_formated.h"

View file

@ -38,7 +38,7 @@
// View // View
#include "nel/gui/view_bitmap.h" #include "nel/gui/view_bitmap.h"
#include "view_bitmap_faber_mp.h" #include "view_bitmap_faber_mp.h"
#include "view_bitmap_combo.h" #include "nel/gui/view_bitmap_combo.h"
#include "nel/gui/view_text.h" #include "nel/gui/view_text.h"
#include "nel/gui/view_text_formated.h" #include "nel/gui/view_text_formated.h"
#include "nel/gui/view_text_id.h" #include "nel/gui/view_text_id.h"

View file

@ -1,579 +0,0 @@
// 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 "view_bitmap_combo.h"
#include "nel/misc/xml_auto_ptr.h"
#include "nel/gui/db_manager.h"
#include "nel/gui/view_renderer.h"
#include "nel/gui/widget_manager.h"
#include "nel/gui/view_pointer_base.h"
#include "nel/gui/interface_group.h"
using namespace NLMISC;
//=======================================================================================
bool CComboBoxDesc::parse(xmlNodePtr cur, CInterfaceElement*owner)
{
nlassert(owner);
const std::string &ownerId = owner->getId();
CXMLAutoPtr prop;
//
prop = xmlGetProp(cur, (const xmlChar *) "selected");
if (!prop)
{
nlwarning((ownerId + " : Couldn't read 'selected' field").c_str());
return false;
}
owner->relativeSInt64Read(CurrSelected, "selected", prop, "0");
//
prop = xmlGetProp(cur, (const xmlChar *) "num_row");
owner->relativeSInt64Read(NumRow, "num_row", prop, "1");
//
prop = xmlGetProp(cur, (const xmlChar *) "num_col");
owner->relativeSInt64Read(NumCol, "num_col", prop, "1");
//
prop = xmlGetProp(cur, (const xmlChar *) "itemw");
owner->relativeSInt64Read(ItemWidth, "itemw", prop, "32");
//
prop = xmlGetProp(cur, (const xmlChar *) "itemh");
owner->relativeSInt64Read(ItemHeight, "itemh", prop, "32");
//
prop = xmlGetProp(cur, (const xmlChar *) "unrolled");
owner->relativeBoolRead(Unrolled, "unrolled", prop, "false");
//
prop = xmlGetProp(cur, (xmlChar *) "wgap");
owner->relativeSInt64Read(WGap, "wgap", prop, "0");
//
prop = xmlGetProp(cur, (xmlChar *) "hgap");
owner->relativeSInt64Read(HGap, "hgap", prop, "0");
//
prop = xmlGetProp(cur, (xmlChar *) "wgap_selected");
owner->relativeSInt64Read(WGapSelected, "wgap_selected", prop, "0");
//
prop = xmlGetProp(cur, (xmlChar *) "hgap_selected");
owner->relativeSInt64Read(HGapSelected, "hgap_selected", prop, "0");
//
//
prop = xmlGetProp(cur, (xmlChar *) "num_sel");
owner->relativeSInt64Read(NumSel, "num_sel", prop, "1");
//
prop = (char*) xmlGetProp (cur, (xmlChar*)"align");
Align.readSInt32 ("0", ownerId + ":align");
if (prop)
{
const char *seekPtr = prop.getDatas();
while (*seekPtr != 0)
{
if ((*seekPtr=='l')||(*seekPtr=='L'))
{
Align.setSInt32 (Align.getSInt32()&(~1));
}
if ((*seekPtr=='r')||(*seekPtr=='R'))
{
Align.setSInt32 (Align.getSInt32()|1);
}
if ((*seekPtr=='b')||(*seekPtr=='B'))
{
Align.setSInt32 (Align.getSInt32()&(~2));
}
if ((*seekPtr=='t')||(*seekPtr=='T'))
{
Align.setSInt32 (Align.getSInt32()|2);
}
++seekPtr;
}
}
//
return true;
}
//=========================================================================================
void CComboBoxDesc::addObserver(ICDBNode::IPropertyObserver *obs)
{
// Add observers on dimensions
if (NumRow.getNodePtr())
{
ICDBNode::CTextId textId;
NumRow.getNodePtr()->addObserver(obs, textId);
}
if (NumCol.getNodePtr())
{
ICDBNode::CTextId textId;
NumCol.getNodePtr()->addObserver(obs, textId);
}
if (ItemWidth.getNodePtr())
{
ICDBNode::CTextId textId;
ItemWidth.getNodePtr()->addObserver(obs, textId);
}
if (ItemHeight.getNodePtr())
{
ICDBNode::CTextId textId;
ItemHeight.getNodePtr()->addObserver(obs, textId);
}
if (Unrolled.getNodePtr())
{
ICDBNode::CTextId textId;
Unrolled.getNodePtr()->addObserver(obs, textId);
}
}
//=======================================================================================
void CComboBoxDesc::getGridSize(uint &numRow, uint &numCol) const
{
numRow = NumRow.getSInt32();
numCol = NumCol.getSInt32();
if (numRow == 0 || numCol == 0) return;
if (!Unrolled.getBool())
{
numRow = numCol = 1;
}
}
//=======================================================================================
void CComboBoxDesc::getDimensions(uint &w, uint &h) const
{
uint numRow, numCol;
getGridSize(numRow, numCol);
w = numCol * (ItemWidth.getSInt32() + WGap.getSInt32());
h = numRow * (ItemHeight.getSInt32() + HGap.getSInt32());
//
if (numCol == 1) w -= WGap.getSInt32();
else w += WGapSelected.getSInt32() - WGap.getSInt32();
//
if (numRow == 1) h -= HGap.getSInt32();
else h += HGapSelected.getSInt32() - HGap.getSInt32();
}
//=======================================================================================
NLMISC_REGISTER_OBJECT(CViewBase, CViewBitmapCombo, std::string, "bitmap_combo");
CViewBitmapCombo::CViewBitmapCombo(const TCtorParam &param) : CViewBase(param)
{
}
//=======================================================================================
bool CViewBitmapCombo::parse(xmlNodePtr cur, CInterfaceGroup * parentGroup)
{
if (! CViewBase::parse(cur, parentGroup) )
{
parseError(parentGroup);
return false;
}
CXMLAutoPtr prop;
std::string texs;
prop = xmlGetProp(cur, (xmlChar *)"tx_normal");
if (prop) texs = (const char*)prop;
std::string texsOver;
prop = xmlGetProp(cur, (xmlChar *)"tx_over");
if (prop) texsOver = (const char*)prop;
std::string texsPushed;
prop = xmlGetProp(cur, (xmlChar *)"tx_pushed");
if (prop) texsPushed = (const char*)prop;
//
// for colors, an empty strings means all colors are white
//
std::string col;
prop = xmlGetProp(cur, (xmlChar *)"col_normal");
if (prop) col = (const char*)prop;
std::string colOver;
prop = xmlGetProp(cur, (xmlChar *)"col_over");
if (prop) colOver = (const char*)prop;
std::string colPushed;
prop = xmlGetProp(cur, (xmlChar *)"col_pushed");
if (prop) colPushed = (const char*)prop;
/* if (texs.empty() || texsOver.empty() || texsPushed.empty())
{
parseError(parentGroup, "Cannot read tx_normal, tx_over, or tx_pushed");
return false;
}*/
parseTexList(texs, _Texs);
parseTexList(texsOver, _TexsOver);
parseTexList(texsPushed, _TexsPushed);
parseColList(col, _Col);
parseColList(colOver, _ColOver);
parseColList(colPushed, _ColPushed);
//
/* if (_Texs.size() != _TexsOver.size() || _TexsOver.size() != _TexsPushed.size())
{
parseError(parentGroup, "Texture names arrays do not have the same size");
return false;
}
//
uint numCols = NLMISC::maxof(_Col.size(), _ColOver.size(), _ColPushed.size());
if (!
(
(_Col.empty() || _Col.size() == numCols)
&& (_ColOver.empty() || _ColOver.size() == numCols)
&& (_ColPushed.empty() || _ColPushed.size() == numCols)
)
)
{
parseError(parentGroup, "Color names arrays do not have the same size (note an empty array is valid, means all color are 255 255 255");
return false;
}*/
//
if (!_CD.parse(cur, this))
{
return false;
}
//
setupSize();
//
_CD.addObserver(this);
return true;
}
//=======================================================================================
NLMISC::CRGBA CViewBitmapCombo::getCol(const CViewBitmapCombo::TColorArray &array,uint index)
{
if (array.empty()) return CRGBA::White;
return array[index % array.size()];
}
//=======================================================================================
const std::string *CViewBitmapCombo::getTex(const TStringArray &array,uint index)
{
if (array.empty()) return NULL;
return &array[index % array.size()];
}
//=======================================================================================
sint32 CViewBitmapCombo::getTexId(const TIdArray &array, uint index)
{
if (array.empty()) return -1;
return array[index % array.size()];
}
//=======================================================================================
void CViewBitmapCombo::draw()
{
if (_Texs.empty()) return;
uint numRow, numCol;
_CD.getGridSize(numRow, numCol);
if (numRow == 0 || numCol == 0) return;
sint32 mx = 0, my = 0;
CViewRenderer &rVR = *CViewRenderer::getInstance();
const std::vector<CViewBase *> &rVB = CWidgetManager::getInstance()->getViewsUnderPointer();
if (!CWidgetManager::getInstance()->getPointer()) return;
CWidgetManager::getInstance()->getPointer()->getPointerDispPos(mx, my);
bool over = false;
uint32 i;
for (i = 0; i < rVB.size(); ++i)
{
if (rVB[i] == this)
{
over = true;
break;
}
}
if (_TexsId.size() == 0)
{
for (i = 0; i < _Texs.size(); ++i)
_TexsId.push_back(rVR.getTextureIdFromName(_Texs[i]));
for (i = 0; i < _TexsOver.size(); ++i)
_TexsOverId.push_back(rVR.getTextureIdFromName(_TexsOver[i]));
for (i = 0; i < _TexsPushed.size(); ++i)
_TexsPushedId.push_back(rVR.getTextureIdFromName(_TexsPushed[i]));
}
sint32 textId;
CRGBA color;
uint selectedTexIndex = _CD.CurrSelected.getSInt32();
uint itemw = _CD.ItemWidth.getSInt32() + _CD.WGap.getSInt32();
uint itemh = _CD.ItemHeight.getSInt32() + _CD.HGap.getSInt32();
uint counter = 0;
bool overItem = false;
for(uint x = 0; x < numCol; ++x)
{
for(uint y = 0; y < numRow; ++y)
{
uint texIndex = counter;
if (counter != 0)
{
if (counter == selectedTexIndex)
{
texIndex = 0;
}
sint px;
sint py;
// get the right position depending on alignment
if (_CD.Align.getSInt32() & 1) // right align ?
{
px = _XReal + _WReal - (x + 1) * itemw;
}
else
{
px = _XReal + x * itemw;
}
// top align ?
if (_CD.Align.getSInt32() & 2)
{
py = _YReal + _HReal - (y + 1) * itemh;
}
else
{
py = _YReal + y * itemh;
}
if (x != 0)
{
if (_CD.Align.getSInt32() & 1)
px -= _CD.WGapSelected.getSInt32() - _CD.WGap.getSInt32();
else px += _CD.WGapSelected.getSInt32() - _CD.WGap.getSInt32();
}
if (y != 0)
{
if (_CD.Align.getSInt32() & 2)
py -= _CD.HGapSelected.getSInt32() - _CD.HGap.getSInt32();
else py += _CD.HGapSelected.getSInt32() - _CD.HGap.getSInt32();
}
// is the mouse on current item ?
if (over
&& mx >= px
&& my >= py
&& mx < px + (sint32) itemw
&& my < py + (sint32) itemh)
{
overItem = true;
if ( CWidgetManager::getInstance()->getPointer()->getButtonState() & NLMISC::leftButton)
{
textId = getTexId(_TexsPushedId, texIndex);
color = getCol(_ColPushed, texIndex);
}
else
{
textId = getTexId(_TexsOverId, texIndex);
color = getCol(_ColOver, texIndex);
}
}
else
{
textId = getTexId(_TexsId, texIndex);
color = getCol(_Col, texIndex);
}
CViewRenderer::getInstance()->drawRotFlipBitmap (_RenderLayer, px, py, itemw, itemh, 0, false,
textId,
color);
}
++counter;
if ((sint32) counter == _CD.NumSel.getSInt32())
break;
}
}
if ((sint32) selectedTexIndex >= _CD.NumSel.getSInt32())
{
return;
}
// draw current selection
sint32 px;
sint32 py;
//
if (_CD.Align.getSInt32() & 1)
{
px = _XReal + _WReal - itemw;
}
else
{
px = _XReal;
}
//
if (_CD.Align.getSInt32() & 2)
{
py = _YReal + _HReal - itemh;
}
else
{
py = _YReal;
}
//
if (_CD.Unrolled.getBool())
{
if (overItem && CWidgetManager::getInstance()->getPointer()->getButtonState() & NLMISC::leftButton)
{
textId = getTexId(_TexsId, selectedTexIndex);
color = getCol(_Col, selectedTexIndex);
}
else
{
textId = getTexId(_TexsPushedId, selectedTexIndex);
color = getCol(_ColPushed, selectedTexIndex);
}
}
else
{
if (over
&& mx >= px
&& my >= py
&& mx < px + (sint32) itemw
&& my < py + (sint32) itemh
)
{
if ( CWidgetManager::getInstance()->getPointer()->getButtonState() & NLMISC::leftButton)
{
textId = getTexId(_TexsPushedId, selectedTexIndex);
color = getCol(_ColPushed, selectedTexIndex);
}
else
{
textId = getTexId(_TexsOverId, selectedTexIndex);
color = getCol(_ColOver, selectedTexIndex);
}
}
else
{
textId = getTexId(_TexsId, selectedTexIndex);
color = getCol(_Col, selectedTexIndex);
}
}
CViewRenderer::getInstance()->drawRotFlipBitmap (_RenderLayer, px, py, itemw, itemh, 0, false,
textId,
color);
}
//=======================================================================================
void CViewBitmapCombo::parseTexList(const std::string &names, TStringArray &dest)
{
static const char sep[] = " ,\t";
std::string::size_type pos = 0, nextPos;
dest.clear();
do
{
nextPos = names.find_first_of(sep, pos);
if (pos != nextPos)
{
dest.push_back(names.substr(pos, nextPos - pos));
}
pos = names.find_first_not_of(sep, nextPos);
}
while (pos != std::string::npos);
}
//=======================================================================================
void CViewBitmapCombo::parseColList(const std::string &names,TColorArray &dest)
{
static const char sep[] = ",\t";
std::string::size_type pos = 0, nextPos;
dest.clear();
std::string col;
do
{
nextPos = names.find_first_of(sep, pos);
if (pos != nextPos)
{
col = names.substr(pos, nextPos - pos);
int r = 0, g = 0, b = 0, a = 255;
sscanf (col.c_str(), "%d %d %d %d", &r, &g, &b, &a);
NLMISC::clamp (r, 0, 255);
NLMISC::clamp (g, 0, 255);
NLMISC::clamp (b, 0, 255);
NLMISC::clamp (a, 0, 255);
dest.push_back(NLMISC::CRGBA((uint8) r, (uint8) g, (uint8) b, (uint8) a));
}
pos = names.find_first_not_of(sep, nextPos);
}
while (pos != std::string::npos);
}
//=======================================================================================
void CViewBitmapCombo::setupSize()
{
uint w, h;
_CD.getDimensions(w, h);
setW(w);
setH(h);
invalidateCoords();
}
//=======================================================================================
void CViewBitmapCombo::update(ICDBNode * /* leaf */)
{
setupSize();
}
//=======================================================================================
/** copy an array of char * into an array of strings
*/
static void copyStrArrayFromChar(CViewBitmapCombo::TStringArray &dest, const char * const src[], uint numColor)
{
dest.resize(numColor);
for(uint k = 0; k < numColor; ++k)
{
dest[k] = src[k];
}
}
static void copyRGBAVectorFromRGBAArray(CViewBitmapCombo::TColorArray &dest, const NLMISC::CRGBA src[], uint numColor)
{
dest.resize(numColor);
std::copy(src, src + numColor, dest.begin());
}
//=======================================================================================
void CViewBitmapCombo::setTexs(const char * const tex[], uint numTex)
{
copyStrArrayFromChar(_Texs, tex, numTex);
}
//=======================================================================================
void CViewBitmapCombo::setTexsOver(const char * const tex[], uint numTex)
{
copyStrArrayFromChar(_TexsOver, tex, numTex);
}
//=======================================================================================
void CViewBitmapCombo::setTexsPushed(const char * const tex[], uint numTex)
{
copyStrArrayFromChar(_TexsPushed, tex, numTex);
}
//=======================================================================================
void CViewBitmapCombo::setColors(const NLMISC::CRGBA colors[], uint numColors)
{
copyRGBAVectorFromRGBAArray(_Col, colors, numColors);
}
//=======================================================================================
void CViewBitmapCombo::setColorsOver(const NLMISC::CRGBA colors[], uint numColors)
{
copyRGBAVectorFromRGBAArray(_ColOver, colors, numColors);
}
//=======================================================================================
void CViewBitmapCombo::setColorsPushed(const NLMISC::CRGBA colors[], uint numColors)
{
copyRGBAVectorFromRGBAArray(_ColPushed, colors, numColors);
}

View file

@ -1,170 +0,0 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef NL_VIEW_BITMAP_COMBO_H
#define NL_VIEW_BITMAP_COMBO_H
#include "nel/misc/cdb.h"
#include "nel/gui/view_base.h"
#include "nel/3d/u_texture.h"
#include <string>
#include <vector>
/** Description of a combo box, this can be parsed from an xml node
* The bitmap layout is as follow :
*
* I W I W I W
* t G t G t G
* e a e a e a
* m p m p m p
* W S W W
* i e i i
* d l d d
* t e t t
* h c h h
* t
* e
* d
* +----+---+----+---+---+---+---+--...
* |ssss| |****| |***| |***|
* ItemHeight |ssss| |****| |***| |***
* +----+---+----+---+---+---+---+--...
* | | | | | | | |
* HGapSeleted | | | | | | | |
* +----+---+----+---+---+---+---+--...
* |****| |****| |***| |***|
* ItemHeight |****| |****| |***| |***|
* +----+---+----+---+---+---+---+--...
* | | | | | | | |
* HGap | | | | | | | |
* +----+---+----+---+---+---+---+--...
* |****| |****| |***| |***|
* ItemHeight |****| |****| |***| |***|
* . . . . . . . .
* . . . . . . . .
* s : selected item. . . . . . .
* * : where bitmap are displayed
*/
struct CComboBoxDesc
{
bool parse(xmlNodePtr cur, CInterfaceElement *owner);
void addObserver(NLMISC::ICDBNode::IPropertyObserver *obs);
void getGridSize(uint &numRow,uint &numCol) const;
void getDimensions(uint &width, uint &height) const;
CInterfaceProperty NumRow;
CInterfaceProperty NumCol;
CInterfaceProperty CurrSelected;
CInterfaceProperty ItemWidth;
CInterfaceProperty ItemHeight;
CInterfaceProperty Unrolled;
CInterfaceProperty WGapSelected;
CInterfaceProperty WGap;
CInterfaceProperty HGapSelected;
CInterfaceProperty HGap;
CInterfaceProperty NumSel;
CInterfaceProperty Align;
};
/**
* A combo box with several bitmaps in it
* \author Nicolas Vizerie
* \author Nevrax France
* \date 2002
*/
class CViewBitmapCombo : public CViewBase, public NLMISC::ICDBNode::IPropertyObserver
{
public:
typedef std::vector<sint32> TIdArray;
typedef std::vector<std::string> TStringArray;
typedef std::vector<NLMISC::CRGBA> TColorArray;
public:
/// ctor
CViewBitmapCombo(const TCtorParam &param);
/**
* parse an xml node and initialize the base view members. Must call CViewBase::parse
* \param cur : pointer to the xml node to be parsed
* \param parentGroup : the parent group of the view
* \partam id : a refence to the string that will receive the view ID
* \return true if success
*/
bool parse(xmlNodePtr cur,CInterfaceGroup * parentGroup);
virtual uint32 getMemory() { return (uint32)(sizeof(*this)+_Id.size()); }
/**
* draw the view
*/
void draw();
// access to texture & colors
const TStringArray &getTexs() const { return _Texs; }
const TStringArray &getTexsOver() const { return _TexsOver; }
const TStringArray &getTexsPushed() const { return _TexsPushed; }
//
const TColorArray &getColors() const { return _Col; }
const TColorArray &getColorsOver() const { return _ColOver; }
const TColorArray &getColorsPushed() const { return _ColPushed; }
//
void setTexs(const char * const tex[], uint numTex);
void setTexsOver(const char * const tex[], uint numTex);
void setTexsPushed(const char * const tex[], uint numTex);
//
void setColors(const NLMISC::CRGBA colors[], uint numColors);
void setColorsOver(const NLMISC::CRGBA colors[], uint numColors);
void setColorsPushed(const NLMISC::CRGBA colors[], uint numColors);
///////////////////////////////////////////////////////////////////////////////////
private:
//
TStringArray _Texs;
TStringArray _TexsOver;
TStringArray _TexsPushed;
TIdArray _TexsId;
TIdArray _TexsOverId;
TIdArray _TexsPushedId;
TColorArray _Col;
TColorArray _ColOver;
TColorArray _ColPushed;
CComboBoxDesc _CD;
CInterfaceElement *_Owner;
private:
void parseTexList(const std::string &names, TStringArray &dest);
void parseColList(const std::string &names, TColorArray &dest);
void setupSize();
void getDimensions(uint &numRow, uint &numCol);
// From ICDBNode::IPropertyObserver
void update(NLMISC::ICDBNode *leaf);
// Return a color from the array, or white if it is empty
static NLMISC::CRGBA getCol(const TColorArray &array, uint index);
static const std::string *getTex(const TStringArray &array, uint index);
static sint32 getTexId(const TIdArray &array, uint index);
};
#endif