aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.common3
-rw-r--r--gui.cpp3
-rw-r--r--gui/ListWidget.cpp129
-rw-r--r--gui/ListWidget.h25
-rw-r--r--gui/ScrollBarWidget.cpp157
-rw-r--r--gui/ScrollBarWidget.h65
-rw-r--r--gui/dialog.cpp16
-rw-r--r--gui/dialog.h11
-rw-r--r--gui/util.cpp246
-rw-r--r--gui/util.h83
-rw-r--r--gui/widget.cpp53
-rw-r--r--gui/widget.h56
-rw-r--r--newgui.cpp72
-rw-r--r--newgui.h1
14 files changed, 734 insertions, 186 deletions
diff --git a/Makefile.common b/Makefile.common
index 9a255d2c43..337d7a2a0f 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -6,7 +6,8 @@ ZIPFILE := scummvm-`date '+%Y-%m-%d'`.zip
INCS = scumm.h scummsys.h stdafx.h
-OBJS += gui/widget.o gui/dialog.o gui/ListWidget.o newgui.o \
+OBJS += gui/widget.o gui/dialog.o gui/util.o newgui.o \
+ gui/ListWidget.o gui/ScrollBarWidget.o \
actor.o boxes.o costume.o gfx.o object.o resource.o \
saveload.o script.o scummvm.o sound.o string.o \
sys.o verbs.o script_v1.o script_v2.o debug.o gui.o \
diff --git a/gui.cpp b/gui.cpp
index 65a132a4bd..2e3162703f 100644
--- a/gui.cpp
+++ b/gui.cpp
@@ -908,11 +908,12 @@ const char *Gui::queryString(int stringno, int id)
result = (char *)_s->getStringAddress(string);
- if (!result) // Gracelessly degrade to english :)
+ if (!result) { // Gracelessly degrade to english :)
if (_s->_features & GF_AFTER_V6)
return string_map_table_v6[stringno - 1].string;
else
return string_map_table_v5[stringno - 1].string;
+ }
return result;
}
diff --git a/gui/ListWidget.cpp b/gui/ListWidget.cpp
index ea2a95ad7c..4d4c42bb72 100644
--- a/gui/ListWidget.cpp
+++ b/gui/ListWidget.cpp
@@ -20,20 +20,19 @@
#include "stdafx.h"
#include "ListWidget.h"
+#include "ScrollBarWidget.h"
#include "dialog.h"
#include "newgui.h"
/*
- * Some thoughts:
- * - We should split out the scrollbar into a seperate widget. This will
- * simplify the drawing & mouse handling considerably, but also requires
- * us to come up with a way to couple both widgets (shouldn't be to hard)
- * - Write a class to encapsulate the data instead of using std::list<string>.
- * How exactly this will look and what it does has yet to be determined.
+ * TODO:
* - The handleKey method of widgets is currently never called, code for that has
* to be added to dialog.cpp
- * - ...
+ * - Once the above item is done, implement scrolling using arrow keys,
+ * pageup/pagedown, home/end keys etc.
+ * - Allow user to select an entry w/ the mouse
+ * - Implement editing of the selected string in a generic fashion
*/
@@ -41,85 +40,87 @@
#define LINE_HEIGHT 10
-// Up/down arrow for the scrollbar
-static uint32 up_arrow[8] = {
- 0x00000000,
- 0x00000000,
- 0x00001000,
- 0x00001000,
- 0x00011100,
- 0x00011100,
- 0x00110110,
- 0x00100010,
-};
-
-static uint32 down_arrow[8] = {
- 0x00000000,
- 0x00000000,
- 0x00100010,
- 0x00110110,
- 0x00011100,
- 0x00011100,
- 0x00001000,
- 0x00001000,
-};
-
ListWidget::ListWidget(Dialog *boss, int x, int y, int w, int h)
- : Widget(boss, x, y, w, h)
+ : Widget(boss, x, y, w - SCROLLBAR_WIDTH, h)
{
- _flags = WIDGET_ENABLED | WIDGET_TRACK_MOUSE | WIDGET_CLEARBG;
+ _flags = WIDGET_ENABLED | WIDGET_CLEARBG;
_type = kListWidget;
+ _numberingMode = kListNumberingOne;
+ _entriesPerPage = (_h - 4) / LINE_HEIGHT;
+ _currentPos = 3;
+
+ _scrollBar = new ScrollBarWidget(boss, _x + _w, _y, SCROLLBAR_WIDTH, _h);
+ _scrollBar->setTarget(this);
+
+ // FIXME - fill in dummy data for now
+ _list.push_back("A simple game?");
+ _list.push_back("This space for rent!");
+ _list.push_back("To be or not to be...");
+ _list.push_back("It's not easy come up with dummy text :-)");
+ _list.push_back("Foo bar baz");
+ _list.push_back("Empty slots follow:");
+ _list.push_back("");
+ _list.push_back("");
+ _list.push_back("Now again a filled slot");
+ _list.push_back("We need some more text!");
+ _list.push_back("Because only this way...");
+ _list.push_back("...can you see the scrollbar...");
+ _list.push_back("...and verify that it works!");
+ _list.push_back("One");
+ _list.push_back("Two");
+ _list.push_back("Three");
+ _list.push_back("Four");
+ _list.push_back("The End");
+
+
+ _scrollBar->_numEntries = _list.size();
+ _scrollBar->_entriesPerPage = _entriesPerPage;
+ _scrollBar->_currentPos = _currentPos;
+ _scrollBar->recalc();
}
ListWidget::~ListWidget()
{
}
-void ListWidget::handleClick(int button)
+void ListWidget::handleClick(int x, int y, int button)
{
if (_flags & WIDGET_ENABLED) {
}
}
-void ListWidget::handleMouseMoved(int x, int y, int state)
+void ListWidget::handleKey(char key, int modifiers)
{
}
-
-void ListWidget::handleKey(char key, int modifiers)
+void ListWidget::handleCommand(CommandSender *sender, uint32 cmd, uint32 data)
{
+ switch (cmd) {
+ case kSetPositionCmd:
+ if (_currentPos != data) {
+ _currentPos = data;
+ draw();
+ }
+ break;
+ }
}
void ListWidget::drawWidget(bool hilite)
{
- NewGui *gui = _boss->getGui();
- int rightX = _x + _w - 1;
- int leftX = rightX - 8;
- int bottomY = _y + _h;
-
- gui->frameRect(leftX, _y, 9, _h, gui->_shadowcolor);
-
- // Up arrow
- gui->fillRect(leftX, _y, 9, 10, gui->_bgcolor);
- gui->frameRect(leftX, _y, 9, 10, gui->_color);
- gui->drawBitmap(up_arrow, leftX, _y, gui->_textcolor);
+ NewGui *gui = _boss->getGui();
+ int i, pos;
+ String buffer;
- // Down arrow
- gui->fillRect(leftX, bottomY - 9, 9, 10, gui->_bgcolor);
- gui->frameRect(leftX, bottomY - 9, 9, 10, gui->_color);
- gui->drawBitmap(down_arrow, leftX, bottomY - 9, gui->_textcolor);
-
- // Slider
- // FIXME - determine slider position and size. This depends on:
- // * the number of entries/page
- // * total number of entries
- // * current scroll position (i.e. idx of "first" visible entry
- gui->fillRect(leftX, _y+20, 9, 4, gui->_textcolor);
- gui->frameRect(leftX, _y+20, 9, 4, gui->_color);
-
- // Now draw the list items
+ // Draw the list items
// FIXME - this is just a temporary demo hack
- gui->drawString("1. A simple game", _x+1, _y+1, _w - 10, gui->_textcolor);
- gui->drawString("2. This space for rent", _x+1, _y+1 + LINE_HEIGHT, _w - 10, gui->_textcolorhi);
- gui->drawString("3. To be or not to be", _x+1, _y+1 + LINE_HEIGHT*2, _w - 10, gui->_textcolor);
+ for (i = 0, pos = _currentPos; i < _entriesPerPage; i++, pos++) {
+ if (_numberingMode == kListNumberingZero || _numberingMode == kListNumberingOne) {
+ char temp[10];
+ sprintf(temp, "%2d. ", (pos + _numberingMode));
+ buffer = temp;
+ } else
+ buffer = "";
+ buffer += _list[pos];
+ gui->drawString(buffer, _x+5, _y+2 + LINE_HEIGHT * i, _w - 10, gui->_textcolor);
+ }
}
diff --git a/gui/ListWidget.h b/gui/ListWidget.h
index e2c1c07447..d3973f6ebe 100644
--- a/gui/ListWidget.h
+++ b/gui/ListWidget.h
@@ -22,13 +22,9 @@
#define LISTWIDGET_H
#include "widget.h"
+#include "util.h"
-// FIXME - use own list class later, this is for rapid development
-//#include <string>
-//#include <vector>
-//typedef std::vector<std::string> StringList;
-typedef int StringList; // FIXME placeholder
-
+class ScrollBarWidget;
enum {
kListNumberingOff = -1,
@@ -37,13 +33,14 @@ enum {
};
/* ListWidget */
-class ListWidget : public Widget {
+class ListWidget : public Widget, public CommandReceiver {
protected:
- StringList _list;
- bool _editable;
- int _numberingMode;
- int _currentPos;
-
+ StringList _list;
+ bool _editable;
+ int _numberingMode;
+ int _currentPos;
+ int _entriesPerPage;
+ ScrollBarWidget *_scrollBar;
public:
ListWidget(Dialog *boss, int x, int y, int w, int h);
virtual ~ListWidget();
@@ -53,9 +50,9 @@ public:
void setNumberingMode(int numberingMode) { _numberingMode = numberingMode; }
- virtual void handleClick(int button);
- virtual void handleMouseMoved(int x, int y, int button);
+ virtual void handleClick(int x, int y, int button);
virtual void handleKey(char key, int modifiers);
+ virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
protected:
void drawWidget(bool hilite);
diff --git a/gui/ScrollBarWidget.cpp b/gui/ScrollBarWidget.cpp
new file mode 100644
index 0000000000..633a01f270
--- /dev/null
+++ b/gui/ScrollBarWidget.cpp
@@ -0,0 +1,157 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ */
+
+#include "stdafx.h"
+#include "ScrollBarWidget.h"
+#include "dialog.h"
+#include "newgui.h"
+
+
+/*
+ * TODO:
+ * - Dragging the slider with the mouse
+ * - Auto-repeast: if one clicks & holds on one of the arrows, then after a
+ * brief delay, it should start to contiously scroll
+ * - Allow for a horizontal scrollbar, too?
+ */
+
+
+// Up arrow
+static uint32 up_arrow[8] = {
+ 0x00000000,
+ 0x00000000,
+ 0x00001000,
+ 0x00001000,
+ 0x00011100,
+ 0x00011100,
+ 0x00110110,
+ 0x00100010,
+};
+
+// Up arrow
+static uint32 down_arrow[8] = {
+ 0x00000000,
+ 0x00000000,
+ 0x00100010,
+ 0x00110110,
+ 0x00011100,
+ 0x00011100,
+ 0x00001000,
+ 0x00001000,
+};
+
+ScrollBarWidget::ScrollBarWidget(Dialog *boss, int x, int y, int w, int h)
+ : Widget(boss, x, y, w, h), CommandSender(boss)
+{
+ _flags = WIDGET_ENABLED | WIDGET_TRACK_MOUSE | WIDGET_CLEARBG;
+ _type = kScrollBarWidget;
+
+ _part = kNoPart;
+
+}
+
+void ScrollBarWidget::handleClick(int x, int y, int button)
+{
+ int old_pos = _currentPos;
+ if (y <= 10) {
+ // Up arrow
+ _currentPos--;
+ } else if (y >= _h-10) {
+ // Down arrow
+ _currentPos++;
+ } else if (y < _sliderPos) {
+ _currentPos -= _entriesPerPage;
+ } else if (y >= _sliderPos + _sliderHeight) {
+ _currentPos += _entriesPerPage;
+ } else {
+ printf("Slider\n");
+ }
+
+ // Bound checking
+ if (_currentPos > _numEntries - _entriesPerPage)
+ _currentPos = _numEntries - _entriesPerPage;
+ else if (_currentPos < 0)
+ _currentPos = 0;
+
+ // Redraw & notify, but only if the position really changed
+ if (old_pos != _currentPos) {
+ recalc();
+ draw();
+ sendCommand(kSetPositionCmd, _currentPos);
+ }
+}
+
+void ScrollBarWidget::handleMouseMoved(int x, int y, int button)
+{
+ int old_part = _part;
+ if (y <= 10) // Up arrow
+ _part = kUpArrowPart;
+ else if (y >= _h-10) // Down arrow
+ _part = kDownArrowPart;
+ else if (y < _sliderPos)
+ _part = kPageUpPart;
+ else if (y >= _sliderPos + _sliderHeight)
+ _part = kPageDownPart;
+ else
+ _part = kSliderPart;
+
+ if (old_part != _part)
+ draw();
+}
+
+void ScrollBarWidget::recalc()
+{
+ _sliderHeight = (_h-20) * _entriesPerPage / _numEntries;
+ if (_sliderHeight < 4)
+ _sliderHeight = 4;
+
+ _sliderPos = 10 + (_h-20-_sliderHeight+1) *_currentPos / (_numEntries - _entriesPerPage);
+ if (_sliderPos < 0)
+ _sliderPos = 0;
+
+}
+
+
+void ScrollBarWidget::drawWidget(bool hilite)
+{
+ NewGui *gui = _boss->getGui();
+ int bottomY = _y + _h;
+
+ gui->frameRect(_x, _y, _w, _h, gui->_shadowcolor);
+
+ // Up arrow
+ gui->frameRect(_x, _y, _w, 10, gui->_color);
+ gui->drawBitmap(up_arrow, _x, _y,
+ (hilite && _part == kUpArrowPart) ? gui->_textcolorhi : gui->_textcolor);
+
+ // Down arrow
+ gui->frameRect(_x, bottomY - 9, _w, 10, gui->_color);
+ gui->drawBitmap(down_arrow, _x, bottomY - 9,
+ (hilite && _part == kDownArrowPart) ? gui->_textcolorhi : gui->_textcolor);
+
+ // Slider
+ // FIXME - determine slider position and size. This depends on:
+ // * the number of entries per page
+ // * total number of entries
+ // * current scroll position (i.e. index of "first" visible entry)
+ gui->checkerRect(_x, _y + _sliderPos, _w, _sliderHeight,
+ (hilite && _part == kSliderPart) ? gui->_textcolorhi : gui->_textcolor);
+ gui->frameRect(_x, _y + _sliderPos, _w, _sliderHeight, gui->_color);
+}
diff --git a/gui/ScrollBarWidget.h b/gui/ScrollBarWidget.h
new file mode 100644
index 0000000000..a30862a333
--- /dev/null
+++ b/gui/ScrollBarWidget.h
@@ -0,0 +1,65 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ */
+
+#ifndef SCROLLBARWIDGET_H
+#define SCROLLBARWIDGET_H
+
+#include "widget.h"
+
+#define SCROLLBAR_WIDTH 9
+
+enum {
+ kSetPositionCmd = 'SETP'
+};
+
+
+class ScrollBarWidget : public Widget, public CommandSender {
+protected:
+ enum {
+ kNoPart,
+ kUpArrowPart,
+ kDownArrowPart,
+ kSliderPart,
+ kPageUpPart,
+ kPageDownPart
+ } _part;
+ int _sliderHeight;
+ int _sliderPos;
+public:
+ int _numEntries;
+ int _entriesPerPage;
+ int _currentPos;
+public:
+ ScrollBarWidget(Dialog *boss, int x, int y, int w, int h);
+// virtual ~ScrollBarWidget();
+
+ void handleClick(int x, int y, int button);
+ void handleMouseMoved(int x, int y, int button);
+ void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); }
+ void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); _part = kNoPart; draw(); }
+
+ void recalc();
+
+protected:
+ void drawWidget(bool hilite);
+};
+
+
+#endif
diff --git a/gui/dialog.cpp b/gui/dialog.cpp
index c14f4e769e..9833058df7 100644
--- a/gui/dialog.cpp
+++ b/gui/dialog.cpp
@@ -84,7 +84,7 @@ void Dialog::handleClick(int x, int y, int button)
{
Widget *w = findWidget(x - _x, y - _y);
if (w)
- w->handleClick(button);
+ w->handleClick(x - _x - w->_x, y - _y - w->_y, button);
}
void Dialog::handleKey(char key, int modifiers)
@@ -98,7 +98,7 @@ void Dialog::handleKey(char key, int modifiers)
key = toupper(key);
while (w) {
if (w->_type == kButtonWidget && key == toupper(((ButtonWidget *)w)->_hotkey)) {
- w->handleClick(1);
+ w->handleClick(0, 0, 1);
break;
}
w = w->_next;
@@ -130,7 +130,7 @@ void Dialog::handleMouseMoved(int x, int y, int button)
}
-void Dialog::handleCommand(uint32 cmd)
+void Dialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data)
{
switch (cmd) {
case kCloseCmd:
@@ -205,10 +205,10 @@ SaveLoadDialog::SaveLoadDialog(NewGui *gui)
new SliderWidget(this, 110, 20, 80, 16, "Volume", 0);
// FIXME - test
- new ListWidget(this, 10, 40, 180, 70);
+ new ListWidget(this, 10, 40, 180, 74);
}
-void SaveLoadDialog::handleCommand(uint32 cmd)
+void SaveLoadDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data)
{
switch (cmd) {
case kSaveCmd:
@@ -225,7 +225,7 @@ void SaveLoadDialog::handleCommand(uint32 cmd)
exit(1);
break;
default:
- Dialog::handleCommand(cmd);
+ Dialog::handleCommand(sender, cmd, data);
}
}
@@ -249,7 +249,7 @@ OptionsDialog::OptionsDialog(NewGui *gui)
addButton(150, 35, 40, 15, CUSTOM_STRING(23), kCloseCmd, 'C'); // Close dialog - FIXME
}
-void OptionsDialog::handleCommand(uint32 cmd)
+void OptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data)
{
switch (cmd) {
case kSoundCmd:
@@ -262,7 +262,7 @@ void OptionsDialog::handleCommand(uint32 cmd)
case kMiscCmd:
break;
default:
- Dialog::handleCommand(cmd);
+ Dialog::handleCommand(sender, cmd, data);
}
}
diff --git a/gui/dialog.h b/gui/dialog.h
index 77eaf57738..336e50db05 100644
--- a/gui/dialog.h
+++ b/gui/dialog.h
@@ -22,9 +22,8 @@
#define DIALOG_H
#include "scummsys.h"
+#include "widget.h"
-
-class Widget;
class NewGui;
#define RES_STRING(id) _gui->queryResString(id)
@@ -35,7 +34,7 @@ enum {
kCloseCmd = 'clos'
};
-class Dialog {
+class Dialog : public CommandReceiver {
friend class Widget;
protected:
NewGui *_gui;
@@ -57,7 +56,7 @@ public:
virtual void handleClick(int x, int y, int button);
virtual void handleKey(char key, int modifiers); // modifiers = alt/shift/ctrl etc.
virtual void handleMouseMoved(int x, int y, int button);
- virtual void handleCommand(uint32 cmd);
+ virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
NewGui *getGui() { return _gui; }
@@ -77,7 +76,7 @@ class SaveLoadDialog : public Dialog {
public:
SaveLoadDialog(NewGui *gui);
- virtual void handleCommand(uint32 cmd);
+ virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
};
@@ -94,7 +93,7 @@ protected:
public:
OptionsDialog(NewGui *gui);
- virtual void handleCommand(uint32 cmd);
+ virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
};
class PauseDialog : public Dialog {
diff --git a/gui/util.cpp b/gui/util.cpp
new file mode 100644
index 0000000000..27e672b472
--- /dev/null
+++ b/gui/util.cpp
@@ -0,0 +1,246 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ */
+
+#include "stdafx.h"
+#include "util.h"
+
+// 8-bit alpha blending routines
+int BlendCache[256][256];
+
+int RGBMatch(byte *palette, int r, int g, int b)
+{
+ int i, bestidx = 0, besterr = 0xFFFFFF;
+ int error = 0;
+
+ for (i = 0;i < 256;i++) {
+ byte *pal = palette + (i * 3);
+ int r_diff = r - (int)*pal++;
+ int g_diff = g - (int)*pal++;
+ int b_diff = b - (int)*pal++;
+ r_diff *= r_diff; g_diff *= g_diff; b_diff *= b_diff;
+
+ error = r_diff + g_diff + b_diff;
+ if (error < besterr) {
+ besterr = error;
+ bestidx = i;
+ }
+ }
+ return bestidx;
+}
+
+int Blend(int src, int dst, byte *palette)
+{
+ int r, g, b;
+ int alpha = 128; // Level of transparency [0-256]
+ byte *srcpal = palette + (dst * 3);
+ byte *dstpal = palette + (src * 3);
+
+ if (BlendCache[dst][src] > -1)
+ return BlendCache[dst][src];
+
+ r = (*srcpal++ * alpha);
+ r += (*dstpal++ * (256-alpha));
+ r /= 256;
+
+ g = (*srcpal++ * alpha);
+ g += (*dstpal++ * (256-alpha));
+ g /= 256;
+
+ b = (*srcpal++ * alpha);
+ b += (*dstpal++ * (256-alpha));
+ b /= 256;
+
+ return (BlendCache[dst][src] = RGBMatch(palette, r , g , b ));
+}
+
+void ClearBlendCache(byte *palette, int weight)
+{
+ for (int i = 0; i < 256; i++)
+ for (int j = 0 ; j < 256 ; j++)
+// BlendCache[i][j] = i; // No alphablending
+// BlendCache[i][j] = j; // 100% translucent
+ BlendCache[i][j] = -1; // Enable alphablending
+}
+
+
+#pragma mark -
+
+
+String::String(const char *str)
+{
+ _capacity = _len = strlen(str);
+ _str = (char *)calloc(1, _capacity+1);
+ memcpy(_str, str, _len+1);
+}
+
+String::String(const String &str)
+{
+ _capacity = str._capacity;
+ _len = str._len;
+ _str = (char *)calloc(1, _capacity+1);
+ memcpy(_str, str._str, _len+1);
+}
+
+String::~String()
+{
+ if (_str)
+ free(_str);
+}
+
+String& String::operator =(const char* str)
+{
+ int len = strlen(str);
+ ensureCapacity(len, false);
+
+ _len = len;
+ memcpy(_str, str, _len + 1);
+
+ return *this;
+}
+
+String& String::operator =(const String& str)
+{
+ int len = str._len;
+ ensureCapacity(len, false);
+
+ _len = len;
+ memcpy(_str, str._str, _len + 1);
+
+ return *this;
+}
+
+String& String::operator +=(const char* str)
+{
+ int len = strlen(str);
+ ensureCapacity(_len + len, true);
+
+ memcpy(_str + _len, str, len + 1);
+ _len += len;
+
+ return *this;
+}
+
+String& String::operator +=(const String& str)
+{
+ int len = str._len;
+ ensureCapacity(_len + len, true);
+
+ memcpy(_str + _len, str._str, len + 1);
+ _len += len;
+
+ return *this;
+}
+
+String& String::operator +=(char c)
+{
+ int len = _len + 1;
+ ensureCapacity(len, true);
+
+ _str[_len++] = c;
+ _str[_len] = 0;
+
+ return *this;
+}
+
+void String::ensureCapacity(int new_len, bool keep_old)
+{
+ if (new_len <= _capacity)
+ return;
+
+ char *old_str = _str;
+ _capacity = new_len + 32;
+ _str = (char *)calloc(1, _capacity+1);
+
+ if (old_str) {
+ if (keep_old)
+ memcpy(_str, old_str, _len+1);
+ free(old_str);
+ }
+}
+
+
+#pragma mark -
+
+
+StringList::StringList(const StringList& list)
+ : _capacity(0), _size(0), _data(0)
+{
+ printf("EEEEK! StringList copy constructor called!\n");
+ assert(0);
+}
+
+StringList::~StringList()
+{
+ if (_data)
+ free(_data);
+}
+
+
+void StringList::push_back(const char* str)
+{
+ ensureCapacity(_size + 1);
+
+ if (!_data[_size])
+ _data[_size] = new String(str);
+ else
+ *_data[_size] = str;
+
+ _size++;
+}
+
+void StringList::push_back(const String& str)
+{
+ ensureCapacity(_size + 1);
+
+ if (!_data[_size])
+ _data[_size] = new String(str);
+ else
+ *_data[_size] = str;
+
+ _size++;
+}
+
+
+String& StringList::operator [](int idx)
+{
+ assert(idx >= 0 && idx < _size);
+ return *_data[idx];
+}
+
+const String& StringList::operator [](int idx) const
+{
+ assert(idx >= 0 && idx < _size);
+ return *_data[idx];
+}
+
+void StringList::ensureCapacity(int new_len)
+{
+ if (new_len <= _capacity)
+ return;
+
+ String **old_data = _data;
+ _capacity = new_len + 32;
+ _data = (String **)calloc(sizeof(String*), _capacity);
+
+ if (old_data) {
+ memcpy(_data, old_data, _size * sizeof(String*));
+ free(old_data);
+ }
+}
diff --git a/gui/util.h b/gui/util.h
new file mode 100644
index 0000000000..91cab2d262
--- /dev/null
+++ b/gui/util.h
@@ -0,0 +1,83 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ */
+
+#ifndef UTIL_H
+#define UTIL_H
+
+#include "scummsys.h"
+
+
+int RGBMatch(byte *palette, int r, int g, int b);
+int Blend(int src, int dst, byte *palette);
+void ClearBlendCache(byte *palette, int weight);
+
+
+class String {
+protected:
+ int _capacity;
+ int _len;
+ char *_str;
+public:
+ String() : _capacity(0), _len(0), _str(0) {}
+ String(const char *str);
+ String(const String &str);
+ ~String();
+
+ String& operator =(const char* str);
+ String& operator =(const String& str);
+ String& operator +=(const char* str);
+ String& operator +=(const String& str);
+ String& operator +=(char c);
+
+// operator char *() { return _str; }
+ operator const char *() const { return _str; }
+ const char *c_str() const { return _str; }
+ int size() const { return _len; }
+
+protected:
+ void ensureCapacity(int new_len, bool keep_old);
+};
+
+class StringList {
+protected:
+ int _capacity;
+ int _size;
+ String **_data;
+public:
+ StringList() : _capacity(0), _size(0), _data(0) {}
+ StringList(const StringList& list);
+ ~StringList();
+
+ void push_back(const char* str);
+ void push_back(const String& str);
+
+ // TODO: insert, remove, ...
+
+ String& operator [](int idx);
+ const String& operator [](int idx) const;
+
+ int size() const { return _size; }
+
+protected:
+ void ensureCapacity(int new_len);
+};
+
+
+#endif
diff --git a/gui/widget.cpp b/gui/widget.cpp
index 82e98f7989..f170ddadc2 100644
--- a/gui/widget.cpp
+++ b/gui/widget.cpp
@@ -44,7 +44,7 @@ void Widget::draw()
_y += _boss->_y;
// Clear background (unless alpha blending is enabled)
- if (_flags & WIDGET_CLEARBG && !_boss->_screenBuf)
+ if (_flags & WIDGET_CLEARBG)
gui->fillRect(_x, _y, _w, _h, gui->_bgcolor);
// Draw border
@@ -74,37 +74,37 @@ void Widget::draw()
StaticTextWidget::StaticTextWidget(Dialog *boss, int x, int y, int w, int h, const char *text)
- : Widget (boss, x, y, w, h), _text(0)
+ : Widget (boss, x, y, w, h), _label(0)
{
_type = kStaticTextWidget;
- setText(text);
+ setLabel(text);
}
StaticTextWidget::~StaticTextWidget()
{
- if (_text) {
- free(_text);
- _text = 0;
+ if (_label) {
+ free(_label);
+ _label = 0;
}
}
-void StaticTextWidget::setText(const char *text)
+void StaticTextWidget::setLabel(const char *label)
{
- // Free old text if any
- if (_text)
- free(_text);
+ // Free old label if any
+ if (_label)
+ free(_label);
- // Duplicate new text
- if (text)
- _text = strdup(text);
+ // Duplicate new label
+ if (label)
+ _label = strdup(label);
else
- _text = 0;
+ _label = 0;
}
void StaticTextWidget::drawWidget(bool hilite)
{
NewGui *gui = _boss->getGui();
- gui->drawString(_text, _x, _y, _w, hilite ? gui->_textcolorhi : gui->_textcolor);
+ gui->drawString(_label, _x, _y, _w, hilite ? gui->_textcolorhi : gui->_textcolor);
}
@@ -112,18 +112,26 @@ void StaticTextWidget::drawWidget(bool hilite)
ButtonWidget::ButtonWidget(Dialog *boss, int x, int y, int w, int h, const char *label, uint32 cmd, uint8 hotkey)
- : StaticTextWidget(boss, x, y, w, h, label), _cmd(cmd), _hotkey(hotkey)
+ : StaticTextWidget(boss, x, y, w, h, label), CommandSender(boss), _cmd(cmd), _hotkey(hotkey)
{
+ assert(label);
_flags = WIDGET_ENABLED | WIDGET_BORDER | WIDGET_CLEARBG ;
_type = kButtonWidget;
}
-void ButtonWidget::handleClick(int button)
+ButtonWidget::~ButtonWidget()
{
- if (_flags & WIDGET_ENABLED && _cmd)
- _boss->handleCommand(_cmd);
+ if (_label) {
+ free(_label);
+ _label = 0;
+ }
}
+void ButtonWidget::handleClick(int x, int y, int button)
+{
+ if (_flags & WIDGET_ENABLED)
+ sendCommand(_cmd, 0);
+}
#pragma mark -
@@ -147,13 +155,12 @@ CheckboxWidget::CheckboxWidget(Dialog *boss, int x, int y, int w, int h, const c
_type = kCheckboxWidget;
}
-void CheckboxWidget::handleClick(int button)
+void CheckboxWidget::handleClick(int x, int y, int button)
{
if (_flags & WIDGET_ENABLED) {
_state = !_state;
draw();
- if (_cmd)
- _boss->handleCommand(_cmd);
+ sendCommand(_cmd, 0);
}
}
@@ -171,7 +178,7 @@ void CheckboxWidget::drawWidget(bool hilite)
gui->fillRect(_x + 2, _y + 2, 10, 10, gui->_bgcolor);
// Finally draw the label
- gui->drawString(_text, _x + 20, _y + 3, _w, gui->_textcolor);
+ gui->drawString(_label, _x + 20, _y + 3, _w, gui->_textcolor);
}
#pragma mark -
diff --git a/gui/widget.h b/gui/widget.h
index a061e31c85..f7cc5eb316 100644
--- a/gui/widget.h
+++ b/gui/widget.h
@@ -41,7 +41,35 @@ enum {
kButtonWidget = 'BTTN',
kCheckboxWidget = 'CHKB',
kSliderWidget = 'SLDE',
- kListWidget = 'LIST'
+ kListWidget = 'LIST',
+ kScrollBarWidget = 'SCRB'
+};
+
+class CommandReceiver;
+class CommandSender;
+
+class CommandReceiver
+{
+friend class CommandSender;
+protected:
+ virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data) = 0;
+};
+
+class CommandSender
+{
+protected:
+ CommandReceiver *_target;
+public:
+ CommandSender(CommandReceiver *target) : _target(target) {}
+
+ void setTarget(CommandReceiver *target) { _target = target; }
+ CommandReceiver *getTarget() const { return _target; }
+
+ virtual void sendCommand(uint32 cmd, uint32 data)
+ {
+ if (_target && cmd)
+ _target->handleCommand(this, cmd, data);
+ }
};
/* Widget */
@@ -59,7 +87,7 @@ public:
Widget(Dialog *boss, int x, int y, int w, int h);
virtual ~Widget() {}
- virtual void handleClick(int button) {}
+ virtual void handleClick(int x, int y, int button) {}
virtual void handleMouseEntered(int button) {}
virtual void handleMouseLeft(int button) {}
virtual void handleMouseMoved(int x, int y, int button) {}
@@ -78,12 +106,12 @@ protected:
/* StaticTextWidget */
class StaticTextWidget : public Widget {
protected:
- char *_text;
+ char *_label;
public:
StaticTextWidget(Dialog *boss, int x, int y, int w, int h, const char *text);
~StaticTextWidget();
- void setText(const char *text);
- const char *getText() const { return _text; }
+ void setLabel(const char *label);
+ const char *getLabel() const { return _label; }
protected:
void drawWidget(bool hilite);
@@ -91,17 +119,19 @@ protected:
/* ButtonWidget */
-class ButtonWidget : public StaticTextWidget {
-friend class Dialog;
+class ButtonWidget : public StaticTextWidget, public CommandSender {
+ friend class Dialog; // Needed for the hotkey handling
protected:
- uint32 _cmd;
- uint8 _hotkey;
+ uint32 _cmd;
+ uint8 _hotkey;
public:
ButtonWidget(Dialog *boss, int x, int y, int w, int h, const char *label, uint32 cmd = 0, uint8 hotkey = 0);
- void setCmd(uint32 cmd) { _cmd = cmd; }
- uint32 getCmd() const { return _cmd; }
+ virtual ~ButtonWidget();
+
+ void setCmd(uint32 cmd) { _cmd = cmd; }
+ uint32 getCmd() const { return _cmd; }
- void handleClick(int button);
+ void handleClick(int x, int y, int button);
void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); draw(); }
void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); draw(); }
};
@@ -115,7 +145,7 @@ public:
void setState(bool state) { _state = state; }
bool getState() const { return _state; }
- void handleClick(int button);
+ void handleClick(int x, int y, int button);
virtual void handleMouseEntered(int button) {}
virtual void handleMouseLeft(int button) {}
diff --git a/newgui.cpp b/newgui.cpp
index 199fb720ff..33f515592d 100644
--- a/newgui.cpp
+++ b/newgui.cpp
@@ -23,65 +23,10 @@
#include "newgui.h"
#include "guimaps.h"
#include "gui/dialog.h"
-
-// 8-bit alpha blending routines
-int BlendCache[256][256];
-
-int RGBMatch(byte *palette, int r, int g, int b) {
- int i, bestidx = 0, besterr = 0xFFFFFF;
- int error = 0;
-
- for (i = 0;i < 256;i++) {
- byte *pal = palette + (i * 3);
- int r_diff = r - (int)*pal++;
- int g_diff = g - (int)*pal++;
- int b_diff = b - (int)*pal++;
- r_diff *= r_diff; g_diff *= g_diff; b_diff *= b_diff;
-
- error = r_diff + g_diff + b_diff;
- if (error < besterr) {
- besterr = error;
- bestidx = i;
- }
- }
- return bestidx;
-}
-
-int Blend(int src, int dst, byte *palette) {
- int r, g, b;
- int alpha = 128; // Level of transparency [0-256]
- byte *srcpal = palette + (dst * 3);
- byte *dstpal = palette + (src * 3);
-
- if (BlendCache[dst][src] > -1)
- return BlendCache[dst][src];
-
- r = (*srcpal++ * alpha);
- r += (*dstpal++ * (256-alpha));
- r /= 256;
-
- g = (*srcpal++ * alpha);
- g += (*dstpal++ * (256-alpha));
- g /= 256;
-
- b = (*srcpal++ * alpha);
- b += (*dstpal++ * (256-alpha));
- b /= 256;
-
- return (BlendCache[dst][src] = RGBMatch(palette, r , g , b ));
-}
-
-void ClearBlendCache(byte *palette, int weight) {
- for (int i = 0; i < 256; i++)
- for (int j = 0 ; j < 256 ; j++)
-// BlendCache[i][j] = i; // No alphablending
-// BlendCache[i][j] = j; // 100% translucent
- BlendCache[i][j] = -1; // Enable alphablending
-}
+#include "gui/util.h"
/*
* TODO list
- * - keep a copy of the original game background, for alpha/moving
* - implement the missing / incomplete dialogs
* - add more widgets
* - add support for right/center aligned text
@@ -357,6 +302,21 @@ void NewGui::fillRect(int x, int y, int w, int h, byte color)
}
}
+void NewGui::checkerRect(int x, int y, int w, int h, byte color)
+{
+ byte *ptr = getBasePtr(x, y);
+ if (ptr == NULL)
+ return;
+
+ while (h--) {
+ for (int i = 0; i < w; i++) {
+ if ((h ^ i) & 1)
+ ptr[i] = color;
+ }
+ ptr += 320;
+ }
+}
+
void NewGui::frameRect(int x, int y, int w, int h, byte color)
{
int i;
diff --git a/newgui.h b/newgui.h
index 7d367b6f19..2f0fa53b10 100644
--- a/newgui.h
+++ b/newgui.h
@@ -102,6 +102,7 @@ public:
void line(int x, int y, int x2, int y2, byte color);
void blendRect(int x, int y, int w, int h, byte color);
void fillRect(int x, int y, int w, int h, byte color);
+ void checkerRect(int x, int y, int w, int h, byte color);
void frameRect(int x, int y, int w, int h, byte color);
void addDirtyRect(int x, int y, int w, int h);
void drawChar(const char c, int x, int y);