r16639 by jghali - #10017 : jump when typing in text frame, provide a more elegant solution

scribus-commit scribus-commit at lists.scribus.net
Tue Jun 7 21:02:29 UTC 2011


Author: jghali
Date: Tue Jun  7 21:02:29 2011
New Revision: 16639

URL: http://scribus.net/websvn/listing.php?repname=Scribus&sc=1&rev=16639
Log:
#10017 : jump when typing in text frame, provide a more elegant solution
- add more functions in StoryText for doing operations directly at current cursor position 
- complement object update api by updateLayout() : contrary to update(), updateLayout() will update layout immediately whereas update() will trigger layout() only in following paintEvent

Modified:
    trunk/Scribus/scribus/canvasmode_edit.cpp
    trunk/Scribus/scribus/observable.h
    trunk/Scribus/scribus/pageitem_textframe.cpp
    trunk/Scribus/scribus/scribusdoc.cpp
    trunk/Scribus/scribus/scribusview.cpp
    trunk/Scribus/scribus/scribusview.h
    trunk/Scribus/scribus/text/sctext_shared.cpp
    trunk/Scribus/scribus/text/sctext_shared.h
    trunk/Scribus/scribus/text/storytext.cpp
    trunk/Scribus/scribus/text/storytext.h

Modified: trunk/Scribus/scribus/canvasmode_edit.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=16639&path=/trunk/Scribus/scribus/canvasmode_edit.cpp
==============================================================================
--- trunk/Scribus/scribus/canvasmode_edit.cpp (original)
+++ trunk/Scribus/scribus/canvasmode_edit.cpp Tue Jun  7 21:02:29 2011
@@ -240,7 +240,7 @@
 		QPen cPen ( Qt::black, 0.9 , Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin );
 
 		// normalize Current Position
-		textframe->itemText.setCursorPosition( qMax ( 0, qMin( textframe->itemText.cursorPosition(), textframe->itemText.length() ) ) );
+		textframe->itemText.normalizeCursorPosition();
 		int textCursorPos ( textframe->itemText.cursorPosition() );
 
 		if ( textframe->lastInFrame() >= signed ( textframe->itemText.nrOfItems() )

Modified: trunk/Scribus/scribus/observable.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=16639&path=/trunk/Scribus/scribus/observable.h
==============================================================================
--- trunk/Scribus/scribus/observable.h (original)
+++ trunk/Scribus/scribus/observable.h Tue Jun  7 21:02:29 2011
@@ -71,9 +71,11 @@
 template<class OBSERVED>
 struct Private_Memento : public UpdateMemento
 {
-	Private_Memento(OBSERVED data) : m_data(data) {};
+	Private_Memento(OBSERVED data) : m_data(data), m_layout(false) {};
+	Private_Memento(OBSERVED data, bool layout) : m_data(data), m_layout(layout) {};
 	
 	OBSERVED m_data;
+	bool     m_layout;
 };
 
 
@@ -84,7 +86,7 @@
 template<class OBSERVED>
 class SCRIBUS_API Observer {
 public:
-	virtual void changed(OBSERVED) = 0;
+	virtual void changed(OBSERVED, bool doLayout) = 0;
 	virtual ~Observer() {}
 };
 
@@ -124,6 +126,11 @@
 	    will take care of that.
 	 */
 	virtual void update(OBSERVED what);
+
+	/**
+		Same as update, except layout will be update immediately
+	 */
+	virtual void updateLayout(OBSERVED what);
 	
 	void connectObserver(Observer<OBSERVED>* o);
 	void disconnectObserver(Observer<OBSERVED>* o);
@@ -170,6 +177,11 @@
 	{ 
 		m_massObservable->update(dynamic_cast<OBSERVED*>(this)); 
 	}
+
+	virtual void updateLayout() 
+	{ 
+		m_massObservable->updateLayout(dynamic_cast<OBSERVED*>(this)); 
+	}
 	
 private:
 	MassObservable<OBSERVED*>* m_massObservable;
@@ -239,6 +251,15 @@
 	}
 }
 
+template<class OBSERVED>
+inline void MassObservable<OBSERVED>::updateLayout(OBSERVED what)
+{
+	Private_Memento<OBSERVED>* memento = new Private_Memento<OBSERVED>(what, true);
+	if (m_um == NULL || m_um->requestUpdate(this, memento))
+	{
+		updateNow(memento);
+	}
+}
 
 template<class OBSERVED>
 inline void MassObservable<OBSERVED>::updateNow(UpdateMemento* what)
@@ -246,7 +267,7 @@
 	Private_Memento<OBSERVED>* memento = dynamic_cast<Private_Memento<OBSERVED>*>(what);
 	foreach (Observer<OBSERVED>* obs, m_observers)
 	{
-		obs->changed(memento->m_data);
+		obs->changed(memento->m_data, memento->m_layout);
 	}
 	changedSignal->emitSignal(QVariant::fromValue(memento->m_data));
 	delete memento;

Modified: trunk/Scribus/scribus/pageitem_textframe.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=16639&path=/trunk/Scribus/scribus/pageitem_textframe.cpp
==============================================================================
--- trunk/Scribus/scribus/pageitem_textframe.cpp (original)
+++ trunk/Scribus/scribus/pageitem_textframe.cpp Tue Jun  7 21:02:29 2011
@@ -903,7 +903,9 @@
 // 	printBacktrace(24);
 	if (BackBox != NULL && BackBox->invalid) {
 //		qDebug("textframe: len=%d, going back", itemText.length());
-		invalid = false;
+		// Why that invalid = false here? Calling prevInChain->layout() does
+		// not ensure that this box will be layouted
+		// invalid = false;
 		PageItem_TextFrame* prevInChain = dynamic_cast<PageItem_TextFrame*>(BackBox);
 		while (prevInChain && prevInChain->invalid)
 		{
@@ -2764,10 +2766,10 @@
 	if (frameUnderflows())
 	{
 		itemText.setCursorPosition( itemText.length() );
-		m_Doc->view()->Deselect(true);
 		PageItem * jumpFrame = frameTextEnd();
 		if (jumpFrame)
 		{
+			m_Doc->view()->Deselect(true);
 			m_Doc->scMW()->selectItemsFromOutlines(jumpFrame);
 			m_Doc->scMW()->setTBvals(jumpFrame);
 			jumpFrame->update();
@@ -2886,6 +2888,8 @@
 		else if (kk == Qt::Key_Right) 
 			kk = Qt::Key_Left;
 	}
+
+	int oldLast = lastInFrame();
 	switch (kk)
 	{
 	case Qt::Key_Home:
@@ -3007,7 +3011,7 @@
 					{
 						view->Deselect(true);
 						// TODO position at the right place in previous frame
-						itemText.setCursorPosition( BackBox->lastInFrame() );
+						BackBox->itemText.setCursorPosition( BackBox->lastInFrame() );
 						m_Doc->scMW()->selectItemsFromOutlines(BackBox);
 					}
 			}
@@ -3017,7 +3021,7 @@
 				if (BackBox != 0)
 				{
 					view->Deselect(true);
-					itemText.setCursorPosition( BackBox->lastInFrame() );
+					BackBox->itemText.setCursorPosition( BackBox->lastInFrame() );
 					m_Doc->scMW()->selectItemsFromOutlines(BackBox);
 				}
 			}
@@ -3030,7 +3034,7 @@
 		if (itemText.cursorPosition() == firstInFrame() && BackBox != 0)
 		{
 			view->Deselect(true);
-			itemText.setCursorPosition( BackBox->firstInFrame() );
+			BackBox->itemText.setCursorPosition( BackBox->firstInFrame() );
 			m_Doc->scMW()->selectItemsFromOutlines(BackBox);
 			//currItem = currItem->BackBox;
 		}
@@ -3065,7 +3069,7 @@
 		{
 			int pos = itemText.cursorPosition();
 			itemText.setCursorPosition(-1, true);
-			if (pos > 0)
+			if ( pos > 0 )
 				ExpandSel(-1, oldPos);
 		}
 		else
@@ -3077,7 +3081,7 @@
 				if (BackBox != 0)
 				{
 					view->Deselect(true);
-					itemText.setCursorPosition( BackBox->lastInFrame() );
+					BackBox->itemText.setCursorPosition( BackBox->lastInFrame() );
 					m_Doc->scMW()->selectItemsFromOutlines(BackBox);
 					//currItem = currItem->BackBox;
 				}
@@ -3164,7 +3168,7 @@
 			keyRepeat = false;
 			return;
 		}
-		cr = itemText.text(itemText.cursorPosition(), 1);
+		cr = itemText.text(1);
 		if (itemText.lengthOfSelection() == 0)
 			itemText.select(itemText.cursorPosition(), 1, true);
 		deleteSelectedTextFromFrame();
@@ -3204,12 +3208,17 @@
 //			m_Doc->chAbStyle(this, findParagraphStyle(m_Doc, itemText.paragraphStyle(qMax(CPos-1,0))));
 //			Tinput = false;
 		}
+		updateLayout();
+		if (oldLast != lastInFrame() && NextBox != 0 && NextBox->invalid)
+			NextBox->updateLayout();
 		if (itemText.cursorPosition() < firstInFrame())
 		{
 			itemText.setCursorPosition( firstInFrame() );
 			if (BackBox != 0)
 			{
 				view->Deselect(true);
+				if (BackBox->invalid)
+					BackBox->updateLayout();
 				itemText.setCursorPosition( BackBox->lastInFrame() );
 				m_Doc->scMW()->selectItemsFromOutlines(BackBox);
 				//currItem = currItem->BackBox;
@@ -3285,14 +3294,20 @@
 			doUpdate = true;
 		}
 		if (doUpdate)
-			update();
+		{
+			// update layout immediately, we need MaxChars to be correct to detect 
+			// if we need to move to next frame or not
+			updateLayout();
+			if (oldLast != lastInFrame() && NextBox != 0 && NextBox->invalid)
+				NextBox->updateLayout();
+		}
 		//check if cursor need to jump to next linked frame
-		if (lastInFrame() < (itemText.length() -2) && NextBox != 0)
+		if ((itemText.cursorPosition() > lastInFrame() + 1) && (lastInFrame() < (itemText.length() - 2)) && NextBox != 0)
 		{
 			view->Deselect(true);
-			//NextBox->CPos = CPos;
+			view->Deselect(true);
+			NextBox->update();
 			m_Doc->scMW()->selectItemsFromOutlines(NextBox);
-			NextBox->update();
 		}
 		break;
 	}

Modified: trunk/Scribus/scribus/scribusdoc.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=16639&path=/trunk/Scribus/scribus/scribusdoc.cpp
==============================================================================
--- trunk/Scribus/scribus/scribusdoc.cpp (original)
+++ trunk/Scribus/scribus/scribusdoc.cpp Tue Jun  7 21:02:29 2011
@@ -135,7 +135,7 @@
 		}
 	}
 	
-	void changed(Page* pg)
+	void changed(Page* pg, bool /*doLayout*/)
 	{
 		QRectF pagebox(pg->xOffset(), pg->yOffset(), pg->width(), pg->height());
 		doc->invalidateRegion(pagebox);
@@ -148,9 +148,11 @@
 		m_docChangeNeeded = true;
 	}
 	
-	void changed(PageItem* it)
+	void changed(PageItem* it, bool doLayout)
 	{
 		it->invalidateLayout();
+		if (doLayout)
+			it->layout();
 		doc->regionsChanged()->update(it->getVisualBoundingRect());
 		if (m_updateEnabled <= 0)
 		{
@@ -6942,7 +6944,7 @@
 				start = currItem->itemText.startOfSelection();
 				stop = currItem->itemText.endOfSelection();
 				if (start >= stop)
-					start = stop = qMax(0, qMin(currItem->itemText.length(), currItem->itemText.cursorPosition()));
+					start = stop = currItem->itemText.normalizedCursorPosition();
 			}
 			for (int pos=start; pos < stop; ++pos)
 			{
@@ -6996,7 +6998,7 @@
 				start = currItem->itemText.startOfSelection();
 				stop = currItem->itemText.endOfSelection();
 				if (start >= stop)
-					start = stop = qMax(0, qMin(currItem->itemText.length(), currItem->itemText.cursorPosition()));
+					start = stop = currItem->itemText.normalizedCursorPosition();
 			}
 			for (int pos=start; pos < stop; ++pos)
 			{
@@ -7060,7 +7062,7 @@
 				start = currItem->itemText.startOfSelection();
 				stop = currItem->itemText.endOfSelection();
 				if (start >= stop)
-					start = stop = qMax(0, qMin(currItem->itemText.length(), currItem->itemText.cursorPosition()));
+					start = stop = currItem->itemText.normalizedCursorPosition();
 			}
 			for (int pos=start; pos < stop; ++pos)
 			{
@@ -7116,7 +7118,7 @@
 				else
 				{
 					start = qMax(currItem->firstInFrame(), currItem->itemText.cursorPosition());
-					length = (start + 1) < currItem->itemText.length()? 1 : 0;
+					length = (start + 1) < currItem->itemText.length() ? 1 : 0;
 				}
 			}
 			currItem->itemText.applyCharStyle(start, qMax(0, length), newStyle);

Modified: trunk/Scribus/scribus/scribusview.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=16639&path=/trunk/Scribus/scribus/scribusview.cpp
==============================================================================
--- trunk/Scribus/scribus/scribusview.cpp (original)
+++ trunk/Scribus/scribus/scribusview.cpp Tue Jun  7 21:02:29 2011
@@ -460,7 +460,7 @@
 	}
 }
 
-void ScribusView::changed(QRectF re)
+void ScribusView::changed(QRectF re, bool)
 {
 	double scale = m_canvas->scale();
 	int newCanvasWidth = qRound((Doc->maxCanvasCoordinate.x() - Doc->minCanvasCoordinate.x()) * scale);

Modified: trunk/Scribus/scribus/scribusview.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=16639&path=/trunk/Scribus/scribus/scribusview.h
==============================================================================
--- trunk/Scribus/scribus/scribusview.h (original)
+++ trunk/Scribus/scribus/scribusview.h Tue Jun  7 21:02:29 2011
@@ -212,7 +212,7 @@
 	void setScale(const double newScale);
 	double scale() const;
 
-	virtual void changed(QRectF re);
+	virtual void changed(QRectF re, bool);
 
 	void updateCanvas(QRectF box = QRectF());
 	void updateCanvas(double x, double y, double width, double height) { updateCanvas(QRectF(x,y,width,height)); }

Modified: trunk/Scribus/scribus/text/sctext_shared.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=16639&path=/trunk/Scribus/scribus/text/sctext_shared.cpp
==============================================================================
--- trunk/Scribus/scribus/text/sctext_shared.cpp (original)
+++ trunk/Scribus/scribus/text/sctext_shared.cpp Tue Jun  7 21:02:29 2011
@@ -66,7 +66,6 @@
 {
 	if (this != &other) 
 	{
-		cursorPosition = other.cursorPosition;
 		defaultStyle   = other.defaultStyle;
 		trailingStyle  = other.trailingStyle;
 		pstyleContext  = other.pstyleContext;
@@ -90,6 +89,7 @@
 			}
 		}
 		len = count();
+		cursorPosition = other.cursorPosition;
 		pstyleContext.invalidate();
 //			qDebug() << QString("StoryText::copy: %1 align=%2 %3").arg(trailingStyle.parentStyle()->name())
 //				   .arg(trailingStyle.alignment()).arg((uint)trailingStyle.context());

Modified: trunk/Scribus/scribus/text/sctext_shared.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=16639&path=/trunk/Scribus/scribus/text/sctext_shared.h
==============================================================================
--- trunk/Scribus/scribus/text/sctext_shared.h (original)
+++ trunk/Scribus/scribus/text/sctext_shared.h Tue Jun  7 21:02:29 2011
@@ -21,7 +21,7 @@
 	StyleContextProxy pstyleContext;
 	uint refs;
 	uint len;
-	uint  cursorPosition;
+	uint cursorPosition;
 	ParagraphStyle trailingStyle;
 	ScText_Shared(const StyleContext* pstyles);	
 

Modified: trunk/Scribus/scribus/text/storytext.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=16639&path=/trunk/Scribus/scribus/text/storytext.cpp
==============================================================================
--- trunk/Scribus/scribus/text/storytext.cpp (original)
+++ trunk/Scribus/scribus/text/storytext.cpp Tue Jun  7 21:02:29 2011
@@ -162,6 +162,27 @@
 	return *this;
 }
 
+int StoryText::cursorPosition() const
+{
+	return d->cursorPosition;
+}
+
+void StoryText::setCursorPosition(int pos, bool relative)
+{
+	if (relative)
+		pos += d->cursorPosition;
+	d->cursorPosition = qMin((uint) qMax(pos, 0), d->len);
+}
+
+void StoryText::normalizeCursorPosition()
+{
+	d->cursorPosition = qMax((uint) 0, qMin(d->cursorPosition, d->len));
+}
+
+int StoryText::normalizedCursorPosition()
+{
+	return (int) qMax((uint) 0, qMin(d->cursorPosition, d->len));
+}
 
 void StoryText::clear()
 {
@@ -316,7 +337,7 @@
 		// consistent in functions such as select()
 		if (i <= selLast) --selLast;
 		if (i < selFirst) --selFirst;
-		if ((i + 1 )<= d->cursorPosition && d->cursorPosition > 0) d->cursorPosition -= 1;
+		if ((i + 1 ) <= d->cursorPosition && d->cursorPosition > 0) d->cursorPosition -= 1;
 	}
 
 	d->len = d->count();
@@ -456,18 +477,6 @@
 	invalidate(pos, pos + 1);
 }
 
-int StoryText::cursorPosition() const
-{
-	return d->cursorPosition;
-}
-
-void StoryText::setCursorPosition(int pos, bool relative)
-{
-	if (relative)
-		pos += d->cursorPosition;
-	d->cursorPosition = qMin((uint) qMax(pos, 0), d->len);
-}
-
 void StoryText::hyphenateWord(int pos, uint len, char* hyphens)
 {
 	assert(pos >= 0);
@@ -617,6 +626,11 @@
 	
 	StoryText* that = const_cast<StoryText *>(this);
 	return dynamic_cast<const CharStyle &> (*that->d->at(pos));
+}
+
+const ParagraphStyle & StoryText::paragraphStyle() const
+{
+	return paragraphStyle(d->cursorPosition);
 }
 
 const ParagraphStyle & StoryText::paragraphStyle(int pos) const

Modified: trunk/Scribus/scribus/text/storytext.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=16639&path=/trunk/Scribus/scribus/text/storytext.h
==============================================================================
--- trunk/Scribus/scribus/text/storytext.h (original)
+++ trunk/Scribus/scribus/text/storytext.h Tue Jun  7 21:02:29 2011
@@ -102,27 +102,41 @@
 	virtual void saxx(SaxHandler& handler, const Xml_string& elemtag) const;
 	virtual void saxx(SaxHandler& handler)                     const { saxx(handler, saxxDefaultElem); }
 	
+	int  cursorPosition() const;
+	void setCursorPosition(int pos, bool relative = false);
+	void normalizeCursorPosition();
+	int  normalizedCursorPosition();
+
  	void clear();
 	StoryText copy() const;
+	// Insert chars from another StoryText object at current cursor position
 	void insert(const StoryText& other, bool onlySelection = false);
+	// Insert chars from another StoryText object at specific position
 	void insert(int pos, const StoryText& other, bool onlySelection = false);
+	// Append chars from another StoryText object
 	void append(const StoryText& other) { insert(length(), other, false); }
+	// Remove len chars at specific position
  	void removeChars(int pos, uint len);
+	// Insert chars at current cursor position
 	void insertChars(QString txt, bool applyNeighbourStyle = false);
+	// Insert chars ar specific position
  	void insertChars(int pos, QString txt, bool applyNeighbourStyle = false);
+	// Insert inline object at current cursor position
 	void insertObject(PageItem* obj);
+	// Insert object at specific position
  	void insertObject(int pos, PageItem* obj);
  	void replaceChar(int pos, QChar ch);
 
-	int  cursorPosition() const;
-	void setCursorPosition(int pos, bool relative = false);
-
 	void hyphenateWord(int pos, uint len, char* hyphens);
 	
  	int length() const;
+	// Get char at current cursor position
 	QChar   text() const;
+	// Get char at specific position
  	QChar   text(int pos) const;
+	// Get text with len chars at specific position
  	QString text(int pos, uint len) const;
+	// Get word at specific position
 	QString wordAt(int pos) const;
 
 	bool hasObject(int pos) const;
@@ -137,8 +151,13 @@
 	int nextFramePos(int c);
 	int prevFramePos(int c);
 	
+	// Get charstyle at current cursor position
 	const CharStyle& charStyle() const;
+	// Get charstyle at specific position
  	const CharStyle& charStyle(int pos) const;
+	// Get paragraph style at current cursor position
+	const ParagraphStyle& paragraphStyle() const;
+	// Get paragraph style at specific position
  	const ParagraphStyle& paragraphStyle(int pos) const;
  	const ParagraphStyle& defaultStyle() const;
  	void setDefaultStyle(const ParagraphStyle& style);




More information about the scribus-commit mailing list