Files
scummvm/engines/ultima/shared/core/tree_item.cpp
T

222 lines
5.2 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ultima/shared/core/tree_item.h"
#include "ultima/shared/core/named_item.h"
#include "ultima/shared/early/game.h"
#include "ultima/shared/early/game_base.h"
namespace Ultima {
namespace Shared {
EMPTY_MESSAGE_MAP(TreeItem, MessageTarget);
TreeItem::TreeItem() : _parent(nullptr), _firstChild(nullptr),
_nextSibling(nullptr), _priorSibling(nullptr),
_disposeAfterUse(DisposeAfterUse::NO) {
}
Game *TreeItem::getGame() {
TreeItem *treeItem = this;
while (treeItem->getParent()) {
treeItem = treeItem->getParent();
}
return dynamic_cast<Game *>(treeItem);
}
const Game *TreeItem::getGame() const {
const TreeItem *treeItem = this;
while (treeItem->getParent()) {
treeItem = treeItem->getParent();
}
return dynamic_cast<const Game *>(treeItem);
}
TreeItem *TreeItem::getLastSibling() {
TreeItem *item = this;
while (item->getNextSibling())
item = item->getNextSibling();
return item;
}
Gfx::VisualItem *TreeItem::getView() {
return getGame()->getView();
}
TreeItem *TreeItem::getLastChild() const {
if (!_firstChild)
return nullptr;
return _firstChild->getLastSibling();
}
TreeItem *TreeItem::scan(TreeItem *item) const {
if (_firstChild)
return _firstChild;
const TreeItem *treeItem = this;
while (treeItem != item) {
if (treeItem->_nextSibling)
return treeItem->_nextSibling;
treeItem = treeItem->_parent;
if (!treeItem)
break;
}
return nullptr;
}
TreeItem *TreeItem::findChildInstanceOf(const ClassDef &classDef) const {
for (TreeItem *treeItem = _firstChild; treeItem; treeItem = treeItem->getNextSibling()) {
if (treeItem->isInstanceOf(classDef))
return treeItem;
}
return nullptr;
}
TreeItem *TreeItem::findNextInstanceOf(const ClassDef &classDef, TreeItem *startItem) const {
TreeItem *treeItem = startItem ? startItem->getNextSibling() : getFirstChild();
for (; treeItem; treeItem = treeItem->getNextSibling()) {
if (treeItem->isInstanceOf(classDef))
return treeItem;
}
return nullptr;
}
void TreeItem::addUnder(TreeItem *newParent) {
if (newParent->_firstChild)
addSibling(newParent->_firstChild->getLastSibling());
else
setParent(newParent);
}
void TreeItem::addChild(TreeItem *child) {
child->addUnder(this);
}
void TreeItem::setParent(TreeItem *newParent) {
_parent = newParent;
_priorSibling = nullptr;
_nextSibling = newParent->_firstChild;
if (newParent->_firstChild)
newParent->_firstChild->_priorSibling = this;
newParent->_firstChild = this;
}
void TreeItem::addSibling(TreeItem *item) {
_priorSibling = item;
_nextSibling = item->_nextSibling;
_parent = item->_parent;
if (item->_nextSibling)
item->_nextSibling->_priorSibling = this;
item->_nextSibling = this;
}
void TreeItem::moveUnder(TreeItem *newParent) {
if (newParent) {
detach();
addUnder(newParent);
}
}
void TreeItem::destroyAll() {
destroyChildren();
detach();
if (_disposeAfterUse == DisposeAfterUse::YES)
delete this;
}
int TreeItem::destroyChildren() {
if (!_firstChild)
return 0;
TreeItem *item = _firstChild, *child, *nextSibling;
int total = 0;
do {
child = item->_firstChild;
nextSibling = item->_nextSibling;
if (child)
total += item->destroyChildren();
item->detach();
if (item->_disposeAfterUse == DisposeAfterUse::YES)
delete item;
++total;
} while ((item = nextSibling) != nullptr);
return total;
}
void TreeItem::detach() {
// Delink this item from any prior and/or next siblings
if (_priorSibling)
_priorSibling->_nextSibling = _nextSibling;
if (_nextSibling)
_nextSibling->_priorSibling = _priorSibling;
if (_parent && _parent->_firstChild == this)
_parent->_firstChild = _nextSibling;
_priorSibling = _nextSibling = _parent = nullptr;
}
void TreeItem::attach(TreeItem *item) {
_nextSibling = item;
_priorSibling = item->_priorSibling;
_parent = item->_parent;
if (item->_priorSibling)
item->_priorSibling->_nextSibling = this;
item->_priorSibling = this;
if (item->_parent && !item->_parent->_firstChild)
item->_parent->_firstChild = this;
}
NamedItem *TreeItem::findByName(const Common::String &name) {
Common::String nameLower = name;
nameLower.toLowercase();
for (TreeItem *treeItem = this; treeItem; treeItem = treeItem->scan(this)) {
Common::String itemName = treeItem->getName();
itemName.toLowercase();
if (!itemName.compareTo(nameLower))
return dynamic_cast<NamedItem *>(treeItem);
}
return nullptr;
}
} // End of namespace Shared
} // End of namespace Ultima