scummvm/engines/wintermute/ui/ui_object.cpp
Einar Johan Trøan Sømåen 5683f07633 WINTERMUTE: Rename CamelCased filenames to prefixed_under_score-filenames
This is mostly a lead-up to namespacing the Ad/Base folders, and then
possibly removing the prefixes from the files, it also has the added
benefit of getting rid of the odd case-typos that makes for issues
on platforms that don't ignore case.
2012-07-21 19:15:33 +02:00

589 lines
17 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This file is based on WME Lite.
* http://dead-code.org/redir.php?target=wmelite
* Copyright (c) 2011 Jan Nedoma
*/
#include "engines/wintermute/base/base_game.h"
#include "engines/wintermute/base/base_sprite.h"
#include "engines/wintermute/ui/ui_object.h"
#include "engines/wintermute/ui/ui_tiled_image.h"
#include "engines/wintermute/ui/ui_window.h"
#include "engines/wintermute/platform_osystem.h"
#include "engines/wintermute/base/scriptables/script_value.h"
#include "engines/wintermute/base/scriptables/script_stack.h"
#include "engines/wintermute/base/font/base_font_storage.h"
namespace WinterMute {
IMPLEMENT_PERSISTENT(CUIObject, false)
//////////////////////////////////////////////////////////////////////////
CUIObject::CUIObject(CBGame *inGame): CBObject(inGame) {
_back = NULL;
_image = NULL;
_font = NULL;
_text = NULL;
_sharedFonts = _sharedImages = false;
_width = _height = 0;
_listenerObject = NULL;
_listenerParamObject = NULL;
_listenerParamDWORD = 0;
_disable = false;
_visible = true;
_type = UI_UNKNOWN;
_parent = NULL;
_parentNotify = false;
_focusedWidget = NULL;
_canFocus = false;
_nonIntMouseEvents = true;
}
//////////////////////////////////////////////////////////////////////////
CUIObject::~CUIObject() {
if (!_gameRef->_loadInProgress) CSysClassRegistry::getInstance()->enumInstances(CBGame::invalidateValues, "CScValue", (void *)this);
if (_back) delete _back;
if (_font && !_sharedFonts) _gameRef->_fontStorage->removeFont(_font);
if (_image && !_sharedImages) delete _image;
if (_text) delete [] _text;
_focusedWidget = NULL; // ref only
}
//////////////////////////////////////////////////////////////////////////
void CUIObject::setText(const char *text) {
if (_text) delete [] _text;
_text = new char [strlen(text) + 1];
if (_text) {
strcpy(_text, text);
for (int i = 0; i < strlen(_text); i++) {
if (_text[i] == '|') _text[i] = '\n';
}
}
}
//////////////////////////////////////////////////////////////////////////
bool CUIObject::display(int offsetX, int offsetY) {
return STATUS_OK;
}
//////////////////////////////////////////////////////////////////////////
void CUIObject::setListener(CBScriptHolder *object, CBScriptHolder *listenerObject, uint32 listenerParam) {
_listenerObject = object;
_listenerParamObject = listenerObject;
_listenerParamDWORD = listenerParam;
}
//////////////////////////////////////////////////////////////////////////
void CUIObject::correctSize() {
Rect32 rect;
if (_width <= 0) {
if (_image) {
_image->getBoundingRect(&rect, 0, 0);
_width = rect.right - rect.left;
} else _width = 100;
}
if (_height <= 0) {
if (_image) {
_image->getBoundingRect(&rect, 0, 0);
_height = rect.bottom - rect.top;
}
}
if (_back) _back->correctSize(&_width, &_height);
}
//////////////////////////////////////////////////////////////////////////
// high level scripting interface
//////////////////////////////////////////////////////////////////////////
bool CUIObject::scCallMethod(CScScript *script, CScStack *stack, CScStack *thisStack, const char *name) {
//////////////////////////////////////////////////////////////////////////
// SetFont
//////////////////////////////////////////////////////////////////////////
if (strcmp(name, "SetFont") == 0) {
stack->correctParams(1);
CScValue *Val = stack->pop();
if (_font) _gameRef->_fontStorage->removeFont(_font);
if (Val->isNULL()) {
_font = NULL;
stack->pushBool(true);
} else {
_font = _gameRef->_fontStorage->addFont(Val->getString());
stack->pushBool(_font != NULL);
}
return STATUS_OK;
}
//////////////////////////////////////////////////////////////////////////
// SetImage
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "SetImage") == 0) {
stack->correctParams(1);
CScValue *val = stack->pop();
/* const char *filename = */ val->getString();
delete _image;
_image = NULL;
if (val->isNULL()) {
stack->pushBool(true);
return STATUS_OK;
}
_image = new CBSprite(_gameRef);
if (!_image || DID_FAIL(_image->loadFile(val->getString()))) {
delete _image;
_image = NULL;
stack->pushBool(false);
} else stack->pushBool(true);
return STATUS_OK;
}
//////////////////////////////////////////////////////////////////////////
// GetImage
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "GetImage") == 0) {
stack->correctParams(0);
if (!_image || !_image->_filename) stack->pushNULL();
else stack->pushString(_image->_filename);
return STATUS_OK;
}
//////////////////////////////////////////////////////////////////////////
// GetImageObject
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "GetImageObject") == 0) {
stack->correctParams(0);
if (!_image) stack->pushNULL();
else stack->pushNative(_image, true);
return STATUS_OK;
}
//////////////////////////////////////////////////////////////////////////
// Focus
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "Focus") == 0) {
stack->correctParams(0);
focus();
stack->pushNULL();
return STATUS_OK;
}
//////////////////////////////////////////////////////////////////////////
// MoveAfter / MoveBefore
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "MoveAfter") == 0 || strcmp(name, "MoveBefore") == 0) {
stack->correctParams(1);
if (_parent && _parent->_type == UI_WINDOW) {
CUIWindow *win = (CUIWindow *)_parent;
int i;
bool found = false;
CScValue *val = stack->pop();
// find directly
if (val->isNative()) {
CUIObject *widget = (CUIObject *)val->getNative();
for (i = 0; i < win->_widgets.getSize(); i++) {
if (win->_widgets[i] == widget) {
found = true;
break;
}
}
}
// find by name
else {
const char *findName = val->getString();
for (i = 0; i < win->_widgets.getSize(); i++) {
if (scumm_stricmp(win->_widgets[i]->_name, findName) == 0) {
found = true;
break;
}
}
}
if (found) {
bool done = false;
for (int j = 0; j < win->_widgets.getSize(); j++) {
if (win->_widgets[j] == this) {
if (strcmp(name, "MoveAfter") == 0) i++;
if (j >= i) j++;
win->_widgets.insertAt(i, this);
win->_widgets.removeAt(j);
done = true;
stack->pushBool(true);
break;
}
}
if (!done) stack->pushBool(false);
} else stack->pushBool(false);
} else stack->pushBool(false);
return STATUS_OK;
}
//////////////////////////////////////////////////////////////////////////
// MoveToBottom
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "MoveToBottom") == 0) {
stack->correctParams(0);
if (_parent && _parent->_type == UI_WINDOW) {
CUIWindow *win = (CUIWindow *)_parent;
for (int i = 0; i < win->_widgets.getSize(); i++) {
if (win->_widgets[i] == this) {
win->_widgets.removeAt(i);
win->_widgets.insertAt(0, this);
break;
}
}
stack->pushBool(true);
} else stack->pushBool(false);
return STATUS_OK;
}
//////////////////////////////////////////////////////////////////////////
// MoveToTop
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "MoveToTop") == 0) {
stack->correctParams(0);
if (_parent && _parent->_type == UI_WINDOW) {
CUIWindow *win = (CUIWindow *)_parent;
for (int i = 0; i < win->_widgets.getSize(); i++) {
if (win->_widgets[i] == this) {
win->_widgets.removeAt(i);
win->_widgets.add(this);
break;
}
}
stack->pushBool(true);
} else stack->pushBool(false);
return STATUS_OK;
}
else return CBObject::scCallMethod(script, stack, thisStack, name);
}
//////////////////////////////////////////////////////////////////////////
CScValue *CUIObject::scGetProperty(const char *name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type
//////////////////////////////////////////////////////////////////////////
if (strcmp(name, "Type") == 0) {
_scValue->setString("ui_object");
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// Name
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "Name") == 0) {
_scValue->setString(_name);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// Parent (RO)
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "Parent") == 0) {
_scValue->setNative(_parent, true);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// ParentNotify
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "ParentNotify") == 0) {
_scValue->setBool(_parentNotify);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// Width
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "Width") == 0) {
_scValue->setInt(_width);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// Height
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "Height") == 0) {
_scValue->setInt(_height);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// Visible
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "Visible") == 0) {
_scValue->setBool(_visible);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// Disabled
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "Disabled") == 0) {
_scValue->setBool(_disable);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// Text
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "Text") == 0) {
_scValue->setString(_text);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// NextSibling (RO) / PrevSibling (RO)
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "NextSibling") == 0 || strcmp(name, "PrevSibling") == 0) {
_scValue->setNULL();
if (_parent && _parent->_type == UI_WINDOW) {
CUIWindow *win = (CUIWindow *)_parent;
for (int i = 0; i < win->_widgets.getSize(); i++) {
if (win->_widgets[i] == this) {
if (strcmp(name, "NextSibling") == 0) {
if (i < win->_widgets.getSize() - 1) _scValue->setNative(win->_widgets[i + 1], true);
} else {
if (i > 0) _scValue->setNative(win->_widgets[i - 1], true);
}
break;
}
}
}
return _scValue;
}
else return CBObject::scGetProperty(name);
}
//////////////////////////////////////////////////////////////////////////
bool CUIObject::scSetProperty(const char *name, CScValue *value) {
//////////////////////////////////////////////////////////////////////////
// Name
//////////////////////////////////////////////////////////////////////////
if (strcmp(name, "Name") == 0) {
setName(value->getString());
return STATUS_OK;
}
//////////////////////////////////////////////////////////////////////////
// ParentNotify
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "ParentNotify") == 0) {
_parentNotify = value->getBool();
return STATUS_OK;
}
//////////////////////////////////////////////////////////////////////////
// Width
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "Width") == 0) {
_width = value->getInt();
return STATUS_OK;
}
//////////////////////////////////////////////////////////////////////////
// Height
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "Height") == 0) {
_height = value->getInt();
return STATUS_OK;
}
//////////////////////////////////////////////////////////////////////////
// Visible
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "Visible") == 0) {
_visible = value->getBool();
return STATUS_OK;
}
//////////////////////////////////////////////////////////////////////////
// Disabled
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "Disabled") == 0) {
_disable = value->getBool();
return STATUS_OK;
}
//////////////////////////////////////////////////////////////////////////
// Text
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "Text") == 0) {
setText(value->getString());
return STATUS_OK;
}
else return CBObject::scSetProperty(name, value);
}
//////////////////////////////////////////////////////////////////////////
const char *CUIObject::scToString() {
return "[ui_object]";
}
//////////////////////////////////////////////////////////////////////////
bool CUIObject::isFocused() {
if (!_gameRef->_focusedWindow) return false;
if (_gameRef->_focusedWindow == this) return true;
CUIObject *obj = _gameRef->_focusedWindow;
while (obj) {
if (obj == this) return true;
else obj = obj->_focusedWidget;
}
return false;
}
//////////////////////////////////////////////////////////////////////////
bool CUIObject::handleMouse(TMouseEvent event, TMouseButton button) {
// handle focus change
if (event == MOUSE_CLICK && button == MOUSE_BUTTON_LEFT) {
focus();
}
return CBObject::handleMouse(event, button);
}
//////////////////////////////////////////////////////////////////////////
bool CUIObject::focus() {
CUIObject *obj = this;
bool disabled = false;
while (obj) {
if (obj->_disable && obj->_type == UI_WINDOW) {
disabled = true;
break;
}
obj = obj->_parent;
}
if (!disabled) {
obj = this;
while (obj) {
if (obj->_parent) {
if (!obj->_disable && obj->_canFocus) obj->_parent->_focusedWidget = obj;
} else {
if (obj->_type == UI_WINDOW) _gameRef->focusWindow((CUIWindow *)obj);
}
obj = obj->_parent;
}
}
return STATUS_OK;
}
//////////////////////////////////////////////////////////////////////////
bool CUIObject::getTotalOffset(int *offsetX, int *offsetY) {
int offX = 0, offY = 0;
CUIObject *obj = _parent;
while (obj) {
offX += obj->_posX;
offY += obj->_posY;
obj = obj->_parent;
}
if (offsetX) *offsetX = offX;
if (offsetY) *offsetY = offY;
return STATUS_OK;
}
//////////////////////////////////////////////////////////////////////////
bool CUIObject::persist(CBPersistMgr *persistMgr) {
CBObject::persist(persistMgr);
persistMgr->transfer(TMEMBER(_back));
persistMgr->transfer(TMEMBER(_canFocus));
persistMgr->transfer(TMEMBER(_disable));
persistMgr->transfer(TMEMBER(_focusedWidget));
persistMgr->transfer(TMEMBER(_font));
persistMgr->transfer(TMEMBER(_height));
persistMgr->transfer(TMEMBER(_image));
persistMgr->transfer(TMEMBER(_listenerObject));
persistMgr->transfer(TMEMBER(_listenerParamObject));
persistMgr->transfer(TMEMBER(_listenerParamDWORD));
persistMgr->transfer(TMEMBER(_parent));
persistMgr->transfer(TMEMBER(_parentNotify));
persistMgr->transfer(TMEMBER(_sharedFonts));
persistMgr->transfer(TMEMBER(_sharedImages));
persistMgr->transfer(TMEMBER(_text));
persistMgr->transfer(TMEMBER_INT(_type));
persistMgr->transfer(TMEMBER(_visible));
persistMgr->transfer(TMEMBER(_width));
return STATUS_OK;
}
//////////////////////////////////////////////////////////////////////////
bool CUIObject::saveAsText(CBDynBuffer *buffer, int indent) {
return STATUS_FAILED;
}
} // end of namespace WinterMute