Enable line deletion in starmath
* Implemented SmCursor::DeletePrev, for deletion of lines * Fixed nasty bug in SmCursor::InsertRow * Code cleanup in cursor.cxx
This commit is contained in:
parent
aede297486
commit
592777e2b2
3 changed files with 115 additions and 70 deletions
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue