mirror of
https://github.com/scummvm/scummvm.git
synced 2026-06-20 05:45:29 +00:00
222 lines
5.2 KiB
C++
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
|