diff options
Diffstat (limited to 'engines/sci/graphics/gui_controls.cpp')
-rw-r--r-- | engines/sci/graphics/gui_controls.cpp | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/engines/sci/graphics/gui_controls.cpp b/engines/sci/graphics/gui_controls.cpp new file mode 100644 index 0000000000..073819a654 --- /dev/null +++ b/engines/sci/graphics/gui_controls.cpp @@ -0,0 +1,231 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "common/util.h" +#include "common/stack.h" +#include "graphics/primitives.h" + +#include "sci/sci.h" +#include "sci/event.h" +#include "sci/engine/state.h" +#include "sci/graphics/gui_gfx.h" +#include "sci/graphics/gui_font.h" +#include "sci/graphics/gui_text.h" +#include "sci/graphics/gui_controls.h" + +namespace Sci { + +SciGuiControls::SciGuiControls(SegManager *segMan, SciGuiGfx *gfx, SciGuiText *text) + : _segMan(segMan), _gfx(gfx), _text(text) { + init(); +} + +SciGuiControls::~SciGuiControls() { +} + +void SciGuiControls::init() { + _texteditCursorVisible = false; +} + +const char controlListUpArrow[2] = { 0x18, 0 }; +const char controlListDownArrow[2] = { 0x19, 0 }; + +void SciGuiControls::drawListControl(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const char **entries, GuiResourceId fontId, int16 upperPos, int16 cursorPos, bool isAlias) { + Common::Rect workerRect = rect; + GuiResourceId oldFontId = _text->GetFontId(); + int16 oldPenColor = _gfx->_curPort->penClr; + uint16 fontSize = 0; + int16 i; + const char *listEntry; + int16 listEntryLen; + int16 lastYpos; + + // draw basic window + _gfx->EraseRect(workerRect); + workerRect.grow(1); + _gfx->FrameRect(workerRect); + + // draw UP/DOWN arrows + // we draw UP arrow one pixel lower than sierra did, because it looks nicer. Also the DOWN arrow has one pixel + // line inbetween as well + workerRect.top++; + _text->Box(controlListUpArrow, 0, workerRect, SCI_TEXT_ALIGNMENT_CENTER, 0); + workerRect.top = workerRect.bottom - 10; + _text->Box(controlListDownArrow, 0, workerRect, SCI_TEXT_ALIGNMENT_CENTER, 0); + + // Draw inner lines + workerRect.top = rect.top + 9; + workerRect.bottom -= 10; + _gfx->FrameRect(workerRect); + workerRect.grow(-1); + + _text->SetFont(fontId); + fontSize = _gfx->_curPort->fontHeight; + _gfx->PenColor(_gfx->_curPort->penClr); _gfx->BackColor(_gfx->_curPort->backClr); + workerRect.bottom = workerRect.top + 9; + lastYpos = rect.bottom - fontSize; + + // Write actual text + for (i = upperPos; i < count; i++) { + _gfx->EraseRect(workerRect); + listEntry = entries[i]; + if (listEntry[0]) { + _gfx->MoveTo(workerRect.left, workerRect.top); + listEntryLen = strlen(listEntry); + _text->Draw(listEntry, 0, MIN(maxChars, listEntryLen), oldFontId, oldPenColor); + if ((!isAlias) && (i == cursorPos)) { + _gfx->InvertRect(workerRect); + } + } + workerRect.translate(0, fontSize); + if (workerRect.bottom > lastYpos) + break; + } + + _text->SetFont(oldFontId); +} + +void SciGuiControls::TexteditCursorDraw(Common::Rect rect, const char *text, uint16 curPos) { + int16 textWidth, i; + if (!_texteditCursorVisible) { + textWidth = 0; + for (i = 0; i < curPos; i++) { + textWidth += _text->_font->getCharWidth(text[i]); + } + _texteditCursorRect.left = rect.left + textWidth; + _texteditCursorRect.top = rect.top; + _texteditCursorRect.bottom = _texteditCursorRect.top + _text->_font->getHeight(); + _texteditCursorRect.right = _texteditCursorRect.left + (text[curPos] == 0 ? 1 : _text->_font->getCharWidth(text[curPos])); + _gfx->InvertRect(_texteditCursorRect); + _gfx->BitsShow(_texteditCursorRect); + _texteditCursorVisible = true; + TexteditSetBlinkTime(); + } +} + +void SciGuiControls::TexteditCursorErase() { + if (_texteditCursorVisible) { + _gfx->InvertRect(_texteditCursorRect); + _gfx->BitsShow(_texteditCursorRect); + _texteditCursorVisible = false; + } + TexteditSetBlinkTime(); +} + +void SciGuiControls::TexteditSetBlinkTime() { + _texteditBlinkTime = g_system->getMillis() + (30 * 1000 / 60); +} + +void SciGuiControls::TexteditChange(reg_t controlObject, reg_t eventObject) { + uint16 cursorPos = GET_SEL32V(_segMan, controlObject, cursor); + uint16 maxChars = GET_SEL32V(_segMan, controlObject, max); + reg_t textReference = GET_SEL32(_segMan, controlObject, text); + Common::String text; + uint16 textSize, eventType, eventKey; + bool textChanged = false; + Common::Rect rect; + + if (textReference.isNull()) + error("kEditControl called on object that doesnt have a text reference"); + text = _segMan->getString(textReference); + + if (!eventObject.isNull()) { + textSize = text.size(); + eventType = GET_SEL32V(_segMan, eventObject, type); + + switch (eventType) { + case SCI_EVENT_MOUSE_PRESS: + // TODO: Implement mouse support for cursor change + break; + case SCI_EVENT_KEYBOARD: + eventKey = GET_SEL32V(_segMan, eventObject, message); + switch (eventKey) { + case SCI_KEY_BACKSPACE: + if (cursorPos > 0) { + cursorPos--; text.deleteChar(cursorPos); + textChanged = true; + } + break; + case SCI_KEY_DELETE: + text.deleteChar(cursorPos); + textChanged = true; + break; + case SCI_KEY_HOME: // HOME + cursorPos = 0; textChanged = true; + break; + case SCI_KEY_END: // END + cursorPos = textSize; textChanged = true; + break; + case SCI_KEY_LEFT: // LEFT + if (cursorPos > 0) { + cursorPos--; textChanged = true; + } + break; + case SCI_KEY_RIGHT: // RIGHT + if (cursorPos + 1 <= textSize) { + cursorPos++; textChanged = true; + } + break; + default: + if (eventKey > 31 && eventKey < 256 && textSize < maxChars) { + // insert pressed character + // we check, if there is space left for this character + + text.insertChar(eventKey, cursorPos++); + textChanged = true; + } + break; + } + break; + } + } + + if (textChanged) { + GuiResourceId oldFontId = _text->GetFontId(); + GuiResourceId fontId = GET_SEL32V(_segMan, controlObject, font); + rect = Common::Rect(GET_SEL32V(_segMan, controlObject, nsLeft), GET_SEL32V(_segMan, controlObject, nsTop), + GET_SEL32V(_segMan, controlObject, nsRight), GET_SEL32V(_segMan, controlObject, nsBottom)); + TexteditCursorErase(); + _gfx->EraseRect(rect); + _text->Box(text.c_str(), 0, rect, SCI_TEXT_ALIGNMENT_LEFT, fontId); + _gfx->BitsShow(rect); + _text->SetFont(fontId); + TexteditCursorDraw(rect, text.c_str(), cursorPos); + _text->SetFont(oldFontId); + // Write back string + _segMan->strcpy(textReference, text.c_str()); + } else { + if (g_system->getMillis() >= _texteditBlinkTime) { + _gfx->InvertRect(_texteditCursorRect); + _gfx->BitsShow(_texteditCursorRect); + _texteditCursorVisible = !_texteditCursorVisible; + TexteditSetBlinkTime(); + } + } + + PUT_SEL32V(_segMan, controlObject, cursor, cursorPos); +} + +} // End of namespace Sci |