Revision: 4368 http://vexi.svn.sourceforge.net/vexi/?rev=4368&view=rev Author: clrg Date: 2012-03-12 15:59:39 +0000 (Mon, 12 Mar 2012) Log Message: ----------- Improved cursor placement handling
Modified Paths: -------------- trunk/org.vexi-vexi.widgets/src_main/org/vexi/lib/text/edit.t Modified: trunk/org.vexi-vexi.widgets/src_main/org/vexi/lib/text/edit.t =================================================================== --- trunk/org.vexi-vexi.widgets/src_main/org/vexi/lib/text/edit.t 2012-03-09 01:18:15 UTC (rev 4367) +++ trunk/org.vexi-vexi.widgets/src_main/org/vexi/lib/text/edit.t 2012-03-12 15:59:39 UTC (rev 4368) @@ -655,77 +655,96 @@ // reset need to loop updateCurPos = false; - if (aWord and aInWord) { - // place cursor at mouse position if it's over a word - var tx = aX-aBlock.distanceto(aWord).x; - var ci = static.getIndInWord(aWord, tx); + if (!aWord or !aInWord) while(true) { + // using a while loop so we can "break" out + // to avoid a more complex suite of if/else - if (ci == aWord.text.length and aBlock.numchildren > aBlock.indexof(aWord)+1) { - // place cursor after word - //aBlock = aBlock; - aPos = 0; - aWord = aBlock[aBlock.indexof(aWord)+1]; - - } else { - // place cursor in word - //aBlock = aBlock; - aPos = ci; - //aWord = aWord; - } - - } else while (true) { // place cursor as close to the mouse position as possible var d = thisbox.distanceto(aBlock); var dY = d.y; var dX = d.x; + // STAGE 1: find the correct block + + var aI = thisbox.indexof(aBlock); + if (aI == -1) { + // aBlock no longer part of this edit + // -> probably an error + throw "Invalid edit state"; + + } else + if (!multiline) { + aBlock = thisbox[0]; + } else if (dY > aY) { - // mouse is above aBlock - var i = thisbox.indexof(aBlock); - for (i--; i >= 0; i--) { - aBlock = thisbox[i]; - dY -= aBlock.height; + // mouse is above aBlock; + // this occurs when the user moves the mouse + // outside of the edit but continues to hold + // the button down + // -> update ablock to correct block for the + // height of the mouse + var i; + for (i = aI; i > 0; i--) { + dY -= thisbox[i].height; if (aY > dY) break; } - if (i == -1) { - aWord = aBlock[0]; - aPos = 0; - break; - } + aBlock = thisbox[i]; - } else if (aY > dY+aBlock.height) { + } else + if (aY > dY+aBlock.height) { // mouse is below aBlock - var n = thisbox.numchildren; - dY += aBlock.height; - var i = thisbox.indexof(aBlock); - for (i++; n > i; i++) { - aBlock = thisbox[i]; - dY += aBlock.height; + // -> update ablock to correct block for the + // height of the mouse + var i; + for (i = aI; n-1 > i; i++) { + dY += thisbox[i].height; if (dY > aY) break; } - if (i == thisbox.numchildren) { - aWord = aBlock.numchildren ? aBlock[aBlock.numchildren-1] : null; - aPos = aWord ? aWord.text.length : 0; - break; - } + aBlock = thisbox[i]; } - // else working within the current block + // else working within the vertical confines of + // the current block; mouse to left or right of word + // STAGE 2: find the aligned word + if (aBlock.numchildren == 0) { // empty block aWord = null; aPos = 0; + break; } else { - // block with children + // STAGE 2a: find a word on the correct line + var ind1 = 0; var ind2 = aBlock.numchildren-1; var indm = 0; + var lineY; + var subY = aY - dY; + var w1 = aBlock[ind1]; + var w2 = aBlock[ind2]; + var wm; + + if (!aBlock.multiline or w1.y+w1.height >= subY) { + // use top line + lineY = 0; + wm = aBlock[0]; + + } else + if (aY >= w2.y) { + // use bottom line + lineY = w2.y; + wm = aBlock[aBlock.numchildren-1]; + + } else while (ind2 > ind1) { + // locate the line + // the middle indm = vexi.math.floor(ind1+(ind2-ind1)/2); + wm = aBlock[indm]; - if (aY > aBlock[indm].y+aBlock[indm].height) { + if (aY > wm.y+wm.height) { // indm is on a line below mouse click if (ind1 == indm) { indm = ind2; @@ -733,7 +752,7 @@ ind1 = indm; continue; } - if (aBlock[indm].y > aY) { + if (wm.y > aY) { // indm is on a line above mouse click if (ind2 == indm) { indm = ind1; @@ -742,28 +761,50 @@ continue; } // indm is on the same line that was clicked + lineY = wm.y; break; } - if (aX > dX) { - // to the right of current line, find word at the end of the line - var n = aBlock.numchildren; - while (n > indm+1 and aBlock[indm].y == aBlock[indm+1].y) { - indm++; - } - aWord = aBlock[indm]; - aPos = aWord ? aWord.text.length : 0; - } else { - // to the left, find word at the start of the line - while (indm-1 >= 0 and aBlock[indm].y == aBlock[indm-1].y) { - indm--; - } - aWord = aBlock[indm]; - aPos = 0; - } + // STAGE 2b: we have the line and a starting point + // (word) from which we can find the word that is + // closest to the mouse cursor + + // go left + for (var i = indm; i>=0 and wm.x > aX-dX; i--) + wm = aBlock[i]; + + // go right + var n = aBlock.numchildren; + for (var i = indm; n>i and aX-dX >= wm.x; i++) + wm = aBlock[i]; + + aWord = wm; } break; } + + if (aWord==null) { + aPos = 0; + } else { + // place cursor at mouse x position + // relative to aWord + var tx = aX-aBlock.distanceto(aWord).x; + var ci = static.getIndInWord(aWord, tx); + + if (ci == aWord.text.length and aBlock.numchildren > aBlock.indexof(aWord)+1) { + // place cursor after word + //aBlock = aBlock; + aPos = 0; + aWord = aBlock[aBlock.indexof(aWord)+1]; + + } else { + // place cursor in word + //aBlock = aBlock; + aPos = ci; + //aWord = aWord; + } + } + // FEATURE: syncCursor should probably happen post-highlight ? if (abortTip) { abortTip = false; @@ -805,6 +846,7 @@ // clean up; thread no longer in progress doHighlight = false; + frameToThis = null; tip = false; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ Try before you buy = See our experts in action! The most comprehensive online learning library for Microsoft developers is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3, Metro Style Apps, more. Free future releases when you subscribe now! http://p.sf.net/sfu/learndevnow-dev2 _______________________________________________ Vexi-svn mailing list Vexi-svn@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/vexi-svn