From a31e4c61842b57fa6f610cbd424c735396d445b8 Mon Sep 17 00:00:00 2001 From: Thomas Jentzsch Date: Wed, 7 Aug 2019 15:17:19 +0200 Subject: [PATCH] add multi line string drawing (used in Input Dialog) --- src/emucore/FBSurface.cxx | 68 ++++++++++++++++++++++++++++++++++ src/emucore/FBSurface.hxx | 29 +++++++++++++++ src/gui/EditTextWidget.cxx | 2 +- src/gui/EventMappingWidget.cxx | 5 ++- 4 files changed, 101 insertions(+), 3 deletions(-) diff --git a/src/emucore/FBSurface.cxx b/src/emucore/FBSurface.cxx index 79740d7b0..1edb85c2d 100644 --- a/src/emucore/FBSurface.cxx +++ b/src/emucore/FBSurface.cxx @@ -309,6 +309,74 @@ void FBSurface::frameRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h, } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FBSurface::wrapString(const string inStr, int pos, string& leftStr, string& rightStr) const +{ + int i; + + for(i = pos; i > 0; --i) + { + if(isWhiteSpace(inStr[i])) + { + leftStr = inStr.substr(0, i); + if(inStr[i] == ' ') // skip leading space after line break + i++; + rightStr = inStr.substr(i); + return; + } + } + leftStr = inStr.substr(0, pos); + rightStr = inStr.substr(pos); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool FBSurface::isWhiteSpace(const char s) const +{ + const string WHITESPACES = " ,.;:+-"; + int i; + + for(i = 0; i < WHITESPACES.length(); ++i) + if(s == WHITESPACES[i]) + return true; + + return false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FBSurface::drawString(const GUI::Font& font, const string& s, + int x, int y, int w, int h, + ColorId color, TextAlign align, + int deltax, bool useEllipsis, ColorId shadowColor) +{ + string inStr = s; + + // draw multiline string + 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); + drawString(font, leftStr, x, y, w, color, align, deltax, false, shadowColor); + h -= font.getFontHeight(); + y += font.getFontHeight(); + inStr = rightStr; + } + drawString(font, inStr, x, y, w, color, align, deltax, useEllipsis, shadowColor); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FBSurface::drawString(const GUI::Font& font, const string& s, int x, int y, int w, diff --git a/src/emucore/FBSurface.hxx b/src/emucore/FBSurface.hxx index f1aa8ffb7..54a46e15c 100644 --- a/src/emucore/FBSurface.hxx +++ b/src/emucore/FBSurface.hxx @@ -203,6 +203,26 @@ class FBSurface virtual void frameRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h, ColorId color, FrameStyle style = FrameStyle::Solid); + /** + This method should be called to draw the specified string. + + @param font The font to draw the string with + @param s The string to draw + @param x The x coordinate + @param y The y coordinate + @param w The width of the string area + @param h The height of the string area (for multi line strings) + @param color The color of the text + @param align The alignment of the text in the string width area + @param deltax FIXME + @param useEllipsis Whether to use '...' when the string is too long + */ + + virtual void drawString( + const GUI::Font& font, const string& s, int x, int y, int w, int h, + ColorId color, TextAlign align = TextAlign::Left, + int deltax = 0, bool useEllipsis = true, ColorId shadowColor = kNone); + /** This method should be called to draw the specified string. @@ -344,6 +364,15 @@ 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 c Character to check + @return True if whitespace character + */ + bool isWhiteSpace(const char s) const; + protected: static const uInt32* myPalette; uInt32* myPixels; diff --git a/src/gui/EditTextWidget.cxx b/src/gui/EditTextWidget.cxx index 256d9f4b9..a2fe4de26 100644 --- a/src/gui/EditTextWidget.cxx +++ b/src/gui/EditTextWidget.cxx @@ -93,7 +93,7 @@ void EditTextWidget::drawWidget(bool hilite) // Draw the text adjustOffset(); - s.drawString(_font, editString(), _x + 2, _y + 2, getEditRect().w(), + s.drawString(_font, editString(), _x + 2, _y + 2, getEditRect().w(), getEditRect().h(), _changed && onTop && isEnabled() ? kDbgChangedTextColor : onTop && isEnabled() ? _textcolor : kColor, diff --git a/src/gui/EventMappingWidget.cxx b/src/gui/EventMappingWidget.cxx index f62adf9db..81b52158f 100644 --- a/src/gui/EventMappingWidget.cxx +++ b/src/gui/EventMappingWidget.cxx @@ -56,10 +56,11 @@ EventMappingWidget::EventMappingWidget(GuiObject* boss, const GUI::Font& font, buttonHeight = font.getLineHeight() + 4; const int HBORDER = 8; const int VBORDER = 8; + const int ACTION_LINES = 2; int xpos = HBORDER, ypos = VBORDER; myActionsList = new StringListWidget(boss, font, xpos, ypos, - _w - buttonWidth - HBORDER * 2 - 8, _h - 3*lineHeight - VBORDER); + _w - buttonWidth - HBORDER * 2 - 8, _h - (2 + ACTION_LINES) * lineHeight - VBORDER); myActionsList->setTarget(this); myActionsList->setEditable(false); myActionsList->setList(actions); @@ -117,7 +118,7 @@ EventMappingWidget::EventMappingWidget(GuiObject* boss, const GUI::Font& font, fontHeight, "Action", TextAlign::Left); myKeyMapping = new EditTextWidget(boss, font, xpos + t->getWidth() + 8, ypos, - _w - xpos - t->getWidth() - 8 - HBORDER, lineHeight, ""); + _w - xpos - t->getWidth() - 8 - HBORDER, lineHeight * ACTION_LINES, ""); myKeyMapping->setEditable(false, true); myKeyMapping->clearFlags(Widget::FLAG_RETAIN_FOCUS); }