From 01f9006ee7e8d0fd153f42fb00afbc25c4804d2b Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:52:35 +0000 Subject: GUI: Implement tooltips. FR #2821513. FR #2821513: "GUI: add tooltips". Added tooltips for Add Game button, clear field buttons and couple other. Current problem: Only first call correctly restores text. I could not find where restore information gets lost. svn-id: r49774 --- engines/dialogs.cpp | 22 ++-- engines/scumm/dialogs.cpp | 6 +- gui/GuiManager.cpp | 31 ++++- gui/GuiManager.h | 6 + gui/PopUpWidget.cpp | 4 +- gui/PopUpWidget.h | 2 +- gui/TabWidget.cpp | 4 +- gui/ThemeEngine.cpp | 72 ++++++++++-- gui/ThemeEngine.h | 19 ++- gui/ThemeParser.cpp | 3 +- gui/browser.cpp | 6 +- gui/chooser.cpp | 4 +- gui/dialog.h | 1 + gui/launcher.cpp | 38 +++--- gui/massadd.cpp | 4 +- gui/message.cpp | 4 +- gui/options.cpp | 32 ++--- gui/saveload.cpp | 6 +- gui/themebrowser.cpp | 4 +- gui/themes/default.inc | 14 +++ gui/themes/scummclassic.zip | Bin 55147 -> 55660 bytes gui/themes/scummclassic/classic_gfx.stx | 9 ++ gui/themes/scummclassic/classic_layout.stx | 4 + gui/themes/scummclassic/classic_layout_lowres.stx | 4 + gui/themes/scummmodern.zip | Bin 162581 -> 162933 bytes gui/themes/scummmodern/scummmodern_gfx.stx | 7 +- gui/themes/scummmodern/scummmodern_layout.stx | 4 + .../scummmodern/scummmodern_layout_lowres.stx | 4 + gui/widget.cpp | 129 ++++++++++++++++----- gui/widget.h | 57 ++++++--- 30 files changed, 375 insertions(+), 125 deletions(-) diff --git a/engines/dialogs.cpp b/engines/dialogs.cpp index 0f391692e8..2397a474c6 100644 --- a/engines/dialogs.cpp +++ b/engines/dialogs.cpp @@ -86,31 +86,31 @@ MainMenuDialog::MainMenuDialog(Engine *engine) StaticTextWidget *version = new StaticTextWidget(this, "GlobalMenu.Version", gScummVMVersionDate); version->setAlign(Graphics::kTextAlignCenter); - new GUI::ButtonWidget(this, "GlobalMenu.Resume", _("~R~esume"), kPlayCmd, 'P'); + new GUI::ButtonWidget(this, "GlobalMenu.Resume", _("~R~esume"), 0, kPlayCmd, 'P'); - _loadButton = new GUI::ButtonWidget(this, "GlobalMenu.Load", _("~L~oad"), kLoadCmd); + _loadButton = new GUI::ButtonWidget(this, "GlobalMenu.Load", _("~L~oad"), 0, kLoadCmd); // TODO: setEnabled -> setVisible _loadButton->setEnabled(_engine->hasFeature(Engine::kSupportsLoadingDuringRuntime)); - _saveButton = new GUI::ButtonWidget(this, "GlobalMenu.Save", _("~S~ave"), kSaveCmd); + _saveButton = new GUI::ButtonWidget(this, "GlobalMenu.Save", _("~S~ave"), 0, kSaveCmd); // TODO: setEnabled -> setVisible _saveButton->setEnabled(_engine->hasFeature(Engine::kSupportsSavingDuringRuntime)); - new GUI::ButtonWidget(this, "GlobalMenu.Options", _("~O~ptions"), kOptionsCmd); + new GUI::ButtonWidget(this, "GlobalMenu.Options", _("~O~ptions"), 0, kOptionsCmd); // The help button is disabled by default. // To enable "Help", an engine needs to use a subclass of MainMenuDialog // (at least for now, we might change how this works in the future). - _helpButton = new GUI::ButtonWidget(this, "GlobalMenu.Help", _("~H~elp"), kHelpCmd); + _helpButton = new GUI::ButtonWidget(this, "GlobalMenu.Help", _("~H~elp"), 0, kHelpCmd); _helpButton->setEnabled(false); - new GUI::ButtonWidget(this, "GlobalMenu.About", _("~A~bout"), kAboutCmd); + new GUI::ButtonWidget(this, "GlobalMenu.About", _("~A~bout"), 0, kAboutCmd); - _rtlButton = new GUI::ButtonWidget(this, "GlobalMenu.RTL", _("~R~eturn to Launcher"), kRTLCmd); + _rtlButton = new GUI::ButtonWidget(this, "GlobalMenu.RTL", _("~R~eturn to Launcher"), 0, kRTLCmd); _rtlButton->setEnabled(_engine->hasFeature(Engine::kSupportsRTL)); - new GUI::ButtonWidget(this, "GlobalMenu.Quit", _("~Q~uit"), kQuitCmd); + new GUI::ButtonWidget(this, "GlobalMenu.Quit", _("~Q~uit"), 0, kQuitCmd); _aboutDialog = new GUI::AboutDialog(); _optionsDialog = new ConfigDialog(_engine->hasFeature(Engine::kSupportsSubtitleOptions)); @@ -298,11 +298,11 @@ ConfigDialog::ConfigDialog(bool subtitleControls) // Add the buttons // - new GUI::ButtonWidget(this, "GlobalConfig.Ok", _("~O~K"), GUI::kOKCmd); - new GUI::ButtonWidget(this, "GlobalConfig.Cancel", _("~C~ancel"), GUI::kCloseCmd); + new GUI::ButtonWidget(this, "GlobalConfig.Ok", _("~O~K"), 0, GUI::kOKCmd); + new GUI::ButtonWidget(this, "GlobalConfig.Cancel", _("~C~ancel"), 0, GUI::kCloseCmd); #ifdef SMALL_SCREEN_DEVICE - new GUI::ButtonWidget(this, "GlobalConfig.Keys", _("~K~eys"), kKeysCmd); + new GUI::ButtonWidget(this, "GlobalConfig.Keys", _("~K~eys"), 0, kKeysCmd); _keysDialog = NULL; #endif } diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp index 258b1875fe..1e0bf6d4be 100644 --- a/engines/scumm/dialogs.cpp +++ b/engines/scumm/dialogs.cpp @@ -284,9 +284,9 @@ HelpDialog::HelpDialog(const GameSettings &game) _numPages = ScummHelp::numPages(_game.id); - _prevButton = new GUI::ButtonWidget(this, "ScummHelp.Prev", _("~P~revious"), kPrevCmd); - _nextButton = new GUI::ButtonWidget(this, "ScummHelp.Next", _("~N~ext"), kNextCmd); - new GUI::ButtonWidget(this, "ScummHelp.Close", _("~C~lose"), GUI::kCloseCmd); + _prevButton = new GUI::ButtonWidget(this, "ScummHelp.Prev", _("~P~revious"), 0, kPrevCmd); + _nextButton = new GUI::ButtonWidget(this, "ScummHelp.Next", _("~N~ext"), 0, kNextCmd); + new GUI::ButtonWidget(this, "ScummHelp.Close", _("~C~lose"), 0, GUI::kCloseCmd); _prevButton->clearFlags(WIDGET_ENABLED); _numLines = HELP_NUM_LINES; diff --git a/gui/GuiManager.cpp b/gui/GuiManager.cpp index 9f04c382cb..49c078a723 100644 --- a/gui/GuiManager.cpp +++ b/gui/GuiManager.cpp @@ -27,6 +27,7 @@ #include "common/util.h" #include "common/config-manager.h" #include "common/algorithm.h" +#include "common/timer.h" #include "common/translation.h" #include "backends/keymapper/keymapper.h" @@ -49,7 +50,7 @@ enum { // Constructor GuiManager::GuiManager() : _redrawStatus(kRedrawDisabled), - _stateIsSaved(false), _cursorAnimateCounter(0), _cursorAnimateTimer(0) { + _stateIsSaved(false), _cursorAnimateCounter(0), _cursorAnimateTimer(0) { _theme = 0; _useStdCursor = false; @@ -75,10 +76,13 @@ GuiManager::GuiManager() : _redrawStatus(kRedrawDisabled), error(_t("Failed to load any GUI theme, aborting")); } } + + _tooltip = new Tooltip(this); } GuiManager::~GuiManager() { delete _theme; + delete _tooltip; } #ifdef ENABLE_KEYMAPPER @@ -220,6 +224,13 @@ Dialog *GuiManager::getTopDialog() const { return _dialogStack.top(); } +static void tooltipCallback(void *ref) { + GuiManager *guiManager = (GuiManager *)ref; + + guiManager->getTooltip()->setVisible(true); + g_system->getTimerManager()->removeTimerProc(&tooltipCallback); +} + void GuiManager::runLoop() { Dialog *activeDialog = getTopDialog(); bool didSaveState = false; @@ -278,6 +289,8 @@ void GuiManager::runLoop() { } Common::Event event; + + bool eventTookplace = false; while (eventMan->pollEvent(event)) { // The top dialog can change during the event loop. In that case, flush all the @@ -300,16 +313,21 @@ void GuiManager::runLoop() { switch (event.type) { case Common::EVENT_KEYDOWN: activeDialog->handleKeyDown(event.kbd); + eventTookplace = true; break; case Common::EVENT_KEYUP: activeDialog->handleKeyUp(event.kbd); + eventTookplace = true; break; case Common::EVENT_MOUSEMOVE: activeDialog->handleMouseMoved(mouse.x, mouse.y, 0); + _tooltip->setMouseXY(mouse.x, mouse.y); + eventTookplace = true; break; // We don't distinguish between mousebuttons (for now at least) case Common::EVENT_LBUTTONDOWN: case Common::EVENT_RBUTTONDOWN: + eventTookplace = true; button = (event.type == Common::EVENT_LBUTTONDOWN ? 1 : 2); time = _system->getMillis(); if (_lastClick.count && (time < _lastClick.time + kDoubleClickDelay) @@ -326,18 +344,22 @@ void GuiManager::runLoop() { break; case Common::EVENT_LBUTTONUP: case Common::EVENT_RBUTTONUP: + eventTookplace = true; button = (event.type == Common::EVENT_LBUTTONUP ? 1 : 2); activeDialog->handleMouseUp(mouse.x, mouse.y, button, _lastClick.count); break; case Common::EVENT_WHEELUP: + eventTookplace = true; activeDialog->handleMouseWheel(mouse.x, mouse.y, -1); break; case Common::EVENT_WHEELDOWN: + eventTookplace = true; activeDialog->handleMouseWheel(mouse.x, mouse.y, 1); break; case Common::EVENT_QUIT: return; case Common::EVENT_SCREEN_CHANGED: + eventTookplace = true; screenChange(); break; default: @@ -345,6 +367,13 @@ void GuiManager::runLoop() { } } + if (eventTookplace) { + _tooltip->setVisible(false); + + _system->getTimerManager()->removeTimerProc(&tooltipCallback); + _system->getTimerManager()->installTimerProc(&tooltipCallback, 2*1000000, this); + } + // Delay for a moment _system->delayMillis(10); } diff --git a/gui/GuiManager.h b/gui/GuiManager.h index 3187a0ba73..2591838416 100644 --- a/gui/GuiManager.h +++ b/gui/GuiManager.h @@ -60,6 +60,7 @@ typedef Common::FixedStack DialogStack; */ class GuiManager : public Common::Singleton { friend class Dialog; + friend class Tooltip; friend class Common::Singleton; GuiManager(); ~GuiManager(); @@ -91,6 +92,9 @@ public: * @return true if the a screen change indeed occurred, false otherwise */ bool checkScreenChange(); + + Tooltip *getTooltip() { return _tooltip; } + protected: enum RedrawStatus { kRedrawDisabled = 0, @@ -114,6 +118,8 @@ protected: bool _useStdCursor; + Tooltip *_tooltip; + // position and time of last mouse click (used to detect double clicks) struct { int16 x, y; // Position of mouse when the click occured diff --git a/gui/PopUpWidget.cpp b/gui/PopUpWidget.cpp index 7463399e0b..1bd9cc5063 100644 --- a/gui/PopUpWidget.cpp +++ b/gui/PopUpWidget.cpp @@ -378,8 +378,8 @@ void PopUpDialog::drawMenuEntry(int entry, bool hilite) { // PopUpWidget // -PopUpWidget::PopUpWidget(GuiObject *boss, const String &name) - : Widget(boss, name), CommandSender(boss) { +PopUpWidget::PopUpWidget(GuiObject *boss, const String &name, const char *tooltip) + : Widget(boss, name, tooltip), CommandSender(boss) { setFlags(WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS | WIDGET_IGNORE_DRAG); _type = kPopUpWidget; diff --git a/gui/PopUpWidget.h b/gui/PopUpWidget.h index bd1d3b3918..d1c89e45ae 100644 --- a/gui/PopUpWidget.h +++ b/gui/PopUpWidget.h @@ -59,7 +59,7 @@ protected: int _rightPadding; public: - PopUpWidget(GuiObject *boss, const String &name); + PopUpWidget(GuiObject *boss, const String &name, const char *tooltip = 0); void handleMouseDown(int x, int y, int button, int clickCount); void handleMouseWheel(int x, int y, int direction); diff --git a/gui/TabWidget.cpp b/gui/TabWidget.cpp index 275e3613b5..ca409e50ab 100644 --- a/gui/TabWidget.cpp +++ b/gui/TabWidget.cpp @@ -68,8 +68,8 @@ void TabWidget::init() { int x = _w - _butRP - _butW * 2 - 2; int y = _butTP - _tabHeight; - _navLeft = new ButtonWidget(this, x, y, _butW, _butH, "<", kCmdLeft); - _navRight = new ButtonWidget(this, x + _butW + 2, y, _butW, _butH, ">", kCmdRight); + _navLeft = new ButtonWidget(this, x, y, _butW, _butH, "<", 0, kCmdLeft); + _navRight = new ButtonWidget(this, x + _butW + 2, y, _butW, _butH, ">", 0, kCmdRight); } TabWidget::~TabWidget() { diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp index 5bde44d792..8f4f767a94 100644 --- a/gui/ThemeEngine.cpp +++ b/gui/ThemeEngine.cpp @@ -1070,7 +1070,7 @@ void ThemeEngine::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, co } } -void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, Graphics::TextAlign align, TextInversionState inverted, int deltax, bool useEllipsis, FontStyle font, FontColor color) { +void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, Graphics::TextAlign align, TextInversionState inverted, int deltax, bool useEllipsis, FontStyle font, FontColor color, bool restore) { if (!ready()) return; @@ -1121,13 +1121,7 @@ void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, Wid return; } - TextData textId = kTextDataNone; - if (font == kFontStyleNormal) - textId = kTextDataNormalFont; - else - textId = kTextDataDefault; - - bool restore = true; + TextData textId = fontStyleToData(font); switch (inverted) { case kTextInversion: @@ -1169,7 +1163,69 @@ void ThemeEngine::debugWidgetPosition(const char *name, const Common::Rect &r) { _screen.vLine(r.right, r.top, r.bottom, 0xFFFF); } +ThemeEngine::StoredState *ThemeEngine::storeState(const Common::Rect &r) { + StoredState *state = new StoredState; + byte *dst; + byte *src; + + state->r.top = r.top; + state->r.bottom = r.bottom; + state->r.left = r.left; + state->r.right = r.right; + + state->r.clip(_screen.w, _screen.h); + state->screen.create(state->r.width(), state->r.height(), _screen.bytesPerPixel); + state->backBuffer.create(state->r.width(), state->r.height(), _backBuffer.bytesPerPixel); + + src = (byte *)_screen.getBasePtr(state->r.left, state->r.top); + dst = (byte *)state->screen.getBasePtr(0, 0); + + for (int i = state->r.height(); i > 0; i--) { + memcpy(dst, src, state->r.width() * _screen.bytesPerPixel); + src += _screen.pitch; + dst += state->screen.pitch; + } + + src = (byte *)_backBuffer.getBasePtr(state->r.left, state->r.top); + dst = (byte *)state->backBuffer.getBasePtr(0, 0); + + for (int i = state->r.height(); i > 0; i--) { + memcpy(dst, src, state->r.width() * _backBuffer.bytesPerPixel); + src += _backBuffer.pitch; + dst += state->backBuffer.pitch; + } + + return state; +} + +void ThemeEngine::restoreState(StoredState *state) { + byte *dst; + byte *src; + + if (!state) + return; + + src = (byte *)state->screen.getBasePtr(0, 0); + dst = (byte *)_screen.getBasePtr(state->r.left, state->r.top); + + for (int i = state->r.height(); i > 0; i--) { + memcpy(dst, src, state->r.width() * _screen.bytesPerPixel); + src += state->screen.pitch; + dst += _screen.pitch; + } + + src = (byte *)state->backBuffer.getBasePtr(0, 0); + dst = (byte *)_backBuffer.getBasePtr(state->r.left, state->r.top); + + for (int i = state->r.height(); i > 0; i--) { + memcpy(dst, src, state->r.width() * _backBuffer.bytesPerPixel); + src += state->backBuffer.pitch; + dst += _backBuffer.pitch; + } + + addDirtyRect(state->r); +} /********************************************************** * Screen/overlay management diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h index 2ef6fe3781..5f474f1a88 100644 --- a/gui/ThemeEngine.h +++ b/gui/ThemeEngine.h @@ -112,6 +112,7 @@ enum TextData { kTextDataDefault = 0, kTextDataButton, kTextDataNormalFont, + kTextDataTooltip, kTextDataMAX }; @@ -177,7 +178,7 @@ public: enum TextInversionState { kTextInversionNone, ///< Indicates that the text should not be drawn inverted kTextInversion, ///< Indicates that the text should be drawn inverted, but not focused - kTextInversionFocus ///< Indicates thte the test should be drawn inverted, and focused + kTextInversionFocus ///< Indicates that the text should be drawn inverted, and focused }; enum ScrollbarState { @@ -196,6 +197,7 @@ public: kFontStyleFixedNormal = 3, ///< Fixed size font. kFontStyleFixedBold = 4, ///< Fixed size bold font. kFontStyleFixedItalic = 5, ///< Fixed size italic font. + kFontStyleTooltip = 6, ///< Tiny console font kFontStyleMax }; @@ -259,6 +261,17 @@ public: void enable(); void disable(); + struct StoredState { + Common::Rect r; + Graphics::Surface screen; + Graphics::Surface backBuffer; + + StoredState() {} + }; + + StoredState *storeState(const Common::Rect &r); + void restoreState(StoredState *state); + /** * Implementation of the GUI::Theme API. Called when a * new dialog is opened. Note that the boolean parameter @@ -284,6 +297,8 @@ public: TextData fontStyleToData(FontStyle font) const { if (font == kFontStyleNormal) return kTextDataNormalFont; + if (font == kFontStyleTooltip) + return kTextDataTooltip; return kTextDataDefault; } @@ -336,7 +351,7 @@ public: void drawDialogBackground(const Common::Rect &r, DialogBackground type, WidgetStateInfo state = kStateEnabled); - void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignCenter, TextInversionState inverted = kTextInversionNone, int deltax = 0, bool useEllipsis = true, FontStyle font = kFontStyleBold, FontColor color = kFontColorNormal); + void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignCenter, TextInversionState inverted = kTextInversionNone, int deltax = 0, bool useEllipsis = true, FontStyle font = kFontStyleBold, FontColor color = kFontColorNormal, bool restore = true); void drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state = kStateEnabled, FontColor color = kFontColorNormal); diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index e22d440bd9..4cabf6ad2e 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -42,7 +42,8 @@ struct TextDataInfo { static const TextDataInfo kTextDataDefaults[] = { { kTextDataDefault, "text_default" }, { kTextDataButton, "text_button" }, - { kTextDataNormalFont, "text_normal" } + { kTextDataNormalFont, "text_normal" }, + { kTextDataTooltip, "tooltip_normal" } }; diff --git a/gui/browser.cpp b/gui/browser.cpp index 000359e1e7..0d95e5397b 100644 --- a/gui/browser.cpp +++ b/gui/browser.cpp @@ -66,9 +66,9 @@ BrowserDialog::BrowserDialog(const char *title, bool dirBrowser) _backgroundType = GUI::ThemeEngine::kDialogBackgroundPlain; // Buttons - new ButtonWidget(this, "Browser.Up", _("Go up"), kGoUpCmd); - new ButtonWidget(this, "Browser.Cancel", _("Cancel"), kCloseCmd); - new ButtonWidget(this, "Browser.Choose", _("Choose"), kChooseCmd); + new ButtonWidget(this, "Browser.Up", _("Go up"), _("Go to previous directory level"), kGoUpCmd); + new ButtonWidget(this, "Browser.Cancel", _("Cancel"), 0, kCloseCmd); + new ButtonWidget(this, "Browser.Choose", _("Choose"), 0, kChooseCmd); } void BrowserDialog::open() { diff --git a/gui/chooser.cpp b/gui/chooser.cpp index 7039e40947..a7b453c957 100644 --- a/gui/chooser.cpp +++ b/gui/chooser.cpp @@ -46,8 +46,8 @@ ChooserDialog::ChooserDialog(const String &title, String dialogId) _list->setEditable(false); // Buttons - new ButtonWidget(this, dialogId + ".Cancel", _("Cancel"), kCloseCmd); - _chooseButton = new ButtonWidget(this, dialogId + ".Choose", _("Choose"), kChooseCmd); + new ButtonWidget(this, dialogId + ".Cancel", _("Cancel"), 0, kCloseCmd); + _chooseButton = new ButtonWidget(this, dialogId + ".Choose", _("Choose"), 0, kChooseCmd); _chooseButton->setEnabled(false); } diff --git a/gui/dialog.h b/gui/dialog.h index 5008f272ba..1845786044 100644 --- a/gui/dialog.h +++ b/gui/dialog.h @@ -44,6 +44,7 @@ enum { class Dialog : public GuiObject { friend class GuiManager; + friend class Tooltip; protected: Widget *_mouseWidget; Widget *_focusedWidget; diff --git a/gui/launcher.cpp b/gui/launcher.cpp index b12c56dbde..829a57469b 100644 --- a/gui/launcher.cpp +++ b/gui/launcher.cpp @@ -202,7 +202,7 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) // _graphicsTabId = tab->addTab(g_system->getOverlayWidth() > 320 ? _("Graphics") : _("GFX")); - _globalGraphicsOverride = new CheckboxWidget(tab, "GameOptions_Graphics.EnableTabCheckbox", _("Override global graphic settings"), kCmdGlobalGraphicsOverride); + _globalGraphicsOverride = new CheckboxWidget(tab, "GameOptions_Graphics.EnableTabCheckbox", _("Override global graphic settings"), 0, kCmdGlobalGraphicsOverride); addGraphicControls(tab, "GameOptions_Graphics."); @@ -211,7 +211,7 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) // tab->addTab(_("Audio")); - _globalAudioOverride = new CheckboxWidget(tab, "GameOptions_Audio.EnableTabCheckbox", _("Override global audio settings"), kCmdGlobalAudioOverride); + _globalAudioOverride = new CheckboxWidget(tab, "GameOptions_Audio.EnableTabCheckbox", _("Override global audio settings"), 0, kCmdGlobalAudioOverride); addAudioControls(tab, "GameOptions_Audio."); addSubtitleControls(tab, "GameOptions_Audio."); @@ -221,7 +221,7 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) // tab->addTab(_("Volume")); - _globalVolumeOverride = new CheckboxWidget(tab, "GameOptions_Volume.EnableTabCheckbox", _("Override global volume settings"), kCmdGlobalVolumeOverride); + _globalVolumeOverride = new CheckboxWidget(tab, "GameOptions_Volume.EnableTabCheckbox", _("Override global volume settings"), 0, kCmdGlobalVolumeOverride); addVolumeControls(tab, "GameOptions_Volume."); @@ -230,7 +230,7 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) // tab->addTab(_("MIDI")); - _globalMIDIOverride = new CheckboxWidget(tab, "GameOptions_MIDI.EnableTabCheckbox", _("Override global MIDI settings"), kCmdGlobalMIDIOverride); + _globalMIDIOverride = new CheckboxWidget(tab, "GameOptions_MIDI.EnableTabCheckbox", _("Override global MIDI settings"), 0, kCmdGlobalMIDIOverride); if (_guioptions & Common::GUIO_NOMIDI) _globalMIDIOverride->setEnabled(false); @@ -246,15 +246,15 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) // in the small version of the GUI. // GUI: Button + Label for the game path - new ButtonWidget(tab, "GameOptions_Paths.Gamepath", _("Game Path:"), kCmdGameBrowser); + new ButtonWidget(tab, "GameOptions_Paths.Gamepath", _("Game Path:"), 0, kCmdGameBrowser); _gamePathWidget = new StaticTextWidget(tab, "GameOptions_Paths.GamepathText", gamePath); // GUI: Button + Label for the additional path - new ButtonWidget(tab, "GameOptions_Paths.Extrapath", _("Extra Path:"), kCmdExtraBrowser); + new ButtonWidget(tab, "GameOptions_Paths.Extrapath", _("Extra Path:"), 0, kCmdExtraBrowser); _extraPathWidget = new StaticTextWidget(tab, "GameOptions_Paths.ExtrapathText", extraPath); // GUI: Button + Label for the save path - new ButtonWidget(tab, "GameOptions_Paths.Savepath", _("Save Path:"), kCmdSaveBrowser); + new ButtonWidget(tab, "GameOptions_Paths.Savepath", _("Save Path:"), 0, kCmdSaveBrowser); _savePathWidget = new StaticTextWidget(tab, "GameOptions_Paths.SavepathText", savePath); // Activate the first tab @@ -262,8 +262,8 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) _tabWidget = tab; // Add OK & Cancel buttons - new ButtonWidget(this, "GameOptions.Cancel", _("Cancel"), kCloseCmd); - new ButtonWidget(this, "GameOptions.Ok", _("OK"), kOKCmd); + new ButtonWidget(this, "GameOptions.Cancel", _("Cancel"), 0, kCloseCmd); + new ButtonWidget(this, "GameOptions.Ok", _("OK"), 0, kOKCmd); } void EditGameDialog::open() { @@ -497,36 +497,36 @@ LauncherDialog::LauncherDialog() new StaticTextWidget(this, "Launcher.Version", gScummVMFullVersion); #endif - new ButtonWidget(this, "Launcher.QuitButton", _("~Q~uit"), kQuitCmd); - new ButtonWidget(this, "Launcher.AboutButton", _("A~b~out..."), kAboutCmd); - new ButtonWidget(this, "Launcher.OptionsButton", _("~O~ptions..."), kOptionsCmd); + new ButtonWidget(this, "Launcher.QuitButton", _("~Q~uit"), 0, kQuitCmd); + new ButtonWidget(this, "Launcher.AboutButton", _("A~b~out..."), 0, kAboutCmd); + new ButtonWidget(this, "Launcher.OptionsButton", _("~O~ptions..."), 0, kOptionsCmd); _startButton = - new ButtonWidget(this, "Launcher.StartButton", _("~S~tart"), kStartCmd); + new ButtonWidget(this, "Launcher.StartButton", _("~S~tart"), 0, kStartCmd); _loadButton = - new ButtonWidget(this, "Launcher.LoadGameButton", _("~L~oad..."), kLoadGameCmd); + new ButtonWidget(this, "Launcher.LoadGameButton", _("~L~oad..."), 0, kLoadGameCmd); // Above the lowest button rows: two more buttons (directly below the list box) _addButton = - new ButtonWidget(this, "Launcher.AddGameButton", _("~A~dd Game..."), kAddGameCmd); + new ButtonWidget(this, "Launcher.AddGameButton", _("~A~dd Game..."), _("Hold Shift for Mass Add"), kAddGameCmd); _editButton = - new ButtonWidget(this, "Launcher.EditGameButton", _("~E~dit Game..."), kEditGameCmd); + new ButtonWidget(this, "Launcher.EditGameButton", _("~E~dit Game..."), 0, kEditGameCmd); _removeButton = - new ButtonWidget(this, "Launcher.RemoveGameButton", _("~R~emove Game"), kRemoveGameCmd); + new ButtonWidget(this, "Launcher.RemoveGameButton", _("~R~emove Game"), 0, kRemoveGameCmd); // Search box _searchDesc = 0; #ifndef DISABLE_FANCY_THEMES _searchPic = 0; if (g_gui.xmlEval()->getVar("Globals.ShowSearchPic") == 1 && g_gui.theme()->supportsImages()) { - _searchPic = new GraphicsWidget(this, "Launcher.SearchPic"); + _searchPic = new GraphicsWidget(this, "Launcher.SearchPic", _("Search in game list")); _searchPic->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageSearch)); } else #endif _searchDesc = new StaticTextWidget(this, "Launcher.SearchDesc", _("Search:")); _searchWidget = new EditTextWidget(this, "Launcher.Search", _search, kSearchCmd); - _searchClearButton = new ButtonWidget(this, "Launcher.SearchClearButton", "C", kSearchClearCmd); + _searchClearButton = new ButtonWidget(this, "Launcher.SearchClearButton", "C", _("Clear value"), kSearchClearCmd); // Add list with game titles _list = new ListWidget(this, "Launcher.GameList", kListSearchCmd); diff --git a/gui/massadd.cpp b/gui/massadd.cpp index 36efdfdd59..b981520cdc 100644 --- a/gui/massadd.cpp +++ b/gui/massadd.cpp @@ -89,10 +89,10 @@ MassAddDialog::MassAddDialog(const Common::FSNode &startDir) _list->setNumberingMode(kListNumberingOff); _list->setList(l); - _okButton = new ButtonWidget(this, "MassAdd.Ok", _("OK"), kOkCmd, Common::ASCII_RETURN); + _okButton = new ButtonWidget(this, "MassAdd.Ok", _("OK"), 0, kOkCmd, Common::ASCII_RETURN); _okButton->setEnabled(false); - new ButtonWidget(this, "MassAdd.Cancel", _("Cancel"), kCancelCmd, Common::ASCII_ESCAPE); + new ButtonWidget(this, "MassAdd.Cancel", _("Cancel"), 0, kCancelCmd, Common::ASCII_ESCAPE); // Build a map from all configured game paths to the targets using them const Common::ConfigManager::DomainMap &domains = ConfMan.getGameDomains(); diff --git a/gui/message.cpp b/gui/message.cpp index 12ac3123a4..6406976569 100644 --- a/gui/message.cpp +++ b/gui/message.cpp @@ -89,10 +89,10 @@ MessageDialog::MessageDialog(const Common::String &message, const char *defaultB } if (defaultButton) - new ButtonWidget(this, okButtonPos, _h - buttonHeight - 8, buttonWidth, buttonHeight, defaultButton, kOkCmd, Common::ASCII_RETURN); // Confirm dialog + new ButtonWidget(this, okButtonPos, _h - buttonHeight - 8, buttonWidth, buttonHeight, defaultButton, 0, kOkCmd, Common::ASCII_RETURN); // Confirm dialog if (altButton) - new ButtonWidget(this, cancelButtonPos, _h - buttonHeight - 8, buttonWidth, buttonHeight, altButton, kCancelCmd, Common::ASCII_ESCAPE); // Cancel dialog + new ButtonWidget(this, cancelButtonPos, _h - buttonHeight - 8, buttonWidth, buttonHeight, altButton, 0, kCancelCmd, Common::ASCII_ESCAPE); // Cancel dialog } void MessageDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { diff --git a/gui/options.cpp b/gui/options.cpp index e9be2834a4..ac7b2dc475 100644 --- a/gui/options.cpp +++ b/gui/options.cpp @@ -642,9 +642,9 @@ void OptionsDialog::addAudioControls(GuiObject *boss, const Common::String &pref void OptionsDialog::addMIDIControls(GuiObject *boss, const Common::String &prefix) { // SoundFont - _soundFontButton = new ButtonWidget(boss, prefix + "mcFontButton", _("SoundFont:"), kChooseSoundFontCmd); + _soundFontButton = new ButtonWidget(boss, prefix + "mcFontButton", _("SoundFont:"), 0, kChooseSoundFontCmd); _soundFont = new StaticTextWidget(boss, prefix + "mcFontPath", _("None")); - _soundFontClearButton = new ButtonWidget(boss, prefix + "mcFontClearButton", "C", kClearSoundFontCmd); + _soundFontClearButton = new ButtonWidget(boss, prefix + "mcFontClearButton", "C", _("Clear value"), kClearSoundFontCmd); // Multi midi setting _multiMidiCheckbox = new CheckboxWidget(boss, prefix + "mcMixedCheckbox", _("Mixed AdLib/MIDI mode")); @@ -657,7 +657,7 @@ void OptionsDialog::addMIDIControls(GuiObject *boss, const Common::String &prefi // MIDI gain setting (FluidSynth uses this) _midiGainDesc = new StaticTextWidget(boss, prefix + "mcMidiGainText", _("MIDI gain:")); - _midiGainSlider = new SliderWidget(boss, prefix + "mcMidiGainSlider", kMidiGainChanged); + _midiGainSlider = new SliderWidget(boss, prefix + "mcMidiGainSlider", 0, kMidiGainChanged); _midiGainSlider->setMinValue(0); _midiGainSlider->setMaxValue(1000); _midiGainLabel = new StaticTextWidget(boss, prefix + "mcMidiGainLabel", "1.00"); @@ -687,7 +687,7 @@ void OptionsDialog::addSubtitleControls(GuiObject *boss, const Common::String &p // Subtitle speed _subSpeedDesc = new StaticTextWidget(boss, prefix + "subSubtitleSpeedDesc", _("Subtitle speed:")); - _subSpeedSlider = new SliderWidget(boss, prefix + "subSubtitleSpeedSlider", kSubtitleSpeedChanged); + _subSpeedSlider = new SliderWidget(boss, prefix + "subSubtitleSpeedSlider", 0, kSubtitleSpeedChanged); _subSpeedLabel = new StaticTextWidget(boss, prefix + "subSubtitleSpeedLabel", "100%"); _subSpeedSlider->setMinValue(0); _subSpeedSlider->setMaxValue(maxSliderVal); _subSpeedLabel->setFlags(WIDGET_CLEARBG); @@ -699,24 +699,24 @@ void OptionsDialog::addVolumeControls(GuiObject *boss, const Common::String &pre // Volume controllers _musicVolumeDesc = new StaticTextWidget(boss, prefix + "vcMusicText", _("Music volume:")); - _musicVolumeSlider = new SliderWidget(boss, prefix + "vcMusicSlider", kMusicVolumeChanged); + _musicVolumeSlider = new SliderWidget(boss, prefix + "vcMusicSlider", 0, kMusicVolumeChanged); _musicVolumeLabel = new StaticTextWidget(boss, prefix + "vcMusicLabel", "100%"); _musicVolumeSlider->setMinValue(0); _musicVolumeSlider->setMaxValue(Audio::Mixer::kMaxMixerVolume); _musicVolumeLabel->setFlags(WIDGET_CLEARBG); - _muteCheckbox = new CheckboxWidget(boss, prefix + "vcMuteCheckbox", _("Mute All"), kMuteAllChanged); + _muteCheckbox = new CheckboxWidget(boss, prefix + "vcMuteCheckbox", _("Mute All"), 0, kMuteAllChanged); _sfxVolumeDesc = new StaticTextWidget(boss, prefix + "vcSfxText", _("SFX volume:")); - _sfxVolumeSlider = new SliderWidget(boss, prefix + "vcSfxSlider", kSfxVolumeChanged); + _sfxVolumeSlider = new SliderWidget(boss, prefix + "vcSfxSlider", 0, kSfxVolumeChanged); _sfxVolumeLabel = new StaticTextWidget(boss, prefix + "vcSfxLabel", "100%"); _sfxVolumeSlider->setMinValue(0); _sfxVolumeSlider->setMaxValue(Audio::Mixer::kMaxMixerVolume); _sfxVolumeLabel->setFlags(WIDGET_CLEARBG); _speechVolumeDesc = new StaticTextWidget(boss, prefix + "vcSpeechText" , _("Speech volume:")); - _speechVolumeSlider = new SliderWidget(boss, prefix + "vcSpeechSlider", kSpeechVolumeChanged); + _speechVolumeSlider = new SliderWidget(boss, prefix + "vcSpeechSlider", 0, kSpeechVolumeChanged); _speechVolumeLabel = new StaticTextWidget(boss, prefix + "vcSpeechLabel", "100%"); _speechVolumeSlider->setMinValue(0); _speechVolumeSlider->setMaxValue(Audio::Mixer::kMaxMixerVolume); @@ -792,24 +792,24 @@ GlobalOptionsDialog::GlobalOptionsDialog() // truncated in the small version of the GUI. // Save game path - new ButtonWidget(tab, "GlobalOptions_Paths.SaveButton", _("Save Path: "), kChooseSaveDirCmd); + new ButtonWidget(tab, "GlobalOptions_Paths.SaveButton", _("Save Path: "), 0, kChooseSaveDirCmd); _savePath = new StaticTextWidget(tab, "GlobalOptions_Paths.SavePath", "/foo/bar"); - new ButtonWidget(tab, "GlobalOptions_Paths.ThemeButton", _("Theme Path:"), kChooseThemeDirCmd); + new ButtonWidget(tab, "GlobalOptions_Paths.ThemeButton", _("Theme Path:"), 0, kChooseThemeDirCmd); _themePath = new StaticTextWidget(tab, "GlobalOptions_Paths.ThemePath", _("None")); - new ButtonWidget(tab, "GlobalOptions_Paths.ExtraButton", _("Extra Path:"), kChooseExtraDirCmd); + new ButtonWidget(tab, "GlobalOptions_Paths.ExtraButton", _("Extra Path:"), 0, kChooseExtraDirCmd); _extraPath = new StaticTextWidget(tab, "GlobalOptions_Paths.ExtraPath", _("None")); #ifdef DYNAMIC_MODULES - new ButtonWidget(tab, "GlobalOptions_Paths.PluginsButton", _("Plugins Path:"), kChoosePluginsDirCmd); + new ButtonWidget(tab, "GlobalOptions_Paths.PluginsButton", _("Plugins Path:"), 0, kChoosePluginsDirCmd); _pluginsPath = new StaticTextWidget(tab, "GlobalOptions_Paths.PluginsPath", _("None")); #endif #endif tab->addTab(_("Misc")); - new ButtonWidget(tab, "GlobalOptions_Misc.ThemeButton", _("Theme:"), kChooseThemeCmd); + new ButtonWidget(tab, "GlobalOptions_Misc.ThemeButton", _("Theme:"), 0, kChooseThemeCmd); _curTheme = new StaticTextWidget(tab, "GlobalOptions_Misc.CurTheme", g_gui.theme()->getThemeName()); @@ -827,7 +827,7 @@ GlobalOptionsDialog::GlobalOptionsDialog() } #ifdef SMALL_SCREEN_DEVICE - new ButtonWidget(tab, "GlobalOptions_Misc.KeysButton", _("Keys"), kChooseKeyMappingCmd); + new ButtonWidget(tab, "GlobalOptions_Misc.KeysButton", _("Keys"), 0, kChooseKeyMappingCmd); #endif // TODO: joystick setting @@ -856,8 +856,8 @@ GlobalOptionsDialog::GlobalOptionsDialog() _tabWidget = tab; // Add OK & Cancel buttons - new ButtonWidget(this, "GlobalOptions.Cancel", _("Cancel"), kCloseCmd); - new ButtonWidget(this, "GlobalOptions.Ok", _("OK"), kOKCmd); + new ButtonWidget(this, "GlobalOptions.Cancel", _("Cancel"), 0, kCloseCmd); + new ButtonWidget(this, "GlobalOptions.Ok", _("OK"), 0, kOKCmd); #ifdef SMALL_SCREEN_DEVICE _keysDialog = new KeysDialog(); diff --git a/gui/saveload.cpp b/gui/saveload.cpp index bd5aadc206..cef7269b95 100644 --- a/gui/saveload.cpp +++ b/gui/saveload.cpp @@ -62,11 +62,11 @@ SaveLoadChooser::SaveLoadChooser(const String &title, const String &buttonLabel) _playtime = new StaticTextWidget(this, 0, 0, 10, 10, _("No playtime saved"), Graphics::kTextAlignCenter); // Buttons - new GUI::ButtonWidget(this, "SaveLoadChooser.Cancel", _("Cancel"), kCloseCmd); - _chooseButton = new GUI::ButtonWidget(this, "SaveLoadChooser.Choose", buttonLabel, kChooseCmd); + new GUI::ButtonWidget(this, "SaveLoadChooser.Cancel", _("Cancel"), 0, kCloseCmd); + _chooseButton = new GUI::ButtonWidget(this, "SaveLoadChooser.Choose", buttonLabel, 0, kChooseCmd); _chooseButton->setEnabled(false); - _deleteButton = new GUI::ButtonWidget(this, "SaveLoadChooser.Delete", _("Delete"), kDelCmd); + _deleteButton = new GUI::ButtonWidget(this, "SaveLoadChooser.Delete", _("Delete"), 0, kDelCmd); _deleteButton->setEnabled(false); _delSupport = _metaInfoSupport = _thumbnailSupport = false; diff --git a/gui/themebrowser.cpp b/gui/themebrowser.cpp index 987408e1b4..c8f732fe5f 100644 --- a/gui/themebrowser.cpp +++ b/gui/themebrowser.cpp @@ -53,8 +53,8 @@ ThemeBrowser::ThemeBrowser() : Dialog("Browser") { _backgroundType = GUI::ThemeEngine::kDialogBackgroundPlain; // Buttons - new ButtonWidget(this, "Browser.Cancel", _("Cancel"), kCloseCmd); - new ButtonWidget(this, "Browser.Choose", _("Choose"), kChooseCmd); + new ButtonWidget(this, "Browser.Cancel", _("Cancel"), 0, kCloseCmd); + new ButtonWidget(this, "Browser.Choose", _("Choose"), 0, kChooseCmd); } void ThemeBrowser::open() { diff --git a/gui/themes/default.inc b/gui/themes/default.inc index 17294703f4..1009f31816 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -27,6 +27,9 @@ " " +" " " " @@ -411,6 +414,11 @@ "bevel='2' " "/> " " " +" " +" " +" " " " " " " " @@ -425,6 +433,9 @@ " " " " " " +" " +" " +" " " " " " " " +" " +" " +" " " " diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip index cc288765ac..3f3f9cee37 100644 Binary files a/gui/themes/scummclassic.zip and b/gui/themes/scummclassic.zip differ diff --git a/gui/themes/scummclassic/classic_gfx.stx b/gui/themes/scummclassic/classic_gfx.stx index e107c1f04d..05040751f9 100644 --- a/gui/themes/scummclassic/classic_gfx.stx +++ b/gui/themes/scummclassic/classic_gfx.stx @@ -52,6 +52,9 @@ + + + + + diff --git a/gui/themes/scummclassic/classic_layout.stx b/gui/themes/scummclassic/classic_layout.stx index 9f241c06e5..e4a31e0971 100644 --- a/gui/themes/scummclassic/classic_layout.stx +++ b/gui/themes/scummclassic/classic_layout.stx @@ -41,6 +41,10 @@ + + + + + + + + diff --git a/gui/themes/scummmodern.zip b/gui/themes/scummmodern.zip index 1f3a017b45..22e8ccaa90 100644 Binary files a/gui/themes/scummmodern.zip and b/gui/themes/scummmodern.zip differ diff --git a/gui/themes/scummmodern/scummmodern_gfx.stx b/gui/themes/scummmodern/scummmodern_gfx.stx index 13f9cd2196..3ed915200a 100644 --- a/gui/themes/scummmodern/scummmodern_gfx.stx +++ b/gui/themes/scummmodern/scummmodern_gfx.stx @@ -114,6 +114,9 @@ + - - + + + + + + + + getFontHeight(ThemeEngine::kFontStyleTooltip) + 2; + + // Make Rect bigger for compensating the shadow + _storedState = g_gui.theme()->storeState(Common::Rect(_x - 5, _y - 5, _x + _w + 5, _y + _h + 5)); + + g_gui.theme()->startBuffering(); + g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h), 0, ThemeEngine::kWidgetBackgroundBorderSmall); + + for (Common::StringArray::const_iterator i = _wrappedLines.begin(); i != _wrappedLines.end(); ++i, ++num) { + g_gui.theme()->drawText(Common::Rect(_x + 1, _y + 1 + num * h, _x + 1 +_w, _y + 1+ (num + 1) * h), *i, ThemeEngine::kStateEnabled, Graphics::kTextAlignLeft, ThemeEngine::kTextInversionNone, 0, false, ThemeEngine::kFontStyleTooltip, ThemeEngine::kFontColorNormal, false); + } + g_gui.theme()->finishBuffering(); +} + +void Tooltip::reflowLayout() { +} + +void Tooltip::setMouseXY(int x, int y) { + _mouseX = x; + _mouseY = y; +} + +void Tooltip::setVisible(bool state) { + if (state == _visible) + return; + + if (state) { + Widget *wdg = _guiManager->getTopDialog()->findWidget(_mouseX, _mouseY); + + if (!wdg) + return; + + if (wdg->getTooltip()) { + _visible = state; + + // Cache config values. + // NOTE: we cannot do it in the consturctor + if (_maxWidth == -1) { + _maxWidth = g_gui.xmlEval()->getVar("Globals.Tooltip.MaxWidth", 100); + _xdelta = g_gui.xmlEval()->getVar("Globals.Tooltip.XDelta", 0); + _ydelta = g_gui.xmlEval()->getVar("Globals.Tooltip.YDelta", 0); + } + + const Graphics::Font *tooltipFont = g_gui.theme()->getFont(ThemeEngine::kFontStyleTooltip); + + _wrappedLines.clear(); + _w = tooltipFont->wordWrapText(wdg->getTooltip(), _maxWidth - 4, _wrappedLines); + _h = (tooltipFont->getFontHeight() + 2) * _wrappedLines.size(); + + _x = MIN(_guiManager->getTopDialog()->_x + _mouseX + _xdelta, g_gui.getWidth() - _w - 3); + _y = MIN(_guiManager->getTopDialog()->_y + _mouseY + _ydelta, g_gui.getHeight() - _h - 3); + + draw(); + } + } else { + _visible = state; + + g_gui.theme()->restoreState(_storedState); + delete _storedState; + } +} + +#pragma mark - + +StaticTextWidget::StaticTextWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &text, Graphics::TextAlign align, const char *tooltip) + : Widget(boss, x, y, w, h, tooltip), _align(align) { setFlags(WIDGET_ENABLED); _type = kStaticTextWidget; _label = text; } -StaticTextWidget::StaticTextWidget(GuiObject *boss, const Common::String &name, const Common::String &text) - : Widget(boss, name) { +StaticTextWidget::StaticTextWidget(GuiObject *boss, const Common::String &name, const Common::String &text, const char *tooltip) + : Widget(boss, name, tooltip) { setFlags(WIDGET_ENABLED); _type = kStaticTextWidget; _label = text; @@ -272,8 +345,8 @@ void StaticTextWidget::drawWidget() { #pragma mark - -ButtonWidget::ButtonWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, uint32 cmd, uint8 hotkey) - : StaticTextWidget(boss, x, y, w, h, cleanupHotkey(label), Graphics::kTextAlignCenter), CommandSender(boss), +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) { if (hotkey == 0) @@ -283,8 +356,8 @@ ButtonWidget::ButtonWidget(GuiObject *boss, int x, int y, int w, int h, const Co _type = kButtonWidget; } -ButtonWidget::ButtonWidget(GuiObject *boss, const Common::String &name, const Common::String &label, uint32 cmd, uint8 hotkey) - : StaticTextWidget(boss, name, cleanupHotkey(label)), CommandSender(boss), +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) { if (hotkey == 0) _hotkey = parseHotkey(label); @@ -303,14 +376,14 @@ void ButtonWidget::drawWidget() { #pragma mark - -CheckboxWidget::CheckboxWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, uint32 cmd, uint8 hotkey) - : ButtonWidget(boss, x, y, w, h, label, cmd, hotkey), _state(false) { +CheckboxWidget::CheckboxWidget(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), _state(false) { setFlags(WIDGET_ENABLED); _type = kCheckboxWidget; } -CheckboxWidget::CheckboxWidget(GuiObject *boss, const Common::String &name, const Common::String &label, uint32 cmd, uint8 hotkey) - : ButtonWidget(boss, name, label, cmd, hotkey), _state(false) { +CheckboxWidget::CheckboxWidget(GuiObject *boss, const Common::String &name, const Common::String &label, const char *tooltip, uint32 cmd, uint8 hotkey) + : ButtonWidget(boss, name, label, tooltip, cmd, hotkey), _state(false) { setFlags(WIDGET_ENABLED); _type = kCheckboxWidget; } @@ -364,15 +437,15 @@ void RadiobuttonGroup::setEnabled(bool ena) { #pragma mark - -RadiobuttonWidget::RadiobuttonWidget(GuiObject *boss, int x, int y, int w, int h, RadiobuttonGroup *group, int value, const Common::String &label, uint8 hotkey) - : ButtonWidget(boss, x, y, w, h, label, 0, hotkey), _state(false), _value(value), _group(group) { +RadiobuttonWidget::RadiobuttonWidget(GuiObject *boss, int x, int y, int w, int h, RadiobuttonGroup *group, int value, const Common::String &label, const char *tooltip, uint8 hotkey) + : ButtonWidget(boss, x, y, w, h, label, tooltip, 0, hotkey), _state(false), _value(value), _group(group) { setFlags(WIDGET_ENABLED); _type = kRadiobuttonWidget; _group->addButton(this); } -RadiobuttonWidget::RadiobuttonWidget(GuiObject *boss, const Common::String &name, RadiobuttonGroup *group, int value, const Common::String &label, uint8 hotkey) - : ButtonWidget(boss, name, label, 0, hotkey), _state(false), _value(value), _group(group) { +RadiobuttonWidget::RadiobuttonWidget(GuiObject *boss, const Common::String &name, RadiobuttonGroup *group, int value, const Common::String &label, const char *tooltip, uint8 hotkey) + : ButtonWidget(boss, name, label, tooltip, 0, hotkey), _state(false), _value(value), _group(group) { setFlags(WIDGET_ENABLED); _type = kRadiobuttonWidget; _group->addButton(this); @@ -404,15 +477,15 @@ void RadiobuttonWidget::drawWidget() { #pragma mark - -SliderWidget::SliderWidget(GuiObject *boss, int x, int y, int w, int h, uint32 cmd) - : Widget(boss, x, y, w, h), CommandSender(boss), +SliderWidget::SliderWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip, uint32 cmd) + : Widget(boss, x, y, w, h, tooltip), CommandSender(boss), _cmd(cmd), _value(0), _oldValue(0), _valueMin(0), _valueMax(100), _isDragging(false) { setFlags(WIDGET_ENABLED | WIDGET_TRACK_MOUSE | WIDGET_CLEARBG); _type = kSliderWidget; } -SliderWidget::SliderWidget(GuiObject *boss, const Common::String &name, uint32 cmd) - : Widget(boss, name), CommandSender(boss), +SliderWidget::SliderWidget(GuiObject *boss, const Common::String &name, const char *tooltip, uint32 cmd) + : Widget(boss, name, tooltip), CommandSender(boss), _cmd(cmd), _value(0), _oldValue(0), _valueMin(0), _valueMax(100), _isDragging(false) { setFlags(WIDGET_ENABLED | WIDGET_TRACK_MOUSE | WIDGET_CLEARBG); _type = kSliderWidget; @@ -484,14 +557,14 @@ int SliderWidget::posToValue(int pos) { #pragma mark - -GraphicsWidget::GraphicsWidget(GuiObject *boss, int x, int y, int w, int h) - : Widget(boss, x, y, w, h), _gfx(), _alpha(256), _transparency(false) { +GraphicsWidget::GraphicsWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip) + : Widget(boss, x, y, w, h, tooltip), _gfx(), _alpha(256), _transparency(false) { setFlags(WIDGET_ENABLED | WIDGET_CLEARBG); _type = kGraphicsWidget; } -GraphicsWidget::GraphicsWidget(GuiObject *boss, const Common::String &name) - : Widget(boss, name), _gfx(), _alpha(256), _transparency(false) { +GraphicsWidget::GraphicsWidget(GuiObject *boss, const Common::String &name, const char *tooltip) + : Widget(boss, name, tooltip), _gfx(), _alpha(256), _transparency(false) { setFlags(WIDGET_ENABLED | WIDGET_CLEARBG); _type = kGraphicsWidget; } diff --git a/gui/widget.h b/gui/widget.h index 0b075c19db..7b5fe9253f 100644 --- a/gui/widget.h +++ b/gui/widget.h @@ -27,6 +27,7 @@ #include "common/scummsys.h" #include "common/str.h" +#include "common/str-array.h" #include "common/keyboard.h" #include "graphics/surface.h" #include "gui/object.h" @@ -86,6 +87,7 @@ protected: uint16 _id; bool _hasFocus; ThemeEngine::WidgetStateInfo _state; + const char *_tooltip; private: uint16 _flags; @@ -95,8 +97,8 @@ public: static Widget *findWidgetInChain(Widget *start, const char *name); public: - Widget(GuiObject *boss, int x, int y, int w, int h); - Widget(GuiObject *boss, const Common::String &name); + Widget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip = 0); + Widget(GuiObject *boss, const Common::String &name, const char *tooltip = 0); virtual ~Widget(); void init(); @@ -139,6 +141,8 @@ public: uint8 parseHotkey(const Common::String &label); Common::String cleanupHotkey(const Common::String &label); + const char *getTooltip() const { return _tooltip; } + protected: void updateState(int oldFlags, int newFlags); @@ -155,14 +159,39 @@ protected: void handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { assert(_boss); _boss->handleCommand(sender, cmd, data); } }; +class GuiManager; + +class Tooltip : public GuiObject { +public: + Tooltip(GuiManager *guiManager); + + bool isVisible() const { return _visible; } + void draw(); + void reflowLayout(); + void releaseFocus() {} + void setVisible(bool state); + void setMouseXY(int x, int y); + +protected: + Common::String _text; + GuiManager *_guiManager; + bool _visible; + int _mouseX, _mouseY; + int _maxWidth; + int _xdelta, _ydelta; + + Common::StringArray _wrappedLines; + ThemeEngine::StoredState *_storedState; +}; + /* StaticTextWidget */ class StaticTextWidget : public Widget { protected: Common::String _label; Graphics::TextAlign _align; public: - StaticTextWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &text, Graphics::TextAlign align); - StaticTextWidget(GuiObject *boss, const Common::String &name, const Common::String &text); + StaticTextWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &text, Graphics::TextAlign align, const char *tooltip = 0); + StaticTextWidget(GuiObject *boss, const Common::String &name, const Common::String &text, const char *tooltip = 0); void setValue(int value); void setLabel(const Common::String &label); const Common::String &getLabel() const { return _label; } @@ -180,8 +209,8 @@ protected: uint32 _cmd; uint8 _hotkey; public: - ButtonWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, uint32 cmd = 0, uint8 hotkey = 0); - ButtonWidget(GuiObject *boss, const Common::String &name, const Common::String &label, uint32 cmd = 0, uint8 hotkey = 0); + ButtonWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, const char *tooltip = 0, uint32 cmd = 0, uint8 hotkey = 0); + ButtonWidget(GuiObject *boss, const Common::String &name, const Common::String &label, const char *tooltip = 0, uint32 cmd = 0, uint8 hotkey = 0); void setCmd(uint32 cmd) { _cmd = cmd; } uint32 getCmd() const { return _cmd; } @@ -199,8 +228,8 @@ class CheckboxWidget : public ButtonWidget { protected: bool _state; public: - CheckboxWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, uint32 cmd = 0, uint8 hotkey = 0); - CheckboxWidget(GuiObject *boss, const Common::String &name, const Common::String &label, uint32 cmd = 0, uint8 hotkey = 0); + CheckboxWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, const char *tooltip = 0, uint32 cmd = 0, uint8 hotkey = 0); + CheckboxWidget(GuiObject *boss, const Common::String &name, const Common::String &label, const char *tooltip = 0, uint32 cmd = 0, uint8 hotkey = 0); void handleMouseUp(int x, int y, int button, int clickCount); virtual void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); draw(); } @@ -245,8 +274,8 @@ protected: int _value; public: - RadiobuttonWidget(GuiObject *boss, int x, int y, int w, int h, RadiobuttonGroup *group, int value, const Common::String &label, uint8 hotkey = 0); - RadiobuttonWidget(GuiObject *boss, const Common::String &name, RadiobuttonGroup *group, int value, const Common::String &label, uint8 hotkey = 0); + RadiobuttonWidget(GuiObject *boss, int x, int y, int w, int h, RadiobuttonGroup *group, int value, const Common::String &label, const char *tooltip = 0, uint8 hotkey = 0); + RadiobuttonWidget(GuiObject *boss, const Common::String &name, RadiobuttonGroup *group, int value, const Common::String &label, const char *tooltip = 0, uint8 hotkey = 0); void handleMouseUp(int x, int y, int button, int clickCount); virtual void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); draw(); } @@ -272,8 +301,8 @@ protected: bool _isDragging; uint _labelWidth; public: - SliderWidget(GuiObject *boss, int x, int y, int w, int h, uint32 cmd = 0); - SliderWidget(GuiObject *boss, const Common::String &name, uint32 cmd = 0); + SliderWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip = 0, uint32 cmd = 0); + SliderWidget(GuiObject *boss, const Common::String &name, const char *tooltip = 0, uint32 cmd = 0); void setCmd(uint32 cmd) { _cmd = cmd; } uint32 getCmd() const { return _cmd; } @@ -304,8 +333,8 @@ protected: /* GraphicsWidget */ class GraphicsWidget : public Widget { public: - GraphicsWidget(GuiObject *boss, int x, int y, int w, int h); - GraphicsWidget(GuiObject *boss, const Common::String &name); + GraphicsWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip = 0); + GraphicsWidget(GuiObject *boss, const Common::String &name, const char *tooltip = 0); ~GraphicsWidget(); void setGfx(const Graphics::Surface *gfx); -- cgit v1.2.3