diff options
-rw-r--r-- | Makefile.common | 3 | ||||
-rw-r--r-- | gui.cpp | 3 | ||||
-rw-r--r-- | gui/ListWidget.cpp | 129 | ||||
-rw-r--r-- | gui/ListWidget.h | 25 | ||||
-rw-r--r-- | gui/ScrollBarWidget.cpp | 157 | ||||
-rw-r--r-- | gui/ScrollBarWidget.h | 65 | ||||
-rw-r--r-- | gui/dialog.cpp | 16 | ||||
-rw-r--r-- | gui/dialog.h | 11 | ||||
-rw-r--r-- | gui/util.cpp | 246 | ||||
-rw-r--r-- | gui/util.h | 83 | ||||
-rw-r--r-- | gui/widget.cpp | 53 | ||||
-rw-r--r-- | gui/widget.h | 56 | ||||
-rw-r--r-- | newgui.cpp | 72 | ||||
-rw-r--r-- | newgui.h | 1 |
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 \ @@ -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; @@ -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); |