📄 guitreeviewctrl.cc
字号:
{
if(!Parent::onWake() || !mProfile->constructBitmapArray())
return false;
// If destroy on sleep, then we have to give things a chance to rebuild.
if(mDestroyOnSleep)
{
destroyTree();
Con::executef(this, 1, "onWake");
// (Re)build our icon table.
const char * res = Con::executef(this, 1, "onDefineIcons");
// If no icons were defined in script then use defaults.
if(!(dAtob(res)))
{
buildIconTable(NULL);
}
}
// Update the row height, if appropriate.
if(mProfile->mAutoSizeHeight)
{
// make sure it's big enough for both bitmap AND font...
mItemHeight = getMax((S32)mFont->getHeight(), (S32)mProfile->mBitmapArrayRects[0].extent.y);
}
return true;
}
void GuiTreeViewCtrl::onSleep()
{
Parent::onSleep();
// If appropriate, blast the tree. (We probably rebuild it on wake.)
if( mDestroyOnSleep )
destroyTree();
}
bool GuiTreeViewCtrl::buildIconTable(const char * icons)
{
// Icons should be designated by the bitmap/png file names (minus the file extensions)
// and separated by colons (:). This list should be synchronized with the Icons enum.
// This is an abominal piece of code. -- BJG
if (!icons)
{
#ifdef TGE_RPG_UI ///TGE_RPG_UI
icons = "default:"
"simgroup:"
"simgroup_closed:"
"simgroup_selected:"
"simgroup_selected_closed:"
"audio:"
"camera:"
"fxfoliage:"
"fxlight:"
"fxshapereplicator:"
"fxsunlight:"
"hidden:"
"interior:"
"lightning:"
"shll_icon_passworded_hi:"
"shll_icon_passworded:"
"mission_area:"
"particle:"
"path:"
"pathmarker:"
"physical_area:"
"precipitation:"
"shape:"
"sky:"
"static_shape:"
"sun:"
"terrain:"
"trigger:"
"water:"
"default";
#else
icons = "ui/icons/default:"
"ui/icons/simgroup:"
"ui/icons/simgroup_closed:"
"ui/icons/simgroup_selected:"
"ui/icons/simgroup_selected_closed:"
"ui/icons/audio:"
"ui/icons/camera:"
"ui/icons/fxfoliage:"
"ui/icons/fxlight:"
"ui/icons/fxshapereplicator:"
"ui/icons/fxsunlight:"
"ui/icons/hidden:"
"ui/icons/interior:"
"ui/icons/lightning:"
"ui/icons/ui/icons/shll_icon_passworded_hi:"
"ui/icons/shll_icon_passworded:"
"ui/icons/mission_area:"
"ui/icons/particle:"
"ui/icons/path:"
"ui/icons/pathmarker:"
"ui/icons/physical_area:"
"ui/icons/precipitation:"
"ui/icons/shape:"
"ui/icons/sky:"
"ui/icons/static_shape:"
"ui/icons/sun:"
"ui/icons/terrain:"
"ui/icons/trigger:"
"ui/icons/water:"
"ui/icons/default";
#endif
}
// Figure the size of the buffer we need...
const char* temp = dStrchr( icons, '\t' );
U32 textLen = temp ? ( temp - icons ) : dStrlen( icons );
// Allocate temporary space.
FrameAllocatorMarker txtBuff;
char* drawText = (char*)txtBuff.alloc(sizeof(char) * (textLen + 4));
dStrncpy( drawText, icons, textLen );
drawText[textLen] = '\0';
U32 numIcons = 0;
char *buf = (char*)txtBuff.alloc(sizeof(char) * 64);
char* token = dStrtok( drawText, ":" );
#ifdef TGE_RPG_UI ///TGE_RPG_UI
StringTableEntry pIconsPath = Con::getVariable("$theme::PathIcons");
AssertFatal(pIconsPath && pIconsPath[0],"$theme::PathIcons图标路径不能为空!");
#endif
// Count the number of icons and store them.
while (token && numIcons < MaxIcons)
{
#ifdef TGE_RPG_UI ///TGE_RPG_UI
dSprintf( buf, sizeof( buf ), "%s%s",pIconsPath ,token );
#else
dSprintf( buf, sizeof( buf ), "%s", token );
#endif
mIconTable[numIcons] = TextureHandle( buf, BitmapKeepTexture );
token = dStrtok( NULL, ":" );
numIcons++;
}
/*
图标列表导出为整张图片
GBitmap bmp(320,320,0,GBitmap::RGBA);
ColorI clr(0,0,0,0);
for(U32 m=0;m<320;m++)
for(U32 k=0;k<320;k++)
bmp.setColor(m,k,clr);
U32 nWrite=0;
for(U32 n=0; n< MaxIcons; n++)
{
int x = (n&15) * 16;
int y = (n>>4) * 16;
if(!bool(mIconTable[n]))
continue;
nWrite++;
bmp.blt(*(mIconTable[n]).getBitmap(),x,y);
}
char szPath[256];
FileStream stream;
if(ResourceManager->openFileForWrite(stream,avar("common/icon%d.png",nWrite) ) )
bmp.writePNG(stream);
*/
return true;
}
//------------------------------------------------------------------------------
void GuiTreeViewCtrl::onPreRender()
{
Parent::onPreRender();
// Update every render in case new objects are added
buildVisibleTree();
}
//------------------------------------------------------------------------------
bool GuiTreeViewCtrl::hitTest(const Point2I & pnt, Item* & item, BitSet32 & flags)
{
// Initialize some things.
const Point2I pos = globalToLocalCoord(pnt);
flags.clear();
item = 0;
// get the hit cell
Point2I cell((pos.x < 0 ? -1 : pos.x / mCellSize.x),
(pos.y < 0 ? -1 : pos.y / mCellSize.y));
// valid?
if((cell.x < 0 || cell.x >= mSize.x) ||
(cell.y < 0 || cell.y >= mSize.y))
return false;
flags.set(OnRow);
// Grab the cell.
if (cell.y >= mVisibleItems.size())
return false; //Invalid cell, so don't do anything
item = mVisibleItems[cell.y];
S32 min = mTabSize * item->mTabLevel;
// left of icon/text?
if(pos.x < min)
{
flags.set(OnIndent);
return true;
}
// check image
S32 image = BmpChild;
if(item->isInspectorData())
image = item->isExpanded() ? BmpExp : BmpCon;
else
image = item->isExpanded() ? item->getExpandedImage() : item->getNormalImage();
if((image >= 0) && (image < mProfile->mBitmapArrayRects.size()))
min += mProfile->mBitmapArrayRects[image].extent.x;
// Is it on the image?
if(pos.x < min)
{
flags.set(OnImage);
return(true);
}
// Bump over to the start of the text.
min += mTextOffset;
// Check against the text.
FrameAllocatorMarker txtAlloc;
U32 bufLen = item->getDisplayTextLength();
char *buf = (char*)txtAlloc.alloc(bufLen);
item->getDisplayText(bufLen, buf);
min += mProfile->mFont->getStrWidth(buf);
if(pos.x < min)
flags.set(OnText);
return true;
}
void GuiTreeViewCtrl::setInstantGroup(SimObject * obj)
{
// make sure we're talking about a group.
SimGroup * grp = dynamic_cast<SimGroup*>(obj);
// Set the instant group variable.
if(grp)
{
Con::setVariable("instantGroup", grp->getIdString());
}
}
void GuiTreeViewCtrl::syncSelection()
{
// for each visible item check to see if it is on the mSelected list.
// if it is then make sure that it is on the mSelectedItems list as well.
for (S32 i = 0; i < mVisibleItems.size(); i++)
{
for (S32 j = 0; j < mSelected.size(); j++)
{
if (mVisibleItems[i]->mId == mSelected[j])
{
// check to see if it is on the visible items list.
bool addToSelectedItems = true;
for (S32 k = 0; k < mSelectedItems.size(); k++)
{
if (mSelected[j] == mSelectedItems[k]->mId)
{
// don't add it
addToSelectedItems = false;
}
}
if (addToSelectedItems)
{
mVisibleItems[i]->mState.set(Item::Selected, true);
mSelectedItems.push_front(mVisibleItems[i]);
break;
}
}
else if (mVisibleItems[i]->isInspectorData())
{
if (mVisibleItems[i]->getObject()->getId() == mSelected[j])
{
// check to see if it is on the visible items list.
bool addToSelectedItems = true;
for (S32 k = 0; k < mSelectedItems.size(); k++)
{
if (mSelectedItems[k]->isInspectorData())
{
if (mSelected[j] == mSelectedItems[k]->getObject()->getId())
{
// don't add it
addToSelectedItems = false;
}
}
else
{
if (mSelected[j] == mSelectedItems[k]->mId)
{
// don't add it
addToSelectedItems = false;
}
}
}
if (addToSelectedItems)
{
mVisibleItems[i]->mState.set(Item::Selected, true);
mSelectedItems.push_front(mVisibleItems[i]);
break;
}
}
}
}
}
}
void GuiTreeViewCtrl::removeSelection(S32 itemId)
{
if (mDebug)
Con::printf("removeSelection called");
Item * item = getItem(itemId);
// the item may have been selected at one point but was never created/visible in the tree
// so remove it.
for (S32 j = 0; j <mSelected.size(); j++)
{
if (item)
{
if (item->isInspectorData())
{
if (item->getObject()->getId() == mSelected[j])
{
mSelected.erase(j);
break;
}
}
}
if (mSelected[j] == itemId)
{
mSelected.erase(j);
break;
}
}
if(!item)
{
// maybe what we were passed wasn't an item id but an object id.
for (S32 i = 0; i <mItems.size(); i++)
{
if (mItems[i] != 0)
{
if (mItems[i]->isInspectorData())
{
if (mItems[i]->getObject()->getId() == itemId)
{
item = mItems[i];
break;
}
}
}
}
if (!item)
{
//Con::errorf(ConsoleLogEntry::General, "GuiTreeViewCtrl::removeSelection: invalid item id! Perhaps it isn't visible yet");
return;
}
}
item->mState.set(Item::Selected, false);
for (S32 i = 0; i < mSelectedItems.size(); i++)
{
if (mSelectedItems[i] == item)
{
mSelectedItems.erase(i);
break;
}
}
}
void GuiTreeViewCtrl::addSelection(S32 itemId)
{
if (mDebug)
Con::printf("addSelection called");
Item * item = getItem(itemId);
if(!item)
{
// maybe what we were passed wasn't an item id but an object id.
for (S32 i = 0; i <mItems.size(); i++)
{
if (mItems[i] != 0)
{
if (mItems[i]->isInspectorData())
{
if (mItems[i]->getObject()->getId() == itemId)
{
item = mItems[i];
//looks like it is. check to see if it is on the list
bool alreadySelected = false;
Vector<Item *>::iterator i;
for(i = mSelectedItems.begin(); i != mSelectedItems.end(); i++)
{
if (*(i) == item)
{
//already a selected item which means this call should be ignored
alreadySelected = true;
return;
}
}
break;
}
}
}
}
if (!item)
{
// Do we want to allow more than one selected item?
if( !mMultipleSelections )
clearSelection();
//Con::errorf(ConsoleLogEntry::General, "GuiTreeViewCtrl::addSelection: invalid item id! Perhaps it isn't visible yet.");
mSelected.push_front(itemId);
return;
}
}
else
{
// Do we want to allow more than one selected item?
if( !mMultipleSelections )
clearSelection();
// regardless of whether we found an item, we keep track of the Id that was passed
// as the item may simply not have been created/visible yet.
mSelected.push_front(itemId);
}
item->mState.set(Item::Selected, true);
// Also make it so we can see it if we didn't already.
scrollVisible(item);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -