diff --git a/src/debugger/gui/RomListWidget.cxx b/src/debugger/gui/RomListWidget.cxx index 861a4112d..5f4487786 100644 --- a/src/debugger/gui/RomListWidget.cxx +++ b/src/debugger/gui/RomListWidget.cxx @@ -40,7 +40,7 @@ RomListWidget::RomListWidget(GuiObject* boss, const GUI::Font& lfont, _textcolorhi = kTextColor; _editMode = false; - _dyCaret = 1; + _dyText = -1; // fixes the vertical position of selected text _cols = w / _fontWidth; _rows = h / _lineHeight; @@ -631,8 +631,8 @@ Common::Rect RomListWidget::getEditRect() const { const int yoffset = std::max(0, (_selectedItem - _currentPos) * _lineHeight); - return Common::Rect(2 + _w - _bytesWidth, 1 + yoffset, - _w, _lineHeight + yoffset); + return Common::Rect(2 + _w - _bytesWidth, 1 + yoffset + 1, + _w, _lineHeight + yoffset + 1); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/FBSurface.cxx b/src/emucore/FBSurface.cxx index c489fc703..cfcf58ff3 100644 --- a/src/emucore/FBSurface.cxx +++ b/src/emucore/FBSurface.cxx @@ -296,21 +296,39 @@ void FBSurface::frameRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h, } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void FBSurface::wrapString(const string& inStr, int pos, string& leftStr, string& rightStr) const +void FBSurface::splitString(const GUI::Font& font, const string& s, int w, + string& left, string& right) const { - for(int i = pos; i > 0; --i) + uInt32 pos; + int w2 = 0; + bool split = false; + + // SLOW algorithm to find the acceptable length. But it is good enough for now. + for(pos = 0; pos < s.size(); ++pos) { - if(isWhiteSpace(inStr[i])) + int charWidth = font.getCharWidth(s[pos]); + if(w2 + charWidth > w) { - leftStr = inStr.substr(0, i); - if(inStr[i] == ' ') // skip leading space after line break - i++; - rightStr = inStr.substr(i); - return; + split = true; + break; } + w2 += charWidth; } - leftStr = inStr.substr(0, pos); - rightStr = inStr.substr(pos); + + if(split) + for(int i = pos; i > 0; --i) + { + if(isWhiteSpace(s[i])) + { + left = s.substr(0, i); + if(s[i] == ' ') // skip leading space after line break + i++; + right = s.substr(i); + return; + } + } + left = s.substr(0, pos); + right = s.substr(pos); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -340,21 +358,9 @@ int FBSurface::drawString(const GUI::Font& font, const string& s, while (font.getStringWidth(inStr) > w && h >= font.getFontHeight() * 2) { // String is too wide. - uInt32 i; string leftStr, rightStr; - int w2 = 0; - // SLOW algorithm to find the acceptable length. But it is good enough for now. - for(i = 0; i < inStr.size(); ++i) - { - int charWidth = font.getCharWidth(inStr[i]); - if(w2 + charWidth > w) - break; - - w2 += charWidth; - //str += inStr[i]; - } - wrapString(inStr, i, leftStr, rightStr); + splitString(font, inStr, w, leftStr, rightStr); drawString(font, leftStr, x, y, w, color, align, deltax, false, shadowColor); h -= font.getFontHeight(); y += font.getFontHeight(); diff --git a/src/emucore/FBSurface.hxx b/src/emucore/FBSurface.hxx index 71bddc289..de19fca28 100644 --- a/src/emucore/FBSurface.hxx +++ b/src/emucore/FBSurface.hxx @@ -247,6 +247,18 @@ class FBSurface ColorId color, TextAlign align = TextAlign::Left, int deltax = 0, bool useEllipsis = true, ColorId shadowColor = kNone); + /** + Splits a given string to a given width considering whitespaces. + + @param font The font to draw the string with + @param s The string to split + @param w The width of the string area + @param left The left part of the split string + @param right The right part of the split string + */ + void splitString(const GUI::Font& font, const string& s, int w, + string& left, string& right) const; + /** The rendering attributes that can be modified for this texture. These probably can only be implemented in child FBSurfaces where @@ -383,9 +395,6 @@ class FBSurface */ bool checkBounds(const uInt32 x, const uInt32 y) const; - void wrapString(const string& inStr, int pos, - string& leftStr, string& rightStr) const; - /** Check if the given character is a whitespace. @param s Character to check diff --git a/src/gui/EditableWidget.cxx b/src/gui/EditableWidget.cxx index 8ff411f83..e015dd899 100644 --- a/src/gui/EditableWidget.cxx +++ b/src/gui/EditableWidget.cxx @@ -379,8 +379,8 @@ void EditableWidget::drawCaretSelection() x += _x; y += _y; - s.fillRect(x - 1, y + 1 + _dyCaret, w + 1, h - 3, kTextColorHi); - s.drawString(_font, text, x, y + 1, w, h, + s.fillRect(x - 1, y + 1, w + 1, h - 3, kTextColorHi); + s.drawString(_font, text, x, y + 1 + _dyText, w, h, kTextColorInv, TextAlign::Left, 0, false); } @@ -397,8 +397,8 @@ void EditableWidget::drawCaretSelection() x += _x; y += _y; - s.vLine(x, y + 1 + _dyCaret, y + editRect.h() - 3, color); - s.vLine(x - 1, y + 1 + _dyCaret, y + editRect.h() - 3, color); + s.vLine(x, y + 1, y + editRect.h() - 3, color); + s.vLine(x - 1, y + 1, y + editRect.h() - 3, color); clearDirty(); } } diff --git a/src/gui/EditableWidget.hxx b/src/gui/EditableWidget.hxx index 497c2a4e8..3ffe09a65 100644 --- a/src/gui/EditableWidget.hxx +++ b/src/gui/EditableWidget.hxx @@ -125,7 +125,7 @@ class EditableWidget : public Widget, public CommandSender protected: int _editScrollOffset{0}; bool _editMode{true}; - int _dyCaret{0}; + int _dyText{0}; private: TextFilter _filter; diff --git a/src/gui/ToolTip.cxx b/src/gui/ToolTip.cxx index 5d37478db..5cfed635c 100644 --- a/src/gui/ToolTip.cxx +++ b/src/gui/ToolTip.cxx @@ -27,7 +27,6 @@ // TODOs: // - option to disable tips -// - multi line tips // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ToolTip::ToolTip(Dialog& dialog, const GUI::Font& font) @@ -47,8 +46,8 @@ void ToolTip::setFont(const GUI::Font& font) myTextXOfs = fontHeight < 24 ? 5 : 8; myTextYOfs = fontHeight < 24 ? 2 : 3; - myWidth = fontWidth * MAX_LEN + myTextXOfs * 2; - myHeight = fontHeight + myTextYOfs * 2; + myWidth = fontWidth * MAX_COLUMNS + myTextXOfs * 2; + myHeight = fontHeight * MAX_ROWS + myTextYOfs * 2; mySurface = myDialog.instance().frameBuffer().allocateSurface(myWidth, myHeight); } @@ -129,9 +128,30 @@ void ToolTip::show(const string& tip) { myTipPos = myMousePos; + uInt32 maxWidth = std::min(myWidth - myTextXOfs * 2, uInt32(myFont->getStringWidth(tip))); + + mySurface->fillRect(1, 1, maxWidth + myTextXOfs * 2 - 2, myHeight - 2, kWidColor); + int lines = std::min(MAX_ROWS, + uInt32(mySurface->drawString(*myFont, tip, myTextXOfs, myTextYOfs, + maxWidth, myHeight - myTextYOfs * 2, + kTextColor))); + // Calculate maximum width of drawn string lines + uInt32 width = 0; + string inStr = tip; + for(int i = 0; i < lines; ++i) + { + string leftStr, rightStr; + + mySurface->splitString(*myFont, inStr, maxWidth, leftStr, rightStr); + width = std::max(width, uInt32(myFont->getStringWidth(leftStr))); + inStr = rightStr; + } + width += myTextXOfs * 2; + + // Calculate and set surface size and position + const uInt32 height = std::min(myHeight, myFont->getFontHeight() * lines + myTextYOfs * 2); const uInt32 V_GAP = 1; const uInt32 H_CURSOR = 18; - uInt32 width = std::min(myWidth, myFont->getStringWidth(tip) + myTextXOfs * 2); // Note: The rects include HiDPI scaling const Common::Rect imageRect = myDialog.instance().frameBuffer().imageRect(); const Common::Rect dialogRect = myDialog.surface().dstRect(); @@ -139,24 +159,20 @@ void ToolTip::show(const string& tip) const Int32 xAbs = myTipPos.x + dialogRect.x() / myScale; const uInt32 yAbs = myTipPos.y + dialogRect.y() / myScale; Int32 x = std::min(xAbs, Int32(imageRect.w() / myScale - width)); - const uInt32 y = (yAbs + myHeight + H_CURSOR > imageRect.h() / myScale) - ? yAbs - myHeight - V_GAP + const uInt32 y = (yAbs + height + H_CURSOR > imageRect.h() / myScale) + ? yAbs - height - V_GAP : yAbs + H_CURSOR / myScale + V_GAP; if(x < 0) { x = 0; - width = imageRect.w() / myScale; + width = std::min(width, imageRect.w() / myScale); } - mySurface->setSrcSize(width, myHeight); - mySurface->setDstSize(width * myScale, myHeight * myScale); + mySurface->setSrcSize(width, height); + mySurface->setDstSize(width * myScale, height * myScale); mySurface->setDstPos(x * myScale, y * myScale); - - mySurface->frameRect(0, 0, width, myHeight, kColor); - mySurface->fillRect(1, 1, width - 2, myHeight - 2, kWidColor); - mySurface->drawString(*myFont, tip, myTextXOfs, myTextYOfs, - width - myTextXOfs * 2, myHeight - myTextYOfs * 2, kTextColor); + mySurface->frameRect(0, 0, width, height, kColor); myTipShown = true; myDialog.instance().frameBuffer().setPendingRender(); diff --git a/src/gui/ToolTip.hxx b/src/gui/ToolTip.hxx index 2c9f95037..71da6dc13 100644 --- a/src/gui/ToolTip.hxx +++ b/src/gui/ToolTip.hxx @@ -33,9 +33,13 @@ class FBSurface; class ToolTip { + private: + static constexpr uInt32 MAX_COLUMNS = 60; + static constexpr uInt32 MAX_ROWS = 5; + public: // Maximum tooltip length - static constexpr uInt32 MAX_LEN = 80; + static constexpr uInt32 MAX_LEN = MAX_COLUMNS * MAX_ROWS; ToolTip(Dialog& dialog, const GUI::Font& font); ~ToolTip() = default;