diff options
| author | Simon Robertshaw <simon@hardwired.org.uk> | 2013-03-22 14:14:17 (GMT) |
|---|---|---|
| committer | Simon Robertshaw <simon@hardwired.org.uk> | 2013-03-22 14:14:17 (GMT) |
| commit | 9abe51526cac2634af0541c3de69834dd30e9f78 (patch) | |
| tree | 6ae4deadfe00a83094b9d288d8c11d8ce823577a /src/gui/interface/Label.cpp | |
| parent | 2c311b9a36a88fadd96f3d39acb1ab2590835d81 (diff) | |
| download | powder-9abe51526cac2634af0541c3de69834dd30e9f78.zip powder-9abe51526cac2634af0541c3de69834dd30e9f78.tar.gz | |
Move all GUI source files into gui/
Diffstat (limited to 'src/gui/interface/Label.cpp')
| -rw-r--r-- | src/gui/interface/Label.cpp | 420 |
1 files changed, 420 insertions, 0 deletions
diff --git a/src/gui/interface/Label.cpp b/src/gui/interface/Label.cpp new file mode 100644 index 0000000..24b8035 --- /dev/null +++ b/src/gui/interface/Label.cpp @@ -0,0 +1,420 @@ +#include <string> +#include "Config.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), + caret(-1) +{ + 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; + } + 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 = 12; + } + 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; + + if(selectionIndex1 > selectionIndex0) { + ClipboardPush((char*)currentText.substr(selectionIndex0, selectionIndex1-selectionIndex0).c_str()); + } else if(selectionIndex0 > selectionIndex1) { + ClipboardPush((char*)currentText.substr(selectionIndex1, selectionIndex0-selectionIndex1).c_str()); + } else { + ClipboardPush((char*)currentText.c_str()); + } +} + +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 > text.length()) selectionIndex0 = text.length(); + if(selectionIndex1 < 0) selectionIndex1 = 0; + if(selectionIndex1 > 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) +{ + displayText = newText; + tDisplayText = displayText; +} + +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); + } + } +} + |
