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

Merge pull request #285 from CIB/fix-text-input

Fix text input
Ivan Safrin 12 лет назад
Родитель
Сommit
cfc11ee7e9

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

@@ -31,7 +31,7 @@ PolycodeClipboard *globalClipboard;
 
 
 PolycodeIDEApp::PolycodeIDEApp(PolycodeView *view) : EventDispatcher() {
-	core = new POLYCODE_CORE(view, 900,700,false,true, 0, 0,30, -1);	
+	core = new POLYCODE_CORE(view, 1100, 700,false,true, 0, 0,30, -1);	
 //	core->pauseOnLoseFocus = true;
 	
 	CoreServices::getInstance()->getResourceManager()->reloadResourcesOnModify = true;

+ 1 - 0
Modules/Contents/UI/Include/PolyUIElement.h

@@ -33,6 +33,7 @@ namespace Polycode {
 	class _PolyExport UIElement : public ScreenEntity {
 		public:
 			UIElement();
+			UIElement(Number width, Number height);
 			~UIElement();
 			
 			virtual void Resize(Number width, Number height);

+ 14 - 1
Modules/Contents/UI/Include/PolyUITextInput.h

@@ -372,6 +372,16 @@ namespace Polycode {
 		
 			int selectionCaretPosition;
 			int selectionLine;
+
+			// Used only by single-line text input, so
+			// that you can edit text longer than the width
+			// of the line.
+			// TODO/considerations: Use this to scroll a single
+			// line in multi-line mode?
+			int horizontalPixelScroll;
+			// By how many characters have we scrolled right?
+			int horizontalCharacterScroll;
+
 		
 			bool draggingSelection;
 			bool hasSelection; 
@@ -383,6 +393,9 @@ namespace Polycode {
 			UITextInputSyntaxHighlighter *syntaxHighliter;
 		
 			ScreenEntity *linesContainer;
+
+			// container for the actual text contents
+			UIElement *textContainer; 
 			
 			vector<ScreenLabel*> linesToDelete;	
 			
@@ -429,4 +442,4 @@ namespace Polycode {
 			int indentSpacing;
 			
 	};
-}
+}

+ 7 - 1
Modules/Contents/UI/Source/PolyUIElement.cpp

@@ -29,6 +29,12 @@ UIElement::UIElement() : ScreenEntity() {
 	processInputEvents = true;
 }
 
+UIElement::UIElement(Number width, Number height) : ScreenEntity() {
+	setPositionMode(ScreenEntity::POSITION_TOPLEFT);
+	processInputEvents = true;
+	this->width = width; this->height = height;
+}
+
 UIElement::~UIElement() {
 
 }
@@ -36,4 +42,4 @@ UIElement::~UIElement() {
 void UIElement::Resize(Number width, Number height) {
 	setWidth(width);
 	setHeight(height);
-}
+}

+ 68 - 36
Modules/Contents/UI/Source/PolyUITextInput.cpp

@@ -30,7 +30,7 @@
 
 using namespace Polycode;
 
-UITextInput::UITextInput(bool multiLine, Number width, Number height) : UIElement() {
+UITextInput::UITextInput(bool multiLine, Number width, Number height) : UIElement(width, height) {
 	this->multiLine = multiLine;
 	processInputEvents = true;
 	isNumberOnly = false;
@@ -48,6 +48,9 @@ UITextInput::UITextInput(bool multiLine, Number width, Number height) : UIElemen
 	
 	caretPosition = 0;
 	caretImagePosition = 0;
+
+	horizontalPixelScroll = 0;
+	horizontalCharacterScroll = 0;
 	
 	settingText = false;	
 	
@@ -74,7 +77,7 @@ UITextInput::UITextInput(bool multiLine, Number width, Number height) : UIElemen
 	if(!multiLine) {
 		rectHeight = fontSize+12;
 	} 
-	
+
 	linesContainer = new ScreenEntity();	
 	linesContainer->processInputEvents = true;
 	linesContainer->ownsChildren = true;
@@ -86,8 +89,13 @@ UITextInput::UITextInput(bool multiLine, Number width, Number height) : UIElemen
 	sl = conf->getNumericValue("Polycode", "textBgSkinL");
 
 	
-	padding = conf->getNumericValue("Polycode", "textBgSkinPadding");	
+	padding = conf->getNumericValue("Polycode", "textBgSkinPadding");
 	
+	textContainer = new UIElement();
+	textContainer->ownsChildren = true;
+	textContainer->enableScissor = true;
+
+	linesContainer->addChild(textContainer);
 	if(multiLine) {
 		inputRect = new UIBox(conf->getStringValue("Polycode", "textBgSkinMultiline"),
 						  st,sr,sb,sl,
@@ -109,13 +117,15 @@ UITextInput::UITextInput(bool multiLine, Number width, Number height) : UIElemen
 		
 		lineNumberAnchor = new ScreenEntity();
 		linesContainer->addChild(lineNumberAnchor);
-		
 	} else {
 		lineNumberBg = NULL;
 		lineNumberAnchor = NULL;
 		decoratorOffset = sl/2.0;
 	}
 
+	textContainer->setWidth(this->getWidth() - textContainer->getPosition2D().x - padding);
+	textContainer->setHeight(this->getHeight() - textContainer->getPosition2D().y);
+	textContainer->setPosition(padding + decoratorOffset, padding);
 	
 	inputRect->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
 	inputRect->addEventListener(this, InputEvent::EVENT_MOUSEUP);	
@@ -130,27 +140,27 @@ UITextInput::UITextInput(bool multiLine, Number width, Number height) : UIElemen
 	selectorRectTop->setPositionMode(ScreenEntity::POSITION_TOPLEFT);
 	selectorRectTop->setColor(181.0f/255.0f, 213.0f/255.0f, 255.0f/255.0f, 1);
 	selectorRectTop->visible = false;
-	linesContainer->addChild(selectorRectTop);
+	textContainer->addChild(selectorRectTop);
 
 	selectorRectMiddle = new ScreenShape(ScreenShape::SHAPE_RECT, 1,1);
 	selectorRectMiddle->setPositionMode(ScreenEntity::POSITION_TOPLEFT);	
 	selectorRectMiddle->setColor(181.0f/255.0f, 213.0f/255.0f, 255.0f/255.0f, 1);
 	selectorRectMiddle->visible = false;
-	linesContainer->addChild(selectorRectMiddle);
+	textContainer->addChild(selectorRectMiddle);
 
 	selectorRectBottom = new ScreenShape(ScreenShape::SHAPE_RECT, 1,1);
 	selectorRectBottom->setPositionMode(ScreenEntity::POSITION_TOPLEFT);	
 	selectorRectBottom->setColor(181.0f/255.0f, 213.0f/255.0f, 255.0f/255.0f, 1);
 	selectorRectBottom->visible = false;
-	linesContainer->addChild(selectorRectBottom);
+	textContainer->addChild(selectorRectBottom);
 		
 	
 	blinkerRect = new ScreenShape(ScreenShape::SHAPE_RECT, 1, fontSize+2,0,0);
 	blinkerRect->setPositionMode(ScreenEntity::POSITION_TOPLEFT);
 	blinkerRect->setColor(0,0,0,1);
-	linesContainer->addChild(blinkerRect);
+	textContainer->addChild(blinkerRect);
 	blinkerRect->visible = false;
-	blinkerRect->setPosition(0,3);
+	blinkerRect->setPosition(-horizontalPixelScroll,3);
 	
 	blinkTimer = new Timer(true, 500);
 	blinkTimer->addEventListener(this, Timer::EVENT_TRIGGER);
@@ -160,18 +170,13 @@ UITextInput::UITextInput(bool multiLine, Number width, Number height) : UIElemen
 	this->height = rectHeight;
 	setHitbox(width, rectHeight);
 	
-	updateCaretPosition();
-		
-	
 	scrollContainer = NULL;
-	
 	if(multiLine) {
 		scrollContainer = new UIScrollContainer(linesContainer, false, true, 200, 200);
 		scrollContainer->addEventListener(this, Event::CHANGE_EVENT);
 		addChild(scrollContainer);
 	} else {
 		addChild(linesContainer);
-		enableScissor = true;
 	}
 		
 	undoStateIndex = 0;
@@ -180,12 +185,13 @@ UITextInput::UITextInput(bool multiLine, Number width, Number height) : UIElemen
 	syntaxHighliter = NULL;
 	
 	textColor = Color(0.0,0.0,0.0,1.0);
-	
+
 	currentBufferLines = 0;
 	neededBufferLines = 1;
 	checkBufferLines();
-	
+
 	insertLine(true);
+	updateCaretPosition();
 	
 	core = CoreServices::getInstance()->getCore();
 	core->addEventListener(this, Core::EVENT_COPY);
@@ -194,7 +200,6 @@ UITextInput::UITextInput(bool multiLine, Number width, Number height) : UIElemen
 	core->addEventListener(this, Core::EVENT_UNDO);
 	core->addEventListener(this, Core::EVENT_REDO);
 	core->addEventListener(this, Core::EVENT_SELECT_ALL);
-	
 	indentSpacing = 4;
 	indentType = INDENT_TAB;
 }
@@ -224,7 +229,7 @@ void UITextInput::checkBufferLines() {
 		ScreenLabel *newLine = new ScreenLabel(L"", fontSize, fontName, aaMode);
 		newLine->color = textColor;
 		lineHeight = newLine->getHeight();
-		linesContainer->addChild(newLine);
+		textContainer->addChild(newLine);
 		bufferLines.push_back(newLine);
 	}
 	
@@ -309,7 +314,7 @@ void UITextInput::setSelection(int lineStart, int lineEnd, int colStart, int col
 	}
 
 	selectorRectTop->setScale(topSize, topHeight);
-	selectorRectTop->setPosition(decoratorOffset + topX + padding + (topSize/2.0), padding + (lineStart * (lineHeight+lineSpacing)) + (topHeight/2.0));
+	selectorRectTop->setPosition(topX + (topSize/2.0) - horizontalPixelScroll, lineStart * (lineHeight+lineSpacing) + (topHeight/2.0));
 	
 	if(lineEnd > lineStart && lineEnd < lines.size()) {
 		String bottomLine = lines[lineEnd];
@@ -319,7 +324,7 @@ void UITextInput::setSelection(int lineStart, int lineEnd, int colStart, int col
 			bottomSize = this->width-padding;
 		Number bottomHeight = lineHeight+lineSpacing;
 		selectorRectBottom->setScale(bottomSize, bottomHeight);
-		selectorRectBottom->setPosition(decoratorOffset + padding + (bottomSize/2.0), padding + (lineEnd * (lineHeight+lineSpacing)) + (bottomHeight/2.0));
+		selectorRectBottom->setPosition(bottomSize/2.0 - horizontalPixelScroll, lineEnd * (lineHeight+lineSpacing) + (bottomHeight/2.0));
 		
 		if(lineEnd != lineStart+1) {
 			// need filler
@@ -330,7 +335,7 @@ void UITextInput::setSelection(int lineStart, int lineEnd, int colStart, int col
 				midHeight += lineHeight+lineSpacing;
 			}
 			selectorRectMiddle->setScale(midSize, midHeight);
-			selectorRectMiddle->setPosition(decoratorOffset + padding + (midSize/2.0), padding + ((lineStart+1) * (lineHeight+lineSpacing)) + (midHeight/2.0));										
+			selectorRectMiddle->setPosition(midSize/2.0 - horizontalPixelScroll, ((lineStart+1) * (lineHeight+lineSpacing)) + (midHeight/2.0));										
 			
 		}
 		
@@ -568,12 +573,18 @@ void UITextInput::renumberLines() {
 	}
 	
 	lineNumberAnchor->setPositionX(padding+decoratorOffset - 10);
+
+	// Update the position and width of the text accordingly.
+	textContainer->setPosition(decoratorOffset + padding, padding);
+	textContainer->setWidth(this->getWidth() - textContainer->getPosition2D().x - padding);
+	textContainer->setHeight(this->getHeight() - textContainer->getPosition2D().y - padding);
+	textContainer->scissorBox.setRect(textContainer->getPosition2D().x, textContainer->getPosition2D().y, textContainer->getWidth(), textContainer->getHeight());
 }
 
 void UITextInput::restructLines() {
 
 	for(int i=0; i < bufferLines.size(); i++) {
-		bufferLines[i]->setPosition(decoratorOffset + padding,padding + (i*(lineHeight+lineSpacing)),0.0f);
+		bufferLines[i]->setPosition(0, (i*(lineHeight+lineSpacing)),0.0f);
 	}
 	
 	if(multiLine && lineNumbersEnabled) {
@@ -626,29 +637,53 @@ String UITextInput::getText() {
 }
 
 void UITextInput::updateCaretPosition() {
+	// If this assertion fails, you likely called the function in the wrong
+	// place in the constructor.
+	assert(bufferLines.size() && lines.size());
 
 	if(lineOffset > lines.size()-1)
 		lineOffset = lines.size()-1;
 
-	caretImagePosition = padding;
+	caretImagePosition = 0;
 	if(caretPosition == 0) {
-		caretImagePosition = padding;
+		caretImagePosition = 0;
 	} else if(caretPosition > lines[lineOffset].length()) {
 		caretPosition = lines[lineOffset].length();
 		String caretSubString = lines[lineOffset].substr(0,caretPosition);
-		caretImagePosition = bufferLines[0]->getLabel()->getTextWidthForString(caretSubString);		
-		caretImagePosition = caretImagePosition + padding;		
+		caretImagePosition = bufferLines[0]->getLabel()->getTextWidthForString(caretSubString);
 	} else {
 		String caretSubString = lines[lineOffset].substr(0,caretPosition);
 		caretImagePosition = bufferLines[0]->getLabel()->getTextWidthForString(caretSubString);
-		caretImagePosition = caretImagePosition  + padding;		
 	}
 	blinkerRect->visible  = true;
 	blinkTimer->Reset();
 	
 	if(doSelectToCaret) {
 		doSelectToCaret = false;
-		
+	}
+
+	if(!multiLine) {
+		// Make sure the new caret position is visible.
+
+		// Try scrolling left.
+		while(caretImagePosition < horizontalPixelScroll) {
+			horizontalCharacterScroll--;
+
+			// Update pixel scroll from new character scroll.
+			String subString = lines[0].substr(0,horizontalCharacterScroll);
+			horizontalPixelScroll = bufferLines[0]->getLabel()->getTextWidthForString(subString);
+		}
+
+		// Try scrolling right.
+		while(caretImagePosition + blinkerRect->getWidth() > horizontalPixelScroll + textContainer->getWidth()) {
+			horizontalCharacterScroll++;
+
+			// Update pixel scroll from new character scroll.
+			String subString = lines[0].substr(0,horizontalCharacterScroll);
+			horizontalPixelScroll = bufferLines[0]->getLabel()->getTextWidthForString(subString);
+		}
+
+		bufferLines[0]->setPosition(-horizontalPixelScroll, 0);
 	}
 /*	
 	if(multiLine) {	
@@ -1402,16 +1437,11 @@ void UITextInput::onKeyDown(PolyKEY key, wchar_t charCode) {
 
 void UITextInput::Update() {
 
-	if(!multiLine) {
-		Vector2 pos = getScreenPosition();
-		scissorBox.setRect(pos.x,pos.y, width+sr+sl, height+sb+st);
-	}
-
 	if(hasSelection) {
 		blinkerRect->visible = false;
 	}
 
-	blinkerRect->setPosition(decoratorOffset + caretImagePosition + 1, padding + (lineOffset * ( lineHeight+lineSpacing)));
+	blinkerRect->setPosition(caretImagePosition + 1 -horizontalPixelScroll, (lineOffset * ( lineHeight+lineSpacing)));
 
 	if(hasFocus) {
 //		inputRect->setStrokeColor(1.0f, 1.0f, 1.0f, 0.25f);	
@@ -1424,6 +1454,8 @@ void UITextInput::Update() {
 		delete linesToDelete[i];
 	}
 	linesToDelete.clear();
+
+	textContainer->scissorBox.setRect(textContainer->getScreenPosition().x, textContainer->getScreenPosition().y, textContainer->getWidth(), textContainer->getHeight());
 }
 
 UITextInput::~UITextInput() {
@@ -1458,7 +1490,7 @@ void UITextInput::readjustBuffer() {
 		} else {
 			bufferLines[i]->setText("");
 		}
-		bufferLines[i]->setPosition(decoratorOffset + padding,padding + bufferLineOffset + (i*(lineHeight+lineSpacing)),0.0f);	
+		bufferLines[i]->setPosition(0, (i*(lineHeight+lineSpacing)),0.0f);	
 	}
 	
 	for(int i=0; i < numberLines.size(); i++) {
@@ -1618,4 +1650,4 @@ void UITextInput::convertIndentToTabs() {
 		
 		//TODO
 	}
-}
+}