Просмотр исходного кода

UITextInput speedups, bugfixes

Ivan Safrin 12 лет назад
Родитель
Сommit
14890293f8

+ 1 - 0
IDE/Contents/Include/PolycodeTextEditor.h

@@ -103,6 +103,7 @@ protected:
 	FindBar *findBar;
 	bool isLoading;
 	String lastFindString;
+	bool firstTimeResize;
 
 	PolycodeSyntaxHighlighter *syntaxHighligher;
 	UITextInput *textInput;

+ 5 - 2
IDE/Contents/Source/PolycodeFrame.cpp

@@ -796,8 +796,11 @@ void PolycodeFrame::handleEvent(Event *event) {
 	
 	if(event->getDispatcher() == currentFileSelector && event->getEventType() == "UIEvent") {
 		PolycodeEditor *editor = editorManager->openEditors[currentFileSelector->getSelectedIndex()];
-		editorManager->setCurrentEditor(editor, false);
-		showEditor(editor);
+		
+		if(editorManager->getCurrentEditor() != editor) {
+			editorManager->setCurrentEditor(editor, false);
+			showEditor(editor);
+		}
 	}
 	
 	if(event->getDispatcher() == editorManager) {

+ 1 - 1
IDE/Contents/Source/PolycodeIDEApp.cpp

@@ -556,7 +556,7 @@ void PolycodeIDEApp::openFile(OSFileEntry file) {
 		if(editor) {
 			editor->parentProject = projectManager->getActiveProject();
 			if(editor->openFile(file)) {
-				frame->addEditor(editor);					
+				frame->addEditor(editor);
 				frame->showEditor(editor);
 			} else {
 				delete editor;

+ 6 - 0
IDE/Contents/Source/PolycodeTextEditor.cpp

@@ -427,6 +427,7 @@ std::vector<SyntaxHighlightToken> PolycodeSyntaxHighlighter::parseLua(String tex
 }
 
 PolycodeTextEditor::PolycodeTextEditor() : PolycodeEditor(true){
+	firstTimeResize = true;
 	editorType = "PolycodeTextEditor";
 }
 
@@ -575,6 +576,7 @@ void PolycodeTextEditor::saveFile() {
 }
 
 void PolycodeTextEditor::Resize(int x, int y) {
+
 	findBar->setBarWidth(x);	
 	
 	if(findBar->visible) {
@@ -584,6 +586,10 @@ void PolycodeTextEditor::Resize(int x, int y) {
 		textInput->Resize(x,y);
 		textInput->setPosition(0,0);
 	}
+	if(firstTimeResize) {
+		textInput->doMultilineResize();
+		firstTimeResize = false;
+	}
 	PolycodeEditor::Resize(x,y);
 }
 

+ 21 - 15
Modules/Contents/UI/Include/PolyUITextInput.h

@@ -97,6 +97,7 @@ namespace Polycode {
 			bool isWordWrap;
 			int actualLineNumber;
 			int lineStart;
+			LineColorInfo colorInfo;
 	};
 	
 	class TextColorPair {
@@ -105,6 +106,14 @@ namespace Polycode {
 			String text;
 	};
 
+	class LineInfo {
+		public:
+			LineInfo(){ wordWrapLineIndex = -1; }
+			String text;
+			int wordWrapLineIndex;
+			LineColorInfo colorInfo;
+	};
+
 	/**
 	 * A text input element. Can be single- or multiline.
 	 */
@@ -155,9 +164,6 @@ namespace Polycode {
 			 */
 			int insertLine(bool after = true);
 
-			void changedText(bool sendChangeEvent = true);
-			void applySyntaxFormatting();
-			
 			void onKeyDown(PolyKEY key, wchar_t charCode);
 		
 			/**
@@ -295,7 +301,6 @@ namespace Polycode {
 			 */
 			void setSyntaxHighlighter(UITextInputSyntaxHighlighter *syntaxHighlighter);
 					
-			bool isNumberOrCharacter(wchar_t charCode);
 			void Resize(Number width, Number height);
 			
 			/**
@@ -323,7 +328,7 @@ namespace Polycode {
 			 *
 			 * @param text The string to insert.
 			 */
-			void insertText(String text);
+			void insertText(String text, bool updateWordWrap = true);
 			
 			void setCaretPosition(int position);
 			
@@ -334,20 +339,20 @@ namespace Polycode {
             void shiftText(bool left=false);
             void convertIndentToTabs();
             void convertIndentToSpaces();
+			
+			void doMultilineResize();			
 		
 		protected:
 		
-			void readjustBuffer();
-			void updateWordWrap();
+			void readjustBuffer(int lineStart=0, int lineEnd=-1);
+			void updateWordWrap(int lineStart, int lineEnd);
 			
 			Number resizeTimer;
-			void doMultilineResize();
 
-			std::vector<LineColorInfo> lineColors;
-			std::vector<LineColorInfo> wordWrapColors;					
 			ScreenEntity *lineNumberAnchor;
 		
 			void renumberLines();
+			bool isNumberOrCharacter(wchar_t charCode);			
 		
 			bool lineNumbersEnabled;
 		
@@ -359,6 +364,9 @@ namespace Polycode {
 		
 			bool isNumberOnly;
 			
+			void changedText(int lineStart, int lineEnd, bool sendChangeEvent = true);
+			void applySyntaxFormatting(int startLine, int end);					
+			
 			void setActualToCaret();
 			void setOffsetToActual();
 			
@@ -382,15 +390,13 @@ namespace Polycode {
 			void restructLines();
 			void removeLines(unsigned int startIndex, unsigned int endIndex);
 			
-			std::vector<TextColorPair> makeWordWrapBuffer(int wrapLineOffset, String indentPrefix);
+			std::vector<TextColorPair> makeWordWrapBuffer(LineInfo *lineInfo, String indentPrefix);
 			std::vector<TextColorPair> splitTokens(String stringToSplit, LineColorInfo *stringColorInfo);
 			
 			ScreenShape *selectorRectTop;
 			ScreenShape *selectorRectMiddle;
 			ScreenShape *selectorRectBottom;		
-			int numLines;
-			
-			bool needFullRedraw;
+			int numLines;			
 			
 			Number padding;
 			Number lineSpacing;
@@ -475,7 +481,7 @@ namespace Polycode {
 			int lineOffset;
 			int actualLineOffset;
 			
-			vector<String> lines;
+			vector<LineInfo> lines;
 			vector<WordWrapLine> wordWrapLines;
 									
 			vector<ScreenLabel*> bufferLines;

+ 245 - 187
Modules/Contents/UI/Source/PolyUITextInput.cpp

@@ -57,10 +57,7 @@ UITextInput::UITextInput(bool multiLine, Number width, Number height) : UIElemen
 	horizontalPixelScroll = 0;
 	horizontalCharacterScroll = 0;
 	
-	settingText = false;	
-	
-	needFullRedraw = false;
-
+	settingText = false;
 	isTypingWord = false;
 	
 	numLines = 0;
@@ -303,7 +300,7 @@ void UITextInput::setSelection(int lineStart, int lineEnd, int colStart, int col
 		return;	
 	}
 	
-	String topLine = lines[lineStart];
+	String topLine = lines[lineStart].text;
 	
 	if(colStart+1 > topLine.length()) {
 		colStart = topLine.length();
@@ -316,7 +313,9 @@ void UITextInput::setSelection(int lineStart, int lineEnd, int colStart, int col
 	selectionL = colStart;
 	selectionR = colEnd;
 	
-	updateSelectionRects();
+	if(!settingText) {
+		updateSelectionRects();
+	}
 }
 
 void UITextInput::updateSelectionRects() {
@@ -389,20 +388,20 @@ void UITextInput::updateSelectionRects() {
 
 void UITextInput::deleteSelection() {
 	if(selectionTop == selectionBottom) {
-		String ctext = lines[selectionTop];
+		String ctext = lines[selectionTop].text;
 		String newText = ctext.substr(0, selectionL);
 		int rside = selectionR;
 		if(rside > ctext.length()-1)
 			rside = ctext.length() - 1;
 		newText += ctext.substr(rside,ctext.length() - selectionR); 
-		lines[selectionTop] = newText;
+		lines[selectionTop].text = newText;
 	} else {
 		
-		String ctext = lines[selectionTop];
+		String ctext = lines[selectionTop].text;
 		String newText = ctext.substr(0, selectionL);
-		lines[selectionTop] = newText;
+		lines[selectionTop].text = newText;
 
-		ctext = lines[selectionBottom];
+		ctext = lines[selectionBottom].text;
 		
 		int rside = selectionR;
 		if(rside > ctext.length()-1)
@@ -410,11 +409,11 @@ void UITextInput::deleteSelection() {
 		newText = ctext.substr(rside,ctext.length() - selectionR); 
 		
 		actualLineOffset = selectionTop;		
-		actualCaretPosition = lines[actualLineOffset].length();
+		actualCaretPosition = lines[actualLineOffset].text.length();
 		setOffsetToActual();		
 		updateCaretPosition();
 		
-		lines[actualLineOffset] =  lines[actualLineOffset] + newText;
+		lines[actualLineOffset].text =  lines[actualLineOffset].text + newText;
 		
 		removeLines(selectionTop+1, selectionBottom+1);
 		
@@ -423,68 +422,42 @@ void UITextInput::deleteSelection() {
 	clearSelection();
 	actualCaretPosition = selectionL;
 	updateCaretPosition();
-	changedText();
+	
+	setActualLineOffset();
+	
+	changedText(actualLineOffset,lines.size()-1);
 }
 
-void UITextInput::applySyntaxFormatting() {
-
-	needFullRedraw = true;
+void UITextInput::applySyntaxFormatting(int startLine, int endLine) {
 
 	if(syntaxHighliter && multiLine) {
-	
-		int startLine = (-linesContainer->getPosition().y) / (lineHeight+lineSpacing);				
-		unsigned int endLine = startLine + ((int)((height / (lineHeight+lineSpacing)))) + 1;					
-		
+			
 		if(startLine < 0)
 			startLine = 0;
 		
 		if(endLine > lines.size())
 			endLine = lines.size();
-	
-		if(needFullRedraw) {
-			startLine = 0;
-			endLine = lines.size();
-		}
-		
+			
 		String totalText = L"";
-		for(int i=startLine; i < endLine; i++) {
-			totalText += lines[i];
-			if(i < lines.size()-1)
+		for(int i=startLine; i < endLine+1; i++) {
+			totalText += lines[i].text;
+			if(i < endLine)
 				totalText += L"\n";
 		}		
-		
+
 	std::vector<SyntaxHighlightToken> tokens = syntaxHighliter->parseText(totalText);	
-		
-	// DO SYNTAX HIGHLIGHTING
-	if(needFullRedraw) {
-		lineColors.clear();
-		for(int i=0; i < lines.size(); i++) {
-			lineColors.push_back(LineColorInfo());
-		}		
-		needFullRedraw = false;
-	} else {
-		std::vector<LineColorInfo> newInfo;
-		
-		for(int i=0; i < lines.size(); i++) {
-			if((i >= startLine && i < endLine) || i >= lineColors.size()) {
-				newInfo.push_back(LineColorInfo());
-			} else {
-				newInfo.push_back(lineColors[i]);
-			}
-		}
-		
-		lineColors = newInfo;
-	}
 	
 	int lineIndex = startLine;
+	lines[lineIndex].colorInfo.colors.clear();
 	int rangeStart = 0;
 	int rangeEnd = 0;
-		
+	
+	
 	for(int i=0; i < tokens.size(); i++) {	
 		if(tokens[i].text == "\n") {
 			lineIndex++;
-			if(lineIndex >= endLine) {
-				lineIndex = endLine-1;
+			if(lineIndex < lines.size() && i < tokens.size()-1) {
+				lines[lineIndex].colorInfo.colors.clear();
 			}
 			rangeStart = 0;
 			rangeEnd = 0;
@@ -493,11 +466,11 @@ void UITextInput::applySyntaxFormatting() {
 				int textLength = tokens[i].text.length();
 				if(tokens[i].text.length() > 1) {
 					rangeEnd = rangeStart + textLength-1;
-					lineColors[lineIndex].colors.push_back(LineColorData(tokens[i].color, rangeStart, rangeEnd));
+					lines[lineIndex].colorInfo.colors.push_back(LineColorData(tokens[i].color, rangeStart, rangeEnd));
 					rangeStart = rangeStart + textLength; 
 				} else {
 					rangeEnd = rangeStart;
-					lineColors[lineIndex].colors.push_back(LineColorData(tokens[i].color, rangeStart, rangeEnd));	
+					lines[lineIndex].colorInfo.colors.push_back(LineColorData(tokens[i].color, rangeStart, rangeEnd));
 					rangeStart++;
 				}				
 			}
@@ -509,11 +482,15 @@ void UITextInput::applySyntaxFormatting() {
 	readjustBuffer();	
 }
 
-void UITextInput::changedText(bool sendChangeEvent) {
+void UITextInput::changedText(int lineStart, int lineEnd, bool sendChangeEvent) {
+	if(lineStart <0)
+		lineStart = 0;
+
 	if(settingText)
 		return;
-	applySyntaxFormatting();	
-	updateWordWrap();
+
+	applySyntaxFormatting(lineStart, lineEnd);	
+	updateWordWrap(lineStart, lineEnd);
 	
 	if(sendChangeEvent) {
 		dispatchEvent(new UIEvent(), UIEvent::CHANGE_EVENT);	
@@ -526,7 +503,7 @@ void UITextInput::setSyntaxHighlighter(UITextInputSyntaxHighlighter *syntaxHighl
 
 void UITextInput::doMultilineResize() {
 	if(multiLine) {
-		updateWordWrap();
+		updateWordWrap(0, lines.size()-1);
 		renumberLines();
 		restructLines();		
 		readjustBuffer();
@@ -580,36 +557,54 @@ int UITextInput::insertLine(bool after) {
 	if(after) {	
 		String newText = "";
 		if(lines.size() > 0 && !settingText) {
-			String ctext = lines[actualLineOffset];
+			String ctext = lines[actualLineOffset].text;
 			String text2 = ctext.substr(actualCaretPosition, ctext.length()-actualCaretPosition);
 			ctext = ctext.substr(0,actualCaretPosition);
-			lines[actualLineOffset] = ctext;
+			lines[actualLineOffset].text = ctext;
 			newText = text2;
 			actualCaretPosition=0;
 			caretPosition = 0;
 		}		
 		
-		vector<String>::iterator it;
+		vector<LineInfo>::iterator it;
 						
 		lineOffset = lineOffset + 1;
 		actualLineOffset = actualLineOffset + 1;
-		
-				
+						
 		if(lineOffset >= wordWrapLines.size()) {
 			it = lines.end();
 		} else {
 			int actualLineOffset = wordWrapLines[lineOffset].actualLineNumber;		
 			it = lines.begin() + actualLineOffset;
 		}
-		lines.insert(it,newText);
 		
-		renumberLines();
-		restructLines();
-	} else {	
-		// do we even need that? I don't think so.
-	}	
+		LineInfo info;
+		info.text = newText;
+		lines.insert(it,info);
+		
+		WordWrapLine line;		
+		line.text = info.text;
+		line.isWordWrap = false;
+		line.actualLineNumber = actualLineOffset;
+		lines[actualLineOffset].wordWrapLineIndex = lineOffset;
+		line.colorInfo = lines[actualLineOffset].colorInfo;
+		
+		vector<WordWrapLine>::iterator wit;
+		wit = wordWrapLines.begin() + lineOffset;
+		wordWrapLines.insert(wit,line);
+	} 
 	
-	changedText();
+	if(!settingText) {
+		for(int i=actualLineOffset+1; i < lines.size(); i++) {
+			lines[i].wordWrapLineIndex += 1;
+		}
+		
+		for(int i=lineOffset+1; i < wordWrapLines.size(); i++) {
+			wordWrapLines[i].actualLineNumber += 1;
+		}
+	
+		changedText(actualLineOffset-1, actualLineOffset);		
+	}
 	return 1;	
 }
 
@@ -677,7 +672,7 @@ void UITextInput::restructLines() {
 }
 
 void UITextInput::setCaretPosition(int position) {
-	if(position >= 0 && position < lines[lineOffset].length()) {
+	if(position >= 0 && position < lines[lineOffset].text.length()) {
 		caretPosition = position;
 		updateCaretPosition();		
 	}
@@ -685,18 +680,19 @@ void UITextInput::setCaretPosition(int position) {
 
 void UITextInput::setText(String text, bool sendChangeEvent) {
 	if(!multiLine) {
-		lines[lineOffset] = text;
+		lines[lineOffset].text = text;
 		caretPosition = text.length();
 		clearSelection();				
 		updateCaretPosition();		
+		changedText(0, 0);
 	} else {
 		selectAll();
-		insertText(text);
+		insertText(text, false);
 		clearSelection();
+		changedText(0, lines.size()-1, false);
+//		wordWrapLines.clear();
+//		doMultilineResize();
 	}
-//	needFullRedraw = true;		
-	changedText(sendChangeEvent);
-	doMultilineResize();
 }
 
 void UITextInput::onLoseFocus() {
@@ -707,11 +703,11 @@ void UITextInput::onLoseFocus() {
 String UITextInput::getText() {
 	
 	if(!multiLine) {
-		return lines[0];
+		return lines[0].text;
 	} else {
 		String totalText = L"";
 		for(int i=0; i < lines.size(); i++) {
-				totalText += lines[i];
+				totalText += lines[i].text;
 				if(i < lines.size()-1)
 					totalText += L"\n";
 		}	
@@ -734,8 +730,8 @@ void UITextInput::convertOffsetToActual(int lineOffset, int caretPosition, int *
 		*actualCaretPosition = caretPosition;
 	}
 	
-	if((*actualCaretPosition) > lines[actualLineOffset].size()) {
-		*actualCaretPosition = lines[actualLineOffset].size();
+	if((*actualCaretPosition) > lines[actualLineOffset].text.size()) {
+		*actualCaretPosition = lines[actualLineOffset].text.size();
 	}
 
 
@@ -746,14 +742,8 @@ void UITextInput::setActualToCaret() {
 	convertOffsetToActual(lineOffset, caretPosition, &actualCaretPosition);
 }
 
-void UITextInput::convertActualToOffset(int actualLineOffset, int actualCaretPosition, int *lineOffset, int *caretPosition) {
-
-	for(int i=0; i < wordWrapLines.size(); i++) {
-		if(wordWrapLines[i].actualLineNumber == actualLineOffset) {
-			*lineOffset = i;
-			break;
-		}
-	}
+void UITextInput::convertActualToOffset(int actualLineOffset, int actualCaretPosition, int *lineOffset, int *caretPosition) {	
+	*lineOffset = lines[actualLineOffset].wordWrapLineIndex;
 	
 	int totalTextWidth = wordWrapLines[(*lineOffset)].text.size() - wordWrapLines[(*lineOffset)].lineStart;
 
@@ -762,6 +752,10 @@ void UITextInput::convertActualToOffset(int actualLineOffset, int actualCaretPos
 	while(actualCaretPosition > totalTextWidth) {
 		*caretPosition -= (wordWrapLines[(*lineOffset)].text.size() - wordWrapLines[(*lineOffset)].lineStart);
 		(*lineOffset)++;
+		if((*lineOffset) > wordWrapLines.size()-1) {
+			(*lineOffset) = wordWrapLines.size()-1;
+			break;
+		}
 		totalTextWidth += wordWrapLines[(*lineOffset)].text.size() - wordWrapLines[(*lineOffset)].lineStart;
 	}
 	*caretPosition += wordWrapLines[(*lineOffset)].lineStart;
@@ -827,6 +821,8 @@ void UITextInput::updateCaretPosition() {
 
 		bufferLines[0]->setPosition(-horizontalPixelScroll, 0);
 	}
+	
+	blinkerRect->setPosition(caretImagePosition + 1 -horizontalPixelScroll, (lineOffset * ( lineHeight+lineSpacing)));	
 /*	
 	if(multiLine) {	
 		if(linesContainer->getPosition().y + currentLine->getPosition2D().y < 0.0) {
@@ -900,7 +896,7 @@ void UITextInput::dragSelectionTo(Number x, Number y) {
 
 int UITextInput::caretSkipWordBack(int caretLine, int caretPosition) {
 	for(int i=caretPosition; i > 0; i--) {
-		String bit = lines[caretLine].substr(i,1);
+		String bit = lines[caretLine].text.substr(i,1);
 		char chr = ((char*)bit.c_str())[0]; 		
 		if(!isNumberOrCharacter(chr) && i < caretPosition-1) {
 			return i+1;
@@ -910,15 +906,15 @@ int UITextInput::caretSkipWordBack(int caretLine, int caretPosition) {
 }
 
 int UITextInput::caretSkipWordForward(int caretLine, int caretPosition) {
-	int len = lines[caretLine].length();
+	int len = lines[caretLine].text.length();
 	for(int i=caretPosition; i < len; i++) {
-		String bit = lines[caretLine].substr(i,1);
+		String bit = lines[caretLine].text.substr(i,1);
 		char chr = ((char*)bit.c_str())[0]; 
 		if(!isNumberOrCharacter(chr) && i > caretPosition) {
 			return i;
 		}
 	}
-	return lines[caretLine].length();	
+	return lines[caretLine].text.length();	
 }
 
 void UITextInput::selectWordAtCaret() {
@@ -935,10 +931,9 @@ void UITextInput::selectWordAtCaret() {
 
 void UITextInput::replaceAll(String what, String withWhat) {
 	for(int i=0; i < lines.size(); i++) {
-		lines[i] = lines[i].replace(what, withWhat);
+		lines[i].text = lines[i].text.replace(what, withWhat);
+		changedText(i,i);
 	}
-	needFullRedraw  = true;
-	changedText();
 }
 
 void UITextInput::findString(String stringToFind, bool replace, String replaceString) {
@@ -949,7 +944,7 @@ void UITextInput::findString(String stringToFind, bool replace, String replaceSt
 	for(int i=0; i < lines.size(); i++) {
 
 
-		String lineText = lines[i];
+		String lineText = lines[i].text;
 		
 		int offset = 0;				
 		int retVal = -1;
@@ -972,12 +967,12 @@ void UITextInput::findString(String stringToFind, bool replace, String replaceSt
 
 		if(replace) {
 			FindMatch match = findMatches[findIndex];
-			String oldText = lines[match.lineNumber];
+			String oldText = lines[match.lineNumber].text;
 			String newText = oldText.substr(0,match.caretStart) + replaceString + oldText.substr(match.caretEnd);
 			
-			lines[match.lineNumber] = newText;
+			lines[match.lineNumber].text = newText;
 			findMatches[findIndex].caretEnd = findMatches[findIndex].caretStart + replaceString.length();
-			changedText();			
+			changedText(match.lineNumber, match.lineNumber);
 		}
 	
 		findIndex = 0;
@@ -1065,66 +1060,84 @@ void UITextInput::setCaretToMouse(Number x, Number y) {
 }
 
 void UITextInput::removeLines(unsigned int startIndex, unsigned int endIndex) {	
+
+	int startLine = lines[startIndex].wordWrapLineIndex;
+	int endLine = lines[endIndex].wordWrapLineIndex;
+	if(endIndex == lines.size())
+		endLine = wordWrapLines.size();
+
+	wordWrapLines.erase(wordWrapLines.begin()+startLine, wordWrapLines.begin()+endLine);
+	
 	lines.erase(lines.begin()+startIndex, lines.begin()+endIndex);
+
+	for(int i=startIndex; i < lines.size(); i++) {
+		lines[i].wordWrapLineIndex -= (endLine-startLine);
+	}
+	
+	for(int i=startLine; i < wordWrapLines.size(); i++) {
+		wordWrapLines[i].actualLineNumber -= (endIndex-startIndex);
+	}
 	
-	updateWordWrap();
 	renumberLines();
 	restructLines();
-	changedText();
+	readjustBuffer();
 }
 
 void UITextInput::selectAll() {
-	setSelection(0, lines.size()-1, 0, lines[lines.size()-1].length());
+	setSelection(0, lines.size()-1, 0, lines[lines.size()-1].text.length());
 }
 
-void UITextInput::insertText(String text) {	
+void UITextInput::insertText(String text, bool updateWordWrap) {	
 	vector<String> strings = text.split("\n");
 	settingText = true;
 
 	if(hasSelection)
 		deleteSelection();
 
+	int startChangeOffset = actualLineOffset;
+	
 	if(strings.size() > 1) {
-		String ctext = lines[actualLineOffset];
+		String ctext = lines[actualLineOffset].text;
 		String text2 = ctext.substr(caretPosition, ctext.length()-caretPosition);
 		ctext = ctext.substr(0,caretPosition);
 		ctext += strings[0];
-		lines[lineOffset] = ctext;
+		lines[lineOffset].text = ctext;
 		caretPosition = ctext.length();
 		
 		for(int i=1; i < strings.size()-1; i++) {
 			insertLine(true);
 			ctext = strings[i];
-			lines[lineOffset] = ctext;
+			lines[lineOffset].text = ctext;
 			caretPosition = ctext.length();			
 		}
 		
 		insertLine(true);
 		ctext = strings[strings.size()-1] + text2;
 		caretPosition = ctext.length();
-		lines[lineOffset] = ctext;
+		lines[lineOffset].text = ctext;
 		
 	} else {
-		String ctext = lines[actualLineOffset];
+		String ctext = lines[actualLineOffset].text;
 		String text2 = ctext.substr(caretPosition, ctext.length()-caretPosition);
 		ctext = ctext.substr(0,caretPosition);
 		ctext += text + text2;
 		caretPosition += text.length();
-		lines[lineOffset] = ctext;
+		lines[lineOffset].text = ctext;
 	}
 	
 	settingText = false;	
 
-	updateWordWrap();
-	restructLines();	
-	renumberLines();	
-	changedText();
-	updateCaretPosition();	
+	if(updateWordWrap) {
+		restructLines();	
+		renumberLines();
+		changedText(startChangeOffset, actualLineOffset);
+		updateCaretPosition();	
+	}
 }
 
 String UITextInput::getLineText(unsigned int index) {
 	if(index < lines.size()) {
-		return lines[index];
+		return lines[index].text;
 	} else {
 		return "";
 	}
@@ -1142,12 +1155,12 @@ String UITextInput::getSelectionText() {
 
 	// Iterate over the inner lines(we'll be appending \n to these)
 	while(currentLine < selectionBottom) {
-		totalText += lines[currentLine].substr(currentLeft, lines[currentLine].length()-currentLeft) + '\n';
+		totalText += lines[currentLine].text.substr(currentLeft, lines[currentLine].text.length()-currentLeft) + '\n';
 		currentLine++;
 		currentLeft = 0;
 	}
 	// Add the selection in the last line(no \n needed)
-	totalText += lines[currentLine].substr(currentLeft, selectionR-currentLeft);
+	totalText += lines[currentLine].text.substr(currentLeft, selectionR-currentLeft);
 
 	return totalText;
 }
@@ -1222,13 +1235,14 @@ void UITextInput::setUndoState(UITextInputUndoState state) {
 	setText(state.content);
 	actualLineOffset = state.lineOffset;
 	actualCaretPosition = state.caretPosition;
-	updateCaretPosition();
+	updateCaretPosition();	
 	
 	if(state.hasSelection) {
 		setSelection(actualLineOffset, state.selectionLine, actualCaretPosition, state.selectionCaretPosition);
 	}
 	
 	showLine(state.lineOffset, false);
+	changedText(0, lines.size()-1);
 }
 
 void UITextInput::Undo() {
@@ -1364,7 +1378,7 @@ void UITextInput::onKeyDown(PolyKEY key, wchar_t charCode) {
 						newCaretPosition--;
 					} else if(newLineStart > 0) {
 						newLineStart--;
-						newCaretPosition = lines[newLineStart].length();
+						newCaretPosition = lines[newLineStart].text.length();
 					}
 
 					clearSelection();
@@ -1398,7 +1412,7 @@ void UITextInput::onKeyDown(PolyKEY key, wchar_t charCode) {
 				}
 			}
 		} else if (input->getKeyState(KEY_LALT) || input->getKeyState(KEY_RALT)) {
-			if(actualCaretPosition < lines[actualLineOffset].length()) {
+			if(actualCaretPosition < lines[actualLineOffset].text.length()) {
 				if(input->getKeyState(KEY_LSHIFT) || input->getKeyState(KEY_RSHIFT)) {
 					if(hasSelection) {
 						setSelection(actualLineOffset, selectionLine, actualCaretPosition, caretSkipWordForward(selectionLine, selectionCaretPosition));
@@ -1412,7 +1426,7 @@ void UITextInput::onKeyDown(PolyKEY key, wchar_t charCode) {
 				}
 			}
 		} else {
-			if(actualCaretPosition < lines[actualLineOffset].length() || lineOffset + 1 < lines.size()) {
+			if(actualCaretPosition < lines[actualLineOffset].text.length() || lineOffset + 1 < lines.size()) {
 				if(input->getKeyState(KEY_LSHIFT) || input->getKeyState(KEY_RSHIFT)) {
 					// Holding down shift allows you to select with the arrow keys.
 					if(hasSelection) {
@@ -1425,7 +1439,7 @@ void UITextInput::onKeyDown(PolyKEY key, wchar_t charCode) {
 
 					int newLineEnd = actualLineOffset;
 					int newCaretPosition = actualCaretPosition;
-					if(newCaretPosition < lines[actualLineOffset].length()) {
+					if(newCaretPosition < lines[actualLineOffset].text.length()) {
 						newCaretPosition++;
 					} else if(newLineEnd + 1 < lines.size()) {
 						newLineEnd++;
@@ -1588,7 +1602,7 @@ void UITextInput::onKeyDown(PolyKEY key, wchar_t charCode) {
 		input->getKeyState(KEY_RCTRL) || input->getKeyState(KEY_LALT) || input->getKeyState(KEY_RALT))
 			return;
 	
-	String ctext = lines[actualLineOffset];
+	String ctext = lines[actualLineOffset].text;
 	
 	bool _changedText = false;
 		
@@ -1603,7 +1617,7 @@ void UITextInput::onKeyDown(PolyKEY key, wchar_t charCode) {
 			}
 			if(hasSelection)
 				deleteSelection();
-			ctext = lines[actualLineOffset];
+			ctext = lines[actualLineOffset].text;
 			String text2 = ctext.substr(actualCaretPosition, ctext.length()-actualCaretPosition);
 			ctext = ctext.substr(0,actualCaretPosition);
 			ctext += charCode + text2;
@@ -1616,7 +1630,7 @@ void UITextInput::onKeyDown(PolyKEY key, wchar_t charCode) {
 		saveUndoState();
 		if(hasSelection)
 			deleteSelection();		
-		ctext = lines[actualLineOffset];
+		ctext = lines[actualLineOffset].text;
 		String text2 = ctext.substr(caretPosition, ctext.length()-caretPosition);
 		ctext = ctext.substr(0,caretPosition);
 		ctext += (wchar_t)'\t' + text2;
@@ -1630,7 +1644,7 @@ void UITextInput::onKeyDown(PolyKEY key, wchar_t charCode) {
 			deleteSelection();
 			return;
 		} else {
-		ctext = lines[actualLineOffset];
+		ctext = lines[actualLineOffset].text;
 		
 		if(actualCaretPosition > 0) {
 			saveUndoState();
@@ -1639,17 +1653,18 @@ void UITextInput::onKeyDown(PolyKEY key, wchar_t charCode) {
 				ctext = ctext.substr(0,actualCaretPosition-1);
 				ctext += text2;
 				actualCaretPosition--;
-				_changedText = true;				
+				_changedText = true;			
 			}
 		} else {
 			if(actualLineOffset > 0) {
 				saveUndoState();			
 				actualLineOffset--;
-				actualCaretPosition = lines[actualLineOffset].length();
-				lines[actualLineOffset] = lines[actualLineOffset] + ctext;	
-				removeLines(actualLineOffset+1, actualLineOffset+2);
+				actualCaretPosition = lines[actualLineOffset].text.length();
+				lines[actualLineOffset].text = lines[actualLineOffset].text + ctext;	
+				removeLines(actualLineOffset+1, actualLineOffset+2);				
+				changedText(actualLineOffset, actualLineOffset);
 				setOffsetToActual();
-				updateCaretPosition();				
+				updateCaretPosition();
 				return;
 			}
 		}
@@ -1661,10 +1676,10 @@ void UITextInput::onKeyDown(PolyKEY key, wchar_t charCode) {
         }
 	}
 	
-	lines[actualLineOffset] = ctext;
+	lines[actualLineOffset].text = ctext;
 	
 	if(_changedText) {
-		changedText();
+		changedText(actualLineOffset, actualLineOffset);
 	}
 	updateCaretPosition();
 }
@@ -1771,20 +1786,17 @@ std::vector<TextColorPair> UITextInput::splitTokens(String stringToSplit, LineCo
     return result;
 }
 
-std::vector<TextColorPair> UITextInput::makeWordWrapBuffer(int wrapLineOffset, String indentPrefix) {
+std::vector<TextColorPair> UITextInput::makeWordWrapBuffer(LineInfo *lineInfo, String indentPrefix) {
 
-	String text = lines[wrapLineOffset];
-	
+	String text = lineInfo->text;
 	std::vector<TextColorPair> retVec;
 	
 	if(bufferLines[0]->getLabel()->getTextWidthForString(text) < width - decoratorOffset - padding) {
 			return retVec;
 	}		
 	
-	LineColorInfo *stringColorInfo = NULL;
-	if(wrapLineOffset < lineColors.size()) {
-		stringColorInfo = &lineColors[wrapLineOffset];
-	}
+	LineColorInfo *stringColorInfo = &lineInfo->colorInfo;
+	
 	std::vector<TextColorPair> parts = splitTokens(text, stringColorInfo);
 
 	String checkString;
@@ -1793,9 +1805,7 @@ std::vector<TextColorPair> UITextInput::makeWordWrapBuffer(int wrapLineOffset, S
 	if(parts.size() == 1) {
 		TextColorPair pair;
 		pair.text = text;
-		if(wrapLineOffset < lineColors.size()) {
-			pair.colorInfo = lineColors[wrapLineOffset];
-		}
+		pair.colorInfo = lineInfo->colorInfo;
 		retVec.push_back(pair);
 	} else {
 	
@@ -1833,9 +1843,7 @@ std::vector<TextColorPair> UITextInput::makeWordWrapBuffer(int wrapLineOffset, S
 		if(retVec.size() == 0) {
 			TextColorPair pair;
 			pair.text = checkString;
-			if(wrapLineOffset < lineColors.size()) {
-				pair.colorInfo = lineColors[wrapLineOffset];
-			}		
+			pair.colorInfo = lineInfo->colorInfo;			
 			retVec.push_back(pair);				
 		} else {
 			TextColorPair pair;
@@ -1853,14 +1861,42 @@ std::vector<TextColorPair> UITextInput::makeWordWrapBuffer(int wrapLineOffset, S
 	return retVec;
 }
 
-void UITextInput::updateWordWrap() {
-	wordWrapLines.clear();
-	wordWrapColors.clear();
-		
-	for(int i=0; i < lines.size(); i++) {
-		String indentPrefix = lines[i].substr(0, lines[i].contents.find_first_not_of(" \t", 0));
+void UITextInput::updateWordWrap(int lineStart, int lineEnd) {
+
+
+	int wordWrapRangeBegin = lines[lineStart].wordWrapLineIndex;
+	int wordWrapRangeEnd = lines[lineEnd].wordWrapLineIndex;
+	
+	if(wordWrapRangeBegin == -1) {
+		wordWrapRangeBegin = 0;
+	}
+
+	if(wordWrapRangeEnd == -1) {
+		wordWrapRangeEnd = wordWrapLines.size()-1;
+	}
+
+	for(int i=wordWrapRangeEnd+1; i < wordWrapLines.size(); i++) {
+		if(wordWrapLines[i].actualLineNumber == lineEnd && wordWrapLines[i].isWordWrap) {
+			wordWrapRangeEnd++;
+		} else {
+			break;
+		}
+	}		
+
+	if(wordWrapLines.size()) {
+		if(wordWrapRangeEnd < wordWrapLines.size()) {
+			wordWrapLines.erase(wordWrapLines.begin()+wordWrapRangeBegin, wordWrapLines.begin()+wordWrapRangeEnd+1);
+		} else {
+			wordWrapLines.erase(wordWrapLines.begin()+wordWrapRangeBegin, wordWrapLines.end());		
+		}
+	}
+
+	int insertPoint = wordWrapRangeBegin;
+	
+	for(int i=lineStart; i < lineEnd+1; i++) {
+		String indentPrefix = lines[i].text.substr(0, lines[i].text.contents.find_first_not_of(" \t", 0));
 		
-		std::vector<TextColorPair> wrapLines = makeWordWrapBuffer(i, indentPrefix);
+		std::vector<TextColorPair> wrapLines = makeWordWrapBuffer(&lines[i], indentPrefix);
 		if(wrapLines.size() > 0) {
 			for(int j=0; j < wrapLines.size(); j++) {
 				WordWrapLine line;
@@ -1868,61 +1904,82 @@ void UITextInput::updateWordWrap() {
 				if(j == 0) {
 					line.isWordWrap = false;
 					line.lineStart = 0;
+					lines[i].wordWrapLineIndex = insertPoint;
 				} else {
 					line.isWordWrap = true;
 					line.lineStart = indentPrefix.size();
 				}
 				line.actualLineNumber = i;
-				wordWrapLines.push_back(line);
-				wordWrapColors.push_back(wrapLines[j].colorInfo);
+				
+				line.colorInfo = wrapLines[j].colorInfo;
+				wordWrapLines.insert(wordWrapLines.begin()+insertPoint, line);
+				insertPoint++;
 			}
 		} else {
 				WordWrapLine line;		
-				line.text = lines[i];
+				line.text = lines[i].text;
 				line.isWordWrap = false;
 				line.actualLineNumber = i;
 				line.lineStart = 0;
-				wordWrapLines.push_back(line);
-				if(i < lineColors.size()) {
-					wordWrapColors.push_back(lineColors[i]);
-				}
+				lines[i].wordWrapLineIndex = insertPoint;
+				line.colorInfo = lines[i].colorInfo;		
+				wordWrapLines.insert(wordWrapLines.begin()+insertPoint, line);
+				insertPoint++;				
 		}
 	}
-	readjustBuffer();
+	
+	int actualLineNumber = wordWrapLines[insertPoint-1].actualLineNumber;
+	for(int i=insertPoint; i < wordWrapLines.size(); i++) {
+		if(!wordWrapLines[i].isWordWrap) {
+			actualLineNumber++;		
+			lines[actualLineNumber].wordWrapLineIndex = i;		
+		}
+	}
+			
+	readjustBuffer(wordWrapRangeBegin, wordWrapRangeEnd);
 }
 
-void UITextInput::readjustBuffer() {
+void UITextInput::readjustBuffer(int lineStart, int lineEnd) {
+
+	if(lineEnd == -1) {
+		lineEnd = wordWrapLines.size()-1;
+	}
+
 	int bufferOffset = -linesContainer->position.y/ ( lineHeight+lineSpacing);	
 	Number bufferLineOffset = bufferOffset * ( lineHeight+lineSpacing);		
 
 	for(int i=0; i < bufferLines.size(); i++) {
+	
 		bufferLines[i]->getLabel()->clearColors();
-
 		if(bufferOffset + i < wordWrapLines.size()) {
-
-			if(bufferOffset+i < wordWrapColors.size()) {
-				for(int j=0; j < wordWrapColors[bufferOffset+i].colors.size(); j++) {
-					bufferLines[i]->getLabel()->setColorForRange(wordWrapColors[bufferOffset+i].colors[j].color, wordWrapColors[bufferOffset+i].colors[j].rangeStart, wordWrapColors[bufferOffset+i].colors[j].rangeEnd);
-					bufferLines[i]->setColor(1.0, 1.0, 1.0, 1.0);
-				}		
-			}
+			for(int j=0; j < wordWrapLines[bufferOffset+i].colorInfo.colors.size(); j++) {
+				bufferLines[i]->getLabel()->setColorForRange(wordWrapLines[bufferOffset+i].colorInfo.colors[j].color, wordWrapLines[bufferOffset+i].colorInfo.colors[j].rangeStart, wordWrapLines[bufferOffset+i].colorInfo.colors[j].rangeEnd);
+				bufferLines[i]->setColor(1.0, 1.0, 1.0, 1.0);
+			}		
 			
-			bufferLines[i]->setText(wordWrapLines[bufferOffset+i].text);
+//			if(bufferOffset+i >= lineStart && bufferOffset+i <= lineEnd) {			
+				bufferLines[i]->setText(wordWrapLines[bufferOffset+i].text);
+//			}
 			bufferLines[i]->visible = true;
 		} else {
 			bufferLines[i]->visible = false;
 		}
 		bufferLines[i]->setPosition(-horizontalPixelScroll, bufferLineOffset + (i*(lineHeight+lineSpacing)),0.0f);
+		
 	}
 
 	for(int i=0; i < numberLines.size(); i++) {
 	
+	
 		if(bufferOffset + i < wordWrapLines.size()) {
-		if(lineNumbersEnabled) {						
-			numberLines[i]->setText(String::IntToString(wordWrapLines[bufferOffset+i].actualLineNumber+1));
-			int textWidth = ceil(numberLines[i]->getLabel()->getTextWidth());			
-			numberLines[i]->setPosition(-textWidth,padding + bufferLineOffset + (i*(lineHeight+lineSpacing)),0.0f);		
-
+		if(lineNumbersEnabled) {	
+		
+//			if(bufferOffset+i >= lineStart && bufferOffset+i <= lineEnd) {												
+				numberLines[i]->setText(String::IntToString(wordWrapLines[bufferOffset+i].actualLineNumber+1));
+				int textWidth = ceil(numberLines[i]->getLabel()->getTextWidth());			
+				numberLines[i]->setPosition(-textWidth,padding + bufferLineOffset + (i*(lineHeight+lineSpacing)),0.0f);		
+//			}
+			
 			if(wordWrapLines[bufferOffset+i].isWordWrap) {
 				numberLines[i]->visible = false;			
 			} else {
@@ -1932,6 +1989,7 @@ void UITextInput::readjustBuffer() {
 		} else {
 			numberLines[i]->visible = false;		
 		}
+		
 	}
 
 }
@@ -2026,7 +2084,7 @@ void UITextInput::handleEvent(Event *event) {
 }
 
 void UITextInput::shiftText(bool left) {
-	if (multiLine && (hasSelection || lines[lineOffset] != "")) {
+	if (multiLine && (hasSelection || lines[lineOffset].text != "")) {
 		saveUndoState();
 		
 		String t = (wchar_t)'\t';
@@ -2038,12 +2096,12 @@ void UITextInput::shiftText(bool left) {
 					break;
 				if (indentType == INDENT_TAB) {
 					if (left) {
-						if (lines[i].substr(0,1) == t) {
-							lines[i] = lines[i].substr(1, lines[i].length()-1);
+						if (lines[i].text.substr(0,1) == t) {
+							lines[i].text = lines[i].text.substr(1, lines[i].text.length()-1);
 							caretPosition--;
 						}
 					} else {
-						lines[i] = t + lines[i];
+						lines[i].text = t + lines[i].text;
 						caretPosition++;
 					}
 				} else if (indentType == INDENT_SPACE) {
@@ -2058,12 +2116,12 @@ void UITextInput::shiftText(bool left) {
 		else {
 			if (indentType == INDENT_TAB) {
 				if (left) {
-					if (lines[lineOffset].substr(0,1) == t) {
-						lines[lineOffset] = lines[lineOffset].substr(1, lines[lineOffset].length()-1);
+					if (lines[lineOffset].text.substr(0,1) == t) {
+						lines[lineOffset].text = lines[lineOffset].text.substr(1, lines[lineOffset].text.length()-1);
 						caretPosition--;
 					}
 				} else {
-					lines[lineOffset] = t + lines[lineOffset];
+					lines[lineOffset].text = t + lines[lineOffset].text;
 					caretPosition++;
 				}
 			} else if (indentType == INDENT_SPACE) {
@@ -2075,7 +2133,7 @@ void UITextInput::shiftText(bool left) {
 			}
 		}
 		
-		changedText();
+		changedText(selectionTop, selectionBottom);
 		updateCaretPosition();
 	}
 }

+ 1 - 1
Modules/Contents/UI/Source/PolyUITree.cpp

@@ -162,7 +162,7 @@ void UITree::handleEvent(Event *event) {
 	} else if(event->getDispatcher() == bgBox) {
 		switch(event->getEventCode()) {
 			case InputEvent::EVENT_MOUSEUP:
-				setSelected();
+//				setSelected();
 				willDrag = false;				
 				isDragging = false;				
 			break;