aboutsummaryrefslogtreecommitdiff
path: root/gui/widgets
diff options
context:
space:
mode:
authorBastien Bouclet2019-11-13 21:09:21 +0100
committerBastien Bouclet2019-11-24 14:06:25 +0100
commit2c812a6b7a0b24b9012379118867fb4f64f32c14 (patch)
tree6f4225127305dbdae8f3a0dc7dfe61e51af51b1a /gui/widgets
parent3db6aed4e474d5b16639ee4958d1cd13504d12fb (diff)
downloadscummvm-rg350-2c812a6b7a0b24b9012379118867fb4f64f32c14.tar.gz
scummvm-rg350-2c812a6b7a0b24b9012379118867fb4f64f32c14.tar.bz2
scummvm-rg350-2c812a6b7a0b24b9012379118867fb4f64f32c14.zip
GUI: Add DropdownButtonWidget and use it in the launcher for mass add
DropdownButtonWidget is a button split in two parts vertically. Clicking the left part triggers a default action. Clicking the right part shows a list of other actions the user can choose from. Using this widget on the launcher lets 'Mass add' be a secondary action of the 'Add' button, removing the necessity of pressing the shift key to access the feature.
Diffstat (limited to 'gui/widgets')
-rw-r--r--gui/widgets/popup.cpp187
-rw-r--r--gui/widgets/popup.h59
2 files changed, 155 insertions, 91 deletions
diff --git a/gui/widgets/popup.cpp b/gui/widgets/popup.cpp
index 970e35ab23..351d0fe559 100644
--- a/gui/widgets/popup.cpp
+++ b/gui/widgets/popup.cpp
@@ -21,7 +21,6 @@
*/
#include "common/system.h"
-#include "gui/dialog.h"
#include "gui/gui-manager.h"
#include "gui/widgets/popup.h"
@@ -33,62 +32,35 @@ namespace GUI {
// PopUpDialog
//
-class PopUpDialog : public Dialog {
-protected:
- PopUpWidget *_popUpBoss;
- int _clickX, _clickY;
- int _selection;
- uint32 _openTime;
- bool _twoColumns;
- int _entriesPerColumn;
-
- int _leftPadding;
- int _rightPadding;
-
- int _lastRead;
-
-public:
- PopUpDialog(PopUpWidget *boss, int clickX, int clickY);
-
- void drawDialog(DrawLayer layerToDraw) override;
-
- void handleMouseUp(int x, int y, int button, int clickCount) override;
- void handleMouseWheel(int x, int y, int direction) override; // Scroll through entries with scroll wheel
- void handleMouseMoved(int x, int y, int button) override; // Redraw selections depending on mouse position
- void handleMouseLeft(int button) override;
- void handleKeyDown(Common::KeyState state) override; // Scroll through entries with arrow keys etc.
-
-protected:
- void drawMenuEntry(int entry, bool hilite);
-
- int findItem(int x, int y) const;
- void setSelection(int item);
- bool isMouseDown();
-
- void moveUp();
- void moveDown();
- void read(Common::String);
-};
-
-PopUpDialog::PopUpDialog(PopUpWidget *boss, int clickX, int clickY)
- : Dialog(0, 0, 16, 16),
- _popUpBoss(boss) {
+PopUpDialog::PopUpDialog(Widget *boss, const Common::String &name, int clickX, int clickY):
+ Dialog(name),
+ _boss(boss),
+ // Remember original mouse position
+ _clickX(clickX),
+ _clickY(clickY),
+ _selection(-1),
+ _initialSelection(-1),
+ _openTime(0),
+ _twoColumns(false),
+ _entriesPerColumn(1),
+ _leftPadding(0),
+ _rightPadding(0),
+ _lineHeight(kLineHeight),
+ _lastRead(-1) {
_backgroundType = ThemeEngine::kDialogBackgroundNone;
+ _w = _boss->getWidth();
+}
- _openTime = 0;
- _entriesPerColumn = 1;
+void PopUpDialog::open() {
+ // Time the popup was opened
+ _openTime = g_system->getMillis();
- // Copy the selection index
- _selection = _popUpBoss->_selectedItem;
+ _initialSelection = _selection;
// Calculate real popup dimensions
- _x = _popUpBoss->getAbsX();
- _y = _popUpBoss->getAbsY() - _popUpBoss->_selectedItem * kLineHeight;
- _h = _popUpBoss->_entries.size() * kLineHeight + 2;
- _w = _popUpBoss->_w - kLineHeight + 2;
+ _h = _entries.size() * _lineHeight + 2;
- _leftPadding = _popUpBoss->_leftPadding;
- _rightPadding = _popUpBoss->_rightPadding;
+ _entriesPerColumn = 1;
// Perform clipping / switch to scrolling mode if we don't fit on the screen
// FIXME - OSystem should send out notification messages when the screen
@@ -103,16 +75,16 @@ PopUpDialog::PopUpDialog(PopUpWidget *boss, int clickX, int clickY)
const int screenW = g_system->getOverlayWidth();
_twoColumns = true;
- _entriesPerColumn = _popUpBoss->_entries.size() / 2;
+ _entriesPerColumn = _entries.size() / 2;
- if (_popUpBoss->_entries.size() & 1)
+ if (_entries.size() & 1)
_entriesPerColumn++;
- _h = _entriesPerColumn * kLineHeight + 2;
+ _h = _entriesPerColumn * _lineHeight + 2;
_w = 0;
- for (uint i = 0; i < _popUpBoss->_entries.size(); i++) {
- int width = g_gui.getStringWidth(_popUpBoss->_entries[i].name);
+ for (uint i = 0; i < _entries.size(); i++) {
+ int width = g_gui.getStringWidth(_entries[i]);
if (width > _w)
_w = width;
@@ -123,9 +95,9 @@ PopUpDialog::PopUpDialog(PopUpWidget *boss, int clickX, int clickY)
if (!(_w & 1))
_w++;
- if (_popUpBoss->_selectedItem >= _entriesPerColumn) {
+ if (_selection >= _entriesPerColumn) {
_x -= _w / 2;
- _y = _popUpBoss->getAbsY() - (_popUpBoss->_selectedItem - _entriesPerColumn) * kLineHeight;
+ _y = _boss->getAbsY() - (_selection - _entriesPerColumn) * _lineHeight;
}
if (_w >= screenW)
@@ -146,11 +118,12 @@ PopUpDialog::PopUpDialog(PopUpWidget *boss, int clickX, int clickY)
// TODO - implement scrolling if we had to move the menu, or if there are too many entries
- // Remember original mouse position
- _clickX = clickX - _x;
- _clickY = clickY - _y;
-
_lastRead = -1;
+
+ Dialog::open();
+}
+
+void PopUpDialog::reflowLayout() {
}
void PopUpDialog::drawDialog(DrawLayer layerToDraw) {
@@ -163,7 +136,7 @@ void PopUpDialog::drawDialog(DrawLayer layerToDraw) {
g_gui.vLine(_x + _w / 2, _y, _y + _h - 2, g_gui._color);*/
// Draw the entries
- int count = _popUpBoss->_entries.size();
+ int count = _entries.size();
for (int i = 0; i < count; i++) {
drawMenuEntry(i, i == _selection);
}
@@ -172,17 +145,15 @@ void PopUpDialog::drawDialog(DrawLayer layerToDraw) {
/*if (_twoColumns && (count & 1)) {
g_gui.fillRect(_x + 1 + _w / 2, _y + 1 + kLineHeight * (_entriesPerColumn - 1), _w / 2 - 1, kLineHeight, g_gui._bgcolor);
}*/
-
- if (_openTime == 0) {
- // Time the popup was opened
- _openTime = g_system->getMillis();
- }
}
void PopUpDialog::handleMouseUp(int x, int y, int button, int clickCount) {
+ int absX = x + getAbsX();
+ int absY = y + getAbsY();
+
// 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);
+ int dist = (_clickX - absX) * (_clickX - absX) + (_clickY - absY) * (_clickY - absY);
if (dist > 3 * 3 || g_system->getMillis() - _openTime > 300) {
setResult(_selection);
close();
@@ -203,18 +174,18 @@ void PopUpDialog::handleMouseMoved(int x, int y, int button) {
// Compute over which item the mouse is...
int item = findItem(x, y);
- if (item >= 0 && _popUpBoss->_entries[item].name.size() == 0)
+ if (item >= 0 && _entries[item].size() == 0)
item = -1;
if (item == -1 && !isMouseDown()) {
- setSelection(_popUpBoss->_selectedItem);
+ setSelection(_initialSelection);
return;
}
// ...and update the selection accordingly
setSelection(item);
- if (_lastRead != item && _popUpBoss->_entries.size() > 0 && item != -1) {
- read(_popUpBoss->_entries[item].name);
+ if (_lastRead != item && _entries.size() > 0 && item != -1) {
+ read(_entries[item]);
_lastRead = item;
}
}
@@ -261,7 +232,7 @@ void PopUpDialog::handleKeyDown(Common::KeyState state) {
break;
// fall through
case Common::KEYCODE_END:
- setSelection(_popUpBoss->_entries.size()-1);
+ setSelection(_entries.size()-1);
break;
case Common::KEYCODE_KP2:
@@ -293,19 +264,45 @@ void PopUpDialog::handleKeyDown(Common::KeyState state) {
}
}
+void PopUpDialog::setPosition(int x, int y) {
+ _x = x;
+ _y = y;
+}
+
+void PopUpDialog::setPadding(int left, int right) {
+ _leftPadding = left;
+ _rightPadding = right;
+}
+
+void PopUpDialog::setLineHeight(int lineHeight) {
+ _lineHeight = lineHeight;
+}
+
+void PopUpDialog::setWidth(uint16 width) {
+ _w = width;
+}
+
+void PopUpDialog::appendEntry(const Common::String &entry) {
+ _entries.push_back(entry);
+}
+
+void PopUpDialog::clearEntries() {
+ _entries.clear();
+}
+
int PopUpDialog::findItem(int x, int y) const {
if (x >= 0 && x < _w && y >= 0 && y < _h) {
if (_twoColumns) {
- uint entry = (y - 2) / kLineHeight;
+ uint entry = (y - 2) / _lineHeight;
if (x > _w / 2) {
entry += _entriesPerColumn;
- if (entry >= _popUpBoss->_entries.size())
+ if (entry >= _entries.size())
return -1;
}
return entry;
}
- return (y - 2) / kLineHeight;
+ return (y - 2) / _lineHeight;
}
return -1;
}
@@ -335,19 +332,19 @@ bool PopUpDialog::isMouseDown() {
void PopUpDialog::moveUp() {
if (_selection < 0) {
- setSelection(_popUpBoss->_entries.size() - 1);
+ setSelection(_entries.size() - 1);
} else if (_selection > 0) {
int item = _selection;
do {
item--;
- } while (item >= 0 && _popUpBoss->_entries[item].name.size() == 0);
+ } while (item >= 0 && _entries[item].size() == 0);
if (item >= 0)
setSelection(item);
}
}
void PopUpDialog::moveDown() {
- int lastItem = _popUpBoss->_entries.size() - 1;
+ int lastItem = _entries.size() - 1;
if (_selection < 0) {
setSelection(0);
@@ -355,7 +352,7 @@ void PopUpDialog::moveDown() {
int item = _selection;
do {
item++;
- } while (item <= lastItem && _popUpBoss->_entries[item].name.size() == 0);
+ } while (item <= lastItem && _entries[item].size() == 0);
if (item <= lastItem)
setSelection(item);
}
@@ -367,34 +364,34 @@ void PopUpDialog::drawMenuEntry(int entry, bool hilite) {
int x, y, w;
if (_twoColumns) {
- int n = _popUpBoss->_entries.size() / 2;
+ int n = _entries.size() / 2;
- if (_popUpBoss->_entries.size() & 1)
+ if (_entries.size() & 1)
n++;
if (entry >= n) {
x = _x + 1 + _w / 2;
- y = _y + 1 + kLineHeight * (entry - n);
+ y = _y + 1 + _lineHeight * (entry - n);
} else {
x = _x + 1;
- y = _y + 1 + kLineHeight * entry;
+ y = _y + 1 + _lineHeight * entry;
}
w = _w / 2 - 1;
} else {
x = _x + 1;
- y = _y + 1 + kLineHeight * entry;
+ y = _y + 1 + _lineHeight * entry;
w = _w - 2;
}
- Common::String &name(_popUpBoss->_entries[entry].name);
+ Common::String &name(_entries[entry]);
if (name.size() == 0) {
// Draw a separator
- g_gui.theme()->drawLineSeparator(Common::Rect(x, y, x + w, y + kLineHeight));
+ g_gui.theme()->drawLineSeparator(Common::Rect(x, y, x + w, y + _lineHeight));
} else {
g_gui.theme()->drawText(
- Common::Rect(x + 1, y + 2, x + w, y + 2 + kLineHeight),
+ Common::Rect(x + 1, y + 2, x + w, y + 2 + _lineHeight),
name, hilite ? ThemeEngine::kStateHighlight : ThemeEngine::kStateEnabled,
Graphics::kTextAlignLeft, ThemeEngine::kTextInversionNone, _leftPadding
);
@@ -429,7 +426,17 @@ PopUpWidget::PopUpWidget(GuiObject *boss, int x, int y, int w, int h, const char
void PopUpWidget::handleMouseDown(int x, int y, int button, int clickCount) {
if (isEnabled()) {
- PopUpDialog popupDialog(this, x + getAbsX(), y + getAbsY());
+ PopUpDialog popupDialog(this, "", x + getAbsX(), y + getAbsY());
+ popupDialog.setPosition(getAbsX(), getAbsY() - _selectedItem * kLineHeight);
+ popupDialog.setPadding(_leftPadding, _rightPadding);
+ popupDialog.setWidth(getWidth() - kLineHeight + 2);
+
+
+ for (uint i = 0; i < _entries.size(); i++) {
+ popupDialog.appendEntry(_entries[i].name);
+ }
+ popupDialog.setSelection(_selectedItem);
+
int newSel = popupDialog.runModal();
if (newSel != -1 && _selectedItem != newSel) {
_selectedItem = newSel;
diff --git a/gui/widgets/popup.h b/gui/widgets/popup.h
index 3ccf8787d5..d7c218f2d3 100644
--- a/gui/widgets/popup.h
+++ b/gui/widgets/popup.h
@@ -23,6 +23,7 @@
#ifndef GUI_WIDGETS_POPUP_H
#define GUI_WIDGETS_POPUP_H
+#include "gui/dialog.h"
#include "gui/widget.h"
#include "common/str.h"
#include "common/array.h"
@@ -41,7 +42,6 @@ enum {
* is broadcast, with data being equal to the tag value of the selected entry.
*/
class PopUpWidget : public Widget, public CommandSender {
- friend class PopUpDialog;
typedef Common::String String;
struct Entry {
@@ -85,6 +85,63 @@ protected:
void drawWidget();
};
+/**
+ * A small dialog showing a list of items and allowing the user to chose one of them
+ *
+ * Used by PopUpWidget and DropdownButtonWidget.
+ */
+class PopUpDialog : public Dialog {
+protected:
+ Widget *_boss;
+ int _clickX, _clickY;
+ int _selection;
+ int _initialSelection;
+ uint32 _openTime;
+ bool _twoColumns;
+ int _entriesPerColumn;
+
+ int _leftPadding;
+ int _rightPadding;
+ int _lineHeight;
+
+ int _lastRead;
+
+ typedef Common::Array<Common::String> EntryList;
+ EntryList _entries;
+
+public:
+ PopUpDialog(Widget *boss, const Common::String &name, int clickX, int clickY);
+
+ void open() override;
+ void reflowLayout() override;
+ void drawDialog(DrawLayer layerToDraw) override;
+
+ void handleMouseUp(int x, int y, int button, int clickCount) override;
+ void handleMouseWheel(int x, int y, int direction) override; // Scroll through entries with scroll wheel
+ void handleMouseMoved(int x, int y, int button) override; // Redraw selections depending on mouse position
+ void handleMouseLeft(int button) override;
+ void handleKeyDown(Common::KeyState state) override; // Scroll through entries with arrow keys etc.
+
+ void setPosition(int x, int y);
+ void setPadding(int left, int right);
+ void setLineHeight(int lineHeight);
+ void setWidth(uint16 width);
+
+ void appendEntry(const Common::String &entry);
+ void clearEntries();
+ void setSelection(int item);
+
+protected:
+ void drawMenuEntry(int entry, bool hilite);
+
+ int findItem(int x, int y) const;
+ bool isMouseDown();
+
+ void moveUp();
+ void moveDown();
+ void read(Common::String);
+};
+
} // End of namespace GUI
#endif