#include #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); } } }