aboutsummaryrefslogtreecommitdiff
path: root/gui
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
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')
-rw-r--r--gui/ThemeEngine.cpp40
-rw-r--r--gui/ThemeEngine.h10
-rw-r--r--gui/ThemeParser.cpp11
-rw-r--r--gui/ThemeParser.h1
-rw-r--r--gui/launcher.cpp122
-rw-r--r--gui/launcher.h7
-rw-r--r--gui/options.cpp30
-rw-r--r--gui/themes/default.inc307
-rw-r--r--gui/themes/scummclassic.zipbin154528 -> 157690 bytes
-rw-r--r--gui/themes/scummclassic/classic_gfx.stx307
-rw-r--r--gui/themes/scummclassic/classic_layout.stx4
-rw-r--r--gui/themes/scummclassic/classic_layout_lowres.stx4
-rw-r--r--gui/themes/scummmodern.zipbin283299 -> 287846 bytes
-rw-r--r--gui/themes/scummmodern/scummmodern_gfx.stx362
-rw-r--r--gui/themes/scummmodern/scummmodern_layout.stx35
-rw-r--r--gui/themes/scummmodern/scummmodern_layout_lowres.stx4
-rw-r--r--gui/themes/scummremastered.zipbin283227 -> 285890 bytes
-rw-r--r--gui/themes/scummremastered/remastered_gfx.stx316
-rw-r--r--gui/themes/scummremastered/remastered_layout.stx24
-rw-r--r--gui/themes/scummremastered/remastered_layout_lowres.stx4
-rw-r--r--gui/widget.cpp103
-rw-r--r--gui/widget.h35
-rw-r--r--gui/widgets/popup.cpp187
-rw-r--r--gui/widgets/popup.h59
24 files changed, 1738 insertions, 234 deletions
diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index e27ee7ac9d..2c089708a4 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -126,9 +126,16 @@ static const DrawDataInfo kDrawDataDefaults[] = {
{kDDWidgetBackgroundSlider, "widget_slider", kDrawLayerBackground, kDDNone},
{kDDButtonIdle, "button_idle", kDrawLayerBackground, kDDNone},
- {kDDButtonHover, "button_hover", kDrawLayerForeground, kDDButtonIdle},
+ {kDDButtonHover, "button_hover", kDrawLayerForeground, kDDButtonIdle},
{kDDButtonDisabled, "button_disabled", kDrawLayerBackground, kDDNone},
- {kDDButtonPressed, "button_pressed", kDrawLayerForeground, kDDButtonIdle},
+ {kDDButtonPressed, "button_pressed", kDrawLayerForeground, kDDButtonIdle},
+
+ {kDDDropDownButtonIdle, "dropdown_button_idle", kDrawLayerBackground, kDDNone},
+ {kDDDropDownButtonHoverLeft, "dropdown_button_hover_left", kDrawLayerForeground, kDDDropDownButtonIdle},
+ {kDDDropDownButtonHoverRight, "dropdown_button_hover_right", kDrawLayerForeground, kDDDropDownButtonIdle},
+ {kDDDropDownButtonDisabled, "dropdown_button_disabled", kDrawLayerForeground, kDDNone},
+ {kDDDropDownButtonPressedLeft, "dropdown_button_pressed_left", kDrawLayerForeground, kDDDropDownButtonIdle},
+ {kDDDropDownButtonPressedRight, "dropdown_button_pressed_right", kDrawLayerForeground, kDDDropDownButtonIdle},
{kDDSliderFull, "slider_full", kDrawLayerForeground, kDDNone},
{kDDSliderHover, "slider_hover", kDrawLayerForeground, kDDNone},
@@ -935,6 +942,35 @@ void ThemeEngine::drawButton(const Common::Rect &r, const Common::String &str, W
_widgets[dd]->_textAlignV);
}
+void ThemeEngine::drawDropDownButton(const Common::Rect &r, uint32 dropdownWidth, const Common::String &str,
+ ThemeEngine::WidgetStateInfo buttonState, bool inButton, bool inDropdown) {
+ if (!ready())
+ return;
+
+ DrawData dd;
+ if (buttonState == kStateHighlight && inButton)
+ dd = kDDDropDownButtonHoverLeft;
+ else if (buttonState == kStateHighlight && inDropdown)
+ dd = kDDDropDownButtonHoverRight;
+ else if (buttonState == kStateDisabled)
+ dd = kDDDropDownButtonDisabled;
+ else if (buttonState == kStatePressed && inButton)
+ dd = kDDDropDownButtonPressedLeft;
+ else if (buttonState == kStatePressed && inDropdown)
+ dd = kDDDropDownButtonPressedRight;
+ else
+ dd = kDDDropDownButtonIdle;
+
+ drawDD(dd, r);
+
+ // Center the text in the button without using the area of the drop down button
+ Common::Rect textRect = r;
+ textRect.left = r.left + dropdownWidth;
+ textRect.right = r.right - dropdownWidth;
+ drawDDText(getTextData(dd), getTextColor(dd), textRect, str, false, true, _widgets[dd]->_textAlignH,
+ _widgets[dd]->_textAlignV);
+}
+
void ThemeEngine::drawLineSeparator(const Common::Rect &r) {
if (!ready())
return;
diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h
index 1c35b1ea03..827ec197f9 100644
--- a/gui/ThemeEngine.h
+++ b/gui/ThemeEngine.h
@@ -80,6 +80,13 @@ enum DrawData {
kDDButtonDisabled,
kDDButtonPressed,
+ kDDDropDownButtonIdle,
+ kDDDropDownButtonHoverLeft,
+ kDDDropDownButtonHoverRight,
+ kDDDropDownButtonDisabled,
+ kDDDropDownButtonPressedLeft,
+ kDDDropDownButtonPressedRight,
+
kDDSliderFull,
kDDSliderHover,
kDDSliderDisabled,
@@ -400,6 +407,9 @@ public:
void drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled,
uint16 hints = 0);
+ void drawDropDownButton(const Common::Rect &r, uint32 dropdownWidth, const Common::String &str,
+ WidgetStateInfo buttonState, bool inButton, bool inDropdown);
+
void drawSurface(const Common::Point &p, const Graphics::Surface &surface, bool themeTrans = false);
void drawSlider(const Common::Rect &r, int width, WidgetStateInfo state = kStateEnabled);
diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp
index a52e3592af..f92676a383 100644
--- a/gui/ThemeParser.cpp
+++ b/gui/ThemeParser.cpp
@@ -629,6 +629,17 @@ bool ThemeParser::parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawst
}
}
+ if (stepNode->values.contains("clip")) {
+ val = stepNode->values["clip"];
+ int cl, ct, cr, cb;
+ if (parseIntegerKey(val, 4, &cl, &ct, &cr, &cb)) {
+ drawstep->clip.left = cl;
+ drawstep->clip.top = ct;
+ drawstep->clip.right = cr;
+ drawstep->clip.bottom = cb;
+ }
+ }
+
#undef PARSER_ASSIGN_INT
#undef PARSER_ASSIGN_RGB
diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h
index 155731467f..f55a24aa80 100644
--- a/gui/ThemeParser.h
+++ b/gui/ThemeParser.h
@@ -147,6 +147,7 @@ protected:
XML_PROP(orientation, false)
XML_PROP(file, false)
XML_PROP(autoscale, false)
+ XML_PROP(clip, false)
KEY_END()
XML_KEY(text)
diff --git a/gui/launcher.cpp b/gui/launcher.cpp
index 84512ea018..15866c0bc8 100644
--- a/gui/launcher.cpp
+++ b/gui/launcher.cpp
@@ -66,9 +66,11 @@ enum {
kAboutCmd = 'ABOU',
kOptionsCmd = 'OPTN',
kAddGameCmd = 'ADDG',
+ kMassAddGameCmd = 'MADD',
kEditGameCmd = 'EDTG',
kRemoveGameCmd = 'REMG',
kLoadGameCmd = 'LOAD',
+ kRecordGameCmd = 'RECG',
kQuitCmd = 'QUIT',
kSearchCmd = 'SRCH',
kListSearchCmd = 'LSSR',
@@ -145,20 +147,30 @@ void LauncherDialog::build() {
_startButton =
new ButtonWidget(this, "Launcher.StartButton", _("~S~tart"), _("Start selected game"), kStartCmd);
- _loadButton =
- new ButtonWidget(this, "Launcher.LoadGameButton", _("~L~oad..."), _("Load saved game for selected game"), kLoadGameCmd);
+ DropdownButtonWidget *loadButton =
+ new DropdownButtonWidget(this, "Launcher.LoadGameButton", _("~L~oad..."), _("Load saved game for selected game"), kLoadGameCmd);
+#ifdef ENABLE_EVENTRECORDER
+ loadButton->appendEntry(_s("Record..."), kRecordGameCmd);
+#endif
+ _loadButton = loadButton;
// Above the lowest button rows: two more buttons (directly below the list box)
if (g_system->getOverlayWidth() > 320) {
- _addButton =
- new ButtonWidget(this, "Launcher.AddGameButton", _("~A~dd Game..."), _("Hold Shift for Mass Add"), kAddGameCmd);
+ DropdownButtonWidget *addButton =
+ new DropdownButtonWidget(this, "Launcher.AddGameButton", _("~A~dd Game..."), _("Add games to the list"), kAddGameCmd);
+ addButton->appendEntry(_s("Mass Add..."), kMassAddGameCmd);
+ _addButton = addButton;
+
_editButton =
new ButtonWidget(this, "Launcher.EditGameButton", _("~E~dit Game..."), _("Change game options"), kEditGameCmd);
_removeButton =
new ButtonWidget(this, "Launcher.RemoveGameButton", _("~R~emove Game"), _("Remove game from the list. The game data files stay intact"), kRemoveGameCmd);
} else {
- _addButton =
- new ButtonWidget(this, "Launcher.AddGameButton", _c("~A~dd Game...", "lowres"), _("Hold Shift for Mass Add"), kAddGameCmd);
+ DropdownButtonWidget *addButton =
+ new DropdownButtonWidget(this, "Launcher.AddGameButton", _c("~A~dd Game...", "lowres"), _("Add games to the list"), kAddGameCmd);
+ addButton->appendEntry(_c("Mass Add...", "lowres"), kMassAddGameCmd);
+ _addButton = addButton;
+
_editButton =
new ButtonWidget(this, "Launcher.EditGameButton", _c("~E~dit Game...", "lowres"), _("Change game options"), kEditGameCmd);
_removeButton =
@@ -318,38 +330,6 @@ void LauncherDialog::updateListing() {
}
void LauncherDialog::addGame() {
-
-#ifndef DISABLE_MASS_ADD
- const bool massAdd = checkModifier(Common::KBD_SHIFT);
-
- if (massAdd) {
- MessageDialog alert(_("Do you really want to run the mass game detector? "
- "This could potentially add a huge number of games."), _("Yes"), _("No"));
- if (alert.runModal() == GUI::kMessageOK && _browser->runModal() > 0) {
- MassAddDialog massAddDlg(_browser->getResult());
-
- massAddDlg.runModal();
-
- // Update the ListWidget and force a redraw
-
- // If new target(s) were added, update the ListWidget and move
- // the selection to to first newly detected game.
- Common::String newTarget = massAddDlg.getFirstAddedTarget();
- if (!newTarget.empty()) {
- updateListing();
- selectTarget(newTarget);
- }
-
- g_gui.scheduleTopDialogRedraw();
- }
-
- // We need to update the buttons here, so "Mass add" will revert to "Add game"
- // without any additional event.
- updateButtons();
- return;
- }
-#endif
-
// Allow user to add a new game to the list.
// 1) show a dir selection dialog which lets the user pick the directory
// the game data resides in.
@@ -392,6 +372,28 @@ void LauncherDialog::addGame() {
} while (looping);
}
+void LauncherDialog::massAddGame() {
+ MessageDialog alert(_("Do you really want to run the mass game detector? "
+ "This could potentially add a huge number of games."), _("Yes"), _("No"));
+ if (alert.runModal() == GUI::kMessageOK && _browser->runModal() > 0) {
+ MassAddDialog massAddDlg(_browser->getResult());
+
+ massAddDlg.runModal();
+
+ // Update the ListWidget and force a redraw
+
+ // If new target(s) were added, update the ListWidget and move
+ // the selection to to first newly detected game.
+ Common::String newTarget = massAddDlg.getFirstAddedTarget();
+ if (!newTarget.empty()) {
+ updateListing();
+ selectTarget(newTarget);
+ }
+
+ g_gui.scheduleTopDialogRedraw();
+ }
+}
+
void LauncherDialog::removeGame(int item) {
MessageDialog alert(_("Do you really want to remove this game configuration?"), _("Yes"), _("No"));
@@ -432,20 +434,6 @@ void LauncherDialog::editGame(int item) {
}
}
-void LauncherDialog::loadGameButtonPressed(int item) {
-#ifdef ENABLE_EVENTRECORDER
- const bool shiftPressed = checkModifier(Common::KBD_SHIFT);
- if (shiftPressed) {
- recordGame(item);
- } else {
- loadGame(item);
- }
- updateButtons();
-#else
- loadGame(item);
-#endif
-}
-
#ifdef ENABLE_EVENTRECORDER
void LauncherDialog::recordGame(int item) {
RecorderDialog recorderDialog;
@@ -640,6 +628,9 @@ void LauncherDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
case kAddGameCmd:
addGame();
break;
+ case kMassAddGameCmd:
+ massAddGame();
+ break;
case kRemoveGameCmd:
removeGame(item);
break;
@@ -647,8 +638,13 @@ void LauncherDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
editGame(item);
break;
case kLoadGameCmd:
- loadGameButtonPressed(item);
+ loadGame(item);
break;
+#ifdef ENABLE_EVENTRECORDER
+ case kRecordGameCmd:
+ recordGame(item);
+ break;
+#endif
case kOptionsCmd: {
GlobalOptionsDialog options(this);
options.runModal();
@@ -717,28 +713,8 @@ void LauncherDialog::updateButtons() {
_loadButton->setEnabled(en);
_loadButton->markAsDirty();
}
- switchButtonsText(_addButton, "~A~dd Game...", _s("Mass Add..."));
-#ifdef ENABLE_EVENTRECORDER
- switchButtonsText(_loadButton, "~L~oad...", _s("Record..."));
-#endif
}
-// Update the label of the button depending on whether shift is pressed or not
-void LauncherDialog::switchButtonsText(ButtonWidget *button, const char *normalText, const char *shiftedText) {
- const bool shiftPressed = checkModifier(Common::KBD_SHIFT);
- const bool lowRes = g_system->getOverlayWidth() <= 320;
-
- const char *newAddButtonLabel = shiftPressed
- ? (lowRes ? _c(shiftedText, "lowres") : _(shiftedText))
- : (lowRes ? _c(normalText, "lowres") : _(normalText));
-
- if (button->getLabel() != newAddButtonLabel)
- button->setLabel(newAddButtonLabel);
-}
-
-
-
-
void LauncherDialog::reflowLayout() {
#ifndef DISABLE_FANCY_THEMES
if (g_gui.xmlEval()->getVar("Globals.ShowLauncherLogo") == 1 && g_gui.theme()->supportsImages()) {
diff --git a/gui/launcher.h b/gui/launcher.h
index 5bb386f9a0..7009b993f2 100644
--- a/gui/launcher.h
+++ b/gui/launcher.h
@@ -82,7 +82,6 @@ protected:
void updateListing();
void updateButtons();
- void switchButtonsText(ButtonWidget *button, const char *normalText, const char *shiftedText);
void build();
void clean();
@@ -94,6 +93,7 @@ protected:
* Handle "Add game..." button.
*/
virtual void addGame();
+ void massAddGame();
/**
* Handle "Remove game..." button.
@@ -106,11 +106,6 @@ protected:
void editGame(int item);
/**
- * Facade for "Load..."/"Record..." buttons.
- */
- void loadGameButtonPressed(int item);
-
- /**
* Handle "Record..." button.
*/
void recordGame(int item);
diff --git a/gui/options.cpp b/gui/options.cpp
index a324ef6338..161742d9bc 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -2154,22 +2154,24 @@ void GlobalOptionsDialog::apply() {
}
#ifdef USE_TTS
Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
- if (newLang != oldLang) {
- if (newLang == "C")
- ttsMan->setLanguage("en");
- else {
- ttsMan->setLanguage(newLang);
+ if (ttsMan) {
+ if (newLang != oldLang) {
+ if (newLang == "C")
+ ttsMan->setLanguage("en");
+ else {
+ ttsMan->setLanguage(newLang);
+ }
+ _ttsVoiceSelectionPopUp->setSelectedTag(0);
}
- _ttsVoiceSelectionPopUp->setSelectedTag(0);
+ int volume = (ConfMan.getInt("speech_volume", "scummvm") * 100) / 256;
+ if (ConfMan.hasKey("mute", "scummvm") && ConfMan.getBool("mute", "scummvm"))
+ volume = 0;
+ ttsMan->setVolume(volume);
+ ConfMan.setBool("tts_enabled", _ttsCheckbox->getState(), _domain);
+ int selectedVoice = _ttsVoiceSelectionPopUp->getSelectedTag();
+ ConfMan.setInt("tts_voice", selectedVoice, _domain);
+ ttsMan->setVoice(selectedVoice);
}
- int volume = (ConfMan.getInt("speech_volume", "scummvm") * 100) / 256;
- if (ConfMan.hasKey("mute", "scummvm") && ConfMan.getBool("mute", "scummvm"))
- volume = 0;
- ttsMan->setVolume(volume);
- ConfMan.setBool("tts_enabled", _ttsCheckbox->getState(), _domain);
- int selectedVoice = _ttsVoiceSelectionPopUp->getSelectedTag();
- ConfMan.setInt("tts_voice", selectedVoice, _domain);
- ttsMan->setVoice(selectedVoice);
#endif
if (isRebuildNeeded) {
diff --git a/gui/themes/default.inc b/gui/themes/default.inc
index 3e09b49851..9b6b102c23 100644
--- a/gui/themes/default.inc
+++ b/gui/themes/default.inc
@@ -17,6 +17,9 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
"<color name='green2' "
"rgb='0,255,0' "
"/>"
+"<color name='white' "
+"rgb='255,255,255' "
+"/>"
"</palette>"
"<fonts>"
"<font id='text_default' "
@@ -62,7 +65,7 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
"color='lightgrey' "
"/>"
"<text_color id='color_alternative_inverted' "
-"color='255,255,255' "
+"color='white' "
"/>"
"<text_color id='color_alternative_hover' "
"color='176,176,176' "
@@ -508,6 +511,302 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
"fill='none' "
"/>"
"</drawdata>"
+"<drawdata id='dropdown_button_idle' cache='false' resolution='y>399'>"
+"<text font='text_button' "
+"text_color='color_button' "
+"vertical_align='center' "
+"horizontal_align='center' "
+"/>"
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
+"/>"
+"<drawstep func='triangle' "
+"fg_color='green' "
+"fill='foreground' "
+"width='8' "
+"height='6' "
+"xpos='right' "
+"ypos='center' "
+"padding='0,0,4,0' "
+"orientation='bottom' "
+"/>"
+"<drawstep func='line' "
+"fg_color='lightgrey' "
+"stroke='2' "
+"fill='foreground' "
+"width='0' "
+"height='auto' "
+"xpos='right' "
+"ypos='center' "
+"padding='0,0,17,1' "
+"/>"
+"</drawdata>"
+"<drawdata id='dropdown_button_idle' cache='false' resolution='y<400'>"
+"<text font='text_button' "
+"text_color='color_button' "
+"vertical_align='center' "
+"horizontal_align='center' "
+"/>"
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
+"/>"
+"<drawstep func='triangle' "
+"fg_color='green' "
+"fill='foreground' "
+"width='6' "
+"height='6' "
+"xpos='right' "
+"ypos='center' "
+"padding='0,0,0,0' "
+"orientation='bottom' "
+"/>"
+"</drawdata>"
+"<drawdata id='dropdown_button_hover_left' cache='false' resolution='y>399'>"
+"<text font='text_button' "
+"text_color='color_button_hover' "
+"vertical_align='center' "
+"horizontal_align='center' "
+"/>"
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
+"/>"
+"<drawstep func='triangle' "
+"fg_color='green' "
+"fill='foreground' "
+"width='8' "
+"height='6' "
+"xpos='right' "
+"ypos='center' "
+"padding='0,0,4,0' "
+"orientation='bottom' "
+"/>"
+"<drawstep func='line' "
+"fg_color='lightgrey' "
+"stroke='2' "
+"fill='foreground' "
+"width='0' "
+"height='auto' "
+"xpos='right' "
+"ypos='center' "
+"padding='0,0,17,1' "
+"/>"
+"</drawdata>"
+"<drawdata id='dropdown_button_hover_left' cache='false' resolution='y<400'>"
+"<text font='text_button' "
+"text_color='color_button_hover' "
+"vertical_align='center' "
+"horizontal_align='center' "
+"/>"
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
+"/>"
+"<drawstep func='triangle' "
+"fg_color='green' "
+"fill='foreground' "
+"width='6' "
+"height='6' "
+"xpos='right' "
+"ypos='center' "
+"padding='0,0,0,0' "
+"orientation='bottom' "
+"/>"
+"</drawdata>"
+"<drawdata id='dropdown_button_hover_right' cache='false' resolution='y>399'>"
+"<text font='text_button' "
+"text_color='color_button' "
+"vertical_align='center' "
+"horizontal_align='center' "
+"/>"
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
+"/>"
+"<drawstep func='triangle' "
+"fg_color='green2' "
+"fill='foreground' "
+"width='8' "
+"height='6' "
+"xpos='right' "
+"ypos='center' "
+"padding='0,0,4,0' "
+"orientation='bottom' "
+"/>"
+"<drawstep func='line' "
+"fg_color='lightgrey' "
+"stroke='2' "
+"fill='foreground' "
+"width='0' "
+"height='auto' "
+"xpos='right' "
+"ypos='center' "
+"padding='0,0,17,1' "
+"/>"
+"</drawdata>"
+"<drawdata id='dropdown_button_hover_right' cache='false' resolution='y<400'>"
+"<text font='text_button' "
+"text_color='color_button' "
+"vertical_align='center' "
+"horizontal_align='center' "
+"/>"
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
+"/>"
+"<drawstep func='triangle' "
+"fg_color='green2' "
+"fill='foreground' "
+"width='6' "
+"height='6' "
+"xpos='right' "
+"ypos='center' "
+"padding='0,0,0,0' "
+"orientation='bottom' "
+"/>"
+"</drawdata>"
+"<drawdata id='dropdown_button_disabled' cache='false' resolution='y>399'>"
+"<text font='text_button' "
+"text_color='color_button_disabled' "
+"vertical_align='center' "
+"horizontal_align='center' "
+"/>"
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
+"/>"
+"<drawstep func='triangle' "
+"fg_color='lightgrey' "
+"fill='foreground' "
+"width='8' "
+"height='6' "
+"xpos='right' "
+"ypos='center' "
+"padding='0,0,4,0' "
+"orientation='bottom' "
+"/>"
+"<drawstep func='line' "
+"fg_color='lightgrey' "
+"stroke='2' "
+"fill='foreground' "
+"width='0' "
+"height='auto' "
+"xpos='right' "
+"ypos='center' "
+"padding='0,0,17,1' "
+"/>"
+"</drawdata>"
+"<drawdata id='dropdown_button_disabled' cache='false' resolution='y<400'>"
+"<text font='text_button' "
+"text_color='color_button_disabled' "
+"vertical_align='center' "
+"horizontal_align='center' "
+"/>"
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
+"/>"
+"<drawstep func='triangle' "
+"fg_color='lightgrey' "
+"fill='foreground' "
+"width='6' "
+"height='6' "
+"xpos='right' "
+"ypos='center' "
+"padding='0,0,0,0' "
+"orientation='bottom' "
+"/>"
+"</drawdata>"
+"<drawdata id='dropdown_button_pressed_left' cache='false' resolution='y>399'>"
+"<text font='text_button' "
+"text_color='color_alternative_inverted' "
+"vertical_align='center' "
+"horizontal_align='center' "
+"/>"
+"<drawstep func='square' "
+"fill='foreground' "
+"fg_color='green' "
+"clip='0,0,-18,0' "
+"/>"
+"<drawstep func='triangle' "
+"fg_color='green' "
+"fill='foreground' "
+"width='8' "
+"height='6' "
+"xpos='right' "
+"ypos='center' "
+"padding='0,0,4,0' "
+"orientation='bottom' "
+"/>"
+"</drawdata>"
+"<drawdata id='dropdown_button_pressed_left' cache='false' resolution='y<400'>"
+"<text font='text_button' "
+"text_color='color_alternative_inverted' "
+"vertical_align='center' "
+"horizontal_align='center' "
+"/>"
+"<drawstep func='square' "
+"fill='foreground' "
+"fg_color='green' "
+"clip='0,0,-7,0' "
+"/>"
+"<drawstep func='triangle' "
+"fg_color='green' "
+"fill='foreground' "
+"width='6' "
+"height='6' "
+"xpos='right' "
+"ypos='center' "
+"padding='0,0,0,0' "
+"orientation='bottom' "
+"/>"
+"</drawdata>"
+"<drawdata id='dropdown_button_pressed_right' cache='false' resolution='y>399'>"
+"<text font='text_button' "
+"text_color='color_button' "
+"vertical_align='center' "
+"horizontal_align='center' "
+"/>"
+"<drawstep func='square' "
+"fill='foreground' "
+"fg_color='green' "
+"clip='-16,0,0,0' "
+"/>"
+"<drawstep func='triangle' "
+"fg_color='white' "
+"fill='foreground' "
+"width='8' "
+"height='6' "
+"xpos='right' "
+"ypos='center' "
+"padding='0,0,4,0' "
+"orientation='bottom' "
+"/>"
+"</drawdata>"
+"<drawdata id='dropdown_button_pressed_right' cache='false' resolution='y<400'>"
+"<text font='text_button' "
+"text_color='color_button' "
+"vertical_align='center' "
+"horizontal_align='center' "
+"/>"
+"<drawstep func='square' "
+"fill='foreground' "
+"fg_color='green' "
+"clip='-7,0,0,0' "
+"/>"
+"<drawstep func='triangle' "
+"fg_color='white' "
+"fill='foreground' "
+"width='6' "
+"height='6' "
+"xpos='right' "
+"ypos='center' "
+"padding='0,0,0,0' "
+"orientation='bottom' "
+"/>"
+"</drawdata>"
"<drawdata id='checkbox_disabled' cache='false'>"
"<text font='text_default' "
"text_color='color_normal_disabled' "
@@ -637,6 +936,7 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
"<def var='Tooltip.YDelta' value='16'/>"
"<def var='Predictive.Button.Width' value='60' />"
"<def var='Predictive.ShowDeletePic' value='0'/>"
+"<def var='DropdownButton.Width' value='17'/>"
"<widget name='OptionsLabel' "
"size='110,Globals.Line.Height' "
"textalign='right' "
@@ -2339,6 +2639,8 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
"</layout>"
"</layout>"
"</dialog>"
+"<dialog name='DropdownDialog' overlays='screen_center' shading='luminance'>"
+"</dialog>"
"</layout_info>"
;
const char *defaultXML4 = "<layout_info resolution='y<400'>"
@@ -2364,6 +2666,7 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
"<def var='Predictive.Button.Width' value='45' />"
"<def var='Predictive.Button.Height' value='15' />"
"<def var='Predictive.ShowDeletePic' value='0'/>"
+"<def var='DropdownButton.Width' value='7'/>"
"<widget name='Button' "
"size='72,16' "
"/>"
@@ -4034,6 +4337,8 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
"</layout>"
"</layout>"
"</dialog>"
+"<dialog name='DropdownDialog' overlays='screen_center' shading='luminance'>"
+"</dialog>"
"</layout_info>"
;
const char *defaultXML[] = { defaultXML1, defaultXML2, defaultXML3, defaultXML4 };
diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip
index b59e9b0cc7..eb43825106 100644
--- a/gui/themes/scummclassic.zip
+++ b/gui/themes/scummclassic.zip
Binary files differ
diff --git a/gui/themes/scummclassic/classic_gfx.stx b/gui/themes/scummclassic/classic_gfx.stx
index 8b72802ef7..a5fa994e89 100644
--- a/gui/themes/scummclassic/classic_gfx.stx
+++ b/gui/themes/scummclassic/classic_gfx.stx
@@ -37,6 +37,9 @@
<color name = 'green2'
rgb = '0, 255, 0'
/>
+ <color name = 'white'
+ rgb = '255, 255, 255'
+ />
</palette>
<fonts>
@@ -89,7 +92,7 @@
/>
<text_color id = 'color_alternative_inverted'
- color = '255, 255, 255'
+ color = 'white'
/>
<text_color id = 'color_alternative_hover'
@@ -593,6 +596,308 @@
/>
</drawdata>
+ <drawdata id = 'dropdown_button_idle' cache = 'false' resolution = 'y>399'>
+ <text font = 'text_button'
+ text_color = 'color_button'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'bevelsq'
+ bevel = '2'
+ fill = 'none'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'green'
+ fill = 'foreground'
+ width = '8'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,4,0'
+ orientation = 'bottom'
+ />
+ <drawstep func = 'line'
+ fg_color = 'lightgrey'
+ stroke = '2'
+ fill = 'foreground'
+ width = '0'
+ height = 'auto'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,17,1'
+ />
+ </drawdata>
+ <drawdata id = 'dropdown_button_idle' cache = 'false' resolution = 'y<400'>
+ <text font = 'text_button'
+ text_color = 'color_button'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'bevelsq'
+ bevel = '2'
+ fill = 'none'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'green'
+ fill = 'foreground'
+ width = '6'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,0,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+
+ <drawdata id = 'dropdown_button_hover_left' cache = 'false' resolution = 'y>399'>
+ <text font = 'text_button'
+ text_color = 'color_button_hover'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'bevelsq'
+ bevel = '2'
+ fill = 'none'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'green'
+ fill = 'foreground'
+ width = '8'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,4,0'
+ orientation = 'bottom'
+ />
+ <drawstep func = 'line'
+ fg_color = 'lightgrey'
+ stroke = '2'
+ fill = 'foreground'
+ width = '0'
+ height = 'auto'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,17,1'
+ />
+ </drawdata>
+ <drawdata id = 'dropdown_button_hover_left' cache = 'false' resolution = 'y<400'>
+ <text font = 'text_button'
+ text_color = 'color_button_hover'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'bevelsq'
+ bevel = '2'
+ fill = 'none'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'green'
+ fill = 'foreground'
+ width = '6'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,0,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+
+ <drawdata id = 'dropdown_button_hover_right' cache = 'false' resolution = 'y>399'>
+ <text font = 'text_button'
+ text_color = 'color_button'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'bevelsq'
+ bevel = '2'
+ fill = 'none'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'green2'
+ fill = 'foreground'
+ width = '8'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,4,0'
+ orientation = 'bottom'
+ />
+ <drawstep func = 'line'
+ fg_color = 'lightgrey'
+ stroke = '2'
+ fill = 'foreground'
+ width = '0'
+ height = 'auto'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,17,1'
+ />
+ </drawdata>
+ <drawdata id = 'dropdown_button_hover_right' cache = 'false' resolution = 'y<400'>
+ <text font = 'text_button'
+ text_color = 'color_button'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'bevelsq'
+ bevel = '2'
+ fill = 'none'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'green2'
+ fill = 'foreground'
+ width = '6'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,0,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+
+ <drawdata id = 'dropdown_button_disabled' cache = 'false' resolution = 'y>399'>
+ <text font = 'text_button'
+ text_color = 'color_button_disabled'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'bevelsq'
+ bevel = '2'
+ fill = 'none'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'lightgrey'
+ fill = 'foreground'
+ width = '8'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,4,0'
+ orientation = 'bottom'
+ />
+ <drawstep func = 'line'
+ fg_color = 'lightgrey'
+ stroke = '2'
+ fill = 'foreground'
+ width = '0'
+ height = 'auto'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,17,1'
+ />
+ </drawdata>
+ <drawdata id = 'dropdown_button_disabled' cache = 'false' resolution = 'y<400'>
+ <text font = 'text_button'
+ text_color = 'color_button_disabled'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'bevelsq'
+ bevel = '2'
+ fill = 'none'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'lightgrey'
+ fill = 'foreground'
+ width = '6'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,0,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+
+ <drawdata id = 'dropdown_button_pressed_left' cache = 'false' resolution = 'y>399'>
+ <text font = 'text_button'
+ text_color = 'color_alternative_inverted'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'square'
+ fill = 'foreground'
+ fg_color = 'green'
+ clip = '0,0,-18,0'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'green'
+ fill = 'foreground'
+ width = '8'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,4,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+ <drawdata id = 'dropdown_button_pressed_left' cache = 'false' resolution = 'y<400'>
+ <text font = 'text_button'
+ text_color = 'color_alternative_inverted'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'square'
+ fill = 'foreground'
+ fg_color = 'green'
+ clip = '0,0,-7,0'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'green'
+ fill = 'foreground'
+ width = '6'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,0,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+
+ <drawdata id = 'dropdown_button_pressed_right' cache = 'false' resolution = 'y>399'>
+ <text font = 'text_button'
+ text_color = 'color_button'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'square'
+ fill = 'foreground'
+ fg_color = 'green'
+ clip = '-16,0,0,0'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'white'
+ fill = 'foreground'
+ width = '8'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,4,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+ <drawdata id = 'dropdown_button_pressed_right' cache = 'false' resolution = 'y<400'>
+ <text font = 'text_button'
+ text_color = 'color_button'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'square'
+ fill = 'foreground'
+ fg_color = 'green'
+ clip = '-7,0,0,0'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'white'
+ fill = 'foreground'
+ width = '6'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,0,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+
<drawdata id = 'checkbox_disabled' cache = 'false'>
<text font = 'text_default'
text_color = 'color_normal_disabled'
diff --git a/gui/themes/scummclassic/classic_layout.stx b/gui/themes/scummclassic/classic_layout.stx
index 84bd056d9d..66fab1d7a1 100644
--- a/gui/themes/scummclassic/classic_layout.stx
+++ b/gui/themes/scummclassic/classic_layout.stx
@@ -51,6 +51,8 @@
<def var = 'Predictive.Button.Width' value = '60' />
<def var = 'Predictive.ShowDeletePic' value = '0'/>
+ <def var = 'DropdownButton.Width' value = '17'/>
+
<widget name = 'OptionsLabel'
size = '110, Globals.Line.Height'
textalign = 'right'
@@ -1807,4 +1809,6 @@
</layout>
</layout>
</dialog>
+ <dialog name = 'DropdownDialog' overlays = 'screen_center' shading = 'luminance'>
+ </dialog>
</layout_info>
diff --git a/gui/themes/scummclassic/classic_layout_lowres.stx b/gui/themes/scummclassic/classic_layout_lowres.stx
index e1d90fff50..e65e3d2ca7 100644
--- a/gui/themes/scummclassic/classic_layout_lowres.stx
+++ b/gui/themes/scummclassic/classic_layout_lowres.stx
@@ -53,6 +53,8 @@
<def var = 'Predictive.Button.Height' value = '15' />
<def var = 'Predictive.ShowDeletePic' value = '0'/>
+ <def var = 'DropdownButton.Width' value = '7'/>
+
<widget name = 'Button'
size = '72, 16'
/>
@@ -1775,4 +1777,6 @@
</layout>
</layout>
</dialog>
+ <dialog name = 'DropdownDialog' overlays = 'screen_center' shading = 'luminance'>
+ </dialog>
</layout_info>
diff --git a/gui/themes/scummmodern.zip b/gui/themes/scummmodern.zip
index 75064465e4..f7a69004d3 100644
--- a/gui/themes/scummmodern.zip
+++ b/gui/themes/scummmodern.zip
Binary files differ
diff --git a/gui/themes/scummmodern/scummmodern_gfx.stx b/gui/themes/scummmodern/scummmodern_gfx.stx
index 0e62f36627..c449c1a30e 100644
--- a/gui/themes/scummmodern/scummmodern_gfx.stx
+++ b/gui/themes/scummmodern/scummmodern_gfx.stx
@@ -86,6 +86,9 @@
<color name = 'darkgray'
rgb = '176, 168, 144'
/>
+ <color name = 'darkgray2'
+ rgb = '192, 192, 192'
+ />
<color name = 'lightgray'
rgb = '210, 200, 170'
/>
@@ -208,7 +211,7 @@
/>
<text_color id = 'color_alternative_disabled'
- color = '192, 192, 192'
+ color = 'darkgray2'
/>
<text_color id = 'color_button'
@@ -216,7 +219,7 @@
/>
<text_color id = 'color_button_disabled'
- color = '192, 192, 192'
+ color = 'darkgray2'
/>
</fonts>
@@ -856,6 +859,361 @@
/>
</drawdata>
+ <!-- Dropdown button widget -->
+ <drawdata id = 'dropdown_button_idle' cache = 'false' resolution = 'y>399'>
+ <text font = 'text_button'
+ text_color = 'color_button'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'roundedsq'
+ radius = '5'
+ stroke = '1'
+ fill = 'gradient'
+ shadow = '0'
+ fg_color = 'darkredborder'
+ gradient_start = 'brightred'
+ gradient_end = 'darkred'
+ bevel = '1'
+ bevel_color = 'brightredborder'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'white'
+ fill = 'foreground'
+ width = '8'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,2,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+ <drawdata id = 'dropdown_button_idle' cache = 'false' resolution = 'y<400'>
+ <text font = 'text_button'
+ text_color = 'color_button'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'roundedsq'
+ radius = '5'
+ stroke = '1'
+ fill = 'gradient'
+ shadow = '0'
+ fg_color = 'darkredborder'
+ gradient_start = 'brightred'
+ gradient_end = 'darkred'
+ bevel = '1'
+ bevel_color = 'brightredborder'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'white'
+ fill = 'foreground'
+ width = '6'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,0,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+
+ <drawdata id = 'dropdown_button_hover_left' cache = 'false' resolution = 'y>399'>
+ <text font = 'text_button'
+ text_color = 'color_button'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'roundedsq'
+ radius = '5'
+ stroke = '1'
+ fill = 'gradient'
+ shadow = '0'
+ fg_color = 'darkredborder'
+ gradient_start = 'brightpink'
+ gradient_end = 'darkpink'
+ bevel = '1'
+ bevel_color = 'brightredborder'
+ clip = '0,0,-13,0'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'white'
+ fill = 'foreground'
+ width = '8'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,2,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+ <drawdata id = 'dropdown_button_hover_left' cache = 'false' resolution = 'y<400'>
+ <text font = 'text_button'
+ text_color = 'color_button'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'roundedsq'
+ radius = '5'
+ stroke = '1'
+ fill = 'gradient'
+ shadow = '0'
+ fg_color = 'darkredborder'
+ gradient_start = 'brightpink'
+ gradient_end = 'darkpink'
+ bevel = '1'
+ bevel_color = 'brightredborder'
+ clip = '0,0,-7,0'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'white'
+ fill = 'foreground'
+ width = '6'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,0,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+
+ <drawdata id = 'dropdown_button_hover_right' cache = 'false' resolution = 'y>399'>
+ <text font = 'text_button'
+ text_color = 'color_button'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'roundedsq'
+ radius = '5'
+ stroke = '1'
+ fill = 'gradient'
+ shadow = '0'
+ fg_color = 'darkredborder'
+ gradient_start = 'brightpink'
+ gradient_end = 'darkpink'
+ bevel = '1'
+ bevel_color = 'brightredborder'
+ clip = '-13,0,0,0'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'white'
+ fill = 'foreground'
+ width = '8'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,2,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+ <drawdata id = 'dropdown_button_hover_right' cache = 'false' resolution = 'y<400'>
+ <text font = 'text_button'
+ text_color = 'color_button'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'roundedsq'
+ radius = '5'
+ stroke = '1'
+ fill = 'gradient'
+ shadow = '0'
+ fg_color = 'darkredborder'
+ gradient_start = 'brightpink'
+ gradient_end = 'darkpink'
+ bevel = '1'
+ bevel_color = 'brightredborder'
+ clip = '-7,0,0,0'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'white'
+ fill = 'foreground'
+ width = '6'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,0,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+
+ <drawdata id = 'dropdown_button_disabled' cache = 'false' resolution = 'y>399'>
+ <text font = 'text_button'
+ text_color = 'color_button_disabled'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'roundedsq'
+ radius = '5'
+ stroke = '1'
+ fill = 'gradient'
+ shadow = '0'
+ fg_color = 'shadowcolor'
+ gradient_start = 'darkenedbrightred'
+ gradient_end = 'darkeneddarkred'
+ bevel = '1'
+ bevel_color = 'darkgray'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'darkgray2'
+ fill = 'foreground'
+ width = '8'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,2,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+ <drawdata id = 'dropdown_button_disabled' cache = 'false' resolution = 'y<400'>
+ <text font = 'text_button'
+ text_color = 'color_button_disabled'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'roundedsq'
+ radius = '5'
+ stroke = '1'
+ fill = 'gradient'
+ shadow = '0'
+ fg_color = 'shadowcolor'
+ gradient_start = 'darkenedbrightred'
+ gradient_end = 'darkeneddarkred'
+ bevel = '1'
+ bevel_color = 'darkgray'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'darkgray2'
+ fill = 'foreground'
+ width = '6'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,0,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+
+ <drawdata id = 'dropdown_button_pressed_left' cache = 'false' resolution = 'y>399'>
+ <text font = 'text_button'
+ text_color = 'color_button'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'roundedsq'
+ radius = '5'
+ stroke = '1'
+ fill = 'foreground'
+ shadow = '0'
+ factor = '0'
+ fg_color = '120, 40, 16'
+ gradient_start = '255, 0, 0'
+ gradient_end = '255, 0, 0'
+ bevel = '1'
+ bevel_color = 'black'
+ clip = '0,0,-13,0'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'white'
+ fill = 'foreground'
+ width = '8'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,2,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+ <drawdata id = 'dropdown_button_pressed_left' cache = 'false' resolution = 'y<400'>
+ <text font = 'text_button'
+ text_color = 'color_button'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'roundedsq'
+ radius = '5'
+ stroke = '1'
+ fill = 'foreground'
+ shadow = '0'
+ factor = '0'
+ fg_color = '120, 40, 16'
+ gradient_start = '255, 0, 0'
+ gradient_end = '255, 0, 0'
+ bevel = '1'
+ bevel_color = 'black'
+ clip = '0,0,-7,0'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'white'
+ fill = 'foreground'
+ width = '6'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,0,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+
+ <drawdata id = 'dropdown_button_pressed_right' cache = 'false' resolution = 'y>399'>
+ <text font = 'text_button'
+ text_color = 'color_button'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'roundedsq'
+ radius = '5'
+ stroke = '1'
+ fill = 'foreground'
+ shadow = '0'
+ factor = '0'
+ fg_color = '120, 40, 16'
+ gradient_start = '255, 0, 0'
+ gradient_end = '255, 0, 0'
+ bevel = '1'
+ bevel_color = 'black'
+ clip = '-13,0,0,0'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'white'
+ fill = 'foreground'
+ width = '8'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,2,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+ <drawdata id = 'dropdown_button_pressed_right' cache = 'false' resolution = 'y<400'>
+ <text font = 'text_button'
+ text_color = 'color_button'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'roundedsq'
+ radius = '5'
+ stroke = '1'
+ fill = 'foreground'
+ shadow = '0'
+ factor = '0'
+ fg_color = '120, 40, 16'
+ gradient_start = '255, 0, 0'
+ gradient_end = '255, 0, 0'
+ bevel = '1'
+ bevel_color = 'black'
+ clip = '-7,0,0,0'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'white'
+ fill = 'foreground'
+ width = '6'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,0,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+
<!-- Disabled checkbox -->
<drawdata id = 'checkbox_disabled' cache = 'false'>
<text font = 'text_default'
diff --git a/gui/themes/scummmodern/scummmodern_layout.stx b/gui/themes/scummmodern/scummmodern_layout.stx
index a45dd3edca..dd958ea4a0 100644
--- a/gui/themes/scummmodern/scummmodern_layout.stx
+++ b/gui/themes/scummmodern/scummmodern_layout.stx
@@ -58,6 +58,8 @@
<def var = 'Predictive.Button.Width' value = '60' />
<def var = 'Predictive.ShowDeletePic' value = '1'/>
+ <def var = 'DropdownButton.Width' value = '13'/>
+
<widget name = 'OptionsLabel'
size = '115, Globals.Line.Height'
textalign = 'right'
@@ -75,6 +77,9 @@
<widget name = 'Button'
size = '108, 24'
/>
+ <widget name = 'LauncherButton'
+ size = '130, 24'
+ />
<widget name = 'WideButton'
size = '216, 24'
/>
@@ -160,31 +165,31 @@
<widget name = 'GameList'/>
<layout type = 'vertical' padding = '10, 0, 0, 0'>
<widget name = 'StartButton'
- type = 'Button'
+ type = 'LauncherButton'
/>
<widget name = 'LoadGameButton'
- type = 'Button'
+ type = 'LauncherButton'
/>
<space size = '10' />
<widget name = 'AddGameButton'
- type = 'Button'
+ type = 'LauncherButton'
/>
<widget name = 'EditGameButton'
- type = 'Button'
+ type = 'LauncherButton'
/>
<widget name = 'RemoveGameButton'
- type = 'Button'
+ type = 'LauncherButton'
/>
<space size = '10' />
<widget name = 'OptionsButton'
- type = 'Button'
+ type = 'LauncherButton'
/>
<widget name = 'AboutButton'
- type = 'Button'
+ type = 'LauncherButton'
/>
<space size = '10' />
<widget name = 'QuitButton'
- type = 'Button'
+ type = 'LauncherButton'
/>
</layout>
</layout>
@@ -260,7 +265,7 @@
</layout>
</layout>
</dialog>
-
+
<dialog name = 'GlobalOptions_Control' overlays = 'Dialog.GlobalOptions.TabWidget'>
<layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'>
<widget name = 'grOnScreenCheckbox'
@@ -934,13 +939,12 @@
<layout type='vertical' padding='16,16,16,16' spacing='16'>
<widget name='TTSCheckbox'
type='Checkbox'
- />
+ />
<widget name='TTSVoiceSelection'
type='PopUp'
- />
- </layout>
- </dialog>
-
+ />
+ </layout>
+ </dialog>
<dialog name='KeysDialog' overlays='Dialog.GlobalOptions' shading='dim'>
<layout type='vertical' padding='8,8,8,8' center='true'>
<widget name='Action'
@@ -1821,5 +1825,6 @@
</layout>
</layout>
</dialog>
-
+ <dialog name = 'DropdownDialog' overlays = 'screen_center'>
+ </dialog>
</layout_info>
diff --git a/gui/themes/scummmodern/scummmodern_layout_lowres.stx b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
index 20363bbba0..7324663fee 100644
--- a/gui/themes/scummmodern/scummmodern_layout_lowres.stx
+++ b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
@@ -43,6 +43,8 @@
<def var = 'Predictive.Button.Height' value = '15' />
<def var = 'Predictive.ShowDeletePic' value = '0'/>
+ <def var = 'DropdownButton.Width' value = '7'/>
+
<widget name = 'Button'
size = '72, 16'
/>
@@ -1793,4 +1795,6 @@
</layout>
</layout>
</dialog>
+ <dialog name = 'DropdownDialog' overlays = 'screen_center'>
+ </dialog>
</layout_info>
diff --git a/gui/themes/scummremastered.zip b/gui/themes/scummremastered.zip
index b4f7c0eebb..b9b247c84a 100644
--- a/gui/themes/scummremastered.zip
+++ b/gui/themes/scummremastered.zip
Binary files differ
diff --git a/gui/themes/scummremastered/remastered_gfx.stx b/gui/themes/scummremastered/remastered_gfx.stx
index 76b722c5d5..c18a8bf358 100644
--- a/gui/themes/scummremastered/remastered_gfx.stx
+++ b/gui/themes/scummremastered/remastered_gfx.stx
@@ -36,13 +36,13 @@
rgb = '180, 39, 9'
/>
- <color name = 'button_pressed'
+ <color name = 'button_pressed'
rgb = '190, 39, 9'
/>
- <color name = 'button_disabled'
- rgb = '96, 96, 96'
- />
+ <color name = 'button_disabled'
+ rgb = '96, 96, 96'
+ />
<!-- Dialog background -->
<color name = 'dialog_background'
@@ -57,7 +57,7 @@
rgb = '0, 204, 51'
/>
- <color name = 'paleyellow'
+ <color name = 'paleyellow'
rgb = '247, 228, 166'
/>
@@ -73,6 +73,9 @@
<color name = 'darkgray'
rgb = '176, 168, 144'
/>
+ <color name = 'darkgray2'
+ rgb = '192, 192, 192'
+ />
<color name = 'lightgray'
rgb = '210, 200, 170'
/>
@@ -81,8 +84,8 @@
/>
- <!-- Older/Unused? -->
- <color name = 'brightredborder'
+ <!-- Older/Unused? -->
+ <color name = 'brightredborder'
rgb = '238, 213, 207'
/>
@@ -128,7 +131,7 @@
scalable_file = 'FreeSansBold.ttf'
/>
<font resolution = 'y<400'
- id = 'text_default'
+ id = 'text_default'
file = 'clR6x12.bdf'
scalable_file = 'FreeSans.ttf'
point_size = '11'
@@ -138,7 +141,7 @@
scalable_file = 'FreeSansBold.ttf'
/>
<font resolution = 'y<400'
- id = 'text_button'
+ id = 'text_button'
file = 'clR6x12.bdf'
scalable_file = 'FreeSans.ttf'
point_size = '11'
@@ -148,7 +151,7 @@
scalable_file = 'FreeSans.ttf'
/>
<font resolution = 'y<400'
- id = 'text_normal'
+ id = 'text_normal'
file = 'clR6x12.bdf'
scalable_file = 'FreeSans.ttf'
point_size = '11'
@@ -209,7 +212,7 @@
/>
<text_color id = 'color_alternative_disabled'
- color = '192, 192, 192'
+ color = 'darkgray2'
/>
<text_color id = 'color_button'
@@ -217,7 +220,7 @@
/>
<text_color id = 'color_button_disabled'
- color = '192, 192, 192'
+ color = 'darkgray2'
/>
</fonts>
@@ -287,7 +290,7 @@
stroke = '1'
radius = '10'
fill = 'gradient'
- fg_color = 'blandyellow'
+ fg_color = 'blandyellow'
gradient_start = 'button_hover'
gradient_end = 'button_hover'
/>
@@ -298,7 +301,7 @@
stroke = '1'
radius = '10'
fill = 'gradient'
- fg_color = 'blandyellow'
+ fg_color = 'blandyellow'
gradient_start = 'button_idle'
gradient_end = 'button_idle'
/>
@@ -807,7 +810,7 @@
fill = 'background'
shadow = '2'
fg_color = 'darkredborder'
- bg_color = 'button_idle'
+ bg_color = 'button_idle'
bevel = '0'
bevel_color = 'brightredborder'
/>
@@ -826,7 +829,7 @@
fill = 'background'
shadow = '2'
fg_color = 'darkredborder'
- bg_color = 'button_hover'
+ bg_color = 'button_hover'
bevel = '0'
bevel_color = 'brightredborder'
/>
@@ -852,6 +855,287 @@
/>
</drawdata>
+ <!-- Dropdown button widget -->
+ <drawdata id = 'dropdown_button_idle' cache = 'false' resolution = 'y>399'>
+ <text font = 'text_button'
+ text_color = 'color_button'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'roundedsq'
+ radius = '5'
+ fill = 'foreground'
+ shadow = '2'
+ fg_color = 'button_idle'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'white'
+ fill = 'foreground'
+ width = '8'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,2,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+ <drawdata id = 'dropdown_button_idle' cache = 'false' resolution = 'y<400'>
+ <text font = 'text_button'
+ text_color = 'color_button'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'roundedsq'
+ radius = '5'
+ fill = 'foreground'
+ shadow = '2'
+ fg_color = 'button_idle'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'white'
+ fill = 'foreground'
+ width = '6'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,0,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+
+ <drawdata id = 'dropdown_button_hover_left' cache = 'false' resolution = 'y>399'>
+ <text font = 'text_button'
+ text_color = 'color_button'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'roundedsq'
+ radius = '5'
+ fill = 'foreground'
+ fg_color = 'button_hover'
+ clip = '0,0,-13,0'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'white'
+ fill = 'foreground'
+ width = '8'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,2,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+ <drawdata id = 'dropdown_button_hover_left' cache = 'false' resolution = 'y<400'>
+ <text font = 'text_button'
+ text_color = 'color_button'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'roundedsq'
+ radius = '5'
+ fill = 'foreground'
+ fg_color = 'button_hover'
+ clip = '0,0,-7,0'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'white'
+ fill = 'foreground'
+ width = '6'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,0,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+
+ <drawdata id = 'dropdown_button_hover_right' cache = 'false' resolution = 'y>399'>
+ <text font = 'text_button'
+ text_color = 'color_button'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'roundedsq'
+ radius = '5'
+ fill = 'foreground'
+ fg_color = 'button_hover'
+ clip = '-13,0,0,0'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'white'
+ fill = 'foreground'
+ width = '8'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,2,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+ <drawdata id = 'dropdown_button_hover_right' cache = 'false' resolution = 'y<400'>
+ <text font = 'text_button'
+ text_color = 'color_button'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'roundedsq'
+ radius = '5'
+ fill = 'foreground'
+ fg_color = 'button_hover'
+ clip = '-7,0,0,0'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'white'
+ fill = 'foreground'
+ width = '6'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,0,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+
+ <drawdata id = 'dropdown_button_disabled' cache = 'false' resolution = 'y>399'>
+ <text font = 'text_button'
+ text_color = 'color_button_disabled'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'roundedsq'
+ radius = '5'
+ fill = 'foreground'
+ fg_color = 'button_disabled'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'darkgray2'
+ fill = 'foreground'
+ width = '8'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,2,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+ <drawdata id = 'dropdown_button_disabled' cache = 'false' resolution = 'y<400'>
+ <text font = 'text_button'
+ text_color = 'color_button_disabled'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'roundedsq'
+ radius = '5'
+ fill = 'foreground'
+ fg_color = 'button_disabled'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'darkgray2'
+ fill = 'foreground'
+ width = '6'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,0,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+
+ <drawdata id = 'dropdown_button_pressed_left' cache = 'false' resolution = 'y>399'>
+ <text font = 'text_button'
+ text_color = 'color_button'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'roundedsq'
+ radius = '5'
+ fill = 'foreground'
+ fg_color = 'button_pressed'
+ clip = '0,0,-13,0'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'white'
+ fill = 'foreground'
+ width = '8'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,2,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+ <drawdata id = 'dropdown_button_pressed_left' cache = 'false' resolution = 'y<400'>
+ <text font = 'text_button'
+ text_color = 'color_button'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'roundedsq'
+ radius = '5'
+ fill = 'foreground'
+ fg_color = 'button_pressed'
+ clip = '0,0,-7,0'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'white'
+ fill = 'foreground'
+ width = '6'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,0,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+
+ <drawdata id = 'dropdown_button_pressed_right' cache = 'false' resolution = 'y>399'>
+ <text font = 'text_button'
+ text_color = 'color_button'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'roundedsq'
+ radius = '5'
+ fill = 'foreground'
+ fg_color = 'button_pressed'
+ clip = '-13,0,0,0'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'white'
+ fill = 'foreground'
+ width = '8'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,2,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+ <drawdata id = 'dropdown_button_pressed_right' cache = 'false' resolution = 'y<400'>
+ <text font = 'text_button'
+ text_color = 'color_button'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'roundedsq'
+ radius = '5'
+ fill = 'foreground'
+ fg_color = 'button_pressed'
+ clip = '-7,0,0,0'
+ />
+ <drawstep func = 'triangle'
+ fg_color = 'white'
+ fill = 'foreground'
+ width = '6'
+ height = '6'
+ xpos = 'right'
+ ypos = 'center'
+ padding = '0,0,0,0'
+ orientation = 'bottom'
+ />
+ </drawdata>
+
<!-- Disabled checkbox -->
<drawdata id = 'checkbox_disabled' cache = 'false'>
<text font = 'text_default'
diff --git a/gui/themes/scummremastered/remastered_layout.stx b/gui/themes/scummremastered/remastered_layout.stx
index 092bbc0134..3d5587ed4b 100644
--- a/gui/themes/scummremastered/remastered_layout.stx
+++ b/gui/themes/scummremastered/remastered_layout.stx
@@ -58,6 +58,8 @@
<def var = 'Predictive.Button.Width' value = '60' />
<def var = 'Predictive.ShowDeletePic' value = '1'/>
+ <def var = 'DropdownButton.Width' value = '13'/>
+
<widget name = 'OptionsLabel'
size = '115, Globals.Line.Height'
textalign = 'right'
@@ -75,6 +77,9 @@
<widget name = 'Button'
size = '108, 24'
/>
+ <widget name = 'LauncherButton'
+ size = '130, 24'
+ />
<widget name = 'WideButton'
size = '216, 24'
/>
@@ -160,31 +165,31 @@
<widget name = 'GameList'/>
<layout type = 'vertical' padding = '10, 0, 0, 0'>
<widget name = 'StartButton'
- type = 'Button'
+ type = 'LauncherButton'
/>
<widget name = 'LoadGameButton'
- type = 'Button'
+ type = 'LauncherButton'
/>
<space size = '10' />
<widget name = 'AddGameButton'
- type = 'Button'
+ type = 'LauncherButton'
/>
<widget name = 'EditGameButton'
- type = 'Button'
+ type = 'LauncherButton'
/>
<widget name = 'RemoveGameButton'
- type = 'Button'
+ type = 'LauncherButton'
/>
<space size = '10' />
<widget name = 'OptionsButton'
- type = 'Button'
+ type = 'LauncherButton'
/>
<widget name = 'AboutButton'
- type = 'Button'
+ type = 'LauncherButton'
/>
<space size = '10' />
<widget name = 'QuitButton'
- type = 'Button'
+ type = 'LauncherButton'
/>
</layout>
</layout>
@@ -1820,5 +1825,6 @@
</layout>
</layout>
</dialog>
-
+ <dialog name = 'DropdownDialog' overlays = 'screen_center'>
+ </dialog>
</layout_info>
diff --git a/gui/themes/scummremastered/remastered_layout_lowres.stx b/gui/themes/scummremastered/remastered_layout_lowres.stx
index 3f8ec01a28..2a20442468 100644
--- a/gui/themes/scummremastered/remastered_layout_lowres.stx
+++ b/gui/themes/scummremastered/remastered_layout_lowres.stx
@@ -43,6 +43,8 @@
<def var = 'Predictive.Button.Height' value = '15' />
<def var = 'Predictive.ShowDeletePic' value = '0'/>
+ <def var = 'DropdownButton.Width' value = '7'/>
+
<widget name = 'Button'
size = '72, 16'
/>
@@ -1793,4 +1795,6 @@
</layout>
</layout>
</dialog>
+ <dialog name = 'DropdownDialog' overlays = 'screen_center'>
+ </dialog>
</layout_info>
diff --git a/gui/widget.cpp b/gui/widget.cpp
index 750fa4e80f..bbb8b06ee6 100644
--- a/gui/widget.cpp
+++ b/gui/widget.cpp
@@ -32,6 +32,7 @@
#include "gui/ThemeEval.h"
#include "gui/dialog.h"
+#include "gui/widgets/popup.h"
namespace GUI {
@@ -322,7 +323,7 @@ void StaticTextWidget::drawWidget() {
ButtonWidget::ButtonWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, const char *tooltip, uint32 cmd, uint8 hotkey)
: StaticTextWidget(boss, x, y, w, h, cleanupHotkey(label), Graphics::kTextAlignCenter, tooltip), CommandSender(boss),
- _cmd(cmd), _hotkey(hotkey), _lastTime(0), _duringPress(false) {
+ _cmd(cmd), _hotkey(hotkey), _duringPress(false) {
if (hotkey == 0)
_hotkey = parseHotkey(label);
@@ -333,7 +334,7 @@ ButtonWidget::ButtonWidget(GuiObject *boss, int x, int y, int w, int h, const Co
ButtonWidget::ButtonWidget(GuiObject *boss, const Common::String &name, const Common::String &label, const char *tooltip, uint32 cmd, uint8 hotkey)
: StaticTextWidget(boss, name, cleanupHotkey(label), tooltip), CommandSender(boss),
- _cmd(cmd), _hotkey(hotkey), _lastTime(0), _duringPress(false) {
+ _cmd(cmd), _hotkey(hotkey), _duringPress(false) {
if (hotkey == 0)
_hotkey = parseHotkey(label);
setFlags(WIDGET_ENABLED/* | WIDGET_BORDER*/ | WIDGET_CLEARBG);
@@ -400,6 +401,104 @@ void ButtonWidget::setUnpressedState() {
#pragma mark -
+DropdownButtonWidget::DropdownButtonWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, const char *tooltip, uint32 cmd, uint8 hotkey) :
+ ButtonWidget(boss, x, y, w, h, label, tooltip, cmd, hotkey) {
+ setFlags(getFlags() | WIDGET_TRACK_MOUSE);
+
+ reset();
+}
+
+DropdownButtonWidget::DropdownButtonWidget(GuiObject *boss, const Common::String &name, const Common::String &label, const char *tooltip, uint32 cmd, uint8 hotkey) :
+ ButtonWidget(boss, name, label, tooltip, cmd, hotkey) {
+ setFlags(getFlags() | WIDGET_TRACK_MOUSE);
+
+ reset();
+}
+
+void DropdownButtonWidget::reset() {
+ _inDropdown = false;
+ _inButton = false;
+ _dropdownWidth = g_gui.xmlEval()->getVar("Globals.DropdownButton.Width", 13);
+}
+
+bool DropdownButtonWidget::isInDropDown(int x, int y) const {
+ Common::Rect dropdownRect(_w - _dropdownWidth, 0, _w, _h);
+ return dropdownRect.contains(x, y);
+}
+
+void DropdownButtonWidget::handleMouseMoved(int x, int y, int button) {
+ if (_entries.empty()) {
+ return;
+ }
+
+ // Detect which part of the button the cursor is over
+ bool inDropdown = isInDropDown(x, y);
+ bool inButton = Common::Rect(_w, _h).contains(x, y) && !inDropdown;
+
+ if (inDropdown != _inDropdown) {
+ _inDropdown = inDropdown;
+ markAsDirty();
+ }
+
+ if (inButton != _inButton) {
+ _inButton = inButton;
+ markAsDirty();
+ }
+}
+
+void DropdownButtonWidget::handleMouseUp(int x, int y, int button, int clickCount) {
+ if (isEnabled() && !_entries.empty() && _duringPress && isInDropDown(x, y)) {
+
+ PopUpDialog popupDialog(this, "DropdownDialog", x + getAbsX(), y + getAbsY());
+ popupDialog.setPosition(getAbsX(), getAbsY() + _h);
+ popupDialog.setLineHeight(_h);
+ popupDialog.setPadding(_dropdownWidth, _dropdownWidth);
+
+ for (uint i = 0; i < _entries.size(); i++) {
+ popupDialog.appendEntry(_entries[i].label);
+ }
+
+ int newSel = popupDialog.runModal();
+ if (newSel != -1) {
+ sendCommand(_entries[newSel].cmd, 0);
+ }
+
+ setUnpressedState();
+ _duringPress = false;
+ } else {
+ ButtonWidget::handleMouseUp(x, y, button, clickCount);
+ }
+}
+
+void DropdownButtonWidget::reflowLayout() {
+ ButtonWidget::reflowLayout();
+
+ reset();
+}
+
+void DropdownButtonWidget::appendEntry(const Common::String &label, uint32 cmd) {
+ Entry e;
+ e.label = label;
+ e.cmd = cmd;
+ _entries.push_back(e);
+}
+
+void DropdownButtonWidget::clearEntries() {
+ _entries.clear();
+}
+
+void DropdownButtonWidget::drawWidget() {
+ if (_entries.empty()) {
+ // Degrade to a regular button
+ g_gui.theme()->drawButton(Common::Rect(_x, _y, _x + _w, _y + _h), _label, _state);
+ } else {
+ g_gui.theme()->drawDropDownButton(Common::Rect(_x, _y, _x + _w, _y + _h), _dropdownWidth, _label,
+ _state, _inButton, _inDropdown);
+ }
+}
+
+#pragma mark -
+
PicButtonWidget::PicButtonWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip, uint32 cmd, uint8 hotkey)
: ButtonWidget(boss, x, y, w, h, "", tooltip, cmd, hotkey),
_alpha(255), _transparency(false), _showButton(true) {
diff --git a/gui/widget.h b/gui/widget.h
index 06df49629d..2339012074 100644
--- a/gui/widget.h
+++ b/gui/widget.h
@@ -234,8 +234,39 @@ public:
protected:
void drawWidget();
bool _duringPress;
-private:
- uint32 _lastTime;
+};
+
+/* DropdownButtonWidget */
+class DropdownButtonWidget : public ButtonWidget {
+public:
+ DropdownButtonWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, const char *tooltip = nullptr, uint32 cmd = 0, uint8 hotkey = 0);
+ DropdownButtonWidget(GuiObject *boss, const Common::String &name, const Common::String &label, const char *tooltip = nullptr, uint32 cmd = 0, uint8 hotkey = 0);
+
+ void handleMouseMoved(int x, int y, int button) override;
+ void handleMouseUp(int x, int y, int button, int clickCount) override;
+ void reflowLayout() override;
+
+ void appendEntry(const Common::String &label, uint32 cmd);
+ void clearEntries();
+
+protected:
+ struct Entry {
+ Common::String label;
+ uint32 cmd;
+ };
+ typedef Common::Array<Entry> EntryList;
+
+ // Widget API
+ void drawWidget() override;
+
+ void reset();
+ bool isInDropDown(int x, int y) const;
+
+ EntryList _entries;
+
+ uint32 _dropdownWidth;
+ bool _inDropdown;
+ bool _inButton;
};
/* PicButtonWidget */
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