Commits

Anonymous committed c32e354 Merge

calcdatatables: handle TabKey in DataTable
+ TabKey wraps cell cursor within DataTable
+ if wrapped on last data row a new data row is appended
+ cells are inserted with shift down
* merged WaE wntmsci12

Comments (0)

Files changed (11)

sc/inc/document.hxx

 											ScDirection eDir );
 
 	void			FindAreaPos( SCCOL& rCol, SCROW& rRow, SCTAB nTab, SCsCOL nMovX, SCsROW nMovY );
-	SC_DLLPUBLIC void			GetNextPos( SCCOL& rCol, SCROW& rRow, SCTAB nTab, SCsCOL nMovX, SCsROW nMovY,
-								BOOL bMarked, BOOL bUnprotected, const ScMarkData& rMark );
+
+    /** Get next position for cell cursor, wrapping within marked selection or 
+        DataTable.
+
+        @returns DataTable pointer if and only if bMarked==false and 
+        bWrapDataTable==true and the position was wrapped below a DataTable's 
+        data range. That is if a new row is to be added.
+     */
+	SC_DLLPUBLIC const ScDataTableFormat*   GetNextPos(
+                                SCCOL& rCol, SCROW& rRow, SCTAB nTab, SCsCOL nMovX, SCsROW nMovY,
+                                BOOL bMarked, BOOL bUnprotected, const ScMarkData& rMark,
+                                bool bWrapDataTable );
 
 	BOOL			GetNextMarkedCell( SCCOL& rCol, SCROW& rRow, SCTAB nTab,
 										const ScMarkData& rMark );

sc/source/core/data/attarray.cxx

 #include "globstr.hrc"
 #include "segmenttree.hxx"
 
+#include <algorithm>
+
 #undef DBG_INVALIDATE
 #define DBGOUTPUT(s) \
 	DBG_ERROR( String("Invalidate ") + String(s) + String(": ") \
 
     // If DataTable and not in list, remove all attributes and set default 
     // pattern. Else proceed as usual.
-    if (nDataTable && (!pDataTables || find( pDataTables->begin(), 
+    if (nDataTable && (!pDataTables || ::std::find( pDataTables->begin(), 
                     pDataTables->end(), nDataTable) == pDataTables->end()))
         SetPatternArea( nStartRow, nStartRow+nSize-1, pDocument->GetDefPattern());
     else
                         pTmpPattern->GetItemSet().ClearItem( ATTR_MERGE_FLAG );
                 }
 
-                /* TODO: The styles associated with the DataTable positions 
+                /* TODO DataTable: The styles associated with the positions 
                  * could be applied as normal style sheets in case the 
                  * clipboard content is to be pasted outside the table. This 
                  * would result in different patterns to be applied on paste 

sc/source/core/data/datatablestyle.cxx

         ScRange aOldRange( maRange);
         ScRefUpdateRes eRes = ScRefUpdate::UpdateGrow( aOldRange, nDx, nDy, maRange);
         if (eRes != UR_NOTHING)
+        {
+            if (nDy > 0 && mbTotalRow && rRange.aStart.Row() == aOldRange.aEnd.Row())
+                // For references grow data range excluding total row. If 
+                // references include total row they're updated during insert 
+                // anyway.
+                aOldRange.aEnd.IncRow( -1);
             o_rGrowRanges.push_back( aOldRange);
+        }
     }
     else
     {
 void ScDataTableFormatList::SetList( const ScDataTableFormatList& rList, const ScDocument* pNewDoc )
 {
     DeleteAndDestroy( 0, Count());
-    size_t nCount = rList.Count();
-    for (size_t i=0; i<nCount; i++)
+    USHORT nCount = rList.Count();
+    for (USHORT i=0; i<nCount; i++)
         InsertNew( new ScDataTableFormat( *rList[i], pNewDoc));
 }
 
 
 bool ScDataTableFormatList::operator==( const ScDataTableFormatList& rList ) const
 {
-    size_t nCount = Count();
+    USHORT nCount = Count();
     bool bEqual = (nCount == rList.Count());
-    for (size_t i=0; i<nCount && bEqual; i++)       // entries are sorted
+    for (USHORT i=0; i<nCount && bEqual; i++)       // entries are sorted
         if (!(*this)[i]->Equals( *rList[i]))
             bEqual = false;
 
 {
     /* TODO: binary search */
 
-    size_t nCount = Count();
-    for (size_t i=0; i<nCount; i++)
+    USHORT nCount = Count();
+    for (USHORT i=0; i<nCount; i++)
         if ((*this)[i]->GetKey() == nKey)
             return (*this)[i];
 
 
 void ScDataTableFormat::InitStyles( const ::std::vector<String> & rStyleNames )
 {
-    /* TODO: Derive the DataTable presets from themes or templates. These 
+    /* TODO DataTable: Derive the presets from themes or templates. These 
      * presets are for banded rows with header row. See also 
      * InitDisplayFeatures() */
     ScStyleSheetPool* pPool = mpDoc->GetStyleSheetPool();
 
 void ScDataTableFormat::InitDisplayFeatures( const String& rPrefix )
 {
-    /* TODO: parameters for DataTable feature appearance */
+    /* TODO DataTable: parameters for feature appearance */
     bool bBandedRows = true;
     SetBandedRowsFlag( bBandedRows);
     ::std::vector<String> aStyleNames( CreateAndSetStyles( rPrefix));
         SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
 {
     ::std::vector<ScRange> aGrowRanges;
-    size_t nCount = Count();
-    for (size_t i=0; i < nCount; i++)
+    USHORT nCount = Count();
+    for (USHORT i=0; i < nCount; i++)
         (*this)[i]->UpdateReference( aGrowRanges, eUpdateRefMode, rRange, nDx, nDy, nDz);
     return aGrowRanges;
 }
 
 void ScDataTableFormatList::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos )
 {
-	size_t nCount = Count();
-	for (size_t i=0; i < nCount; i++)
+	USHORT nCount = Count();
+	for (USHORT i=0; i < nCount; i++)
 		(*this)[i]->UpdateMoveTab( nOldPos, nNewPos );
 }
 
     if (!rOld.Len())
         return;
 
-    size_t nCount = Count();
-    for (size_t i=0; i < nCount; i++)
+    USHORT nCount = Count();
+    for (USHORT i=0; i < nCount; i++)
         (*this)[i]->RenameCellStyle( rOld, rNew);
 }
 
 void ScDataTableFormatList::InvalidateStyleSheet( const SfxStyleSheetBase* pStyleSheet )
 {
     const String& rName = pStyleSheet->GetName();
-    size_t nCount = Count();
-    for (size_t i=0; i < nCount; i++)
+    USHORT nCount = Count();
+    for (USHORT i=0; i < nCount; i++)
         (*this)[i]->InvalidateStyleSheet( pStyleSheet, rName);
 }
 
 bool ScDataTableFormatList::IsStyleSheetUsed( const ScStyleSheet& rStyle, bool bGatherAllStyles ) const
 {
     bool bUsed = false;
-    size_t nCount = Count();
-    for (size_t i=0; i < nCount; i++)
+    USHORT nCount = Count();
+    for (USHORT i=0; i < nCount; i++)
     {
         if ((*this)[i]->IsStyleSheetUsed( rStyle, bGatherAllStyles))
         {
 
 void ScDataTableFormatList::FindInRange( ScDataTableMap & o_rDataTables, const ScRange& rRange ) const
 {
-    size_t nCount = Count();
-    for (size_t i=0; i < nCount; i++)
+    USHORT nCount = Count();
+    for (USHORT i=0; i < nCount; i++)
     {
         if ((*this)[i]->IsInRange( rRange))
         {
         bool bTestOnly ) const
 {
     bool bNoFragment = true;
-    size_t nCount = Count();
-    for (size_t i=0; i < nCount && (!bTestOnly || bNoFragment); i++)
+    USHORT nCount = Count();
+    for (USHORT i=0; i < nCount && (!bTestOnly || bNoFragment); i++)
     {
         const ScDataTableFormat* pFormat = (*this)[i];
         const ScRange& rRange = pFormat->GetTableRange();
         bool bTestOnly ) const
 {
     bool bNoFragment = true;
-    size_t nCount = Count();
-    for (size_t i=0; i < nCount && (!bTestOnly || bNoFragment); i++)
+    USHORT nCount = Count();
+    for (USHORT i=0; i < nCount && (!bTestOnly || bNoFragment); i++)
     {
         const ScDataTableFormat* pFormat = (*this)[i];
         const ScRange& rRange = pFormat->GetTableRange();
 {
     bool bNoFragment = true;
     SCROW nEndRow = nRow + nSize - 1;
-    size_t nCount = Count();
-    for (size_t i=0; i < nCount && bNoFragment; i++)
+    USHORT nCount = Count();
+    for (USHORT i=0; i < nCount && bNoFragment; i++)
     {
         const ScDataTableFormat* pFormat = (*this)[i];
         const ScRange& rRange = pFormat->GetTableRange();
         SCCOL nCol, SCSIZE /* nSize */, const ::std::vector<SCTAB> & rTabs) const
 {
     bool bNoFragment = true;
-    size_t nCount = Count();
-    for (size_t i=0; i < nCount && bNoFragment; i++)
+    USHORT nCount = Count();
+    for (USHORT i=0; i < nCount && bNoFragment; i++)
     {
         const ScDataTableFormat* pFormat = (*this)[i];
         const ScRange& rRange = pFormat->GetTableRange();

sc/source/core/data/document.cxx

                 // pair mapping. If source document is this document, the 
                 // clipboard document has the same pool and cut/paste within 
                 // same document doesn't need copies.
-                bool bCut, bSameDoc;
-                if (!aDataTables.empty() && 
-                        (!(bCut = pCBFCP->pClipDoc->GetClipParam().mbCutMode) || 
-                         !(bSameDoc = (pCBFCP->pClipDoc->GetPool() == GetPool()))))
+                bool bCut = pCBFCP->pClipDoc->GetClipParam().mbCutMode;
+                if (!aDataTables.empty() && (!bCut || (pCBFCP->pClipDoc->GetPool() != GetPool())))
                 {
                     const ScDataTableFormatList* pClipList = pCBFCP->pClipDoc->pDataTableFormatList;
                     for (ScDataTableMap::iterator it( aDataTables.begin());
         else
         {
             aTabs.resize( nEndTab - nStartTab + 1);
-            iota( aTabs.begin(), aTabs.end(), nStartTab);
+            ::std::iota( aTabs.begin(), aTabs.end(), nStartTab);
         }
         if (bCol)
             return pDataTableFormatList->FindInsertWithCol( o_rDataTables, 
         else
         {
             aTabs.reserve( nEndTab - nStartTab + 1);
-            iota( aTabs.begin(), aTabs.end(), nStartTab);
+            ::std::iota( aTabs.begin(), aTabs.end(), nStartTab);
         }
         if (bCol)
             return pDataTableFormatList->TestDeleteCol( 
 }
 
 
-void ScDocument::GetNextPos( SCCOL& rCol, SCROW& rRow, SCTAB nTab, SCsCOL nMovX, SCsROW nMovY,
-								BOOL bMarked, BOOL bUnprotected, const ScMarkData& rMark )
-{
-	DBG_ASSERT( !nMovX || !nMovY, "GetNextPos: nur X oder Y" );
-
-	ScMarkData aCopyMark = rMark;
-	aCopyMark.SetMarking(FALSE);
-	aCopyMark.MarkToMulti();
-
-	if (ValidTab(nTab) && pTab[nTab])
-		pTab[nTab]->GetNextPos( rCol, rRow, nMovX, nMovY, bMarked, bUnprotected, aCopyMark );
+const ScDataTableFormat* ScDocument::GetNextPos( SCCOL& rCol, SCROW& rRow, SCTAB nTab,
+        SCsCOL nMovX, SCsROW nMovY, BOOL bMarked, BOOL bUnprotected,
+        const ScMarkData& rMark, bool bWrapDataTable )
+{
+    DBG_ASSERT( !nMovX || !nMovY, "GetNextPos: nur X oder Y" );
+
+    const ScDataTableFormat* pDataTable = NULL;
+    ScRange aDataTableRange( ScAddress::UNINITIALIZED);
+    ScMarkData aCopyMark = rMark;
+    if (bWrapDataTable && !bMarked && nMovX > 0)
+    {
+        // Wrap within DataTable.
+        pDataTable = GetDataTableFormat( rCol, rRow, nTab);
+        if (pDataTable)
+        {
+            aCopyMark.ResetMark();
+            aDataTableRange = pDataTable->GetTableRange();
+            if (aDataTableRange.aEnd.Row() < MAXROW)
+                // Do not wrap to top row, position under last data row 
+                // instead.
+                aDataTableRange.aEnd.SetRow( pDataTable->GetLastDataRow() + 1);
+            aCopyMark.SetMarkArea( aDataTableRange);
+            bMarked = TRUE;
+        }
+    }
+    aCopyMark.SetMarking(FALSE);
+    aCopyMark.MarkToMulti();
+
+    if (ValidTab(nTab) && pTab[nTab])
+        pTab[nTab]->GetNextPos( rCol, rRow, nMovX, nMovY, bMarked, bUnprotected, aCopyMark );
+
+    return (pDataTable && rRow == aDataTableRange.aEnd.Row()) ? pDataTable : NULL;
 }
 
 //

sc/source/core/data/table2.cxx

 			const ScPatternAttr* pPattern = aIter.GetNext( nAttrCol, nAttrRow1, nAttrRow2 );
 			while ( pPattern )
 			{
-                /* FIXME: The DataTable ItemSet would have to be obtained for 
+                /* FIXME DataTable: The ItemSet would have to be obtained for 
                  * individual cells, which doesn't fit with the approach taken 
                  * for conditional formats. Need to run slices within 
                  * conditional formats. */

sc/source/ui/docshell/dbdocfun.cxx

 	{
 		ScDocShellModificator aModificator( rDocShell );
 
-        /* TODO: What if a DataTable is associated? As is, the DBRange is 
-         * deleted and the DataTable style kept intact. */
+        /* TODO DataTable: What if a DataTable is associated? As is, the 
+         * DBRange is deleted and the DataTable style kept intact. */
 
 		ScDBCollection* pUndoColl = NULL;
 		if (bUndo)

sc/source/ui/docshell/dbdocimp.cxx

             // Always apply DataTable format.
             ScPatternAttr aPattern( pImportDoc->GetPool());
             aPattern.GetItemSet().Put( SfxUInt32Item( ATTR_DATATABLE, nDataTable));
-            /* TODO: should nFormulaCols be included in DataTable? If so, the 
+            /* TODO DataTable: should nFormulaCols be included? If so, the 
              * ranges of DBData and DataTable would differ and that would have 
              * to be remembered! */
             pImportDoc->ApplyPatternAreaTab( rParam.nCol1, rParam.nRow1, nEndCol, nEndRow, nTab, aPattern);

sc/source/ui/unoobj/cursuno.cxx

 	SCTAB nTab  = aCursor.Tab();
 	ScDocShell* pDocSh = GetDocShell();
 	if ( pDocSh )
-		pDocSh->GetDocument()->GetNextPos( nNewX,nNewY, nTab,  1,0, FALSE,TRUE, aMark );
+		pDocSh->GetDocument()->GetNextPos( nNewX,nNewY, nTab,  1,0, FALSE,TRUE, aMark, false );
 	//!	sonst Exception oder so
 
 	SetNewRange( ScRange( nNewX, nNewY, nTab ) );
 	SCTAB nTab  = aCursor.Tab();
 	ScDocShell* pDocSh = GetDocShell();
 	if ( pDocSh )
-		pDocSh->GetDocument()->GetNextPos( nNewX,nNewY, nTab, -1,0, FALSE,TRUE, aMark );
+		pDocSh->GetDocument()->GetNextPos( nNewX,nNewY, nTab, -1,0, FALSE,TRUE, aMark, false );
 	//!	sonst Exception oder so
 
 	SetNewRange( ScRange( nNewX, nNewY, nTab ) );

sc/source/ui/vba/vbarange.cxx

 	SCTAB nTab = refRange.aStart.Tab();
 
 	ScDocument* pDoc = getScDocument(); 
-	pDoc->GetNextPos( nNewX,nNewY, nTab, nMove,0, TRUE,TRUE, markedRange );	
+	pDoc->GetNextPos( nNewX,nNewY, nTab, nMove,0, TRUE,TRUE, markedRange, false );	
 	refRange.aStart.SetCol( nNewX );
 	refRange.aStart.SetRow( nNewY );
 	refRange.aStart.SetTab( nTab );

sc/source/ui/view/dbfunc.cxx

 
 void ScDBFunc::NotifyCloseDbNameDlg( const ScDBCollection& rNewColl, const List& rDelAreaList )
 {
-    /* TODO: What if a DataTable is associated? As is, the DBRange is deleted 
-     * and the DataTable style kept intact. */
+    /* TODO DataTable: What if a DataTable is associated? As is, the DBRange is 
+     * deleted and the DataTable style kept intact. */
 
 	ScDocShell* pDocShell = GetViewData()->GetDocShell();
 	ScDocShellModificator aModificator( *pDocShell );

sc/source/ui/view/tabview3.cxx

 #include "rangeutl.hxx"
 #include "client.hxx"
 #include "tabprotection.hxx"
+#include "datatablestyle.hxx"
 
 #include <com/sun/star/chart2/data/HighlightedRange.hpp>
 
 		SCTAB nTab = aViewData.GetTabNo();
 
 		ScDocument* pDoc = aViewData.GetDocument();
-		pDoc->GetNextPos( nNewX,nNewY, nTab, nMoveX,nMoveY, TRUE,FALSE, rMark );
+        pDoc->GetNextPos( nNewX,nNewY, nTab, nMoveX,nMoveY, TRUE,FALSE, rMark, false );
 
 		MoveCursorRel( ((SCsCOL)nNewX)-(SCsCOL)nCurX, ((SCsROW)nNewY)-(SCsROW)nCurY,
 							SC_FOLLOW_LINE, FALSE, TRUE );
 	SCTAB nTab = aViewData.GetTabNo();
 
 	ScDocument* pDoc = aViewData.GetDocument();
-	pDoc->GetNextPos( nNewX,nNewY, nTab, nMove,0, bMarked,TRUE, rMark );
+	const ScDataTableFormat* pDTab = pDoc->GetNextPos( nNewX,nNewY, nTab, nMove,0, bMarked,TRUE, rMark, true );
+    if (pDTab)
+    {
+        // Pointer is returned only if the new position is on the row following 
+        // the last data row, no need to check again.
+        ScMarkData aOldMark( rMark);
+        ScRange aRange( pDTab->GetTableRange());
+        aRange.aStart.SetRow( nNewY);
+        aRange.aEnd.SetRow( nNewY);
+        rMark.ResetMark();
+        rMark.SetMarkArea( aRange);
+/* TODO DataTable: the non-inserting approach needs quite some work */
+#if 0
+        // Insert new DataTable cells only if the range is not empty or is a 
+        // total row, else copy only attributes to be less invasive on existing 
+        // data.
+        if (nNewY <= pDTab->GetTableRange().aEnd.Row() ||
+                !pDoc->IsBlockEmpty( aRange.aStart.Tab(), aRange.aStart.Col(), nNewY, aRange.aEnd.Col(), nNewY))
+            aViewData.GetViewShell()->InsertCells( INS_CELLSDOWN);
+        else
+        {
+            /* FIXME DataTable: copy attributes (may include formats, 
+             * conditional, ...) from last data row instead of setting only 
+             * DataTable */
+            SfxUInt32Item aItem( ATTR_DATATABLE, pDTab->GetKey());
+            aViewData.GetViewShell()->ApplyAttr( aItem);
+            aRange = pDTab->GetTableRange();
+            aRange.aEnd.SetRow( nNewY);
+            /* FIXME DataTable: obtain non-const pointer from document */
+            const_cast<ScDataTableFormat*>(pDTab)->SetTableRange( aRange);
+            /* FIXME DataTable: call UpdateGrow() for references */
+            /* FIXME DataTable: new range and grow need Undo */
+        }
+#else
+        aViewData.GetViewShell()->InsertCells( INS_CELLSDOWN);
+#endif
+        rMark = aOldMark;
+    }
 
 	SCCOL nTabCol = aViewData.GetTabStartCol();
 	if ( nTabCol == SC_TABSTART_NONE )
-		nTabCol = nCurX;					// auf diese Spalte zurueck bei Enter
+		nTabCol = nCurX;					// back to this column upon Enter
 
 	MoveCursorRel( ((SCsCOL)nNewX)-(SCsCOL)nCurX, ((SCsROW)nNewY)-(SCsROW)nCurY,
 						SC_FOLLOW_LINE, FALSE, TRUE );
 
-	//	in MoveCursorRel wird die TabCol zurueckgesetzt...
+    // in MoveCursorRel TabCol is reset...
 	aViewData.SetTabStartCol( nTabCol );
 }