diff options
author | Jonas Finnemann Jensen <jopsen@gmail.com> | 2010-11-24 09:36:21 +0100 |
---|---|---|
committer | Jonas Finnemann Jensen <jopsen@gmail.com> | 2011-01-30 20:20:21 +0100 |
commit | 592777e2b22e4f1121b755d49ecdfdfb2e322d45 (patch) | |
tree | a73a24d279ef457959b3edfa46090d214be3f393 /starmath | |
parent | aede297486282b3f49804a72f7230e4536bb0469 (diff) |
Enable line deletion in starmath
* Implemented SmCursor::DeletePrev, for deletion of lines
* Fixed nasty bug in SmCursor::InsertRow
* Code cleanup in cursor.cxx
Diffstat (limited to 'starmath')
-rw-r--r-- | starmath/inc/cursor.hxx | 28 | ||||
-rw-r--r-- | starmath/source/cursor.cxx | 152 | ||||
-rw-r--r-- | starmath/source/view.cxx | 5 |
3 files changed, 115 insertions, 70 deletions
diff --git a/starmath/inc/cursor.hxx b/starmath/inc/cursor.hxx index 49f1e0c18a8c..b5fbd13e28cb 100644 --- a/starmath/inc/cursor.hxx +++ b/starmath/inc/cursor.hxx @@ -132,6 +132,12 @@ public: /** Delete the current selection or do nothing */ void Delete(); + /** Delete selection, previous element or merge lines + * + * This method implements the behaviour of backspace. + */ + void DeletePrev(OutputDevice* pDev); + /** Insert text at the current position */ void InsertText(XubString aString); @@ -270,6 +276,28 @@ private: */ static SmNodeList* LineToList(SmStructureNode* pLine, SmNodeList* pList = new SmNodeList()); + /** Auxiliary function for calling LineToList on a node + * + * This method sets pNode = NULL and remove it from it's parent. + * (Assuming it has a parent, and is a child of it). + */ + static SmNodeList* NodeToList(SmNode*& rpNode, SmNodeList* pList = new SmNodeList()){ + //Remove from parent and NULL rpNode + SmNode* pNode = rpNode; + if(rpNode && rpNode->GetParent()){ //Don't remove this, correctness relies on it + int index = rpNode->GetParent()->IndexOfSubNode(rpNode); + if(index != -1) + rpNode->GetParent()->SetSubNode(index, NULL); + } + rpNode = NULL; + //Create line from node + if(pNode && IsLineCompositionNode(pNode)) + return LineToList((SmStructureNode*)pNode, pList); + if(pNode) + pList->push_front(pNode); + return pList; + } + /** Clone a visual line to a list * * Doesn't clone SmErrorNode's these are ignored, as they are context dependent metadata. diff --git a/starmath/source/cursor.cxx b/starmath/source/cursor.cxx index 25c4522b67d1..c5303663f047 100644 --- a/starmath/source/cursor.cxx +++ b/starmath/source/cursor.cxx @@ -186,6 +186,76 @@ void SmCursor::Draw(OutputDevice& pDev, Point Offset, bool isCaretVisible){ SmCaretDrawingVisitor(pDev, GetPosition(), Offset, isCaretVisible); } +void SmCursor::DeletePrev(OutputDevice* pDev){ + //Delete only a selection if there's a selection + if(HasSelection()){ + Delete(); + return; + } + + SmNode* pLine = FindTopMostNodeInLine(position->CaretPos.pSelectedNode); + SmStructureNode* pLineParent = pLine->GetParent(); + int nLineOffset = pLineParent->IndexOfSubNode(pLine); + + //If we're in front of a node who's parent is a TABLE + if(pLineParent->GetType() == NTABLE && position->CaretPos.Index == 0 && nLineOffset > 0){ + //Now we can merge with nLineOffset - 1 + BeginEdit(); + //Line to merge things into, so we can delete pLine + SmNode* pMergeLine = pLineParent->GetSubNode(nLineOffset-1); + j_assert(pMergeLine, "pMergeLine cannot be NULL!"); + //Convert first line to list + SmNodeList *pLineList = NodeToList(pMergeLine); + //Find iterator to patch + SmNodeList::iterator patchPoint = pLineList->end(); + patchPoint--; + //Convert second line to list + NodeToList(pLine, pLineList); + //Patch the line list + patchPoint++; + SmCaretPos PosAfterDelete = PatchLineList(pLineList, patchPoint); + //Parse the line + pLine = SmNodeListParser().Parse(pLineList); + delete pLineList; + pLineParent->SetSubNode(nLineOffset-1, pLine); + //Delete the removed line slot + SmNodeArray lines(pLineParent->GetNumSubNodes()-1); + for(int i = 0; i < pLineParent->GetNumSubNodes(); i++){ + if(i < nLineOffset) + lines[i] = pLineParent->GetSubNode(i); + else if(i > nLineOffset) + lines[i-1] = pLineParent->GetSubNode(i); + } + pLineParent->SetSubNodes(lines); + //Rebuild graph + anchor = NULL; + position = NULL; + BuildGraph(); + AnnotateSelection(); + //Set caret position + if(!SetCaretPosition(PosAfterDelete, true)) + SetCaretPosition(SmCaretPos(pLine, 0), true); + //Finish editing + EndEdit(); + + //TODO: If we're in an empty (sub/super/*) script + /*}else if(pLineParent->GetType() == NSUBSUP && + nLineOffset != 0 && + pLine->GetType() == NEXPRESSION && + pLine->GetNumSubNodes() == 0){ + //There's a (sub/super/*) script we can delete + //Consider selecting the entire script if GetNumSubNodes() != 0 or pLine->GetType() != NEXPRESSION + //TODO: Handle case where we delete a limit + */ + + //Else move select, and delete if not complex + }else{ + this->Move(pDev, MoveLeft, false); + if(!this->HasComplexSelection()) + Delete(); + } +} + void SmCursor::Delete(){ //Return if we don't have a selection to delete if(!HasSelection()) @@ -214,13 +284,7 @@ void SmCursor::Delete(){ //Position after delete SmCaretPos PosAfterDelete; - SmNodeList* pLineList; - if(IsLineCompositionNode(pLine)) - pLineList = LineToList((SmStructureNode*)pLine); - else { - pLineList = new SmNodeList(); - pLineList->push_back(pLine); - } + SmNodeList* pLineList = NodeToList(pLine); //Take the selected nodes and delete them... SmNodeList::iterator patchIt = TakeSelectedNodesFromList(pLineList); @@ -256,13 +320,7 @@ void SmCursor::InsertNodes(SmNodeList* pNewNodes){ j_assert(nParentIndex != -1, "pLine must be a subnode of pLineParent!"); //Convert line to list - SmNodeList* pLineList; - if(IsLineCompositionNode(pLine)) - pLineList = LineToList((SmStructureNode*)pLine); - else { - pLineList = new SmNodeList(); - pLineList->push_front(pLine); - } + SmNodeList* pLineList = NodeToList(pLine); //Find iterator for place to insert nodes SmNodeList::iterator it = FindPositionInLineList(pLineList, pos); @@ -465,13 +523,7 @@ void SmCursor::InsertSubSup(SmSubSup eSubSup) { BeginEdit(); //Convert line to list - SmNodeList* pLineList; - if(IsLineCompositionNode(pLine)) - pLineList = LineToList((SmStructureNode*)pLine); - else { - pLineList = new SmNodeList(); - pLineList->push_front(pLine); - } + SmNodeList* pLineList = NodeToList(pLine); //Take the selection, and/or find iterator for current position SmNodeList* pSelectedNodesList = new SmNodeList(); @@ -518,14 +570,7 @@ void SmCursor::InsertSubSup(SmSubSup eSubSup) { //Convert existing, if any, sub-/superscript line to list SmNode *pScriptLine = pSubSup->GetSubSup(eSubSup); - SmNodeList* pScriptLineList; - if(pScriptLine && IsLineCompositionNode(pScriptLine)) - pScriptLineList = LineToList((SmStructureNode*)pScriptLine); - else{ - pScriptLineList = new SmNodeList(); - if(pScriptLine) - pScriptLineList->push_front(pScriptLine); - } + SmNodeList* pScriptLineList = NodeToList(pScriptLine); //Add selection to pScriptLineList unsigned int nOldSize = pScriptLineList->size(); @@ -601,13 +646,7 @@ bool SmCursor::InsertLimit(SmSubSup eSubSup, bool bMoveCaret) { //If it's already there... let's move the caret } else if(bMoveCaret){ pLine = pSubSup->GetSubSup(eSubSup); - SmNodeList* pLineList; - if(IsLineCompositionNode(pLine)) - pLineList = LineToList((SmStructureNode*)pLine); - else { - pLineList = new SmNodeList(); - pLineList->push_front(pLine); - } + SmNodeList* pLineList = NodeToList(pLine); if(pLineList->size() > 0) PosAfterLimit = SmCaretPos::GetPosAfter(pLineList->back()); pLine = SmNodeListParser().Parse(pLineList); @@ -649,13 +688,7 @@ void SmCursor::InsertBrackets(SmBracketType eBracketType) { j_assert( nParentIndex != -1, "pLine must be a subnode of pLineParent!"); //Convert line to list - SmNodeList *pLineList; - if(IsLineCompositionNode(pLine)) - pLineList = LineToList((SmStructureNode*)pLine); - else { - pLineList = new SmNodeList(); - pLineList->push_front(pLine); - } + SmNodeList *pLineList = NodeToList(pLine); //Take the selection, and/or find iterator for current position SmNodeList *pSelectedNodesList = new SmNodeList(); @@ -816,13 +849,7 @@ bool SmCursor::InsertRow() { BeginEdit(); //Convert line to list - SmNodeList *pLineList; - if(IsLineCompositionNode(pLine)) - pLineList = LineToList((SmStructureNode*)pLine); - else { - pLineList = new SmNodeList(); - pLineList->push_front(pLine); - } + SmNodeList *pLineList = NodeToList(pLine); //Find position in line SmNodeList::iterator it; @@ -849,20 +876,21 @@ bool SmCursor::InsertRow() { //Parse new line SmNode *pNewLine = SmNodeListParser().Parse(pNewLineList); delete pNewLineList; - //Get position before we wrap in SmLineNode - //NOTE: This should be done after, if SmLineNode ever becomes a line composition node - PosAfterInsert = SmCaretPos(pNewLine, 0); //Wrap pNewLine in SmLineNode if needed if(pLineParent->GetType() == NLINE) { SmLineNode *pNewLineNode = new SmLineNode(SmToken(TNEWLINE, '\0', "newline")); pNewLineNode->SetSubNodes(pNewLine, NULL); pNewLine = pNewLineNode; } + //Get position + PosAfterInsert = SmCaretPos(pNewLine, 0); //Move other nodes if needed for( int i = pTable->GetNumSubNodes(); i > nTableIndex + 1; i--) pTable->SetSubNode(i, pTable->GetSubNode(i-1)); + //Insert new line pTable->SetSubNode(nTableIndex + 1, pNewLine); + //Check if we need to change token type: if(pTable->GetNumSubNodes() > 2 && pTable->GetToken().eType == TBINOM) { SmToken tok = pTable->GetToken(); @@ -919,13 +947,7 @@ void SmCursor::InsertFraction() { BeginEdit(); //Convert line to list - SmNodeList* pLineList; - if(IsLineCompositionNode(pLine)) - pLineList = LineToList((SmStructureNode*)pLine); - else { - pLineList = new SmNodeList(); - pLineList->push_front(pLine); - } + SmNodeList* pLineList = NodeToList(pLine); //Take the selection, and/or find iterator for current position SmNodeList* pSelectedNodesList = new SmNodeList(); @@ -957,7 +979,6 @@ void SmCursor::InsertFraction() { FinishEdit(pLineList, pLineParent, nParentIndex, SmCaretPos(pDenom, 1)); } - void SmCursor::InsertText(XubString aString){ BeginEdit(); @@ -1142,13 +1163,7 @@ void SmCursor::InsertCommandText(XubString aCommandText) { pSubExpr->Prepare(pDocShell->GetFormat(), *pDocShell); //Convert subtree to list - SmNodeList* pLineList; - if(IsLineCompositionNode(pSubExpr)) - pLineList = LineToList((SmStructureNode*)pSubExpr); - else { - pLineList = new SmNodeList(); - pLineList->push_front(pSubExpr); - } + SmNodeList* pLineList = NodeToList(pSubExpr); BeginEdit(); @@ -1219,7 +1234,6 @@ SmNodeList* SmCursor::CloneList(SmNodeList* pList){ return pClones; } - void SmCursor::SetClipboard(SmNodeList* pList){ if(pClipboard){ //Delete all nodes on the clipboard diff --git a/starmath/source/view.cxx b/starmath/source/view.cxx index bfe0bc7b2cb9..aec233e52650 100644 --- a/starmath/source/view.cxx +++ b/starmath/source/view.cxx @@ -451,7 +451,6 @@ void SmGraphicWindow::KeyInput(const KeyEvent& rKEvt) #endif /* DEBUG_ENABLE_DUMPASDOT */ }break; case KEY_DELETE: - case KEY_BACKSPACE: { if(!rCursor.HasSelection()){ rCursor.Move(this, nCode == KEY_DELETE ? MoveRight : MoveLeft, false); @@ -459,6 +458,10 @@ void SmGraphicWindow::KeyInput(const KeyEvent& rKEvt) } rCursor.Delete(); }break; + case KEY_BACKSPACE: + { + rCursor.DeletePrev(this); + }break; case KEY_ADD: rCursor.InsertElement(PlusElement); break; |