diff options
author | Oliver Bolte <obo@openoffice.org> | 2009-02-11 15:19:01 +0000 |
---|---|---|
committer | Oliver Bolte <obo@openoffice.org> | 2009-02-11 15:19:01 +0000 |
commit | 6fed8a270237f81690addb2f5853e372535d66a9 (patch) | |
tree | 7fc19d7aed581096ed202f831b17e6465745166a | |
parent | e6e8722c10e925c05c7eeea073a717f20c0ebdb2 (diff) |
CWS-TOOLING: integrate CWS tbe35
2008-12-15 15:10:58 +0100 tbe r265503 : CWS-TOOLING: rebase CWS tbe35 to trunk@264807 (milestone: DEV300:m37)
2008-12-11 17:12:58 +0100 tbe r265335 : #i90682# formatting failed when first character is '-', '+' or '='
2008-12-10 18:59:13 +0100 nn r265228 : #i96930# invalidate sort toolbar slots in SelectionChanged
2008-12-09 15:58:45 +0100 nn r265111 : #i77853# InitDocShell: SetLayoutRTL
2008-12-03 15:54:50 +0100 tbe r264795 : #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
2008-11-14 16:13:21 +0100 tbe r263682 : #i95212# [Collaboration] Bad handling of row insertion in shared spreadsheet
-rw-r--r-- | sc/inc/chgtrack.hxx | 7 | ||||
-rw-r--r-- | sc/source/core/tool/chgtrack.cxx | 83 | ||||
-rw-r--r-- | sc/source/ui/app/inputhdl.cxx | 3 | ||||
-rw-r--r-- | sc/source/ui/app/transobj.cxx | 1 | ||||
-rw-r--r-- | sc/source/ui/docshell/docsh3.cxx | 22 | ||||
-rw-r--r-- | sc/source/ui/inc/viewfunc.hxx | 2 | ||||
-rw-r--r-- | sc/source/ui/view/cellsh3.cxx | 10 | ||||
-rw-r--r-- | sc/source/ui/view/tabview3.cxx | 2 | ||||
-rw-r--r-- | sc/source/ui/view/viewfunc.cxx | 46 |
9 files changed, 146 insertions, 30 deletions
diff --git a/sc/inc/chgtrack.hxx b/sc/inc/chgtrack.hxx index bf2c624cbcb4..ba15daa3c4d9 100644 --- a/sc/inc/chgtrack.hxx +++ b/sc/inc/chgtrack.hxx @@ -1035,6 +1035,7 @@ enum ScChangeTrackMergeState SC_CTMS_NONE, SC_CTMS_PREPARE, SC_CTMS_OWN, + SC_CTMS_UNDO, SC_CTMS_OTHER }; @@ -1343,14 +1344,14 @@ public: pLastCutMove; } - SC_DLLPUBLIC void Undo( ULONG nStartAction, ULONG nEndAction ); + SC_DLLPUBLIC void Undo( ULONG nStartAction, ULONG nEndAction, bool bMerge = false ); // fuer MergeDocument, Referenzen anpassen, //! darf nur in einem temporaer geoeffneten //! Dokument verwendet werden, der Track //! ist danach verhunzt - void MergePrepare( ScChangeAction* pFirstMerge ); - void MergeOwn( ScChangeAction* pAct, ULONG nFirstMerge ); + void MergePrepare( ScChangeAction* pFirstMerge, bool bShared = false ); + void MergeOwn( ScChangeAction* pAct, ULONG nFirstMerge, bool bShared = false ); static BOOL MergeIgnore( const ScChangeAction&, ULONG nFirstMerge ); // Abhaengige in Table einfuegen. diff --git a/sc/source/core/tool/chgtrack.cxx b/sc/source/core/tool/chgtrack.cxx index 17ea1a6cbb31..ac0dd1cbe9ef 100644 --- a/sc/source/core/tool/chgtrack.cxx +++ b/sc/source/core/tool/chgtrack.cxx @@ -4042,8 +4042,14 @@ void ScChangeTrack::Remove( ScChangeAction* pRemove ) } -void ScChangeTrack::Undo( ULONG nStartAction, ULONG nEndAction ) +void ScChangeTrack::Undo( ULONG nStartAction, ULONG nEndAction, bool bMerge ) { + // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong + if ( bMerge ) + { + SetMergeState( SC_CTMS_UNDO ); + } + if ( nStartAction == 0 ) ++nStartAction; if ( nEndAction > nActionMax ) @@ -4119,6 +4125,12 @@ void ScChangeTrack::Undo( ULONG nStartAction, ULONG nEndAction ) } EndBlockModify( nEndAction ); } + + // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong + if ( bMerge ) + { + SetMergeState( SC_CTMS_OTHER ); + } } @@ -4135,7 +4147,7 @@ BOOL ScChangeTrack::MergeIgnore( const ScChangeAction& rAction, ULONG nFirstMerg } -void ScChangeTrack::MergePrepare( ScChangeAction* pFirstMerge ) +void ScChangeTrack::MergePrepare( ScChangeAction* pFirstMerge, bool bShared ) { SetMergeState( SC_CTMS_PREPARE ); ULONG nFirstMerge = pFirstMerge->GetActionNumber(); @@ -4145,7 +4157,8 @@ void ScChangeTrack::MergePrepare( ScChangeAction* pFirstMerge ) SetLastMerge( pAct->GetActionNumber() ); while ( pAct ) { // rueckwaerts, Deletes in richtiger Reihenfolge - if ( !ScChangeTrack::MergeIgnore( *pAct, nFirstMerge ) ) + // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong + if ( bShared || !ScChangeTrack::MergeIgnore( *pAct, nFirstMerge ) ) { if ( pAct->IsDeleteType() ) { @@ -4167,9 +4180,10 @@ void ScChangeTrack::MergePrepare( ScChangeAction* pFirstMerge ) } -void ScChangeTrack::MergeOwn( ScChangeAction* pAct, ULONG nFirstMerge ) +void ScChangeTrack::MergeOwn( ScChangeAction* pAct, ULONG nFirstMerge, bool bShared ) { - if ( !ScChangeTrack::MergeIgnore( *pAct, nFirstMerge ) ) + // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong + if ( bShared || !ScChangeTrack::MergeIgnore( *pAct, nFirstMerge ) ) { SetMergeState( SC_CTMS_OWN ); if ( pAct->IsDeleteType() ) @@ -4533,6 +4547,15 @@ void ScChangeTrack::UpdateReference( ScChangeAction** ppFirstAction, BOOL bUpdate = TRUE; if ( aDelRange.In( p->GetBigRange() ) ) { + // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong + if ( GetMergeState() == SC_CTMS_UNDO && !p->IsDeletedIn( pAct ) && pAct->IsDeleteType() && + ( p->GetType() == SC_CAT_CONTENT || + p->GetType() == SC_CAT_DELETE_ROWS || p->GetType() == SC_CAT_DELETE_COLS || + p->GetType() == SC_CAT_INSERT_ROWS || p->GetType() == SC_CAT_INSERT_COLS ) ) + { + p->SetDeletedIn( pAct ); + } + if ( p->IsDeletedInDelType( eActType ) ) { if ( p->IsDeletedIn( pActDel ) ) @@ -4687,7 +4710,10 @@ void ScChangeTrack::UpdateReference( ScChangeAction** ppFirstAction, for ( ScChangeAction* p = *ppFirstAction; p; p = p->GetNext() ) { if ( !p->IsDeletedIn( pAct ) && pAct->IsInsertType() && - p->GetType() == SC_CAT_CONTENT && + // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong + ( p->GetType() == SC_CAT_CONTENT || + p->GetType() == SC_CAT_DELETE_ROWS || p->GetType() == SC_CAT_DELETE_COLS || + p->GetType() == SC_CAT_INSERT_ROWS || p->GetType() == SC_CAT_INSERT_COLS ) && pAct->GetBigRange().Intersects( p->GetBigRange() ) ) { p->SetDeletedIn( pAct ); @@ -4698,8 +4724,12 @@ void ScChangeTrack::UpdateReference( ScChangeAction** ppFirstAction, { if ( p == pAct ) continue; // for - if ( !p->IsDeletedIn( pAct ) ) + if ( !p->IsDeletedIn( pAct ) + // #i95212# [Collaboration] Bad handling of row insertion in shared spreadsheet + && p->GetActionNumber() <= pAct->GetActionNumber() ) + { p->UpdateReference( this, eMode, aRange, nDx, nDy, nDz ); + } } } break; @@ -4709,8 +4739,12 @@ void ScChangeTrack::UpdateReference( ScChangeAction** ppFirstAction, { if ( p == pAct ) continue; // for - if ( !p->IsDeletedIn( pAct ) ) + if ( !p->IsDeletedIn( pAct ) + // #i95212# [Collaboration] Bad handling of row insertion in shared spreadsheet + && p->GetActionNumber() <= pAct->GetActionNumber() ) + { p->UpdateReference( this, eMode, aRange, nDx, nDy, nDz ); + } } // in Insert-Undo "Delete" rueckgaengig const ScChangeActionLinkEntry* pLink = pAct->GetFirstDependentEntry(); @@ -4726,7 +4760,10 @@ void ScChangeTrack::UpdateReference( ScChangeAction** ppFirstAction, for ( ScChangeAction* p = *ppFirstAction; p; p = p->GetNext() ) { if ( p->IsDeletedIn( pAct ) && pAct->IsInsertType() && - p->GetType() == SC_CAT_CONTENT && + // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong + ( p->GetType() == SC_CAT_CONTENT || + p->GetType() == SC_CAT_DELETE_ROWS || p->GetType() == SC_CAT_DELETE_COLS || + p->GetType() == SC_CAT_INSERT_ROWS || p->GetType() == SC_CAT_INSERT_COLS ) && pAct->GetBigRange().Intersects( p->GetBigRange() ) ) { p->RemoveDeletedIn( pAct ); @@ -4734,6 +4771,34 @@ void ScChangeTrack::UpdateReference( ScChangeAction** ppFirstAction, } } break; + // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong + case SC_CTMS_UNDO : + { + for ( ScChangeAction* p = *ppFirstAction; p; p = p->GetNext() ) + { + if ( !p->IsDeletedIn( pAct ) && pAct->IsInsertType() && + ( p->GetType() == SC_CAT_CONTENT || + p->GetType() == SC_CAT_DELETE_ROWS || p->GetType() == SC_CAT_DELETE_COLS || + p->GetType() == SC_CAT_INSERT_ROWS || p->GetType() == SC_CAT_INSERT_COLS ) && + pAct->GetBigRange().Intersects( p->GetBigRange() ) ) + { + p->SetDeletedIn( pAct ); + } + } + + for ( ScChangeAction* p = *ppFirstAction; p; p = p->GetNext() ) + { + if ( p == pAct ) + { + continue; + } + if ( !p->IsDeletedIn( pAct ) && p->GetActionNumber() <= pAct->GetActionNumber() ) + { + p->UpdateReference( this, eMode, aRange, nDx, nDy, nDz ); + } + } + } + break; } } } diff --git a/sc/source/ui/app/inputhdl.cxx b/sc/source/ui/app/inputhdl.cxx index 86b658dc039d..c1f4a15a514b 100644 --- a/sc/source/ui/app/inputhdl.cxx +++ b/sc/source/ui/app/inputhdl.cxx @@ -2532,9 +2532,6 @@ void ScInputHandler::EnterHandler( BYTE nBlockMode ) // Formeln immer als Formeln erkennen (#38309#) // (der Test vorher ist trotzdem noetig wegen Zell-Attributen) - - if ( bAttrib && bFormulaMode ) - bAttrib = FALSE; } if (bMatrix) diff --git a/sc/source/ui/app/transobj.cxx b/sc/source/ui/app/transobj.cxx index 642612123a72..9e8d280403a9 100644 --- a/sc/source/ui/app/transobj.cxx +++ b/sc/source/ui/app/transobj.cxx @@ -606,6 +606,7 @@ void ScTransferObj::InitDocShell() SCCOL nCol; SCROW nRow; SCTAB nSrcTab = aBlock.aStart.Tab(); + pDestDoc->SetLayoutRTL(0, pDoc->IsLayoutRTL(nSrcTab)); for (nCol=nStartX; nCol<=nEndX; nCol++) if ( pDoc->GetColFlags( nCol, nSrcTab ) & CR_HIDDEN ) pDestDoc->ShowCol( nCol, 0, FALSE ); diff --git a/sc/source/ui/docshell/docsh3.cxx b/sc/source/ui/docshell/docsh3.cxx index 786e99921b63..58c72458ba0a 100644 --- a/sc/source/ui/docshell/docsh3.cxx +++ b/sc/source/ui/docshell/docsh3.cxx @@ -769,15 +769,16 @@ inline BOOL lcl_Equal( const ScChangeAction* pA, const ScChangeAction* pB, BOOL // State nicht vergleichen, falls eine alte Aenderung akzeptiert wurde } -bool lcl_FindAction( ScDocument* pDoc, const ScChangeAction* pAction, ScDocument* pSearchDoc, const ScChangeAction* pFirstSearchAction, BOOL bIgnore100Sec ) +bool lcl_FindAction( ScDocument* pDoc, const ScChangeAction* pAction, ScDocument* pSearchDoc, const ScChangeAction* pFirstSearchAction, const ScChangeAction* pLastSearchAction, BOOL bIgnore100Sec ) { - if ( !pDoc || !pAction || !pSearchDoc || !pFirstSearchAction ) + if ( !pDoc || !pAction || !pSearchDoc || !pFirstSearchAction || !pLastSearchAction ) { return false; } + ULONG nLastSearchAction = pLastSearchAction->GetActionNumber(); const ScChangeAction* pA = pFirstSearchAction; - while ( pA ) + while ( pA && pA->GetActionNumber() <= nLastSearchAction ) { if ( pAction->GetType() == pA->GetType() && pAction->GetUser() == pA->GetUser() && @@ -850,6 +851,10 @@ void ScDocShell::MergeDocument( ScDocument& rOtherDoc, bool bShared, bool bCheck const ScChangeAction* pFirstMergeAction = pSourceAction; const ScChangeAction* pFirstSearchAction = pThisAction; + + // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong + const ScChangeAction* pLastSearchAction = pThisTrack->GetLast(); + // MergeChangeData aus den folgenden Aktionen erzeugen ULONG nNewActionCount = 0; const ScChangeAction* pCount = pSourceAction; @@ -869,7 +874,7 @@ void ScDocShell::MergeDocument( ScDocument& rOtherDoc, bool bShared, bool bCheck ULONG nLastMergeAction = pSourceTrack->GetLast()->GetActionNumber(); // UpdateReference-Undo, gueltige Referenzen fuer den letzten gemeinsamen Zustand - pSourceTrack->MergePrepare( (ScChangeAction*) pFirstMergeAction ); + pSourceTrack->MergePrepare( (ScChangeAction*) pFirstMergeAction, bShared ); // MergeChangeData an alle noch folgenden Aktionen in diesem Dokument anpassen // -> Referenzen gueltig fuer dieses Dokument @@ -929,7 +934,7 @@ void ScDocShell::MergeDocument( ScDocument& rOtherDoc, bool bShared, bool bCheck bool bMergeAction = false; if ( bShared ) { - if ( !bCheckDuplicates || !lcl_FindAction( &rOtherDoc, pSourceAction, &aDocument, pFirstSearchAction, bIgnore100Sec ) ) + if ( !bCheckDuplicates || !lcl_FindAction( &rOtherDoc, pSourceAction, &aDocument, pFirstSearchAction, pLastSearchAction, bIgnore100Sec ) ) { bMergeAction = true; } @@ -1119,7 +1124,7 @@ void ScDocShell::MergeDocument( ScDocument& rOtherDoc, bool bShared, bool bCheck } // Referenzen anpassen - pSourceTrack->MergeOwn( (ScChangeAction*) pSourceAction, nFirstNewNumber ); + pSourceTrack->MergeOwn( (ScChangeAction*) pSourceAction, nFirstNewNumber, bShared ); // merge action state if ( bShared && !pSourceAction->IsRejected() ) @@ -1159,6 +1164,7 @@ void ScDocShell::MergeDocument( ScDocument& rOtherDoc, bool bShared, bool bCheck } pSourceAction = pSourceAction->GetNext(); } + rMarkData = aOldMarkData; pThisTrack->SetUser(aOldUser); pThisTrack->SetUseFixDateTime( FALSE ); @@ -1284,7 +1290,9 @@ bool ScDocShell::MergeSharedDocument( ScDocShell* pSharedDocShell ) pThisTrack->Reject( pAction ); pAction = pAction->GetPrev(); } - pThisTrack->Undo( nStartShared, pThisTrack->GetActionMax() ); + + // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong + pThisTrack->Undo( nStartShared, pThisTrack->GetActionMax(), true ); // merge shared changes into own document ScChangeActionMergeMap aSharedMergeMap; diff --git a/sc/source/ui/inc/viewfunc.hxx b/sc/source/ui/inc/viewfunc.hxx index a0064570f6a0..b3a4af0b3aac 100644 --- a/sc/source/ui/inc/viewfunc.hxx +++ b/sc/source/ui/inc/viewfunc.hxx @@ -98,7 +98,7 @@ public: String GetAutoSumFormula( const ScRangeList& rRangeList, bool bSubTotal ); void EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const String& rString, - BOOL bRecord = TRUE ); + BOOL bRecord = TRUE, const EditTextObject* pData = NULL ); void EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const double& rValue ); void EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const EditTextObject* pData, BOOL bRecord = TRUE, BOOL bTestSimple = FALSE ); diff --git a/sc/source/ui/view/cellsh3.cxx b/sc/source/ui/view/cellsh3.cxx index b05b86608a4f..a569e04ea238 100644 --- a/sc/source/ui/view/cellsh3.cxx +++ b/sc/source/ui/view/cellsh3.cxx @@ -241,17 +241,25 @@ void ScCellShell::Execute( SfxRequest& rReq ) Get( FID_INPUTLINE_STATUS ); ScAddress aCursorPos = pStatusItem->GetPos(); + String aString = pStatusItem->GetString(); const EditTextObject* pData = pStatusItem->GetEditData(); if (pData) { if (nSlot == FID_INPUTLINE_BLOCK) + { pTabViewShell->EnterBlock( String(), pData ); + } + else if ( aString.Len() > 0 && ( aString.GetChar(0) == '=' || aString.GetChar(0) == '+' || aString.GetChar(0) == '-' ) ) + { + pTabViewShell->EnterData( aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab(), aString, TRUE, pData ); + } else + { pTabViewShell->EnterData( aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab(), pData ); + } } else { - String aString = pStatusItem->GetString(); if (nSlot == FID_INPUTLINE_ENTER) { if ( diff --git a/sc/source/ui/view/tabview3.cxx b/sc/source/ui/view/tabview3.cxx index 46552b7d34d7..e8a83f89a406 100644 --- a/sc/source/ui/view/tabview3.cxx +++ b/sc/source/ui/view/tabview3.cxx @@ -447,6 +447,8 @@ void ScTabView::SelectionChanged() rBindings.Invalidate( FID_VALIDATION ); rBindings.Invalidate( SID_EXTERNAL_SOURCE ); rBindings.Invalidate( SID_TEXT_TO_COLUMNS ); + rBindings.Invalidate( SID_SORT_ASCENDING ); + rBindings.Invalidate( SID_SORT_DESCENDING ); if (aViewData.GetViewShell()->HasAccessibilityObjects()) aViewData.GetViewShell()->BroadcastAccessibility(SfxSimpleHint(SC_HINT_ACC_CURSORCHANGED)); diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx index d5cbd4690080..2faf542d7544 100644 --- a/sc/source/ui/view/viewfunc.cxx +++ b/sc/source/ui/view/viewfunc.cxx @@ -345,7 +345,7 @@ BOOL lcl_AddFunction( ScAppOptions& rAppOpt, USHORT nOpCode ) // Eingabe - Undo OK void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const String& rString, - BOOL bRecord ) + BOOL bRecord, const EditTextObject* pData ) { ScDocument* pDoc = GetViewData()->GetDocument(); ScMarkData& rMark = GetViewData()->GetMarkData(); @@ -369,6 +369,7 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const String& rS ULONG* pOldFormats = NULL; SCTAB* pTabs = NULL; SCTAB nUndoPos = 0; + EditTextObject* pUndoData = NULL; if ( bRecord ) { ppOldCells = new ScBaseCell*[nSelCount]; @@ -415,6 +416,8 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const String& rS } DBG_ASSERT( nUndoPos==nSelCount, "nUndoPos!=nSelCount" ); + + pUndoData = ( pData ? pData->Clone() : NULL ); } bool bFormula = false; @@ -581,8 +584,16 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const String& rS if ( pFormatter->GetType( nIndex ) == NUMBERFORMAT_TEXT || ( ( rString.GetChar(0) == '+' || rString.GetChar(0) == '-' ) && nError && rString.Equals( aFormula ) ) ) { - ScStringCell* pCell = new ScStringCell( aFormula ); - pDoc->PutCell( aPos, pCell ); + if ( pData ) + { + ScEditCell* pCell = new ScEditCell( pData, pDoc, NULL ); + pDoc->PutCell( aPos, pCell ); + } + else + { + ScStringCell* pCell = new ScStringCell( aFormula ); + pDoc->PutCell( aPos, pCell ); + } } else { @@ -631,10 +642,10 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const String& rS if ( bRecord ) { // wg. ChangeTrack erst jetzt - pDocSh->GetUndoManager()->AddUndoAction( + pDocSh->GetUndoManager()->AddUndoAction( new ScUndoEnterData( pDocSh, nCol, nRow, nTab, nUndoPos, pTabs, ppOldCells, pHasFormat, pOldFormats, - rString, NULL ) ); + rString, pUndoData ) ); } for (i=0; i<nTabCount; i++) @@ -1585,7 +1596,30 @@ void ScViewFunc::DeleteCells( DelCellCmd eCmd, BOOL bRecord ) { ScDocShell* pDocSh = GetViewData()->GetDocShell(); const ScMarkData& rMark = GetViewData()->GetMarkData(); - pDocSh->GetDocFunc().DeleteCells( aRange, &rMark, eCmd, bRecord, FALSE ); + + // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong + if ( pDocSh->IsDocShared() && ( eCmd == DEL_DELROWS || eCmd == DEL_DELCOLS ) ) + { + ScRange aDelRange( aRange.aStart ); + SCCOLROW nCount = 0; + if ( eCmd == DEL_DELROWS ) + { + nCount = sal::static_int_cast< SCCOLROW >( aRange.aEnd.Row() - aRange.aStart.Row() + 1 ); + } + else + { + nCount = sal::static_int_cast< SCCOLROW >( aRange.aEnd.Col() - aRange.aStart.Col() + 1 ); + } + while ( nCount > 0 ) + { + pDocSh->GetDocFunc().DeleteCells( aDelRange, &rMark, eCmd, bRecord, FALSE ); + --nCount; + } + } + else + { + pDocSh->GetDocFunc().DeleteCells( aRange, &rMark, eCmd, bRecord, FALSE ); + } pDocSh->UpdateOle(GetViewData()); CellContentChanged(); |