424 lines
10 KiB
C++
424 lines
10 KiB
C++
#include <string>
|
|
#include "Config.h"
|
|
#include "Format.h"
|
|
#include "Point.h"
|
|
#include "Label.h"
|
|
#include "Keys.h"
|
|
#include "ContextMenu.h"
|
|
|
|
using namespace ui;
|
|
|
|
Label::Label(Point position, Point size, std::string labelText):
|
|
Component(position, size),
|
|
text(labelText),
|
|
textColour(255, 255, 255),
|
|
selectionIndex0(-1),
|
|
selectionIndex1(-1),
|
|
selectionXL(-1),
|
|
selectionXH(-1),
|
|
multiline(false),
|
|
selecting(false),
|
|
autoHeight(size.Y==-1?true:false)
|
|
{
|
|
menu = new ContextMenu(this);
|
|
menu->AddItem(ContextMenuItem("Copy", 0, true));
|
|
}
|
|
|
|
Label::~Label()
|
|
{
|
|
|
|
}
|
|
|
|
void Label::SetMultiline(bool status)
|
|
{
|
|
multiline = status;
|
|
if(status)
|
|
{
|
|
updateMultiline();
|
|
updateSelection();
|
|
TextPosition(textLines);
|
|
}
|
|
else
|
|
{
|
|
TextPosition(text);
|
|
}
|
|
}
|
|
|
|
void Label::SetText(std::string text)
|
|
{
|
|
this->text = text;
|
|
if(multiline)
|
|
{
|
|
updateMultiline();
|
|
updateSelection();
|
|
TextPosition(textLines);
|
|
}
|
|
else
|
|
{
|
|
TextPosition(text);
|
|
}
|
|
}
|
|
|
|
void Label::AutoHeight()
|
|
{
|
|
bool oldAH = autoHeight;
|
|
autoHeight = true;
|
|
updateMultiline();
|
|
autoHeight = oldAH;
|
|
}
|
|
|
|
void Label::updateMultiline()
|
|
{
|
|
int lines = 1;
|
|
if (text.length()>0)
|
|
{
|
|
char * rawText = new char[text.length()+1];
|
|
std::copy(text.begin(), text.end(), rawText);
|
|
rawText[text.length()] = 0;
|
|
|
|
char c, pc = 0;
|
|
int charIndex = 0;
|
|
|
|
int wordWidth = 0;
|
|
int lineWidth = 0;
|
|
char * wordStart = NULL;
|
|
while ((c = rawText[charIndex++]))
|
|
{
|
|
switch(c)
|
|
{
|
|
case ' ':
|
|
lineWidth += Graphics::CharWidth(c);
|
|
lineWidth += wordWidth;
|
|
wordWidth = 0;
|
|
break;
|
|
case '\n':
|
|
lineWidth = wordWidth = 0;
|
|
lines++;
|
|
break;
|
|
default:
|
|
wordWidth += Graphics::CharWidth(c);
|
|
break;
|
|
}
|
|
if (pc == ' ')
|
|
{
|
|
wordStart = &rawText[charIndex-2];
|
|
}
|
|
if ((c != ' ' || pc == ' ') && lineWidth + wordWidth >= Size.X-(Appearance.Margin.Left+Appearance.Margin.Right))
|
|
{
|
|
if (wordStart && *wordStart)
|
|
{
|
|
*wordStart = '\n';
|
|
if (lineWidth != 0)
|
|
lineWidth = wordWidth;
|
|
}
|
|
else if (!wordStart)
|
|
{
|
|
rawText[charIndex-1] = '\n';
|
|
lineWidth = 0;
|
|
}
|
|
wordWidth = 0;
|
|
wordStart = 0;
|
|
lines++;
|
|
}
|
|
pc = c;
|
|
}
|
|
if (autoHeight)
|
|
{
|
|
Size.Y = lines*12+3;
|
|
}
|
|
textLines = std::string(rawText);
|
|
delete[] rawText;
|
|
/*int currentWidth = 0;
|
|
char * lastSpace = NULL;
|
|
char * currentWord = rawText;
|
|
char * nextSpace;
|
|
while(true)
|
|
{
|
|
nextSpace = strchr(currentWord+1, ' ');
|
|
if(nextSpace)
|
|
nextSpace[0] = 0;
|
|
int width = Graphics::textwidth(currentWord);
|
|
if(width+currentWidth >= Size.X-(Appearance.Margin.Left+Appearance.Margin.Right))
|
|
{
|
|
currentWidth = width;
|
|
if(currentWord!=rawText)
|
|
{
|
|
currentWord[0] = '\n';
|
|
lines++;
|
|
}
|
|
}
|
|
else
|
|
currentWidth += width;
|
|
if(nextSpace)
|
|
nextSpace[0] = ' ';
|
|
if(!currentWord[0] || !currentWord[1] || !(currentWord = strchr(currentWord+1, ' ')))
|
|
break;
|
|
}
|
|
if(autoHeight)
|
|
{
|
|
Size.Y = lines*12;
|
|
}
|
|
textLines = std::string(rawText);
|
|
delete[] rawText;*/
|
|
}
|
|
else
|
|
{
|
|
if (autoHeight)
|
|
{
|
|
Size.Y = 15;
|
|
}
|
|
textLines = std::string("");
|
|
}
|
|
}
|
|
|
|
std::string Label::GetText()
|
|
{
|
|
return this->text;
|
|
}
|
|
|
|
void Label::OnContextMenuAction(int item)
|
|
{
|
|
switch(item)
|
|
{
|
|
case 0:
|
|
copySelection();
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Label::OnMouseClick(int x, int y, unsigned button)
|
|
{
|
|
if(button == BUTTON_RIGHT)
|
|
{
|
|
if(menu)
|
|
menu->Show(GetScreenPos() + ui::Point(x, y));
|
|
}
|
|
else
|
|
{
|
|
selecting = true;
|
|
if(multiline)
|
|
selectionIndex0 = Graphics::CharIndexAtPosition((char*)textLines.c_str(), x-textPosition.X, y-textPosition.Y);
|
|
else
|
|
selectionIndex0 = Graphics::CharIndexAtPosition((char*)text.c_str(), x-textPosition.X, y-textPosition.Y);
|
|
selectionIndex1 = selectionIndex0;
|
|
|
|
updateSelection();
|
|
}
|
|
}
|
|
|
|
void Label::copySelection()
|
|
{
|
|
std::string currentText = text;
|
|
std::string copyText;
|
|
|
|
if (selectionIndex1 > selectionIndex0)
|
|
copyText = currentText.substr(selectionIndex0, selectionIndex1-selectionIndex0).c_str();
|
|
else if(selectionIndex0 > selectionIndex1)
|
|
copyText = currentText.substr(selectionIndex1, selectionIndex0-selectionIndex1).c_str();
|
|
else if (!currentText.length())
|
|
return;
|
|
else
|
|
copyText = currentText.c_str();
|
|
ClipboardPush(format::CleanString(copyText, false, true, false));
|
|
}
|
|
|
|
void Label::OnMouseUp(int x, int y, unsigned button)
|
|
{
|
|
selecting = false;
|
|
}
|
|
|
|
void Label::OnKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool alt)
|
|
{
|
|
if(ctrl && key == 'c')
|
|
{
|
|
copySelection();
|
|
}
|
|
}
|
|
|
|
void Label::OnMouseMoved(int localx, int localy, int dx, int dy)
|
|
{
|
|
if(selecting)
|
|
{
|
|
if(multiline)
|
|
selectionIndex1 = Graphics::CharIndexAtPosition((char*)textLines.c_str(), localx-textPosition.X, localy-textPosition.Y);
|
|
else
|
|
selectionIndex1 = Graphics::CharIndexAtPosition((char*)text.c_str(), localx-textPosition.X, localy-textPosition.Y);
|
|
updateSelection();
|
|
}
|
|
}
|
|
|
|
void Label::Tick(float dt)
|
|
{
|
|
if(!this->IsFocused() && (selecting || (selectionIndex0 != -1 && selectionIndex1 != -1)))
|
|
{
|
|
ClearSelection();
|
|
}
|
|
}
|
|
|
|
int Label::getLowerSelectionBound()
|
|
{
|
|
return (selectionIndex0 > selectionIndex1) ? selectionIndex1 : selectionIndex0;
|
|
}
|
|
|
|
int Label::getHigherSelectionBound()
|
|
{
|
|
return (selectionIndex0 > selectionIndex1) ? selectionIndex0 : selectionIndex1;
|
|
}
|
|
|
|
bool Label::HasSelection()
|
|
{
|
|
if(selectionIndex0 != -1 && selectionIndex1 != -1 && selectionIndex0 != selectionIndex1)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
void Label::ClearSelection()
|
|
{
|
|
selecting = false;
|
|
selectionIndex0 = -1;
|
|
selectionIndex1 = -1;
|
|
updateSelection();
|
|
}
|
|
|
|
void Label::updateSelection()
|
|
{
|
|
std::string currentText;
|
|
|
|
if (selectionIndex0 < 0) selectionIndex0 = 0;
|
|
if (selectionIndex0 > (int)text.length()) selectionIndex0 = text.length();
|
|
if (selectionIndex1 < 0) selectionIndex1 = 0;
|
|
if (selectionIndex1 > (int)text.length()) selectionIndex1 = text.length();
|
|
|
|
if(selectionIndex0 == -1 || selectionIndex1 == -1)
|
|
{
|
|
selectionXH = -1;
|
|
selectionXL = -1;
|
|
|
|
textFragments = std::string(currentText);
|
|
return;
|
|
}
|
|
|
|
if(multiline)
|
|
currentText = textLines;
|
|
else
|
|
currentText = text;
|
|
|
|
if(selectionIndex1 > selectionIndex0) {
|
|
selectionLineH = Graphics::PositionAtCharIndex((char*)currentText.c_str(), selectionIndex1, selectionXH, selectionYH);
|
|
selectionLineL = Graphics::PositionAtCharIndex((char*)currentText.c_str(), selectionIndex0, selectionXL, selectionYL);
|
|
|
|
textFragments = std::string(currentText);
|
|
//textFragments.insert(selectionIndex1, "\x0E");
|
|
//textFragments.insert(selectionIndex0, "\x0F\x01\x01\x01");
|
|
textFragments.insert(selectionIndex1, "\x01");
|
|
textFragments.insert(selectionIndex0, "\x01");
|
|
} else if(selectionIndex0 > selectionIndex1) {
|
|
selectionLineH = Graphics::PositionAtCharIndex((char*)currentText.c_str(), selectionIndex0, selectionXH, selectionYH);
|
|
selectionLineL = Graphics::PositionAtCharIndex((char*)currentText.c_str(), selectionIndex1, selectionXL, selectionYL);
|
|
|
|
textFragments = std::string(currentText);
|
|
//textFragments.insert(selectionIndex0, "\x0E");
|
|
//textFragments.insert(selectionIndex1, "\x0F\x01\x01\x01");
|
|
textFragments.insert(selectionIndex0, "\x01");
|
|
textFragments.insert(selectionIndex1, "\x01");
|
|
} else {
|
|
selectionXH = -1;
|
|
selectionXL = -1;
|
|
|
|
textFragments = std::string(currentText);
|
|
}
|
|
|
|
if(displayText.length())
|
|
{
|
|
displayText = tDisplayText;
|
|
if(selectionIndex1 > selectionIndex0) {
|
|
int tSelectionIndex1 = Graphics::CharIndexAtPosition((char*)displayText.c_str(), selectionXH, selectionYH);
|
|
int tSelectionIndex0 = Graphics::CharIndexAtPosition((char*)displayText.c_str(), selectionXL, selectionYL);
|
|
|
|
displayText.insert(tSelectionIndex1, "\x01");
|
|
displayText.insert(tSelectionIndex0, "\x01");
|
|
} else if(selectionIndex0 > selectionIndex1) {
|
|
int tSelectionIndex0 = Graphics::CharIndexAtPosition((char*)displayText.c_str(), selectionXH, selectionYH);
|
|
int tSelectionIndex1 = Graphics::CharIndexAtPosition((char*)displayText.c_str(), selectionXL, selectionYL);
|
|
|
|
displayText.insert(tSelectionIndex0, "\x01");
|
|
displayText.insert(tSelectionIndex1, "\x01");
|
|
}
|
|
}
|
|
}
|
|
|
|
void Label::SetDisplayText(std::string newText)
|
|
{
|
|
ClearSelection();
|
|
displayText = tDisplayText = newText;
|
|
}
|
|
|
|
void Label::Draw(const Point& screenPos)
|
|
{
|
|
if(!drawn)
|
|
{
|
|
if(multiline)
|
|
{
|
|
TextPosition(textLines);
|
|
updateMultiline();
|
|
updateSelection();
|
|
}
|
|
else
|
|
TextPosition(text);
|
|
drawn = true;
|
|
}
|
|
Graphics * g = Engine::Ref().g;
|
|
|
|
std::string cDisplayText = displayText;
|
|
|
|
if(!cDisplayText.length())
|
|
{
|
|
if(selectionXL != -1 && selectionXH != -1)
|
|
{
|
|
cDisplayText = textFragments;
|
|
}
|
|
else
|
|
{
|
|
if(multiline)
|
|
cDisplayText = textLines;
|
|
else
|
|
cDisplayText = text;
|
|
}
|
|
}
|
|
|
|
if(multiline)
|
|
{
|
|
if(selectionXL != -1 && selectionXH != -1)
|
|
{
|
|
if(selectionLineH - selectionLineL > 0)
|
|
{
|
|
g->fillrect(screenPos.X+textPosition.X+selectionXL, (screenPos.Y+textPosition.Y-1)+selectionYL, textSize.X-(selectionXL), 10, 255, 255, 255, 255);
|
|
for(int i = 1; i < selectionLineH-selectionLineL; i++)
|
|
{
|
|
g->fillrect(screenPos.X+textPosition.X, (screenPos.Y+textPosition.Y-1)+selectionYL+(i*12), textSize.X, 10, 255, 255, 255, 255);
|
|
}
|
|
g->fillrect(screenPos.X+textPosition.X, (screenPos.Y+textPosition.Y-1)+selectionYH, selectionXH, 10, 255, 255, 255, 255);
|
|
|
|
} else {
|
|
g->fillrect(screenPos.X+textPosition.X+selectionXL, screenPos.Y+selectionYL+textPosition.Y-1, selectionXH-(selectionXL), 10, 255, 255, 255, 255);
|
|
}
|
|
g->drawtext(screenPos.X+textPosition.X, screenPos.Y+textPosition.Y, cDisplayText, textColour.Red, textColour.Green, textColour.Blue, 255);
|
|
}
|
|
else
|
|
{
|
|
g->drawtext(screenPos.X+textPosition.X, screenPos.Y+textPosition.Y, cDisplayText, textColour.Red, textColour.Green, textColour.Blue, 255);
|
|
}
|
|
} else {
|
|
if(selectionXL != -1 && selectionXH != -1)
|
|
{
|
|
g->fillrect(screenPos.X+textPosition.X+selectionXL, screenPos.Y+textPosition.Y-1, selectionXH-(selectionXL), 10, 255, 255, 255, 255);
|
|
g->drawtext(screenPos.X+textPosition.X, screenPos.Y+textPosition.Y, cDisplayText, textColour.Red, textColour.Green, textColour.Blue, 255);
|
|
}
|
|
else
|
|
{
|
|
g->drawtext(screenPos.X+textPosition.X, screenPos.Y+textPosition.Y, cDisplayText, textColour.Red, textColour.Green, textColour.Blue, 255);
|
|
}
|
|
}
|
|
}
|
|
|