Move cursor to the right of brace when the closing brace is typed.
This commit is contained in:
committed by
Noel Power
parent
1b6d2c7f46
commit
20dde3737f
@@ -50,7 +50,7 @@ struct SmCaretPos{
|
|||||||
//TODO: Consider forgetting about the todo above... As it's really unpleasent.
|
//TODO: Consider forgetting about the todo above... As it's really unpleasent.
|
||||||
int Index;
|
int Index;
|
||||||
/** True, if this is a valid caret position */
|
/** True, if this is a valid caret position */
|
||||||
bool IsValid() { return pSelectedNode != NULL; }
|
bool IsValid() const { return pSelectedNode != NULL; }
|
||||||
bool operator!=(SmCaretPos pos) const {
|
bool operator!=(SmCaretPos pos) const {
|
||||||
return pos.pSelectedNode != pSelectedNode || Index != pos.Index;
|
return pos.pSelectedNode != pSelectedNode || Index != pos.Index;
|
||||||
}
|
}
|
||||||
|
@@ -118,7 +118,7 @@ public:
|
|||||||
SmCaretPos GetAnchor(){ return anchor->CaretPos; }
|
SmCaretPos GetAnchor(){ return anchor->CaretPos; }
|
||||||
|
|
||||||
/** Get position */
|
/** Get position */
|
||||||
SmCaretPos GetPosition() { return position->CaretPos; }
|
SmCaretPos GetPosition() const { return position->CaretPos; }
|
||||||
|
|
||||||
/** True, if the cursor has a selection */
|
/** True, if the cursor has a selection */
|
||||||
bool HasSelection() { return anchor != position; }
|
bool HasSelection() { return anchor != position; }
|
||||||
@@ -236,6 +236,9 @@ public:
|
|||||||
/** Draw the caret */
|
/** Draw the caret */
|
||||||
void Draw(OutputDevice& pDev, Point Offset, bool isCaretVisible);
|
void Draw(OutputDevice& pDev, Point Offset, bool isCaretVisible);
|
||||||
|
|
||||||
|
bool IsAtTailOfBracket(SmBracketType eBracketType, SmBraceNode** ppBraceNode = NULL) const;
|
||||||
|
void MoveAfterBracket(SmBraceNode* pBraceNode, bool bMoveAnchor = true);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class SmDocShell;
|
friend class SmDocShell;
|
||||||
|
|
||||||
|
@@ -119,13 +119,13 @@ public:
|
|||||||
virtual SmNode * GetSubNode(sal_uInt16 nIndex);
|
virtual SmNode * GetSubNode(sal_uInt16 nIndex);
|
||||||
const SmNode * GetSubNode(sal_uInt16 nIndex) const
|
const SmNode * GetSubNode(sal_uInt16 nIndex) const
|
||||||
{
|
{
|
||||||
return ((SmNode *) this)->GetSubNode(nIndex);
|
return const_cast<SmNode *>(this)->GetSubNode(nIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual SmNode * GetLeftMost();
|
virtual SmNode * GetLeftMost();
|
||||||
const SmNode * GetLeftMost() const
|
const SmNode * GetLeftMost() const
|
||||||
{
|
{
|
||||||
return ((SmNode *) this)->GetLeftMost();
|
return const_cast<SmNode *>(this)->GetLeftMost();
|
||||||
}
|
}
|
||||||
|
|
||||||
sal_uInt16 & Flags() { return nFlags; }
|
sal_uInt16 & Flags() { return nFlags; }
|
||||||
@@ -149,6 +149,8 @@ public:
|
|||||||
virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell);
|
virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell);
|
||||||
virtual void PrepareAttributes();
|
virtual void PrepareAttributes();
|
||||||
|
|
||||||
|
sal_uInt16 FindIndex() const;
|
||||||
|
|
||||||
#if OSL_DEBUG_LEVEL
|
#if OSL_DEBUG_LEVEL
|
||||||
void ToggleDebug() const;
|
void ToggleDebug() const;
|
||||||
#endif
|
#endif
|
||||||
@@ -206,6 +208,7 @@ public:
|
|||||||
|
|
||||||
/** Get the parent node of this node */
|
/** Get the parent node of this node */
|
||||||
SmStructureNode* GetParent(){ return aParentNode; }
|
SmStructureNode* GetParent(){ return aParentNode; }
|
||||||
|
const SmStructureNode* GetParent() const { return aParentNode; }
|
||||||
/** Set the parent node */
|
/** Set the parent node */
|
||||||
void SetParent(SmStructureNode* parent){
|
void SetParent(SmStructureNode* parent){
|
||||||
aParentNode = parent;
|
aParentNode = parent;
|
||||||
|
@@ -1474,6 +1474,95 @@ void SmCursor::RequestRepaint(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SmCursor::IsAtTailOfBracket(SmBracketType eBracketType, SmBraceNode** ppBraceNode) const {
|
||||||
|
const SmCaretPos pos = GetPosition();
|
||||||
|
if (!pos.IsValid()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SmNode* pNode = pos.pSelectedNode;
|
||||||
|
|
||||||
|
if (pNode->GetType() == NTEXT) {
|
||||||
|
SmTextNode* pTextNode = static_cast<SmTextNode*>(pNode);
|
||||||
|
if (pos.Index < pTextNode->GetText().Len()) {
|
||||||
|
// The cursor is on a text node and at the middle of it.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (pos.Index < 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
SmStructureNode* pParentNode = pNode->GetParent();
|
||||||
|
if (!pParentNode) {
|
||||||
|
// There's no brace body node in the ancestors.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sal_uInt16 index = pNode->FindIndex();
|
||||||
|
if (index + 1 != pParentNode->GetNumSubNodes()) {
|
||||||
|
// The cursor is not at the tail at one of ancestor nodes.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pNode = pParentNode;
|
||||||
|
if (pNode->GetType() == NBRACEBODY) {
|
||||||
|
// Found the brace body node.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SmStructureNode* pBraceNodeTmp = pNode->GetParent();
|
||||||
|
if (!pBraceNodeTmp || pBraceNodeTmp->GetType() != NBRACE) {
|
||||||
|
// Brace node is invalid.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SmBraceNode* pBraceNode = static_cast<SmBraceNode*>(pBraceNodeTmp);
|
||||||
|
SmMathSymbolNode* pClosingNode = pBraceNode->ClosingBrace();
|
||||||
|
if (!pClosingNode) {
|
||||||
|
// Couldn't get closing symbol node.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the closing brace matches eBracketType.
|
||||||
|
SmTokenType eClosingTokenType = pClosingNode->GetToken().eType;
|
||||||
|
switch (eBracketType) {
|
||||||
|
case NoneBrackets: if (eClosingTokenType != TNONE) { return false; } break;
|
||||||
|
case RoundBrackets: if (eClosingTokenType != TRPARENT) { return false; } break;
|
||||||
|
case SquareBrackets: if (eClosingTokenType != TRBRACKET) { return false; } break;
|
||||||
|
case DoubleSquareBrackets: if (eClosingTokenType != TRDBRACKET) { return false; } break;
|
||||||
|
case LineBrackets: if (eClosingTokenType != TRLINE) { return false; } break;
|
||||||
|
case DoubleLineBrackets: if (eClosingTokenType != TRDLINE) { return false; } break;
|
||||||
|
case CurlyBrackets: if (eClosingTokenType != TRBRACE) { return false; } break;
|
||||||
|
case AngleBrackets: if (eClosingTokenType != TRANGLE) { return false; } break;
|
||||||
|
case CeilBrackets: if (eClosingTokenType != TRCEIL) { return false; } break;
|
||||||
|
case FloorBrackets: if (eClosingTokenType != TRFLOOR) { return false; } break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ppBraceNode) {
|
||||||
|
*ppBraceNode = static_cast<SmBraceNode*>(pBraceNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmCursor::MoveAfterBracket(SmBraceNode* pBraceNode, bool bMoveAnchor)
|
||||||
|
{
|
||||||
|
position->CaretPos.pSelectedNode = pBraceNode;
|
||||||
|
position->CaretPos.Index = 1;
|
||||||
|
if (bMoveAnchor) {
|
||||||
|
anchor->CaretPos.pSelectedNode = pBraceNode;
|
||||||
|
anchor->CaretPos.Index = 1;
|
||||||
|
}
|
||||||
|
RequestRepaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////// SmNodeListParser ///////////////////////////////////////
|
/////////////////////////////////////// SmNodeListParser ///////////////////////////////////////
|
||||||
|
|
||||||
SmNode* SmNodeListParser::Parse(SmNodeList* list, bool bDeleteErrorNodes){
|
SmNode* SmNodeListParser::Parse(SmNodeList* list, bool bDeleteErrorNodes){
|
||||||
|
@@ -381,6 +381,21 @@ void SmNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell)
|
|||||||
pNode->Prepare(rFormat, rDocShell);
|
pNode->Prepare(rFormat, rDocShell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sal_uInt16 SmNode::FindIndex() const
|
||||||
|
{
|
||||||
|
const SmStructureNode* pParent = GetParent();
|
||||||
|
if (!pParent) { return 0; }
|
||||||
|
|
||||||
|
for (sal_uInt16 i = 0; i < pParent->GetNumSubNodes(); ++i) {
|
||||||
|
if (pParent->GetSubNode(i) == this) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG_ASSERT(false, "Connection between parent and child is inconsistent.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if OSL_DEBUG_LEVEL > 1
|
#if OSL_DEBUG_LEVEL > 1
|
||||||
void SmNode::ToggleDebug() const
|
void SmNode::ToggleDebug() const
|
||||||
|
@@ -504,6 +504,8 @@ void SmGraphicWindow::KeyInput(const KeyEvent& rKEvt)
|
|||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
sal_Unicode code = rKEvt.GetCharCode();
|
sal_Unicode code = rKEvt.GetCharCode();
|
||||||
|
SmBraceNode* pBraceNode = NULL;
|
||||||
|
|
||||||
if(code == ' ') {
|
if(code == ' ') {
|
||||||
rCursor.InsertElement(BlankElement);
|
rCursor.InsertElement(BlankElement);
|
||||||
}else if(code == 'c' && rKEvt.GetKeyCode().IsMod1()) {
|
}else if(code == 'c' && rKEvt.GetKeyCode().IsMod1()) {
|
||||||
@@ -524,6 +526,12 @@ void SmGraphicWindow::KeyInput(const KeyEvent& rKEvt)
|
|||||||
rCursor.InsertElement(FactorialElement);
|
rCursor.InsertElement(FactorialElement);
|
||||||
}else if(code == '%') {
|
}else if(code == '%') {
|
||||||
rCursor.InsertElement(PercentElement);
|
rCursor.InsertElement(PercentElement);
|
||||||
|
}else if(code == ')' && rCursor.IsAtTailOfBracket(RoundBrackets, &pBraceNode)) {
|
||||||
|
rCursor.MoveAfterBracket(pBraceNode);
|
||||||
|
}else if(code == ']' && rCursor.IsAtTailOfBracket(SquareBrackets, &pBraceNode)) {
|
||||||
|
rCursor.MoveAfterBracket(pBraceNode);
|
||||||
|
}else if(code == '}' && rCursor.IsAtTailOfBracket(CurlyBrackets, &pBraceNode)) {
|
||||||
|
rCursor.MoveAfterBracket(pBraceNode);
|
||||||
}else{
|
}else{
|
||||||
if(code != 0){
|
if(code != 0){
|
||||||
rCursor.InsertText(code);
|
rCursor.InsertText(code);
|
||||||
|
Reference in New Issue
Block a user