aboutsummaryrefslogtreecommitdiff
path: root/gui
diff options
context:
space:
mode:
Diffstat (limited to 'gui')
-rw-r--r--gui/PopUpWidget.cpp262
-rw-r--r--gui/PopUpWidget.h78
-rw-r--r--gui/ScrollBarWidget.cpp2
-rw-r--r--gui/launcher.cpp14
-rw-r--r--gui/module.mk1
-rw-r--r--gui/newgui.cpp47
-rw-r--r--gui/newgui.h6
7 files changed, 392 insertions, 18 deletions
diff --git a/gui/PopUpWidget.cpp b/gui/PopUpWidget.cpp
new file mode 100644
index 0000000000..966f3cc463
--- /dev/null
+++ b/gui/PopUpWidget.cpp
@@ -0,0 +1,262 @@
+/* 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 "PopUpWidget.h"
+#include "dialog.h"
+#include "newgui.h"
+
+/* TODO:
+ * - draw an (unselectable) sepeator line for items that start with a '-'
+ * - handle looong lists by allowing scrolling (a lot of work if done right,
+ * so I will probably only implement if we really need it)
+ * - ...
+ */
+
+#define UP_DOWN_BOX_HEIGHT 10
+
+// Down arrow
+static uint32 down_arrow[8] = {
+ 0x00000000,
+ 0x00000000,
+ 0x00100010,
+ 0x00110110,
+ 0x00011100,
+ 0x00011100,
+ 0x00001000,
+ 0x00001000,
+};
+
+const ScummVM::String PopUpWidget::emptyStr;
+
+class PopUpDialog : public Dialog {
+protected:
+ PopUpWidget *_popUpBoss;
+ int _clickX, _clickY;
+ byte *_buffer;
+ int _selection;
+public:
+ PopUpDialog(PopUpWidget *boss, int clickX, int clickY);
+
+ void drawDialog();
+
+ void handleMouseDown(int x, int y, int button, int clickCount);
+ void handleMouseUp(int x, int y, int button, int clickCount);
+// void handleMouseWheel(int x, int y, int direction); // Scroll through entries with scroll wheel
+ void handleMouseMoved(int x, int y, int button); // Redraw selections depending on mouse position
+// bool handleKeyDown(uint16 ascii, int keycode, int modifiers); // Scroll through entries with arrow keys etc.
+// void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
+
+protected:
+// void backupMenuBackground();
+// void restoreMenuBackground();
+
+ void drawMenuEntry(int entry, bool hilite);
+
+ int findItem(int x, int y) const;
+};
+
+PopUpDialog::PopUpDialog(PopUpWidget *boss, int clickX, int clickY)
+ : Dialog(boss->_boss->getGui(), 0, 0, 16, 16),
+ _popUpBoss(boss)
+{
+ // Calculate real popup dimensions
+ _x = _popUpBoss->_boss->getX() + _popUpBoss->_x;
+ _y = _popUpBoss->_boss->getY() + _popUpBoss->_y - _popUpBoss->_selectedItem * kLineHeight;
+ _h = _popUpBoss->_entries.size() * kLineHeight + 2;
+ _w = _popUpBoss->_w;
+
+ // Copy the selection index
+ _selection = _popUpBoss->_selectedItem;
+
+ // TODO - perform clipping / switch to scrolling mode if we don't fit on the screen
+
+ // TODO - backup background here
+
+ // Remember original mouse position
+ _clickX = clickX - _x;
+ _clickY = clickY - _y;
+}
+
+void PopUpDialog::drawDialog()
+{
+ // Draw the menu border
+ _gui->box(_x, _y, _w, _h);
+
+ // Draw the entries
+ int count = _popUpBoss->_entries.size();
+ for (int i = 0; i < count; i++) {
+ drawMenuEntry(i, i == _selection);
+ }
+
+ _gui->addDirtyRect(_x, _y, _w, _h);
+}
+
+void PopUpDialog::handleMouseDown(int x, int y, int button, int clickCount)
+{
+}
+
+
+void PopUpDialog::handleMouseUp(int x, int y, int button, int clickCount)
+{
+ // Mouse was released. If it wasn't moved much since the original mouse down,
+ // let the popup stay open. If it did move, assume the user made his selection.
+ int dist = (_clickX - x) * (_clickX - x) + (_clickY - y) * (_clickY - y);
+ if (dist > 3*3) {
+ setResult(_selection);
+ close();
+ }
+ _clickX = -1;
+ _clickY = -1;
+}
+
+void PopUpDialog::handleMouseMoved(int x, int y, int button)
+{
+ // Compute over which item
+ int item = findItem(x, y);
+ if (item != _selection) {
+ // Undraw old selection
+ if (_selection >= 0)
+ drawMenuEntry(_selection, false);
+
+ // Change selection
+ _selection = item;
+
+ // Draw new selection
+ if (item >= 0)
+ drawMenuEntry(item, true);
+ }
+}
+
+int PopUpDialog::findItem(int x, int y) const
+{
+ if (x >= 0 && x < _w && y >= 0 && y < _h) {
+ return (y-2) / kLineHeight;
+ }
+ return _popUpBoss->_selectedItem;
+}
+
+/*
+void PopUpWidget::backupMenuBackground()
+{
+ NewGui *gui = _boss->getGui();
+
+ assert(_menu.buffer);
+ gui->blitToBuffer(_menu.x1, _menu.y1, _menu.w, _menu.h, _menu.buffer, _menu.w * 2);
+}
+
+void PopUpWidget::restoreMenuBackground()
+{
+ NewGui *gui = _boss->getGui();
+
+ assert(_menu.buffer);
+ gui->blitFromBuffer(_menu.x1, _menu.y1, _menu.w, _menu.h, _menu.buffer, _menu.w * 2);
+ gui->addDirtyRect(_menu.x1, _menu.y1, _menu.w, _menu.h);
+ draw();
+}
+*/
+
+void PopUpDialog::drawMenuEntry(int entry, bool hilite)
+{
+ // Draw one entry of the popup menu, including selection
+ assert(entry >= 0);
+ int x = _x + 2;
+ int y = _y + 2 + kLineHeight * entry;
+ int w = _w - 4;
+
+ _gui->fillRect(x, y, w, kLineHeight,
+ hilite ? _gui->_textcolorhi : _gui->_bgcolor);
+ _gui->drawString(_popUpBoss->_entries[entry].name, x+1, y+1, w-2,
+ hilite ? _gui->_bgcolor : _gui->_textcolor);
+ _gui->addDirtyRect(x, y, w, kLineHeight);
+}
+
+//
+//
+//
+//
+//
+
+
+PopUpWidget::PopUpWidget(Dialog *boss, int x, int y, int w, int h)
+ : Widget(boss, x, y-1, w, h+2), CommandSender(boss)
+{
+ _flags = WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS;
+ _type = 'POPU';
+
+ _selectedItem = -1;
+}
+
+void PopUpWidget::handleMouseDown(int x, int y, int button, int clickCount)
+{
+ PopUpDialog popupDialog(this, x + _x + _boss->getX(), y + _y + _boss->getY());
+ int newSel = popupDialog.runModal();
+ if (newSel != -1 && _selectedItem != newSel) {
+ _selectedItem = newSel;
+ sendCommand(kPopUpItemSelectedCmd, _selectedItem);
+ }
+}
+
+void PopUpWidget::appendEntry(const String &entry, uint32 tag)
+{
+ Entry e;
+ e.name = entry;
+ e.tag = tag;
+ _entries.push_back(e);
+}
+
+void PopUpWidget::clearEntries()
+{
+ _entries.clear();
+ _selectedItem = -1;
+}
+
+void PopUpWidget::setSelected(int item)
+{
+ // FIXME
+ if (item != _selectedItem) {
+ if (item >= 0 && item < _entries.size()) {
+ _selectedItem = item;
+ } else {
+ _selectedItem = -1;
+ }
+ }
+}
+
+void PopUpWidget::drawWidget(bool hilite)
+{
+ NewGui *gui = _boss->getGui();
+
+ // Draw a thin frame around us.
+ // TODO - should look different than the EditTextWidget fram
+ gui->hline(_x, _y, _x+_w-1, gui->_color);
+ gui->hline(_x, _y+_h-1, _x+_w-1, gui->_shadowcolor);
+ gui->vline(_x, _y, _y+_h-1, gui->_color);
+ gui->vline(_x+_w-1, _y, _y+_h-1, gui->_shadowcolor);
+
+ // Draw an arrow pointing down at the right end to signal this is a dropdown/popup
+ gui->drawBitmap(down_arrow, _x+_w - 10, _y+1, hilite ? gui->_textcolorhi : gui->_textcolor);
+
+ // Draw the selected entry, if any
+ if (_selectedItem >= 0) {
+ int align = (gui->getStringWidth(_entries[_selectedItem].name) > _w-6) ? kTextAlignRight : kTextAlignLeft;
+ gui->drawString(_entries[_selectedItem].name, _x+2, _y+3, _w-6, gui->_textcolor, align);
+ }
+}
diff --git a/gui/PopUpWidget.h b/gui/PopUpWidget.h
new file mode 100644
index 0000000000..c5901a2317
--- /dev/null
+++ b/gui/PopUpWidget.h
@@ -0,0 +1,78 @@
+/* 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 POPUPWIDGET_H
+#define POPUPWIDGET_H
+
+#include "widget.h"
+#include "common/str.h"
+#include "common/list.h"
+
+enum {
+ kPopUpItemSelectedCmd = 'POPs'
+};
+
+/* PopUpWidget
+ * A popup or dropdown widget which, when clicked, "pop up" a list of items and
+ * lets the user pick on of them.
+ *
+ * Implementation wise, when the user selects an item, then a kPopUpItemSelectedCmd
+ * is broadcast, with data being equal to the tag value of the selected entry.
+ */
+class PopUpWidget : public Widget, public CommandSender {
+ friend class PopUpDialog;
+ typedef ScummVM::String String;
+
+ struct Entry {
+ String name;
+ uint32 tag;
+ };
+ typedef ScummVM::List<Entry> EntryList;
+protected:
+ static const String emptyStr;
+
+ EntryList _entries;
+ int _selectedItem;
+
+public:
+ PopUpWidget(Dialog *boss, int x, int y, int w, int h);
+
+ void handleMouseDown(int x, int y, int button, int clickCount);
+/*
+ void handleMouseUp(int x, int y, int button, int clickCount);
+// void handleMouseWheel(int x, int y, int direction); // Scroll through entries with scroll wheel
+ void handleMouseMoved(int x, int y, int button); // Redraw selections depending on mouse position
+// bool handleKeyDown(uint16 ascii, int keycode, int modifiers); // Scroll through entries with arrow keys etc.
+// void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
+*/
+
+ void appendEntry(const String &entry, uint32 tag = (uint32)-1);
+// void setEntries(const EntryList &entries);
+ void clearEntries();
+
+ void setSelected(int item);
+ int getSelected() const { return _selectedItem; }
+ const String& getSelectedString() const { return (_selectedItem >= 0) ? _entries[_selectedItem].name : emptyStr; }
+
+protected:
+ void drawWidget(bool hilite);
+};
+
+#endif
diff --git a/gui/ScrollBarWidget.cpp b/gui/ScrollBarWidget.cpp
index 9066c67291..232dbc8053 100644
--- a/gui/ScrollBarWidget.cpp
+++ b/gui/ScrollBarWidget.cpp
@@ -48,7 +48,7 @@ static uint32 up_arrow[8] = {
0x00100010,
};
-// Up arrow
+// Down arrow
static uint32 down_arrow[8] = {
0x00000000,
0x00000000,
diff --git a/gui/launcher.cpp b/gui/launcher.cpp
index 0bfae7ca35..5d77021b6e 100644
--- a/gui/launcher.cpp
+++ b/gui/launcher.cpp
@@ -26,6 +26,7 @@
#include "message.h"
#include "EditTextWidget.h"
#include "ListWidget.h"
+#include "PopUpWidget.h"
#include "backends/fs/fs.h"
#include "common/config-file.h"
@@ -86,7 +87,8 @@ protected:
};
EditGameDialog::EditGameDialog(NewGui *gui, Config &config, const String &domain)
- : Dialog(gui, 8, 50, 320-2*8, 200-2*40), _config(config), _domain(domain)
+// : Dialog(gui, 8, 50, 320-2*8, 200-2*40), _config(config), _domain(domain)
+ : Dialog(gui, 8, 30, 320-2*8, 200-2*30), _config(config), _domain(domain)
{
// Determine the description string
String gameid(_config.get("gameid", _domain));
@@ -130,7 +132,15 @@ EditGameDialog::EditGameDialog(NewGui *gui, Config &config, const String &domain
// Load in settings for the checkboxs
_fullscreenCheckbox->setState(_config.getBool("fullscreen", false, _domain));
_AmigaPalCheckbox->setState(_config.getBool("amiga", false, _domain));
-
+
+ // FIXME HACK - add a dummy popup widget here, for debugging.
+ // Note: this isn't useful at all right now...
+ PopUpWidget *foo;
+ foo = new PopUpWidget(this, 15, 102, 200, kLineHeight);
+ foo->appendEntry("Foo");
+ foo->appendEntry("Bar");
+ foo->appendEntry("Baz", 'QUUX');
+ foo->setSelected(0);
}
void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data)
diff --git a/gui/module.mk b/gui/module.mk
index bb024d180a..57bd3ff706 100644
--- a/gui/module.mk
+++ b/gui/module.mk
@@ -9,6 +9,7 @@ MODULE_OBJS = \
gui/ListWidget.o \
gui/message.o \
gui/newgui.o \
+ gui/PopUpWidget.o \
gui/ScrollBarWidget.o \
gui/widget.o \
diff --git a/gui/newgui.cpp b/gui/newgui.cpp
index a30be8ad10..4060fb0d56 100644
--- a/gui/newgui.cpp
+++ b/gui/newgui.cpp
@@ -157,7 +157,7 @@ void NewGui::runLoop()
_system->set_mouse_pos(event.mouse.x, event.mouse.y);
activeDialog->handleMouseMoved(event.mouse.x - activeDialog->_x, event.mouse.y - activeDialog->_y, 0);
break;
- // We don'event distinguish between mousebuttons (for now at least)
+ // We don't distinguish between mousebuttons (for now at least)
case OSystem::EVENT_LBUTTONDOWN:
case OSystem::EVENT_RBUTTONDOWN: {
if (_lastClick.count && (time < _lastClick.time + kDoubleClickDelay)
@@ -297,9 +297,6 @@ void NewGui::line(int x, int y, int x2, int y2, int16 color)
ptr = getBasePtr(x, y);
- if (ptr == NULL)
- return;
-
if (x == x2) {
/* vertical line */
while (y++ <= y2) {
@@ -320,8 +317,6 @@ void NewGui::blendRect(int x, int y, int w, int h, int16 color)
int g = GREEN_FROM_16(color) * 3;
int b = BLUE_FROM_16(color) * 3;
int16 *ptr = getBasePtr(x, y);
- if (ptr == NULL)
- return;
while (h--) {
for (int i = 0; i < w; i++) {
@@ -337,8 +332,6 @@ void NewGui::fillRect(int x, int y, int w, int h, int16 color)
{
int i;
int16 *ptr = getBasePtr(x, y);
- if (ptr == NULL)
- return;
while (h--) {
for (i = 0; i < w; i++) {
@@ -352,8 +345,6 @@ void NewGui::checkerRect(int x, int y, int w, int h, int16 color)
{
int i;
int16 *ptr = getBasePtr(x, y);
- if (ptr == NULL)
- return;
while (h--) {
for (i = 0; i < w; i++) {
@@ -402,8 +393,6 @@ void NewGui::drawChar(const byte chr, int xx, int yy, int16 color)
tmp = guifont + 224 + (chr + 1) * 8;
int16 *ptr = getBasePtr(xx, yy);
- if (ptr == NULL)
- return;
for (y = 0; y < 8; y++) {
for (x = 0; x < 8; x++) {
@@ -454,13 +443,43 @@ void NewGui::drawString(const String &str, int x, int y, int w, int16 color, int
}
//
+// Blit from a buffer to the display
+//
+void NewGui::blitFromBuffer(int x, int y, int w, int h, const byte *buf, int pitch)
+{
+ int16 *ptr = getBasePtr(x, y);
+
+ assert(buf);
+ while (h--) {
+ memcpy(ptr, buf, w*2);
+ ptr += _screenPitch;
+ buf += pitch;
+ }
+}
+
+
+//
+// Blit from the display to a buffer
+//
+void NewGui::blitToBuffer(int x, int y, int w, int h, byte *buf, int pitch)
+{
+ int16 *ptr = getBasePtr(x, y);
+
+ assert(buf);
+ while (h--) {
+ memcpy(buf, ptr, w*2);
+ ptr += _screenPitch;
+ buf += pitch;
+ }
+}
+
+
+//
// Draw an 8x8 bitmap at location (x,y)
//
void NewGui::drawBitmap(uint32 bitmap[8], int x, int y, int16 color)
{
int16 *ptr = getBasePtr(x, y);
- if (ptr == NULL)
- return;
for (int y2 = 0; y2 < 8; y2++) {
uint32 mask = 0xF0000000;
diff --git a/gui/newgui.h b/gui/newgui.h
index 25c22b8147..648f8d34dd 100644
--- a/gui/newgui.h
+++ b/gui/newgui.h
@@ -132,13 +132,17 @@ public:
void fillRect(int x, int y, int w, int h, int16 color);
void checkerRect(int x, int y, int w, int h, int16 color);
void frameRect(int x, int y, int w, int h, int16 color);
- void addDirtyRect(int x, int y, int w, int h);
void drawChar(byte c, int x, int y, int16 color);
int getStringWidth(const String &str);
int getCharWidth(byte c);
void drawString(const String &str, int x, int y, int w, int16 color, int align = kTextAlignLeft);
+ void blitFromBuffer(int x, int y, int w, int h, const byte *buf, int pitch);
+ void blitToBuffer(int x, int y, int w, int h, byte *buf, int pitch);
+
void drawBitmap(uint32 bitmap[8], int x, int y, int16 color);
+
+ void addDirtyRect(int x, int y, int w, int h);
};
#endif