diff options
27 files changed, 1785 insertions, 240 deletions
diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index e226e45475..bcab4bf5a2 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -52,13 +52,48 @@ void VectorRenderer::drawStep(const Common::Rect &area, const Common::Rect &clip setGradientFactor(step.factor); setStrokeWidth(step.stroke); setFillMode((FillMode)step.fillMode); - setClippingRect(clip); + setClippingRect(applyStepClippingRect(area, clip, step)); _dynamicData = extra; (this->*(step.drawingCall))(area, step); } +Common::Rect VectorRenderer::applyStepClippingRect(const Common::Rect &area, const Common::Rect &clip, const DrawStep &step) { + if (step.clip == Common::Rect()) { + return clip; + } + + Common::Rect finalClip = clip; + if (step.clip.left > 0) { + finalClip.left = area.left + step.clip.left; + } else if (step.clip.left < 0) { + finalClip.left = area.right + step.clip.left; + } + + if (step.clip.top > 0) { + finalClip.top = area.top + step.clip.top; + } else if (step.clip.top < 0) { + finalClip.top = area.bottom + step.clip.top; + } + + if (step.clip.right > 0) { + finalClip.right = area.left + step.clip.right; + } else if (step.clip.right < 0) { + finalClip.right = area.right + step.clip.right; + } + + if (step.clip.bottom > 0) { + finalClip.bottom = area.top + step.clip.bottom; + } else if (step.clip.bottom < 0) { + finalClip.bottom = area.bottom + step.clip.bottom; + } + + finalClip.clip(clip); + + return finalClip; +} + int VectorRenderer::stepGetRadius(const DrawStep &step, const Common::Rect &area) { int radius = 0; @@ -102,7 +137,7 @@ void VectorRenderer::stepGetPositions(const DrawStep &step, const Common::Rect & } } else { in_x = area.left + step.padding.left; - in_w = area.width(); + in_w = area.width() - step.padding.left - step.padding.right; } if (!step.autoHeight) { @@ -133,7 +168,7 @@ void VectorRenderer::stepGetPositions(const DrawStep &step, const Common::Rect & } } else { in_y = area.top + step.padding.top; - in_h = area.height(); + in_h = area.height() - step.padding.top - step.padding.bottom; } if (step.scale != (1 << 16) && step.scale != 0) { diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 9be55460c2..28a987a927 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -64,6 +64,7 @@ struct DrawStep { negative values mean counting from the opposite direction */ Common::Rect padding; + Common::Rect clip; /**< Clipping rect restriction */ enum VectorAlignment { kVectorAlignManual, @@ -392,6 +393,11 @@ public: int stepGetRadius(const DrawStep &step, const Common::Rect &area); /** + * Restrict a draw call clipping rect with a step specific clipping rect + */ + Common::Rect applyStepClippingRect(const Common::Rect &area, const Common::Rect &clip, const DrawStep &step); + + /** * DrawStep callback functions for each drawing feature */ void drawCallback_CIRCLE(const Common::Rect &area, const DrawStep &step) { @@ -412,7 +418,7 @@ public: void drawCallback_LINE(const Common::Rect &area, const DrawStep &step) { uint16 x, y, w, h; stepGetPositions(step, area, x, y, w, h); - drawLine(x, y, x + w, y + w); + drawLine(x, y, x + w, y + h); } void drawCallback_ROUNDSQ(const Common::Rect &area, const DrawStep &step) { diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index 457e9ff149..a1d8ba3599 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -670,9 +670,9 @@ gradientFillClip(PixelType *ptr, int width, int x, int y, int realX, int realY) if (grad == 0 || _gradCache[curGrad] == _gradCache[curGrad + 1] || // no color change stripSize < 2) { // the stip is small - colorFill<PixelType>(ptr, ptr + width, _gradCache[curGrad]); + colorFillClip<PixelType>(ptr, ptr + width, _gradCache[curGrad], realX, realY, _clippingArea); } else if (grad == 3 && ox) { - colorFill<PixelType>(ptr, ptr + width, _gradCache[curGrad + 1]); + colorFillClip<PixelType>(ptr, ptr + width, _gradCache[curGrad + 1], realX, realY, _clippingArea); } else { for (int j = x; j < x + width; j++, ptr++) { if (realX + j - x < _clippingArea.left || realX + j - x >= _clippingArea.right) continue; 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 Binary files differindex b59e9b0cc7..eb43825106 100644 --- a/gui/themes/scummclassic.zip +++ b/gui/themes/scummclassic.zip 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 Binary files differindex 75064465e4..f7a69004d3 100644 --- a/gui/themes/scummmodern.zip +++ b/gui/themes/scummmodern.zip 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 Binary files differindex b4f7c0eebb..b9b247c84a 100644 --- a/gui/themes/scummremastered.zip +++ b/gui/themes/scummremastered.zip 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 |