📄 guitreeviewctrl.cc
字号:
//Con::executef(this,2, "onDeleteObject",Con::getIntArg(item->mInspectorInfo.mObject->getIdString()));
SimObject *obj = item->getObject();
if( obj )
obj->deleteObject();
item->setObject(NULL);
}
else
{
// Clean up the memory...
if ( item->getText() )
{
delete [] item->getText();
item->setText(NULL);
}
if ( item->getValue() )
{
delete [] item->getValue();
item->setValue(NULL);
}
}
// unlink
if(item->mPrevious)
item->mPrevious->mNext = item->mNext;
if(item->mNext)
item->mNext->mPrevious = item->mPrevious;
if(item->mParent && (item->mParent->mChild == item))
item->mParent->mChild = item->mNext;
// remove from vector
mItems[item->mId-1] = 0;
// set as root free item
item->mNext = mItemFreeList;
mItemFreeList = item;
mItemCount--;
}
//------------------------------------------------------------------------------
void GuiTreeViewCtrl::deleteItem(Item *item)
{
removeItem(item->mId);
}
//------------------------------------------------------------------------------
void GuiTreeViewCtrl::destroyTree()
{
// clear the item list
for(U32 i = 0; i < mItems.size(); i++)
delete mItems[i];
mItems.clear();
// clear the free list
while(mItemFreeList)
{
Item * next = mItemFreeList->mNext;
delete mItemFreeList;
mItemFreeList = next;
}
mVisibleItems.clear();
mSelectedItems.clear();
//
mItemFreeList = 0;
mRoot = 0;
mItemCount = 0;
mSelectedItem = 0;
mDraggedToItem = 0;
}
//------------------------------------------------------------------------------
void GuiTreeViewCtrl::buildItem( Item* item, U32 tabLevel )
{
if (!item )
return;
// If it's inspector data, make sure we still have it, if not, kill it.
if(item->isInspectorData())
{
// Blast an item if it doesn't have a corresponding SimObject...
if(!item->getObject())
{
removeItem(item->mId);
return;
}
}
// If it's a virtual parent, give a chance to update itself...
if(item->mState.test( Item::VirtualParent) )
{
// If it returns true the item has been removed.
if(!onVirtualParentBuild(item))
return;
}
item->mTabLevel = tabLevel;
mVisibleItems.push_back( item );
if ( bool( mProfile->mFont ) )
{
S32 width = ( tabLevel + 1 ) * mTabSize + item->getDisplayTextWidth(mProfile->mFont);
if ( mProfile->mBitmapArrayRects.size() > 0 )
width += mProfile->mBitmapArrayRects[0].extent.x;
width += (item->mTabLevel+1) * mItemHeight; // using mItemHeight for icon width, close enough
// this will only fail if somebody starts using super wide icons.
if ( width > mMaxWidth )
mMaxWidth = width;
}
// if expanded, then add all the children items as well
if ( item->isExpanded() )
{
Item * child = item->mChild;
while ( child )
{
// Bit of a hack so we can safely remove items as we
// traverse.
Item *tmp = child;
child = child->mNext;
buildItem( tmp, tabLevel + 1 );
}
}
}
//------------------------------------------------------------------------------
void GuiTreeViewCtrl::buildVisibleTree()
{
mMaxWidth = 0;
mVisibleItems.clear();
// Update the flags.
mFlags.clear(RebuildVisible);
// build the root items
Item * traverse = mRoot;
while(traverse)
{
buildItem(traverse, 0);
traverse = traverse->mNext;
}
// adjust the GuiArrayCtrl
mCellSize.set(mMaxWidth+1, mItemHeight);
setSize(Point2I(1, mVisibleItems.size()));
syncSelection();
}
//------------------------------------------------------------------------------
bool GuiTreeViewCtrl::scrollVisible( Item *item )
{
// Now, make sure it's visible (ie, all parents expanded)
Item *parent = item->mParent;
if( !item->isInspectorData() && item->mState.test(Item::VirtualParent) )
onVirtualParentExpand(item);
while(parent)
{
parent->setExpanded(true);
if( !parent->isInspectorData() && parent->mState.test(Item::VirtualParent) )
onVirtualParentExpand(parent);
parent = parent->mParent;
}
// Get our scroll-pappy, if any.
GuiScrollCtrl *pappy = dynamic_cast<GuiScrollCtrl*>( getParent() );
if ( !pappy )
{
Con::warnf("GuiTreeViewCtrl::scrollVisible - parent control is not a GuiScrollCtrl!");
return false;
}
// And now, build the visible tree so we know where we have to scroll.
buildVisibleTree();
// All done, let's figure out where we have to scroll...
for(S32 i=0; i<mVisibleItems.size(); i++)
{
if(mVisibleItems[i] == item)
{
pappy->scrollRectVisible(RectI(0, i * mItemHeight, mMaxWidth, mItemHeight));
return true;
}
}
// If we got here, it's probably bad...
Con::errorf("GuiTreeViewCtrl::scrollVisible - was unable to find specified item in visible list!");
return false;
}
//------------------------------------------------------------------------------
S32 GuiTreeViewCtrl::insertItem(S32 parentId, const char * text, const char * value, const char * iconString, S16 normalImage, S16 expandedImage)
{
if((parentId < 0) || (parentId > mItems.size()))
{
Con::errorf(ConsoleLogEntry::General, "GuiTreeViewCtrl::insertItem: invalid parent id!");
return 0;
}
if((parentId != 0) && (mItems[parentId-1] == 0))
{
Con::errorf(ConsoleLogEntry::General, "GuiTreeViewCtrl::insertItem: parent item invalid!");
return 0;
}
S32 icon = getIcon(iconString);
// create an item (assigns id)
Item * item = createItem(icon);
// fill the data
item->setText( new char[dStrlen( text ) + 1] );
dStrcpy( item->getText(), text );
item->setValue( new char[dStrlen( value ) + 1] );
dStrcpy( item->getValue(), value );
item->setNormalImage( normalImage );
item->setExpandedImage( expandedImage );
// root level?
if(parentId == 0)
{
// insert back
if(mRoot)
{
Item * traverse = mRoot;
while(traverse->mNext)
traverse = traverse->mNext;
traverse->mNext = item;
item->mPrevious = traverse;
}
else
mRoot = item;
mFlags.set(RebuildVisible);
}
else
{
Item * parent = mItems[parentId-1];
// insert back
if(parent->mChild)
{
Item * traverse = parent->mChild;
while(traverse->mNext)
traverse = traverse->mNext;
traverse->mNext = item;
item->mPrevious = traverse;
}
else
parent->mChild = item;
item->mParent = parent;
if(parent->isExpanded())
mFlags.set(RebuildVisible);
}
//
if(mFlags.test(RebuildVisible))
buildVisibleTree();
return(item->mId);
}
//------------------------------------------------------------------------------
bool GuiTreeViewCtrl::removeItem(S32 itemId)
{
// tree?
if(itemId == 0)
{
destroyTree();
return(true);
}
Item * item = getItem(itemId);
if(!item)
{
//Con::errorf(ConsoleLogEntry::General, "GuiTreeViewCtrl::removeItem: invalid item id!");
return false;
}
// root?
if(item == mRoot)
mRoot = item->mNext;
// Dispose of any children...
if (item->mChild)
destroyChildren(item->mChild, item);
// Kill the item...
destroyItem(item);
// Update the rendered tree...
buildVisibleTree();
return true;
}
//------------------------------------------------------------------------------
const S32 GuiTreeViewCtrl::getFirstRootItem() const
{
return (mRoot ? mRoot->mId : 0);
}
//------------------------------------------------------------------------------
S32 GuiTreeViewCtrl::getChildItem(S32 itemId)
{
Item * item = getItem(itemId);
if(!item)
{
Con::errorf(ConsoleLogEntry::General, "GuiTreeViewCtrl::getChild: invalid item id!");
return(0);
}
return(item->mChild ? item->mChild->mId : 0);
}
S32 GuiTreeViewCtrl::getParentItem(S32 itemId)
{
Item * item = getItem(itemId);
if(!item)
{
Con::errorf(ConsoleLogEntry::General, "GuiTreeViewCtrl::getParent: invalid item id!");
return(0);
}
return(item->mParent ? item->mParent->mId : 0);
}
S32 GuiTreeViewCtrl::getNextSiblingItem(S32 itemId)
{
Item * item = getItem(itemId);
if(!item)
{
Con::errorf(ConsoleLogEntry::General, "GuiTreeViewCtrl::getNextSibling: invalid item id!");
return(0);
}
return(item->mNext ? item->mNext->mId : 0);
}
S32 GuiTreeViewCtrl::getPrevSiblingItem(S32 itemId)
{
Item * item = getItem(itemId);
if(!item)
{
Con::errorf(ConsoleLogEntry::General, "GuiTreeViewCtrl::getPrevSibling: invalid item id!");
return(0);
}
return(item->mPrevious ? item->mPrevious->mId : 0);
}
//------------------------------------------------------------------------------
S32 GuiTreeViewCtrl::getItemCount()
{
return(mItemCount);
}
S32 GuiTreeViewCtrl::getSelectedItem()
{
return mSelectedItem;
}
//------------------------------------------------------------------------------
void GuiTreeViewCtrl::moveItemUp( S32 itemId )
{
GuiTreeViewCtrl::Item* item = getItem( itemId );
if ( !item )
{
Con::errorf( ConsoleLogEntry::General, "GuiTreeViewCtrl::moveItemUp: invalid item id!");
return;
}
Item* prevItem = item->mPrevious;
if ( !prevItem )
{
Con::errorf( ConsoleLogEntry::General, "GuiTreeViewCtrl::moveItemUp: no previous sibling - how'd this get called?");
return;
}
// Diddle the linked list!
if ( prevItem->mPrevious )
prevItem->mPrevious->mNext = item;
else if ( item->mParent )
item->mParent->mChild = item;
if ( item->mNext )
item->mNext->mPrevious = prevItem;
item->mPrevious = prevItem->mPrevious;
prevItem->mNext = item->mNext;
item->mNext = prevItem;
prevItem->mPrevious = item;
// And update the simobjects if apppropriate...
SimObject * simobj = NULL;
if (item->isInspectorData())
simobj = item->getObject();
SimSet *parentSet = NULL;
// grab the current parentSet if there is any...
if(item->mParent->isInspectorData())
parentSet = dynamic_cast<SimSet*>(item->mParent->getObject());
else
{
// parent is probably script data so we search up the tree for a
// set to put our object in
Item * temp = item->mParent;
while (!temp->isInspectorData())
temp = temp->mParent;
// found an ancestor who is an inspectorData?
parentSet = temp->isInspectorData() ? dynamic_cast<SimSet*>(temp->getObject()) : NULL;
}
// Reorder the item and make sure that the children of the item get updated
// correctly prev item may be script... so find a prevItem if there is.
// We only need to reorder if there you move it above an inspector item.
if (simobj && parentSet)
{
Item * temp = item->mNext;
while(temp)
{
if (temp->isInspectorData())
break;
temp = temp->mNext;
}
if (temp)
parentSet->reOrder(item->getObject(), temp->getObject());
}
buildVisibleTree();
}
//------------------------------------------------------------------------------
bool GuiTreeViewCtrl::onWake()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -