diff options
-rw-r--r-- | sc/source/ui/docshell/docfunc.cxx | 224 | ||||
-rw-r--r-- | sc/source/ui/inc/cellmergeoption.hxx | 60 | ||||
-rw-r--r-- | sc/source/ui/inc/docfunc.hxx | 12 | ||||
-rw-r--r-- | sc/source/ui/inc/undoblk.hxx | 14 | ||||
-rw-r--r-- | sc/source/ui/inc/viewfunc.hxx | 2 | ||||
-rw-r--r-- | sc/source/ui/undo/undoblk.cxx | 103 | ||||
-rw-r--r-- | sc/source/ui/undo/undoblk3.cxx | 107 | ||||
-rw-r--r-- | sc/source/ui/unoobj/cellsuno.cxx | 9 | ||||
-rw-r--r-- | sc/source/ui/view/cellmergeoption.cxx | 74 | ||||
-rw-r--r-- | sc/source/ui/view/cellsh3.cxx | 4 | ||||
-rw-r--r-- | sc/source/ui/view/makefile.mk | 1 | ||||
-rw-r--r-- | sc/source/ui/view/viewfun2.cxx | 82 | ||||
-rw-r--r-- | sc/uiconfig/scalc/menubar/menubar.xml | 8 |
13 files changed, 518 insertions, 182 deletions
diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx index b6bb1483adfe..425372556678 100644 --- a/sc/source/ui/docshell/docfunc.cxx +++ b/sc/source/ui/docshell/docfunc.cxx @@ -65,6 +65,7 @@ #include "dociter.hxx" #include "autoform.hxx" #include "cell.hxx" +#include "cellmergeoption.hxx" #include "detdata.hxx" #include "detfunc.hxx" #include "docpool.hxx" @@ -103,6 +104,7 @@ #include <memory> #include <basic/basmgr.hxx> #include <boost/scoped_ptr.hpp> +#include <set> using namespace com::sun::star; using ::com::sun::star::uno::Sequence; @@ -1714,7 +1716,11 @@ BOOL ScDocFunc::InsertCells( const ScRange& rRange, const ScMarkData* pTabMark, default: break; } - MergeCells(aRange, FALSE, TRUE, TRUE); + ScCellMergeOption aMergeOption( + aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Col(), aRange.aEnd.Row() ); + aMergeOption.maTabs.insert(aRange.aStart.Tab()); + MergeCells(aMergeOption, FALSE, TRUE, TRUE); } qIncreaseRange.pop_back(); } @@ -1763,7 +1769,10 @@ BOOL ScDocFunc::InsertCells( const ScRange& rRange, const ScMarkData* pTabMark, while( !qIncreaseRange.empty() ) { ScRange aRange = qIncreaseRange.back(); - MergeCells(aRange, FALSE, TRUE, TRUE); + ScCellMergeOption aMergeOption( + aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Col(), aRange.aEnd.Row() ); + MergeCells(aMergeOption, FALSE, TRUE, TRUE); qIncreaseRange.pop_back(); } @@ -2201,7 +2210,10 @@ BOOL ScDocFunc::DeleteCells( const ScRange& rRange, const ScMarkData* pTabMark, if( !pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) ) { - MergeCells( aRange, FALSE, TRUE, TRUE ); + ScCellMergeOption aMergeOption( + aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Col(), aRange.aEnd.Row() ); + MergeCells( aMergeOption, FALSE, TRUE, TRUE ); } qDecreaseRange.pop_back(); } @@ -4338,86 +4350,110 @@ BOOL ScDocFunc::FillAuto( ScRange& rRange, const ScMarkData* pTabMark, //------------------------------------------------------------------------ -BOOL ScDocFunc::MergeCells( const ScRange& rRange, BOOL bContents, BOOL bRecord, BOOL bApi ) +BOOL ScDocFunc::MergeCells( const ScCellMergeOption& rOption, BOOL bContents, BOOL bRecord, BOOL bApi ) { + using ::std::set; + ScDocShellModificator aModificator( rDocShell ); + SCCOL nStartCol = rOption.mnStartCol; + SCROW nStartRow = rOption.mnStartRow; + SCCOL nEndCol = rOption.mnEndCol; + SCROW nEndRow = rOption.mnEndRow; + if ((nStartCol == nEndCol && nStartRow == nEndRow) || rOption.maTabs.empty()) + { + // Nothing to do. Bail out quick. + return TRUE; + } + ScDocument* pDoc = rDocShell.GetDocument(); - SCCOL nStartCol = rRange.aStart.Col(); - SCROW nStartRow = rRange.aStart.Row(); - SCCOL nEndCol = rRange.aEnd.Col(); - SCROW nEndRow = rRange.aEnd.Row(); - SCTAB nTab = rRange.aStart.Tab(); + set<SCTAB>::const_iterator itrBeg = rOption.maTabs.begin(), itrEnd = rOption.maTabs.end(); + SCTAB nTab1 = *itrBeg, nTab2 = *rOption.maTabs.rbegin(); if (bRecord && !pDoc->IsUndoEnabled()) bRecord = FALSE; - ScEditableTester aTester( pDoc, nTab, nStartCol, nStartRow, nEndCol, nEndRow ); - if (!aTester.IsEditable()) + for (set<SCTAB>::const_iterator itr = itrBeg; itr != itrEnd; ++itr) { - if (!bApi) - rDocShell.ErrorMessage(aTester.GetMessageId()); - return FALSE; - } + ScEditableTester aTester( pDoc, *itr, nStartCol, nStartRow, nEndCol, nEndRow ); + if (!aTester.IsEditable()) + { + if (!bApi) + rDocShell.ErrorMessage(aTester.GetMessageId()); + return FALSE; + } - if ( nStartCol == nEndCol && nStartRow == nEndRow ) - { - // nichts zu tun - return TRUE; + if ( pDoc->HasAttrib( nStartCol, nStartRow, *itr, nEndCol, nEndRow, *itr, + HASATTR_MERGED | HASATTR_OVERLAPPED ) ) + { + // "Zusammenfassen nicht verschachteln !" + if (!bApi) + rDocShell.ErrorMessage(STR_MSSG_MERGECELLS_0); + return FALSE; + } } - if ( pDoc->HasAttrib( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab, - HASATTR_MERGED | HASATTR_OVERLAPPED ) ) + ScDocument* pUndoDoc = NULL; + bool bNeedContentsUndo = false; + for (set<SCTAB>::const_iterator itr = itrBeg; itr != itrEnd; ++itr) { - // "Zusammenfassen nicht verschachteln !" - if (!bApi) - rDocShell.ErrorMessage(STR_MSSG_MERGECELLS_0); - return FALSE; - } + SCTAB nTab = *itr; + bool bNeedContents = bContents && + ( !pDoc->IsBlockEmpty( nTab, nStartCol,nStartRow+1, nStartCol,nEndRow, true ) || + !pDoc->IsBlockEmpty( nTab, nStartCol+1,nStartRow, nEndCol,nEndRow, true ) ); - BOOL bNeedContents = bContents && - ( !pDoc->IsBlockEmpty( nTab, nStartCol,nStartRow+1, nStartCol,nEndRow, true ) || - !pDoc->IsBlockEmpty( nTab, nStartCol+1,nStartRow, nEndCol,nEndRow, true ) ); + if (bRecord) + { + // test if the range contains other notes which also implies that we need an undo document + bool bHasNotes = false; + for( ScAddress aPos( nStartCol, nStartRow, nTab ); !bHasNotes && (aPos.Col() <= nEndCol); aPos.IncCol() ) + for( aPos.SetRow( nStartRow ); !bHasNotes && (aPos.Row() <= nEndRow); aPos.IncRow() ) + bHasNotes = ((aPos.Col() != nStartCol) || (aPos.Row() != nStartRow)) && (pDoc->GetNote( aPos ) != 0); - ScDocument* pUndoDoc = 0; - if (bRecord) - { - // test if the range contains other notes which also implies that we need an undo document - bool bHasNotes = false; - for( ScAddress aPos( nStartCol, nStartRow, nTab ); !bHasNotes && (aPos.Col() <= nEndCol); aPos.IncCol() ) - for( aPos.SetRow( nStartRow ); !bHasNotes && (aPos.Row() <= nEndRow); aPos.IncRow() ) - bHasNotes = ((aPos.Col() != nStartCol) || (aPos.Row() != nStartRow)) && (pDoc->GetNote( aPos ) != 0); + if (bNeedContents || bHasNotes || rOption.mbCenter) + { + if (!pUndoDoc) + { + pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + pUndoDoc->InitUndo(pDoc, nTab1, nTab2); + } + // note captions are collected by drawing undo + pDoc->CopyToDocument( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab, + IDF_ALL|IDF_NOCAPTIONS, FALSE, pUndoDoc ); + } + if( bHasNotes ) + pDoc->BeginDrawUndo(); + } + + if (bNeedContents) + pDoc->DoMergeContents( nTab, nStartCol,nStartRow, nEndCol,nEndRow ); + pDoc->DoMerge( nTab, nStartCol,nStartRow, nEndCol,nEndRow ); - if (bNeedContents || bHasNotes) + if (rOption.mbCenter) { - pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); - pUndoDoc->InitUndo( pDoc, nTab, nTab ); - // note captions are collected by drawing undo - pDoc->CopyToDocument( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab, - IDF_ALL|IDF_NOCAPTIONS, FALSE, pUndoDoc ); + pDoc->ApplyAttr( nStartCol, nStartRow, nTab, SvxHorJustifyItem( SVX_HOR_JUSTIFY_CENTER, ATTR_HOR_JUSTIFY ) ); + pDoc->ApplyAttr( nStartCol, nStartRow, nTab, SvxVerJustifyItem( SVX_VER_JUSTIFY_CENTER, ATTR_VER_JUSTIFY ) ); } - if( bHasNotes ) - pDoc->BeginDrawUndo(); - } - if (bNeedContents) - pDoc->DoMergeContents( nTab, nStartCol,nStartRow, nEndCol,nEndRow ); - pDoc->DoMerge( nTab, nStartCol,nStartRow, nEndCol,nEndRow ); + if ( !AdjustRowHeight( ScRange( 0,nStartRow,nTab, MAXCOL,nEndRow,nTab ) ) ) + rDocShell.PostPaint( nStartCol, nStartRow, nTab, + nEndCol, nEndRow, nTab, PAINT_GRID ); + if (bNeedContents || rOption.mbCenter) + { + ScRange aRange(nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab); + pDoc->SetDirty(aRange); + } - if( bRecord ) + bNeedContentsUndo |= bNeedContents; + } + + if (pUndoDoc) { - SdrUndoGroup* pDrawUndo = pDoc->GetDrawLayer() ? pDoc->GetDrawLayer()->GetCalcUndo() : 0; + SdrUndoGroup* pDrawUndo = pDoc->GetDrawLayer() ? pDoc->GetDrawLayer()->GetCalcUndo() : NULL; rDocShell.GetUndoManager()->AddUndoAction( - new ScUndoMerge( &rDocShell, - nStartCol, nStartRow, nTab, - nEndCol, nEndRow, nTab, bNeedContents, pUndoDoc, pDrawUndo ) ); + new ScUndoMerge(&rDocShell, rOption, bNeedContentsUndo, pUndoDoc, pDrawUndo) ); } - if ( !AdjustRowHeight( ScRange( 0,nStartRow,nTab, MAXCOL,nEndRow,nTab ) ) ) - rDocShell.PostPaint( nStartCol, nStartRow, nTab, - nEndCol, nEndRow, nTab, PAINT_GRID ); - if (bNeedContents) - pDoc->SetDirty( rRange ); aModificator.SetDocumentModified(); SfxBindings* pBindings = rDocShell.GetViewBindings(); @@ -4433,49 +4469,81 @@ BOOL ScDocFunc::MergeCells( const ScRange& rRange, BOOL bContents, BOOL bRecord, BOOL ScDocFunc::UnmergeCells( const ScRange& rRange, BOOL bRecord, BOOL bApi ) { - ScDocShellModificator aModificator( rDocShell ); + ScCellMergeOption aOption(rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row()); + SCTAB nTab1 = rRange.aStart.Tab(), nTab2 = rRange.aEnd.Tab(); + for (SCTAB i = nTab1; i <= nTab2; ++i) + aOption.maTabs.insert(i); + + return UnmergeCells(aOption, bRecord, bApi); +} + +bool ScDocFunc::UnmergeCells( const ScCellMergeOption& rOption, BOOL bRecord, BOOL bApi ) +{ + using ::std::set; + + if (rOption.maTabs.empty()) + // Nothing to unmerge. + return true; + ScDocShellModificator aModificator( rDocShell ); ScDocument* pDoc = rDocShell.GetDocument(); - SCTAB nTab = rRange.aStart.Tab(); if (bRecord && !pDoc->IsUndoEnabled()) bRecord = FALSE; - if ( pDoc->HasAttrib( rRange, HASATTR_MERGED ) ) + ScDocument* pUndoDoc = NULL; + bool bBeep = false; + for (set<SCTAB>::const_iterator itr = rOption.maTabs.begin(), itrEnd = rOption.maTabs.end(); + itr != itrEnd; ++itr) { - ScRange aExtended = rRange; - pDoc->ExtendMerge( aExtended ); + SCTAB nTab = *itr; + ScRange aRange = rOption.getSingleRange(nTab); + if ( !pDoc->HasAttrib(aRange, HASATTR_MERGED) ) + { + bBeep = true; + continue; + } + + ScRange aExtended = aRange; + pDoc->ExtendMerge(aExtended); ScRange aRefresh = aExtended; - pDoc->ExtendOverlapped( aRefresh ); + pDoc->ExtendOverlapped(aRefresh); if (bRecord) { - ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); - pUndoDoc->InitUndo( pDoc, nTab, nTab ); - pDoc->CopyToDocument( aExtended, IDF_ATTRIB, FALSE, pUndoDoc ); - rDocShell.GetUndoManager()->AddUndoAction( - new ScUndoRemoveMerge( &rDocShell, rRange, pUndoDoc ) ); + if (!pUndoDoc) + { + pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + pUndoDoc->InitUndo(pDoc, *rOption.maTabs.begin(), *rOption.maTabs.rbegin()); + } + pDoc->CopyToDocument(aExtended, IDF_ATTRIB, FALSE, pUndoDoc); } const SfxPoolItem& rDefAttr = pDoc->GetPool()->GetDefaultItem( ATTR_MERGE ); ScPatternAttr aPattern( pDoc->GetPool() ); aPattern.GetItemSet().Put( rDefAttr ); - pDoc->ApplyPatternAreaTab( rRange.aStart.Col(), rRange.aStart.Row(), - rRange.aEnd.Col(), rRange.aEnd.Row(), nTab, - aPattern ); + pDoc->ApplyPatternAreaTab( aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Col(), aRange.aEnd.Row(), nTab, + aPattern ); pDoc->RemoveFlagsTab( aExtended.aStart.Col(), aExtended.aStart.Row(), - aExtended.aEnd.Col(), aExtended.aEnd.Row(), nTab, - SC_MF_HOR | SC_MF_VER ); + aExtended.aEnd.Col(), aExtended.aEnd.Row(), nTab, + SC_MF_HOR | SC_MF_VER ); pDoc->ExtendMerge( aRefresh, TRUE, FALSE ); if ( !AdjustRowHeight( aExtended ) ) rDocShell.PostPaint( aExtended, PAINT_GRID ); - aModificator.SetDocumentModified(); } - else if (!bApi) - Sound::Beep(); //! FALSE zurueck??? + if (bBeep && !bApi) + Sound::Beep(); + + if (bRecord) + { + rDocShell.GetUndoManager()->AddUndoAction( + new ScUndoRemoveMerge( &rDocShell, rOption, pUndoDoc ) ); + } + aModificator.SetDocumentModified(); return TRUE; } diff --git a/sc/source/ui/inc/cellmergeoption.hxx b/sc/source/ui/inc/cellmergeoption.hxx new file mode 100644 index 000000000000..37b5b0b3e697 --- /dev/null +++ b/sc/source/ui/inc/cellmergeoption.hxx @@ -0,0 +1,60 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2010 by Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: docfunc.hxx,v $ + * $Revision: 1.18.30.2 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SC_CELLMERGEOPTION_HXX +#define SC_CELLMERGEOPTION_HXX + +#include "address.hxx" + +#include <set> + +class ScRange; + +struct ScCellMergeOption +{ + ::std::set<SCTAB> maTabs; + SCCOL mnStartCol; + SCROW mnStartRow; + SCCOL mnEndCol; + SCROW mnEndRow; + bool mbCenter; + + explicit ScCellMergeOption(); + explicit ScCellMergeOption(SCCOL nStartCol, SCROW nStartRow, + SCCOL nEndCol, SCROW nEndRow, + bool bCenter = false); + explicit ScCellMergeOption(const ScCellMergeOption& r); + + ScRange getSingleRange(SCTAB nTab) const; + ScRange getFirstSingleRange() const; +}; + + +#endif diff --git a/sc/source/ui/inc/docfunc.hxx b/sc/source/ui/inc/docfunc.hxx index fc2f4b40d9a9..85fe9ec264ed 100644 --- a/sc/source/ui/inc/docfunc.hxx +++ b/sc/source/ui/inc/docfunc.hxx @@ -49,13 +49,14 @@ class ScBaseCell; class ScTokenArray; struct ScTabOpParam; class ScTableProtection; +struct ScCellMergeOption; // --------------------------------------------------------------------------- class ScDocFunc { private: - ScDocShell& rDocShell; + ScDocShell& rDocShell; BOOL AdjustRowHeight( const ScRange& rRange, BOOL bPaint = TRUE ); void CreateOneName( ScRangeName& rList, @@ -131,9 +132,9 @@ public: BOOL SetLayoutRTL( SCTAB nTab, BOOL bRTL, BOOL bApi ); -//UNUSED2009-05 BOOL SetGrammar( formula::FormulaGrammar::Grammar eGrammar ); +//UNUSED2009-05 BOOL SetGrammar( formula::FormulaGrammar::Grammar eGrammar ); - SC_DLLPUBLIC BOOL SetWidthOrHeight( BOOL bWidth, SCCOLROW nRangeCnt, SCCOLROW* pRanges, + SC_DLLPUBLIC BOOL SetWidthOrHeight( BOOL bWidth, SCCOLROW nRangeCnt, SCCOLROW* pRanges, SCTAB nTab, ScSizeMode eMode, USHORT nSizeTwips, BOOL bRecord, BOOL bApi ); @@ -164,7 +165,7 @@ public: BOOL FillSimple( const ScRange& rRange, const ScMarkData* pTabMark, FillDir eDir, BOOL bRecord, BOOL bApi ); BOOL FillSeries( const ScRange& rRange, const ScMarkData* pTabMark, - FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd, + FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd, double fStart, double fStep, double fMax, BOOL bRecord, BOOL bApi ); // FillAuto: rRange wird von Source-Range auf Dest-Range angepasst @@ -173,9 +174,10 @@ public: BOOL ResizeMatrix( const ScRange& rOldRange, const ScAddress& rNewEnd, BOOL bApi ); - BOOL MergeCells( const ScRange& rRange, BOOL bContents, + BOOL MergeCells( const ScCellMergeOption& rOption, BOOL bContents, BOOL bRecord, BOOL bApi ); BOOL UnmergeCells( const ScRange& rRange, BOOL bRecord, BOOL bApi ); + bool UnmergeCells( const ScCellMergeOption& rOption, BOOL bRecord, BOOL bApi ); BOOL SetNewRangeNames( ScRangeName* pNewRanges, BOOL bApi ); // takes ownership of pNewRanges BOOL ModifyRangeNames( const ScRangeName& rNewRanges, BOOL bApi ); diff --git a/sc/source/ui/inc/undoblk.hxx b/sc/source/ui/inc/undoblk.hxx index b910baccc766..6b8ed3c3b539 100644 --- a/sc/source/ui/inc/undoblk.hxx +++ b/sc/source/ui/inc/undoblk.hxx @@ -31,6 +31,7 @@ #include "markdata.hxx" #include "viewutil.hxx" #include "spellparam.hxx" +#include "cellmergeoption.hxx" #include "cell.hxx" @@ -452,10 +453,8 @@ class ScUndoMerge: public ScSimpleUndo { public: TYPEINFO(); - ScUndoMerge( ScDocShell* pNewDocShell, - SCCOL nStartX, SCROW nStartY, SCTAB nStartZ, - SCCOL nEndX, SCROW nEndY, SCTAB nEndZ, - bool bMergeContents, ScDocument* pUndoDoc, SdrUndoAction* pDrawUndo ); + ScUndoMerge( ScDocShell* pNewDocShell, const ScCellMergeOption& rOption, + bool bMergeContents, ScDocument* pUndoDoc, SdrUndoAction* pDrawUndo); virtual ~ScUndoMerge(); virtual void Undo(); @@ -466,7 +465,7 @@ public: virtual String GetComment() const; private: - ScRange maRange; + ScCellMergeOption maOption; bool mbMergeContents; // Merge contents in Redo(). ScDocument* mpUndoDoc; // wenn Daten zusammengefasst SdrUndoAction* mpDrawUndo; @@ -947,7 +946,7 @@ class ScUndoRemoveMerge: public ScBlockUndo public: TYPEINFO(); ScUndoRemoveMerge( ScDocShell* pNewDocShell, - const ScRange& rArea, + const ScCellMergeOption& rOption, ScDocument* pNewUndoDoc ); virtual ~ScUndoRemoveMerge(); @@ -959,6 +958,9 @@ public: virtual String GetComment() const; private: + void SetCurTab(); + + ScCellMergeOption maOption; ScDocument* pUndoDoc; }; diff --git a/sc/source/ui/inc/viewfunc.hxx b/sc/source/ui/inc/viewfunc.hxx index b80595c09f50..7c594506e521 100644 --- a/sc/source/ui/inc/viewfunc.hxx +++ b/sc/source/ui/inc/viewfunc.hxx @@ -239,7 +239,7 @@ public: BOOL TestMergeCells(); BOOL TestRemoveMerge(); - BOOL MergeCells( BOOL bApi, BOOL& rDoContents, BOOL bRecord = TRUE ); + BOOL MergeCells( BOOL bApi, BOOL& rDoContents, BOOL bRecord = TRUE, BOOL bCenter = FALSE ); BOOL RemoveMerge( BOOL bRecord = TRUE ); void FillSimple( FillDir eDir, BOOL bRecord = TRUE ); diff --git a/sc/source/ui/undo/undoblk.cxx b/sc/source/ui/undo/undoblk.cxx index 3fb2c74a9954..1435dbff6077 100644 --- a/sc/source/ui/undo/undoblk.cxx +++ b/sc/source/ui/undo/undoblk.cxx @@ -64,6 +64,7 @@ #include "clipparam.hxx" #include "sc.hrc" +#include <set> // STATIC DATA ----------------------------------------------------------- @@ -2051,8 +2052,9 @@ BOOL __EXPORT ScUndoRemoveBreaks::CanRepeat(SfxRepeatTarget& rTarget) const // ScUndoRemoveMerge::ScUndoRemoveMerge( ScDocShell* pNewDocShell, - const ScRange& rArea, ScDocument* pNewUndoDoc ) : - ScBlockUndo( pNewDocShell, rArea, SC_UNDO_SIMPLE ), + const ScCellMergeOption& rOption, ScDocument* pNewUndoDoc ) : + ScBlockUndo( pNewDocShell, rOption.getFirstSingleRange(), SC_UNDO_SIMPLE ), + maOption(rOption), pUndoDoc( pNewUndoDoc ) { } @@ -2069,66 +2071,78 @@ String __EXPORT ScUndoRemoveMerge::GetComment() const void __EXPORT ScUndoRemoveMerge::Undo() { - BeginUndo(); - - ScDocument* pDoc = pDocShell->GetDocument(); - - ScRange aExtended = aBlockRange; - pUndoDoc->ExtendMerge( aExtended ); + using ::std::set; - pDoc->DeleteAreaTab( aExtended, IDF_ATTRIB ); - pUndoDoc->CopyToDocument( aExtended, IDF_ATTRIB, FALSE, pDoc ); + SetCurTab(); + BeginUndo(); - BOOL bDidPaint = FALSE; ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); - if ( pViewShell ) + + ScDocument* pDoc = pDocShell->GetDocument(); + for (set<SCTAB>::const_iterator itr = maOption.maTabs.begin(), itrEnd = maOption.maTabs.end(); + itr != itrEnd; ++itr) { - pViewShell->SetTabNo( aExtended.aStart.Tab() ); - bDidPaint = pViewShell->AdjustRowHeight( aExtended.aStart.Row(), aExtended.aEnd.Row() ); + // There is no need to extend merge area because it's already been extended. + ScRange aRange = maOption.getSingleRange(*itr); + pDoc->DeleteAreaTab(aRange, IDF_ATTRIB); + pUndoDoc->CopyToDocument(aRange, IDF_ATTRIB, FALSE, pDoc); + + bool bDidPaint = false; + if ( pViewShell ) + { + pViewShell->SetTabNo(*itr); + bDidPaint = pViewShell->AdjustRowHeight(maOption.mnStartRow, maOption.mnEndRow); + } + if (!bDidPaint) + ScUndoUtil::PaintMore(pDocShell, aRange); } - if (!bDidPaint) - ScUndoUtil::PaintMore( pDocShell, aExtended ); EndUndo(); } void __EXPORT ScUndoRemoveMerge::Redo() { + using ::std::set; + + SetCurTab(); BeginRedo(); - SCTAB nTab = aBlockRange.aStart.Tab(); ScDocument* pDoc = pDocShell->GetDocument(); - ScRange aExtended = aBlockRange; - pDoc->ExtendMerge( aExtended ); - ScRange aRefresh = aExtended; - pDoc->ExtendOverlapped( aRefresh ); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + + for (set<SCTAB>::const_iterator itr = maOption.maTabs.begin(), itrEnd = maOption.maTabs.end(); + itr != itrEnd; ++itr) + { + SCTAB nTab = *itr; + // There is no need to extend merge area because it's already been extended. + ScRange aRange = maOption.getSingleRange(nTab); - // ausfuehren + // ausfuehren - const SfxPoolItem& rDefAttr = pDoc->GetPool()->GetDefaultItem( ATTR_MERGE ); - ScPatternAttr aPattern( pDoc->GetPool() ); - aPattern.GetItemSet().Put( rDefAttr ); - pDoc->ApplyPatternAreaTab( aBlockRange.aStart.Col(), aBlockRange.aStart.Row(), - aBlockRange.aEnd.Col(), aBlockRange.aEnd.Row(), nTab, - aPattern ); + const SfxPoolItem& rDefAttr = pDoc->GetPool()->GetDefaultItem( ATTR_MERGE ); + ScPatternAttr aPattern( pDoc->GetPool() ); + aPattern.GetItemSet().Put( rDefAttr ); + pDoc->ApplyPatternAreaTab( maOption.mnStartCol, maOption.mnStartRow, + maOption.mnEndCol, maOption.mnEndRow, nTab, + aPattern ); - pDoc->RemoveFlagsTab( aExtended.aStart.Col(), aExtended.aStart.Row(), - aExtended.aEnd.Col(), aExtended.aEnd.Row(), nTab, - SC_MF_HOR | SC_MF_VER ); + pDoc->RemoveFlagsTab( maOption.mnStartCol, maOption.mnStartRow, + maOption.mnEndCol, maOption.mnEndRow, nTab, + SC_MF_HOR | SC_MF_VER ); - pDoc->ExtendMerge( aRefresh, TRUE, FALSE ); + pDoc->ExtendMerge(aRange, TRUE, FALSE); - // Paint + // Paint - BOOL bDidPaint = FALSE; - ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); - if ( pViewShell ) - { - pViewShell->SetTabNo( aExtended.aStart.Tab() ); - bDidPaint = pViewShell->AdjustRowHeight( aExtended.aStart.Row(), aExtended.aEnd.Row() ); + BOOL bDidPaint = FALSE; + if ( pViewShell ) + { + pViewShell->SetTabNo(nTab); + bDidPaint = pViewShell->AdjustRowHeight(maOption.mnStartRow, maOption.mnEndRow); + } + if (!bDidPaint) + ScUndoUtil::PaintMore(pDocShell, aRange); } - if (!bDidPaint) - ScUndoUtil::PaintMore( pDocShell, aExtended ); EndRedo(); } @@ -2144,6 +2158,13 @@ BOOL __EXPORT ScUndoRemoveMerge::CanRepeat(SfxRepeatTarget& rTarget) const return (rTarget.ISA(ScTabViewTarget)); } +void ScUndoRemoveMerge::SetCurTab() +{ + SCTAB nCurTab = pDocShell->GetCurTab(); + aBlockRange.aStart.SetTab(nCurTab); + aBlockRange.aEnd.SetTab(nCurTab); +} + // ----------------------------------------------------------------------- // // nur Umrandung setzen, per ScRangeList (StarOne) diff --git a/sc/source/ui/undo/undoblk3.cxx b/sc/source/ui/undo/undoblk3.cxx index 4140d85f5051..1579b9ceb5db 100644 --- a/sc/source/ui/undo/undoblk3.cxx +++ b/sc/source/ui/undo/undoblk3.cxx @@ -31,6 +31,7 @@ // INCLUDE ------------------------------------------------------------------- #include "scitems.hxx" +#include <svx/algitem.hxx> #include <editeng/boxitem.hxx> #include <svl/srchitem.hxx> #include <sfx2/linkmgr.hxx> @@ -798,14 +799,12 @@ BOOL __EXPORT ScUndoAutoFill::CanRepeat(SfxRepeatTarget& rTarget) const //---------------------------------------------------------------------------- -ScUndoMerge::ScUndoMerge( ScDocShell* pNewDocShell, - SCCOL nStartX, SCROW nStartY, SCTAB nStartZ, - SCCOL nEndX, SCROW nEndY, SCTAB nEndZ, - bool bMergeContents, ScDocument* pUndoDoc, SdrUndoAction* pDrawUndo ) +ScUndoMerge::ScUndoMerge( ScDocShell* pNewDocShell, const ScCellMergeOption& rOption, + bool bMergeContents, ScDocument* pUndoDoc, SdrUndoAction* pDrawUndo ) // : ScSimpleUndo( pNewDocShell ), // - maRange( nStartX, nStartY, nStartZ, nEndX, nEndY, nEndZ ), + maOption(rOption), mbMergeContents( bMergeContents ), mpUndoDoc( pUndoDoc ), mpDrawUndo( pDrawUndo ) @@ -834,51 +833,77 @@ String ScUndoMerge::GetComment() const void ScUndoMerge::DoChange( bool bUndo ) const { - ScDocument* pDoc = pDocShell->GetDocument(); + using ::std::set; - ScUndoUtil::MarkSimpleBlock( pDocShell, maRange ); + if (maOption.maTabs.empty()) + // Nothing to do. + return; - if (bUndo) - // remove merge (contents are copied back below from undo document) - pDoc->RemoveMerge( maRange.aStart.Col(), maRange.aStart.Row(), maRange.aStart.Tab() ); - else - // repeat merge, but do not remove note captions (will be done by drawing redo below) -/*!*/ pDoc->DoMerge( maRange.aStart.Tab(), - maRange.aStart.Col(), maRange.aStart.Row(), - maRange.aEnd.Col(), maRange.aEnd.Row(), false ); + ScDocument* pDoc = pDocShell->GetDocument(); + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); - // undo -> copy back deleted contents - if (bUndo && mpUndoDoc) - { - pDoc->DeleteAreaTab( maRange, IDF_CONTENTS|IDF_NOCAPTIONS ); - mpUndoDoc->CopyToDocument( maRange, IDF_ALL|IDF_NOCAPTIONS, FALSE, pDoc ); - } + ScRange aCurRange = maOption.getSingleRange(pDocShell->GetCurTab()); + ScUndoUtil::MarkSimpleBlock(pDocShell, aCurRange); - // redo -> merge contents again - else if (!bUndo && mbMergeContents) + for (set<SCTAB>::const_iterator itr = maOption.maTabs.begin(), itrEnd = maOption.maTabs.end(); + itr != itrEnd; ++itr) { -/*!*/ pDoc->DoMergeContents( maRange.aStart.Tab(), - maRange.aStart.Col(), maRange.aStart.Row(), - maRange.aEnd.Col(), maRange.aEnd.Row() ); - } + SCTAB nTab = *itr; + ScRange aRange = maOption.getSingleRange(nTab); - if (bUndo) - DoSdrUndoAction( mpDrawUndo, pDoc ); - else - RedoSdrUndoAction( mpDrawUndo ); + if (bUndo) + // remove merge (contents are copied back below from undo document) + pDoc->RemoveMerge( aRange.aStart.Col(), aRange.aStart.Row(), aRange.aStart.Tab() ); + else + { + // repeat merge, but do not remove note captions (will be done by drawing redo below) + pDoc->DoMerge( aRange.aStart.Tab(), + aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Col(), aRange.aEnd.Row(), false ); - BOOL bDidPaint = FALSE; - ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); - if ( pViewShell ) - { - pViewShell->SetTabNo( maRange.aStart.Tab() ); - bDidPaint = pViewShell->AdjustRowHeight( maRange.aStart.Row(), maRange.aEnd.Row() ); - } + if (maOption.mbCenter) + { + pDoc->ApplyAttr( aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aStart.Tab(), + SvxHorJustifyItem( SVX_HOR_JUSTIFY_CENTER, ATTR_HOR_JUSTIFY ) ); + pDoc->ApplyAttr( aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aStart.Tab(), + SvxVerJustifyItem( SVX_VER_JUSTIFY_CENTER, ATTR_VER_JUSTIFY ) ); + } + } + + // undo -> copy back deleted contents + if (bUndo && mpUndoDoc) + { + pDoc->DeleteAreaTab( aRange, IDF_CONTENTS|IDF_NOCAPTIONS ); + mpUndoDoc->CopyToDocument( aRange, IDF_ALL|IDF_NOCAPTIONS, FALSE, pDoc ); + } + + // redo -> merge contents again + else if (!bUndo && mbMergeContents) + { + pDoc->DoMergeContents( aRange.aStart.Tab(), + aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Col(), aRange.aEnd.Row() ); + } - if (!bDidPaint) - ScUndoUtil::PaintMore( pDocShell, maRange ); + if (bUndo) + DoSdrUndoAction( mpDrawUndo, pDoc ); + else + RedoSdrUndoAction( mpDrawUndo ); + + bool bDidPaint = false; + if ( pViewShell ) + { + pViewShell->SetTabNo(nTab); + bDidPaint = pViewShell->AdjustRowHeight(maOption.mnStartRow, maOption.mnEndRow); + } + + if (!bDidPaint) + ScUndoUtil::PaintMore(pDocShell, aRange); + } - ShowTable( maRange ); + ShowTable(aCurRange); } diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx index dea7cc056756..764c3b6c671d 100644 --- a/sc/source/ui/unoobj/cellsuno.cxx +++ b/sc/source/ui/unoobj/cellsuno.cxx @@ -68,6 +68,7 @@ #include <com/sun/star/text/WritingMode2.hpp> #include "autoform.hxx" +#include "cellmergeoption.hxx" #include "cellsuno.hxx" #include "cursuno.hxx" #include "textuno.hxx" @@ -5342,10 +5343,14 @@ void SAL_CALL ScCellRangeObj::merge( sal_Bool bMerge ) throw(uno::RuntimeExcepti if ( pDocSh ) { ScDocFunc aFunc(*pDocSh); + ScCellMergeOption aMergeOption( + aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Col(), aRange.aEnd.Row(), false); + aMergeOption.maTabs.insert(aRange.aStart.Tab()); if ( bMerge ) - aFunc.MergeCells( aRange, FALSE, TRUE, TRUE ); + aFunc.MergeCells( aMergeOption, FALSE, TRUE, TRUE ); else - aFunc.UnmergeCells( aRange, TRUE, TRUE ); + aFunc.UnmergeCells( aMergeOption, TRUE, TRUE ); //! Fehler abfangen? } diff --git a/sc/source/ui/view/cellmergeoption.cxx b/sc/source/ui/view/cellmergeoption.cxx new file mode 100644 index 000000000000..da531966cb19 --- /dev/null +++ b/sc/source/ui/view/cellmergeoption.cxx @@ -0,0 +1,74 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2010 by Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: docfunc.hxx,v $ + * $Revision: 1.18.30.2 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "cellmergeoption.hxx" +#include "address.hxx" + +ScCellMergeOption::ScCellMergeOption() : + mnStartCol(0), + mnStartRow(0), + mnEndCol(0), + mnEndRow(0), + mbCenter(false) +{ +} + +ScCellMergeOption::ScCellMergeOption(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, bool bCenter) : + mnStartCol(nStartCol), + mnStartRow(nStartRow), + mnEndCol(nEndCol), + mnEndRow(nEndRow), + mbCenter(bCenter) +{ +} + +ScCellMergeOption::ScCellMergeOption(const ScCellMergeOption& r) : + maTabs(r.maTabs), + mnStartCol(r.mnStartCol), + mnStartRow(r.mnStartRow), + mnEndCol(r.mnEndCol), + mnEndRow(r.mnEndRow), + mbCenter(r.mbCenter) +{ +} + +ScRange ScCellMergeOption::getSingleRange(SCTAB nTab) const +{ + return ScRange(mnStartCol, mnStartRow, nTab, mnEndCol, mnEndRow, nTab); +} + +ScRange ScCellMergeOption::getFirstSingleRange() const +{ + SCTAB nTab = 0; + if (!maTabs.empty()) + nTab = *maTabs.begin(); + + return getSingleRange(nTab); +} diff --git a/sc/source/ui/view/cellsh3.cxx b/sc/source/ui/view/cellsh3.cxx index ed391f154892..f8985748302c 100644 --- a/sc/source/ui/view/cellsh3.cxx +++ b/sc/source/ui/view/cellsh3.cxx @@ -769,6 +769,7 @@ void ScCellShell::Execute( SfxRequest& rReq ) { // test whether to merge or to split bool bMerge = false; + BOOL bCenter = FALSE; switch( nSlot ) { case FID_MERGE_ON: @@ -779,6 +780,7 @@ void ScCellShell::Execute( SfxRequest& rReq ) break; case FID_MERGE_TOGGLE: { + bCenter = TRUE; SfxPoolItem* pItem = 0; if( rBindings.QueryState( nSlot, pItem ) >= SFX_ITEM_DEFAULT ) bMerge = !static_cast< SfxBoolItem* >( pItem )->GetValue(); @@ -799,7 +801,7 @@ void ScCellShell::Execute( SfxRequest& rReq ) bMoveContents = ((const SfxBoolItem*)pItem)->GetValue(); } - if (pTabViewShell->MergeCells( bApi, bMoveContents )) + if (pTabViewShell->MergeCells( bApi, bMoveContents, TRUE, bCenter )) { if (!bApi && bMoveContents) // "ja" im Dialog geklickt rReq.AppendItem( SfxBoolItem( nSlot, bMoveContents ) ); diff --git a/sc/source/ui/view/makefile.mk b/sc/source/ui/view/makefile.mk index 1b2fef913fc2..521c5bda91fc 100644 --- a/sc/source/ui/view/makefile.mk +++ b/sc/source/ui/view/makefile.mk @@ -96,6 +96,7 @@ SLOFILES = \ $(SLO)$/output3.obj \ $(SLO)$/gridmerg.obj \ $(SLO)$/invmerge.obj \ + $(SLO)$/cellmergeoption.obj \ $(SLO)$/select.obj \ $(SLO)$/olinewin.obj \ $(SLO)$/hintwin.obj \ diff --git a/sc/source/ui/view/viewfun2.cxx b/sc/source/ui/view/viewfun2.cxx index a125cbea6f50..d3a83ad6bde5 100644 --- a/sc/source/ui/view/viewfun2.cxx +++ b/sc/source/ui/view/viewfun2.cxx @@ -60,6 +60,7 @@ #include "attrib.hxx" #include "autoform.hxx" #include "cell.hxx" // EnterAutoSum +#include "cellmergeoption.hxx" #include "compiler.hxx" #include "docfunc.hxx" #include "docpool.hxx" @@ -1085,7 +1086,7 @@ BOOL ScViewFunc::TestMergeCells() // Vorab-Test (fuer Menue) //---------------------------------------------------------------------------- -BOOL ScViewFunc::MergeCells( BOOL bApi, BOOL& rDoContents, BOOL bRecord ) +BOOL ScViewFunc::MergeCells( BOOL bApi, BOOL& rDoContents, BOOL bRecord, BOOL bCenter ) { // Editable- und Verschachtelungs-Abfrage muss vorneweg sein (auch in DocFunc), // damit dann nicht die Inhalte-QueryBox kommt @@ -1128,10 +1129,26 @@ BOOL ScViewFunc::MergeCells( BOOL bApi, BOOL& rDoContents, BOOL bRecord ) return FALSE; } + // Check for the contents of all selected tables. + bool bAskDialog = false; + SCTAB nTabCount = pDoc->GetTableCount(); + ScCellMergeOption aMergeOption(nStartCol, nStartRow, nEndCol, nEndRow, bCenter); + for (SCTAB i = 0; i < nTabCount; ++i) + { + if (!rMark.GetTableSelect(i)) + // this table is not selected. + continue; + + aMergeOption.maTabs.insert(i); + + if (!pDoc->IsBlockEmpty(i, nStartCol, nStartRow+1, nStartCol, nEndRow) || + !pDoc->IsBlockEmpty(i, nStartCol+1, nStartRow, nEndCol, nEndRow)) + bAskDialog = true; + } + BOOL bOk = TRUE; - if ( !pDoc->IsBlockEmpty( nStartTab, nStartCol,nStartRow+1, nStartCol,nEndRow, true ) || - !pDoc->IsBlockEmpty( nStartTab, nStartCol+1,nStartRow, nEndCol,nEndRow, true ) ) + if (bAskDialog) { if (!bApi) { @@ -1151,7 +1168,7 @@ BOOL ScViewFunc::MergeCells( BOOL bApi, BOOL& rDoContents, BOOL bRecord ) if (bOk) { HideCursor(); - bOk = pDocSh->GetDocFunc().MergeCells( aMarkRange, rDoContents, bRecord, bApi ); + bOk = pDocSh->GetDocFunc().MergeCells( aMergeOption, rDoContents, bRecord, bApi ); ShowCursor(); if (bOk) @@ -1187,6 +1204,32 @@ BOOL ScViewFunc::TestRemoveMerge() //---------------------------------------------------------------------------- +static bool lcl_extendMergeRange(ScCellMergeOption& rOption, const ScRange& rRange) +{ + bool bExtended = false; + if (rOption.mnStartCol > rRange.aStart.Col()) + { + rOption.mnStartCol = rRange.aStart.Col(); + bExtended = true; + } + if (rOption.mnStartRow > rRange.aStart.Row()) + { + rOption.mnStartRow = rRange.aStart.Row(); + bExtended = true; + } + if (rOption.mnEndCol < rRange.aEnd.Col()) + { + rOption.mnEndCol = rRange.aEnd.Col(); + bExtended = true; + } + if (rOption.mnEndRow < rRange.aEnd.Row()) + { + rOption.mnEndRow = rRange.aEnd.Row(); + bExtended = true; + } + return bExtended; +} + BOOL ScViewFunc::RemoveMerge( BOOL bRecord ) { ScRange aRange; @@ -1198,12 +1241,39 @@ BOOL ScViewFunc::RemoveMerge( BOOL bRecord ) } else if (GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE) { + ScDocument* pDoc = GetViewData()->GetDocument(); ScRange aExtended( aRange ); - GetViewData()->GetDocument()->ExtendMerge( aExtended ); + pDoc->ExtendMerge( aExtended ); ScDocShell* pDocSh = GetViewData()->GetDocShell(); + const ScMarkData& rMark = GetViewData()->GetMarkData(); + SCTAB nTabCount = pDoc->GetTableCount(); + ScCellMergeOption aOption(aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row()); + bool bExtended = false; + do + { + bExtended = false; + for (SCTAB i = 0; i < nTabCount; ++i) + { + if (!rMark.GetTableSelect(i)) + // This table is not selected. + continue; + + aOption.maTabs.insert(i); + aExtended.aStart.SetTab(i); + aExtended.aEnd.SetTab(i); + pDoc->ExtendMerge(aExtended); + pDoc->ExtendOverlapped(aExtended); + + // Expand the current range to be inclusive of all merged + // areas on all sheets. + bExtended = lcl_extendMergeRange(aOption, aExtended); + } + } + while (bExtended); HideCursor(); - BOOL bOk = pDocSh->GetDocFunc().UnmergeCells( aRange, bRecord, FALSE ); + BOOL bOk = pDocSh->GetDocFunc().UnmergeCells(aOption, bRecord, FALSE ); + aExtended = aOption.getFirstSingleRange(); MarkRange( aExtended ); ShowCursor(); diff --git a/sc/uiconfig/scalc/menubar/menubar.xml b/sc/uiconfig/scalc/menubar/menubar.xml index 9132cc2d647f..959e5384ac75 100644 --- a/sc/uiconfig/scalc/menubar/menubar.xml +++ b/sc/uiconfig/scalc/menubar/menubar.xml @@ -220,7 +220,13 @@ <menu:menuitem menu:id=".uno:SetTabBgColor"/> </menu:menupopup> </menu:menu> - <menu:menuitem menu:id=".uno:ToggleMergeCells"/> + <menu:menu menu:id=".uno:MergeCellsMenu"> + <menu:menupopup> + <menu:menuitem menu:id=".uno:ToggleMergeCells"/> + <menu:menuitem menu:id=".uno:MergeCells"/> + <menu:menuitem menu:id=".uno:SplitCell"/> + </menu:menupopup> + </menu:menu> <menu:menuseparator/> <menu:menuitem menu:id=".uno:PageFormatDialog"/> <menu:menu menu:id=".uno:PrintRangesMenu"> |