implement line wrap for text messages

This commit is contained in:
Eduardo Bart 2012-01-24 22:50:30 -02:00
parent dd457b2b2f
commit 99ff5ce24c
8 changed files with 120 additions and 95 deletions

View File

@ -5,16 +5,15 @@ importStyle 'textmessage.otui'
-- private variables -- private variables
local MessageTypes = { local MessageTypes = {
consoleRed = { color = '#F55E5E', consoleTab = 'Server Log' }, consoleRed = { color = '#F55E5E', consoleTab = 'Default' }, -- 18
eventOrange = { color = '#FE6500', consoleTab = 'Default' }, consoleOrange = { color = '#FE6500', consoleTab = 'Default' }, -- 19/20
consoleOrange = { color = '#FE6500', consoleTab = 'Default' }, consoleBlue = { color = '#9F9DFD', consoleTab = 'Default' }, -- 27
warning = { color = '#F55E5E', consoleTab = 'Server Log', windowLocation = 'center' }, warning = { color = '#F55E5E', consoleTab = 'Server Log', windowLocation = 'center' }, -- 21
eventAdvance = { color = '#FFFFFF', consoleTab = 'Server Log', windowLocation = 'center', consoleOption = 'showEventMessagesInConsole' }, infoDescription = { color = '#00EB00', consoleTab = 'Server Log', windowLocation = 'center', consoleOption = 'showInfoMessagesInConsole' }, -- 25
eventDefault = { color = '#FFFFFF', consoleTab = 'Server Log', windowLocation = 'bottom', consoleOption = 'showEventMessagesInConsole' }, eventAdvance = { color = '#FFFFFF', consoleTab = 'Server Log', windowLocation = 'center', consoleOption = 'showEventMessagesInConsole' }, -- 22
statusDefault = { color = '#FFFFFF', consoleTab = 'Server Log', windowLocation = 'bottom', consoleOption = 'showStatusMessagesInConsole' }, eventDefault = { color = '#FFFFFF', consoleTab = 'Server Log', windowLocation = 'bottom', consoleOption = 'showEventMessagesInConsole' }, -- 23
infoDescription = { color = '#00EB00', consoleTab = 'Server Log', windowLocation = 'center', consoleOption = 'showInfoMessagesInConsole' }, statusDefault = { color = '#FFFFFF', consoleTab = 'Server Log', windowLocation = 'bottom', consoleOption = 'showStatusMessagesInConsole' }, -- 24
statusSmall = { color = '#FFFFFF', windowLocation = 'bottom' }, statusSmall = { color = '#FFFFFF', windowLocation = 'bottom' }, -- 26
consoleBlue = { color = '#9F9DFD', consoleTab = 'Default' },
} }
local bottomLabelWidget local bottomLabelWidget
@ -48,6 +47,10 @@ local function displayMessage(msgtype, msg, time)
label:setStyle(style) label:setStyle(style)
label:setColor(msgtype.color) label:setColor(msgtype.color)
if msgtype.windowLocation == 'center' then
label:wrapText()
end
if not time then if not time then
time = math.max(#msg * 75, 3000) time = math.max(#msg * 75, 3000)
else else

View File

@ -2,9 +2,8 @@ CenterLabel < GameLabel
font: verdana-11px-rounded font: verdana-11px-rounded
height: 64 height: 64
text-align: center text-align: center
anchors.verticalCenter: parent.verticalCenter anchors.centerIn: parent
anchors.left: parent.left size: 360 264
anchors.right: parent.right
BottomLabel < GameLabel BottomLabel < GameLabel
font: verdana-11px-rounded font: verdana-11px-rounded

View File

@ -282,3 +282,56 @@ void Font::calculateGlyphsWidthsAutomatically(const Size& glyphSize)
m_glyphsSize[glyph].resize(width, m_glyphHeight); m_glyphsSize[glyph].resize(width, m_glyphHeight);
} }
} }
std::string Font::wrapText(const std::string& text, int maxWidth)
{
std::string outText;
std::string line;
std::vector<std::string> words;
std::vector<std::string> wordsSplit = Fw::split(text);
// break huge words into small ones
for(uint i=0;i<wordsSplit.size();++i) {
const std::string& word = wordsSplit[i];
int wordWidth = calculateTextRectSize(word).width();
if(wordWidth > maxWidth) {
std::string newWord;
for(uint j=0;j<word.length();++j) {
std::string candidate = newWord + word[j];
if(j != word.length() - 1)
candidate += "-";
int candidateWidth = calculateTextRectSize(candidate).width();
if(candidateWidth > maxWidth) {
newWord += "-";
words.push_back(newWord);
newWord = "";
}
newWord += word[j];
}
words.push_back(newWord);
} else
words.push_back(word);
}
// compose lines
for(uint i=0;i<words.size();++i) {
std::string candidate = line + words[i];
int candidateWidth = calculateTextRectSize(candidate).width();
if(candidateWidth > maxWidth) {
if(!line.empty())
outText += line.substr(0, line.length()-1) + "\n";
line = "";
}
line += words[i] + " ";
}
outText += line;
outText = outText.substr(0, outText.length()-1);
return outText;
}

View File

@ -54,6 +54,8 @@ public:
/// Simulate render and calculate text size /// Simulate render and calculate text size
Size calculateTextRectSize(const std::string& text); Size calculateTextRectSize(const std::string& text);
std::string wrapText(const std::string& text, int maxWidth);
std::string getName() const { return m_name; } std::string getName() const { return m_name; }
int getGlyphHeight() const { return m_glyphHeight; } int getGlyphHeight() const { return m_glyphHeight; }
const Rect* getGlyphsTextureCoords() const { return m_glyphsTextureCoords; } const Rect* getGlyphsTextureCoords() const { return m_glyphsTextureCoords; }

View File

@ -266,6 +266,7 @@ void Application::registerLuaFunctions()
g_lua.bindClassMemberFunction<UIWidget>("getImageBorderLeft", &UIWidget::getImageBorderLeft); g_lua.bindClassMemberFunction<UIWidget>("getImageBorderLeft", &UIWidget::getImageBorderLeft);
g_lua.bindClassMemberFunction<UIWidget>("resizeToText", &UIWidget::resizeToText); g_lua.bindClassMemberFunction<UIWidget>("resizeToText", &UIWidget::resizeToText);
g_lua.bindClassMemberFunction<UIWidget>("clearText", &UIWidget::clearText); g_lua.bindClassMemberFunction<UIWidget>("clearText", &UIWidget::clearText);
g_lua.bindClassMemberFunction<UIWidget>("wrapText", &UIWidget::wrapText);
g_lua.bindClassMemberFunction<UIWidget>("setText", &UIWidget::setText); g_lua.bindClassMemberFunction<UIWidget>("setText", &UIWidget::setText);
g_lua.bindClassMemberFunction<UIWidget>("setTextAlign", &UIWidget::setTextAlign); g_lua.bindClassMemberFunction<UIWidget>("setTextAlign", &UIWidget::setTextAlign);
g_lua.bindClassMemberFunction<UIWidget>("setTextOffset", &UIWidget::setTextOffset); g_lua.bindClassMemberFunction<UIWidget>("setTextOffset", &UIWidget::setTextOffset);

View File

@ -434,6 +434,7 @@ protected:
public: public:
void resizeToText() { setSize(getTextSize()); } void resizeToText() { setSize(getTextSize()); }
void clearText() { setText(""); } void clearText() { setText(""); }
void wrapText();
void setText(const std::string& text); void setText(const std::string& text);
void setTextAlign(Fw::AlignmentFlag align) { m_textAlign = align; m_textMustRecache = true; } void setTextAlign(Fw::AlignmentFlag align) { m_textAlign = align; m_textMustRecache = true; }

View File

@ -84,6 +84,11 @@ void UIWidget::onFontChange(const std::string& font)
callLuaField("onFontChange", font); callLuaField("onFontChange", font);
} }
void UIWidget::wrapText()
{
setText(m_font->wrapText(m_text, getWidth()));
}
void UIWidget::setText(const std::string& text) void UIWidget::setText(const std::string& text)
{ {
if(m_text == text) if(m_text == text)

View File

@ -267,8 +267,8 @@ namespace Proto {
enum MessageTypes { enum MessageTypes {
#if PROTOCOL==860 #if PROTOCOL==860
MessageConsoleRed = 18, MessageConsoleRed = 18,
MessageEventOrange,
MessageConsoleOrange, MessageConsoleOrange,
MessageConsoleOrange2,
MessageWarning, MessageWarning,
MessageEventAdvance, MessageEventAdvance,
MessageEventDefault, MessageEventDefault,
@ -277,8 +277,8 @@ namespace Proto {
MessageStatusSmall, MessageStatusSmall,
MessageConsoleBlue MessageConsoleBlue
#elif PROTOCOL==862 #elif PROTOCOL==862
MessageEventOrange = 13, MessageConsoleOrange = 13,
MessageConsoleOrange, MessageConsoleOrange2,
MessageWarning, MessageWarning,
MessageEventAdvance, MessageEventAdvance,
MessageEventDefault, MessageEventDefault,
@ -301,35 +301,21 @@ namespace Proto {
inline std::string translateSpeakType(int type) { inline std::string translateSpeakType(int type) {
switch(type) { switch(type) {
case Proto::SpeakSay: case Proto::SpeakSay: return "say";
return "say"; case Proto::SpeakWhisper: return "whisper";
case Proto::SpeakWhisper: case Proto::SpeakYell: return "yell";
return "whisper"; case Proto::SpeakMonsterSay: return "monsterSay";
case Proto::SpeakYell: case Proto::SpeakMonsterYell: return "monsterYell";
return "yell"; case Proto::SpeakPrivateNpcToPlayer: return "npcToPlayer";
case Proto::SpeakMonsterSay: case Proto::SpeakChannelYellow: return "channelYellow";
return "monsterSay"; case Proto::SpeakChannelWhite: return "channelWhite";
case Proto::SpeakMonsterYell: case Proto::SpeakChannelRed: return "channelRed";
return "monsterYell"; case Proto::SpeakChannelRed2: return "channelRed";
case Proto::SpeakPrivateNpcToPlayer: case Proto::SpeakChannelOrange: return "channelOrange";
return "npcToPlayer"; case Proto::SpeakPrivate: return "private";
case Proto::SpeakChannelYellow: case Proto::SpeakPrivatePlayerToNpc: return "playerToNpc";
return "channelYellow"; case Proto::SpeakBroadcast: return "broadcast";
case Proto::SpeakChannelWhite: case Proto::SpeakPrivateRed: return "privateRed";
return "channelWhite";
case Proto::SpeakChannelRed:
case Proto::SpeakChannelRed2:
return "channelRed";
case Proto::SpeakChannelOrange:
return "channelOrange";
case Proto::SpeakPrivate:
return "private";
case Proto::SpeakPrivatePlayerToNpc:
return "playerToNpc";
case Proto::SpeakBroadcast:
return "broadcast";
case Proto::SpeakPrivateRed:
return "privateRed";
default: default:
logError("unknown protocol speak type ", type); logError("unknown protocol speak type ", type);
return "unknown"; return "unknown";
@ -337,36 +323,21 @@ namespace Proto {
} }
inline int translateSpeakTypeDesc(const std::string& type) { inline int translateSpeakTypeDesc(const std::string& type) {
if(type == "say") if(type == "say") return Proto::SpeakSay;
return Proto::SpeakSay; else if(type == "whisper") return Proto::SpeakWhisper;
else if(type == "whisper") else if(type == "yell") return Proto::SpeakYell;
return Proto::SpeakWhisper; else if(type == "monsterSay") return Proto::SpeakMonsterSay;
else if(type == "yell") else if(type == "monsterYell") return Proto::SpeakMonsterYell;
return Proto::SpeakYell; else if(type == "npcToPlayer") return Proto::SpeakPrivateNpcToPlayer;
else if(type == "monsterSay") else if(type == "channelYellow") return Proto::SpeakChannelYellow;
return Proto::SpeakMonsterSay; else if(type == "channelWhite") return Proto::SpeakChannelWhite;
else if(type == "monsterYell") else if(type == "channelRed") return Proto::SpeakChannelRed;
return Proto::SpeakMonsterYell; else if(type == "channelRed") return Proto::SpeakChannelRed2;
else if(type == "npcToPlayer") else if(type == "channelOrange") return Proto::SpeakChannelOrange;
return Proto::SpeakPrivateNpcToPlayer; else if(type == "private") return Proto::SpeakPrivate;
else if(type == "channelYellow") else if(type == "playerToNpc") return Proto::SpeakPrivatePlayerToNpc;
return Proto::SpeakChannelYellow; else if(type == "broadcast") return Proto::SpeakBroadcast;
else if(type == "channelWhite") else if(type == "privateRed") return Proto::SpeakPrivateRed;
return Proto::SpeakChannelWhite;
else if(type == "channelRed")
return Proto::SpeakChannelRed;
else if(type == "channelRed")
return Proto::SpeakChannelRed2;
else if(type == "channelOrange")
return Proto::SpeakChannelOrange;
else if(type == "private")
return Proto::SpeakPrivate;
else if(type == "playerToNpc")
return Proto::SpeakPrivatePlayerToNpc;
else if(type == "broadcast")
return Proto::SpeakBroadcast;
else if(type == "privateRed")
return Proto::SpeakPrivateRed;
else { else {
logError("unknown protocol speak type desc ", type); logError("unknown protocol speak type desc ", type);
return 0; return 0;
@ -375,26 +346,16 @@ namespace Proto {
inline std::string translateTextMessageType(int type) { inline std::string translateTextMessageType(int type) {
switch(type) { switch(type) {
case Proto::MessageConsoleOrange: case Proto::MessageConsoleOrange: return "consoleOrange";
return "consoleOrange"; case Proto::MessageConsoleOrange2: return "consoleOrange";
case Proto::MessageEventOrange: case Proto::MessageWarning: return "warning";
return "eventOrange"; case Proto::MessageEventAdvance: return "eventAdvance";
case Proto::MessageWarning: case Proto::MessageEventDefault: return "eventDefault";
return "warning"; case Proto::MessageStatusDefault: return "statusDefault";
case Proto::MessageEventAdvance: case Proto::MessageInfoDescription: return "infoDescription";
return "eventAdvance"; case Proto::MessageStatusSmall: return "statusSmall";
case Proto::MessageEventDefault: case Proto::MessageConsoleBlue: return "consoleBlue";
return "eventDefault"; case Proto::MessageConsoleRed: return "consoleRed";
case Proto::MessageStatusDefault:
return "statusDefault";
case Proto::MessageInfoDescription:
return "infoDescription";
case Proto::MessageStatusSmall:
return "statusSmall";
case Proto::MessageConsoleBlue:
return "consoleBlue";
case Proto::MessageConsoleRed:
return "consoleRed";
default: default:
logError("unknown protocol text message type ", type); logError("unknown protocol text message type ", type);
return "unknown"; return "unknown";