#include <config.h>
#include "MFXDynamicLabel.h"
FXDEFMAP(MFXDynamicLabel) MFXLabelMap[] = {
FXMAPFUNC(SEL_UPDATE, 0, MFXDynamicLabel::onUpdate),
};
FXIMPLEMENT(MFXDynamicLabel, FXLabel, MFXLabelMap, ARRAYNUMBER(MFXLabelMap))
MFXDynamicLabel::MFXDynamicLabel(FXComposite* p, const FXString& text, FXIcon* ic, FXuint opts, FXint x, FXint y, FXint w, FXint h, FXint pl, FXint pr, FXint pt, FXint pb, std::string indent):
FXLabel(p, text, ic, opts, x, y, w, h, pl, pr, pt, pb), myOriginalString(text.text()), myIndentString(indent), myPreviousWidth(0) {
computeIndentation();
}
long
MFXDynamicLabel::onUpdate(FXObject* sender, FXSelector sel, void* ptr) {
const int curWidth = getWidth();
if (myPreviousWidth - curWidth != 0 && curWidth > 1) {
reformatLineBreaks(curWidth);
myPreviousWidth = curWidth;
}
return FXLabel::onUpdate(sender, sel, ptr);
}
void
MFXDynamicLabel::setText(const FXString& text) {
FXLabel::setText(text);
myOriginalString = text.text();
computeIndentation();
}
void
MFXDynamicLabel::position(FXint x, FXint y, FXint w, FXint h) {
FXLabel::position(x, y, w, h);
reformatLineBreaks(w);
}
FXint
MFXDynamicLabel::getDefaultHeight() {
int pWidth = getParent()->getWidth();
if (pWidth > 1) {
FXFrame* frame = dynamic_cast<FXFrame*>(getParent());
int padding = 0;
if (frame != nullptr) {
padding = frame->getPadLeft() + frame->getPadRight();
}
reformatLineBreaks(pWidth - padding);
}
return FXLabel::getDefaultHeight();
}
void
MFXDynamicLabel::computeIndentation() {
if (myOriginalString.find(myIndentString) == 0 || myOriginalString.find("\n" + myIndentString) != std::string::npos) {
myIndent = (int)myIndentString.size();
} else {
myIndent = 0;
}
}
void
MFXDynamicLabel::reformatLineBreaks(const int curWidth) {
const int preferredWidth = curWidth - getPadLeft() - getPadRight();
const int textWidth = getApp()->getNormalFont()->getTextWidth(label);
if (textWidth <= preferredWidth || preferredWidth < 1) {
return;
}
std::string newLine = "\n" + std::string(myIndent, ' ');
const int newLineOffset = (int)newLine.size();
std::string msg = myOriginalString;
int pos = 0;
int finalPos = (int)msg.size() - 1;
std::string::size_type nextLineBreak;
while (pos < finalPos) {
nextLineBreak = msg.find('\n', pos);
int subPos = (nextLineBreak != std::string::npos) ? (int)nextLineBreak : finalPos;
if (getApp()->getNormalFont()->getTextWidth(msg.substr(pos, subPos - pos).c_str()) <= preferredWidth) {
pos = subPos + 1;
continue;
}
if (myIndent > 0 && msg.substr(pos, myIndent) == myIndentString) {
pos += myIndent;
}
const int endPos = (nextLineBreak != std::string::npos) ? (int)nextLineBreak - 1 : finalPos;
std::string::size_type nextSpace = std::string::npos;
int lastSpacePos = -1;
int pos2 = pos;
while (pos2 < endPos) {
nextSpace = msg.find(' ', pos2);
if (nextSpace != std::string::npos && (int)nextSpace <= pos + myIndent) {
nextSpace = std::string::npos;
pos2 += myIndent + 1;
} else if (nextSpace != std::string::npos && (int)nextSpace < endPos) {
std::string testString = msg.substr(pos, nextSpace - pos);
if (getApp()->getNormalFont()->getTextWidth(msg.substr(pos, nextSpace - pos).c_str()) > preferredWidth) {
if (lastSpacePos > 0) {
msg.replace(lastSpacePos, 1, newLine);
pos2 = lastSpacePos + newLineOffset;
finalPos += newLineOffset;
} else {
msg.replace(nextSpace, 1, newLine);
pos2 = (int)nextSpace + newLineOffset;
finalPos += newLineOffset;
}
break;
} else {
pos2 = (int)nextSpace + 1;
if (msg.find(' ', pos2) == std::string::npos && lastSpacePos > 0) {
msg.replace(lastSpacePos, 1, newLine);
pos2 += newLineOffset;
break;
}
}
lastSpacePos = (int)nextSpace;
} else {
pos2 = endPos + 2;
}
}
pos = pos2;
}
label = msg.c_str();
}
MFXDynamicLabel::MFXDynamicLabel() {}