aboutsummaryrefslogtreecommitdiff
path: root/engines/bladerunner/ui/ui_scroll_box.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/bladerunner/ui/ui_scroll_box.cpp')
-rw-r--r--engines/bladerunner/ui/ui_scroll_box.cpp662
1 files changed, 662 insertions, 0 deletions
diff --git a/engines/bladerunner/ui/ui_scroll_box.cpp b/engines/bladerunner/ui/ui_scroll_box.cpp
new file mode 100644
index 0000000000..a0d53a444d
--- /dev/null
+++ b/engines/bladerunner/ui/ui_scroll_box.cpp
@@ -0,0 +1,662 @@
+/* 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.
+ *
+ */
+
+#include "bladerunner/ui/ui_scroll_box.h"
+
+#include "bladerunner/audio_player.h"
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/font.h"
+#include "bladerunner/game_info.h"
+#include "bladerunner/shape.h"
+#include "bladerunner/ui/kia.h"
+#include "bladerunner/ui/kia_shapes.h"
+
+namespace BladeRunner {
+
+const int UIScrollBox::k3DFrameColors[] = { 0x1083, 0x14A5, 0x14A6, 0x2508, 0x5230, 0x5230, 0x0000, 0x0000 };
+const int UIScrollBox::kTextBackgroundColors[] = { 0x14EA, 0x190C, 0x1D2E, 0x2570, 0x4F1F, 0x0000 };
+const int UIScrollBox::kTextColors1[] = { 0x25B3, 0x31F7, 0x3A5B, 0x46BF, 0x4F1F };
+const int UIScrollBox::kTextColors2[] = { 0x677F, 0x6F9F, 0x73BF, 0x77DF, 0x7FFF };
+const int UIScrollBox::kTextColors3[] = { 0x7BB8, 0x7BBA, 0x7BDB, 0x7FDD, 0x7FFF };
+const int UIScrollBox::kTextColors4[] = { 0x4DC7, 0x5E4B, 0x6EEE, 0x7751, 0x7F92 };
+
+UIScrollBox::UIScrollBox(BladeRunnerEngine *vm, UIScrollBoxCallback *lineSelectedCallback, void *callbackData, int maxLineCount, int style, bool center, Common::Rect rect, Common::Rect scrollBarRect) : UIComponent(vm) {
+ _selectedLineState = 0;
+ _scrollUpButtonState = 0;
+ _scrollDownButtonState = 0;
+ _scrollAreaUpState = 0;
+ _scrollAreaDownState = 0;
+ _scrollBarState = 0;
+
+ _scrollUpButtonHover = false;
+ _scrollDownButtonHover = false;
+ _scrollAreaUpHover = false;
+ _scrollAreaDownHover = false;
+ _scrollBarHover = false;
+
+ _hoveredLine = -1;
+ _selectedLineIndex = -1;
+
+ _lineSelectedCallback = lineSelectedCallback;
+ _callbackData = callbackData;
+
+ _isVisible = false;
+ _style = style;
+ _center = center;
+ _timeLastScroll = _vm->getTotalPlayTime();
+ _timeLastCheckbox = _vm->getTotalPlayTime();
+ _timeLastHighlight = _vm->getTotalPlayTime();
+
+ _highlightFrame = 0;
+
+ _rect = rect;
+ _scrollBarRect = scrollBarRect;
+
+ _lineCount = 0;
+ _maxLineCount = maxLineCount;
+
+ _firstLineVisible = 0;
+
+ _maxLinesVisible = _rect.height() / kLineHeight;
+ _rect.bottom = _rect.top + kLineHeight * _maxLinesVisible - 1;
+
+ _lines.resize(_maxLineCount);
+ for (int i = 0; i < _maxLineCount; ++i) {
+ _lines[i] = new Line();
+ _lines[i]->lineData = -1;
+ _lines[i]->flags = 0x00;
+ _lines[i]->checkboxFrame = 5;
+ }
+}
+
+UIScrollBox::~UIScrollBox() {
+ for (int i = 0; i < _maxLineCount; ++i) {
+ delete _lines[i];
+ }
+}
+
+void UIScrollBox::show() {
+ _selectedLineState = 0;
+ _scrollUpButtonState = 0;
+ _scrollDownButtonState = 0;
+ _scrollAreaUpState = 0;
+ _scrollAreaDownState = 0;
+ _scrollBarState = 0;
+
+ _hoveredLine = -1;
+ _selectedLineIndex = -1;
+
+ _scrollUpButtonHover = false;
+ _scrollDownButtonHover = false;
+ _scrollAreaUpHover = false;
+ _scrollAreaDownHover = false;
+ _scrollBarHover = false;
+
+ _timeLastScroll = _vm->getTotalPlayTime();
+ _timeLastCheckbox = _vm->getTotalPlayTime();
+ _timeLastHighlight = _vm->getTotalPlayTime();
+
+ _highlightFrame = 0;
+ _isVisible = true;
+}
+
+void UIScrollBox::hide() {
+ _isVisible = false;
+}
+
+void UIScrollBox::clearLines(){
+ _lineCount = 0;
+ _firstLineVisible = 0;
+
+}
+
+void UIScrollBox::addLine(const Common::String &text, int lineData, int flags) {
+ _lines[_lineCount]->text = text;
+ _lines[_lineCount]->lineData = lineData;
+ _lines[_lineCount]->flags = flags;
+
+ ++_lineCount;
+}
+
+void UIScrollBox::addLine(const char *text, int lineData, int flags) {
+ _lines[_lineCount]->text = text;
+ _lines[_lineCount]->lineData = lineData;
+ _lines[_lineCount]->flags = flags;
+
+ ++_lineCount;
+}
+
+void UIScrollBox::sortLines() {
+ qsort(_lines.data(), _lineCount, sizeof(Line *), &sortFunction);
+}
+
+void UIScrollBox::handleMouseMove(int mouseX, int mouseY) {
+ if (!_isVisible) {
+ return;
+ }
+
+ if (_rect.contains(mouseX, mouseY)) {
+ int newHoveredLine = (mouseY - _rect.top) / 10 + _firstLineVisible;
+ if (newHoveredLine >= _lineCount) {
+ newHoveredLine = -1;
+ }
+
+ if (newHoveredLine != _hoveredLine && newHoveredLine >= 0 && newHoveredLine < _lineCount) {
+ if (_lines[newHoveredLine]->lineData >= 0 && _selectedLineState == 0) {
+ int soundId = 507;
+ if (_lines[newHoveredLine]->flags & 0x01 ) {
+ soundId = 508;
+ }
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(soundId), 100, 0, 0, 50, 0);
+ }
+ }
+ _hoveredLine = newHoveredLine;
+ } else {
+ _hoveredLine = -1;
+ }
+
+ _scrollUpButtonHover =
+ (mouseX >= _scrollBarRect.left)
+ && (mouseX < _scrollBarRect.left + 15)
+ && (mouseY >= _scrollBarRect.top)
+ && (mouseY < _scrollBarRect.top + 8);
+
+ _scrollDownButtonHover =
+ (mouseX >= _scrollBarRect.left)
+ && (mouseX < _scrollBarRect.left + 15)
+ && (mouseY > _scrollBarRect.bottom - 8)
+ && (mouseY <= _scrollBarRect.bottom);
+
+ int scrollAreaHeight = _scrollBarRect.bottom - _scrollBarRect.top - 15;
+
+ int scrollBarHeight = scrollAreaHeight;
+ if (_lineCount > _maxLinesVisible) {
+ scrollBarHeight = _maxLinesVisible * scrollAreaHeight / _lineCount;
+ }
+ if (scrollBarHeight < 16) {
+ scrollBarHeight = 16;
+ }
+
+ int scrollAreaEmptySize = scrollAreaHeight - scrollBarHeight;
+
+ int scrollBarY = 0;
+ if (_lineCount > _maxLinesVisible) {
+ scrollBarY = scrollAreaEmptySize * _firstLineVisible / (_lineCount - _maxLinesVisible);
+ }
+
+ if (_scrollBarState == 2) {
+ int v12 = scrollBarHeight / 2 + 8;
+ if (mouseY - _scrollBarRect.top > v12 && _lineCount > _maxLinesVisible && scrollAreaEmptySize > 0) {
+ _firstLineVisible = (_lineCount - _maxLinesVisible) * (mouseY - _scrollBarRect.top - v12) / scrollAreaEmptySize;
+ if (_firstLineVisible > _lineCount - _maxLinesVisible) {
+ _firstLineVisible = _lineCount - _maxLinesVisible;
+ }
+ } else {
+ _firstLineVisible = 0;
+ }
+
+ if (_lineCount <= _maxLinesVisible) {
+ scrollBarY = 0;
+ } else {
+ scrollBarY = scrollAreaEmptySize * _firstLineVisible/ (_lineCount - _maxLinesVisible);
+ }
+ }
+ scrollBarY = scrollBarY + _scrollBarRect.top + 8;
+
+ _scrollBarHover =
+ (mouseX >= _scrollBarRect.left)
+ && (mouseX < _scrollBarRect.left + 15)
+ && (mouseY >= scrollBarY)
+ && (mouseY < scrollBarY + scrollBarHeight);
+
+ _scrollAreaUpHover =
+ (mouseX >= _scrollBarRect.left)
+ && (mouseX < _scrollBarRect.left + 15)
+ && (mouseY >= _scrollBarRect.top + 8)
+ && (mouseY < scrollBarY);
+
+ _scrollAreaDownHover =
+ (mouseX >= _scrollBarRect.left)
+ && (mouseX < _scrollBarRect.left + 15)
+ && (mouseY >= scrollBarY + scrollBarHeight)
+ && (mouseY < _scrollBarRect.bottom - 8);
+}
+
+void UIScrollBox::handleMouseDown(bool alternateButton) {
+ if (!_isVisible) {
+ return;
+ }
+
+ _mouseButton = alternateButton;
+ if (_hoveredLine == -1) {
+ _selectedLineState = 1;
+ } else if (_selectedLineIndex == -1) {
+ _selectedLineIndex = _hoveredLine;
+ _selectedLineState = 2;
+ if (_hoveredLine < _lineCount) {
+ if (_lineSelectedCallback) {
+ _lineSelectedCallback(_callbackData, this, _lines[_selectedLineIndex]->lineData, _mouseButton);
+ }
+
+ if (_lines[_selectedLineIndex]->flags & 0x01) {
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(509), 100, 0, 0, 50, 0);
+ }
+ }
+ }
+ if (!alternateButton) {
+ if (_scrollUpButtonHover) {
+ _scrollUpButtonState = 2;
+ _timeLastScroll = _vm->getTotalPlayTime() - 160;
+ } else {
+ _scrollUpButtonState = 1;
+ }
+ if (_scrollDownButtonHover) {
+ _scrollDownButtonState = 2;
+ } else {
+ _scrollDownButtonState = 1;
+ }
+ if (_scrollBarHover) {
+ _scrollBarState = 2;
+ } else {
+ _scrollBarState = 1;
+ }
+ if (_scrollAreaUpHover) {
+ _scrollAreaUpState = 2;
+ _timeLastScroll = _vm->getTotalPlayTime() - 160;
+ } else {
+ _scrollAreaUpState = 1;
+ }
+ if (_scrollAreaDownHover) {
+ _scrollAreaDownState = 2;
+ _timeLastScroll = _vm->getTotalPlayTime() - 160;
+ } else {
+ _scrollAreaDownState = 1;
+ }
+ }
+}
+
+void UIScrollBox::handleMouseUp(bool alternateButton) {
+ if (_isVisible) {
+ if ( alternateButton == _mouseButton) {
+ _selectedLineState = 0;
+ _selectedLineIndex = -1;
+ }
+
+ if (!alternateButton) {
+ _scrollUpButtonState = 0;
+ _scrollDownButtonState = 0;
+ _scrollAreaUpState = 0;
+ _scrollAreaDownState = 0;
+ _scrollBarState = 0;
+ }
+ }
+}
+
+int UIScrollBox::getSelectedLineData() {
+ if (_hoveredLine >= 0 && _selectedLineState != 1 && _hoveredLine < _lineCount) {
+ return _lines[_hoveredLine]->lineData;
+ }
+ return -1;
+}
+
+void UIScrollBox::draw(Graphics::Surface &surface) {
+ int timeNow = _vm->getTotalPlayTime();
+
+ // update scrolling
+ if (_scrollUpButtonState == 2 && _scrollUpButtonHover) {
+ if ((timeNow - _timeLastScroll) > 160) {
+ scrollUp();
+ _timeLastScroll = timeNow;
+ }
+ } else if (_scrollDownButtonState == 2 && _scrollDownButtonHover) {
+ if ((timeNow - _timeLastScroll) > 160) {
+ scrollDown();
+ _timeLastScroll = timeNow;
+ }
+ } else if (_scrollAreaUpState == 2 && _scrollAreaUpHover) {
+ if ((timeNow - _timeLastScroll) > 160) {
+ _firstLineVisible -= _maxLinesVisible - 1;
+ _firstLineVisible = CLIP(_firstLineVisible, 0, _lineCount - _maxLinesVisible);
+ _timeLastScroll = timeNow;
+ }
+ } else if (_scrollAreaDownState == 2 && _scrollAreaDownHover) {
+ if ((timeNow - _timeLastScroll) > 160) {
+ _firstLineVisible += _maxLinesVisible - 1;
+ _firstLineVisible = CLIP(_firstLineVisible, 0, _lineCount - _maxLinesVisible);
+ _timeLastScroll = timeNow;
+ }
+ }
+
+ // update checkboxes
+ int timeDiffCheckBox = timeNow - _timeLastCheckbox;
+ if (timeDiffCheckBox > 67) {
+ _timeLastCheckbox = timeNow;
+ for (int i = 0; i < _lineCount; ++i) {
+ if (_lines[i]->flags & 0x01) { // has checkbox
+ if (_lines[i]->flags & 0x02) { // checkbox checked
+ if (_lines[i]->checkboxFrame < 5) {
+ _lines[i]->checkboxFrame += timeDiffCheckBox / 67;
+ }
+ if (_lines[i]->checkboxFrame > 5) {
+ _lines[i]->checkboxFrame = 5;
+ }
+ } else { // checkbox not checked
+ if (_lines[i]->checkboxFrame > 0) {
+ _lines[i]->checkboxFrame -= timeDiffCheckBox / 67;
+ }
+ if (_lines[i]->checkboxFrame < 0) {
+ _lines[i]->checkboxFrame = 0;
+ }
+ }
+ }
+ }
+ }
+
+
+ // update highlight
+ if ((timeNow - _timeLastHighlight) > 67) {
+ _timeLastHighlight = timeNow;
+ _highlightFrame = (_highlightFrame + 1) % 8;
+ }
+
+ // draw text lines
+ int linesVisible = 0;
+ int lastLineVisible = 0;
+
+ if (_maxLinesVisible < _lineCount - _firstLineVisible) {
+ linesVisible = _maxLinesVisible;
+ lastLineVisible = _firstLineVisible + _maxLinesVisible;
+ } else {
+ linesVisible = _lineCount - _firstLineVisible;
+ lastLineVisible = _lineCount;
+ }
+
+ if (_firstLineVisible < lastLineVisible) {
+ int y = _rect.top;
+ int y1 = _rect.top + 8;
+ int y2 = _rect.top + 2;
+ int i = _firstLineVisible;
+ do {
+ int startingColorIndex = 3;
+ if (i - _firstLineVisible < 3) {
+ startingColorIndex = i - _firstLineVisible;
+ }
+
+ int endingColorIndex = 3;
+ if (i - _firstLineVisible >= linesVisible - 3) {
+ endingColorIndex = linesVisible - (i - _firstLineVisible + 1);
+ }
+
+ int colorIndex = endingColorIndex;
+ if (startingColorIndex < endingColorIndex) {
+ colorIndex = startingColorIndex;
+ }
+
+ bool v35 = false;
+ int color = 0;
+
+ if ((((_selectedLineState == 0 && i == _hoveredLine) || (_selectedLineState == 2 && i == _selectedLineIndex && _selectedLineIndex == _hoveredLine)) && _lines[i]->lineData != -1) || _lines[i]->flags & 0x04) {
+ v35 = true;
+ if (_style) {
+ color = kTextColors2[colorIndex];
+ } else {
+ color = kTextColors3[colorIndex];
+ }
+ }
+ else {
+ if (_style) {
+ color = kTextColors1[colorIndex];
+ } else {
+ color = kTextColors4[colorIndex];
+ }
+ }
+
+ int x = _rect.left;
+
+ if (_lines[i]->flags & 0x01) { // has checkbox
+ int checkboxShapeId = 0;
+ if (_style == 0) {
+ if (_lines[i]->checkboxFrame || v35) {
+ if (_lines[i]->checkboxFrame != 5 || v35) {
+ checkboxShapeId = _lines[i]->checkboxFrame + 62;
+ } else {
+ checkboxShapeId = 61;
+ }
+ } else {
+ checkboxShapeId = 60;
+ }
+ } else if (_lines[i]->checkboxFrame || v35) {
+ if (_lines[i]->checkboxFrame != 5 || v35) {
+ checkboxShapeId = _lines[i]->checkboxFrame + 54;
+ } else {
+ checkboxShapeId = 53;
+ }
+ } else {
+ checkboxShapeId = 52;
+ }
+ _vm->_kia->_shapes->get(checkboxShapeId)->draw(surface, x - 1, y);
+ x += 11;
+ }
+
+ if (_lines[i]->flags & 0x10) { // highlighted line
+ if (_lines[i]->flags & 0x20) {
+ int highlightShapeId = _highlightFrame;
+ if (highlightShapeId > 4) {
+ highlightShapeId = 8 - highlightShapeId;
+ }
+ _vm->_kia->_shapes->get(highlightShapeId + 85)->draw(surface, x, y2);
+ }
+ x += 6;
+ }
+
+ if (_lines[i]->flags & 0x08) { // has background rectangle
+ int colorBackground = 0;
+ if (_style) {
+ colorBackground = kTextBackgroundColors[colorIndex];
+ } else {
+ colorBackground = 0x28E4;
+ }
+ surface.fillRect(Common::Rect(x, y, _rect.right + 1, y1 + 1), colorBackground);
+ }
+
+ if (_center) {
+ x = (_rect.width() - _vm->_mainFont->getTextWidth(_lines[i]->text)) / 2;
+ }
+
+ _vm->_mainFont->drawColor(_lines[i]->text, surface, x, y, color);
+
+ y1 += kLineHeight;
+ y2 += kLineHeight;
+ y += kLineHeight;
+ ++i;
+ }
+ while (i < lastLineVisible);
+ }
+
+ // draw scroll up button
+ int scrollUpButtonShapeId = 0;
+ if (_scrollUpButtonState) {
+ if (_scrollUpButtonState == 2) {
+ if (_scrollUpButtonHover) {
+ scrollUpButtonShapeId = 72;
+ } else {
+ scrollUpButtonShapeId = 71;
+ }
+ } else {
+ scrollUpButtonShapeId = 70;
+ }
+ } else if (_scrollUpButtonHover) {
+ scrollUpButtonShapeId = 71;
+ } else {
+ scrollUpButtonShapeId = 70;
+ }
+ _vm->_kia->_shapes->get(scrollUpButtonShapeId)->draw(surface, _scrollBarRect.left, _scrollBarRect.top);
+
+ // draw scroll down button
+ int scrollDownButtonShapeId = 0;
+ if (_scrollDownButtonState) {
+ if (_scrollDownButtonState == 2) {
+ if (_scrollDownButtonHover) {
+ scrollDownButtonShapeId = 75;
+ } else {
+ scrollDownButtonShapeId = 74;
+ }
+ } else {
+ scrollDownButtonShapeId = 73;
+ }
+ } else if (_scrollDownButtonHover) {
+ scrollDownButtonShapeId = 74;
+ } else {
+ scrollDownButtonShapeId = 73;
+ }
+ _vm->_kia->_shapes->get(scrollDownButtonShapeId)->draw(surface, _scrollBarRect.left, _scrollBarRect.bottom - 7);
+
+ int scrollAreaSize = _scrollBarRect.bottom - (_scrollBarRect.top + 15);
+ int scrollBarHeight = 0;
+ if (_lineCount <= _maxLinesVisible) {
+ scrollBarHeight = _scrollBarRect.bottom - (_scrollBarRect.top + 15);
+ } else {
+ scrollBarHeight = _maxLinesVisible * scrollAreaSize / _lineCount;
+ }
+ scrollBarHeight = MAX(scrollBarHeight, 16);
+
+ int v56 = 0;
+ if (_lineCount <= _maxLinesVisible) {
+ v56 = 0;
+ } else {
+ v56 = _firstLineVisible * (scrollAreaSize - scrollBarHeight) / (_lineCount - _maxLinesVisible);
+ }
+
+ int v58 = v56 + _scrollBarRect.top + 8;
+
+ if (_scrollBarState == 2) {
+ draw3DFrame(surface, Common::Rect(_scrollBarRect.left, v58, _scrollBarRect.left + 15, v58 + scrollBarHeight), 1, 1);
+ } else if (!_scrollBarState && _scrollBarHover) {
+ draw3DFrame(surface, Common::Rect(_scrollBarRect.left, v56 + _scrollBarRect.top + 8, _scrollBarRect.left + 15, v58 + scrollBarHeight), 0, 1);
+ } else {
+ draw3DFrame(surface, Common::Rect(_scrollBarRect.left, v58, _scrollBarRect.left + 15, v58 + scrollBarHeight), 0, 0);
+ }
+}
+
+void UIScrollBox::checkAll() {
+ for (int i = 0; i < _lineCount; ++i) {
+ if (_lines[i]->flags & 0x01) {
+ _lines[i]->flags |= 0x02;
+ }
+ }
+}
+
+void UIScrollBox::uncheckAll() {
+ for (int i = 0; i < _lineCount; ++i) {
+ if (_lines[i]->flags & 0x01) {
+ _lines[i]->flags &= ~0x02;
+ }
+ }
+}
+
+void UIScrollBox::toggleCheckBox(int lineData) {
+ int i = findLine(lineData);
+ if (i != -1) {
+ if (_lines[i]->flags & 0x02) {
+ _lines[i]->flags &= ~0x02;
+ } else {
+ _lines[i]->flags |= 0x02;
+ }
+ }
+}
+
+bool UIScrollBox::hasLine(int lineData) {
+ return findLine(lineData) != -1;
+}
+
+void UIScrollBox::resetHighlight(int lineData) {
+ int i = findLine(lineData);
+ if (i != -1) {
+ _lines[i]->flags &= ~0x20;
+ }
+}
+
+void UIScrollBox::setFlags(int lineData, int flags) {
+ int i = findLine(lineData);
+ if (i != -1) {
+ _lines[i]->flags |= flags;
+ }
+}
+
+void UIScrollBox::resetFlags(int lineData, int flags) {
+ int i = findLine(lineData);
+ if (i != -1) {
+ _lines[i]->flags &= ~flags;
+ }
+}
+
+int UIScrollBox::sortFunction(const void *item1, const void *item2) {
+ Line *line1 = *(Line * const *)item1;
+ Line *line2 = *(Line * const *)item2;
+ return line1->text.compareToIgnoreCase(line2->text);
+}
+
+void UIScrollBox::draw3DFrame(Graphics::Surface &surface, Common::Rect rect, bool pressed, int style) {
+ int color1, color2;
+
+ if (pressed) {
+ color1 = k3DFrameColors[style + 6];
+ color2 = k3DFrameColors[style + 4];
+ } else {
+ color1 = k3DFrameColors[style + 4];
+ color2 = k3DFrameColors[style + 6];
+ }
+
+ int fillColor = k3DFrameColors[style + 2];
+
+ surface.fillRect(Common::Rect(rect.left + 1, rect.top + 1, rect.right - 1, rect.bottom - 1), fillColor);
+
+ surface.hLine(rect.left + 1, rect.top, rect.right - 2, color1);
+ surface.hLine(rect.left + 1, rect.bottom - 1, rect.right - 2, color2);
+ surface.vLine(rect.left, rect.top, rect.bottom - 2, color1);
+ surface.vLine(rect.right - 1, rect.top + 1, rect.bottom - 1, color2);
+ surface.hLine(rect.right - 1, rect.top, rect.right - 1, k3DFrameColors[style]);
+ surface.hLine(rect.left, rect.bottom - 1, rect.left, k3DFrameColors[style]);
+}
+
+void UIScrollBox::scrollUp() {
+ if (_firstLineVisible > 0) {
+ --_firstLineVisible;
+ }
+}
+
+void UIScrollBox::scrollDown() {
+ if (_lineCount - _firstLineVisible > _maxLinesVisible) {
+ ++_firstLineVisible;
+ }
+}
+
+int UIScrollBox::findLine(int lineData) {
+ for (int i = 0; i < _lineCount; ++i) {
+ if (_lines[i]->lineData == lineData) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+} // End of namespace BladeRunner