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/RichLabel.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/RichLabel.cpp')
| -rw-r--r-- | src/gui/interface/RichLabel.cpp | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/src/gui/interface/RichLabel.cpp b/src/gui/interface/RichLabel.cpp new file mode 100644 index 0000000..f6143d3 --- /dev/null +++ b/src/gui/interface/RichLabel.cpp @@ -0,0 +1,198 @@ +#include <vector> +#include <exception> + +#include "RichLabel.h" +#include "Misc.h" +#include "gui/interface/Point.h" +#include "gui/interface/Component.h" +#include "graphics/Graphics.h" + +using namespace ui; + +struct RichTextParseException: public std::exception { + std::string message; +public: + RichTextParseException(std::string message_ = "Parse error"): message(message_) {} + const char * what() const throw() + { + return message.c_str(); + } + ~RichTextParseException() throw() {}; +}; + +RichLabel::RichLabel(Point position, Point size, std::string labelText): + Component(position, size), + textSource(labelText), + displayText("") +{ + updateRichText(); +} + +RichLabel::~RichLabel() +{ + +} + +void RichLabel::updateRichText() +{ + regions.clear(); + displayText = ""; + + if(textSource.length()) + { + + enum State { ReadText, ReadData, ReadRegion, ReadDataStart }; + State state = ReadText; + + int currentDataPos = 0; + char * currentData = new char[textSource.length()+1]; + std::fill(currentData, currentData+textSource.length()+1, 0); + + int finalTextPos = 0; + char * finalText = new char[textSource.length()+1]; + std::fill(finalText, finalText+textSource.length()+1, 0); + + int originalTextPos = 0; + char * originalText = new char[textSource.length()+1]; + std::copy(textSource.begin(), textSource.end(), originalText); + originalText[textSource.length()] = 0; + + int stackPos = -1; + RichTextRegion * regionsStack = new RichTextRegion[256]; + + try + { + while(originalText[originalTextPos]) + { + char current = originalText[originalTextPos]; + + if(state == ReadText) + { + if(current == '{') + { + if(stackPos > 255) + throw RichTextParseException("Too many nested regions"); + stackPos++; + regionsStack[stackPos].start = finalTextPos; + regionsStack[stackPos].finish = finalTextPos; + state = ReadRegion; + } + else if(current == '}') + { + if(stackPos >= 0) + { + currentData[currentDataPos] = 0; + regionsStack[stackPos].actionData = std::string(currentData); + regions.push_back(regionsStack[stackPos]); + stackPos--; + } + else + { + throw RichTextParseException("Unexpected '}'"); + } + } + else + { + finalText[finalTextPos++] = current; + finalText[finalTextPos] = 0; + if(stackPos >= 0) + { + regionsStack[stackPos].finish = finalTextPos; + } + } + } + else if(state == ReadData) + { + if(current == '|') + { + state = ReadText; + } + else + { + currentData[currentDataPos++] = current; + currentData[currentDataPos] = 0; + } + } + else if(state == ReadDataStart) + { + if(current != ':') + { + throw RichTextParseException("Expected ':'"); + } + state = ReadData; + currentDataPos = 0; + } + else if(state == ReadRegion) + { + if(stackPos >= 0) + { + regionsStack[stackPos].action = current; + state = ReadDataStart; + } + else + { + throw RichTextParseException(); + } + } + + originalTextPos++; + } + + if(stackPos != -1) + throw RichTextParseException("Unclosed region"); + + finalText[finalTextPos] = 0; + displayText = std::string(finalText); + } + catch (const RichTextParseException & e) + { + displayText = "\br[Parse exception: " + std::string(e.what()) + "]"; + regions.clear(); + } + delete[] currentData; + delete[] finalText; + delete[] originalText; + delete[] regionsStack; + } + TextPosition(displayText); +} + +void RichLabel::SetText(std::string text) +{ + textSource = text; + updateRichText(); +} + +std::string RichLabel::GetDisplayText() +{ + return displayText; +} + +std::string RichLabel::GetText() +{ + return textSource; +} + +void RichLabel::Draw(const Point& screenPos) +{ + Graphics * g = ui::Engine::Ref().g; + ui::Colour textColour = Appearance.TextInactive; + g->drawtext(screenPos.X+textPosition.X, screenPos.Y+textPosition.Y, displayText, textColour.Red, textColour.Green, textColour.Blue, 255); +} + +void RichLabel::OnMouseClick(int x, int y, unsigned button) +{ + int cursorPosition = Graphics::CharIndexAtPosition((char*)displayText.c_str(), x-textPosition.X, y-textPosition.Y); + for(std::vector<RichTextRegion>::iterator iter = regions.begin(), end = regions.end(); iter != end; ++iter) + { + if((*iter).start <= cursorPosition && (*iter).finish >= cursorPosition) + { + switch((*iter).action) + { + case 'a': + OpenURI((*iter).actionData); + break; + } + } + } +} |
