From 120c3062864f208ddbb2f385e50deeef3dbbcd1b Mon Sep 17 00:00:00 2001 From: thrust26 Date: Mon, 16 Nov 2020 12:26:01 +0100 Subject: [PATCH] added initial tool tip functionality removed duplicate _editMode in DataGridWidget --- src/debugger/gui/DataGridWidget.cxx | 1 + src/debugger/gui/DataGridWidget.hxx | 1 - src/gui/Dialog.cxx | 8 +++ src/gui/Dialog.hxx | 4 +- src/gui/EditTextWidget.cxx | 1 + src/gui/LauncherDialog.cxx | 3 ++ src/gui/ToolTip.cxx | 79 ++++++++++++++++++++++++----- src/gui/ToolTip.hxx | 60 ++++++++++++++++++---- src/gui/Widget.cxx | 12 ++++- src/gui/Widget.hxx | 4 +- 10 files changed, 147 insertions(+), 26 deletions(-) diff --git a/src/debugger/gui/DataGridWidget.cxx b/src/debugger/gui/DataGridWidget.cxx index 32358dd05..877d96c6a 100644 --- a/src/debugger/gui/DataGridWidget.cxx +++ b/src/debugger/gui/DataGridWidget.cxx @@ -45,6 +45,7 @@ DataGridWidget::DataGridWidget(GuiObject* boss, const GUI::Font& font, _base(base) { _flags = Widget::FLAG_ENABLED | Widget::FLAG_RETAIN_FOCUS | Widget::FLAG_WANTS_RAWDATA; + _editMode = false; // Make sure all lists contain some default values _hiliteList.clear(); diff --git a/src/debugger/gui/DataGridWidget.hxx b/src/debugger/gui/DataGridWidget.hxx index 114097b01..82eca7fbc 100644 --- a/src/debugger/gui/DataGridWidget.hxx +++ b/src/debugger/gui/DataGridWidget.hxx @@ -128,7 +128,6 @@ class DataGridWidget : public EditableWidget BoolArray _changedList; BoolArray _hiliteList; - bool _editMode{false}; int _selectedItem{0}; StellaKey _currentKeyDown{KBDK_UNKNOWN}; string _backupString; diff --git a/src/gui/Dialog.cxx b/src/gui/Dialog.cxx index 18dd20cbf..f58d98536 100644 --- a/src/gui/Dialog.cxx +++ b/src/gui/Dialog.cxx @@ -27,6 +27,7 @@ #include "Dialog.hxx" #include "Widget.hxx" #include "TabWidget.hxx" +#include "ToolTip.hxx" #include "ContextMenu.hxx" #include "PopUpWidget.hxx" @@ -65,6 +66,8 @@ Dialog::Dialog(OSystem& instance, DialogContainer& parent, const GUI::Font& font attr.blending = true; attr.blendalpha = 25; // darken background dialogs by 25% _shadeSurface->applyAttributes(); + + _toolTip = make_unique(instance, *this, font); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -266,6 +269,8 @@ void Dialog::render() _shadeSurface->setDstRect(_surface->dstRect()); _shadeSurface->render(); } + + _toolTip->render(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -588,6 +593,9 @@ void Dialog::handleMouseMoved(int x, int y) { Widget* w; + // Update mouse coordinates for tooltips + _toolTip->update(x, y); + if(_focusedWidget && !_dragWidget) { w = _focusedWidget; diff --git a/src/gui/Dialog.hxx b/src/gui/Dialog.hxx index 0d0c57bc3..b92b8e383 100644 --- a/src/gui/Dialog.hxx +++ b/src/gui/Dialog.hxx @@ -26,6 +26,7 @@ class OSystem; class DialogContainer; class TabWidget; class CommandSender; +class ToolTip; #include "Stack.hxx" #include "Widget.hxx" @@ -122,6 +123,7 @@ class Dialog : public GuiObject */ bool shouldResize(uInt32& w, uInt32& h) const; + ToolTip& tooltip() { return *_toolTip; }; //bool enableToolTip(); //void showToolTip(int x, int y); //void hideToolTip(); @@ -203,7 +205,7 @@ class Dialog : public GuiObject string _title; int _th{0}; int _layer{0}; - int _toolTipTimer{0}; + unique_ptr _toolTip; Common::FixedStack> mySurfaceStack; diff --git a/src/gui/EditTextWidget.cxx b/src/gui/EditTextWidget.cxx index c818f3cf0..d3e4587a5 100644 --- a/src/gui/EditTextWidget.cxx +++ b/src/gui/EditTextWidget.cxx @@ -18,6 +18,7 @@ #include "OSystem.hxx" #include "FBSurface.hxx" #include "Dialog.hxx" +#include "ToolTip.hxx" #include "Font.hxx" #include "EditTextWidget.hxx" diff --git a/src/gui/LauncherDialog.cxx b/src/gui/LauncherDialog.cxx index 8018bcb44..abae25742 100644 --- a/src/gui/LauncherDialog.cxx +++ b/src/gui/LauncherDialog.cxx @@ -120,12 +120,14 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent, // Show the filter input field xpos -= fwidth + LBL_GAP; myPattern = new EditTextWidget(this, font, xpos, ypos - 2, fwidth, lineHeight, ""); + myPattern->setToolTip("Enter a filter text to reduce file list."); // Show the "Filter" label xpos -= lwidth3 + LBL_GAP; new StaticTextWidget(this, font, xpos, ypos, lblFilter); // Show the checkbox for all files xpos -= lwidth2 + LBL_GAP * 3; myAllFiles = new CheckboxWidget(this, font, xpos, ypos, lblAllFiles, kAllfilesCmd); + myAllFiles->setToolTip("Uncheck to show ROM files only."); wid.push_back(myAllFiles); wid.push_back(myPattern); } @@ -178,6 +180,7 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent, #ifndef BSPF_MACOS myStartButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 0) / 4, buttonHeight, "Select", kLoadROMCmd); + myStartButton->setToolTip("Start emulation of selected ROM."); wid.push_back(myStartButton); xpos += (buttonWidth + 0) / 4 + BUTTON_GAP; diff --git a/src/gui/ToolTip.cxx b/src/gui/ToolTip.cxx index 53cbea0c3..72ecb47ad 100644 --- a/src/gui/ToolTip.cxx +++ b/src/gui/ToolTip.cxx @@ -16,25 +16,80 @@ //============================================================================ #include "OSystem.hxx" +#include "FrameBuffer.hxx" +#include "FBSurface.hxx" + #include "Font.hxx" #include "Dialog.hxx" -#include "DialogContainer.hxx" +#include "Widget.hxx" #include "ToolTip.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -ToolTip::ToolTip(OSystem& instance, DialogContainer& parent, - const GUI::Font& font) - : Dialog(instance, parent, font) +ToolTip::ToolTip(OSystem& instance, Dialog& dialog, const GUI::Font& font) + : myDialog(dialog), + myFont(font) { - const int lineHeight = font.getLineHeight(), - fontWidth = font.getMaxCharWidth(), - fontHeight = font.getFontHeight(), - buttonWidth = font.getStringWidth("Previous") + fontWidth * 2.5, - buttonHeight = font.getLineHeight() * 1.25; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int VGAP = fontHeight / 4; + const int fontWidth = font.getMaxCharWidth(), + fontHeight = font.getFontHeight(); + + myTextXOfs = fontHeight < 24 ? 5 : 8; //3 : 5; + myWidth = myTextXOfs * 2 + fontWidth * MAX_LEN; + myHeight = fontHeight + TEXT_Y_OFS * 2; + mySurface = instance.frameBuffer().allocateSurface(myWidth, myHeight); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void ToolTip::request(Widget* widget) +{ + if(myWidget != widget) + { + release(); + } + if(myTimer == DELAY_TIME) + { + string text = widget->getToolTip(); + int width = std::min(myWidth, myFont.getStringWidth(text) + myTextXOfs * 2); + int yOffset = 20; // TODO: query cursor height + + myWidget = widget; + // TODO: limit to app or screen size + mySurface->setSrcSize(width, myHeight); + mySurface->setDstSize(width, myHeight); + mySurface->setDstPos(myPos.x, myPos.y + yOffset); + + mySurface->frameRect(0, 0, width, myHeight, kColor); + mySurface->fillRect(1, 1, width - 2, myHeight - 2, kWidColor); + mySurface->drawString(myFont, text, myTextXOfs, TEXT_Y_OFS, + width - myTextXOfs * 2, myHeight - TEXT_Y_OFS * 2, kTextColor); + myDialog.setDirtyChain(); + } + myTimer++; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void ToolTip::release() +{ + if(myWidget != nullptr) + { + myTimer = 0; + myWidget = nullptr; + myDialog.setDirtyChain(); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void ToolTip::render() +{ + if(myWidget != nullptr) + mySurface->render(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void ToolTip::update(int x, int y) +{ + if(myWidget != nullptr && x != myPos.x || y != myPos.y) + release(); + myPos.x = x; + myPos.y = y; +} diff --git a/src/gui/ToolTip.hxx b/src/gui/ToolTip.hxx index 2066bd3df..7ba4dc044 100644 --- a/src/gui/ToolTip.hxx +++ b/src/gui/ToolTip.hxx @@ -18,22 +18,62 @@ #ifndef TOOL_TIP_HXX #define TOOL_TIP_HXX -class OSystem; -class DialogContainer; - /** * Class for providing tooltip functionality * * @author Thomas Jentzsch */ -class ToolTip : public Dialog -{ - public: - public: - ToolTip(OSystem& instance, DialogContainer& parent, - const GUI::Font& font); - ~ToolTip() override = default; +class OSystem; +class FBSurface; +class Widget; + +#include "Rect.hxx" + +class ToolTip +{ +public: + // Maximum tooltip length + static constexpr int MAX_LEN = 60; + + ToolTip(OSystem& instance, Dialog& dialog, const GUI::Font& font); + ~ToolTip() = default; + + /** + Request a tooltip display + */ + void request(Widget* widget); + + + /** + Hide an existing tooltip (if displayed) + */ + void release(); + + /** + Update with current mouse position + */ + void update(int x, int y); + + /* + Render the tooltip + */ + void render(); + +private: + static constexpr uInt32 DELAY_TIME = 45; // display delay + static constexpr int TEXT_Y_OFS = 2; + + const GUI::Font& myFont; + Dialog& myDialog; + + Widget* myWidget{nullptr}; + uInt32 myTimer{0}; + Common::Point myPos; + int myWidth{0}; + int myHeight{0}; + int myTextXOfs{0}; + shared_ptr mySurface; }; #endif diff --git a/src/gui/Widget.cxx b/src/gui/Widget.cxx index f33d27146..f37f8840c 100644 --- a/src/gui/Widget.cxx +++ b/src/gui/Widget.cxx @@ -21,6 +21,7 @@ #include "bspf.hxx" #include "Command.hxx" #include "Dialog.hxx" +#include "ToolTip.hxx" #include "FBSurface.hxx" #include "GuiObject.hxx" #include "OSystem.hxx" @@ -74,7 +75,8 @@ void Widget::tick() { if(isEnabled()) { - //if(_hasFocus && hasToolTip()) + if(isHighlighted() && hasToolTip()) + dialog().tooltip().request(this); //{ // if(dialog().enableToolTip()) // dialog().showToolTip(10, 10); @@ -208,6 +210,14 @@ void Widget::setEnabled(bool e) else clearFlags(Widget::FLAG_ENABLED); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Widget::setToolTip(const string& text) +{ + assert(text.length() <= ToolTip::MAX_LEN); + + _toolTipText = text; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Widget* Widget::findWidgetInChain(Widget* w, int x, int y) { diff --git a/src/gui/Widget.hxx b/src/gui/Widget.hxx index 5ee8ef0b1..98e36863f 100644 --- a/src/gui/Widget.hxx +++ b/src/gui/Widget.hxx @@ -87,6 +87,7 @@ class Widget : public GuiObject bool isEnabled() const { return _flags & FLAG_ENABLED; } bool isVisible() const override { return !(_flags & FLAG_INVISIBLE); } + bool isHighlighted() const { return _flags & FLAG_HILITED; } virtual bool wantsFocus() const { return _flags & FLAG_RETAIN_FOCUS; } bool wantsTab() const { return _flags & FLAG_WANTS_TAB; } bool wantsRaw() const { return _flags & FLAG_WANTS_RAWDATA; } @@ -102,7 +103,8 @@ class Widget : public GuiObject void setBGColorHi(ColorId color) { _bgcolorhi = color; setDirty(); } void setShadowColor(ColorId color) { _shadowcolor = color; setDirty(); } - void setToolTip(const string& text) { _toolTipText = text; } + void setToolTip(const string& text); + const string& getToolTip() const { return _toolTipText; } bool hasToolTip() const { return !_toolTipText.empty(); } virtual void loadConfig() { }