diff options
Diffstat (limited to 'sc/source/ui/view')
84 files changed, 74980 insertions, 0 deletions
diff --git a/sc/source/ui/view/auditsh.cxx b/sc/source/ui/view/auditsh.cxx new file mode 100644 index 000000000000..12851346be2e --- /dev/null +++ b/sc/source/ui/view/auditsh.cxx @@ -0,0 +1,155 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +//------------------------------------------------------------------ + +#include "scitems.hxx" +#include <svl/srchitem.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/objface.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/request.hxx> + +#include "auditsh.hxx" +#include "tabvwsh.hxx" +#include "scresid.hxx" +#include "sc.hrc" +#include "document.hxx" + +//------------------------------------------------------------------------ + +#define ScAuditingShell +#include "scslots.hxx" + +//------------------------------------------------------------------------ + +TYPEINIT1( ScAuditingShell, SfxShell ); + +SFX_IMPL_INTERFACE(ScAuditingShell, SfxShell, ScResId(SCSTR_AUDITSHELL)) +{ + SFX_POPUPMENU_REGISTRATION( ScResId(RID_POPUP_AUDIT) ); +} + + +//------------------------------------------------------------------------ + +ScAuditingShell::ScAuditingShell(ScViewData* pData) : + SfxShell(pData->GetViewShell()), + pViewData( pData ), + nFunction( SID_FILL_ADD_PRED ) +{ + SetPool( &pViewData->GetViewShell()->GetPool() ); + ::svl::IUndoManager* pMgr = pViewData->GetSfxDocShell()->GetUndoManager(); + SetUndoManager( pMgr ); + if ( !pViewData->GetDocument()->IsUndoEnabled() ) + { + pMgr->SetMaxUndoActionCount( 0 ); + } + SetHelpId( HID_SCSHELL_AUDIT ); + SetName(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Auditing"))); +} + +//------------------------------------------------------------------------ + +ScAuditingShell::~ScAuditingShell() +{ +} + +//------------------------------------------------------------------------ + +void ScAuditingShell::Execute( SfxRequest& rReq ) +{ + SfxBindings& rBindings = pViewData->GetBindings(); + sal_uInt16 nSlot = rReq.GetSlot(); + switch ( nSlot ) + { + case SID_FILL_ADD_PRED: + case SID_FILL_DEL_PRED: + case SID_FILL_ADD_SUCC: + case SID_FILL_DEL_SUCC: + nFunction = nSlot; + rBindings.Invalidate( SID_FILL_ADD_PRED ); + rBindings.Invalidate( SID_FILL_DEL_PRED ); + rBindings.Invalidate( SID_FILL_ADD_SUCC ); + rBindings.Invalidate( SID_FILL_DEL_SUCC ); + break; + case SID_CANCEL: // Escape + case SID_FILL_NONE: + pViewData->GetViewShell()->SetAuditShell( sal_False ); + break; + + case SID_FILL_SELECT: + { + const SfxItemSet* pReqArgs = rReq.GetArgs(); + if ( pReqArgs ) + { + const SfxPoolItem* pXItem; + const SfxPoolItem* pYItem; + if ( pReqArgs->GetItemState( SID_RANGE_COL, sal_True, &pXItem ) == SFX_ITEM_SET + && pReqArgs->GetItemState( SID_RANGE_ROW, sal_True, &pYItem ) == SFX_ITEM_SET ) + { + DBG_ASSERT( pXItem->ISA(SfxInt16Item) && pYItem->ISA(SfxInt32Item), + "falsche Items" ); + SCsCOL nCol = static_cast<SCsCOL>(((const SfxInt16Item*) pXItem)->GetValue()); + SCsROW nRow = static_cast<SCsROW>(((const SfxInt32Item*) pYItem)->GetValue()); + ScViewFunc* pView = pViewData->GetView(); + pView->MoveCursorAbs( nCol, nRow, SC_FOLLOW_LINE, sal_False, sal_False ); + switch ( nFunction ) + { + case SID_FILL_ADD_PRED: + pView->DetectiveAddPred(); + break; + case SID_FILL_DEL_PRED: + pView->DetectiveDelPred(); + break; + case SID_FILL_ADD_SUCC: + pView->DetectiveAddSucc(); + break; + case SID_FILL_DEL_SUCC: + pView->DetectiveDelSucc(); + break; + } + } + } + } + break; + } +} + +//------------------------------------------------------------------------ + +void ScAuditingShell::GetState( SfxItemSet& rSet ) +{ + rSet.Put( SfxBoolItem( nFunction, sal_True ) ); // aktive Funktion markieren +} + + diff --git a/sc/source/ui/view/cellsh.cxx b/sc/source/ui/view/cellsh.cxx new file mode 100644 index 000000000000..20f65bd03e93 --- /dev/null +++ b/sc/source/ui/view/cellsh.cxx @@ -0,0 +1,1002 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +//------------------------------------------------------------------ + +#include "scitems.hxx" + +#include <svl/slstitm.hxx> +#include <svl/stritem.hxx> +#include <svl/whiter.hxx> +#include <unotools/moduleoptions.hxx> +#include <svtools/cliplistener.hxx> +#include <svtools/insdlg.hxx> +#include <sot/formats.hxx> +#include <svx/hlnkitem.hxx> +#include <sfx2/app.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/childwin.hxx> +#include <sfx2/objface.hxx> +#include <sfx2/request.hxx> +#include <sfx2/viewfrm.hxx> +#include <svx/clipfmtitem.hxx> +#include <editeng/langitem.hxx> + +#include "cellsh.hxx" +#include "sc.hrc" +#include "docsh.hxx" +#include "attrib.hxx" +#include "scresid.hxx" +#include "tabvwsh.hxx" +#include "impex.hxx" +#include "cell.hxx" +#include "scmod.hxx" +#include "globstr.hrc" +#include "transobj.hxx" +#include "drwtrans.hxx" +#include "scabstdlg.hxx" +#include "dociter.hxx" +#include "postit.hxx" + +//------------------------------------------------------------------ + +#define ScCellShell +#define CellMovement +#include "scslots.hxx" + +TYPEINIT1( ScCellShell, ScFormatShell ); + +SFX_IMPL_INTERFACE(ScCellShell, ScFormatShell , ScResId(SCSTR_CELLSHELL) ) +{ + SFX_OBJECTBAR_REGISTRATION( SFX_OBJECTBAR_OBJECT | SFX_VISIBILITY_STANDARD | + SFX_VISIBILITY_SERVER, + ScResId(RID_OBJECTBAR_FORMAT)); + SFX_POPUPMENU_REGISTRATION(ScResId(RID_POPUP_CELLS)); +} + + +ScCellShell::ScCellShell(ScViewData* pData) : + ScFormatShell(pData), + pImpl( new CellShell_Impl() ), + bPastePossible(sal_False) +{ + SetHelpId(HID_SCSHELL_CELLSH); + SetName(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Cell"))); +} + +ScCellShell::~ScCellShell() +{ + if ( pImpl->m_pClipEvtLstnr ) + { + pImpl->m_pClipEvtLstnr->AddRemoveListener( GetViewData()->GetActiveWin(), sal_False ); + + // #103849# The listener may just now be waiting for the SolarMutex and call the link + // afterwards, in spite of RemoveListener. So the link has to be reset, too. + pImpl->m_pClipEvtLstnr->ClearCallbackLink(); + + pImpl->m_pClipEvtLstnr->release(); + } + + delete pImpl->m_pLinkedDlg; + delete pImpl->m_pRequest; + delete pImpl; +} + +//------------------------------------------------------------------ + +void ScCellShell::GetBlockState( SfxItemSet& rSet ) +{ + ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell(); + ScRange aMarkRange; + ScMarkType eMarkType = GetViewData()->GetSimpleArea( aMarkRange ); + sal_Bool bSimpleArea = (eMarkType == SC_MARK_SIMPLE); + sal_Bool bOnlyNotBecauseOfMatrix; + sal_Bool bEditable = pTabViewShell->SelectionEditable( &bOnlyNotBecauseOfMatrix ); + ScDocument* pDoc = GetViewData()->GetDocument(); + ScDocShell* pDocShell = GetViewData()->GetDocShell(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + SCCOL nCol1, nCol2; + SCROW nRow1, nRow2; + nCol1 = aMarkRange.aStart.Col(); + nRow1 = aMarkRange.aStart.Row(); + nCol2 = aMarkRange.aEnd.Col(); + nRow2 = aMarkRange.aEnd.Row(); + + SfxWhichIter aIter(rSet); + sal_uInt16 nWhich = aIter.FirstWhich(); + while ( nWhich ) + { + sal_Bool bDisable = sal_False; + sal_Bool bNeedEdit = sal_True; // muss Selektion editierbar sein? + switch ( nWhich ) + { + case FID_FILL_TO_BOTTOM: // Fuellen oben/unten + case FID_FILL_TO_TOP: // mind. 2 Zeilen markiert? + bDisable = (!bSimpleArea) || (nRow1 == nRow2); + if ( !bDisable && bEditable ) + { // Matrix nicht zerreissen + if ( nWhich == FID_FILL_TO_BOTTOM ) + bDisable = pDoc->HasSelectedBlockMatrixFragment( + nCol1, nRow1, nCol2, nRow1, rMark ); // erste Zeile + else + bDisable = pDoc->HasSelectedBlockMatrixFragment( + nCol1, nRow2, nCol2, nRow2, rMark ); // letzte Zeile + } + break; + + case FID_FILL_TO_RIGHT: // Fuellen links/rechts + case FID_FILL_TO_LEFT: // mind. 2 Spalten markiert? + bDisable = (!bSimpleArea) || (nCol1 == nCol2); + if ( !bDisable && bEditable ) + { // Matrix nicht zerreissen + if ( nWhich == FID_FILL_TO_RIGHT ) + bDisable = pDoc->HasSelectedBlockMatrixFragment( + nCol1, nRow1, nCol1, nRow2, rMark ); // erste Spalte + else + bDisable = pDoc->HasSelectedBlockMatrixFragment( + nCol2, nRow1, nCol2, nRow2, rMark ); // letzte Spalte + } + break; + + case FID_FILL_SERIES: // Block fuellen + case SID_OPENDLG_TABOP: // Mehrfachoperationen, mind. 2 Zellen markiert? + if (pDoc->GetChangeTrack()!=NULL &&nWhich ==SID_OPENDLG_TABOP) + bDisable = sal_True; + else + bDisable = (!bSimpleArea) || (nCol1 == nCol2 && nRow1 == nRow2); + + if ( !bDisable && bEditable && nWhich == FID_FILL_SERIES ) + { // Matrix nicht zerreissen + bDisable = pDoc->HasSelectedBlockMatrixFragment( + nCol1, nRow1, nCol2, nRow1, rMark ) // erste Zeile + || pDoc->HasSelectedBlockMatrixFragment( + nCol1, nRow2, nCol2, nRow2, rMark ) // letzte Zeile + || pDoc->HasSelectedBlockMatrixFragment( + nCol1, nRow1, nCol1, nRow2, rMark ) // erste Spalte + || pDoc->HasSelectedBlockMatrixFragment( + nCol2, nRow1, nCol2, nRow2, rMark ); // letzte Spalte + } + break; + + case SID_CUT: // Ausschneiden, + case FID_INS_CELL: // Zellen einfuegen, nur einf. Selektion + bDisable = (!bSimpleArea); + break; + + case FID_INS_ROW: // insert rows + case FID_INS_CELLSDOWN: + bDisable = (!bSimpleArea) || GetViewData()->SimpleColMarked(); + break; + + case FID_INS_COLUMN: // insert columns + case FID_INS_CELLSRIGHT: + bDisable = (!bSimpleArea) || GetViewData()->SimpleRowMarked(); + break; + + case SID_COPY: // Kopieren + // nur wegen Matrix nicht editierbar? Matrix nicht zerreissen + //! schlaegt nicht zu, wenn geschuetzt UND Matrix, aber damit + //! muss man leben.. wird in Copy-Routine abgefangen, sonst + //! muesste hier nochmal Aufwand getrieben werden + if ( !(!bEditable && bOnlyNotBecauseOfMatrix) ) + bNeedEdit = sal_False; // erlaubt, wenn geschuetzt/ReadOnly + break; + + case SID_AUTOFORMAT: // Autoformat, mind. 3x3 selektiert + bDisable = (!bSimpleArea) + || ((nCol2 - nCol1) < 2) || ((nRow2 - nRow1) < 2); + break; + + case SID_OPENDLG_CONDFRMT : + { + if ( !bEditable && bOnlyNotBecauseOfMatrix ) + { + bNeedEdit = sal_False; + } + if ( pDocShell && pDocShell->IsDocShared() ) + { + bDisable = sal_True; + } + } + break; + + case FID_CONDITIONAL_FORMAT : + case SID_CELL_FORMAT_RESET : + case FID_CELL_FORMAT : + case SID_ENABLE_HYPHENATION : + // nur wegen Matrix nicht editierbar? Attribute trotzdem ok + if ( !bEditable && bOnlyNotBecauseOfMatrix ) + bNeedEdit = sal_False; + break; + + case FID_VALIDATION: + { + if ( pDocShell && pDocShell->IsDocShared() ) + { + bDisable = sal_True; + } + } + break; + + case SID_TRANSLITERATE_HALFWIDTH: + case SID_TRANSLITERATE_FULLWIDTH: + case SID_TRANSLITERATE_HIRAGANA: + case SID_TRANSLITERATE_KATAGANA: + ScViewUtil::HideDisabledSlot( rSet, GetViewData()->GetBindings(), nWhich ); + break; + } + if (!bDisable && bNeedEdit && !bEditable) + bDisable = sal_True; + + if (bDisable) + rSet.DisableItem(nWhich); + else if (nWhich == SID_ENABLE_HYPHENATION) + { + // toggle slots need a bool item + rSet.Put( SfxBoolItem( nWhich, sal_False ) ); + } + nWhich = aIter.NextWhich(); + } +} + +// Funktionen, die je nach Cursorposition disabled sind +// Default: +// SID_INSERT_POSTIT, SID_CHARMAP, SID_OPENDLG_FUNCTION + +void ScCellShell::GetCellState( SfxItemSet& rSet ) +{ + ScDocShell* pDocShell = GetViewData()->GetDocShell(); + ScDocument* pDoc = GetViewData()->GetDocShell()->GetDocument(); + ScAddress aCursor( GetViewData()->GetCurX(), GetViewData()->GetCurY(), + GetViewData()->GetTabNo() ); + + SfxWhichIter aIter(rSet); + sal_uInt16 nWhich = aIter.FirstWhich(); + while ( nWhich ) + { + sal_Bool bDisable = sal_False; + sal_Bool bNeedEdit = sal_True; // muss Cursorposition editierbar sein? + switch ( nWhich ) + { + case SID_THESAURUS: + { + CellType eType = pDoc->GetCellType( aCursor ); + bDisable = ( eType != CELLTYPE_STRING && eType != CELLTYPE_EDIT); + if (!bDisable) + { + // test for available languages + sal_uInt16 nLang = ScViewUtil::GetEffLanguage( pDoc, aCursor ); + bDisable = !ScModule::HasThesaurusLanguage( nLang ); + } + } + break; + case SID_OPENDLG_FUNCTION: + { + ScMarkData aMarkData=GetViewData()->GetMarkData(); + aMarkData.MarkToSimple(); + ScRange aRange; + aMarkData.GetMarkArea(aRange); + if(aMarkData.IsMarked()) + { + if (!pDoc->IsBlockEditable( aCursor.Tab(), aRange.aStart.Col(),aRange.aStart.Row(), + aRange.aEnd.Col(),aRange.aEnd.Row() )) + { + bDisable = sal_True; + } + bNeedEdit=sal_False; + } + + } + break; + case SID_INSERT_POSTIT: + { + if ( pDocShell && pDocShell->IsDocShared() ) + { + bDisable = sal_True; + } + } + break; + } + if (!bDisable && bNeedEdit) + if (!pDoc->IsBlockEditable( aCursor.Tab(), aCursor.Col(),aCursor.Row(), + aCursor.Col(),aCursor.Row() )) + bDisable = sal_True; + if (bDisable) + rSet.DisableItem(nWhich); + nWhich = aIter.NextWhich(); + } +} + +sal_Bool lcl_TestFormat( SvxClipboardFmtItem& rFormats, const TransferableDataHelper& rDataHelper, + SotFormatStringId nFormatId ) +{ + if ( rDataHelper.HasFormat( nFormatId ) ) + { + // #90675# translated format name strings are no longer inserted here, + // handled by "paste special" dialog / toolbox controller instead. + // Only the object type name has to be set here: + String aStrVal; + if ( nFormatId == SOT_FORMATSTR_ID_EMBED_SOURCE ) + { + TransferableObjectDescriptor aDesc; + if ( ((TransferableDataHelper&)rDataHelper).GetTransferableObjectDescriptor( + SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aDesc ) ) + aStrVal = aDesc.maTypeName; + } + else if ( nFormatId == SOT_FORMATSTR_ID_EMBED_SOURCE_OLE + || nFormatId == SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) + { + String aSource; + SvPasteObjectHelper::GetEmbeddedName( rDataHelper, aStrVal, aSource, nFormatId ); + } + + if ( aStrVal.Len() ) + rFormats.AddClipbrdFormat( nFormatId, aStrVal ); + else + rFormats.AddClipbrdFormat( nFormatId ); + + return sal_True; + } + + return sal_False; +} + +void ScCellShell::GetPossibleClipboardFormats( SvxClipboardFmtItem& rFormats ) +{ + Window* pWin = GetViewData()->GetActiveWin(); + sal_Bool bDraw = ( ScDrawTransferObj::GetOwnClipboard( pWin ) != NULL ); + + TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) ); + + lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_DRAWING ); + lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_SVXB ); + lcl_TestFormat( rFormats, aDataHelper, SOT_FORMAT_GDIMETAFILE ); + lcl_TestFormat( rFormats, aDataHelper, SOT_FORMAT_BITMAP ); + lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_EMBED_SOURCE ); + + if ( !bDraw ) + { + lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_LINK ); + lcl_TestFormat( rFormats, aDataHelper, SOT_FORMAT_STRING ); + lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_DIF ); + lcl_TestFormat( rFormats, aDataHelper, SOT_FORMAT_RTF ); + lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_HTML ); + lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_HTML_SIMPLE ); + lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_BIFF_8 ); + lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_BIFF_5 ); + } + + if ( !lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) ) + lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ); +} + +// Einfuegen, Inhalte einfuegen + +sal_Bool lcl_IsCellPastePossible( const TransferableDataHelper& rData ) +{ + sal_Bool bPossible = sal_False; + if ( ScTransferObj::GetOwnClipboard( NULL ) || ScDrawTransferObj::GetOwnClipboard( NULL ) ) + bPossible = sal_True; + else + { + if ( rData.HasFormat( SOT_FORMAT_BITMAP ) || + rData.HasFormat( SOT_FORMAT_GDIMETAFILE ) || + rData.HasFormat( SOT_FORMATSTR_ID_SVXB ) || + rData.HasFormat( FORMAT_PRIVATE ) || + rData.HasFormat( SOT_FORMAT_RTF ) || + rData.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ) || + rData.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) || + rData.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) || + rData.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) || + rData.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) || + rData.HasFormat( SOT_FORMAT_STRING ) || + rData.HasFormat( SOT_FORMATSTR_ID_SYLK ) || + rData.HasFormat( SOT_FORMATSTR_ID_LINK ) || + rData.HasFormat( SOT_FORMATSTR_ID_HTML ) || + rData.HasFormat( SOT_FORMATSTR_ID_HTML_SIMPLE ) || + rData.HasFormat( SOT_FORMATSTR_ID_DIF ) ) + { + bPossible = sal_True; + } + } + return bPossible; +} + +IMPL_LINK( ScCellShell, ClipboardChanged, TransferableDataHelper*, pDataHelper ) +{ + if ( pDataHelper ) + { + bPastePossible = lcl_IsCellPastePossible( *pDataHelper ); + + SfxBindings& rBindings = GetViewData()->GetBindings(); + rBindings.Invalidate( SID_PASTE ); + rBindings.Invalidate( SID_PASTE_SPECIAL ); + rBindings.Invalidate( SID_CLIPBOARD_FORMAT_ITEMS ); + } + return 0; +} + + +void __EXPORT ScCellShell::GetClipState( SfxItemSet& rSet ) +{ +// SID_PASTE +// SID_PASTE_SPECIAL +// SID_CLIPBOARD_FORMAT_ITEMS + + if ( !pImpl->m_pClipEvtLstnr ) + { + // create listener + pImpl->m_pClipEvtLstnr = new TransferableClipboardListener( LINK( this, ScCellShell, ClipboardChanged ) ); + pImpl->m_pClipEvtLstnr->acquire(); + Window* pWin = GetViewData()->GetActiveWin(); + pImpl->m_pClipEvtLstnr->AddRemoveListener( pWin, sal_True ); + + // get initial state + TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) ); + bPastePossible = lcl_IsCellPastePossible( aDataHelper ); + } + + sal_Bool bDisable = !bPastePossible; + + // Zellschutz / Multiselektion + + if (!bDisable) + { + SCCOL nCol = GetViewData()->GetCurX(); + SCROW nRow = GetViewData()->GetCurY(); + SCTAB nTab = GetViewData()->GetTabNo(); + ScDocument* pDoc = GetViewData()->GetDocShell()->GetDocument(); + if (!pDoc->IsBlockEditable( nTab, nCol,nRow, nCol,nRow )) + bDisable = sal_True; + ScRange aDummy; + ScMarkType eMarkType = GetViewData()->GetSimpleArea( aDummy); + if (eMarkType != SC_MARK_SIMPLE && eMarkType != SC_MARK_SIMPLE_FILTERED) + bDisable = sal_True; + } + + if (bDisable) + { + rSet.DisableItem( SID_PASTE ); + rSet.DisableItem( SID_PASTE_SPECIAL ); + rSet.DisableItem( SID_CLIPBOARD_FORMAT_ITEMS ); + } + else if ( rSet.GetItemState( SID_CLIPBOARD_FORMAT_ITEMS ) != SFX_ITEM_UNKNOWN ) + { + SvxClipboardFmtItem aFormats( SID_CLIPBOARD_FORMAT_ITEMS ); + GetPossibleClipboardFormats( aFormats ); + rSet.Put( aFormats ); + } +} + +// only SID_HYPERLINK_GETLINK: + +void ScCellShell::GetHLinkState( SfxItemSet& rSet ) +{ + // always return an item (or inserting will be disabled) + // if the cell at the cursor contains only a link, return that link + + SvxHyperlinkItem aHLinkItem; + if ( !GetViewData()->GetView()->HasBookmarkAtCursor( &aHLinkItem ) ) + { + //! put selected text into item? + } + + rSet.Put(aHLinkItem); +} + +void ScCellShell::GetState(SfxItemSet &rSet) +{ + // removed: SID_BORDER_OBJECT (old Basic) + + ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell(); +// sal_Bool bOle = pTabViewShell->GetViewFrame()->GetFrame().IsInPlace(); +// sal_Bool bTabProt = GetViewData()->GetDocument()->IsTabProtected(GetViewData()->GetTabNo()); + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScViewData* pData = GetViewData(); + ScDocument* pDoc = pData->GetDocument(); + ScMarkData& rMark = pData->GetMarkData(); + SCCOL nPosX = pData->GetCurX(); + SCROW nPosY = pData->GetCurY(); + SCTAB nTab = pData->GetTabNo(); + + SCTAB nTabCount = pDoc->GetTableCount(); + SCTAB nTabSelCount = rMark.GetSelectCount(); + + + + SfxWhichIter aIter(rSet); + sal_uInt16 nWhich = aIter.FirstWhich(); + while ( nWhich ) + { + switch ( nWhich ) + { + case SID_DETECTIVE_REFRESH: + if (!pDoc->HasDetectiveOperations()) + rSet.DisableItem( nWhich ); + break; + + case SID_RANGE_ADDRESS: + { + ScRange aRange; + if ( pData->GetSimpleArea( aRange ) == SC_MARK_SIMPLE ) + { + String aStr; + sal_uInt16 nFlags = SCA_VALID | SCA_TAB_3D; + aRange.Format(aStr,nFlags,pDoc); + rSet.Put( SfxStringItem( nWhich, aStr ) ); + } + } + break; + + case SID_RANGE_NOTETEXT: + { + // #43343# always take cursor position, do not use top-left cell of selection + ScAddress aPos( nPosX, nPosY, nTab ); + String aNoteText; + if ( const ScPostIt* pNote = pDoc->GetNote( aPos ) ) + aNoteText = pNote->GetText(); + rSet.Put( SfxStringItem( nWhich, aNoteText ) ); + } + break; + + case SID_RANGE_ROW: + rSet.Put( SfxInt32Item( nWhich, nPosY+1 ) ); + break; + + case SID_RANGE_COL: + rSet.Put( SfxInt16Item( nWhich, nPosX+1 ) ); + break; + + case SID_RANGE_TABLE: + rSet.Put( SfxInt16Item( nWhich, nTab+1 ) ); + break; + + case SID_RANGE_VALUE: + { + double nValue; + pDoc->GetValue( nPosX, nPosY, nTab, nValue ); + rSet.Put( ScDoubleItem( nWhich, nValue ) ); + } + break; + + case SID_RANGE_FORMULA: + { + String aString; + pDoc->GetFormula( nPosX, nPosY, nTab, aString ); + if( aString.Len() == 0 ) + { + pDoc->GetInputString( nPosX, nPosY, nTab, aString ); + } + rSet.Put( SfxStringItem( nWhich, aString ) ); + } + break; + + case SID_RANGE_TEXTVALUE: + { + String aString; + pDoc->GetString( nPosX, nPosY, nTab, aString ); + rSet.Put( SfxStringItem( nWhich, aString ) ); + } + break; + + case SID_STATUS_SELMODE: + { + /* 0: STD Click hebt Sel auf + * 1: ER Click erweitert Selektion + * 2: ERG Click definiert weitere Selektion + */ + sal_uInt16 nMode = pTabViewShell->GetLockedModifiers(); + + switch ( nMode ) + { + case KEY_SHIFT: nMode = 1; break; + case KEY_MOD1: nMode = 2; break; // Control-Taste + case 0: + default: + nMode = 0; + } + + rSet.Put( SfxUInt16Item( nWhich, nMode ) ); + } + break; + + case SID_STATUS_DOCPOS: + { + String aStr( ScGlobal::GetRscString( STR_TABLE ) ); + + aStr += ' '; + aStr += String::CreateFromInt32( nTab + 1 ); + aStr.AppendAscii(RTL_CONSTASCII_STRINGPARAM( " / " )); + aStr += String::CreateFromInt32( nTabCount ); + rSet.Put( SfxStringItem( nWhich, aStr ) ); + } + break; + + // Summe etc. mit Datum/Zeit/Fehler/Pos&Groesse zusammengefasst + + // #i34458# The SfxStringItem belongs only into SID_TABLE_CELL. It no longer has to be + // duplicated in SID_ATTR_POSITION or SID_ATTR_SIZE for SvxPosSizeStatusBarControl. + case SID_TABLE_CELL: + { + // Testen, ob Fehler unter Cursor + // (nicht pDoc->GetErrCode, um keine zirkulaeren Referenzen auszuloesen) + + // In interpreter may happen via rescheduled Basic + if ( pDoc->IsInInterpreter() ) + rSet.Put( SfxStringItem( nWhich, + String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("...")) ) ); + else + { + sal_uInt16 nErrCode = 0; + ScBaseCell* pCell; + pDoc->GetCell( nPosX, nPosY, nTab, pCell ); + if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA ) + { + ScFormulaCell* pFCell = (ScFormulaCell*) pCell; + if (!pFCell->IsRunning()) + nErrCode = pFCell->GetErrCode(); + } + + String aFuncStr; + if ( pTabViewShell->GetFunction( aFuncStr, nErrCode ) ) + rSet.Put( SfxStringItem( nWhich, aFuncStr ) ); + } + } + break; + + case SID_DATA_SELECT: + // HasSelectionData includes column content and validity, + // page fields have to be checked separately. + if ( !pDoc->HasSelectionData( nPosX, nPosY, nTab ) && + !pTabViewShell->HasPageFieldDataAtCursor() ) + rSet.DisableItem( nWhich ); + break; + + case SID_STATUS_SUM: + { + String aFuncStr; + if ( pTabViewShell->GetFunction( aFuncStr ) ) + rSet.Put( SfxStringItem( nWhich, aFuncStr ) ); + } + break; + + case FID_MERGE_ON: + if ( pDoc->GetChangeTrack() || !pTabViewShell->TestMergeCells() ) + rSet.DisableItem( nWhich ); + break; + + case FID_MERGE_OFF: + if ( pDoc->GetChangeTrack() || !pTabViewShell->TestRemoveMerge() ) + rSet.DisableItem( nWhich ); + break; + + case FID_MERGE_TOGGLE: + if ( pDoc->GetChangeTrack() ) + rSet.DisableItem( nWhich ); + else + { + bool bCanMerge = pTabViewShell->TestMergeCells(); + bool bCanSplit = pTabViewShell->TestRemoveMerge(); + if( !bCanMerge && !bCanSplit ) + rSet.DisableItem( nWhich ); + else + rSet.Put( SfxBoolItem( nWhich, bCanSplit ) ); + } + break; + + case FID_INS_ROWBRK: + if ( nPosY==0 || (pDoc->HasRowBreak(nPosY, nTab) & BREAK_MANUAL) ) + rSet.DisableItem( nWhich ); + break; + + case FID_INS_COLBRK: + if ( nPosX==0 || (pDoc->HasColBreak(nPosX, nTab) & BREAK_MANUAL) ) + rSet.DisableItem( nWhich ); + break; + + case FID_DEL_ROWBRK: + if ( nPosY==0 || (pDoc->HasRowBreak(nPosY, nTab) & BREAK_MANUAL) == 0 ) + rSet.DisableItem( nWhich ); + break; + + case FID_DEL_COLBRK: + if ( nPosX==0 || (pDoc->HasColBreak(nPosX, nTab) & BREAK_MANUAL) == 0 ) + rSet.DisableItem( nWhich ); + break; + + case FID_FILL_TAB: + if ( nTabSelCount < 2 ) + rSet.DisableItem( nWhich ); + break; + + case SID_SELECT_SCENARIO: + { + // ScDocument* pDoc = GetViewData()->GetDocument(); + // SCTAB nTab = GetViewData()->GetTabNo(); + List aList; + + Color aDummyCol; + + if ( !pDoc->IsScenario(nTab) ) + { + String aStr; + sal_uInt16 nFlags; + SCTAB nScTab = nTab + 1; + String aProtect; + bool bSheetProtected = pDoc->IsTabProtected(nTab); + + while ( pDoc->IsScenario(nScTab) ) + { + pDoc->GetName( nScTab, aStr ); + aList.Insert( new String( aStr ), LIST_APPEND ); + pDoc->GetScenarioData( nScTab, aStr, aDummyCol, nFlags ); + aList.Insert( new String( aStr ), LIST_APPEND ); + // Protection is sal_True if both Sheet and Scenario are protected + aProtect = (bSheetProtected && (nFlags & SC_SCENARIO_PROTECT)) ? '1' : '0'; + aList.Insert( new String( aProtect), LIST_APPEND ); + ++nScTab; + } + } + else + { + String aComment; + sal_uInt16 nDummyFlags; + pDoc->GetScenarioData( nTab, aComment, aDummyCol, nDummyFlags ); + DBG_ASSERT( aList.Count() == 0, "List not empty!" ); + aList.Insert( new String( aComment ) ); + } + + rSet.Put( SfxStringListItem( nWhich, &aList ) ); + + sal_uLong nCount = aList.Count(); + for ( sal_uLong i=0; i<nCount; i++ ) + delete (String*) aList.GetObject(i); + } + break; + + case FID_ROW_HIDE: + case FID_ROW_SHOW: + case FID_COL_HIDE: + case FID_COL_SHOW: + case FID_COL_OPT_WIDTH: + case FID_ROW_OPT_HEIGHT: + case FID_DELETE_CELL: + if ( pDoc->IsTabProtected(nTab) || pDocSh->IsReadOnly()) + rSet.DisableItem( nWhich ); + break; + +/* Zellschutz bei selektierten Zellen wird bei anderen Funktionen auch nicht abgefragt... + case SID_DELETE: + { + if ( pDoc->IsTabProtected(nTab) ) + { + const SfxItemSet& rAttrSet = GetSelectionPattern()->GetItemSet(); + const ScProtectionAttr& rProtAttr = (const ScProtectionAttr&)rAttrSet.Get( ATTR_PROTECTION, sal_True ); + if ( rProtAttr.GetProtection() ) + rSet.DisableItem( nWhich ); + } + } + break; +*/ + case SID_OUTLINE_MAKE: + { + if ( GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(), + GetViewData()->GetCurY(), GetViewData()->GetTabNo() ) ) + { + //! test for data pilot operation + } + else if (pDoc->GetChangeTrack()!=NULL || GetViewData()->IsMultiMarked()) + { + rSet.DisableItem( nWhich ); + } + } + break; + case SID_OUTLINE_SHOW: + if ( GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(), + GetViewData()->GetCurY(), GetViewData()->GetTabNo() ) ) + { + //! test for data pilot operation + } + else if (!pTabViewShell->OutlinePossible(sal_False)) + rSet.DisableItem( nWhich ); + break; + + case SID_OUTLINE_HIDE: + if ( GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(), + GetViewData()->GetCurY(), GetViewData()->GetTabNo() ) ) + { + //! test for data pilot operation + } + else if (!pTabViewShell->OutlinePossible(sal_True)) + rSet.DisableItem( nWhich ); + break; + + case SID_OUTLINE_REMOVE: + { + if ( GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(), + GetViewData()->GetCurY(), GetViewData()->GetTabNo() ) ) + { + //! test for data pilot operation + } + else + { + sal_Bool bCol, bRow; + pTabViewShell->TestRemoveOutline( bCol, bRow ); + if ( !bCol && !bRow ) + rSet.DisableItem( nWhich ); + } + } + break; + + case FID_COL_WIDTH: + { + //GetViewData()->GetCurX(); + SfxUInt16Item aWidthItem( FID_COL_WIDTH, pDoc->GetColWidth( nPosX , nTab) ); + rSet.Put( aWidthItem ); + if ( pDocSh->IsReadOnly()) + rSet.DisableItem( nWhich ); + + //XXX Disablen wenn nicht eindeutig + } + break; + + case FID_ROW_HEIGHT: + { + //GetViewData()->GetCurY(); + SfxUInt16Item aHeightItem( FID_ROW_HEIGHT, pDoc->GetRowHeight( nPosY , nTab) ); + rSet.Put( aHeightItem ); + //XXX Disablen wenn nicht eindeutig + if ( pDocSh->IsReadOnly()) + rSet.DisableItem( nWhich ); + } + break; + + case SID_DETECTIVE_FILLMODE: + rSet.Put(SfxBoolItem( nWhich, pTabViewShell->IsAuditShell() )); + break; + + case FID_INPUTLINE_STATUS: + DBG_ERROR( "Old update method. Use ScTabViewShell::UpdateInputHandler()." ); + break; + + case SID_SCENARIOS: // Szenarios: + if (!(rMark.IsMarked() || rMark.IsMultiMarked())) // nur, wenn etwas selektiert + rSet.DisableItem( nWhich ); + break; + + case FID_NOTE_VISIBLE: + { + const ScPostIt* pNote = pDoc->GetNote( ScAddress( nPosX, nPosY, nTab ) ); + if ( pNote && pDoc->IsBlockEditable( nTab, nPosX,nPosY, nPosX,nPosY ) ) + rSet.Put( SfxBoolItem( nWhich, pNote->IsCaptionShown() ) ); + else + rSet.DisableItem( nWhich ); + } + break; + + case SID_DELETE_NOTE: + { + sal_Bool bEnable = sal_False; + if ( rMark.IsMarked() || rMark.IsMultiMarked() ) + { + if ( pDoc->IsSelectionEditable( rMark ) ) + { + // look for at least one note in selection + ScRangeList aRanges; + rMark.FillRangeListWithMarks( &aRanges, sal_False ); + sal_uLong nCount = aRanges.Count(); + for (sal_uLong nPos=0; nPos<nCount && !bEnable; nPos++) + { + ScCellIterator aCellIter( pDoc, *aRanges.GetObject(nPos) ); + for( ScBaseCell* pCell = aCellIter.GetFirst(); pCell && !bEnable; pCell = aCellIter.GetNext() ) + if ( pCell->HasNote() ) + bEnable = sal_True; // note found + } + } + } + else + { + bEnable = pDoc->IsBlockEditable( nTab, nPosX,nPosY, nPosX,nPosY ) && + pDoc->GetNote( ScAddress( nPosX, nPosY, nTab ) ); + } + if ( !bEnable ) + rSet.DisableItem( nWhich ); + } + break; + + case SID_OPENDLG_CONSOLIDATE: + case SCITEM_CONSOLIDATEDATA: + { + if(pDoc->GetChangeTrack()!=NULL) + rSet.DisableItem( nWhich); + } + break; + + case SID_CHINESE_CONVERSION: + case SID_HANGUL_HANJA_CONVERSION: + ScViewUtil::HideDisabledSlot( rSet, pData->GetBindings(), nWhich ); + break; + + case FID_USE_NAME: + { + if ( pDocSh && pDocSh->IsDocShared() ) + rSet.DisableItem( nWhich ); + else + { + ScRange aRange; + if ( pData->GetSimpleArea( aRange ) != SC_MARK_SIMPLE ) + rSet.DisableItem( nWhich ); + } + } + break; + + case FID_DEFINE_NAME: + case FID_INSERT_NAME: + case SID_DEFINE_COLROWNAMERANGES: + { + if ( pDocSh && pDocSh->IsDocShared() ) + { + rSet.DisableItem( nWhich ); + } + } + break; + + case SID_SPELL_DIALOG: + { + if ( pDoc && pData && pDoc->IsTabProtected( pData->GetTabNo() ) ) + { + bool bVisible = false; + SfxViewFrame* pViewFrame = ( pTabViewShell ? pTabViewShell->GetViewFrame() : NULL ); + if ( pViewFrame && pViewFrame->HasChildWindow( nWhich ) ) + { + SfxChildWindow* pChild = pViewFrame->GetChildWindow( nWhich ); + Window* pWin = ( pChild ? pChild->GetWindow() : NULL ); + if ( pWin && pWin->IsVisible() ) + { + bVisible = true; + } + } + if ( !bVisible ) + { + rSet.DisableItem( nWhich ); + } + } + } + break; + + } // switch ( nWitch ) + nWhich = aIter.NextWhich(); + } // while ( nWitch ) +} + +//------------------------------------------------------------------ + + + diff --git a/sc/source/ui/view/cellsh1.cxx b/sc/source/ui/view/cellsh1.cxx new file mode 100644 index 000000000000..3803a318fb21 --- /dev/null +++ b/sc/source/ui/view/cellsh1.cxx @@ -0,0 +1,2206 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + +//------------------------------------------------------------------ + +//svdraw.hxx +#define _SDR_NOITEMS +#define _SDR_NOTOUCH +#define _SDR_NOTRANSFORM +#define _SI_NOSBXCONTROLS +#define _VCONT_HXX +#define _SI_NOOTHERFORMS +#define _VCTRLS_HXX +#define _SI_NOCONTROL +#define _SETBRW_HXX +#define _VCBRW_HXX +#define _SI_NOSBXCONTROLS + +//------------------------------------------------------------------ +#include <com/sun/star/i18n/TextConversionOption.hpp> +#include <com/sun/star/sheet/DataPilotFieldFilter.hpp> + +#include "scitems.hxx" +#include <sfx2/viewfrm.hxx> + +#define _ZFORLIST_DECLARE_TABLE +#include <svl/stritem.hxx> +#include <svl/whiter.hxx> +#include <svl/zforlist.hxx> +#include <svl/zformat.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/request.hxx> +#include <vcl/msgbox.hxx> +#include <svx/svxdlg.hxx> +#include <sot/formats.hxx> +#include <svx/postattr.hxx> +#include <editeng/fontitem.hxx> +#include <svx/clipfmtitem.hxx> +#include <sfx2/passwd.hxx> +#include <svx/hlnkitem.hxx> +#include <basic/sbxcore.hxx> +#include <unotools/useroptions.hxx> +#include <vcl/waitobj.hxx> +#include <unotools/localedatawrapper.hxx> + +#include "cellsh.hxx" +#include "sc.hrc" +#include "document.hxx" +#include "patattr.hxx" +#include "scmod.hxx" +#include "scresid.hxx" +#include "tabvwsh.hxx" +//CHINA001 #include "inscldlg.hxx" +//CHINA001 #include "inscodlg.hxx" +//CHINA001 #include "delcldlg.hxx" +//CHINA001 #include "delcodlg.hxx" +//CHINA001 #include "filldlg.hxx" +//CHINA001 #include "groupdlg.hxx" +#include "impex.hxx" +#include "reffind.hxx" +//CHINA001 #include "namecrea.hxx" +#include "uiitems.hxx" +#include "reffact.hxx" +//CHINA001 #include "namepast.hxx" +#include "inputhdl.hxx" +#include "transobj.hxx" +#include "drwtrans.hxx" +//CHINA001 #include "linkarea.hxx" +#include "docfunc.hxx" +#include "editable.hxx" +#include "dpobject.hxx" +#include "dpsave.hxx" +#include "dpgroup.hxx" // for ScDPNumGroupInfo +#include "spellparam.hxx" +#include "postit.hxx" +#include "clipparam.hxx" + +#include "globstr.hrc" +#include "scui_def.hxx" //CHINA001 +#include <svx/svxdlg.hxx> //CHINA001 +#include <svx/dialogs.hrc> //CHINA001 +#include "scabstdlg.hxx" //CHINA001 +#define IS_AVAILABLE(WhichId,ppItem) \ + (pReqArgs->GetItemState((WhichId), sal_True, ppItem ) == SFX_ITEM_SET) + +#define C2U(cChar) rtl::OUString::createFromAscii(cChar) + +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <cppuhelper/bootstrap.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; + +//------------------------------------------------------------------ +void ScCellShell::ExecuteEdit( SfxRequest& rReq ) +{ + ScModule* pScMod = SC_MOD(); + ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell(); + SfxBindings& rBindings = pTabViewShell->GetViewFrame()->GetBindings(); + const SfxItemSet* pReqArgs = rReq.GetArgs(); + sal_uInt16 nSlot = rReq.GetSlot(); + + pTabViewShell->HideListBox(); // Autofilter-DropDown-Listbox + + // Eingabe beenden + if ( GetViewData()->HasEditView( GetViewData()->GetActivePart() ) ) + { + switch ( nSlot ) + { + case FID_DEFINE_NAME: + case FID_USE_NAME: + case FID_INSERT_NAME: + case SID_SPELL_DIALOG: + case SID_HANGUL_HANJA_CONVERSION: + + pScMod->InputEnterHandler(); + pTabViewShell->UpdateInputHandler(); + break; + + default: + break; + } + } + + switch ( nSlot ) + { + // + // Einfuegen / Loeschen von Zellen / Zeilen / Spalten + // + + case FID_INS_ROW: + pTabViewShell->InsertCells(INS_INSROWS); + rReq.Done(); + break; + + case FID_INS_COLUMN: + pTabViewShell->InsertCells(INS_INSCOLS); + rReq.Done(); + break; + + case FID_INS_CELLSDOWN: + pTabViewShell->InsertCells(INS_CELLSDOWN); + rReq.Done(); + break; + + case FID_INS_CELLSRIGHT: + pTabViewShell->InsertCells(INS_CELLSRIGHT); + rReq.Done(); + break; + + case SID_DEL_ROWS: + pTabViewShell->DeleteCells( DEL_DELROWS ); + rReq.Done(); + break; + + case SID_DEL_COLS: + pTabViewShell->DeleteCells( DEL_DELCOLS ); + rReq.Done(); + break; + + case FID_INS_CELL: + { + InsCellCmd eCmd=INS_NONE; + + if ( pReqArgs ) + { + const SfxPoolItem* pItem; + String aFlags; + + if( IS_AVAILABLE( FID_INS_CELL, &pItem ) ) + aFlags = ((const SfxStringItem*)pItem)->GetValue(); + if( aFlags.Len() ) + { + switch( aFlags.GetChar(0) ) + { + case 'V': eCmd = INS_CELLSDOWN ;break; + case '>': eCmd = INS_CELLSRIGHT ;break; + case 'R': eCmd = INS_INSROWS ;break; + case 'C': eCmd = INS_INSCOLS ;break; + } + } + } + else + { + if ( GetViewData()->SimpleColMarked() ) + eCmd = INS_INSCOLS; + else if ( GetViewData()->SimpleRowMarked() ) + eCmd = INS_INSROWS; + else + { + ScDocument* pDoc = GetViewData()->GetDocument(); + sal_Bool bTheFlag=(pDoc->GetChangeTrack()!=NULL); + +//CHINA001 ScInsertCellDlg* pDlg = new ScInsertCellDlg( pTabViewShell->GetDialogParent(), +//CHINA001 bTheFlag); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + AbstractScInsertCellDlg* pDlg = pFact->CreateScInsertCellDlg( pTabViewShell->GetDialogParent(), RID_SCDLG_INSCELL, bTheFlag); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + if (pDlg->Execute() == RET_OK) + eCmd = pDlg->GetInsCellCmd(); + delete pDlg; + } + } + + if (eCmd!=INS_NONE) + { + pTabViewShell->InsertCells( eCmd ); + + if( ! rReq.IsAPI() ) + { + String aParam; + + switch( eCmd ) + { + case INS_CELLSDOWN: aParam='V'; break; + case INS_CELLSRIGHT: aParam='>'; break; + case INS_INSROWS: aParam='R'; break; + case INS_INSCOLS: aParam='C'; break; + default: + { + // added to avoid warnings + } + } + rReq.AppendItem( SfxStringItem( FID_INS_CELL, aParam ) ); + rReq.Done(); + } + } + } + break; + + case FID_DELETE_CELL: + { + DelCellCmd eCmd = DEL_NONE; + + if ( pReqArgs ) + { + const SfxPoolItem* pItem; + String aFlags; + + if( IS_AVAILABLE( FID_DELETE_CELL, &pItem ) ) + aFlags = ((const SfxStringItem*)pItem)->GetValue(); + if( aFlags.Len() ) + { + switch( aFlags.GetChar(0) ) + { + case 'U': eCmd = DEL_CELLSUP ;break; + case 'L': eCmd = DEL_CELLSLEFT ;break; + case 'R': eCmd = DEL_DELROWS ;break; + case 'C': eCmd = DEL_DELCOLS ;break; + } + } + } + else + { + if ( GetViewData()->SimpleColMarked() ) + eCmd = DEL_DELCOLS; + else if ( GetViewData()->SimpleRowMarked() ) + eCmd = DEL_DELROWS; + else + { + ScRange aRange; + ScDocument* pDoc = GetViewData()->GetDocument(); + sal_Bool bTheFlag=GetViewData()->IsMultiMarked() || + (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE_FILTERED) || + (pDoc->GetChangeTrack() != NULL); + + //CHINA001 ScDeleteCellDlg* pDlg = new ScDeleteCellDlg( + //CHINA001 pTabViewShell->GetDialogParent(),bTheFlag); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + AbstractScDeleteCellDlg* pDlg = pFact->CreateScDeleteCellDlg( pTabViewShell->GetDialogParent(), RID_SCDLG_DELCELL, bTheFlag ); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + + if (pDlg->Execute() == RET_OK) + eCmd = pDlg->GetDelCellCmd(); + delete pDlg; + } + } + + if (eCmd != DEL_NONE ) + { + pTabViewShell->DeleteCells( eCmd ); + + if( ! rReq.IsAPI() ) + { + String aParam; + + switch( eCmd ) + { + case DEL_CELLSUP: aParam='U'; break; + case DEL_CELLSLEFT: aParam='L'; break; + case DEL_DELROWS: aParam='R'; break; + case DEL_DELCOLS: aParam='C'; break; + default: + { + // added to avoid warnings + } + } + rReq.AppendItem( SfxStringItem( FID_DELETE_CELL, aParam ) ); + rReq.Done(); + } + } + } + break; + + // + // Inhalte von Zellen loeschen + // + + case SID_DELETE_CONTENTS: + pTabViewShell->DeleteContents( IDF_CONTENTS ); + rReq.Done(); + break; + + case SID_DELETE: + { + sal_uInt16 nFlags = IDF_NONE; + + if ( pReqArgs!=NULL && pTabViewShell->SelectionEditable() ) + { + const SfxPoolItem* pItem; + String aFlags = 'A'; + + if( IS_AVAILABLE( SID_DELETE, &pItem ) ) + aFlags = ((const SfxStringItem*)pItem)->GetValue(); + + aFlags.ToUpperAscii(); + sal_Bool bCont = sal_True; + + for( xub_StrLen i=0 ; bCont && i<aFlags.Len() ; i++ ) + { + switch( aFlags.GetChar(i) ) + { + case 'A': // Alle + nFlags |= IDF_ALL; + bCont = sal_False; // nicht mehr weitermachen! + break; + case 'S': nFlags |= IDF_STRING; break; + case 'V': nFlags |= IDF_VALUE; break; + case 'D': nFlags |= IDF_DATETIME; break; + case 'F': nFlags |= IDF_FORMULA; break; + case 'N': nFlags |= IDF_NOTE; break; + case 'T': nFlags |= IDF_ATTRIB; break; + case 'O': nFlags |= IDF_OBJECTS; break; + } + } + } + else + { + ScEditableTester aTester( pTabViewShell ); + if (aTester.IsEditable()) + { + //CHINA001 ScDeleteContentsDlg* pDlg = new ScDeleteContentsDlg( pTabViewShell->GetDialogParent() ); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + AbstractScDeleteContentsDlg* pDlg = pFact->CreateScDeleteContentsDlg( pTabViewShell->GetDialogParent(), RID_SCDLG_DELCONT ); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + ScDocument* pDoc = GetViewData()->GetDocument(); + SCTAB nTab = GetViewData()->GetTabNo(); + if ( pDoc->IsTabProtected(nTab) ) + pDlg->DisableObjects(); + if (pDlg->Execute() == RET_OK) + { + nFlags = pDlg->GetDelContentsCmdBits(); + } + delete pDlg; + } + else + pTabViewShell->ErrorMessage(aTester.GetMessageId()); + } + + if( nFlags != IDF_NONE ) + { + pTabViewShell->DeleteContents( nFlags ); + + if( ! rReq.IsAPI() ) + { + String aFlags; + + if( nFlags == IDF_ALL ) + { + aFlags += 'A'; + } + else + { + if( nFlags & IDF_STRING ) aFlags += 'S'; + if( nFlags & IDF_VALUE ) aFlags += 'V'; + if( nFlags & IDF_DATETIME ) aFlags += 'D'; + if( nFlags & IDF_FORMULA ) aFlags += 'F'; + if( nFlags & IDF_NOTE ) aFlags += 'N'; + if( nFlags & IDF_ATTRIB ) aFlags += 'T'; + if( nFlags & IDF_OBJECTS ) aFlags += 'O'; + } + + rReq.AppendItem( SfxStringItem( SID_DELETE, aFlags ) ); + rReq.Done(); + } + } + } + break; + + // + // Ausfuellen... + // + + case FID_FILL_TO_BOTTOM: + pTabViewShell->FillSimple( FILL_TO_BOTTOM ); + rReq.Done(); + break; + + case FID_FILL_TO_RIGHT: + pTabViewShell->FillSimple( FILL_TO_RIGHT ); + rReq.Done(); + break; + + case FID_FILL_TO_TOP: + pTabViewShell->FillSimple( FILL_TO_TOP ); + rReq.Done(); + break; + + case FID_FILL_TO_LEFT: + pTabViewShell->FillSimple( FILL_TO_LEFT ); + rReq.Done(); + break; + + case FID_FILL_TAB: + { + sal_uInt16 nFlags = IDF_NONE; + sal_uInt16 nFunction = PASTE_NOFUNC; + sal_Bool bSkipEmpty = sal_False; + sal_Bool bAsLink = sal_False; + + if ( pReqArgs!=NULL && pTabViewShell->SelectionEditable() ) + { + const SfxPoolItem* pItem; + String aFlags = 'A'; + + if( IS_AVAILABLE( FID_FILL_TAB, &pItem ) ) + aFlags = ((const SfxStringItem*)pItem)->GetValue(); + + aFlags.ToUpperAscii(); + sal_Bool bCont = sal_True; + + for( xub_StrLen i=0 ; bCont && i<aFlags.Len() ; i++ ) + { + switch( aFlags.GetChar(i) ) + { + case 'A': // Alle + nFlags |= IDF_ALL; + bCont = sal_False; // nicht mehr weitermachen! + break; + case 'S': nFlags |= IDF_STRING; break; + case 'V': nFlags |= IDF_VALUE; break; + case 'D': nFlags |= IDF_DATETIME; break; + case 'F': nFlags |= IDF_FORMULA; break; + case 'N': nFlags |= IDF_NOTE; break; + case 'T': nFlags |= IDF_ATTRIB; break; + } + } + } + else + { +//CHINA001 ScInsertContentsDlg* pDlg = +//CHINA001 new ScInsertContentsDlg(pTabViewShell->GetDialogParent(), +//CHINA001 0, /* nCheckDefaults */ +//CHINA001 &ScGlobal::GetRscString(STR_FILL_TAB) ); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + AbstractScInsertContentsDlg* pDlg = pFact->CreateScInsertContentsDlg( pTabViewShell->GetDialogParent(), + RID_SCDLG_INSCONT, 0, /* nCheckDefaults */ + &ScGlobal::GetRscString(STR_FILL_TAB)); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + pDlg->SetFillMode(sal_True); + + if (pDlg->Execute() == RET_OK) + { + nFlags = pDlg->GetInsContentsCmdBits(); + nFunction = pDlg->GetFormulaCmdBits(); + bSkipEmpty = pDlg->IsSkipEmptyCells(); + bAsLink = pDlg->IsLink(); + // MoveMode gibt's bei Tabelle fuellen nicht + } + delete pDlg; + } + + if( nFlags != IDF_NONE ) + { + pTabViewShell->FillTab( nFlags, nFunction, bSkipEmpty, bAsLink ); + + if( ! rReq.IsAPI() ) + { + String aFlags; + + if( nFlags == IDF_ALL ) + { + aFlags += 'A'; + } + else + { + if( nFlags & IDF_STRING ) aFlags += 'S'; + if( nFlags & IDF_VALUE ) aFlags += 'V'; + if( nFlags & IDF_DATETIME ) aFlags += 'D'; + if( nFlags & IDF_FORMULA ) aFlags += 'F'; + if( nFlags & IDF_NOTE ) aFlags += 'N'; + if( nFlags & IDF_ATTRIB ) aFlags += 'T'; + } + + rReq.AppendItem( SfxStringItem( FID_FILL_TAB, aFlags ) ); + rReq.Done(); + } + } + } + break; + + case FID_FILL_SERIES: + { + SCCOL nStartCol; + SCROW nStartRow; + SCTAB nStartTab; + SCCOL nEndCol; + SCROW nEndRow; + SCTAB nEndTab; + sal_uInt16 nPossDir = FDS_OPT_NONE; + FillDir eFillDir = FILL_TO_BOTTOM; + FillCmd eFillCmd = FILL_LINEAR; + FillDateCmd eFillDateCmd = FILL_DAY; + double fStartVal = MAXDOUBLE; + double fIncVal = 1; + double fMaxVal = MAXDOUBLE; + sal_Bool bDoIt = sal_False; + + GetViewData()->GetSimpleArea( nStartCol, nStartRow, nStartTab, + nEndCol, nEndRow, nEndTab ); + + if( nStartCol!=nEndCol ) + { + nPossDir |= FDS_OPT_HORZ; + eFillDir=FILL_TO_RIGHT; + } + + if( nStartRow!=nEndRow ) + { + nPossDir |= FDS_OPT_VERT; + eFillDir=FILL_TO_BOTTOM; + } + + ScDocument* pDoc = GetViewData()->GetDocument(); + SvNumberFormatter* pFormatter = pDoc->GetFormatTable(); + + if( pReqArgs ) + { + const SfxPoolItem* pItem; + String aFillDir, aFillCmd, aFillDateCmd; + String aFillStep, aFillStart, aFillMax; + sal_uInt32 nKey; + double fTmpVal; + + bDoIt=sal_False; + + if( IS_AVAILABLE( FID_FILL_SERIES, &pItem ) ) + aFillDir = ((const SfxStringItem*)pItem)->GetValue(); + if( IS_AVAILABLE( FN_PARAM_1, &pItem ) ) + aFillCmd = ((const SfxStringItem*)pItem)->GetValue(); + if( IS_AVAILABLE( FN_PARAM_2, &pItem ) ) + aFillDateCmd = ((const SfxStringItem*)pItem)->GetValue(); + if( IS_AVAILABLE( FN_PARAM_3, &pItem ) ) + aFillStep = ((const SfxStringItem*)pItem)->GetValue(); + if( IS_AVAILABLE( FN_PARAM_4, &pItem ) ) + aFillStart = ((const SfxStringItem*)pItem)->GetValue(); + if( IS_AVAILABLE( FN_PARAM_5, &pItem ) ) + aFillMax = ((const SfxStringItem*)pItem)->GetValue(); + + if( aFillDir.Len() ) + switch( aFillDir.GetChar(0) ) + { + case 'B': case 'b': eFillDir=FILL_TO_BOTTOM; break; + case 'R': case 'r': eFillDir=FILL_TO_RIGHT; break; + case 'T': case 't': eFillDir=FILL_TO_TOP; break; + case 'L': case 'l': eFillDir=FILL_TO_LEFT; break; + } + + if( aFillCmd.Len() ) + switch( aFillCmd.GetChar(0) ) + { + case 'S': case 's': eFillCmd=FILL_SIMPLE; break; + case 'L': case 'l': eFillCmd=FILL_LINEAR; break; + case 'G': case 'g': eFillCmd=FILL_GROWTH; break; + case 'D': case 'd': eFillCmd=FILL_DATE; break; + case 'A': case 'a': eFillCmd=FILL_AUTO; break; + } + + if( aFillDateCmd.Len() ) + switch( aFillDateCmd.GetChar(0) ) + { + case 'D': case 'd': eFillDateCmd=FILL_DAY; break; + case 'W': case 'w': eFillDateCmd=FILL_WEEKDAY; break; + case 'M': case 'm': eFillDateCmd=FILL_MONTH; break; + case 'Y': case 'y': eFillDateCmd=FILL_YEAR; break; + } + + nKey = 0; + if( pFormatter->IsNumberFormat( aFillStart, nKey, fTmpVal )) + fStartVal = fTmpVal; + + nKey = 0; + if( pFormatter->IsNumberFormat( aFillStep, nKey, fTmpVal )) + fIncVal = fTmpVal; + + nKey = 0; + if( pFormatter->IsNumberFormat( aFillMax, nKey, fTmpVal )) + fMaxVal = fTmpVal; + + bDoIt = sal_True; + + } + else // (pReqArgs == NULL) => Dialog hochziehen + { + // + sal_uInt32 nPrivFormat; + CellType eCellType; + pDoc->GetNumberFormat( nStartCol, nStartRow, nStartTab, nPrivFormat ); + pDoc->GetCellType( nStartCol, nStartRow, nStartTab,eCellType ); + const SvNumberformat* pPrivEntry = pFormatter->GetEntry( nPrivFormat ); + if (!pPrivEntry) + { + DBG_ERROR("Zahlformat nicht gefunden !!!"); + } + else + { + short nPrivType = pPrivEntry->GetType(); + if ( ( nPrivType & NUMBERFORMAT_DATE)>0) + { + eFillCmd=FILL_DATE; + } + else if(eCellType==CELLTYPE_STRING) + { + eFillCmd=FILL_AUTO; + } + } + + // + String aStartStr; + + // Startwert nur vorbelegen, wenn nur 1 Zeile oder Spalte: + if ( nStartCol == nEndCol || nStartRow == nEndRow ) + { + double fInputEndVal = 0.0; + String aEndStr; + + pDoc->GetInputString( nStartCol, nStartRow, nStartTab, aStartStr); + pDoc->GetValue( nStartCol, nStartRow, nStartTab, fStartVal ); + + + if(eFillDir==FILL_TO_BOTTOM && nStartRow < nEndRow ) + { + pDoc->GetInputString( nStartCol, nStartRow+1, nStartTab, aEndStr); + if(aEndStr.Len()>0) + { + pDoc->GetValue( nStartCol, nStartRow+1, nStartTab, fInputEndVal); + fIncVal=fInputEndVal-fStartVal; + } + } + else + { + if(nStartCol < nEndCol) + { + pDoc->GetInputString( nStartCol+1, nStartRow, nStartTab, aEndStr); + if(aEndStr.Len()>0) + { + pDoc->GetValue( nStartCol+1, nStartRow, nStartTab, fInputEndVal); + fIncVal=fInputEndVal-fStartVal; + } + } + } + if(eFillCmd==FILL_DATE) + { + Date aNullDate = *pDoc->GetFormatTable()->GetNullDate(); + Date aStartDate = aNullDate; + aStartDate+= (long)fStartVal; + Date aEndDate = aNullDate; + aEndDate+= (long)fInputEndVal; + double fTempDate=0; + + if(aStartDate.GetYear()!=aEndDate.GetYear()) + { + eFillDateCmd = FILL_YEAR; + fTempDate=aEndDate.GetYear()-aStartDate.GetYear(); + } + if(aStartDate.GetMonth()!=aEndDate.GetMonth()) + { + eFillDateCmd = FILL_MONTH; + fTempDate=fTempDate*12+aEndDate.GetMonth()-aStartDate.GetMonth(); + } + if(aStartDate.GetDay()==aEndDate.GetDay()) + { + fIncVal=fTempDate; + } + } + } +//CHINA001 ScFillSeriesDlg* pDlg = new ScFillSeriesDlg( +//CHINA001 pTabViewShell->GetDialogParent(), *pDoc, +//CHINA001 eFillDir, eFillCmd, eFillDateCmd, +//CHINA001 aStartStr, fIncVal, fMaxVal, +//CHINA001 nPossDir); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + AbstractScFillSeriesDlg* pDlg = pFact->CreateScFillSeriesDlg( pTabViewShell->GetDialogParent(), + *pDoc, + eFillDir, eFillCmd, eFillDateCmd, + aStartStr, fIncVal, fMaxVal, + nPossDir, + RID_SCDLG_FILLSERIES); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + + if ( nStartCol != nEndCol && nStartRow != nEndRow ) + { + pDlg->SetEdStartValEnabled(sal_False); + } + + if ( pDlg->Execute() == RET_OK ) + { + eFillDir = pDlg->GetFillDir(); + eFillCmd = pDlg->GetFillCmd(); + eFillDateCmd = pDlg->GetFillDateCmd(); + + if(eFillCmd==FILL_AUTO) + { + String aStr=pDlg->GetStartStr(); + if(aStr.Len()>0) + pTabViewShell->EnterData( nStartCol, nStartRow, nStartTab, aStr ); + } + fStartVal = pDlg->GetStart(); + fIncVal = pDlg->GetStep(); + fMaxVal = pDlg->GetMax(); + bDoIt = sal_True; + } + delete pDlg; + } + + if( bDoIt ) + { + //nScFillModeMouseModifier = 0; // kein Ctrl/Copy + pTabViewShell->FillSeries( eFillDir, eFillCmd, eFillDateCmd, fStartVal, fIncVal, fMaxVal ); + + if( ! rReq.IsAPI() ) + { + String aPara; + Color* pColor=0; + + switch( eFillDir ) + { + case FILL_TO_BOTTOM: aPara = 'B'; break; + case FILL_TO_RIGHT: aPara = 'R'; break; + case FILL_TO_TOP: aPara = 'T'; break; + case FILL_TO_LEFT: aPara = 'L'; break; + default: aPara.Erase(); break; + } + rReq.AppendItem( SfxStringItem( FID_FILL_SERIES, aPara ) ); + + switch( eFillCmd ) + { + case FILL_SIMPLE: aPara = 'S'; break; + case FILL_LINEAR: aPara = 'L'; break; + case FILL_GROWTH: aPara = 'G'; break; + case FILL_DATE: aPara = 'D'; break; + case FILL_AUTO: aPara = 'A'; break; + default: aPara.Erase(); break; + } + rReq.AppendItem( SfxStringItem( FN_PARAM_1, aPara ) ); + + switch( eFillDateCmd ) + { + case FILL_DAY: aPara = 'D'; break; + case FILL_WEEKDAY: aPara = 'W'; break; + case FILL_MONTH: aPara = 'M'; break; + case FILL_YEAR: aPara = 'Y'; break; + default: aPara.Erase(); break; + } + rReq.AppendItem( SfxStringItem( FN_PARAM_2, aPara ) ); + + sal_uLong nFormatKey = pFormatter->GetStandardFormat(NUMBERFORMAT_NUMBER, + ScGlobal::eLnge ); + + pFormatter->GetOutputString( fIncVal, nFormatKey, aPara, &pColor ); + rReq.AppendItem( SfxStringItem( FN_PARAM_3, aPara ) ); + + pFormatter->GetOutputString( fStartVal, nFormatKey, aPara, &pColor ); + rReq.AppendItem( SfxStringItem( FN_PARAM_4, aPara ) ); + + pFormatter->GetOutputString( fMaxVal, nFormatKey, aPara, &pColor ); + rReq.AppendItem( SfxStringItem( FN_PARAM_5, aPara ) ); + + rReq.Done(); + } + } + } + break; + + case FID_FILL_AUTO: + { + SCCOL nStartCol; + SCROW nStartRow; + SCCOL nEndCol; + SCROW nEndRow; + SCTAB nStartTab, nEndTab; + + GetViewData()->GetFillData( nStartCol, nStartRow, nEndCol, nEndRow ); + SCCOL nFillCol = GetViewData()->GetRefEndX(); + SCROW nFillRow = GetViewData()->GetRefEndY(); + ScDocument* pDoc = GetViewData()->GetDocument(); + + if( pReqArgs != NULL ) + { + const SfxPoolItem* pItem; + + if( IS_AVAILABLE( FID_FILL_AUTO, &pItem ) ) + { + ScAddress aScAddress; + String aArg = ((const SfxStringItem*)pItem)->GetValue(); + + if( aScAddress.Parse( aArg, pDoc, pDoc->GetAddressConvention() ) & SCA_VALID ) + { + nFillRow = aScAddress.Row(); + nFillCol = aScAddress.Col(); + } + } + + GetViewData()->GetSimpleArea( nStartCol,nStartRow,nStartTab, + nEndCol,nEndRow,nEndTab ); + } + else // Aufruf per Maus + { + // #55284# nicht innerhalb einer zusammengefassten Zelle + + if ( nStartCol == nEndCol && nStartRow == nEndRow ) + { + SCCOL nMergeCol = nStartCol; + SCROW nMergeRow = nStartRow; + if ( GetViewData()->GetDocument()->ExtendMerge( + nStartCol, nStartRow, nMergeCol, nMergeRow, + GetViewData()->GetTabNo() ) ) + { + if ( nFillCol >= nStartCol && nFillCol <= nMergeCol && nFillRow == nStartRow ) + nFillCol = nStartCol; + if ( nFillRow >= nStartRow && nFillRow <= nMergeRow && nFillCol == nStartCol ) + nFillRow = nStartRow; + } + } + } + + if ( nFillCol != nEndCol || nFillRow != nEndRow ) + { + if ( nFillCol==nEndCol || nFillRow==nEndRow ) + { + FillDir eDir = FILL_TO_BOTTOM; + SCCOLROW nCount = 0; + + if ( nFillCol==nEndCol ) + { + if ( nFillRow > nEndRow ) + { + eDir = FILL_TO_BOTTOM; + nCount = nFillRow - nEndRow; + } + else if ( nFillRow < nStartRow ) + { + eDir = FILL_TO_TOP; + nCount = nStartRow - nFillRow; + } + } + else + { + if ( nFillCol > nEndCol ) + { + eDir = FILL_TO_RIGHT; + nCount = nFillCol - nEndCol; + } + else if ( nFillCol < nStartCol ) + { + eDir = FILL_TO_LEFT; + nCount = nStartCol - nFillCol; + } + } + + if ( nCount != 0) + { + pTabViewShell->FillAuto( eDir, nStartCol, nStartRow, nEndCol, nEndRow, nCount ); + + if( ! rReq.IsAPI() ) + { + String aAdrStr; + ScAddress aAdr( nFillCol, nFillRow, 0 ); + aAdr.Format( aAdrStr, SCR_ABS, pDoc, pDoc->GetAddressConvention() ); + + rReq.AppendItem( SfxStringItem( FID_FILL_AUTO, aAdrStr ) ); + rReq.Done(); + } + } + + } + else + { + DBG_ERROR( "Richtung nicht eindeutig fuer AutoFill" ); + } + } + } + break; + + // + // Gliederung (Outlines) + // SID_AUTO_OUTLINE, SID_OUTLINE_DELETEALL in Execute (in docsh.idl) + // + + case SID_OUTLINE_HIDE: + if ( GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(), + GetViewData()->GetCurY(), GetViewData()->GetTabNo() ) ) + pTabViewShell->SetDataPilotDetails( sal_False ); + else + pTabViewShell->HideMarkedOutlines(); + rReq.Done(); + break; + + case SID_OUTLINE_SHOW: + { + ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(), + GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); + if ( pDPObj ) + { + Sequence<sheet::DataPilotFieldFilter> aFilters; + sal_uInt16 nOrientation; + if ( pTabViewShell->HasSelectionForDrillDown( nOrientation ) ) + { + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + AbstractScDPShowDetailDlg* pDlg = pFact->CreateScDPShowDetailDlg( + pTabViewShell->GetDialogParent(), RID_SCDLG_DPSHOWDETAIL, *pDPObj, nOrientation ); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + if ( pDlg->Execute() == RET_OK ) + { + String aNewDimName( pDlg->GetDimensionName() ); + pTabViewShell->SetDataPilotDetails( sal_True, &aNewDimName ); + } + } + else if ( !pDPObj->IsServiceData() && + pDPObj->GetDataFieldPositionData( + ScAddress( GetViewData()->GetCurX(), GetViewData()->GetCurY(), GetViewData()->GetTabNo() ), + aFilters ) ) + pTabViewShell->ShowDataPilotSourceData( *pDPObj, aFilters ); + else + pTabViewShell->SetDataPilotDetails( sal_True ); + } + else + pTabViewShell->ShowMarkedOutlines(); + rReq.Done(); + } + break; + + case SID_OUTLINE_MAKE: + { + sal_Bool bColumns = sal_False; + sal_Bool bOk = sal_True; + + if ( GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(), + GetViewData()->GetCurY(), GetViewData()->GetTabNo() ) ) + { + ScDPNumGroupInfo aNumInfo; + aNumInfo.Enable = sal_True; + aNumInfo.AutoStart = sal_True; + aNumInfo.AutoEnd = sal_True; + sal_Int32 nParts = 0; + if ( pTabViewShell->HasSelectionForDateGroup( aNumInfo, nParts ) ) + { + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT( pFact, "ScAbstractFactory create fail!" ); + Date aNullDate( *GetViewData()->GetDocument()->GetFormatTable()->GetNullDate() ); + AbstractScDPDateGroupDlg* pDlg = pFact->CreateScDPDateGroupDlg( + pTabViewShell->GetDialogParent(), RID_SCDLG_DPDATEGROUP, + aNumInfo, nParts, aNullDate ); + DBG_ASSERT( pDlg, "Dialog create fail!" ); + if( pDlg->Execute() == RET_OK ) + { + aNumInfo = pDlg->GetGroupInfo(); + pTabViewShell->DateGroupDataPilot( aNumInfo, pDlg->GetDatePart() ); + } + } + else if ( pTabViewShell->HasSelectionForNumGroup( aNumInfo ) ) + { + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT( pFact, "ScAbstractFactory create fail!" ); + AbstractScDPNumGroupDlg* pDlg = pFact->CreateScDPNumGroupDlg( + pTabViewShell->GetDialogParent(), RID_SCDLG_DPNUMGROUP, aNumInfo ); + DBG_ASSERT( pDlg, "Dialog create fail!" ); + if( pDlg->Execute() == RET_OK ) + pTabViewShell->NumGroupDataPilot( pDlg->GetGroupInfo() ); + } + else + pTabViewShell->GroupDataPilot(); + + bOk = sal_False; + } + else if( pReqArgs != NULL ) + { + const SfxPoolItem* pItem; + bOk = sal_False; + + if( IS_AVAILABLE( SID_OUTLINE_MAKE, &pItem ) ) + { + String aCol = ((const SfxStringItem*)pItem)->GetValue(); + aCol.ToUpperAscii(); + + switch( aCol.GetChar(0) ) + { + case 'R': bColumns=sal_False; bOk = sal_True;break; + case 'C': bColumns=sal_True; bOk = sal_True;break; + } + } + } + else // Dialog, wenn nicht ganze Zeilen/Spalten markiert + { + if ( GetViewData()->SimpleColMarked() && !GetViewData()->SimpleRowMarked() ) + bColumns = sal_True; + else if ( !GetViewData()->SimpleColMarked() && GetViewData()->SimpleRowMarked() ) + bColumns = sal_False; + else + { +//CHINA001 ScGroupDlg* pDlg = new ScGroupDlg(pTabViewShell->GetDialogParent(), +//CHINA001 RID_SCDLG_GRP_MAKE, sal_False ); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + AbstractScGroupDlg* pDlg = pFact->CreateAbstractScGroupDlg( pTabViewShell->GetDialogParent(), RID_SCDLG_GRP_MAKE, RID_SCDLG_GRP_MAKE,sal_False); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + if ( pDlg->Execute() == RET_OK ) + bColumns = pDlg->GetColsChecked(); + else + bOk = sal_False; + delete pDlg; + } + } + if (bOk) + { + pTabViewShell->MakeOutline( bColumns ); + + if( ! rReq.IsAPI() ) + { + String aCol = bColumns ? 'C' : 'R'; + rReq.AppendItem( SfxStringItem( SID_OUTLINE_MAKE, aCol ) ); + rReq.Done(); + } + } + } + break; + + case SID_OUTLINE_REMOVE: + { + sal_Bool bColumns = sal_False; + sal_Bool bOk = sal_True; + + if ( GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(), + GetViewData()->GetCurY(), GetViewData()->GetTabNo() ) ) + { + pTabViewShell->UngroupDataPilot(); + bOk = sal_False; + } + else if( pReqArgs != NULL ) + { + const SfxPoolItem* pItem; + bOk = sal_False; + + if( IS_AVAILABLE( SID_OUTLINE_REMOVE, &pItem ) ) + { + String aCol = ((const SfxStringItem*)pItem)->GetValue(); + aCol.ToUpperAscii(); + + switch( aCol.GetChar(0) ) + { + case 'R': bColumns=sal_False; bOk = sal_True;break; + case 'C': bColumns=sal_True; bOk = sal_True;break; + } + } + } + else // Dialog nur, wenn Aufheben fuer Zeilen und Spalten moeglich + { + sal_Bool bColPoss, bRowPoss; + pTabViewShell->TestRemoveOutline( bColPoss, bRowPoss ); + if ( bColPoss && bRowPoss ) + { + //CHINA001 ScGroupDlg* pDlg = new ScGroupDlg( pTabViewShell->GetDialogParent(), + //CHINA001 RID_SCDLG_GRP_KILL, sal_True ); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + AbstractScGroupDlg* pDlg = pFact->CreateAbstractScGroupDlg( pTabViewShell->GetDialogParent(), RID_SCDLG_GRP_KILL, RID_SCDLG_GRP_KILL,sal_True); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + if ( pDlg->Execute() == RET_OK ) + bColumns = pDlg->GetColsChecked(); + else + bOk = sal_False; + delete pDlg; + } + else if ( bColPoss ) + bColumns = sal_True; + else if ( bRowPoss ) + bColumns = sal_False; + else + bOk = sal_False; + } + if (bOk) + { + pTabViewShell->RemoveOutline( bColumns ); + + if( ! rReq.IsAPI() ) + { + String aCol = bColumns ? 'C' : 'R'; + rReq.AppendItem( SfxStringItem( SID_OUTLINE_REMOVE, aCol ) ); + rReq.Done(); + } + } + } + break; + + // + // Clipboard + // + + case SID_COPY: // fuer Grafiken in DrawShell + { + WaitObject aWait( GetViewData()->GetDialogParent() ); + pTabViewShell->CopyToClip( NULL, sal_False, sal_False, sal_True ); + rReq.Done(); + } + break; + + case SID_CUT: // fuer Grafiken in DrawShell + { + WaitObject aWait( GetViewData()->GetDialogParent() ); + pTabViewShell->CutToClip( NULL, sal_True ); + rReq.Done(); + } + break; + + case SID_PASTE: + { + PasteFromClipboard ( GetViewData(), pTabViewShell, true ); + rReq.Done(); + } + break; + + case SID_CLIPBOARD_FORMAT_ITEMS: + { + WaitObject aWait( GetViewData()->GetDialogParent() ); + + sal_uLong nFormat = 0; + const SfxPoolItem* pItem; + if ( pReqArgs && + pReqArgs->GetItemState(nSlot, sal_True, &pItem) == SFX_ITEM_SET && + pItem->ISA(SfxUInt32Item) ) + { + nFormat = ((const SfxUInt32Item*)pItem)->GetValue(); + } + + if ( nFormat ) + { + Window* pWin = GetViewData()->GetActiveWin(); + sal_Bool bCells = ( ScTransferObj::GetOwnClipboard( pWin ) != NULL ); + sal_Bool bDraw = ( ScDrawTransferObj::GetOwnClipboard( pWin ) != NULL ); + sal_Bool bOle = ( nFormat == SOT_FORMATSTR_ID_EMBED_SOURCE ); + + if ( bCells && bOle ) + pTabViewShell->PasteFromSystem(); + else if ( bDraw && bOle ) + pTabViewShell->PasteDraw(); + else + pTabViewShell->PasteFromSystem(nFormat); + } + //?else + //? pTabViewShell->PasteFromSystem(); + + rReq.Done(); + } + pTabViewShell->CellContentChanged(); + break; + + case FID_INS_CELL_CONTENTS: + { + sal_uInt16 nFlags = IDF_NONE; + sal_uInt16 nFunction = PASTE_NOFUNC; + sal_Bool bSkipEmpty = sal_False; + sal_Bool bTranspose = sal_False; + sal_Bool bAsLink = sal_False; + InsCellCmd eMoveMode = INS_NONE; + + Window* pWin = GetViewData()->GetActiveWin(); + ScDocument* pDoc = GetViewData()->GetDocument(); + sal_Bool bOtherDoc = !pDoc->IsClipboardSource(); + ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin ); + if ( pOwnClip ) + { + // #129384# keep a reference in case the clipboard is changed during dialog or PasteFromClip + uno::Reference<datatransfer::XTransferable> aOwnClipRef( pOwnClip ); + if ( pReqArgs!=NULL && pTabViewShell->SelectionEditable() ) + { + const SfxPoolItem* pItem; + String aFlags = 'A'; + + if( IS_AVAILABLE( FID_INS_CELL_CONTENTS, &pItem ) ) + aFlags = ((const SfxStringItem*)pItem)->GetValue(); + + aFlags.ToUpperAscii(); + sal_Bool bCont = sal_True; + + for( xub_StrLen i=0 ; bCont && i<aFlags.Len() ; i++ ) + { + switch( aFlags.GetChar(i) ) + { + case 'A': // Alle + nFlags |= IDF_ALL; + bCont = sal_False; // nicht mehr weitermachen! + break; + case 'S': nFlags |= IDF_STRING; break; + case 'V': nFlags |= IDF_VALUE; break; + case 'D': nFlags |= IDF_DATETIME; break; + case 'F': nFlags |= IDF_FORMULA; break; + case 'N': nFlags |= IDF_NOTE; break; + case 'T': nFlags |= IDF_ATTRIB; break; + } + } + + SFX_REQUEST_ARG( rReq, pFuncItem, SfxUInt16Item, FN_PARAM_1, sal_False ); + SFX_REQUEST_ARG( rReq, pSkipItem, SfxBoolItem, FN_PARAM_2, sal_False ); + SFX_REQUEST_ARG( rReq, pTransposeItem, SfxBoolItem, FN_PARAM_3, sal_False ); + SFX_REQUEST_ARG( rReq, pLinkItem, SfxBoolItem, FN_PARAM_4, sal_False ); + SFX_REQUEST_ARG( rReq, pMoveItem, SfxInt16Item, FN_PARAM_5, sal_False ); + if ( pFuncItem ) + nFunction = pFuncItem->GetValue(); + if ( pSkipItem ) + bSkipEmpty = pSkipItem->GetValue(); + if ( pTransposeItem ) + bTranspose = pTransposeItem->GetValue(); + if ( pLinkItem ) + bAsLink = pLinkItem->GetValue(); + if ( pMoveItem ) + eMoveMode = (InsCellCmd) pMoveItem->GetValue(); + } + else + { + ScEditableTester aTester( pTabViewShell ); + if (aTester.IsEditable()) + { + //CHINA001 ScInsertContentsDlg* pDlg = new ScInsertContentsDlg( pTabViewShell->GetDialogParent() ); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + AbstractScInsertContentsDlg* pDlg = pFact->CreateScInsertContentsDlg( pTabViewShell->GetDialogParent(), + RID_SCDLG_INSCONT); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + pDlg->SetOtherDoc( bOtherDoc ); + // #53661# bei ChangeTrack MoveMode disablen + pDlg->SetChangeTrack( pDoc->GetChangeTrack() != NULL ); + // #72930# cut/move references may disable shift + // directions if source and destination ranges intersect + if ( !bOtherDoc ) + { + if ( pOwnClip && pOwnClip->GetDocument()->IsCutMode() ) + { + ScViewData* pData = GetViewData(); + if ( pData->GetMarkData().GetTableSelect( + pData->GetTabNo() ) ) + { + SCCOL nPosX = pData->GetCurX(); + SCROW nPosY = pData->GetCurY(); + SCCOL nClipStartX, nClipSizeX; + SCROW nClipStartY, nClipSizeY; + pOwnClip->GetDocument()->GetClipStart( nClipStartX, nClipStartY ); + // for CutMode, filtered rows can always be included + pOwnClip->GetDocument()->GetClipArea( nClipSizeX, nClipSizeY, sal_True ); + int nDisableShift = 0; + if ( nClipStartX <= nPosX + nClipSizeX && + nPosX <= nClipStartX + nClipSizeX ) + nDisableShift |= SC_CELL_SHIFT_DISABLE_DOWN; + if ( nClipStartY <= nPosY + nClipSizeY && + nPosY <= nClipStartY + nClipSizeY ) + nDisableShift |= SC_CELL_SHIFT_DISABLE_RIGHT; + if ( nDisableShift ) + pDlg->SetCellShiftDisabled( nDisableShift ); + } + } + } + if (pDlg->Execute() == RET_OK) + { + nFlags = pDlg->GetInsContentsCmdBits(); + nFunction = pDlg->GetFormulaCmdBits(); + bSkipEmpty = pDlg->IsSkipEmptyCells(); + bTranspose = pDlg->IsTranspose(); + bAsLink = pDlg->IsLink(); + eMoveMode = pDlg->GetMoveMode(); + } + delete pDlg; + } + else + pTabViewShell->ErrorMessage(aTester.GetMessageId()); + } + + if( nFlags != IDF_NONE ) + { + { + WaitObject aWait( GetViewData()->GetDialogParent() ); + if ( bAsLink && bOtherDoc ) + pTabViewShell->PasteFromSystem(SOT_FORMATSTR_ID_LINK); // DDE einfuegen + else + pTabViewShell->PasteFromClip( nFlags, pOwnClip->GetDocument(), + nFunction, bSkipEmpty, bTranspose, bAsLink, + eMoveMode, IDF_NONE, sal_True ); // allow warning dialog + } + + if( !pReqArgs ) + { + String aFlags; + + if( nFlags == IDF_ALL ) + { + aFlags += 'A'; + } + else + { + if( nFlags & IDF_STRING ) aFlags += 'S'; + if( nFlags & IDF_VALUE ) aFlags += 'V'; + if( nFlags & IDF_DATETIME ) aFlags += 'D'; + if( nFlags & IDF_FORMULA ) aFlags += 'F'; + if( nFlags & IDF_NOTE ) aFlags += 'N'; + if( nFlags & IDF_ATTRIB ) aFlags += 'T'; + } + + rReq.AppendItem( SfxStringItem( FID_INS_CELL_CONTENTS, aFlags ) ); + rReq.AppendItem( SfxBoolItem( FN_PARAM_2, bSkipEmpty ) ); + rReq.AppendItem( SfxBoolItem( FN_PARAM_3, bTranspose ) ); + rReq.AppendItem( SfxBoolItem( FN_PARAM_4, bAsLink ) ); + rReq.AppendItem( SfxUInt16Item( FN_PARAM_1, nFunction ) ); + rReq.AppendItem( SfxInt16Item( FN_PARAM_5, (sal_Int16) eMoveMode ) ); + rReq.Done(); + } + } + } + } + pTabViewShell->CellContentChanged(); // => PasteFromXXX ??? + break; + + case SID_PASTE_SPECIAL: + // Unterscheidung, ob eigene oder fremde Daten, + // dadurch FID_INS_CELL_CONTENTS ueberfluessig + { + Window* pWin = GetViewData()->GetActiveWin(); + + // Clipboard-ID als Parameter angegeben? Basic "PasteSpecial(Format)" + const SfxPoolItem* pItem=NULL; + if ( pReqArgs && + pReqArgs->GetItemState(nSlot, sal_True, &pItem) == SFX_ITEM_SET && + pItem->ISA(SfxUInt32Item) ) + { + sal_uLong nFormat = ((const SfxUInt32Item*)pItem)->GetValue(); + sal_Bool bRet=sal_True; + { + WaitObject aWait( GetViewData()->GetDialogParent() ); + sal_Bool bDraw = ( ScDrawTransferObj::GetOwnClipboard( pWin ) != NULL ); + if ( bDraw && nFormat == SOT_FORMATSTR_ID_EMBED_SOURCE ) + pTabViewShell->PasteDraw(); + else + bRet = pTabViewShell->PasteFromSystem(nFormat, sal_True); // TRUE: keine Fehlermeldungen + } + + if ( bRet ) + { + rReq.SetReturnValue(SfxInt16Item(nSlot, bRet)); // 1 = Erfolg, 0 = Fehler + rReq.Done(); + } + else + // if format is not available -> fallback to request without parameters + pItem = NULL; + } + + if ( !pItem ) + { + if ( ScTransferObj::GetOwnClipboard( pWin ) ) // own cell data + { + rReq.SetSlot( FID_INS_CELL_CONTENTS ); + ExecuteSlot( rReq, GetInterface() ); + rReq.SetReturnValue(SfxInt16Item(nSlot, 1)); // 1 = Erfolg + } + else // Zeichenobjekte oder fremde Daten + { + sal_Bool bDraw = ( ScDrawTransferObj::GetOwnClipboard( pWin ) != NULL ); + + SvxClipboardFmtItem aFormats( SID_CLIPBOARD_FORMAT_ITEMS ); + GetPossibleClipboardFormats( aFormats ); + + sal_uInt16 nFormatCount = aFormats.Count(); + if ( nFormatCount ) + { + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + SfxAbstractPasteDialog* pDlg = pFact->CreatePasteDialog( pTabViewShell->GetDialogParent() ); + if ( pDlg ) + { + for (sal_uInt16 i=0; i<nFormatCount; i++) + { + sal_uLong nFormatId = aFormats.GetClipbrdFormatId( i ); + String aName = aFormats.GetClipbrdFormatName( i ); + // special case for paste dialog: '*' is replaced by object type + if ( nFormatId == SOT_FORMATSTR_ID_EMBED_SOURCE ) + aName.Assign((sal_Unicode)'*'); + pDlg->Insert( nFormatId, aName ); + } + + TransferableDataHelper aDataHelper( + TransferableDataHelper::CreateFromSystemClipboard( pWin ) ); + sal_uLong nFormat = pDlg->GetFormat( aDataHelper.GetTransferable() ); + if (nFormat > 0) + { + { + WaitObject aWait( GetViewData()->GetDialogParent() ); + if ( bDraw && nFormat == SOT_FORMATSTR_ID_EMBED_SOURCE ) + pTabViewShell->PasteDraw(); + else + pTabViewShell->PasteFromSystem(nFormat); + } + rReq.SetReturnValue(SfxInt16Item(nSlot, 1)); // 1 = Erfolg + rReq.AppendItem( SfxUInt32Item( nSlot, nFormat ) ); + rReq.Done(); + } + else + { + rReq.SetReturnValue(SfxInt16Item(nSlot, 0)); // 0 = Fehler + rReq.Ignore(); + } + + delete pDlg; + } + } + else + rReq.SetReturnValue(SfxInt16Item(nSlot, 0)); // 0 = Fehler + } + } + } + pTabViewShell->CellContentChanged(); // => PasteFromSystem() ??? + break; + + // + // sonstiges + // + + case FID_INS_ROWBRK: + pTabViewShell->InsertPageBreak( sal_False ); + rReq.Done(); + break; + + case FID_INS_COLBRK: + pTabViewShell->InsertPageBreak( sal_True ); + rReq.Done(); + break; + + case FID_DEL_ROWBRK: + pTabViewShell->DeletePageBreak( sal_False ); + rReq.Done(); + break; + + case FID_DEL_COLBRK: + pTabViewShell->DeletePageBreak( sal_True ); + rReq.Done(); + break; + + case SID_DETECTIVE_ADD_PRED: + pTabViewShell->DetectiveAddPred(); + rReq.Done(); + break; + + case SID_DETECTIVE_DEL_PRED: + pTabViewShell->DetectiveDelPred(); + rReq.Done(); + break; + + case SID_DETECTIVE_ADD_SUCC: + pTabViewShell->DetectiveAddSucc(); + rReq.Done(); + break; + + case SID_DETECTIVE_DEL_SUCC: + pTabViewShell->DetectiveDelSucc(); + rReq.Done(); + break; + + case SID_DETECTIVE_ADD_ERR: + pTabViewShell->DetectiveAddError(); + rReq.Done(); + break; + + case SID_DETECTIVE_INVALID: + pTabViewShell->DetectiveMarkInvalid(); + rReq.Done(); + break; + + case SID_DETECTIVE_REFRESH: + pTabViewShell->DetectiveRefresh(); + rReq.Done(); + break; + + case SID_SPELL_DIALOG: +// pTabViewShell->DoSpellingChecker(); + { + SfxViewFrame* pViewFrame = pTabViewShell->GetViewFrame(); + if( rReq.GetArgs() ) + pViewFrame->SetChildWindow( SID_SPELL_DIALOG, + static_cast< const SfxBoolItem& >( rReq.GetArgs()-> + Get( SID_SPELL_DIALOG ) ).GetValue() ); + else + pViewFrame->ToggleChildWindow( SID_SPELL_DIALOG ); + + pViewFrame->GetBindings().Invalidate( SID_SPELL_DIALOG ); + rReq.Ignore(); + } + break; + + case SID_HANGUL_HANJA_CONVERSION: + pTabViewShell->DoHangulHanjaConversion(); + break; + + case SID_CHINESE_CONVERSION: + { + //open ChineseTranslationDialog + Reference< XComponentContext > xContext( + ::cppu::defaultBootstrap_InitialComponentContext() ); //@todo get context from calc if that has one + if(xContext.is()) + { + Reference< lang::XMultiComponentFactory > xMCF( xContext->getServiceManager() ); + if(xMCF.is()) + { + Reference< ui::dialogs::XExecutableDialog > xDialog( + xMCF->createInstanceWithContext( + rtl::OUString::createFromAscii("com.sun.star.linguistic2.ChineseTranslationDialog") + , xContext), UNO_QUERY); + Reference< lang::XInitialization > xInit( xDialog, UNO_QUERY ); + if( xInit.is() ) + { + // initialize dialog + Reference< awt::XWindow > xDialogParentWindow(0); + Sequence<Any> aSeq(1); + Any* pArray = aSeq.getArray(); + PropertyValue aParam; + aParam.Name = rtl::OUString::createFromAscii("ParentWindow"); + aParam.Value <<= makeAny(xDialogParentWindow); + pArray[0] <<= makeAny(aParam); + xInit->initialize( aSeq ); + + //execute dialog + sal_Int16 nDialogRet = xDialog->execute(); + if( RET_OK == nDialogRet ) + { + //get some parameters from the dialog + sal_Bool bToSimplified = sal_True; + sal_Bool bUseVariants = sal_True; + sal_Bool bCommonTerms = sal_True; + Reference< beans::XPropertySet > xProp( xDialog, UNO_QUERY ); + if( xProp.is() ) + { + try + { + xProp->getPropertyValue( C2U("IsDirectionToSimplified") ) >>= bToSimplified; + xProp->getPropertyValue( C2U("IsUseCharacterVariants") ) >>= bUseVariants; + xProp->getPropertyValue( C2U("IsTranslateCommonTerms") ) >>= bCommonTerms; + } + catch( Exception& ) + { + } + } + + //execute translation + LanguageType eSourceLang = bToSimplified ? LANGUAGE_CHINESE_TRADITIONAL : LANGUAGE_CHINESE_SIMPLIFIED; + LanguageType eTargetLang = bToSimplified ? LANGUAGE_CHINESE_SIMPLIFIED : LANGUAGE_CHINESE_TRADITIONAL; + sal_Int32 nOptions = bUseVariants ? i18n::TextConversionOption::USE_CHARACTER_VARIANTS : 0; + if( !bCommonTerms ) + nOptions |= i18n::TextConversionOption::CHARACTER_BY_CHARACTER; + + Font aTargetFont = GetViewData()->GetActiveWin()->GetDefaultFont( + DEFAULTFONT_CJK_SPREADSHEET, + eTargetLang, DEFAULTFONT_FLAGS_ONLYONE ); + ScConversionParam aConvParam( SC_CONVERSION_CHINESE_TRANSL, + eSourceLang, eTargetLang, aTargetFont, nOptions, false ); + pTabViewShell->DoSheetConversion( aConvParam ); + } + } + Reference< lang::XComponent > xComponent( xDialog, UNO_QUERY ); + if( xComponent.is() ) + xComponent->dispose(); + } + } + } + break; + + case SID_THESAURUS: + pTabViewShell->DoThesaurus(); + break; + + case SID_TOGGLE_REL: + pTabViewShell->DoRefConversion(); + break; + + case SID_DEC_INDENT: + pTabViewShell->ChangeIndent( sal_False ); + break; + case SID_INC_INDENT: + pTabViewShell->ChangeIndent( sal_True ); + break; + + case FID_USE_NAME: + { + sal_uInt16 nFlags = pTabViewShell->GetCreateNameFlags(); + + //CHINA001 ScNameCreateDlg* pDlg = new ScNameCreateDlg( pTabViewShell->GetDialogParent(), nFlags ); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + AbstractScNameCreateDlg* pDlg = pFact->CreateScNameCreateDlg(pTabViewShell->GetDialogParent(), nFlags, RID_SCDLG_NAMES_CREATE ); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + + if( pDlg->Execute() ) + { + nFlags = pDlg->GetFlags(); + pTabViewShell->CreateNames(nFlags); + rReq.Done(); + } + delete pDlg; + } + break; + + case SID_CONSOLIDATE: + { + const SfxPoolItem* pItem; + if ( pReqArgs && SFX_ITEM_SET == + pReqArgs->GetItemState( SCITEM_CONSOLIDATEDATA, sal_True, &pItem ) ) + { + const ScConsolidateParam& rParam = + ((const ScConsolidateItem*)pItem)->GetData(); + + pTabViewShell->Consolidate( rParam ); + GetViewData()->GetDocument()->SetConsolidateDlgData( &rParam ); + + rReq.Done(); + } + else if (rReq.IsAPI()) + SbxBase::SetError(SbxERR_BAD_PARAMETER); + } + break; + + case SID_INS_FUNCTION: + { + const SfxBoolItem* pOkItem = (const SfxBoolItem*)&pReqArgs->Get( SID_DLG_RETOK ); + +// pScMod->SetFunctionDlg( NULL ); + + if ( pOkItem->GetValue() ) // OK + { + String aFormula; + const SfxStringItem* pSItem = (const SfxStringItem*)&pReqArgs->Get( SCITEM_STRING ); + const SfxBoolItem* pMatrixItem = (const SfxBoolItem*) &pReqArgs->Get( SID_DLG_MATRIX ); + + aFormula += pSItem->GetValue(); + pScMod->ActivateInputWindow( &aFormula, pMatrixItem->GetValue() ); + } + else // CANCEL + { + pScMod->ActivateInputWindow( NULL ); + } + rReq.Ignore(); // only SID_ENTER_STRING is recorded + } + break; + + case FID_DEFINE_NAME: + if ( pReqArgs ) + { + const SfxPoolItem* pItem; + String aName, aSymbol, aAttrib; + + if( IS_AVAILABLE( FID_DEFINE_NAME, &pItem ) ) + aName = ((const SfxStringItem*)pItem)->GetValue(); + + if( IS_AVAILABLE( FN_PARAM_1, &pItem ) ) + aSymbol = ((const SfxStringItem*)pItem)->GetValue(); + + if( IS_AVAILABLE( FN_PARAM_2, &pItem ) ) + aAttrib = ((const SfxStringItem*)pItem)->GetValue(); + + if ( aName.Len() && aSymbol.Len() ) + { + if (pTabViewShell->InsertName( aName, aSymbol, aAttrib )) + rReq.Done(); + else + SbxBase::SetError( SbxERR_BAD_PARAMETER ); // Basic-Fehler + } + } + else + { + sal_uInt16 nId = ScNameDlgWrapper::GetChildWindowId(); + SfxViewFrame* pViewFrm = pTabViewShell->GetViewFrame(); + SfxChildWindow* pWnd = pViewFrm->GetChildWindow( nId ); + + pScMod->SetRefDialog( nId, pWnd ? sal_False : sal_True ); + } + break; + + case SID_DEFINE_COLROWNAMERANGES: + { + + sal_uInt16 nId = ScColRowNameRangesDlgWrapper::GetChildWindowId(); + SfxViewFrame* pViewFrm = pTabViewShell->GetViewFrame(); + SfxChildWindow* pWnd = pViewFrm->GetChildWindow( nId ); + + pScMod->SetRefDialog( nId, pWnd ? sal_False : sal_True ); + + } + break; + + case SID_UPDATECHART: + { + sal_Bool bAll = sal_False; + + if( pReqArgs ) + { + const SfxPoolItem* pItem; + + if( IS_AVAILABLE( SID_UPDATECHART, &pItem ) ) + bAll = ((const SfxBoolItem*)pItem)->GetValue(); + } + + pTabViewShell->UpdateCharts( bAll ); + + if( ! rReq.IsAPI() ) + { + rReq.AppendItem( SfxBoolItem( SID_UPDATECHART, bAll ) ); + rReq.Done(); + } + } + break; + + + case SID_TABOP: + if (pReqArgs) + { + const ScTabOpItem& rItem = + (const ScTabOpItem&) + pReqArgs->Get( SID_TABOP ); + + pTabViewShell->TabOp( rItem.GetData() ); + + rReq.Done( *pReqArgs ); + } + break; + + case SID_SOLVE: + if (pReqArgs) + { + const ScSolveItem& rItem = + (const ScSolveItem&) + pReqArgs->Get( SCITEM_SOLVEDATA ); + + pTabViewShell->Solve( rItem.GetData() ); + + rReq.Done( *pReqArgs ); + } + break; + + case FID_INSERT_NAME: + { + ScDocument* pDoc = GetViewData()->GetDocument(); + //CHINA001 ScNamePasteDlg* pDlg = new ScNamePasteDlg( pTabViewShell->GetDialogParent(), pDoc->GetRangeName() ); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + AbstractScNamePasteDlg* pDlg = pFact->CreateScNamePasteDlg( pTabViewShell->GetDialogParent(), pDoc->GetRangeName(), RID_SCDLG_NAMES_PASTE ); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + switch( pDlg->Execute() ) + { + case BTN_PASTE_LIST: + pTabViewShell->InsertNameList(); + break; + case BTN_PASTE_NAME: + { + ScInputHandler* pHdl = pScMod->GetInputHdl( pTabViewShell ); + if (pHdl) + { + // das "=" per Key-Event, schaltet in den Eingabe-Modus + pScMod->InputKeyEvent( KeyEvent('=',KeyCode()) ); + + String aName = pDlg->GetSelectedName(); + pHdl->InsertFunction( aName, sal_False ); // ohne "()" + } + } + break; + } + delete pDlg; + } + break; + + case SID_RANGE_NOTETEXT: + if (pReqArgs) + { + const SfxStringItem& rTextItem = (const SfxStringItem&)pReqArgs->Get( SID_RANGE_NOTETEXT ); + + // #43343# immer Cursorposition + ScAddress aPos( GetViewData()->GetCurX(), GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); + pTabViewShell->SetNoteText( aPos, rTextItem.GetValue() ); + rReq.Done(); + } + break; + + case SID_INSERT_POSTIT: + if ( pReqArgs ) + { + const SvxPostItAuthorItem& rAuthorItem = (const SvxPostItAuthorItem&)pReqArgs->Get( SID_ATTR_POSTIT_AUTHOR ); + const SvxPostItDateItem& rDateItem = (const SvxPostItDateItem&) pReqArgs->Get( SID_ATTR_POSTIT_DATE ); + const SvxPostItTextItem& rTextItem = (const SvxPostItTextItem&) pReqArgs->Get( SID_ATTR_POSTIT_TEXT ); + + ScAddress aPos( GetViewData()->GetCurX(), GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); + pTabViewShell->ReplaceNote( aPos, rTextItem.GetValue(), &rAuthorItem.GetValue(), &rDateItem.GetValue() ); + rReq.Done(); + } + else + { + pTabViewShell->EditNote(); // Zeichenobjekt zum Editieren + } + break; + + case FID_NOTE_VISIBLE: + { + ScDocument* pDoc = GetViewData()->GetDocument(); + ScAddress aPos( GetViewData()->GetCurX(), GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); + if( ScPostIt* pNote = pDoc->GetNote( aPos ) ) + { + bool bShow; + const SfxPoolItem* pItem; + if ( pReqArgs && (pReqArgs->GetItemState( FID_NOTE_VISIBLE, sal_True, &pItem ) == SFX_ITEM_SET) ) + bShow = ((const SfxBoolItem*) pItem)->GetValue(); + else + bShow = !pNote->IsCaptionShown(); + + pTabViewShell->ShowNote( bShow ); + + if (!pReqArgs) + rReq.AppendItem( SfxBoolItem( FID_NOTE_VISIBLE, bShow ) ); + + rReq.Done(); + rBindings.Invalidate( FID_NOTE_VISIBLE ); + } + else + rReq.Ignore(); + } + break; + + case SID_DELETE_NOTE: + pTabViewShell->DeleteContents( IDF_NOTE ); // delete all notes in selection + rReq.Done(); + break; + + case SID_CHARMAP: + if( pReqArgs != NULL ) + { + String aChars, aFontName; + const SfxItemSet *pArgs = rReq.GetArgs(); + const SfxPoolItem* pItem = 0; + if ( pArgs ) + pArgs->GetItemState(GetPool().GetWhich(SID_CHARMAP), sal_False, &pItem); + if ( pItem ) + { + const SfxStringItem* pStringItem = PTR_CAST( SfxStringItem, pItem ); + if ( pStringItem ) + aChars = pStringItem->GetValue(); + const SfxPoolItem* pFtItem = NULL; + pArgs->GetItemState( GetPool().GetWhich(SID_ATTR_SPECIALCHAR), sal_False, &pFtItem); + const SfxStringItem* pFontItem = PTR_CAST( SfxStringItem, pFtItem ); + if ( pFontItem ) + aFontName = pFontItem->GetValue(); + } + + if ( aChars.Len() ) + { + Font aFont; + pTabViewShell->GetSelectionPattern()->GetFont( aFont, SC_AUTOCOL_BLACK, NULL, NULL, NULL, + pTabViewShell->GetSelectionScriptType() ); + if ( aFontName.Len() ) + aFont = Font( aFontName, Size(1,1) ); + pTabViewShell->InsertSpecialChar( aChars, aFont ); + if( ! rReq.IsAPI() ) + rReq.Done(); + } + } + else + { + //CHINA001 SvxCharacterMap* pDlg = new SvxCharacterMap( pTabViewShell->GetDialogParent(), sal_False ); + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + + // font color doesn't matter here + Font aCurFont; + pTabViewShell->GetSelectionPattern()->GetFont( aCurFont, SC_AUTOCOL_BLACK, NULL, NULL, NULL, + pTabViewShell->GetSelectionScriptType() ); + + SfxAllItemSet aSet( GetPool() ); + aSet.Put( SfxBoolItem( FN_PARAM_1, sal_False ) ); + aSet.Put( SvxFontItem( aCurFont.GetFamily(), aCurFont.GetName(), aCurFont.GetStyleName(), aCurFont.GetPitch(), aCurFont.GetCharSet(), GetPool().GetWhich(SID_ATTR_CHAR_FONT) ) ); + + SfxAbstractDialog* pDlg = pFact->CreateSfxDialog( pTabViewShell->GetDialogParent(), aSet, + pTabViewShell->GetViewFrame()->GetFrame().GetFrameInterface(), RID_SVXDLG_CHARMAP ); + + if ( pDlg->Execute() == RET_OK ) + { + SFX_ITEMSET_ARG( pDlg->GetOutputItemSet(), pItem, SfxStringItem, SID_CHARMAP, sal_False ); + SFX_ITEMSET_ARG( pDlg->GetOutputItemSet(), pFontItem, SvxFontItem, SID_ATTR_CHAR_FONT, sal_False ); + + if ( pItem && pFontItem ) + { + Font aNewFont( pFontItem->GetFamilyName(), pFontItem->GetStyleName(), Size(1,1) ); + aNewFont.SetCharSet( pFontItem->GetCharSet() ); + aNewFont.SetPitch( pFontItem->GetPitch() ); + pTabViewShell->InsertSpecialChar( pItem->GetValue(), aNewFont ); + rReq.AppendItem( *pFontItem ); + rReq.AppendItem( *pItem ); + rReq.Done(); + } + } + delete pDlg; + } + break; + + case SID_SELECT_SCENARIO: + { + // Testing + + if ( pReqArgs ) + { + const SfxStringItem* pItem = + (const SfxStringItem*)&pReqArgs->Get( SID_SELECT_SCENARIO ); + + if( pItem ) + { + pTabViewShell->UseScenario( pItem->GetValue() ); + //! wofuer soll der Return-Wert gut sein?!?! + rReq.SetReturnValue( SfxStringItem( SID_SELECT_SCENARIO, pItem->GetValue() ) ); + rReq.Done(); + } + else + { + DBG_ERROR("NULL"); + } + } + } + break; + + case SID_HYPERLINK_SETLINK: + if( pReqArgs ) + { + const SfxPoolItem* pItem; + if( IS_AVAILABLE( SID_HYPERLINK_SETLINK, &pItem ) ) + { + const SvxHyperlinkItem* pHyper = (const SvxHyperlinkItem*) pItem; + const String& rName = pHyper->GetName(); + const String& rURL = pHyper->GetURL(); + const String& rTarget = pHyper->GetTargetFrame(); + sal_uInt16 nType = (sal_uInt16) pHyper->GetInsertMode(); + + pTabViewShell->InsertURL( rName, rURL, rTarget, nType ); + rReq.Done(); + } + else + rReq.Ignore(); + } + break; + + case FID_CONDITIONAL_FORMAT: + if( pReqArgs ) + { + const SfxPoolItem* pItem; + if( IS_AVAILABLE( FID_CONDITIONAL_FORMAT, &pItem ) ) + { + // Wenn RefInput auf andere Tabelle als Datentabelle umgeschaltet + // hat wieder zurueckschalten: + if ( GetViewData()->GetTabNo() != GetViewData()->GetRefTabNo() ) + { + pTabViewShell->SetTabNo( GetViewData()->GetRefTabNo() ); + pTabViewShell->PaintExtras(); + } + + const ScCondFrmtItem* pCndFmtItem = (const ScCondFrmtItem*) pItem; + pTabViewShell->SetConditionalFormat( pCndFmtItem->GetData() ); + rReq.Done(); + } + } + break; + + case SID_EXTERNAL_SOURCE: + { + String aFile; + String aFilter; + String aOptions; + String aSource; + sal_uLong nRefresh=0; + + SFX_REQUEST_ARG( rReq, pFile, SfxStringItem, SID_FILE_NAME, sal_False ); + SFX_REQUEST_ARG( rReq, pSource, SfxStringItem, FN_PARAM_1, sal_False ); + if ( pFile && pSource ) + { + aFile = pFile->GetValue(); + aSource = pSource->GetValue(); + SFX_REQUEST_ARG( rReq, pFilter, SfxStringItem, SID_FILTER_NAME, sal_False ); + if ( pFilter ) + aFilter = pFilter->GetValue(); + SFX_REQUEST_ARG( rReq, pOptions, SfxStringItem, SID_FILE_FILTEROPTIONS, sal_False ); + if ( pOptions ) + aOptions = pOptions->GetValue(); + SFX_REQUEST_ARG( rReq, pRefresh, SfxUInt32Item, FN_PARAM_2, sal_False ); + if ( pRefresh ) + nRefresh = pRefresh->GetValue(); + } + else + { + //CHINA001 ScLinkedAreaDlg* pDlg = new ScLinkedAreaDlg( pTabViewShell->GetDialogParent() ); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + delete pImpl->m_pLinkedDlg; + pImpl->m_pLinkedDlg = + pFact->CreateScLinkedAreaDlg( pTabViewShell->GetDialogParent(), + RID_SCDLG_LINKAREA); + DBG_ASSERT(pImpl->m_pLinkedDlg, "Dialog create fail!");//CHINA001 + delete pImpl->m_pRequest; + pImpl->m_pRequest = new SfxRequest( rReq ); + pImpl->m_pLinkedDlg->StartExecuteModal( LINK( this, ScCellShell, DialogClosed ) ); + return; + } + + ExecuteExternalSource( aFile, aFilter, aOptions, aSource, nRefresh, rReq ); + } + break; + + // + // + // + + default: + DBG_ERROR("falscher Slot bei ExecuteEdit"); + break; + } +} + +void ScCellShell::ExecuteTrans( SfxRequest& rReq ) +{ + sal_Int32 nType = ScViewUtil::GetTransliterationType( rReq.GetSlot() ); + if ( nType ) + { + GetViewData()->GetView()->TransliterateText( nType ); + rReq.Done(); + } +} + +void ScCellShell::ExecuteExternalSource( + const String& _rFile, const String& _rFilter, const String& _rOptions, + const String& _rSource, sal_uLong _nRefresh, SfxRequest& _rRequest ) +{ + if ( _rFile.Len() && _rSource.Len() ) // filter may be empty + { + ScRange aLinkRange; + sal_Bool bMove = sal_False; + + ScViewData* pData = GetViewData(); + ScMarkData& rMark = pData->GetMarkData(); + rMark.MarkToSimple(); + if ( rMark.IsMarked() ) + { + rMark.GetMarkArea( aLinkRange ); + bMove = sal_True; // insert/delete cells to fit range + } + else + aLinkRange = ScRange( pData->GetCurX(), pData->GetCurY(), pData->GetTabNo() ); + + ScDocFunc aFunc(*pData->GetDocShell()); + aFunc.InsertAreaLink( _rFile, _rFilter, _rOptions, _rSource, + aLinkRange, _nRefresh, bMove, sal_False ); + _rRequest.Done(); + } + else + _rRequest.Ignore(); +} + +IMPL_LINK( ScCellShell, DialogClosed, AbstractScLinkedAreaDlg*, EMPTYARG ) +{ + DBG_ASSERT( pImpl->m_pLinkedDlg, "ScCellShell::DialogClosed(): invalid request" ); + DBG_ASSERT( pImpl->m_pRequest, "ScCellShell::DialogClosed(): invalid request" ); + String sFile, sFilter, sOptions, sSource; + sal_uLong nRefresh = 0; + + if ( pImpl->m_pLinkedDlg->GetResult() == RET_OK ) + { + sFile = pImpl->m_pLinkedDlg->GetURL(); + sFilter = pImpl->m_pLinkedDlg->GetFilter(); + sOptions = pImpl->m_pLinkedDlg->GetOptions(); + sSource = pImpl->m_pLinkedDlg->GetSource(); + nRefresh = pImpl->m_pLinkedDlg->GetRefresh(); + if ( sFile.Len() ) + pImpl->m_pRequest->AppendItem( SfxStringItem( SID_FILE_NAME, sFile ) ); + if ( sFilter.Len() ) + pImpl->m_pRequest->AppendItem( SfxStringItem( SID_FILTER_NAME, sFilter ) ); + if ( sOptions.Len() ) + pImpl->m_pRequest->AppendItem( SfxStringItem( SID_FILE_FILTEROPTIONS, sOptions ) ); + if ( sSource.Len() ) + pImpl->m_pRequest->AppendItem( SfxStringItem( FN_PARAM_1, sSource ) ); + if ( nRefresh ) + pImpl->m_pRequest->AppendItem( SfxUInt32Item( FN_PARAM_2, nRefresh ) ); + } + + ExecuteExternalSource( sFile, sFilter, sOptions, sSource, nRefresh, *(pImpl->m_pRequest) ); + return 0; +} + +void ScCellShell::PasteFromClipboard( ScViewData* pViewData, ScTabViewShell* pTabViewShell, bool bShowDialog ) +{ + Window* pWin = pViewData->GetActiveWin(); + ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin ); + ScDocument* pThisDoc = pViewData->GetDocument(); + ScDPObject* pDPObj = pThisDoc->GetDPAtCursor( pViewData->GetCurX(), + pViewData->GetCurY(), pViewData->GetTabNo() ); + if ( pOwnClip && pDPObj ) + { + // paste from Calc into DataPilot table: sort (similar to drag & drop) + + ScDocument* pClipDoc = pOwnClip->GetDocument(); + SCTAB nSourceTab = pOwnClip->GetVisibleTab(); + + SCCOL nClipStartX; + SCROW nClipStartY; + SCCOL nClipEndX; + SCROW nClipEndY; + pClipDoc->GetClipStart( nClipStartX, nClipStartY ); + pClipDoc->GetClipArea( nClipEndX, nClipEndY, sal_True ); + nClipEndX = nClipEndX + nClipStartX; + nClipEndY = nClipEndY + nClipStartY; // GetClipArea returns the difference + + ScRange aSource( nClipStartX, nClipStartY, nSourceTab, nClipEndX, nClipEndY, nSourceTab ); + sal_Bool bDone = pTabViewShell->DataPilotMove( aSource, pViewData->GetCurPos() ); + if ( !bDone ) + pTabViewShell->ErrorMessage( STR_ERR_DATAPILOT_INPUT ); + } + else + { + // normal paste + WaitObject aWait( pViewData->GetDialogParent() ); + if (!pOwnClip) + pTabViewShell->PasteFromSystem(); + else + { + ScDocument* pClipDoc = pOwnClip->GetDocument(); + sal_uInt16 nFlags = IDF_ALL; + if (pClipDoc->GetClipParam().isMultiRange()) + // For multi-range paste, we paste values by default. + nFlags &= ~IDF_FORMULA; + + pTabViewShell->PasteFromClip( nFlags, pClipDoc, + PASTE_NOFUNC, sal_False, sal_False, sal_False, INS_NONE, IDF_NONE, + bShowDialog ); // allow warning dialog + } + } + pTabViewShell->CellContentChanged(); // => PasteFromSystem() ??? +} diff --git a/sc/source/ui/view/cellsh2.cxx b/sc/source/ui/view/cellsh2.cxx new file mode 100644 index 000000000000..eda6b5cb0efd --- /dev/null +++ b/sc/source/ui/view/cellsh2.cxx @@ -0,0 +1,1432 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +//------------------------------------------------------------------ + +// INCLUDE --------------------------------------------------------------- + +#include "scitems.hxx" +#include <sfx2/viewfrm.hxx> +#include <sfx2/app.hxx> +#include <sfx2/request.hxx> +#include <svl/aeitem.hxx> +#include <basic/sbxcore.hxx> +#include <svl/whiter.hxx> +#include <svl/zforlist.hxx> +#include <vcl/msgbox.hxx> +#include <svl/stritem.hxx> +#include <svl/visitem.hxx> +#include <unotools/moduleoptions.hxx> + +#include <com/sun/star/frame/FrameSearchFlag.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> + +#include "cellsh.hxx" +#include "tabvwsh.hxx" +#include "sc.hrc" +#include "globstr.hrc" +#include "global.hxx" +#include "scmod.hxx" +#include "docsh.hxx" +#include "document.hxx" +#include "uiitems.hxx" +#include "dbfunc.hxx" +#include "dbdocfun.hxx" +//CHINA001 #include "lbseldlg.hxx" +//CHINA001 #include "sortdlg.hxx" +#include "filtdlg.hxx" +#include "dbnamdlg.hxx" +//CHINA001 #include "subtdlg.hxx" +#include "reffact.hxx" +#include "pvlaydlg.hxx" +#include "validat.hxx" +#include "scresid.hxx" +//CHINA001 #include "validate.hxx" +#include "pivot.hxx" +#include "dpobject.hxx" +//CHINA001 #include "dapitype.hxx" +//CHINA001 #include "dapidata.hxx" +#include "dpsdbtab.hxx" // ScImportSourceDesc +#include "dpshttab.hxx" // ScSheetSourceDesc + +#include "validate.hrc" //CHINA001 add for ScValidationDlg +#include "scui_def.hxx" //CHINA001 +#include "scabstdlg.hxx" //CHINA001 +#include "impex.hxx" +#include "asciiopt.hxx" +using namespace com::sun::star; + +//#include "strindlg.hxx" //! Test !!!!! + +//static ScArea aPivotSource; //! wohin? (ueber den Dialog retten) + + +#define IS_AVAILABLE(WhichId,ppItem) \ + (pReqArgs->GetItemState((WhichId), sal_True, ppItem ) == SFX_ITEM_SET) + +//------------------------------------------------------------------ + +bool lcl_GetTextToColumnsRange( const ScViewData* pData, ScRange& rRange ) +{ + DBG_ASSERT( pData, "lcl_GetTextToColumnsRange: pData is null!" ); + + bool bRet = false; + const ScMarkData& rMark = pData->GetMarkData(); + + if ( rMark.IsMarked() ) + { + if ( !rMark.IsMultiMarked() ) + { + rMark.GetMarkArea( rRange ); + if ( rRange.aStart.Col() == rRange.aEnd.Col() ) + { + bRet = true; + } + } + } + else + { + const SCCOL nCol = pData->GetCurX(); + const SCROW nRow = pData->GetCurY(); + const SCTAB nTab = pData->GetTabNo(); + rRange = ScRange( nCol, nRow, nTab, nCol, nRow, nTab ); + bRet = true; + } + + const ScDocument* pDoc = pData->GetDocument(); + DBG_ASSERT( pDoc, "lcl_GetTextToColumnsRange: pDoc is null!" ); + + if ( bRet && pDoc->IsBlockEmpty( rRange.aStart.Tab(), rRange.aStart.Col(), + rRange.aStart.Row(), rRange.aEnd.Col(), + rRange.aEnd.Row() ) ) + { + bRet = false; + } + + return bRet; +} + +sal_Bool lcl_GetSortParam( const ScViewData* pData, ScSortParam& rSortParam ) +{ + ScTabViewShell* pTabViewShell = pData->GetViewShell(); + ScDBData* pDBData = pTabViewShell->GetDBData(); + ScDocument* pDoc = pData->GetDocument(); + SCTAB nTab = pData->GetTabNo(); + ScDirection eFillDir = DIR_TOP; + sal_Bool bSort = sal_True; + ScRange aExternalRange; + + if( rSortParam.nCol1 != rSortParam.nCol2 ) + eFillDir = DIR_LEFT; + if( rSortParam.nRow1 != rSortParam.nRow2 ) + eFillDir = DIR_TOP; + + SCSIZE nCount = pDoc->GetEmptyLinesInBlock( rSortParam.nCol1, rSortParam.nRow1, nTab, rSortParam.nCol2, rSortParam.nRow2, nTab, eFillDir ); + + if( rSortParam.nRow2 == MAXROW ) + aExternalRange = ScRange( rSortParam.nCol1,sal::static_int_cast<SCROW>( nCount ), nTab ); + else + aExternalRange = ScRange( pData->GetCurX(), pData->GetCurY(), nTab ); + + SCROW nStartRow = aExternalRange.aStart.Row(); + SCCOL nStartCol = aExternalRange.aStart.Col(); + SCROW nEndRow = aExternalRange.aEnd.Row(); + SCCOL nEndCol = aExternalRange.aEnd.Col(); + pDoc->GetDataArea( aExternalRange.aStart.Tab(), nStartCol, nStartRow, nEndCol, nEndRow, sal_False, false ); + aExternalRange.aStart.SetRow( nStartRow ); + aExternalRange.aStart.SetCol( nStartCol ); + aExternalRange.aEnd.SetRow( nEndRow ); + aExternalRange.aEnd.SetCol( nEndCol ); + + if(( rSortParam.nCol1 == rSortParam.nCol2 && aExternalRange.aStart.Col() != aExternalRange.aEnd.Col() ) || + ( rSortParam.nRow1 == rSortParam.nRow2 && aExternalRange.aStart.Row() != aExternalRange.aEnd.Row() ) ) + { + sal_uInt16 nFmt = SCA_VALID; + String aExtendStr,aCurrentStr; + + pTabViewShell->AddHighlightRange( aExternalRange,Color( COL_LIGHTBLUE ) ); + ScRange rExtendRange( aExternalRange.aStart.Col(), aExternalRange.aStart.Row(), nTab, aExternalRange.aEnd.Col(), aExternalRange.aEnd.Row(), nTab ); + rExtendRange.Format( aExtendStr, nFmt, pDoc ); + + ScRange rCurrentRange( rSortParam.nCol1, rSortParam.nRow1, nTab, rSortParam.nCol2, rSortParam.nRow2, nTab ); + rCurrentRange.Format( aCurrentStr, nFmt, pDoc ); + + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + VclAbstractDialog* pWarningDlg = pFact->CreateScSortWarningDlg( pTabViewShell->GetDialogParent(),aExtendStr,aCurrentStr,RID_SCDLG_SORT_WARNING ); + DBG_ASSERT(pWarningDlg, "Dialog create fail!");//CHINA001 + short bResult = pWarningDlg->Execute(); + if( bResult == BTN_EXTEND_RANGE || bResult == BTN_CURRENT_SELECTION ) + { + if( bResult == BTN_EXTEND_RANGE ) + { + pTabViewShell->MarkRange( aExternalRange, sal_False ); + pDBData->SetArea( nTab, aExternalRange.aStart.Col(), aExternalRange.aStart.Row(), aExternalRange.aEnd.Col(), aExternalRange.aEnd.Row() ); + } + } + else + { + bSort = sal_False; + pData->GetDocShell()->CancelAutoDBRange(); + } + + delete pWarningDlg; + pTabViewShell->ClearHighlightRanges(); + } + return bSort; +} + +//<!-- Added by PengYunQuan for Validity Cell Range Picker +//after end execute from !IsModalInputMode, it is safer to delay deleting +namespace +{ + long DelayDeleteAbstractDialog( void *pAbstractDialog, void * /*pArg*/ ) + { + delete reinterpret_cast<VclAbstractDialog*>( pAbstractDialog ); + return 0; + } +} +//--> Added by PengYunQuan for Validity Cell Range Picker + +void ScCellShell::ExecuteDB( SfxRequest& rReq ) +{ + ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell(); + sal_uInt16 nSlotId = rReq.GetSlot(); + const SfxItemSet* pReqArgs = rReq.GetArgs(); + ScModule* pScMod = SC_MOD(); + + pTabViewShell->HideListBox(); // Autofilter-DropDown-Listbox + + if ( GetViewData()->HasEditView( GetViewData()->GetActivePart() ) ) + { + pScMod->InputEnterHandler(); + pTabViewShell->UpdateInputHandler(); + } + + switch ( nSlotId ) + { + case SID_VIEW_DATA_SOURCE_BROWSER: + { + // check if database beamer is open + + SfxViewFrame* pViewFrame = pTabViewShell->GetViewFrame(); + sal_Bool bWasOpen = sal_False; + { + uno::Reference<frame::XFrame> xFrame = pViewFrame->GetFrame().GetFrameInterface(); + uno::Reference<frame::XFrame> xBeamerFrame = xFrame->findFrame( + rtl::OUString::createFromAscii("_beamer"), + frame::FrameSearchFlag::CHILDREN); + if ( xBeamerFrame.is() ) + bWasOpen = sal_True; + } + + if ( bWasOpen ) + { + // close database beamer: just forward to SfxViewFrame + + pViewFrame->ExecuteSlot( rReq ); + } + else + { + // show database beamer: SfxViewFrame call must be synchronous + + pViewFrame->ExecuteSlot( rReq, (sal_Bool) sal_False ); // sal_False = synchronous + + // select current database in database beamer + + ScImportParam aImportParam; + ScDBData* pDBData = pTabViewShell->GetDBData(sal_True,SC_DB_OLD); // don't create if none found + if (pDBData) + pDBData->GetImportParam( aImportParam ); + + ScDBDocFunc::ShowInBeamer( aImportParam, pTabViewShell->GetViewFrame() ); + } + rReq.Done(); // needed because it's a toggle slot + } + break; + + case SID_REIMPORT_DATA: + { + sal_Bool bOk = sal_False; + ScDBData* pDBData = pTabViewShell->GetDBData(sal_True,SC_DB_OLD); + if (pDBData) + { + ScImportParam aImportParam; + pDBData->GetImportParam( aImportParam ); + if (aImportParam.bImport && !pDBData->HasImportSelection()) + { + pTabViewShell->ImportData( aImportParam ); + pDBData->SetImportParam( aImportParam ); //! Undo ?? + bOk = sal_True; + } + } + + if (!bOk && ! rReq.IsAPI() ) + pTabViewShell->ErrorMessage(STR_REIMPORT_EMPTY); + + if( bOk ) + rReq.Done(); + } + break; + + case SID_REFRESH_DBAREA: + { + ScDBData* pDBData = pTabViewShell->GetDBData(sal_True,SC_DB_OLD); + if (pDBData) + { + // Import wiederholen wie SID_REIMPORT_DATA + + sal_Bool bContinue = sal_True; + ScImportParam aImportParam; + pDBData->GetImportParam( aImportParam ); + if (aImportParam.bImport && !pDBData->HasImportSelection()) + { + bContinue = pTabViewShell->ImportData( aImportParam ); + pDBData->SetImportParam( aImportParam ); //! Undo ?? + + // markieren (Groesse kann sich geaendert haben) + ScRange aNewRange; + pDBData->GetArea(aNewRange); + pTabViewShell->MarkRange(aNewRange); + } + + if ( bContinue ) // #41905# Fehler beim Import -> Abbruch + { + // interne Operationen, wenn welche gespeichert + + if ( pDBData->HasQueryParam() || pDBData->HasSortParam() || + pDBData->HasSubTotalParam() ) + pTabViewShell->RepeatDB(); + + // Pivottabellen die den Bereich als Quelldaten haben + + ScRange aRange; + pDBData->GetArea(aRange); + GetViewData()->GetDocShell()->RefreshPivotTables(aRange); + } + } + rReq.Done(); + } + break; + + case SID_SBA_BRW_INSERT: + { + DBG_ERROR( "Deprecated Slot" ); + } + break; + + case SID_SUBTOTALS: + { + const SfxItemSet* pArgs = rReq.GetArgs(); + if ( pArgs ) + { + pTabViewShell->DoSubTotals( ((const ScSubTotalItem&) pArgs->Get( SCITEM_SUBTDATA )). + GetSubTotalData() ); + rReq.Done(); + } + else + { + //CHINA001 ScSubTotalDlg* pDlg = NULL; + SfxAbstractTabDialog * pDlg = NULL; + ScSubTotalParam aSubTotalParam; + SfxItemSet aArgSet( GetPool(), SCITEM_SUBTDATA, SCITEM_SUBTDATA ); + + ScDBData* pDBData = pTabViewShell->GetDBData(); + pDBData->GetSubTotalParam( aSubTotalParam ); + aSubTotalParam.bRemoveOnly = sal_False; + + aArgSet.Put( ScSubTotalItem( SCITEM_SUBTDATA, GetViewData(), &aSubTotalParam ) ); + //CHINA001 pDlg = new ScSubTotalDlg( pTabViewShell->GetDialogParent(), &aArgSet ); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + pDlg = pFact->CreateScSubTotalDlg( pTabViewShell->GetDialogParent(), &aArgSet, RID_SCDLG_SUBTOTALS ); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + pDlg->SetCurPageId(1); + + short bResult = pDlg->Execute(); + + if ( (bResult == RET_OK) || (bResult == SCRET_REMOVE) ) + { + const SfxItemSet* pOutSet = NULL; + + if ( bResult == RET_OK ) + { + pOutSet = pDlg->GetOutputItemSet(); + aSubTotalParam = + ((const ScSubTotalItem&) + pOutSet->Get( SCITEM_SUBTDATA )). + GetSubTotalData(); + } + else // if (bResult == SCRET_REMOVE) + { + pOutSet = &aArgSet; + aSubTotalParam.bRemoveOnly = sal_True; + aSubTotalParam.bReplace = sal_True; + aArgSet.Put( ScSubTotalItem( SCITEM_SUBTDATA, + GetViewData(), + &aSubTotalParam ) ); + } + + pTabViewShell->DoSubTotals( aSubTotalParam ); + rReq.Done( *pOutSet ); + } + else + GetViewData()->GetDocShell()->CancelAutoDBRange(); + + delete pDlg; + } + } + break; + + case SID_SORT_DESCENDING: + case SID_SORT_ASCENDING: + { + //#i60401 ux-ctest: Calc does not support all users' strategies regarding sorting data + //the patch comes from maoyg + ScSortParam aSortParam; + ScDBData* pDBData = pTabViewShell->GetDBData(); + ScViewData* pData = GetViewData(); + + pDBData->GetSortParam( aSortParam ); + + if( lcl_GetSortParam( pData, aSortParam ) ) + { + SfxItemSet aArgSet( GetPool(), SCITEM_SORTDATA, SCITEM_SORTDATA ); + SCCOL nCol = GetViewData()->GetCurX(); + SCCOL nTab = GetViewData()->GetTabNo(); + ScDocument* pDoc = GetViewData()->GetDocument(); + + pDBData->GetSortParam( aSortParam ); + sal_Bool bHasHeader = pDoc->HasColHeader( aSortParam.nCol1, aSortParam.nRow1, aSortParam.nCol2, aSortParam.nRow2, nTab ); + + if( nCol < aSortParam.nCol1 ) + nCol = aSortParam.nCol1; + else if( nCol > aSortParam.nCol2 ) + nCol = aSortParam.nCol2; + + aSortParam.bHasHeader = bHasHeader; + aSortParam.bByRow = sal_True; + aSortParam.bCaseSens = sal_False; + aSortParam.bIncludePattern = sal_True; + aSortParam.bInplace = sal_True; + aSortParam.bDoSort[0] = sal_True; + aSortParam.nField[0] = nCol; + aSortParam.bAscending[0] = (nSlotId == SID_SORT_ASCENDING); + + for ( sal_uInt16 i=1; i<MAXSORT; i++ ) + aSortParam.bDoSort[i] = sal_False; + + aArgSet.Put( ScSortItem( SCITEM_SORTDATA, GetViewData(), &aSortParam ) ); + + pTabViewShell->UISort( aSortParam ); // Teilergebnisse bei Bedarf neu + + rReq.Done(); + } + } + break; + + case SID_SORT: + { + const SfxItemSet* pArgs = rReq.GetArgs(); + + //#i60401 ux-ctest: Calc does not support all users' strategies regarding sorting data + //the patch comes from maoyg + + if ( pArgs ) // Basic + { + ScSortParam aSortParam; + ScDBData* pDBData = pTabViewShell->GetDBData(); + ScViewData* pData = GetViewData(); + + pDBData->GetSortParam( aSortParam ); + + if( lcl_GetSortParam( pData, aSortParam ) ) + { + ScDocument* pDoc = GetViewData()->GetDocument(); + + pDBData->GetSortParam( aSortParam ); + sal_Bool bHasHeader = pDoc->HasColHeader( aSortParam.nCol1, aSortParam.nRow1, aSortParam.nCol2, aSortParam.nRow2, pData->GetTabNo() ); + if( bHasHeader ) + aSortParam.bHasHeader = bHasHeader; + + aSortParam.bInplace = sal_True; // von Basic immer + + const SfxPoolItem* pItem; + if ( pArgs->GetItemState( SID_SORT_BYROW, sal_True, &pItem ) == SFX_ITEM_SET ) + aSortParam.bByRow = ((const SfxBoolItem*)pItem)->GetValue(); + if ( pArgs->GetItemState( SID_SORT_HASHEADER, sal_True, &pItem ) == SFX_ITEM_SET ) + aSortParam.bHasHeader = ((const SfxBoolItem*)pItem)->GetValue(); + if ( pArgs->GetItemState( SID_SORT_CASESENS, sal_True, &pItem ) == SFX_ITEM_SET ) + aSortParam.bCaseSens = ((const SfxBoolItem*)pItem)->GetValue(); + if ( pArgs->GetItemState( SID_SORT_ATTRIBS, sal_True, &pItem ) == SFX_ITEM_SET ) + aSortParam.bIncludePattern = ((const SfxBoolItem*)pItem)->GetValue(); + if ( pArgs->GetItemState( SID_SORT_USERDEF, sal_True, &pItem ) == SFX_ITEM_SET ) + { + sal_uInt16 nUserIndex = ((const SfxUInt16Item*)pItem)->GetValue(); + aSortParam.bUserDef = ( nUserIndex != 0 ); + if ( nUserIndex ) + aSortParam.nUserIndex = nUserIndex - 1; // Basic: 1-basiert + } + + SCCOLROW nField0 = 0; + if ( pArgs->GetItemState( FN_PARAM_1, sal_True, &pItem ) == SFX_ITEM_SET ) + nField0 = ((const SfxInt32Item*)pItem)->GetValue(); + aSortParam.bDoSort[0] = ( nField0 != 0 ); + aSortParam.nField[0] = nField0 > 0 ? (nField0-1) : 0; + if ( pArgs->GetItemState( FN_PARAM_2, sal_True, &pItem ) == SFX_ITEM_SET ) + aSortParam.bAscending[0] = ((const SfxBoolItem*)pItem)->GetValue(); + SCCOLROW nField1 = 0; + if ( pArgs->GetItemState( FN_PARAM_3, sal_True, &pItem ) == SFX_ITEM_SET ) + nField1 = ((const SfxInt32Item*)pItem)->GetValue(); + aSortParam.bDoSort[1] = ( nField1 != 0 ); + aSortParam.nField[1] = nField1 > 0 ? (nField1-1) : 0; + if ( pArgs->GetItemState( FN_PARAM_4, sal_True, &pItem ) == SFX_ITEM_SET ) + aSortParam.bAscending[1] = ((const SfxBoolItem*)pItem)->GetValue(); + SCCOLROW nField2 = 0; + if ( pArgs->GetItemState( FN_PARAM_5, sal_True, &pItem ) == SFX_ITEM_SET ) + nField2 = ((const SfxInt32Item*)pItem)->GetValue(); + aSortParam.bDoSort[2] = ( nField2 != 0 ); + aSortParam.nField[2] = nField2 > 0 ? (nField2-1) : 0; + if ( pArgs->GetItemState( FN_PARAM_6, sal_True, &pItem ) == SFX_ITEM_SET ) + aSortParam.bAscending[2] = ((const SfxBoolItem*)pItem)->GetValue(); + + // Teilergebnisse bei Bedarf neu + pTabViewShell->UISort( aSortParam ); + rReq.Done(); + } + } + else + { + ScSortParam aSortParam; + ScDBData* pDBData = pTabViewShell->GetDBData(); + ScViewData* pData = GetViewData(); + + pDBData->GetSortParam( aSortParam ); + + if( lcl_GetSortParam( pData, aSortParam ) ) + { + SfxAbstractTabDialog* pDlg = NULL; + ScDocument* pDoc = GetViewData()->GetDocument(); + SfxItemSet aArgSet( GetPool(), SCITEM_SORTDATA, SCITEM_SORTDATA ); + + pDBData->GetSortParam( aSortParam ); + sal_Bool bHasHeader = pDoc->HasColHeader( aSortParam.nCol1, aSortParam.nRow1, aSortParam.nCol2, aSortParam.nRow2, pData->GetTabNo() ); + if( bHasHeader ) + aSortParam.bHasHeader = bHasHeader; + + aArgSet.Put( ScSortItem( SCITEM_SORTDATA, GetViewData(), &aSortParam ) ); + + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + pDlg = pFact->CreateScSortDlg( pTabViewShell->GetDialogParent(), &aArgSet, RID_SCDLG_SORT ); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + pDlg->SetCurPageId(1); + + if ( pDlg->Execute() == RET_OK ) + { + const SfxItemSet* pOutSet = pDlg->GetOutputItemSet(); + const ScSortParam& rOutParam = ((const ScSortItem&) + pOutSet->Get( SCITEM_SORTDATA )).GetSortData(); + + // Teilergebnisse bei Bedarf neu + pTabViewShell->UISort( rOutParam ); + + if ( rOutParam.bInplace ) + { + rReq.AppendItem( SfxBoolItem( SID_SORT_BYROW, + rOutParam.bByRow ) ); + rReq.AppendItem( SfxBoolItem( SID_SORT_HASHEADER, + rOutParam.bHasHeader ) ); + rReq.AppendItem( SfxBoolItem( SID_SORT_CASESENS, + rOutParam.bCaseSens ) ); + rReq.AppendItem( SfxBoolItem( SID_SORT_ATTRIBS, + rOutParam.bIncludePattern ) ); + sal_uInt16 nUser = rOutParam.bUserDef ? ( rOutParam.nUserIndex + 1 ) : 0; + rReq.AppendItem( SfxUInt16Item( SID_SORT_USERDEF, nUser ) ); + if ( rOutParam.bDoSort[0] ) + { + rReq.AppendItem( SfxInt32Item( FN_PARAM_1, + rOutParam.nField[0] + 1 ) ); + rReq.AppendItem( SfxBoolItem( FN_PARAM_2, + rOutParam.bAscending[0] ) ); + } + if ( rOutParam.bDoSort[1] ) + { + rReq.AppendItem( SfxInt32Item( FN_PARAM_3, + rOutParam.nField[1] + 1 ) ); + rReq.AppendItem( SfxBoolItem( FN_PARAM_4, + rOutParam.bAscending[1] ) ); + } + if ( rOutParam.bDoSort[2] ) + { + rReq.AppendItem( SfxInt32Item( FN_PARAM_5, + rOutParam.nField[2] + 1 ) ); + rReq.AppendItem( SfxBoolItem( FN_PARAM_6, + rOutParam.bAscending[2] ) ); + } + } + + rReq.Done(); + } + else + GetViewData()->GetDocShell()->CancelAutoDBRange(); + + delete pDlg; + } + } + } + break; + + case SID_FILTER: + { + const SfxItemSet* pArgs = rReq.GetArgs(); + if ( pArgs ) + { + DBG_ERROR("SID_FILTER with arguments?"); + pTabViewShell->Query( ((const ScQueryItem&) + pArgs->Get( SCITEM_QUERYDATA )).GetQueryData(), NULL, sal_True ); + rReq.Done(); + } + else + { + sal_uInt16 nId = ScFilterDlgWrapper::GetChildWindowId(); + SfxViewFrame* pViewFrm = pTabViewShell->GetViewFrame(); + SfxChildWindow* pWnd = pViewFrm->GetChildWindow( nId ); + + pScMod->SetRefDialog( nId, pWnd ? sal_False : sal_True ); + } + } + break; + + case SID_SPECIAL_FILTER: + { + const SfxItemSet* pArgs = rReq.GetArgs(); + if ( pArgs ) + { + DBG_ERROR("SID_SPECIAL_FILTER with arguments?"); + pTabViewShell->Query( ((const ScQueryItem&) + pArgs->Get( SCITEM_QUERYDATA )).GetQueryData(), NULL, sal_True ); + rReq.Done(); + } + else + { + sal_uInt16 nId = ScSpecialFilterDlgWrapper::GetChildWindowId(); + SfxViewFrame* pViewFrm = pTabViewShell->GetViewFrame(); + SfxChildWindow* pWnd = pViewFrm->GetChildWindow( nId ); + + pScMod->SetRefDialog( nId, pWnd ? sal_False : sal_True ); + } + } + break; + + case FID_FILTER_OK: + { + const SfxPoolItem* pItem; + if ( pReqArgs && SFX_ITEM_SET == + pReqArgs->GetItemState( SCITEM_QUERYDATA, sal_True, &pItem ) ) + { + const ScQueryItem& rQueryItem = static_cast<const ScQueryItem&>(*pItem); + + SCTAB nCurTab = GetViewData()->GetTabNo(); + SCTAB nRefTab = GetViewData()->GetRefTabNo(); + + // If RefInput switched to a different sheet from the data sheet, + // switch back: + + if ( nCurTab != nRefTab ) + { + pTabViewShell->SetTabNo( nRefTab ); + pTabViewShell->PaintExtras(); + } + + ScRange aAdvSource; + if (rQueryItem.GetAdvancedQuerySource(aAdvSource)) + pTabViewShell->Query( rQueryItem.GetQueryData(), &aAdvSource, sal_True ); + else + pTabViewShell->Query( rQueryItem.GetQueryData(), NULL, sal_True ); + rReq.Done( *pReqArgs ); + } + } + break; + + case SID_UNFILTER: + { + ScQueryParam aParam; + ScDBData* pDBData = pTabViewShell->GetDBData(); + + pDBData->GetQueryParam( aParam ); + SCSIZE nEC = aParam.GetEntryCount(); + for (SCSIZE i=0; i<nEC; i++) + aParam.GetEntry(i).bDoQuery = sal_False; + aParam.bDuplicate = sal_True; + pTabViewShell->Query( aParam, NULL, sal_True ); + rReq.Done(); + } + break; + + case SID_AUTO_FILTER: + pTabViewShell->ToggleAutoFilter(); + rReq.Done(); + break; + + case SID_AUTOFILTER_HIDE: + pTabViewShell->HideAutoFilter(); + rReq.Done(); + break; + + case SID_PIVOT_TABLE: + { + const SfxPoolItem* pItem; + if ( pReqArgs && SFX_ITEM_SET == + pReqArgs->GetItemState( SCITEM_PIVOTDATA, sal_True, &pItem ) ) + { + SCTAB nCurTab = GetViewData()->GetTabNo(); + SCTAB nRefTab = GetViewData()->GetRefTabNo(); + + // Wenn RefInput auf andere Tabelle als Datentabelle umgeschaltet + // hat wieder zurueckschalten: + + if ( nCurTab != nRefTab ) + { + pTabViewShell->SetTabNo( nRefTab ); + pTabViewShell->PaintExtras(); + } + + const ScDPObject* pDPObject = pTabViewShell->GetDialogDPObject(); + if ( pDPObject ) + { + const ScPivotItem* pPItem = (const ScPivotItem*)pItem; + bool bSuccess = pTabViewShell->MakePivotTable( + pPItem->GetData(), pPItem->GetDestRange(), pPItem->IsNewSheet(), *pDPObject ); + SfxBoolItem aRet(0, bSuccess); + rReq.SetReturnValue(aRet); + } + rReq.Done(); + } + else if (rReq.IsAPI()) + SbxBase::SetError(SbxERR_BAD_PARAMETER); + } + break; + + case SID_OPENDLG_PIVOTTABLE: + { + ScViewData* pData = GetViewData(); + ScDocument* pDoc = pData->GetDocument(); + + ScDPObject* pNewDPObject = NULL; + + // ScPivot is no longer used... + ScDPObject* pDPObj = pDoc->GetDPAtCursor( + pData->GetCurX(), pData->GetCurY(), + pData->GetTabNo() ); + if ( pDPObj ) // on an existing table? + { + pNewDPObject = new ScDPObject( *pDPObj ); + } + else // create new table + { + // select database range or data + pTabViewShell->GetDBData( sal_True, SC_DB_OLD ); + ScMarkData& rMark = GetViewData()->GetMarkData(); + if ( !rMark.IsMarked() && !rMark.IsMultiMarked() ) + pTabViewShell->MarkDataArea( sal_False ); + + // output to cursor position for non-sheet data + ScAddress aDestPos( pData->GetCurX(), pData->GetCurY(), + pData->GetTabNo() ); + + // first select type of source data + + sal_Bool bEnableExt = ScDPObject::HasRegisteredSources(); + //CHINA001 ScDataPilotSourceTypeDlg* pTypeDlg = new ScDataPilotSourceTypeDlg( + //CHINA001 pTabViewShell->GetDialogParent(), bEnableExt ); + + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + AbstractScDataPilotSourceTypeDlg* pTypeDlg = pFact->CreateScDataPilotSourceTypeDlg( pTabViewShell->GetDialogParent(), bEnableExt, RID_SCDLG_DAPITYPE ); + DBG_ASSERT(pTypeDlg, "Dialog create fail!");//CHINA001 + if ( pTypeDlg->Execute() == RET_OK ) + { + if ( pTypeDlg->IsExternal() ) + { + uno::Sequence<rtl::OUString> aSources = ScDPObject::GetRegisteredSources(); + //CHINA001 ScDataPilotServiceDlg* pServDlg = new ScDataPilotServiceDlg( + //CHINA001 pTabViewShell->GetDialogParent(), aSources ); + AbstractScDataPilotServiceDlg* pServDlg = pFact->CreateScDataPilotServiceDlg( pTabViewShell->GetDialogParent(), aSources, RID_SCDLG_DAPISERVICE ); + DBG_ASSERT(pServDlg, "Dialog create fail!");//CHINA001 + if ( pServDlg->Execute() == RET_OK ) + { + ScDPServiceDesc aServDesc( + pServDlg->GetServiceName(), + pServDlg->GetParSource(), + pServDlg->GetParName(), + pServDlg->GetParUser(), + pServDlg->GetParPass() ); + pNewDPObject = new ScDPObject( pDoc ); + pNewDPObject->SetServiceData( aServDesc ); + } + delete pServDlg; + } + else if ( pTypeDlg->IsDatabase() ) + { + //CHINA001 ScDataPilotDatabaseDlg* pDataDlg = new ScDataPilotDatabaseDlg( + //CHINA001 pTabViewShell->GetDialogParent() ); + //ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + AbstractScDataPilotDatabaseDlg* pDataDlg = pFact->CreateScDataPilotDatabaseDlg( pTabViewShell->GetDialogParent(), RID_SCDLG_DAPIDATA); + DBG_ASSERT(pDataDlg, "Dialog create fail!");//CHINA001 + if ( pDataDlg->Execute() == RET_OK ) + { + ScImportSourceDesc aImpDesc; + pDataDlg->GetValues( aImpDesc ); + pNewDPObject = new ScDPObject( pDoc ); + pNewDPObject->SetImportDesc( aImpDesc ); + } + delete pDataDlg; + } + else // selection + { + //! use database ranges (select before type dialog?) + ScRange aRange; + ScMarkType eType = GetViewData()->GetSimpleArea(aRange); + if ( (eType & SC_MARK_SIMPLE) == SC_MARK_SIMPLE ) + { + // Shrink the range to the data area. + SCCOL nStartCol = aRange.aStart.Col(), nEndCol = aRange.aEnd.Col(); + SCROW nStartRow = aRange.aStart.Row(), nEndRow = aRange.aEnd.Row(); + if (pDoc->ShrinkToDataArea(aRange.aStart.Tab(), nStartCol, nStartRow, nEndCol, nEndRow)) + { + aRange.aStart.SetCol(nStartCol); + aRange.aStart.SetRow(nStartRow); + aRange.aEnd.SetCol(nEndCol); + aRange.aEnd.SetRow(nEndRow); + rMark.SetMarkArea(aRange); + pTabViewShell->MarkRange(aRange); + } + + sal_Bool bOK = sal_True; + if ( pDoc->HasSubTotalCells( aRange ) ) + { + // confirm selection if it contains SubTotal cells + + QueryBox aBox( pTabViewShell->GetDialogParent(), + WinBits(WB_YES_NO | WB_DEF_YES), + ScGlobal::GetRscString(STR_DATAPILOT_SUBTOTAL) ); + if (aBox.Execute() == RET_NO) + bOK = sal_False; + } + if (bOK) + { + ScSheetSourceDesc aShtDesc; + aShtDesc.aSourceRange = aRange; + pNewDPObject = new ScDPObject( pDoc ); + pNewDPObject->SetSheetDesc( aShtDesc ); + + // output below source data + if ( aRange.aEnd.Row()+2 <= MAXROW - 4 ) + aDestPos = ScAddress( aRange.aStart.Col(), + aRange.aEnd.Row()+2, + aRange.aStart.Tab() ); + } + } + } + } + delete pTypeDlg; + + if ( pNewDPObject ) + pNewDPObject->SetOutRange( aDestPos ); + +#if 0 + ScDBData* pDBData = pTabViewShell->GetDBData(); + String aErrMsg; + + pDBData->GetArea( nTab, nCol1, nRow1, nCol2, nRow2 ); + + bAreaOk = sal_True; + if ( nRow2-nRow1 < 1 ) + { + // "mindestens eine Datenzeile" + pTabViewShell->ErrorMessage(STR_PIVOT_INVALID_DBAREA); + bAreaOk = sal_False; + } + else if (!pDBData->HasHeader()) + { + if ( MessBox( pTabViewShell->GetDialogParent(), WinBits(WB_YES_NO | WB_DEF_YES), + ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_0 ), // "StarCalc" + ScGlobal::GetRscString( STR_MSSG_MAKEAUTOFILTER_0 ) // Koepfe aus erster Zeile? + ).Execute() == RET_YES ) + { + pDBData->SetHeader( sal_True ); //! Undo ?? + } + else + bAreaOk = sal_False; + } +#endif + } + + pTabViewShell->SetDialogDPObject( pNewDPObject ); // is copied + if ( pNewDPObject ) + { + // start layout dialog + + sal_uInt16 nId = ScPivotLayoutWrapper::GetChildWindowId(); + SfxViewFrame* pViewFrm = pTabViewShell->GetViewFrame(); + SfxChildWindow* pWnd = pViewFrm->GetChildWindow( nId ); + pScMod->SetRefDialog( nId, pWnd ? sal_False : sal_True ); + } + delete pNewDPObject; + } + break; + + case SID_DEFINE_DBNAME: + { + + sal_uInt16 nId = ScDbNameDlgWrapper::GetChildWindowId(); + SfxViewFrame* pViewFrm = pTabViewShell->GetViewFrame(); + SfxChildWindow* pWnd = pViewFrm->GetChildWindow( nId ); + + pScMod->SetRefDialog( nId, pWnd ? sal_False : sal_True ); + + } + break; + + case SID_SELECT_DB: + { + if ( pReqArgs ) + { + const SfxStringItem* pItem = + (const SfxStringItem*)&pReqArgs->Get( SID_SELECT_DB ); + + if( pItem ) + { + pTabViewShell->GotoDBArea( pItem->GetValue() ); + rReq.Done(); + } + else + { + DBG_ERROR("NULL"); + } + } + else + { + ScDocument* pDoc = GetViewData()->GetDocument(); + ScDBCollection* pDBCol = pDoc->GetDBCollection(); + + if ( pDBCol ) + { + const String aStrNoName( ScGlobal::GetRscString(STR_DB_NONAME) ); + List aList; + sal_uInt16 nDBCount = pDBCol->GetCount(); + ScDBData* pDbData = NULL; + String* pDBName = NULL; + + for ( sal_uInt16 i=0; i < nDBCount; i++ ) + { + pDbData = (ScDBData*)(pDBCol->At( i )); + if ( pDbData ) + { + pDBName = new String; + pDbData->GetName( *pDBName ); + + if ( *pDBName != aStrNoName ) + aList.Insert( pDBName ); + else + DELETEZ(pDBName); + } + } + +//CHINA001 ScSelEntryDlg* pDlg = +//CHINA001 new ScSelEntryDlg( pTabViewShell->GetDialogParent(), RID_SCDLG_SELECTDB, +//CHINA001 String(ScResId(SCSTR_SELECTDB)), +//CHINA001 String(ScResId(SCSTR_AREAS)), +//CHINA001 aList ); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + AbstractScSelEntryDlg* pDlg = pFact->CreateScSelEntryDlg( pTabViewShell->GetDialogParent(), + RID_SCDLG_SELECTDB, + String(ScResId(SCSTR_SELECTDB)), + String(ScResId(SCSTR_AREAS)), + aList, + RID_SCDLG_SELECTDB); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + if ( pDlg->Execute() == RET_OK ) + { + String aName = pDlg->GetSelectEntry(); + pTabViewShell->GotoDBArea( aName ); + rReq.AppendItem( SfxStringItem( SID_SELECT_DB, aName ) ); + rReq.Done(); + } + + delete pDlg; + + void* pEntry = aList.First(); + while ( pEntry ) + { + delete (String*) aList.Remove( pEntry ); + pEntry = aList.Next(); + } + } + } + } + break; + + case FID_VALIDATION: + { + const SfxPoolItem* pItem; + const SfxItemSet* pArgs = rReq.GetArgs(); + if ( pArgs ) + { + DBG_ERROR("spaeter..."); + } + else + { + //CHINA001 SfxItemSet aArgSet( GetPool(), ScTPValidationValue::GetRanges() ); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + ::GetTabPageRanges ScTPValidationValueGetRanges = pFact->GetTabPageRangesFunc(TP_VALIDATION_VALUES); + DBG_ASSERT(ScTPValidationValueGetRanges, "TabPage create fail!");//CHINA001 + SfxItemSet aArgSet( GetPool(), (*ScTPValidationValueGetRanges)() );//CHINA001 + ScValidationMode eMode = SC_VALID_ANY; + ScConditionMode eOper = SC_COND_EQUAL; + String aExpr1, aExpr2; + sal_Bool bBlank = sal_True; + sal_Int16 nListType = ValidListType::UNSORTED; + sal_Bool bShowHelp = sal_False; + String aHelpTitle, aHelpText; + sal_Bool bShowError = sal_False; + ScValidErrorStyle eErrStyle = SC_VALERR_STOP; + String aErrTitle, aErrText; + + ScDocument* pDoc = GetViewData()->GetDocument(); + SCCOL nCurX = GetViewData()->GetCurX(); + SCROW nCurY = GetViewData()->GetCurY(); + SCTAB nTab = GetViewData()->GetTabNo(); + ScAddress aCursorPos( nCurX, nCurY, nTab ); + sal_uLong nIndex = ((SfxUInt32Item*)pDoc->GetAttr( + nCurX, nCurY, nTab, ATTR_VALIDDATA ))->GetValue(); + if ( nIndex ) + { + const ScValidationData* pOldData = pDoc->GetValidationEntry( nIndex ); + if ( pOldData ) + { + eMode = pOldData->GetDataMode(); + eOper = pOldData->GetOperation(); + sal_uLong nNumFmt = 0; + if ( eMode == SC_VALID_DATE || eMode == SC_VALID_TIME ) + { + short nType = ( eMode == SC_VALID_DATE ) ? NUMBERFORMAT_DATE + : NUMBERFORMAT_TIME; + nNumFmt = pDoc->GetFormatTable()->GetStandardFormat( + nType, ScGlobal::eLnge ); + } + aExpr1 = pOldData->GetExpression( aCursorPos, 0, nNumFmt ); + aExpr2 = pOldData->GetExpression( aCursorPos, 1, nNumFmt ); + bBlank = pOldData->IsIgnoreBlank(); + nListType = pOldData->GetListType(); + + bShowHelp = pOldData->GetInput( aHelpTitle, aHelpText ); + bShowError = pOldData->GetErrMsg( aErrTitle, aErrText, eErrStyle ); + + aArgSet.Put( SfxAllEnumItem( FID_VALID_MODE, sal::static_int_cast<sal_uInt16>(eMode) ) ); + aArgSet.Put( SfxAllEnumItem( FID_VALID_CONDMODE, sal::static_int_cast<sal_uInt16>(eOper) ) ); + aArgSet.Put( SfxStringItem( FID_VALID_VALUE1, aExpr1 ) ); + aArgSet.Put( SfxStringItem( FID_VALID_VALUE2, aExpr2 ) ); + aArgSet.Put( SfxBoolItem( FID_VALID_BLANK, bBlank ) ); + aArgSet.Put( SfxInt16Item( FID_VALID_LISTTYPE, nListType ) ); + aArgSet.Put( SfxBoolItem( FID_VALID_SHOWHELP, bShowHelp ) ); + aArgSet.Put( SfxStringItem( FID_VALID_HELPTITLE, aHelpTitle ) ); + aArgSet.Put( SfxStringItem( FID_VALID_HELPTEXT, aHelpText ) ); + aArgSet.Put( SfxBoolItem( FID_VALID_SHOWERR, bShowError ) ); + aArgSet.Put( SfxAllEnumItem( FID_VALID_ERRSTYLE, sal::static_int_cast<sal_uInt16>(eErrStyle) ) ); + aArgSet.Put( SfxStringItem( FID_VALID_ERRTITLE, aErrTitle ) ); + aArgSet.Put( SfxStringItem( FID_VALID_ERRTEXT, aErrText ) ); + } + } + + //CHINA001 ScValidationDlg* pDlg = new ScValidationDlg( NULL, &aArgSet ); + //CHINA001 ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + //CHINA001 DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + //<!--Modified by PengYunQuan for Validity Cell Range Picker + //SfxAbstractTabDialog* pDlg = pFact->CreateScValidationDlg( NULL, &aArgSet, TAB_DLG_VALIDATION ); + SfxAbstractTabDialog* pDlg = pFact->CreateScValidationDlg( NULL, &aArgSet, TAB_DLG_VALIDATION, pTabViewShell ); + //-->Modified by PengYunQuan for Validity Cell Range Picker + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + + //<!--Modified by PengYunQuan for Validity Cell Range Picker + //if ( pDlg->Execute() == RET_OK ) + short nResult = pDlg->Execute(); + pTabViewShell->SetTabNo( nTab );//When picking Cell Range ,other Tab may be switched. Need restore the correct tab + if ( nResult == RET_OK ) + //-->Modified by PengYunQuan for Validity Cell Range Picker + { + const SfxItemSet* pOutSet = pDlg->GetOutputItemSet(); + + if ( pOutSet->GetItemState( FID_VALID_MODE, sal_True, &pItem ) == SFX_ITEM_SET ) + eMode = (ScValidationMode) ((const SfxAllEnumItem*)pItem)->GetValue(); + if ( pOutSet->GetItemState( FID_VALID_CONDMODE, sal_True, &pItem ) == SFX_ITEM_SET ) + eOper = (ScConditionMode) ((const SfxAllEnumItem*)pItem)->GetValue(); + if ( pOutSet->GetItemState( FID_VALID_VALUE1, sal_True, &pItem ) == SFX_ITEM_SET ) + { + String aTemp1 = ((const SfxStringItem*)pItem)->GetValue(); + if (eMode == SC_VALID_DATE || eMode == SC_VALID_TIME) + { + sal_uInt32 nNumIndex = 0; + double nVal; + if (pDoc->GetFormatTable()->IsNumberFormat(aTemp1, nNumIndex, nVal)) + aExpr1 =String( ::rtl::math::doubleToUString( nVal, + rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, + ScGlobal::pLocaleData->getNumDecimalSep().GetChar(0), sal_True)); + else + aExpr1 = aTemp1; + } + else + aExpr1 = aTemp1; + } + if ( pOutSet->GetItemState( FID_VALID_VALUE2, sal_True, &pItem ) == SFX_ITEM_SET ) + { + String aTemp2 = ((const SfxStringItem*)pItem)->GetValue(); + if (eMode == SC_VALID_DATE || eMode == SC_VALID_TIME) + { + sal_uInt32 nNumIndex = 0; + double nVal; + if (pDoc->GetFormatTable()->IsNumberFormat(aTemp2, nNumIndex, nVal)) + aExpr2 =String( ::rtl::math::doubleToUString( nVal, + rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, + ScGlobal::pLocaleData->getNumDecimalSep().GetChar(0), sal_True)); + else + aExpr2 = aTemp2; + } + else + aExpr2 = aTemp2; + } + + if ( pOutSet->GetItemState( FID_VALID_BLANK, sal_True, &pItem ) == SFX_ITEM_SET ) + bBlank = ((const SfxBoolItem*)pItem)->GetValue(); + if ( pOutSet->GetItemState( FID_VALID_LISTTYPE, sal_True, &pItem ) == SFX_ITEM_SET ) + nListType = ((const SfxInt16Item*)pItem)->GetValue(); + + if ( pOutSet->GetItemState( FID_VALID_SHOWHELP, sal_True, &pItem ) == SFX_ITEM_SET ) + bShowHelp = ((const SfxBoolItem*)pItem)->GetValue(); + if ( pOutSet->GetItemState( FID_VALID_HELPTITLE, sal_True, &pItem ) == SFX_ITEM_SET ) + aHelpTitle = ((const SfxStringItem*)pItem)->GetValue(); + if ( pOutSet->GetItemState( FID_VALID_HELPTEXT, sal_True, &pItem ) == SFX_ITEM_SET ) + aHelpText = ((const SfxStringItem*)pItem)->GetValue(); + + if ( pOutSet->GetItemState( FID_VALID_SHOWERR, sal_True, &pItem ) == SFX_ITEM_SET ) + bShowError = ((const SfxBoolItem*)pItem)->GetValue(); + if ( pOutSet->GetItemState( FID_VALID_ERRSTYLE, sal_True, &pItem ) == SFX_ITEM_SET ) + eErrStyle = (ScValidErrorStyle) ((const SfxAllEnumItem*)pItem)->GetValue(); + if ( pOutSet->GetItemState( FID_VALID_ERRTITLE, sal_True, &pItem ) == SFX_ITEM_SET ) + aErrTitle = ((const SfxStringItem*)pItem)->GetValue(); + if ( pOutSet->GetItemState( FID_VALID_ERRTEXT, sal_True, &pItem ) == SFX_ITEM_SET ) + aErrText = ((const SfxStringItem*)pItem)->GetValue(); + + ScValidationData aData( eMode, eOper, aExpr1, aExpr2, pDoc, aCursorPos ); + aData.SetIgnoreBlank( bBlank ); + aData.SetListType( nListType ); + + aData.SetInput(aHelpTitle, aHelpText); // sets bShowInput to TRUE + if (!bShowHelp) + aData.ResetInput(); // reset only bShowInput + + aData.SetError(aErrTitle, aErrText, eErrStyle); // sets bShowError to TRUE + if (!bShowError) + aData.ResetError(); // reset only bShowError + + pTabViewShell->SetValidation( aData ); + rReq.Done( *pOutSet ); + } + //<!-- Modified by PengYunQuan for Validity Cell Range Picker + //after end execute from !IsModalInputMode, it is safer to delay deleting + //delete pDlg; + Application::PostUserEvent( Link( pDlg, &DelayDeleteAbstractDialog ) ); + //--> Modified by PengYunQuan for Validity Cell Range Picker + } + } + break; + + case SID_TEXT_TO_COLUMNS: + { + ScViewData* pData = GetViewData(); + DBG_ASSERT( pData, "ScCellShell::ExecuteDB: SID_TEXT_TO_COLUMNS - pData is null!" ); + ScRange aRange; + + if ( lcl_GetTextToColumnsRange( pData, aRange ) ) + { + ScDocument* pDoc = pData->GetDocument(); + DBG_ASSERT( pDoc, "ScCellShell::ExecuteDB: SID_TEXT_TO_COLUMNS - pDoc is null!" ); + + ScImportExport aExport( pDoc, aRange ); + aExport.SetExportTextOptions( ScExportTextOptions( ScExportTextOptions::None, 0, false ) ); + + // #i87703# text to columns fails with tab separator + aExport.SetDelimiter( static_cast< sal_Unicode >( 0 ) ); + + SvMemoryStream aStream; + aStream.SetStreamCharSet( RTL_TEXTENCODING_UNICODE ); + ScImportExport::SetNoEndianSwap( aStream ); + aExport.ExportStream( aStream, String(), FORMAT_STRING ); + + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT( pFact, "ScCellShell::ExecuteDB: SID_TEXT_TO_COLUMNS - pFact is null!" ); + AbstractScImportAsciiDlg *pDlg = pFact->CreateScImportAsciiDlg( + NULL, String(), &aStream, RID_SCDLG_ASCII ); + DBG_ASSERT( pDlg, "ScCellShell::ExecuteDB: SID_TEXT_TO_COLUMNS - pDlg is null!" ); + pDlg->SetTextToColumnsMode(); + + if ( pDlg->Execute() == RET_OK ) + { + ScDocShell* pDocSh = pData->GetDocShell(); + DBG_ASSERT( pDocSh, "ScCellShell::ExecuteDB: SID_TEXT_TO_COLUMNS - pDocSh is null!" ); + + String aUndo = ScGlobal::GetRscString( STR_UNDO_TEXTTOCOLUMNS ); + pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo ); + + ScImportExport aImport( pDoc, aRange.aStart ); + ScAsciiOptions aOptions; + pDlg->GetOptions( aOptions ); + aImport.SetExtOptions( aOptions ); + aImport.SetApi( false ); + aStream.Seek( 0 ); + aImport.ImportStream( aStream, String(), FORMAT_STRING ); + + pDocSh->GetUndoManager()->LeaveListAction(); + } + delete pDlg; + } + } + break; + } +} + +void __EXPORT ScCellShell::GetDBState( SfxItemSet& rSet ) +{ + ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell(); + ScViewData* pData = GetViewData(); + ScDocShell* pDocSh = pData->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + SCCOL nPosX = pData->GetCurX(); + SCROW nPosY = pData->GetCurY(); + SCTAB nTab = pData->GetTabNo(); + + sal_Bool bAutoFilter = sal_False; + sal_Bool bAutoFilterTested = sal_False; + + SfxWhichIter aIter(rSet); + sal_uInt16 nWhich = aIter.FirstWhich(); + while (nWhich) + { + switch (nWhich) + { + case SID_REFRESH_DBAREA: + { + // importierte Daten ohne Selektion + // oder Filter,Sortierung,Teilergebis (auch ohne Import) + sal_Bool bOk = sal_False; + ScDBData* pDBData = pTabViewShell->GetDBData(sal_False,SC_DB_OLD); + if (pDBData && pDoc->GetChangeTrack() == NULL) + { + if ( pDBData->HasImportParam() ) + bOk = !pDBData->HasImportSelection(); + else + { + bOk = pDBData->HasQueryParam() || + pDBData->HasSortParam() || + pDBData->HasSubTotalParam(); + } + } + if (!bOk) + rSet.DisableItem( nWhich ); + } + break; + + case SID_FILTER: + case SID_SPECIAL_FILTER: + { + ScRange aDummy; + ScMarkType eMarkType = GetViewData()->GetSimpleArea( aDummy); + if (eMarkType != SC_MARK_SIMPLE && eMarkType != SC_MARK_SIMPLE_FILTERED) + { + rSet.DisableItem( nWhich ); + } + } + break; + + + //Bei Redlining und Multiselektion Disablen + case SID_SORT_ASCENDING: + case SID_SORT_DESCENDING: + case SCITEM_SORTDATA: + case SCITEM_SUBTDATA: + case SID_OPENDLG_PIVOTTABLE: + { + //! move ReadOnly check to idl flags + + if ( pDocSh->IsReadOnly() || pDoc->GetChangeTrack()!=NULL || + GetViewData()->IsMultiMarked() ) + { + rSet.DisableItem( nWhich ); + } + } + break; + + case SID_REIMPORT_DATA: + { + // nur importierte Daten ohne Selektion + ScDBData* pDBData = pTabViewShell->GetDBData(sal_False,SC_DB_OLD); + if (!pDBData || !pDBData->HasImportParam() || pDBData->HasImportSelection() || + pDoc->GetChangeTrack()!=NULL) + { + rSet.DisableItem( nWhich ); + } + } + break; + + case SID_VIEW_DATA_SOURCE_BROWSER: + { + if (!SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::E_SDATABASE)) + rSet.Put(SfxVisibilityItem(nWhich, sal_False)); + else + // get state (BoolItem) from SfxViewFrame + pTabViewShell->GetViewFrame()->GetSlotState( nWhich, NULL, &rSet ); + } + break; + case SID_SBA_BRW_INSERT: + { + // SBA will ein sal_Bool-Item, damit ueberhaupt enabled + + sal_Bool bEnable = sal_True; + rSet.Put(SfxBoolItem(nWhich, bEnable)); + } + break; + + case SID_AUTO_FILTER: + case SID_AUTOFILTER_HIDE: + { + if (!bAutoFilterTested) + { + bAutoFilter = pDoc->HasAutoFilter( nPosX, nPosY, nTab ); + bAutoFilterTested = sal_True; + } + if ( nWhich == SID_AUTO_FILTER ) + { + ScRange aDummy; + ScMarkType eMarkType = GetViewData()->GetSimpleArea( aDummy); + if (eMarkType != SC_MARK_SIMPLE && eMarkType != SC_MARK_SIMPLE_FILTERED) + { + rSet.DisableItem( nWhich ); + } + else if (pDoc->GetDPAtBlock(aDummy)) + { + rSet.DisableItem( nWhich ); + } + else + rSet.Put( SfxBoolItem( nWhich, bAutoFilter ) ); + } + else + if (!bAutoFilter) + rSet.DisableItem( nWhich ); + } + break; + + case SID_UNFILTER: + { + SCCOL nStartCol, nEndCol; + SCROW nStartRow, nEndRow; + SCTAB nStartTab, nEndTab; + sal_Bool bAnyQuery = sal_False; + + sal_Bool bSelected = (GetViewData()->GetSimpleArea( + nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ) + == SC_MARK_SIMPLE); + + if ( bSelected ) + { + if (nStartCol==nEndCol && nStartRow==nEndRow) + bSelected = sal_False; + } + else + { + nStartCol = GetViewData()->GetCurX(); + nStartRow = GetViewData()->GetCurY(); + nStartTab = GetViewData()->GetTabNo(); + } + + ScDBData* pDBData = bSelected + ? pDoc->GetDBAtArea( nStartTab, nStartCol, nStartRow, nEndCol, nEndRow ) + : pDoc->GetDBAtCursor( nStartCol, nStartRow, nStartTab ); + + if ( pDBData ) + { + ScQueryParam aParam; + pDBData->GetQueryParam( aParam ); + if ( aParam.GetEntry(0).bDoQuery ) + bAnyQuery = sal_True; + } + + if ( !bAnyQuery ) + rSet.DisableItem( nWhich ); + } + break; + + case SID_DEFINE_DBNAME: + { + if ( pDocSh && pDocSh->IsDocShared() ) + { + rSet.DisableItem( nWhich ); + } + } + break; + + case SID_TEXT_TO_COLUMNS: + { + ScRange aRange; + if ( !lcl_GetTextToColumnsRange( pData, aRange ) ) + { + rSet.DisableItem( nWhich ); + } + } + break; + } + nWhich = aIter.NextWhich(); + } +} + + + diff --git a/sc/source/ui/view/cellsh3.cxx b/sc/source/ui/view/cellsh3.cxx new file mode 100644 index 000000000000..7001cd9faff4 --- /dev/null +++ b/sc/source/ui/view/cellsh3.cxx @@ -0,0 +1,966 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include "scitems.hxx" +#include <sfx2/viewfrm.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/request.hxx> +#include <svl/stritem.hxx> +#include <vcl/msgbox.hxx> +#include <sfx2/app.hxx> +#include "globstr.hrc" +#include "scmod.hxx" +#include "appoptio.hxx" +#include "tabvwsh.hxx" +#include "document.hxx" +#include "sc.hrc" +#include "docsh.hxx" +#include "reffact.hxx" +#include "uiitems.hxx" +//CHINA001 #include "scendlg.hxx" +//CHINA001 #include "mtrindlg.hxx" +#include "autoform.hxx" +#include "autofmt.hxx" +#include "cellsh.hxx" +#include "attrdlg.hrc" // TP_ALIGNMENT +#include "inputhdl.hxx" +#include "editable.hxx" + +#include "scabstdlg.hxx" //CHINA001 + +#define IS_EDITMODE() GetViewData()->HasEditView( GetViewData()->GetActivePart() ) + +inline long TwipsToHMM(long nTwips) { return (nTwips * 127 + 36) / 72; } +inline long HMMToTwips(long nHMM) { return (nHMM * 72 + 63) / 127; } +inline long TwipsToEvenHMM(long nTwips) { return ( (nTwips * 127 + 72) / 144 ) * 2; } + +//------------------------------------------------------------------ + +void ScCellShell::Execute( SfxRequest& rReq ) +{ + ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell(); + SfxBindings& rBindings = pTabViewShell->GetViewFrame()->GetBindings(); + ScModule* pScMod = SC_MOD(); + const SfxItemSet* pReqArgs = rReq.GetArgs(); + sal_uInt16 nSlot = rReq.GetSlot(); + + if (nSlot != SID_CURRENTCELL) // der kommt beim MouseButtonUp + pTabViewShell->HideListBox(); // Autofilter-DropDown-Listbox + + if ( IS_EDITMODE() ) + { + switch ( nSlot ) + { + // beim Oeffnen eines Referenz-Dialogs darf die SubShell nicht umgeschaltet werden + // (beim Schliessen des Dialogs wird StopEditShell gerufen) + case SID_OPENDLG_FUNCTION: + // #53318# inplace macht die EditShell Aerger... + //! kann nicht immer umgeschaltet werden ???? + if (!pTabViewShell->GetViewFrame()->GetFrame().IsInPlace()) + pTabViewShell->SetDontSwitch(sal_True); // EditShell nicht abschalten + // kein break + + case FID_CELL_FORMAT: + case SID_ENABLE_HYPHENATION: + case SID_DATA_SELECT: + case SID_OPENDLG_CONSOLIDATE: + case SID_OPENDLG_SOLVE: + case SID_OPENDLG_OPTSOLVER: + + pScMod->InputEnterHandler(); + pTabViewShell->UpdateInputHandler(); + + pTabViewShell->SetDontSwitch(sal_False); + + break; + + default: + break; + } + } + + switch ( nSlot ) + { + + + + case SID_ATTR_SIZE://XXX ??? + break; + + case SID_STATUS_SELMODE: + if ( pReqArgs ) + { + /* 0: STD Click hebt Sel auf + * 1: ER Click erweitert Selektion + * 2: ERG Click definiert weitere Selektion + */ + sal_uInt16 nMode = ((const SfxUInt16Item&)pReqArgs->Get( nSlot )).GetValue(); + + switch ( nMode ) + { + case 1: nMode = KEY_SHIFT; break; + case 2: nMode = KEY_MOD1; break; // Control-Taste + case 0: + default: + nMode = 0; + } + + pTabViewShell->LockModifiers( nMode ); + } + else + { + // no arguments (also executed by double click on the status bar controller): + // advance to next selection mode + + sal_uInt16 nModifiers = pTabViewShell->GetLockedModifiers(); + switch ( nModifiers ) + { + case KEY_SHIFT: nModifiers = KEY_MOD1; break; // EXT -> ADD + case KEY_MOD1: nModifiers = 0; break; // ADD -> STD + default: nModifiers = KEY_SHIFT; break; // STD -> EXT + } + pTabViewShell->LockModifiers( nModifiers ); + } + + rBindings.Invalidate( SID_STATUS_SELMODE ); + rReq.Done(); + break; + + // SID_STATUS_SELMODE_NORM wird nicht benutzt ??? + + case SID_STATUS_SELMODE_NORM: + pTabViewShell->LockModifiers( 0 ); + rBindings.Invalidate( SID_STATUS_SELMODE ); + break; + + // SID_STATUS_SELMODE_ERG / SID_STATUS_SELMODE_ERW als Toggles: + + case SID_STATUS_SELMODE_ERG: + if ( pTabViewShell->GetLockedModifiers() & KEY_MOD1 ) + pTabViewShell->LockModifiers( 0 ); + else + pTabViewShell->LockModifiers( KEY_MOD1 ); + rBindings.Invalidate( SID_STATUS_SELMODE ); + break; + + case SID_STATUS_SELMODE_ERW: + if ( pTabViewShell->GetLockedModifiers() & KEY_SHIFT ) + pTabViewShell->LockModifiers( 0 ); + else + pTabViewShell->LockModifiers( KEY_SHIFT ); + rBindings.Invalidate( SID_STATUS_SELMODE ); + break; + + case SID_ENTER_STRING: + { + if ( pReqArgs ) + { + String aStr( ((const SfxStringItem&)pReqArgs-> + Get( SID_ENTER_STRING )).GetValue() ); + + pTabViewShell->EnterData( GetViewData()->GetCurX(), + GetViewData()->GetCurY(), + GetViewData()->GetTabNo(), + aStr ); + + ScInputHandler* pHdl = SC_MOD()->GetInputHdl( pTabViewShell ); + if ( !pHdl || !pHdl->IsInEnterHandler() ) + { + // #101061# UpdateInputHandler is needed after the cell content + // has changed, but if called from EnterHandler, UpdateInputHandler + // will be called later when moving the cursor. + + pTabViewShell->UpdateInputHandler(); + } + + rReq.Done(); + + // hier kein GrabFocus, weil sonst auf dem Mac die Tabelle vor die + // Seitenansicht springt, wenn die Eingabe nicht abgeschlossen war + // (GrabFocus passiert in KillEditView) + } + } + break; + + case SID_INSERT_MATRIX: + { + if ( pReqArgs ) + { + String aStr = ((const SfxStringItem&)pReqArgs-> + Get( SID_INSERT_MATRIX )).GetValue(); + pTabViewShell->EnterMatrix( aStr ); + rReq.Done(); + } + } + break; + + case FID_INPUTLINE_ENTER: + case FID_INPUTLINE_BLOCK: + case FID_INPUTLINE_MATRIX: + { + if( pReqArgs == 0 ) //XXX vorlaufiger HACK um GPF zu vermeiden + break; + + const ScInputStatusItem* pStatusItem + = (const ScInputStatusItem*)&pReqArgs-> + 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( aString, pData ); + } + else if ( aString.Len() > 0 && ( aString.GetChar(0) == '=' || aString.GetChar(0) == '+' || aString.GetChar(0) == '-' ) ) + { + pTabViewShell->EnterData( aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab(), aString, sal_True, pData ); + } + else + { + pTabViewShell->EnterData( aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab(), pData ); + } + } + else + { + if (nSlot == FID_INPUTLINE_ENTER) + { + if ( + aCursorPos.Col() == GetViewData()->GetCurX() && + aCursorPos.Row() == GetViewData()->GetCurY() && + aCursorPos.Tab() == GetViewData()->GetTabNo() + ) + { + SfxStringItem aItem( SID_ENTER_STRING, aString ); + + // SfxBindings& rBindings = pTabViewShell->GetViewFrame()->GetBindings(); + const SfxPoolItem* aArgs[2]; + aArgs[0] = &aItem; + aArgs[1] = NULL; + rBindings.Execute( SID_ENTER_STRING, aArgs ); + } + else + { + pTabViewShell->EnterData( aCursorPos.Col(), + aCursorPos.Row(), + aCursorPos.Tab(), + aString ); + rReq.Done(); + } + } + else if (nSlot == FID_INPUTLINE_BLOCK) + { + pTabViewShell->EnterBlock( aString, NULL ); + rReq.Done(); + } + else + { + pTabViewShell->EnterMatrix( aString ); + rReq.Done(); + } + + } + + // hier kein GrabFocus, weil sonst auf dem Mac die Tabelle vor die + // Seitenansicht springt, wenn die Eingabe nicht abgeschlossen war + // (GrabFocus passiert in KillEditView) + } + break; + + case SID_OPENDLG_FUNCTION: + { + sal_uInt16 nId = SID_OPENDLG_FUNCTION; + SfxViewFrame* pViewFrm = pTabViewShell->GetViewFrame(); + SfxChildWindow* pWnd = pViewFrm->GetChildWindow( nId ); + + pScMod->SetRefDialog( nId, pWnd ? sal_False : sal_True ); + rReq.Ignore(); + } + break; + + case SID_OPENDLG_CONSOLIDATE: + { + sal_uInt16 nId = ScConsolidateDlgWrapper::GetChildWindowId(); + SfxViewFrame* pViewFrm = pTabViewShell->GetViewFrame(); + SfxChildWindow* pWnd = pViewFrm->GetChildWindow( nId ); + + pScMod->SetRefDialog( nId, pWnd ? sal_False : sal_True ); + } + break; + + case FID_CELL_FORMAT: + { + if ( pReqArgs != NULL ) + { + //---------------------------------- + // Zellattribute ohne Dialog setzen: + //---------------------------------- + SfxItemSet* pEmptySet = + new SfxItemSet( *pReqArgs->GetPool(), + ATTR_PATTERN_START, + ATTR_PATTERN_END ); + + SfxItemSet* pNewSet = + new SfxItemSet( *pReqArgs->GetPool(), + ATTR_PATTERN_START, + ATTR_PATTERN_END ); + + const SfxPoolItem* pAttr = NULL; + sal_uInt16 nWhich = 0; + + for ( nWhich=ATTR_PATTERN_START; nWhich<=ATTR_PATTERN_END; nWhich++ ) + if ( pReqArgs->GetItemState( nWhich, sal_True, &pAttr ) == SFX_ITEM_SET ) + pNewSet->Put( *pAttr ); + + pTabViewShell->ApplyAttributes( pNewSet, pEmptySet ); + + delete pNewSet; + delete pEmptySet; + + rReq.Done(); + } + else if ( pReqArgs == NULL ) + { + pTabViewShell->ExecuteCellFormatDlg( rReq ); + } + } + break; + + case SID_ENABLE_HYPHENATION: + pTabViewShell->ExecuteCellFormatDlg( rReq, TP_ALIGNMENT ); + break; + + case SID_OPENDLG_SOLVE: + { + sal_uInt16 nId = ScSolverDlgWrapper::GetChildWindowId(); + SfxViewFrame* pViewFrm = pTabViewShell->GetViewFrame(); + SfxChildWindow* pWnd = pViewFrm->GetChildWindow( nId ); + + pScMod->SetRefDialog( nId, pWnd ? sal_False : sal_True ); + } + break; + + case SID_OPENDLG_OPTSOLVER: + { + sal_uInt16 nId = ScOptSolverDlgWrapper::GetChildWindowId(); + SfxViewFrame* pViewFrm = pTabViewShell->GetViewFrame(); + SfxChildWindow* pWnd = pViewFrm->GetChildWindow( nId ); + + pScMod->SetRefDialog( nId, pWnd ? sal_False : sal_True ); + } + break; + + case SID_OPENDLG_TABOP: + { + sal_uInt16 nId = ScTabOpDlgWrapper::GetChildWindowId(); + SfxViewFrame* pViewFrm = pTabViewShell->GetViewFrame(); + SfxChildWindow* pWnd = pViewFrm->GetChildWindow( nId ); + + pScMod->SetRefDialog( nId, pWnd ? sal_False : sal_True ); + } + break; + + case SID_SCENARIOS: + { + ScDocument* pDoc = GetViewData()->GetDocument(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + SCTAB nTab = GetViewData()->GetTabNo(); + + if ( pDoc->IsScenario(nTab) ) + { + rMark.MarkToMulti(); + if ( rMark.IsMultiMarked() ) + { + if ( rReq.IsAPI() + || RET_YES == + QueryBox( pTabViewShell->GetDialogParent(), WinBits(WB_YES_NO | WB_DEF_YES), + ScGlobal::GetRscString(STR_UPDATE_SCENARIO) ). + Execute() ) + { + pTabViewShell->ExtendScenario(); + rReq.Done(); + } + } + else if( ! rReq.IsAPI() ) + { + ErrorBox aErrorBox( pTabViewShell->GetDialogParent(), WinBits(WB_OK | WB_DEF_OK), + ScGlobal::GetRscString(STR_NOAREASELECTED) ); + aErrorBox.Execute(); + } + } + else + { + rMark.MarkToMulti(); + if ( rMark.IsMultiMarked() ) + { + SCTAB i=1; + String aBaseName; + String aName; + String aComment; + Color aColor; + sal_uInt16 nFlags; + + pDoc->GetName( nTab, aBaseName ); + aBaseName += '_'; + aBaseName += ScGlobal::GetRscString(STR_SCENARIO); + aBaseName += '_'; + + // vorneweg testen, ob der Prefix als gueltig erkannt wird + // wenn nicht, nur doppelte vermeiden + sal_Bool bPrefix = pDoc->ValidTabName( aBaseName ); + DBG_ASSERT(bPrefix, "ungueltiger Tabellenname"); + + while ( pDoc->IsScenario(nTab+i) ) + i++; + + sal_Bool bValid; + SCTAB nDummy; + do + { + aName = aBaseName; + aName += String::CreateFromInt32( i ); + if (bPrefix) + bValid = pDoc->ValidNewTabName( aName ); + else + bValid = !pDoc->GetTable( aName, nDummy ); + ++i; + } + while ( !bValid && i <= 2*MAXTAB ); + + if ( pReqArgs != NULL ) + { + String aArgName; + String aArgComment; + const SfxPoolItem* pItem; + if ( pReqArgs->GetItemState( SID_SCENARIOS, sal_True, &pItem ) == SFX_ITEM_SET ) + aArgName = ((const SfxStringItem*)pItem)->GetValue(); + if ( pReqArgs->GetItemState( SID_NEW_TABLENAME, sal_True, &pItem ) == SFX_ITEM_SET ) + aArgComment = ((const SfxStringItem*)pItem)->GetValue(); + + aColor = Color( COL_LIGHTGRAY ); // Default + nFlags = 0; // nicht-TwoWay + + pTabViewShell->MakeScenario( aArgName, aArgComment, aColor, nFlags ); + if( ! rReq.IsAPI() ) + rReq.Done(); + } + else + { + sal_Bool bSheetProtected = pDoc->IsTabProtected(nTab); + //CHINA001 ScNewScenarioDlg* pNewDlg = + //CHINA001 new ScNewScenarioDlg( pTabViewShell->GetDialogParent(), aName, sal_False, bSheetProtected ); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + AbstractScNewScenarioDlg* pNewDlg = pFact->CreateScNewScenarioDlg( pTabViewShell->GetDialogParent(), aName, RID_SCDLG_NEWSCENARIO, sal_False,bSheetProtected); + DBG_ASSERT(pNewDlg, "Dialog create fail!");//CHINA001 + if ( pNewDlg->Execute() == RET_OK ) + { + pNewDlg->GetScenarioData( aName, aComment, aColor, nFlags ); + pTabViewShell->MakeScenario( aName, aComment, aColor, nFlags ); + + rReq.AppendItem( SfxStringItem( SID_SCENARIOS, aName ) ); + rReq.AppendItem( SfxStringItem( SID_NEW_TABLENAME, aComment ) ); + rReq.Done(); + } + delete pNewDlg; + } + } + else if( ! rReq.IsAPI() ) + { + pTabViewShell->ErrorMessage(STR_ERR_NEWSCENARIO); + } + } + } + break; + + + case SID_SELECTALL: + { + pTabViewShell->SelectAll(); + rReq.Done(); + } + break; + + //---------------------------------------------------------------- + + case FID_ROW_HEIGHT: + { + if ( pReqArgs ) + { + const SfxUInt16Item& rUInt16Item = (const SfxUInt16Item&)pReqArgs->Get( FID_ROW_HEIGHT ); + + // #101390#; the value of the macro is in HMM so use HMMToTwips to convert + pTabViewShell->SetMarkedWidthOrHeight( sal_False, SC_SIZE_DIRECT, + sal::static_int_cast<sal_uInt16>( HMMToTwips(rUInt16Item.GetValue()) ) ); + if( ! rReq.IsAPI() ) + rReq.Done(); + } + else + { + ScViewData* pData = GetViewData(); + FieldUnit eMetric = SC_MOD()->GetAppOptions().GetAppMetric(); + sal_uInt16 nCurHeight = pData->GetDocument()-> + GetRowHeight( pData->GetCurY(), + pData->GetTabNo() ); +//CHINA001 ScMetricInputDlg* pDlg = +//CHINA001 new ScMetricInputDlg( pTabViewShell->GetDialogParent(), RID_SCDLG_ROW_MAN, +//CHINA001 nCurHeight, +//CHINA001 ScGlobal::nStdRowHeight, +//CHINA001 eMetric, +//CHINA001 2, +//CHINA001 MAX_COL_HEIGHT ); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + AbstractScMetricInputDlg* pDlg = pFact->CreateScMetricInputDlg( pTabViewShell->GetDialogParent(), RID_SCDLG_ROW_MAN, + nCurHeight, + ScGlobal::nStdRowHeight, + RID_SCDLG_ROW_MAN, + eMetric, + 2, + MAX_COL_HEIGHT); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + + if ( pDlg->Execute() == RET_OK ) + { + long nVal = pDlg->GetInputValue(); + pTabViewShell->SetMarkedWidthOrHeight( sal_False, SC_SIZE_DIRECT, (sal_uInt16)nVal ); + + // #101390#; the value of the macro should be in HMM so use TwipsToEvenHMM to convert + rReq.AppendItem( SfxUInt16Item( FID_ROW_HEIGHT, (sal_uInt16)TwipsToEvenHMM(nVal) ) ); + rReq.Done(); + + } + delete pDlg; + } + } + break; + + case FID_ROW_OPT_HEIGHT: + { + if ( pReqArgs ) + { + const SfxUInt16Item& rUInt16Item = (const SfxUInt16Item&)pReqArgs->Get( FID_ROW_OPT_HEIGHT ); + + // #101390#; the value of the macro is in HMM so use HMMToTwips to convert + pTabViewShell->SetMarkedWidthOrHeight( sal_False, SC_SIZE_OPTIMAL, + sal::static_int_cast<sal_uInt16>( HMMToTwips(rUInt16Item.GetValue()) ) ); + ScGlobal::nLastRowHeightExtra = rUInt16Item.GetValue(); + + if( ! rReq.IsAPI() ) + rReq.Done(); + } + else + { + FieldUnit eMetric = SC_MOD()->GetAppOptions().GetAppMetric(); + +//CHINA001 ScMetricInputDlg* pDlg = +//CHINA001 new ScMetricInputDlg( pTabViewShell->GetDialogParent(), RID_SCDLG_ROW_OPT, +//CHINA001 ScGlobal::nLastRowHeightExtra, +//CHINA001 0, +//CHINA001 eMetric, +//CHINA001 1, +//CHINA001 MAX_EXTRA_HEIGHT ); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + AbstractScMetricInputDlg* pDlg = pFact->CreateScMetricInputDlg( pTabViewShell->GetDialogParent(), RID_SCDLG_ROW_OPT, + ScGlobal::nLastRowHeightExtra, + 0, + RID_SCDLG_ROW_OPT, + eMetric, + 1, + MAX_EXTRA_HEIGHT); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + + if ( pDlg->Execute() == RET_OK ) + { + long nVal = pDlg->GetInputValue(); + pTabViewShell->SetMarkedWidthOrHeight( sal_False, SC_SIZE_OPTIMAL, (sal_uInt16)nVal ); + ScGlobal::nLastRowHeightExtra = nVal; + + // #101390#; the value of the macro should be in HMM so use TwipsToEvenHMM to convert + rReq.AppendItem( SfxUInt16Item( FID_ROW_OPT_HEIGHT, (sal_uInt16)TwipsToEvenHMM(nVal) ) ); + rReq.Done(); + + } + delete pDlg; + } + } + break; + + case FID_COL_WIDTH: + { + if ( pReqArgs ) + { + const SfxUInt16Item& rUInt16Item = (const SfxUInt16Item&)pReqArgs->Get( FID_COL_WIDTH ); + + // #101390#; the value of the macro is in HMM so use HMMToTwips to convert + pTabViewShell->SetMarkedWidthOrHeight( sal_True, SC_SIZE_DIRECT, + sal::static_int_cast<sal_uInt16>( HMMToTwips(rUInt16Item.GetValue()) ) ); + if( ! rReq.IsAPI() ) + rReq.Done(); + } + else + { + FieldUnit eMetric = SC_MOD()->GetAppOptions().GetAppMetric(); + ScViewData* pData = GetViewData(); + sal_uInt16 nCurHeight = pData->GetDocument()-> + GetColWidth( pData->GetCurX(), + pData->GetTabNo() ); +//CHINA001 ScMetricInputDlg* pDlg = +//CHINA001 new ScMetricInputDlg( pTabViewShell->GetDialogParent(), RID_SCDLG_COL_MAN, +//CHINA001 nCurHeight, +//CHINA001 STD_COL_WIDTH, +//CHINA001 eMetric, +//CHINA001 2, +//CHINA001 MAX_COL_WIDTH ); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + AbstractScMetricInputDlg* pDlg = pFact->CreateScMetricInputDlg( pTabViewShell->GetDialogParent(), RID_SCDLG_COL_MAN, + nCurHeight, + STD_COL_WIDTH, + RID_SCDLG_COL_MAN, + eMetric, + 2, + MAX_COL_WIDTH); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + + if ( pDlg->Execute() == RET_OK ) + { + long nVal = pDlg->GetInputValue(); + pTabViewShell->SetMarkedWidthOrHeight( sal_True, SC_SIZE_DIRECT, (sal_uInt16)nVal ); + + // #101390#; the value of the macro should be in HMM so use TwipsToEvenHMM to convert + rReq.AppendItem( SfxUInt16Item( FID_COL_WIDTH, (sal_uInt16)TwipsToEvenHMM(nVal)) ); + rReq.Done(); + + } + delete pDlg; + } + } + break; + + case FID_COL_OPT_WIDTH: + { + if ( pReqArgs ) + { + const SfxUInt16Item& rUInt16Item = (const SfxUInt16Item&)pReqArgs->Get( FID_COL_OPT_WIDTH ); + + // #101390#; the value of the macro is in HMM so use HMMToTwips to convert + pTabViewShell->SetMarkedWidthOrHeight( sal_True, SC_SIZE_OPTIMAL, + sal::static_int_cast<sal_uInt16>( HMMToTwips(rUInt16Item.GetValue()) ) ); + ScGlobal::nLastColWidthExtra = rUInt16Item.GetValue(); + + if( ! rReq.IsAPI() ) + rReq.Done(); + } + else + { + FieldUnit eMetric = SC_MOD()->GetAppOptions().GetAppMetric(); + +//CHINA001 ScMetricInputDlg* pDlg = +//CHINA001 new ScMetricInputDlg( pTabViewShell->GetDialogParent(), RID_SCDLG_COL_OPT, +//CHINA001 ScGlobal::nLastColWidthExtra, +//CHINA001 STD_EXTRA_WIDTH, +//CHINA001 eMetric, +//CHINA001 1, +//CHINA001 MAX_EXTRA_WIDTH ); + + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + AbstractScMetricInputDlg* pDlg = pFact->CreateScMetricInputDlg( pTabViewShell->GetDialogParent(), RID_SCDLG_COL_OPT, + ScGlobal::nLastColWidthExtra, + STD_EXTRA_WIDTH, + RID_SCDLG_COL_OPT, + eMetric, + 1, + MAX_EXTRA_WIDTH); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + if ( pDlg->Execute() == RET_OK ) + { + long nVal = pDlg->GetInputValue(); + pTabViewShell->SetMarkedWidthOrHeight( sal_True, SC_SIZE_OPTIMAL, (sal_uInt16)nVal ); + ScGlobal::nLastColWidthExtra = nVal; + + // #101390#; the value of the macro should be in HMM so use TwipsToEvenHMM to convert + rReq.AppendItem( SfxUInt16Item( FID_COL_OPT_WIDTH, (sal_uInt16)TwipsToEvenHMM(nVal) ) ); + rReq.Done(); + } + delete pDlg; + } + } + break; + + case FID_COL_OPT_DIRECT: + pTabViewShell->SetMarkedWidthOrHeight( sal_True, SC_SIZE_OPTIMAL, STD_EXTRA_WIDTH ); + rReq.Done(); + break; + + case FID_ROW_HIDE: + pTabViewShell->SetMarkedWidthOrHeight( sal_False, SC_SIZE_DIRECT, 0 ); + rReq.Done(); + break; + case FID_ROW_SHOW: + pTabViewShell->SetMarkedWidthOrHeight( sal_False, SC_SIZE_SHOW, 0 ); + rReq.Done(); + break; + case FID_COL_HIDE: + pTabViewShell->SetMarkedWidthOrHeight( sal_True, SC_SIZE_DIRECT, 0 ); + rReq.Done(); + break; + case FID_COL_SHOW: + pTabViewShell->SetMarkedWidthOrHeight( sal_True, SC_SIZE_SHOW, 0 ); + rReq.Done(); + break; + + //---------------------------------------------------------------- + + + case SID_CELL_FORMAT_RESET: + { + pTabViewShell->DeleteContents( IDF_HARDATTR | IDF_EDITATTR ); + rReq.Done(); + } + break; + + case FID_MERGE_ON: + case FID_MERGE_OFF: + case FID_MERGE_TOGGLE: + { + if ( !GetViewData()->GetDocument()->GetChangeTrack() ) + { + // test whether to merge or to split + bool bMerge = false; + switch( nSlot ) + { + case FID_MERGE_ON: + bMerge = true; + break; + case FID_MERGE_OFF: + bMerge = false; + break; + case FID_MERGE_TOGGLE: + { + SfxPoolItem* pItem = 0; + if( rBindings.QueryState( nSlot, pItem ) >= SFX_ITEM_DEFAULT ) + bMerge = !static_cast< SfxBoolItem* >( pItem )->GetValue(); + } + break; + } + + if( bMerge ) + { + // merge - check if to move contents of covered cells + sal_Bool bMoveContents = sal_False; + sal_Bool bApi = rReq.IsAPI(); + const SfxPoolItem* pItem; + if ( pReqArgs && + pReqArgs->GetItemState(nSlot, sal_True, &pItem) == SFX_ITEM_SET ) + { + DBG_ASSERT(pItem && pItem->ISA(SfxBoolItem), "falsches Item"); + bMoveContents = ((const SfxBoolItem*)pItem)->GetValue(); + } + + if (pTabViewShell->MergeCells( bApi, bMoveContents )) + { + if (!bApi && bMoveContents) // "ja" im Dialog geklickt + rReq.AppendItem( SfxBoolItem( nSlot, bMoveContents ) ); + rBindings.Invalidate( nSlot ); + rReq.Done(); + } + } + else + { + // split cells + if (pTabViewShell->RemoveMerge()) + { + rBindings.Invalidate( nSlot ); + rReq.Done(); + } + } + break; + } + } + break; + + case SID_AUTOFORMAT: + { + Window* pDlgParent = pTabViewShell->GetDialogParent(); + SCCOL nStartCol; + SCROW nStartRow; + SCTAB nStartTab; + SCCOL nEndCol; + SCROW nEndRow; + SCTAB nEndTab; + + const ScMarkData& rMark = GetViewData()->GetMarkData(); + if ( !rMark.IsMarked() && !rMark.IsMultiMarked() ) + pTabViewShell->MarkDataArea( sal_True ); + + GetViewData()->GetSimpleArea( nStartCol,nStartRow,nStartTab, + nEndCol,nEndRow,nEndTab ); + + if ( ( Abs((SCsCOL)nEndCol-(SCsCOL)nStartCol) > 1 ) + && ( Abs((SCsROW)nEndRow-(SCsROW)nStartRow) > 1 ) ) + { + if ( pReqArgs ) + { + const SfxStringItem& rNameItem = (const SfxStringItem&)pReqArgs->Get( SID_AUTOFORMAT ); + ScAutoFormat* pFormat = ScGlobal::GetAutoFormat(); + sal_uInt16 nIndex = pFormat->FindIndexPerName( rNameItem.GetValue() ); + + pTabViewShell->AutoFormat( nIndex ); + + if( ! rReq.IsAPI() ) + rReq.Done(); + } + else + { + ScGlobal::ClearAutoFormat(); + ScAutoFormatData* pNewEntry = pTabViewShell->CreateAutoFormatData(); +//CHINA001 ScAutoFormatDlg* pDlg = new ScAutoFormatDlg( +//CHINA001 pDlgParent, +//CHINA001 ScGlobal::GetAutoFormat(), +//CHINA001 pNewEntry, +//CHINA001 GetViewData()->GetDocument() ); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + AbstractScAutoFormatDlg* pDlg = pFact->CreateScAutoFormatDlg( pDlgParent, ScGlobal::GetAutoFormat(), pNewEntry,GetViewData()->GetDocument(), RID_SCDLG_AUTOFORMAT ); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + + if ( pDlg->Execute() == RET_OK ) + { + ScEditableTester aTester( pTabViewShell ); + if ( !aTester.IsEditable() ) + { + pTabViewShell->ErrorMessage(aTester.GetMessageId()); + } + else + { + pTabViewShell->AutoFormat( pDlg->GetIndex() ); + + rReq.AppendItem( SfxStringItem( SID_AUTOFORMAT, pDlg->GetCurrFormatName() ) ); + rReq.Done(); + } + } + delete pDlg; + delete pNewEntry; + } + } + else + ErrorBox( pDlgParent, WinBits( WB_OK | WB_DEF_OK ), + ScGlobal::GetRscString(STR_INVALID_AFAREA) ).Execute(); + } + break; + + case SID_CANCEL: + { + if (GetViewData()->HasEditView(GetViewData()->GetActivePart())) + pScMod->InputCancelHandler(); + else if (pTabViewShell->HasPaintBrush()) + pTabViewShell->ResetBrushDocument(); // abort format paint brush + else if (pTabViewShell->HasHintWindow()) + pTabViewShell->RemoveHintWindow(); // Eingabemeldung abschalten + else if( ScViewUtil::IsFullScreen( *pTabViewShell ) ) + ScViewUtil::SetFullScreen( *pTabViewShell, false ); + else + { + // TODO/LATER: when is this code executed? + pTabViewShell->Escape(); + //SfxObjectShell* pObjSh = GetViewData()->GetSfxDocShell(); + //if (pObjSh->GetInPlaceObject() && + // pObjSh->GetInPlaceObject()->GetIPClient()) + //{ + // GetViewData()->GetDocShell()-> + // DoInPlaceActivate(sal_False); // OLE beenden + //} + } + +// SetSumAssignMode(); //ScInputWindow + } + break; + + case SID_DATA_SELECT: + pTabViewShell->StartDataSelect(); + break; + + case SID_DETECTIVE_FILLMODE: + { + sal_Bool bOldMode = pTabViewShell->IsAuditShell(); + pTabViewShell->SetAuditShell( !bOldMode ); + pTabViewShell->Invalidate( nSlot ); + } + break; + + case SID_OPENDLG_CONDFRMT: + { + sal_uInt16 nId = ScCondFormatDlgWrapper::GetChildWindowId(); + SfxViewFrame* pViewFrm = pTabViewShell->GetViewFrame(); + SfxChildWindow* pWnd = pViewFrm->GetChildWindow( nId ); + + pScMod->SetRefDialog( nId, pWnd ? sal_False : sal_True ); + } + break; + + // ---------------------------------------------------------------- + + case FID_INPUTLINE_STATUS: + DBG_ERROR("Execute von InputLine-Status"); + break; + + case SID_STATUS_DOCPOS: + // Launch navigator. + GetViewData()->GetDispatcher().Execute( + SID_NAVIGATOR, SFX_CALLMODE_SYNCHRON|SFX_CALLMODE_RECORD ); + break; + + case SID_MARKAREA: + // called from Basic at the hidden view to select a range in the visible view + DBG_ERROR("old slot SID_MARKAREA"); + break; + + default: + DBG_ERROR("Unbekannter Slot bei ScCellShell::Execute"); + break; + } +} + diff --git a/sc/source/ui/view/cellsh4.cxx b/sc/source/ui/view/cellsh4.cxx new file mode 100644 index 000000000000..545aba28ff47 --- /dev/null +++ b/sc/source/ui/view/cellsh4.cxx @@ -0,0 +1,382 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +//------------------------------------------------------------------ + +#ifdef _MSC_VER +#pragma optimize ("", off) +#endif + +// INCLUDE --------------------------------------------------------------- + +#include <sfx2/request.hxx> + +#include "cellsh.hxx" +#include "tabvwsh.hxx" +#include "global.hxx" +#include "scmod.hxx" +#include "inputhdl.hxx" +#include "inputwin.hxx" +#include "document.hxx" +#include "sc.hrc" + + +//------------------------------------------------------------------ + +#define IS_AVAILABLE(WhichId,ppItem) \ + (pReqArgs->GetItemState((WhichId), sal_True, ppItem ) == SFX_ITEM_SET) + + +void ScCellShell::ExecuteCursor( SfxRequest& rReq ) +{ + ScViewData* pData = GetViewData(); + ScTabViewShell* pTabViewShell = pData->GetViewShell(); + const SfxItemSet* pReqArgs = rReq.GetArgs(); + sal_uInt16 nSlotId = rReq.GetSlot(); + SCsCOLROW nRepeat = 1; + sal_Bool bSel = sal_False; + sal_Bool bKeep = sal_False; + + if ( pReqArgs != NULL ) + { + const SfxPoolItem* pItem; + if( IS_AVAILABLE( FN_PARAM_1, &pItem ) ) + nRepeat = static_cast<SCsCOLROW>(((const SfxInt16Item*)pItem)->GetValue()); + if( IS_AVAILABLE( FN_PARAM_2, &pItem ) ) + bSel = ((const SfxBoolItem*)pItem)->GetValue(); + } + else + { + // evaluate locked selection mode + + sal_uInt16 nLocked = pTabViewShell->GetLockedModifiers(); + if ( nLocked & KEY_SHIFT ) + bSel = sal_True; // EXT + else if ( nLocked & KEY_MOD1 ) + { + // ADD mode: keep the selection, start a new block when marking with shift again + bKeep = sal_True; + pTabViewShell->SetNewStartIfMarking(); + } + } + + SCsCOLROW nRTLSign = 1; + if ( pData->GetDocument()->IsLayoutRTL( pData->GetTabNo() ) ) + { + //! evaluate cursor movement option? + nRTLSign = -1; + } + + // einmal extra, damit der Cursor bei ExecuteInputDirect nicht zuoft gemalt wird: + pTabViewShell->HideAllCursors(); + + //OS: einmal fuer alle wird doch reichen! + pTabViewShell->ExecuteInputDirect(); + switch ( nSlotId ) + { + case SID_CURSORDOWN: + pTabViewShell->MoveCursorRel( 0, nRepeat, SC_FOLLOW_LINE, bSel, bKeep ); + break; + + case SID_CURSORBLKDOWN: + pTabViewShell->MoveCursorArea( 0, nRepeat, SC_FOLLOW_JUMP, bSel, bKeep ); + break; + + case SID_CURSORUP: + pTabViewShell->MoveCursorRel( 0, -nRepeat, SC_FOLLOW_LINE, bSel, bKeep ); + break; + + case SID_CURSORBLKUP: + pTabViewShell->MoveCursorArea( 0, -nRepeat, SC_FOLLOW_JUMP, bSel, bKeep ); + break; + + case SID_CURSORLEFT: + pTabViewShell->MoveCursorRel( static_cast<SCsCOL>(-nRepeat * nRTLSign), 0, SC_FOLLOW_LINE, bSel, bKeep ); + break; + + case SID_CURSORBLKLEFT: + pTabViewShell->MoveCursorArea( static_cast<SCsCOL>(-nRepeat * nRTLSign), 0, SC_FOLLOW_JUMP, bSel, bKeep ); + break; + + case SID_CURSORRIGHT: + pTabViewShell->MoveCursorRel( static_cast<SCsCOL>(nRepeat * nRTLSign), 0, SC_FOLLOW_LINE, bSel, bKeep ); + break; + + case SID_CURSORBLKRIGHT: + pTabViewShell->MoveCursorArea( static_cast<SCsCOL>(nRepeat * nRTLSign), 0, SC_FOLLOW_JUMP, bSel, bKeep ); + break; + + case SID_CURSORPAGEDOWN: + pTabViewShell->MoveCursorPage( 0, nRepeat, SC_FOLLOW_FIX, bSel, bKeep ); + break; + + case SID_CURSORPAGEUP: + pTabViewShell->MoveCursorPage( 0, -nRepeat, SC_FOLLOW_FIX, bSel, bKeep ); + break; + + case SID_CURSORPAGERIGHT_: //XXX !!! + pTabViewShell->MoveCursorPage( static_cast<SCsCOL>(nRepeat), 0, SC_FOLLOW_FIX, bSel, bKeep ); + break; + + case SID_CURSORPAGELEFT_: //XXX !!! + pTabViewShell->MoveCursorPage( static_cast<SCsCOL>(-nRepeat), 0, SC_FOLLOW_FIX, bSel, bKeep ); + break; + + default: + DBG_ERROR("Unbekannte Message bei ViewShell (Cursor)"); + return; + } + + pTabViewShell->ShowAllCursors(); + + rReq.AppendItem( SfxInt16Item(FN_PARAM_1, static_cast<sal_Int16>(nRepeat)) ); + rReq.AppendItem( SfxBoolItem(FN_PARAM_2, bSel) ); + rReq.Done(); +} + +void ScCellShell::GetStateCursor( SfxItemSet& /* rSet */ ) +{ +} + +void ScCellShell::ExecuteCursorSel( SfxRequest& rReq ) +{ + const SfxItemSet* pReqArgs = rReq.GetArgs(); + sal_uInt16 nSlotId = rReq.GetSlot(); + short nRepeat = 1; + + if ( pReqArgs != NULL ) + { + const SfxPoolItem* pItem; + if( IS_AVAILABLE( FN_PARAM_1, &pItem ) ) + nRepeat = ((const SfxInt16Item*)pItem)->GetValue(); + } + + switch ( nSlotId ) + { + case SID_CURSORDOWN_SEL: rReq.SetSlot( SID_CURSORDOWN ); break; + case SID_CURSORBLKDOWN_SEL: rReq.SetSlot( SID_CURSORBLKDOWN ); break; + case SID_CURSORUP_SEL: rReq.SetSlot( SID_CURSORUP ); break; + case SID_CURSORBLKUP_SEL: rReq.SetSlot( SID_CURSORBLKUP ); break; + case SID_CURSORLEFT_SEL: rReq.SetSlot( SID_CURSORLEFT ); break; + case SID_CURSORBLKLEFT_SEL: rReq.SetSlot( SID_CURSORBLKLEFT ); break; + case SID_CURSORRIGHT_SEL: rReq.SetSlot( SID_CURSORRIGHT ); break; + case SID_CURSORBLKRIGHT_SEL: rReq.SetSlot( SID_CURSORBLKRIGHT ); break; + case SID_CURSORPAGEDOWN_SEL: rReq.SetSlot( SID_CURSORPAGEDOWN ); break; + case SID_CURSORPAGEUP_SEL: rReq.SetSlot( SID_CURSORPAGEUP ); break; + case SID_CURSORPAGERIGHT_SEL: rReq.SetSlot( SID_CURSORPAGERIGHT_ ); break; + case SID_CURSORPAGELEFT_SEL: rReq.SetSlot( SID_CURSORPAGELEFT_ ); break; + default: + DBG_ERROR("Unbekannte Message bei ViewShell (CursorSel)"); + return; + } + rReq.AppendItem( SfxInt16Item(FN_PARAM_1, nRepeat ) ); + rReq.AppendItem( SfxBoolItem(FN_PARAM_2, sal_True) ); + ExecuteSlot( rReq, GetInterface() ); +} + +void ScCellShell::ExecuteMove( SfxRequest& rReq ) +{ + ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell(); + sal_uInt16 nSlotId = rReq.GetSlot(); + + if(nSlotId != SID_CURSORTOPOFSCREEN && nSlotId != SID_CURSORENDOFSCREEN) + pTabViewShell->ExecuteInputDirect(); + switch ( nSlotId ) + { + case SID_NEXT_TABLE: + case SID_NEXT_TABLE_SEL: + pTabViewShell->SelectNextTab( 1, (nSlotId == SID_NEXT_TABLE_SEL) ); + break; + + case SID_PREV_TABLE: + case SID_PREV_TABLE_SEL: + pTabViewShell->SelectNextTab( -1, (nSlotId == SID_PREV_TABLE_SEL) ); + break; + + // Cursorbewegungen in Bloecken gehen nicht von Basic aus, + // weil das ScSbxRange-Objekt bei Eingaben die Markierung veraendert + + case SID_NEXT_UNPROTECT: + pTabViewShell->FindNextUnprot( sal_False, !rReq.IsAPI() ); + break; + + case SID_PREV_UNPROTECT: + pTabViewShell->FindNextUnprot( sal_True, !rReq.IsAPI() ); + break; + + case SID_CURSORENTERUP: + if (rReq.IsAPI()) + pTabViewShell->MoveCursorRel( 0, -1, SC_FOLLOW_LINE, sal_False ); + else + pTabViewShell->MoveCursorEnter( sal_True ); + break; + + case SID_CURSORENTERDOWN: + if (rReq.IsAPI()) + pTabViewShell->MoveCursorRel( 0, 1, SC_FOLLOW_LINE, sal_False ); + else + pTabViewShell->MoveCursorEnter( sal_False ); + break; + + case SID_SELECT_COL: + pTabViewShell->MarkColumns(); + break; + + case SID_SELECT_ROW: + pTabViewShell->MarkRows(); + break; + + case SID_SELECT_NONE: + pTabViewShell->Unmark(); + break; + + case SID_ALIGNCURSOR: + pTabViewShell->AlignToCursor( GetViewData()->GetCurX(), GetViewData()->GetCurY(), SC_FOLLOW_JUMP ); + break; + + case SID_MARKDATAAREA: + pTabViewShell->MarkDataArea(); + break; + + case SID_MARKARRAYFORMULA: + pTabViewShell->MarkMatrixFormula(); + break; + + case SID_SETINPUTMODE: + SC_MOD()->SetInputMode( SC_INPUT_TABLE ); + break; + + case SID_FOCUS_INPUTLINE: + { + ScInputHandler* pHdl = SC_MOD()->GetInputHdl( pTabViewShell ); + if (pHdl) + { + ScInputWindow* pWin = pHdl->GetInputWindow(); + if (pWin) + pWin->SwitchToTextWin(); + } + } + break; + + case SID_CURSORTOPOFSCREEN: + pTabViewShell->MoveCursorScreen( 0, -1, SC_FOLLOW_LINE, sal_False ); + break; + + case SID_CURSORENDOFSCREEN: + pTabViewShell->MoveCursorScreen( 0, 1, SC_FOLLOW_LINE, sal_False ); + break; + + default: + DBG_ERROR("Unbekannte Message bei ViewShell (Cursor)"); + return; + } + + rReq.Done(); +} + +void ScCellShell::ExecutePageSel( SfxRequest& rReq ) +{ + sal_uInt16 nSlotId = rReq.GetSlot(); + switch ( nSlotId ) + { + case SID_CURSORHOME_SEL: rReq.SetSlot( SID_CURSORHOME ); break; + case SID_CURSOREND_SEL: rReq.SetSlot( SID_CURSOREND ); break; + case SID_CURSORTOPOFFILE_SEL: rReq.SetSlot( SID_CURSORTOPOFFILE ); break; + case SID_CURSORENDOFFILE_SEL: rReq.SetSlot( SID_CURSORENDOFFILE ); break; + default: + DBG_ERROR("Unbekannte Message bei ViewShell (ExecutePageSel)"); + return; + } + rReq.AppendItem( SfxBoolItem(FN_PARAM_2, sal_True) ); + ExecuteSlot( rReq, GetInterface() ); +} + +void ScCellShell::ExecutePage( SfxRequest& rReq ) +{ + ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell(); + const SfxItemSet* pReqArgs = rReq.GetArgs(); + sal_uInt16 nSlotId = rReq.GetSlot(); + sal_Bool bSel = sal_False; + sal_Bool bKeep = sal_False; + + if ( pReqArgs != NULL ) + { + const SfxPoolItem* pItem; + if( IS_AVAILABLE( FN_PARAM_2, &pItem ) ) + bSel = ((const SfxBoolItem*)pItem)->GetValue(); + } + else + { + // evaluate locked selection mode + + sal_uInt16 nLocked = pTabViewShell->GetLockedModifiers(); + if ( nLocked & KEY_SHIFT ) + bSel = sal_True; // EXT + else if ( nLocked & KEY_MOD1 ) + { + // ADD mode: keep the selection, start a new block when marking with shift again + bKeep = sal_True; + pTabViewShell->SetNewStartIfMarking(); + } + } + + pTabViewShell->ExecuteInputDirect(); + switch ( nSlotId ) + { + case SID_CURSORHOME: + pTabViewShell->MoveCursorEnd( -1, 0, SC_FOLLOW_LINE, bSel, bKeep ); + break; + + case SID_CURSOREND: + pTabViewShell->MoveCursorEnd( 1, 0, SC_FOLLOW_JUMP, bSel, bKeep ); + break; + + case SID_CURSORTOPOFFILE: + pTabViewShell->MoveCursorEnd( -1, -1, SC_FOLLOW_LINE, bSel, bKeep ); + break; + + case SID_CURSORENDOFFILE: + pTabViewShell->MoveCursorEnd( 1, 1, SC_FOLLOW_JUMP, bSel, bKeep ); + break; + + default: + DBG_ERROR("Unbekannte Message bei ViewShell (ExecutePage)"); + return; + } + + rReq.AppendItem( SfxBoolItem(FN_PARAM_2, bSel) ); + rReq.Done(); +} + + + + diff --git a/sc/source/ui/view/colrowba.cxx b/sc/source/ui/view/colrowba.cxx new file mode 100644 index 000000000000..13bc1e8eb1f5 --- /dev/null +++ b/sc/source/ui/view/colrowba.cxx @@ -0,0 +1,419 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include <svx/svdtrans.hxx> +#include <unotools/localedatawrapper.hxx> + +#include "colrowba.hxx" +#include "document.hxx" +#include "scmod.hxx" +#include "tabvwsh.hxx" +#include "docsh.hxx" +#include "appoptio.hxx" +#include "globstr.hrc" + +// STATIC DATA ----------------------------------------------------------- + +//================================================================== + +String lcl_MetricString( long nTwips, const String& rText ) +{ + if ( nTwips <= 0 ) + return ScGlobal::GetRscString(STR_TIP_HIDE); + else + { + FieldUnit eUserMet = SC_MOD()->GetAppOptions().GetAppMetric(); + + sal_Int64 nUserVal = MetricField::ConvertValue( nTwips*100, 1, 2, FUNIT_TWIP, eUserMet ); + + String aStr = rText; + aStr += ' '; + aStr += ScGlobal::pLocaleData->getNum( nUserVal, 2 ); + aStr += ' '; + aStr += SdrFormatter::GetUnitStr(eUserMet); + + return aStr; + } +} + +//================================================================== + +ScColBar::ScColBar( Window* pParent, ScViewData* pData, ScHSplitPos eWhichPos, + ScHeaderFunctionSet* pFunc, ScHeaderSelectionEngine* pEng ) : + ScHeaderControl( pParent, pEng, MAXCOL+1, HDR_HORIZONTAL ), + pViewData( pData ), + eWhich( eWhichPos ), + pFuncSet( pFunc ), + pSelEngine( pEng ) +{ + Show(); +} + +ScColBar::~ScColBar() +{ +} + +inline sal_Bool ScColBar::UseNumericHeader() const +{ + return pViewData->GetDocument()->GetAddressConvention() == formula::FormulaGrammar::CONV_XL_R1C1; +} + +SCCOLROW ScColBar::GetPos() +{ + return pViewData->GetPosX(eWhich); +} + +sal_uInt16 ScColBar::GetEntrySize( SCCOLROW nEntryNo ) +{ + ScDocument* pDoc = pViewData->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + SCCOL nLastCol = -1; + if (pDoc->ColHidden(static_cast<SCCOL>(nEntryNo), nTab, nLastCol)) + return 0; + else + return (sal_uInt16) ScViewData::ToPixel( pDoc->GetColWidth( static_cast<SCCOL>(nEntryNo), nTab ), pViewData->GetPPTX() ); +} + +String ScColBar::GetEntryText( SCCOLROW nEntryNo ) +{ + return UseNumericHeader() + ? String::CreateFromInt32( nEntryNo + 1 ) + : ScColToAlpha( static_cast<SCCOL>(nEntryNo) ); +} + +void ScColBar::SetEntrySize( SCCOLROW nPos, sal_uInt16 nNewSize ) +{ + sal_uInt16 nSizeTwips; + ScSizeMode eMode = SC_SIZE_DIRECT; + if (nNewSize>0 && nNewSize<10) nNewSize=10; // (Pixel) + + if ( nNewSize == HDR_SIZE_OPTIMUM ) + { + nSizeTwips = STD_EXTRA_WIDTH; + eMode = SC_SIZE_OPTIMAL; + } + else + nSizeTwips = (sal_uInt16) ( nNewSize / pViewData->GetPPTX() ); + + ScMarkData& rMark = pViewData->GetMarkData(); +// SCTAB nTab = pViewData->GetTabNo(); + + SCCOLROW* pRanges = new SCCOLROW[MAXCOL+1]; + SCCOL nRangeCnt = 0; + if ( rMark.IsColumnMarked( static_cast<SCCOL>(nPos) ) ) + { + SCCOL nStart = 0; + while (nStart<=MAXCOL) + { + while (nStart<MAXCOL && !rMark.IsColumnMarked(nStart)) + ++nStart; + if (rMark.IsColumnMarked(nStart)) + { + SCCOL nEnd = nStart; + while (nEnd<MAXCOL && rMark.IsColumnMarked(nEnd)) + ++nEnd; + if (!rMark.IsColumnMarked(nEnd)) + --nEnd; + pRanges[static_cast<size_t>(2*nRangeCnt) ] = nStart; + pRanges[static_cast<size_t>(2*nRangeCnt+1)] = nEnd; + ++nRangeCnt; + nStart = nEnd+1; + } + else + nStart = MAXCOL+1; + } + } + else + { + pRanges[0] = nPos; + pRanges[1] = nPos; + nRangeCnt = 1; + } + + pViewData->GetView()->SetWidthOrHeight( sal_True, nRangeCnt, pRanges, eMode, nSizeTwips ); + delete[] pRanges; +} + +void ScColBar::HideEntries( SCCOLROW nStart, SCCOLROW nEnd ) +{ + SCCOLROW nRange[2]; + nRange[0] = nStart; + nRange[1] = nEnd; + pViewData->GetView()->SetWidthOrHeight( sal_True, 1, nRange, SC_SIZE_DIRECT, 0 ); +} + +void ScColBar::SetMarking( sal_Bool bSet ) +{ + pViewData->GetMarkData().SetMarking( bSet ); + if (!bSet) + { + pViewData->GetView()->UpdateAutoFillMark(); + } +} + +void ScColBar::SelectWindow() +{ + ScTabViewShell* pViewSh = pViewData->GetViewShell(); + + pViewSh->SetActive(); // Appear und SetViewFrame + pViewSh->DrawDeselectAll(); + + ScSplitPos eActive = pViewData->GetActivePart(); + if (eWhich==SC_SPLIT_LEFT) + { + if (eActive==SC_SPLIT_TOPRIGHT) eActive=SC_SPLIT_TOPLEFT; + if (eActive==SC_SPLIT_BOTTOMRIGHT) eActive=SC_SPLIT_BOTTOMLEFT; + } + else + { + if (eActive==SC_SPLIT_TOPLEFT) eActive=SC_SPLIT_TOPRIGHT; + if (eActive==SC_SPLIT_BOTTOMLEFT) eActive=SC_SPLIT_BOTTOMRIGHT; + } + pViewSh->ActivatePart( eActive ); + + pFuncSet->SetColumn( sal_True ); + pFuncSet->SetWhich( eActive ); + + pViewSh->ActiveGrabFocus(); +} + +sal_Bool ScColBar::IsDisabled() +{ + ScModule* pScMod = SC_MOD(); + return pScMod->IsFormulaMode() || pScMod->IsModalMode(); +} + +sal_Bool ScColBar::ResizeAllowed() +{ + return !pViewData->HasEditView( pViewData->GetActivePart() ) && + !pViewData->GetDocShell()->IsReadOnly(); +} + +void ScColBar::DrawInvert( long nDragPosP ) +{ + Rectangle aRect( nDragPosP,0, nDragPosP+HDR_SLIDERSIZE-1,GetOutputSizePixel().Width()-1 ); + Update(); + Invert(aRect); + + pViewData->GetView()->InvertVertical(eWhich,nDragPosP); +} + +String ScColBar::GetDragHelp( long nVal ) +{ + long nTwips = (long) ( nVal / pViewData->GetPPTX() ); + return lcl_MetricString( nTwips, ScGlobal::GetRscString(STR_TIP_WIDTH) ); +} + +sal_Bool ScColBar::IsLayoutRTL() // overloaded only for columns +{ + return pViewData->GetDocument()->IsLayoutRTL( pViewData->GetTabNo() ); +} + +//================================================================== + +ScRowBar::ScRowBar( Window* pParent, ScViewData* pData, ScVSplitPos eWhichPos, + ScHeaderFunctionSet* pFunc, ScHeaderSelectionEngine* pEng ) : + ScHeaderControl( pParent, pEng, MAXROW+1, HDR_VERTICAL ), + pViewData( pData ), + eWhich( eWhichPos ), + pFuncSet( pFunc ), + pSelEngine( pEng ) +{ + Show(); +} + +ScRowBar::~ScRowBar() +{ +} + +SCCOLROW ScRowBar::GetPos() +{ + return pViewData->GetPosY(eWhich); +} + +sal_uInt16 ScRowBar::GetEntrySize( SCCOLROW nEntryNo ) +{ + ScDocument* pDoc = pViewData->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + SCROW nLastRow = -1; + if (pDoc->RowHidden(nEntryNo, nTab, nLastRow)) + return 0; + else + return (sal_uInt16) ScViewData::ToPixel( pDoc->GetOriginalHeight( nEntryNo, + nTab ), pViewData->GetPPTY() ); +} + +String ScRowBar::GetEntryText( SCCOLROW nEntryNo ) +{ + return String::CreateFromInt32( nEntryNo + 1 ); +} + +void ScRowBar::SetEntrySize( SCCOLROW nPos, sal_uInt16 nNewSize ) +{ + sal_uInt16 nSizeTwips; + ScSizeMode eMode = SC_SIZE_DIRECT; + if (nNewSize>0 && nNewSize<10) nNewSize=10; // (Pixel) + + if ( nNewSize == HDR_SIZE_OPTIMUM ) + { + nSizeTwips = 0; + eMode = SC_SIZE_OPTIMAL; + } + else + nSizeTwips = (sal_uInt16) ( nNewSize / pViewData->GetPPTY() ); + + ScMarkData& rMark = pViewData->GetMarkData(); +// SCTAB nTab = pViewData->GetTabNo(); + + SCCOLROW* pRanges = new SCCOLROW[MAXROW+1]; + SCROW nRangeCnt = 0; + if ( rMark.IsRowMarked( nPos ) ) + { + SCROW nStart = 0; + while (nStart<=MAXROW) + { + while (nStart<MAXROW && !rMark.IsRowMarked(nStart)) + ++nStart; + if (rMark.IsRowMarked(nStart)) + { + SCROW nEnd = nStart; + while (nEnd<MAXROW && rMark.IsRowMarked(nEnd)) + ++nEnd; + if (!rMark.IsRowMarked(nEnd)) + --nEnd; + pRanges[static_cast<size_t>(2*nRangeCnt) ] = nStart; + pRanges[static_cast<size_t>(2*nRangeCnt+1)] = nEnd; + ++nRangeCnt; + nStart = nEnd+1; + } + else + nStart = MAXROW+1; + } + } + else + { + pRanges[0] = nPos; + pRanges[1] = nPos; + nRangeCnt = 1; + } + + pViewData->GetView()->SetWidthOrHeight( sal_False, nRangeCnt, pRanges, eMode, nSizeTwips ); + delete[] pRanges; +} + +void ScRowBar::HideEntries( SCCOLROW nStart, SCCOLROW nEnd ) +{ + SCCOLROW nRange[2]; + nRange[0] = nStart; + nRange[1] = nEnd; + pViewData->GetView()->SetWidthOrHeight( sal_False, 1, nRange, SC_SIZE_DIRECT, 0 ); +} + +void ScRowBar::SetMarking( sal_Bool bSet ) +{ + pViewData->GetMarkData().SetMarking( bSet ); + if (!bSet) + { + pViewData->GetView()->UpdateAutoFillMark(); + } +} + +void ScRowBar::SelectWindow() +{ + ScTabViewShell* pViewSh = pViewData->GetViewShell(); + + pViewSh->SetActive(); // Appear und SetViewFrame + pViewSh->DrawDeselectAll(); + + ScSplitPos eActive = pViewData->GetActivePart(); + if (eWhich==SC_SPLIT_TOP) + { + if (eActive==SC_SPLIT_BOTTOMLEFT) eActive=SC_SPLIT_TOPLEFT; + if (eActive==SC_SPLIT_BOTTOMRIGHT) eActive=SC_SPLIT_TOPRIGHT; + } + else + { + if (eActive==SC_SPLIT_TOPLEFT) eActive=SC_SPLIT_BOTTOMLEFT; + if (eActive==SC_SPLIT_TOPRIGHT) eActive=SC_SPLIT_BOTTOMRIGHT; + } + pViewSh->ActivatePart( eActive ); + + pFuncSet->SetColumn( sal_False ); + pFuncSet->SetWhich( eActive ); + + pViewSh->ActiveGrabFocus(); +} + +sal_Bool ScRowBar::IsDisabled() +{ + ScModule* pScMod = SC_MOD(); + return pScMod->IsFormulaMode() || pScMod->IsModalMode(); +} + +sal_Bool ScRowBar::ResizeAllowed() +{ + return !pViewData->HasEditView( pViewData->GetActivePart() ) && + !pViewData->GetDocShell()->IsReadOnly(); +} + +void ScRowBar::DrawInvert( long nDragPosP ) +{ + Rectangle aRect( 0,nDragPosP, GetOutputSizePixel().Width()-1,nDragPosP+HDR_SLIDERSIZE-1 ); + Update(); + Invert(aRect); + + pViewData->GetView()->InvertHorizontal(eWhich,nDragPosP); +} + +String ScRowBar::GetDragHelp( long nVal ) +{ + long nTwips = (long) ( nVal / pViewData->GetPPTY() ); + return lcl_MetricString( nTwips, ScGlobal::GetRscString(STR_TIP_HEIGHT) ); +} + +// GetHiddenCount ist nur fuer Zeilen ueberladen + +SCROW ScRowBar::GetHiddenCount( SCROW nEntryNo ) +{ + ScDocument* pDoc = pViewData->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + return pDoc->GetHiddenRowCount( nEntryNo, nTab ); +} + +sal_Bool ScRowBar::IsMirrored() // overloaded only for rows +{ + return pViewData->GetDocument()->IsLayoutRTL( pViewData->GetTabNo() ); +} + + diff --git a/sc/source/ui/view/dbfunc.cxx b/sc/source/ui/view/dbfunc.cxx new file mode 100644 index 000000000000..8db71ad9752f --- /dev/null +++ b/sc/source/ui/view/dbfunc.cxx @@ -0,0 +1,512 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include "scitems.hxx" +#include <sfx2/app.hxx> +#include <sfx2/bindings.hxx> +#include <vcl/msgbox.hxx> + +#include <com/sun/star/sdbc/XResultSet.hpp> + +#include "dbfunc.hxx" +#include "docsh.hxx" +#include "attrib.hxx" +#include "sc.hrc" +#include "undodat.hxx" +#include "dbcolect.hxx" +#include "globstr.hrc" +#include "global.hxx" +#include "dbdocfun.hxx" +#include "editable.hxx" + +//================================================================== + +ScDBFunc::ScDBFunc( Window* pParent, ScDocShell& rDocSh, ScTabViewShell* pViewShell ) : + ScViewFunc( pParent, rDocSh, pViewShell ) +{ +} + +//UNUSED2008-05 ScDBFunc::ScDBFunc( Window* pParent, const ScDBFunc& rDBFunc, ScTabViewShell* pViewShell ) : +//UNUSED2008-05 ScViewFunc( pParent, rDBFunc, pViewShell ) +//UNUSED2008-05 { +//UNUSED2008-05 } + +ScDBFunc::~ScDBFunc() +{ +} + +// +// Hilfsfunktionen +// + +void ScDBFunc::GotoDBArea( const String& rDBName ) +{ + ScDocument* pDoc = GetViewData()->GetDocument(); + ScDBCollection* pDBCol = pDoc->GetDBCollection(); + + sal_uInt16 nFoundAt = 0; + if ( pDBCol->SearchName( rDBName, nFoundAt ) ) + { + ScDBData* pData = (*pDBCol)[nFoundAt]; + DBG_ASSERT( pData, "GotoDBArea: Datenbankbereich nicht gefunden!" ); + + if ( pData ) + { + SCTAB nTab = 0; + SCCOL nStartCol = 0; + SCROW nStartRow = 0; + SCCOL nEndCol = 0; + SCROW nEndRow = 0; + + pData->GetArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow ); + SetTabNo( nTab ); + + MoveCursorAbs( nStartCol, nStartRow, ScFollowMode( SC_FOLLOW_JUMP ), + sal_False, sal_False ); // bShift,bControl + DoneBlockMode(); + InitBlockMode( nStartCol, nStartRow, nTab ); + MarkCursor( nEndCol, nEndRow, nTab ); + SelectionChanged(); + } + } +} + +// aktuellen Datenbereich fuer Sortieren / Filtern suchen + +ScDBData* ScDBFunc::GetDBData( sal_Bool bMark, ScGetDBMode eMode, ScGetDBSelection eSel ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDBData* pData = NULL; + ScRange aRange; + ScMarkType eMarkType = GetViewData()->GetSimpleArea(aRange); + if ( eMarkType == SC_MARK_SIMPLE || eMarkType == SC_MARK_SIMPLE_FILTERED ) + { + bool bShrinkColumnsOnly = false; + if (eSel == SC_DBSEL_ROW_DOWN) + { + // Don't alter row range, additional rows may have been selected on + // purpose to append data, or to have a fake header row. + bShrinkColumnsOnly = true; + // Select further rows only if only one row or a portion thereof is + // selected. + if (aRange.aStart.Row() != aRange.aEnd.Row()) + { + // If an area is selected shrink that to the actual used + // columns, don't draw filter buttons for empty columns. + eSel = SC_DBSEL_SHRINK_TO_USED_DATA; + } + else if (aRange.aStart.Col() == aRange.aEnd.Col()) + { + // One cell only, if it is not marked obtain entire used data + // area. + const ScMarkData& rMarkData = GetViewData()->GetMarkData(); + if (!(rMarkData.IsMarked() || rMarkData.IsMultiMarked())) + eSel = SC_DBSEL_KEEP; + } + } + switch (eSel) + { + case SC_DBSEL_SHRINK_TO_SHEET_DATA: + { + // Shrink the selection to sheet data area. + ScDocument* pDoc = pDocSh->GetDocument(); + SCCOL nCol1 = aRange.aStart.Col(), nCol2 = aRange.aEnd.Col(); + SCROW nRow1 = aRange.aStart.Row(), nRow2 = aRange.aEnd.Row(); + if (pDoc->ShrinkToDataArea( aRange.aStart.Tab(), nCol1, nRow1, nCol2, nRow2)) + { + aRange.aStart.SetCol(nCol1); + aRange.aEnd.SetCol(nCol2); + aRange.aStart.SetRow(nRow1); + aRange.aEnd.SetRow(nRow2); + } + } + break; + case SC_DBSEL_SHRINK_TO_USED_DATA: + case SC_DBSEL_ROW_DOWN: + { + // Shrink the selection to actual used area. + ScDocument* pDoc = pDocSh->GetDocument(); + SCCOL nCol1 = aRange.aStart.Col(), nCol2 = aRange.aEnd.Col(); + SCROW nRow1 = aRange.aStart.Row(), nRow2 = aRange.aEnd.Row(); + bool bShrunk; + pDoc->ShrinkToUsedDataArea( bShrunk, aRange.aStart.Tab(), + nCol1, nRow1, nCol2, nRow2, bShrinkColumnsOnly); + if (bShrunk) + { + aRange.aStart.SetCol(nCol1); + aRange.aEnd.SetCol(nCol2); + aRange.aStart.SetRow(nRow1); + aRange.aEnd.SetRow(nRow2); + } + } + break; + default: + ; // nothing + } + pData = pDocSh->GetDBData( aRange, eMode, eSel ); + } + else if ( eMode != SC_DB_OLD ) + pData = pDocSh->GetDBData( + ScRange( GetViewData()->GetCurX(), GetViewData()->GetCurY(), + GetViewData()->GetTabNo() ), + eMode, SC_DBSEL_KEEP ); + + if ( pData && bMark ) + { + ScRange aFound; + pData->GetArea(aFound); + MarkRange( aFound, sal_False ); + } + return pData; +} + +// Datenbankbereiche aendern (Dialog) + +void ScDBFunc::NotifyCloseDbNameDlg( const ScDBCollection& rNewColl, const List& rDelAreaList ) +{ + + ScDocShell* pDocShell = GetViewData()->GetDocShell(); + ScDocShellModificator aModificator( *pDocShell ); + ScDocument* pDoc = pDocShell->GetDocument(); + ScDBCollection* pOldColl = pDoc->GetDBCollection(); + ScDBCollection* pUndoColl = NULL; + ScDBCollection* pRedoColl = NULL; + const sal_Bool bRecord (pDoc->IsUndoEnabled()); + + long nDelCount = rDelAreaList.Count(); + for (long nDelPos=0; nDelPos<nDelCount; nDelPos++) + { + ScRange* pEntry = (ScRange*) rDelAreaList.GetObject(nDelPos); + + if ( pEntry ) + { + ScAddress& rStart = pEntry->aStart; + ScAddress& rEnd = pEntry->aEnd; + pDocShell->DBAreaDeleted( rStart.Tab(), + rStart.Col(), rStart.Row(), + rEnd.Col(), rEnd.Row() ); + + // Targets am SBA abmelden nicht mehr noetig + } + } + + if (bRecord) + pUndoColl = new ScDBCollection( *pOldColl ); + + // neue Targets am SBA anmelden nicht mehr noetig + + pDoc->CompileDBFormula( sal_True ); // CreateFormulaString + pDoc->SetDBCollection( new ScDBCollection( rNewColl ) ); + pDoc->CompileDBFormula( sal_False ); // CompileFormulaString + pOldColl = NULL; + pDocShell->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID ); + aModificator.SetDocumentModified(); + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) ); + + if (bRecord) + { + pRedoColl = new ScDBCollection( rNewColl ); + pDocShell->GetUndoManager()->AddUndoAction( + new ScUndoDBData( pDocShell, pUndoColl, pRedoColl ) ); + } +} + +// +// wirkliche Funktionen +// + +// Sortieren + +void ScDBFunc::UISort( const ScSortParam& rSortParam, sal_Bool bRecord ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = GetViewData()->GetTabNo(); + ScDBData* pDBData = pDoc->GetDBAtArea( nTab, rSortParam.nCol1, rSortParam.nRow1, + rSortParam.nCol2, rSortParam.nRow2 ); + if (!pDBData) + { + DBG_ERROR( "Sort: keine DBData" ); + return; + } + + ScSubTotalParam aSubTotalParam; + pDBData->GetSubTotalParam( aSubTotalParam ); + if (aSubTotalParam.bGroupActive[0] && !aSubTotalParam.bRemoveOnly) + { + // Subtotals wiederholen, mit neuer Sortierung + + DoSubTotals( aSubTotalParam, bRecord, &rSortParam ); + } + else + { + Sort( rSortParam, bRecord ); // nur sortieren + } +} + +void ScDBFunc::Sort( const ScSortParam& rSortParam, sal_Bool bRecord, sal_Bool bPaint ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + SCTAB nTab = GetViewData()->GetTabNo(); + ScDBDocFunc aDBDocFunc( *pDocSh ); + sal_Bool bSuccess = aDBDocFunc.Sort( nTab, rSortParam, bRecord, bPaint, sal_False ); + if ( bSuccess && !rSortParam.bInplace ) + { + // Ziel markieren + ScRange aDestRange( rSortParam.nDestCol, rSortParam.nDestRow, rSortParam.nDestTab, + rSortParam.nDestCol + rSortParam.nCol2 - rSortParam.nCol1, + rSortParam.nDestRow + rSortParam.nRow2 - rSortParam.nRow1, + rSortParam.nDestTab ); + MarkRange( aDestRange ); + } +} + +// Filtern + +void ScDBFunc::Query( const ScQueryParam& rQueryParam, const ScRange* pAdvSource, sal_Bool bRecord ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + SCTAB nTab = GetViewData()->GetTabNo(); + ScDBDocFunc aDBDocFunc( *pDocSh ); + sal_Bool bSuccess = aDBDocFunc.Query( nTab, rQueryParam, pAdvSource, bRecord, sal_False ); + + if (bSuccess) + { + sal_Bool bCopy = !rQueryParam.bInplace; + if (bCopy) + { + // Zielbereich markieren (DB-Bereich wurde ggf. angelegt) + ScDocument* pDoc = pDocSh->GetDocument(); + ScDBData* pDestData = pDoc->GetDBAtCursor( + rQueryParam.nDestCol, rQueryParam.nDestRow, + rQueryParam.nDestTab, sal_True ); + if (pDestData) + { + ScRange aDestRange; + pDestData->GetArea(aDestRange); + MarkRange( aDestRange ); + } + } + + if (!bCopy) + { + UpdateScrollBars(); + SelectionChanged(); // for attribute states (filtered rows are ignored) + } + + GetViewData()->GetBindings().Invalidate( SID_UNFILTER ); + } +} + +// Autofilter-Knoepfe ein-/ausblenden + +void ScDBFunc::ToggleAutoFilter() +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocShellModificator aModificator( *pDocSh ); + + ScQueryParam aParam; + ScDocument* pDoc = GetViewData()->GetDocument(); + ScDBData* pDBData = GetDBData( sal_False, SC_DB_MAKE, SC_DBSEL_ROW_DOWN ); + + pDBData->SetByRow( sal_True ); //! Undo, vorher abfragen ?? + pDBData->GetQueryParam( aParam ); + + + SCCOL nCol; + SCROW nRow = aParam.nRow1; + SCTAB nTab = GetViewData()->GetTabNo(); + sal_Int16 nFlag; + sal_Bool bHasAuto = sal_True; + sal_Bool bHeader = pDBData->HasHeader(); + sal_Bool bPaint = sal_False; + + //! stattdessen aus DB-Bereich abfragen? + + for (nCol=aParam.nCol1; nCol<=aParam.nCol2 && bHasAuto; nCol++) + { + nFlag = ((ScMergeFlagAttr*) pDoc-> + GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG ))->GetValue(); + + if ( (nFlag & SC_MF_AUTO) == 0 ) + bHasAuto = sal_False; + } + + if (bHasAuto) // aufheben + { + // Filterknoepfe ausblenden + + for (nCol=aParam.nCol1; nCol<=aParam.nCol2; nCol++) + { + nFlag = ((ScMergeFlagAttr*) pDoc-> + GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG ))->GetValue(); + pDoc->ApplyAttr( nCol, nRow, nTab, ScMergeFlagAttr( nFlag & ~SC_MF_AUTO ) ); + } + + // use a list action for the AutoFilter buttons (ScUndoAutoFilter) and the filter operation + + String aUndo = ScGlobal::GetRscString( STR_UNDO_QUERY ); + pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo ); + + ScRange aRange; + pDBData->GetArea( aRange ); + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoAutoFilter( pDocSh, aRange, pDBData->GetName(), sal_False ) ); + + pDBData->SetAutoFilter(sal_False); + + // Filter aufheben (incl. Paint / Undo) + + SCSIZE nEC = aParam.GetEntryCount(); + for (SCSIZE i=0; i<nEC; i++) + aParam.GetEntry(i).bDoQuery = sal_False; + aParam.bDuplicate = sal_True; + Query( aParam, NULL, sal_True ); + + pDocSh->GetUndoManager()->LeaveListAction(); + + bPaint = sal_True; + } + else // Filterknoepfe einblenden + { + if ( !pDoc->IsBlockEmpty( nTab, + aParam.nCol1, aParam.nRow1, + aParam.nCol2, aParam.nRow2 ) ) + { + if (!bHeader) + { + if ( MessBox( GetViewData()->GetDialogParent(), WinBits(WB_YES_NO | WB_DEF_YES), + ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_0 ), // "StarCalc" + ScGlobal::GetRscString( STR_MSSG_MAKEAUTOFILTER_0 ) // Koepfe aus erster Zeile? + ).Execute() == RET_YES ) + { + pDBData->SetHeader( sal_True ); //! Undo ?? + bHeader = sal_True; + } + } + + ScRange aRange; + pDBData->GetArea( aRange ); + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoAutoFilter( pDocSh, aRange, pDBData->GetName(), sal_True ) ); + + pDBData->SetAutoFilter(sal_True); + + for (nCol=aParam.nCol1; nCol<=aParam.nCol2; nCol++) + { + nFlag = ((ScMergeFlagAttr*) pDoc-> + GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG ))->GetValue(); + pDoc->ApplyAttr( nCol, nRow, nTab, ScMergeFlagAttr( nFlag | SC_MF_AUTO ) ); + } + pDocSh->PostPaint( aParam.nCol1, nRow, nTab, aParam.nCol2, nRow, nTab, + PAINT_GRID ); + bPaint = sal_True; + } + else + { + ErrorBox aErrorBox( GetViewData()->GetDialogParent(), WinBits( WB_OK | WB_DEF_OK ), + ScGlobal::GetRscString( STR_ERR_AUTOFILTER ) ); + aErrorBox.Execute(); + } + } + + if ( bPaint ) + { + aModificator.SetDocumentModified(); + + SfxBindings& rBindings = GetViewData()->GetBindings(); + rBindings.Invalidate( SID_AUTO_FILTER ); + rBindings.Invalidate( SID_AUTOFILTER_HIDE ); + } +} + +// nur ausblenden, keine Daten veraendern + +void ScDBFunc::HideAutoFilter() +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocShellModificator aModificator( *pDocSh ); + + ScDocument* pDoc = pDocSh->GetDocument(); + + ScQueryParam aParam; + ScDBData* pDBData = GetDBData( sal_False ); + + SCTAB nTab; + SCCOL nCol1, nCol2; + SCROW nRow1, nRow2; + pDBData->GetArea(nTab, nCol1, nRow1, nCol2, nRow2); + + for (SCCOL nCol=nCol1; nCol<=nCol2; nCol++) + { + sal_Int16 nFlag = ((ScMergeFlagAttr*) pDoc-> + GetAttr( nCol, nRow1, nTab, ATTR_MERGE_FLAG ))->GetValue(); + pDoc->ApplyAttr( nCol, nRow1, nTab, ScMergeFlagAttr( nFlag & ~SC_MF_AUTO ) ); + } + + ScRange aRange; + pDBData->GetArea( aRange ); + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoAutoFilter( pDocSh, aRange, pDBData->GetName(), sal_False ) ); + + pDBData->SetAutoFilter(sal_False); + + pDocSh->PostPaint( nCol1,nRow1,nTab, nCol2,nRow1,nTab, PAINT_GRID ); + aModificator.SetDocumentModified(); + + SfxBindings& rBindings = GetViewData()->GetBindings(); + rBindings.Invalidate( SID_AUTO_FILTER ); + rBindings.Invalidate( SID_AUTOFILTER_HIDE ); +} + +// Re-Import + +sal_Bool ScDBFunc::ImportData( const ScImportParam& rParam, sal_Bool bRecord ) +{ + ScDocument* pDoc = GetViewData()->GetDocument(); + ScEditableTester aTester( pDoc, GetViewData()->GetTabNo(), rParam.nCol1,rParam.nRow1, + rParam.nCol2,rParam.nRow2 ); + if ( !aTester.IsEditable() ) + { + ErrorMessage(aTester.GetMessageId()); + return sal_False; + } + + ScDBDocFunc aDBDocFunc( *GetViewData()->GetDocShell() ); + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet > xResultSet; + return aDBDocFunc.DoImport( GetViewData()->GetTabNo(), rParam, xResultSet, NULL, bRecord ); +} + + + diff --git a/sc/source/ui/view/dbfunc2.cxx b/sc/source/ui/view/dbfunc2.cxx new file mode 100644 index 000000000000..d3e4229736d3 --- /dev/null +++ b/sc/source/ui/view/dbfunc2.cxx @@ -0,0 +1,77 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + + +#include "dbfunc.hxx" +#include "docsh.hxx" +#include "global.hxx" +#include "document.hxx" +#include "sc.hrc" +#include "globstr.hrc" + + +// STATIC DATA ----------------------------------------------------------- + + +#ifdef _MSC_VER +#pragma optimize ( "", off ) +#endif + +//================================================================== + +class ScDrawLayer; +class ScChartCollection; + +void ScDBFunc::UpdateCharts( sal_Bool bAllCharts ) +{ + sal_uInt16 nFound = 0; + ScViewData* pViewData = GetViewData(); + ScDocument* pDoc = pViewData->GetDocument(); + + if ( pDoc->GetDrawLayer() ) + nFound = DoUpdateCharts( ScAddress( pViewData->GetCurX(), + pViewData->GetCurY(), + pViewData->GetTabNo()), + pDoc, + bAllCharts ); + + if ( !nFound && !bAllCharts ) + ErrorMessage(STR_NOCHARTATCURSOR); +} + + + + + + diff --git a/sc/source/ui/view/dbfunc3.cxx b/sc/source/ui/view/dbfunc3.cxx new file mode 100644 index 000000000000..bfb3b1de0f82 --- /dev/null +++ b/sc/source/ui/view/dbfunc3.cxx @@ -0,0 +1,2375 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include "dbfunc.hxx" +#include "scitems.hxx" +#include <sfx2/bindings.hxx> +#include <vcl/svapp.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/sound.hxx> +#include <vcl/waitobj.hxx> +#include <svl/zforlist.hxx> +#include <sfx2/app.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/sheet/DataPilotFieldFilter.hpp> +#include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp> +#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp> +#include <com/sun/star/sheet/DataPilotFieldSortMode.hpp> +#include <com/sun/star/sheet/DataPilotTableHeaderData.hpp> +#include <com/sun/star/sheet/GeneralFunction.hpp> +#include <com/sun/star/sheet/MemberResultFlags.hpp> +#include <com/sun/star/sheet/XDimensionsSupplier.hpp> +#include <com/sun/star/sheet/XDrillDownDataSupplier.hpp> + +#include "global.hxx" +#include "globstr.hrc" +#include "sc.hrc" +#include "undotab.hxx" +#include "undodat.hxx" +#include "dbcolect.hxx" +#include "rangenam.hxx" +#include "rangeutl.hxx" +#include "docsh.hxx" +#include "olinetab.hxx" +#include "consoli.hxx" +#include "olinefun.hxx" +#include "dpobject.hxx" +#include "dpsave.hxx" +#include "dpdimsave.hxx" +#include "dbdocfun.hxx" +#include "dpoutput.hxx" +#include "dptabsrc.hxx" +#include "editable.hxx" +#include "docpool.hxx" +#include "patattr.hxx" +#include "unonames.hxx" +#include "cell.hxx" +#include "userlist.hxx" + +#include <hash_set> +#include <hash_map> +#include <memory> +#include <list> +#include <vector> + +using namespace com::sun::star; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::beans::XPropertySet; +using ::com::sun::star::container::XNameAccess; +using ::com::sun::star::sheet::XDimensionsSupplier; +using ::rtl::OUString; +using ::rtl::OUStringHash; +using ::rtl::OUStringBuffer; +using ::std::auto_ptr; +using ::std::list; +using ::std::vector; +using ::std::hash_map; +using ::std::hash_set; + +// STATIC DATA ----------------------------------------------------------- + + +//================================================================== + +// +// Outliner +// + +// Outline-Gruppierung erzeugen + +void ScDBFunc::MakeOutline( sal_Bool bColumns, sal_Bool bRecord ) +{ + ScRange aRange; + if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE) + { + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScOutlineDocFunc aFunc(*pDocSh); + aFunc.MakeOutline( aRange, bColumns, bRecord, sal_False ); + } + else + ErrorMessage(STR_NOMULTISELECT); +} + +// Outline-Gruppierung loeschen + +void ScDBFunc::RemoveOutline( sal_Bool bColumns, sal_Bool bRecord ) +{ + ScRange aRange; + if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE) + { + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScOutlineDocFunc aFunc(*pDocSh); + aFunc.RemoveOutline( aRange, bColumns, bRecord, sal_False ); + } + else + ErrorMessage(STR_NOMULTISELECT); +} + +// Menue-Status: Outlines loeschen + +void ScDBFunc::TestRemoveOutline( sal_Bool& rCol, sal_Bool& rRow ) +{ + sal_Bool bColFound = sal_False; + sal_Bool bRowFound = sal_False; + + SCCOL nStartCol, nEndCol; + SCROW nStartRow, nEndRow; + SCTAB nStartTab, nEndTab; + if (GetViewData()->GetSimpleArea(nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab) == SC_MARK_SIMPLE) + { + SCTAB nTab = nStartTab; + ScDocument* pDoc = GetViewData()->GetDocument(); + ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab ); + if (pTable) + { + ScOutlineArray* pArray; + ScOutlineEntry* pEntry; + SCCOLROW nStart; + SCCOLROW nEnd; + sal_Bool bColMarked = ( nStartRow == 0 && nEndRow == MAXROW ); + sal_Bool bRowMarked = ( nStartCol == 0 && nEndCol == MAXCOL ); + + // Spalten + + if ( !bRowMarked || bColMarked ) // nicht wenn ganze Zeilen markiert + { + pArray = pTable->GetColArray(); + ScSubOutlineIterator aColIter( pArray ); + while ((pEntry=aColIter.GetNext()) != NULL && !bColFound) + { + nStart = pEntry->GetStart(); + nEnd = pEntry->GetEnd(); + if ( nStartCol<=static_cast<SCCOL>(nEnd) && nEndCol>=static_cast<SCCOL>(nStart) ) + bColFound = sal_True; + } + } + + // Zeilen + + if ( !bColMarked || bRowMarked ) // nicht wenn ganze Spalten markiert + { + pArray = pTable->GetRowArray(); + ScSubOutlineIterator aRowIter( pArray ); + while ((pEntry=aRowIter.GetNext()) != NULL && !bRowFound) + { + nStart = pEntry->GetStart(); + nEnd = pEntry->GetEnd(); + if ( nStartRow<=nEnd && nEndRow>=nStart ) + bRowFound = sal_True; + } + } + } + } + + rCol = bColFound; + rRow = bRowFound; +} + +void ScDBFunc::RemoveAllOutlines( sal_Bool bRecord ) +{ + SCTAB nTab = GetViewData()->GetTabNo(); + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScOutlineDocFunc aFunc(*pDocSh); + + HideCursor(); + sal_Bool bOk = aFunc.RemoveAllOutlines( nTab, bRecord, sal_False ); + ShowCursor(); + + if (bOk) + UpdateScrollBars(); +} + +// Auto-Outlines + +void ScDBFunc::AutoOutline( sal_Bool bRecord ) +{ + SCTAB nTab = GetViewData()->GetTabNo(); + ScRange aRange( 0,0,nTab, MAXCOL,MAXROW,nTab ); // ganze Tabelle, wenn nichts markiert + ScMarkData& rMark = GetViewData()->GetMarkData(); + if ( rMark.IsMarked() || rMark.IsMultiMarked() ) + { + rMark.MarkToMulti(); + rMark.GetMultiMarkArea( aRange ); + } + + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScOutlineDocFunc aFunc(*pDocSh); + aFunc.AutoOutline( aRange, bRecord, sal_False ); +} + +// Outline-Ebene auswaehlen + +void ScDBFunc::SelectLevel( sal_Bool bColumns, sal_uInt16 nLevel, sal_Bool bRecord, sal_Bool bPaint ) +{ + SCTAB nTab = GetViewData()->GetTabNo(); + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScOutlineDocFunc aFunc(*pDocSh); + + HideCursor(); + sal_Bool bOk = aFunc.SelectLevel( nTab, bColumns, nLevel, bRecord, bPaint, sal_False ); + ShowCursor(); + + if (bOk) + UpdateScrollBars(); +} + +// einzelne Outline-Gruppe einblenden + +void ScDBFunc::ShowOutline( sal_Bool bColumns, sal_uInt16 nLevel, sal_uInt16 nEntry, sal_Bool bRecord, sal_Bool bPaint ) +{ + SCTAB nTab = GetViewData()->GetTabNo(); + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScOutlineDocFunc aFunc(*pDocSh); + + HideCursor(); + sal_Bool bOk = aFunc.ShowOutline( nTab, bColumns, nLevel, nEntry, bRecord, bPaint, sal_False ); + ShowCursor(); + + if ( bOk && bPaint ) + UpdateScrollBars(); +} + +// einzelne Outline-Gruppe ausblenden + +void ScDBFunc::HideOutline( sal_Bool bColumns, sal_uInt16 nLevel, sal_uInt16 nEntry, sal_Bool bRecord, sal_Bool bPaint ) +{ + SCTAB nTab = GetViewData()->GetTabNo(); + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScOutlineDocFunc aFunc(*pDocSh); + + HideCursor(); + sal_Bool bOk = aFunc.HideOutline( nTab, bColumns, nLevel, nEntry, bRecord, bPaint, sal_False ); + ShowCursor(); + + if ( bOk && bPaint ) + UpdateScrollBars(); +} + +// Menue-Status: markierten Bereich ein-/ausblenden + +sal_Bool ScDBFunc::OutlinePossible(sal_Bool bHide) +{ + sal_Bool bEnable = sal_False; + + SCCOL nStartCol; + SCROW nStartRow; + SCTAB nStartTab; + SCCOL nEndCol; + SCROW nEndRow; + SCTAB nEndTab; + + if (GetViewData()->GetSimpleArea(nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab) == SC_MARK_SIMPLE) + { + ScDocument* pDoc = GetViewData()->GetDocument(); + SCTAB nTab = GetViewData()->GetTabNo(); + ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab ); + if (pTable) + { + ScOutlineArray* pArray; + ScOutlineEntry* pEntry; + SCCOLROW nStart; + SCCOLROW nEnd; + + // Spalten + + pArray = pTable->GetColArray(); + ScSubOutlineIterator aColIter( pArray ); + while ((pEntry=aColIter.GetNext()) != NULL && !bEnable) + { + nStart = pEntry->GetStart(); + nEnd = pEntry->GetEnd(); + if ( bHide ) + { + if ( nStartCol<=static_cast<SCCOL>(nEnd) && nEndCol>=static_cast<SCCOL>(nStart) ) + if (!pEntry->IsHidden()) + bEnable = sal_True; + } + else + { + if ( nStart>=nStartCol && nEnd<=nEndCol ) + if (pEntry->IsHidden()) + bEnable = sal_True; + } + } + + // Zeilen + + pArray = pTable->GetRowArray(); + ScSubOutlineIterator aRowIter( pArray ); + while ((pEntry=aRowIter.GetNext()) != NULL) + { + nStart = pEntry->GetStart(); + nEnd = pEntry->GetEnd(); + if ( bHide ) + { + if ( nStartRow<=nEnd && nEndRow>=nStart ) + if (!pEntry->IsHidden()) + bEnable = sal_True; + } + else + { + if ( nStart>=nStartRow && nEnd<=nEndRow ) + if (pEntry->IsHidden()) + bEnable = sal_True; + } + } + } + } + + return bEnable; +} + +// markierten Bereich einblenden + +void ScDBFunc::ShowMarkedOutlines( sal_Bool bRecord ) +{ + ScRange aRange; + if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE) + { + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScOutlineDocFunc aFunc(*pDocSh); + HideCursor(); + sal_Bool bDone = aFunc.ShowMarkedOutlines( aRange, bRecord, sal_False ); + ShowCursor(); + if (bDone) + UpdateScrollBars(); + } + else + ErrorMessage(STR_NOMULTISELECT); +} + +// markierten Bereich ausblenden + +void ScDBFunc::HideMarkedOutlines( sal_Bool bRecord ) +{ + ScRange aRange; + if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE) + { + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScOutlineDocFunc aFunc(*pDocSh); + HideCursor(); + sal_Bool bDone = aFunc.HideMarkedOutlines( aRange, bRecord, sal_False ); + ShowCursor(); + if (bDone) + UpdateScrollBars(); + } + else + ErrorMessage(STR_NOMULTISELECT); +} + +// -------------------------------------------------------------------------- + +// +// Teilergebnisse +// + +void ScDBFunc::DoSubTotals( const ScSubTotalParam& rParam, sal_Bool bRecord, + const ScSortParam* pForceNewSort ) +{ + sal_Bool bDo = !rParam.bRemoveOnly; // sal_False = nur loeschen + + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + SCTAB nTab = GetViewData()->GetTabNo(); + if (bRecord && !pDoc->IsUndoEnabled()) + bRecord = sal_False; + + ScDBData* pDBData = pDoc->GetDBAtArea( nTab, rParam.nCol1, rParam.nRow1, + rParam.nCol2, rParam.nRow2 ); + if (!pDBData) + { + DBG_ERROR( "SubTotals: keine DBData" ); + return; + } + + ScEditableTester aTester( pDoc, nTab, 0,rParam.nRow1+1, MAXCOL,MAXROW ); + if (!aTester.IsEditable()) + { + ErrorMessage(aTester.GetMessageId()); + return; + } + + if (pDoc->HasAttrib( rParam.nCol1, rParam.nRow1+1, nTab, + rParam.nCol2, rParam.nRow2, nTab, HASATTR_MERGED | HASATTR_OVERLAPPED )) + { + ErrorMessage(STR_MSSG_INSERTCELLS_0); // nicht in zusammengefasste einfuegen + return; + } + + WaitObject aWait( GetViewData()->GetDialogParent() ); + sal_Bool bOk = sal_True; + sal_Bool bDelete = sal_False; + if (rParam.bReplace) + if (pDoc->TestRemoveSubTotals( nTab, rParam )) + { + bDelete = sal_True; + bOk = ( MessBox( GetViewData()->GetDialogParent(), WinBits(WB_YES_NO | WB_DEF_YES), + // "StarCalc" "Daten loeschen?" + ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_0 ), + ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_1 ) ).Execute() + == RET_YES ); + } + + if (bOk) + { + ScDocShellModificator aModificator( *pDocSh ); + + ScSubTotalParam aNewParam( rParam ); // Bereichsende wird veraendert + ScDocument* pUndoDoc = NULL; + ScOutlineTable* pUndoTab = NULL; + ScRangeName* pUndoRange = NULL; + ScDBCollection* pUndoDB = NULL; + SCTAB nTabCount = 0; // fuer Referenz-Undo + + if (bRecord) // alte Daten sichern + { + sal_Bool bOldFilter = bDo && rParam.bDoSort; + + nTabCount = pDoc->GetTableCount(); + pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab ); + if (pTable) + { + pUndoTab = new ScOutlineTable( *pTable ); + + SCCOLROW nOutStartCol; // Zeilen/Spaltenstatus + SCCOLROW nOutStartRow; + SCCOLROW nOutEndCol; + SCCOLROW nOutEndRow; + pTable->GetColArray()->GetRange( nOutStartCol, nOutEndCol ); + pTable->GetRowArray()->GetRange( nOutStartRow, nOutEndRow ); + + pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_True ); + pDoc->CopyToDocument( static_cast<SCCOL>(nOutStartCol), 0, nTab, static_cast<SCCOL>(nOutEndCol), MAXROW, nTab, IDF_NONE, sal_False, pUndoDoc ); + pDoc->CopyToDocument( 0, nOutStartRow, nTab, MAXCOL, nOutEndRow, nTab, IDF_NONE, sal_False, pUndoDoc ); + } + else + pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_False, bOldFilter ); + + // Datenbereich sichern - incl. Filter-Ergebnis + pDoc->CopyToDocument( 0,rParam.nRow1+1,nTab, MAXCOL,rParam.nRow2,nTab, + IDF_ALL, sal_False, pUndoDoc ); + + // alle Formeln wegen Referenzen + pDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1, + IDF_FORMULA, sal_False, pUndoDoc ); + + // DB- und andere Bereiche + ScRangeName* pDocRange = pDoc->GetRangeName(); + if (pDocRange->GetCount()) + pUndoRange = new ScRangeName( *pDocRange ); + ScDBCollection* pDocDB = pDoc->GetDBCollection(); + if (pDocDB->GetCount()) + pUndoDB = new ScDBCollection( *pDocDB ); + } + +// pDoc->SetOutlineTable( nTab, NULL ); + ScOutlineTable* pOut = pDoc->GetOutlineTable( nTab ); + if (pOut) + pOut->GetRowArray()->RemoveAll(); // nur Zeilen-Outlines loeschen + + if (rParam.bReplace) + pDoc->RemoveSubTotals( nTab, aNewParam ); + sal_Bool bSuccess = sal_True; + if (bDo) + { + // Sortieren + if ( rParam.bDoSort || pForceNewSort ) + { + pDBData->SetArea( nTab, aNewParam.nCol1,aNewParam.nRow1, aNewParam.nCol2,aNewParam.nRow2 ); + + // Teilergebnis-Felder vor die Sortierung setzen + // (doppelte werden weggelassen, kann darum auch wieder aufgerufen werden) + + ScSortParam aOldSort; + pDBData->GetSortParam( aOldSort ); + ScSortParam aSortParam( aNewParam, pForceNewSort ? *pForceNewSort : aOldSort ); + Sort( aSortParam, sal_False, sal_False ); + } + + bSuccess = pDoc->DoSubTotals( nTab, aNewParam ); + } + ScRange aDirtyRange( aNewParam.nCol1, aNewParam.nRow1, nTab, + aNewParam.nCol2, aNewParam.nRow2, nTab ); + pDoc->SetDirty( aDirtyRange ); + + if (bRecord) + { +// ScDBData* pUndoDBData = pDBData ? new ScDBData( *pDBData ) : NULL; + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoSubTotals( pDocSh, nTab, + rParam, aNewParam.nRow2, + pUndoDoc, pUndoTab, // pUndoDBData, + pUndoRange, pUndoDB ) ); + } + + if (!bSuccess) + { + // "Kann keine Zeilen einfuegen" + ErrorMessage(STR_MSSG_DOSUBTOTALS_2); + } + + // merken + pDBData->SetSubTotalParam( aNewParam ); + pDBData->SetArea( nTab, aNewParam.nCol1,aNewParam.nRow1, aNewParam.nCol2,aNewParam.nRow2 ); + pDoc->CompileDBFormula(); + + DoneBlockMode(); + InitOwnBlockMode(); + rMark.SetMarkArea( ScRange( aNewParam.nCol1,aNewParam.nRow1,nTab, + aNewParam.nCol2,aNewParam.nRow2,nTab ) ); + MarkDataChanged(); + + pDocSh->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, + PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE ); + + aModificator.SetDocumentModified(); + + SelectionChanged(); + } +} + +// +// Consolidate +// + +void ScDBFunc::Consolidate( const ScConsolidateParam& rParam, sal_Bool bRecord ) +{ + ScDocShell* pDocShell = GetViewData()->GetDocShell(); + pDocShell->DoConsolidate( rParam, bRecord ); + SetTabNo( rParam.nTab, sal_True ); +} + +// +// Pivot +// + +String lcl_MakePivotTabName( const String& rPrefix, SCTAB nNumber ) +{ + String aName = rPrefix; + aName += String::CreateFromInt32( nNumber ); + return aName; +} + +bool ScDBFunc::MakePivotTable( const ScDPSaveData& rData, const ScRange& rDest, sal_Bool bNewTable, + const ScDPObject& rSource, sal_Bool bApi ) +{ + // #70096# error message if no fields are set + // this must be removed when drag&drop of fields from a toolbox is available + + if ( rData.IsEmpty() && !bApi ) + { + ErrorMessage(STR_PIVOT_NODATA); + return false; + } + + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = GetViewData()->GetDocument(); + sal_Bool bUndo(pDoc->IsUndoEnabled()); + + ScRange aDestRange = rDest; + if ( bNewTable ) + { + SCTAB nSrcTab = GetViewData()->GetTabNo(); + + String aName( ScGlobal::GetRscString(STR_PIVOT_TABLE) ); + String aStr; + + pDoc->GetName( nSrcTab, aStr ); + aName += '_'; + aName += aStr; + aName += '_'; + + SCTAB nNewTab = nSrcTab+1; + + SCTAB i=1; + while ( !pDoc->InsertTab( nNewTab, lcl_MakePivotTabName( aName, i ) ) && i <= MAXTAB ) + i++; + + sal_Bool bAppend = ( nNewTab+1 == pDoc->GetTableCount() ); + if (bUndo) + { + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoInsertTab( pDocSh, nNewTab, bAppend, lcl_MakePivotTabName( aName, i ) )); + } + + GetViewData()->InsertTab( nNewTab ); + SetTabNo( nNewTab, sal_True ); + + aDestRange = ScRange( 0, 0, nNewTab ); + } + + ScDPObject* pDPObj = pDoc->GetDPAtCursor( + aDestRange.aStart.Col(), aDestRange.aStart.Row(), aDestRange.aStart.Tab() ); + + ScDPObject aObj( rSource ); + aObj.SetOutRange( aDestRange ); + if ( pDPObj && !rData.GetExistingDimensionData() ) + { + // copy dimension data from old object - lost in the dialog + //! change the dialog to keep the dimension data + + ScDPSaveData aNewData( rData ); + const ScDPSaveData* pOldData = pDPObj->GetSaveData(); + if ( pOldData ) + { + const ScDPDimensionSaveData* pDimSave = pOldData->GetExistingDimensionData(); + aNewData.SetDimensionData( pDimSave ); + } + aObj.SetSaveData( aNewData ); + } + else + aObj.SetSaveData( rData ); + + sal_Bool bAllowMove = ( pDPObj != NULL ); // allow re-positioning when editing existing table + + ScDBDocFunc aFunc( *pDocSh ); + bool bSuccess = aFunc.DataPilotUpdate( pDPObj, &aObj, sal_True, sal_False, bAllowMove ); + + CursorPosChanged(); // shells may be switched + + if ( bNewTable ) + { + pDocSh->PostPaintExtras(); + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); + } + + return bSuccess; +} + +void ScDBFunc::DeletePivotTable() +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + ScDPObject* pDPObj = pDoc->GetDPAtCursor( GetViewData()->GetCurX(), + GetViewData()->GetCurY(), + GetViewData()->GetTabNo() ); + if ( pDPObj ) + { + ScDBDocFunc aFunc( *pDocSh ); + aFunc.DataPilotUpdate( pDPObj, NULL, sal_True, sal_False ); + CursorPosChanged(); // shells may be switched + } + else + ErrorMessage(STR_PIVOT_NOTFOUND); +} +sal_uLong RefreshDPObject( ScDPObject *pDPObj, ScDocument *pDoc, ScDocShell *pDocSh, sal_Bool bRecord, sal_Bool bApi ) +{ + if( !pDPObj ) + return STR_PIVOT_NOTFOUND; + + if ( pDocSh && !pDoc ) + pDoc = pDocSh->GetDocument(); + + if( !pDoc ) + return static_cast<sal_uLong>(-1); + + if( !pDocSh && ( pDocSh = PTR_CAST( ScDocShell, pDoc->GetDocumentShell() ) ) == NULL ) + return static_cast<sal_uLong>(-1); + + if( sal_uLong nErrId = pDPObj->RefreshCache() ) + return nErrId; + else if ( nErrId == 0 ) + { + //Refresh all dpobjects + ScDPCollection* pDPCollection = pDoc->GetDPCollection(); + sal_uInt16 nCount = pDPCollection->GetCount(); + for (sal_uInt16 i=0; i<nCount; i++) + { + if ( (*pDPCollection)[i]->GetCacheId() == pDPObj->GetCacheId() ) + { + ScDBDocFunc aFunc( * pDocSh ); + if ( !aFunc.DataPilotUpdate( (*pDPCollection)[i], (*pDPCollection)[i], bRecord, bApi ) ) + break; + } + } + + return nErrId; + } + + return 0U; +} + +sal_uLong ScDBFunc::RecalcPivotTable() +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = GetViewData()->GetDocument(); + + // old pivot not used any more + + ScDPObject* pDPObj = pDoc->GetDPAtCursor( GetViewData()->GetCurX(), + GetViewData()->GetCurY(), + GetViewData()->GetTabNo() ); + if ( pDPObj ) + { + // Wang Xu Ming -- 2009-6-17 + // DataPilot Migration + //ScDBDocFunc aFunc( *pDocSh ); + //aFunc.DataPilotUpdate( pDPObj, pDPObj, sal_True, sal_False ); + //CursorPosChanged(); // shells may be switched + sal_uLong nErrId = RefreshDPObject( pDPObj, pDoc, pDocSh, sal_True, sal_False );//pDPObj->RefreshCache(); + if ( nErrId == 0 ) + { + // There is no undo for the refresh of the cache table, but the undo history for cell changes + // remains valid and should be preserved, so the history isn't cleared here. + //GetViewData()->GetDocShell()->GetUndoManager()->Clear(); + } + else if (nErrId <= USHRT_MAX) + ErrorMessage(static_cast<sal_uInt16>(nErrId)); + return nErrId; + // End Comments + } + else + ErrorMessage(STR_PIVOT_NOTFOUND); + return STR_PIVOT_NOTFOUND; +} + +void ScDBFunc::GetSelectedMemberList( ScStrCollection& rEntries, long& rDimension ) +{ + ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(), + GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); + if ( !pDPObj ) + return; + + long nStartDimension = -1; + long nStartHierarchy = -1; + long nStartLevel = -1; + + ScRangeListRef xRanges; + GetViewData()->GetMultiArea( xRanges ); // incl. cursor if nothing is selected + sal_uLong nRangeCount = xRanges->Count(); + sal_Bool bContinue = sal_True; + + for (sal_uLong nRangePos=0; nRangePos<nRangeCount && bContinue; nRangePos++) + { + ScRange aRange = *xRanges->GetObject(nRangePos); + SCCOL nStartCol = aRange.aStart.Col(); + SCROW nStartRow = aRange.aStart.Row(); + SCCOL nEndCol = aRange.aEnd.Col(); + SCROW nEndRow = aRange.aEnd.Row(); + SCTAB nTab = aRange.aStart.Tab(); + + for (SCROW nRow=nStartRow; nRow<=nEndRow && bContinue; nRow++) + for (SCCOL nCol=nStartCol; nCol<=nEndCol && bContinue; nCol++) + { + sheet::DataPilotTableHeaderData aData; + pDPObj->GetHeaderPositionData(ScAddress(nCol, nRow, nTab), aData); + if ( aData.Dimension < 0 ) + bContinue = sal_False; // not part of any dimension + else + { + if ( nStartDimension < 0 ) // first member? + { + nStartDimension = aData.Dimension; + nStartHierarchy = aData.Hierarchy; + nStartLevel = aData.Level; + } + if ( aData.Dimension != nStartDimension || + aData.Hierarchy != nStartHierarchy || + aData.Level != nStartLevel ) + { + bContinue = sal_False; // cannot mix dimensions + } + } + if ( bContinue ) + { + // accept any part of a member description, also subtotals, + // but don't stop if empty parts are contained + if ( aData.Flags & sheet::MemberResultFlags::HASMEMBER ) + { + StrData* pNew = new StrData( aData.MemberName ); + if ( !rEntries.Insert( pNew ) ) + delete pNew; + } + } + } + } + + rDimension = nStartDimension; // dimension from which the found members came + if (!bContinue) + rEntries.FreeAll(); // remove all if not valid +} + +sal_Bool ScDBFunc::HasSelectionForDateGroup( ScDPNumGroupInfo& rOldInfo, sal_Int32& rParts ) +{ + // determine if the date group dialog has to be shown for the current selection + + sal_Bool bFound = sal_False; + + SCCOL nCurX = GetViewData()->GetCurX(); + SCROW nCurY = GetViewData()->GetCurY(); + SCTAB nTab = GetViewData()->GetTabNo(); + ScDocument* pDoc = GetViewData()->GetDocument(); + + ScDPObject* pDPObj = pDoc->GetDPAtCursor( nCurX, nCurY, nTab ); + if ( pDPObj ) + { + ScStrCollection aEntries; + long nSelectDimension = -1; + GetSelectedMemberList( aEntries, nSelectDimension ); + + if ( aEntries.GetCount() > 0 ) + { + sal_Bool bIsDataLayout; + String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout ); + String aBaseDimName( aDimName ); + + sal_Bool bInGroupDim = sal_False; + sal_Bool bFoundParts = sal_False; + + ScDPDimensionSaveData* pDimData = + const_cast<ScDPDimensionSaveData*>( pDPObj->GetSaveData()->GetExistingDimensionData() ); + if ( pDimData ) + { + const ScDPSaveNumGroupDimension* pNumGroupDim = pDimData->GetNumGroupDim( aDimName ); + const ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDim( aDimName ); + if ( pNumGroupDim ) + { + // existing num group dimension + + if ( pNumGroupDim->GetDatePart() != 0 ) + { + // dimension has date info -> edit settings of this dimension + // (parts are collected below) + + rOldInfo = pNumGroupDim->GetDateInfo(); + bFound = sal_True; + } + else if ( pNumGroupDim->GetInfo().DateValues ) + { + // Numerical grouping with DateValues flag is used for grouping + // of days with a "Number of days" value. + + rOldInfo = pNumGroupDim->GetInfo(); + rParts = com::sun::star::sheet::DataPilotFieldGroupBy::DAYS; // not found in CollectDateParts + bFoundParts = sal_True; + bFound = sal_True; + } + bInGroupDim = sal_True; + } + else if ( pGroupDim ) + { + // existing additional group dimension + + if ( pGroupDim->GetDatePart() != 0 ) + { + // dimension has date info -> edit settings of this dimension + // (parts are collected below) + + rOldInfo = pGroupDim->GetDateInfo(); + aBaseDimName = pGroupDim->GetSourceDimName(); + bFound = sal_True; + } + bInGroupDim = sal_True; + } + } + if ( bFound && !bFoundParts ) + { + // collect date parts from all group dimensions + rParts = pDimData->CollectDateParts( aBaseDimName ); + } + if ( !bFound && !bInGroupDim ) + { + // create new date group dimensions if the selection is a single cell + // in a normal dimension with date content + + ScRange aSelRange; + if ( (GetViewData()->GetSimpleArea( aSelRange ) == SC_MARK_SIMPLE) && + aSelRange.aStart == aSelRange.aEnd ) + { + SCCOL nSelCol = aSelRange.aStart.Col(); + SCROW nSelRow = aSelRange.aStart.Row(); + SCTAB nSelTab = aSelRange.aStart.Tab(); + if ( pDoc->HasValueData( nSelCol, nSelRow, nSelTab ) ) + { + sal_uLong nIndex = static_cast<const SfxUInt32Item*>(pDoc->GetAttr( + nSelCol, nSelRow, nSelTab, ATTR_VALUE_FORMAT))->GetValue(); + short nType = pDoc->GetFormatTable()->GetType(nIndex); + if ( nType == NUMBERFORMAT_DATE || nType == NUMBERFORMAT_TIME || nType == NUMBERFORMAT_DATETIME ) + { + bFound = sal_True; + // use currently selected value for automatic limits + if( rOldInfo.AutoStart ) + rOldInfo.Start = pDoc->GetValue( aSelRange.aStart ); + if( rOldInfo.AutoEnd ) + rOldInfo.End = pDoc->GetValue( aSelRange.aStart ); + } + } + } + } + } + } + + return bFound; +} + +sal_Bool ScDBFunc::HasSelectionForNumGroup( ScDPNumGroupInfo& rOldInfo ) +{ + // determine if the numeric group dialog has to be shown for the current selection + + sal_Bool bFound = sal_False; + + SCCOL nCurX = GetViewData()->GetCurX(); + SCROW nCurY = GetViewData()->GetCurY(); + SCTAB nTab = GetViewData()->GetTabNo(); + ScDocument* pDoc = GetViewData()->GetDocument(); + + ScDPObject* pDPObj = pDoc->GetDPAtCursor( nCurX, nCurY, nTab ); + if ( pDPObj ) + { + ScStrCollection aEntries; + long nSelectDimension = -1; + GetSelectedMemberList( aEntries, nSelectDimension ); + + if ( aEntries.GetCount() > 0 ) + { + sal_Bool bIsDataLayout; + String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout ); + + sal_Bool bInGroupDim = sal_False; + + ScDPDimensionSaveData* pDimData = + const_cast<ScDPDimensionSaveData*>( pDPObj->GetSaveData()->GetExistingDimensionData() ); + if ( pDimData ) + { + const ScDPSaveNumGroupDimension* pNumGroupDim = pDimData->GetNumGroupDim( aDimName ); + if ( pNumGroupDim ) + { + // existing num group dimension + // -> edit settings of this dimension + + rOldInfo = pNumGroupDim->GetInfo(); + bFound = sal_True; + } + else if ( pDimData->GetNamedGroupDim( aDimName ) ) + bInGroupDim = sal_True; // in a group dimension + } + if ( !bFound && !bInGroupDim ) + { + // create a new num group dimension if the selection is a single cell + // in a normal dimension with numeric content + + ScRange aSelRange; + if ( (GetViewData()->GetSimpleArea( aSelRange ) == SC_MARK_SIMPLE) && + aSelRange.aStart == aSelRange.aEnd ) + { + if ( pDoc->HasValueData( aSelRange.aStart.Col(), aSelRange.aStart.Row(), + aSelRange.aStart.Tab() ) ) + { + bFound = sal_True; + // use currently selected value for automatic limits + if( rOldInfo.AutoStart ) + rOldInfo.Start = pDoc->GetValue( aSelRange.aStart ); + if( rOldInfo.AutoEnd ) + rOldInfo.End = pDoc->GetValue( aSelRange.aStart ); + } + } + } + } + } + + return bFound; +} + +void ScDBFunc::DateGroupDataPilot( const ScDPNumGroupInfo& rInfo, sal_Int32 nParts ) +{ + ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(), + GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); + if ( pDPObj ) + { + ScStrCollection aEntries; + long nSelectDimension = -1; + GetSelectedMemberList( aEntries, nSelectDimension ); + + if ( aEntries.GetCount() > 0 ) + { + sal_Bool bIsDataLayout; + String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout ); + + ScDPSaveData aData( *pDPObj->GetSaveData() ); + ScDPDimensionSaveData* pDimData = aData.GetDimensionData(); // created if not there + + // find original base + String aBaseDimName = aDimName; + if( const ScDPSaveGroupDimension* pBaseGroupDim = pDimData->GetNamedGroupDim( aDimName ) ) + aBaseDimName = pBaseGroupDim->GetSourceDimName(); + + // remove all existing parts (the grouping is built completely new) + + /* Remove numeric group dimension (exists once at most). No need + to delete anything in save data (grouping was done inplace in + an existing base dimension). */ + pDimData->RemoveNumGroupDimension( aBaseDimName ); + + /* Remove named group dimension(s). Collect deleted dimension + names which may be reused while recreating the groups. + Dimensions have to be removed from dimension save data and from + save data too. */ + std::vector< String > aDeletedNames; + const ScDPSaveGroupDimension* pExistingGroup = pDimData->GetGroupDimForBase( aBaseDimName ); + while ( pExistingGroup ) + { + String aGroupDimName = pExistingGroup->GetGroupDimName(); + pDimData->RemoveGroupDimension( aGroupDimName ); // pExistingGroup is deleted + + // also remove SaveData settings for the dimension that no longer exists + aData.RemoveDimensionByName( aGroupDimName ); + + /* The name can be used for the new group dimensions, although + it is still in use with the DataPilotSource. */ + aDeletedNames.push_back( aGroupDimName ); + + // see if there are more group dimensions + pExistingGroup = pDimData->GetGroupDimForBase( aBaseDimName ); + + if ( pExistingGroup && pExistingGroup->GetGroupDimName() == aGroupDimName ) + { + // still get the same group dimension? + DBG_ERROR("couldn't remove group dimension"); + pExistingGroup = NULL; // avoid endless loop + } + } + + if ( nParts ) + { + // create date group dimensions + + ScDPNumGroupInfo aEmpty; + bool bFirst = true; + sal_Int32 nMask = 1; + for (sal_uInt16 nBit=0; nBit<32; nBit++) + { + if ( nParts & nMask ) + { + if ( bFirst ) + { + // innermost part: create NumGroupDimension (replacing original values) + // Dimension name is left unchanged + + if ( (nParts == sheet::DataPilotFieldGroupBy::DAYS) && (rInfo.Step >= 1.0) ) + { + // only days, and a step value specified: use numerical grouping + // with DateValues flag, not date grouping + + ScDPNumGroupInfo aNumInfo( rInfo ); + aNumInfo.DateValues = sal_True; + + ScDPSaveNumGroupDimension aNumGroupDim( aBaseDimName, aNumInfo ); + pDimData->AddNumGroupDimension( aNumGroupDim ); + } + else + { + ScDPSaveNumGroupDimension aNumGroupDim( aBaseDimName, rInfo, nMask ); + pDimData->AddNumGroupDimension( aNumGroupDim ); + } + + bFirst = false; + } + else + { + // additional parts: create GroupDimension (shown as additional dimensions) + String aGroupDimName = pDimData->CreateDateGroupDimName( nMask, *pDPObj, true, &aDeletedNames ); + ScDPSaveGroupDimension aGroupDim( aBaseDimName, aGroupDimName ); + aGroupDim.SetDateInfo( rInfo, nMask ); + pDimData->AddGroupDimension( aGroupDim ); + + // set orientation + ScDPSaveDimension* pSaveDimension = aData.GetDimensionByName( aGroupDimName ); + if ( pSaveDimension->GetOrientation() == sheet::DataPilotFieldOrientation_HIDDEN ) + { + ScDPSaveDimension* pOldDimension = aData.GetDimensionByName( aBaseDimName ); + pSaveDimension->SetOrientation( pOldDimension->GetOrientation() ); + long nPosition = 0; //! before (immediate) base + aData.SetPosition( pSaveDimension, nPosition ); + } + } + } + nMask *= 2; + } + } + + // apply changes + ScDBDocFunc aFunc( *GetViewData()->GetDocShell() ); + ScDPObject* pNewObj = new ScDPObject( *pDPObj ); + pNewObj->SetSaveData( aData ); + aFunc.DataPilotUpdate( pDPObj, pNewObj, sal_True, sal_False ); + delete pNewObj; + + // unmark cell selection + Unmark(); + } + } +} + +void ScDBFunc::NumGroupDataPilot( const ScDPNumGroupInfo& rInfo ) +{ + ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(), + GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); + if ( pDPObj ) + { + ScStrCollection aEntries; + long nSelectDimension = -1; + GetSelectedMemberList( aEntries, nSelectDimension ); + + if ( aEntries.GetCount() > 0 ) + { + sal_Bool bIsDataLayout; + String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout ); + + ScDPSaveData aData( *pDPObj->GetSaveData() ); + ScDPDimensionSaveData* pDimData = aData.GetDimensionData(); // created if not there + + ScDPSaveNumGroupDimension* pExisting = pDimData->GetNumGroupDimAcc( aDimName ); + if ( pExisting ) + { + // modify existing group dimension + pExisting->SetGroupInfo( rInfo ); + } + else + { + // create new group dimension + ScDPSaveNumGroupDimension aNumGroupDim( aDimName, rInfo ); + pDimData->AddNumGroupDimension( aNumGroupDim ); + } + + // apply changes + ScDBDocFunc aFunc( *GetViewData()->GetDocShell() ); + ScDPObject* pNewObj = new ScDPObject( *pDPObj ); + pNewObj->SetSaveData( aData ); + aFunc.DataPilotUpdate( pDPObj, pNewObj, sal_True, sal_False ); + delete pNewObj; + + // unmark cell selection + Unmark(); + } + } +} + +void ScDBFunc::GroupDataPilot() +{ + ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(), + GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); + if ( pDPObj ) + { + ScStrCollection aEntries; + long nSelectDimension = -1; + GetSelectedMemberList( aEntries, nSelectDimension ); + + if ( aEntries.GetCount() > 0 ) + { + sal_Bool bIsDataLayout; + String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout ); + + ScDPSaveData aData( *pDPObj->GetSaveData() ); + ScDPDimensionSaveData* pDimData = aData.GetDimensionData(); // created if not there + + // find original base + String aBaseDimName( aDimName ); + const ScDPSaveGroupDimension* pBaseGroupDim = pDimData->GetNamedGroupDim( aDimName ); + if ( pBaseGroupDim ) + { + // any entry's SourceDimName is the original base + aBaseDimName = pBaseGroupDim->GetSourceDimName(); + } + + // find existing group dimension + // (using the selected dim, can be intermediate group dim) + ScDPSaveGroupDimension* pGroupDimension = pDimData->GetGroupDimAccForBase( aDimName ); + + // remove the selected items from their groups + // (empty groups are removed, too) + sal_uInt16 nEntryCount = aEntries.GetCount(); + sal_uInt16 nEntry; + if ( pGroupDimension ) + { + for (nEntry=0; nEntry<nEntryCount; nEntry++) + { + String aEntryName = aEntries[nEntry]->GetString(); + if ( pBaseGroupDim ) + { + // for each selected (intermediate) group, remove all its items + // (same logic as for adding, below) + const ScDPSaveGroupItem* pBaseGroup = pBaseGroupDim->GetNamedGroup( aEntryName ); + if ( pBaseGroup ) + pBaseGroup->RemoveElementsFromGroups( *pGroupDimension ); // remove all elements + else + pGroupDimension->RemoveFromGroups( aEntryName ); + } + else + pGroupDimension->RemoveFromGroups( aEntryName ); + } + } + + ScDPSaveGroupDimension* pNewGroupDim = NULL; + if ( !pGroupDimension ) + { + // create a new group dimension + String aGroupDimName = pDimData->CreateGroupDimName( aBaseDimName, *pDPObj, false, NULL ); + pNewGroupDim = new ScDPSaveGroupDimension( aBaseDimName, aGroupDimName ); + + pGroupDimension = pNewGroupDim; // make changes to the new dim if none existed + + if ( pBaseGroupDim ) + { + // If it's a higher-order group dimension, pre-allocate groups for all + // non-selected original groups, so the individual base members aren't + // used for automatic groups (this would make the original groups hard + // to find). + //! Also do this when removing groups? + //! Handle this case dynamically with automatic groups? + + long nGroupCount = pBaseGroupDim->GetGroupCount(); + for ( long nGroup = 0; nGroup < nGroupCount; nGroup++ ) + { + const ScDPSaveGroupItem* pBaseGroup = pBaseGroupDim->GetGroupByIndex( nGroup ); + + StrData aStrData( pBaseGroup->GetGroupName() ); + sal_uInt16 nCollIndex; + if ( !aEntries.Search( &aStrData, nCollIndex ) ) //! ignore case? + { + // add an additional group for each item that is not in the selection + ScDPSaveGroupItem aGroup( pBaseGroup->GetGroupName() ); + aGroup.AddElementsFromGroup( *pBaseGroup ); + pGroupDimension->AddGroupItem( aGroup ); + } + } + } + } + String aGroupDimName = pGroupDimension->GetGroupDimName(); + + //! localized prefix string + String aGroupName = pGroupDimension->CreateGroupName( String::CreateFromAscii("Group") ); + ScDPSaveGroupItem aGroup( aGroupName ); + for (nEntry=0; nEntry<nEntryCount; nEntry++) + { + String aEntryName = aEntries[nEntry]->GetString(); + if ( pBaseGroupDim ) + { + // for each selected (intermediate) group, add all its items + const ScDPSaveGroupItem* pBaseGroup = pBaseGroupDim->GetNamedGroup( aEntryName ); + if ( pBaseGroup ) + aGroup.AddElementsFromGroup( *pBaseGroup ); + else + aGroup.AddElement( aEntryName ); // no group found -> automatic group, add the item itself + } + else + aGroup.AddElement( aEntryName ); // no group dimension, add all items directly + } + + pGroupDimension->AddGroupItem( aGroup ); + + if ( pNewGroupDim ) + { + pDimData->AddGroupDimension( *pNewGroupDim ); + delete pNewGroupDim; // AddGroupDimension copies the object + // don't access pGroupDimension after here + } + pGroupDimension = pNewGroupDim = NULL; + + // set orientation + ScDPSaveDimension* pSaveDimension = aData.GetDimensionByName( aGroupDimName ); + if ( pSaveDimension->GetOrientation() == sheet::DataPilotFieldOrientation_HIDDEN ) + { + ScDPSaveDimension* pOldDimension = aData.GetDimensionByName( aDimName ); + pSaveDimension->SetOrientation( pOldDimension->GetOrientation() ); + long nPosition = 0; //! before (immediate) base + aData.SetPosition( pSaveDimension, nPosition ); + } + + // apply changes + ScDBDocFunc aFunc( *GetViewData()->GetDocShell() ); + ScDPObject* pNewObj = new ScDPObject( *pDPObj ); + pNewObj->SetSaveData( aData ); + aFunc.DataPilotUpdate( pDPObj, pNewObj, sal_True, sal_False ); + delete pNewObj; + + // unmark cell selection + Unmark(); + } + } +} + +void ScDBFunc::UngroupDataPilot() +{ + ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(), + GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); + if ( pDPObj ) + { + ScStrCollection aEntries; + long nSelectDimension = -1; + GetSelectedMemberList( aEntries, nSelectDimension ); + + if ( aEntries.GetCount() > 0 ) + { + sal_Bool bIsDataLayout; + String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout ); + + ScDPSaveData aData( *pDPObj->GetSaveData() ); + ScDPDimensionSaveData* pDimData = aData.GetDimensionData(); // created if not there + //! test first if DimensionData exists? + + sal_Bool bApply = sal_False; + + ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aDimName ); + const ScDPSaveNumGroupDimension* pNumGroupDim = pDimData->GetNumGroupDim( aDimName ); + if ( ( pGroupDim && pGroupDim->GetDatePart() != 0 ) || + ( pNumGroupDim && pNumGroupDim->GetDatePart() != 0 ) ) + { + // Date grouping: need to remove all affected group dimensions. + // This is done using DateGroupDataPilot with nParts=0. + + DateGroupDataPilot( ScDPNumGroupInfo(), 0 ); + // bApply remains FALSE + // dimension pointers become invalid + } + else if ( pGroupDim ) + { + sal_uInt16 nEntryCount = aEntries.GetCount(); + for (sal_uInt16 nEntry=0; nEntry<nEntryCount; nEntry++) + { + String aEntryName = aEntries[nEntry]->GetString(); + pGroupDim->RemoveGroup( aEntryName ); + } + // remove group dimension if empty + bool bEmptyDim = pGroupDim->IsEmpty(); + if ( !bEmptyDim ) + { + // If all remaining groups in the dimension aren't shown, remove + // the dimension too, as if it was completely empty. + ScStrCollection aVisibleEntries; + pDPObj->GetMemberResultNames( aVisibleEntries, nSelectDimension ); + bEmptyDim = pGroupDim->HasOnlyHidden( aVisibleEntries ); + } + if ( bEmptyDim ) + { + pDimData->RemoveGroupDimension( aDimName ); // pGroupDim is deleted + + // also remove SaveData settings for the dimension that no longer exists + aData.RemoveDimensionByName( aDimName ); + } + bApply = sal_True; + } + else if ( pNumGroupDim ) + { + // remove the numerical grouping + pDimData->RemoveNumGroupDimension( aDimName ); + // SaveData settings can remain unchanged - the same dimension still exists + bApply = sal_True; + } + + if ( bApply ) + { + // apply changes + ScDBDocFunc aFunc( *GetViewData()->GetDocShell() ); + ScDPObject* pNewObj = new ScDPObject( *pDPObj ); + pNewObj->SetSaveData( aData ); + aFunc.DataPilotUpdate( pDPObj, pNewObj, sal_True, sal_False ); + delete pNewObj; + + // unmark cell selection + Unmark(); + } + } + } +} + +static OUString lcl_replaceMemberNameInSubtotal(const OUString& rSubtotal, const OUString& rMemberName) +{ + sal_Int32 n = rSubtotal.getLength(); + const sal_Unicode* p = rSubtotal.getStr(); + OUStringBuffer aBuf, aWordBuf; + for (sal_Int32 i = 0; i < n; ++i) + { + sal_Unicode c = p[i]; + if (c == sal_Unicode(' ')) + { + OUString aWord = aWordBuf.makeStringAndClear(); + if (aWord.equals(rMemberName)) + aBuf.append(sal_Unicode('?')); + else + aBuf.append(aWord); + aBuf.append(c); + } + else if (c == sal_Unicode('\\')) + { + // Escape a backslash character. + aWordBuf.append(c); + aWordBuf.append(c); + } + else if (c == sal_Unicode('?')) + { + // A literal '?' must be escaped with a backslash ('\'); + aWordBuf.append(sal_Unicode('\\')); + aWordBuf.append(c); + } + else + aWordBuf.append(c); + } + + if (aWordBuf.getLength() > 0) + { + OUString aWord = aWordBuf.makeStringAndClear(); + if (aWord.equals(rMemberName)) + aBuf.append(sal_Unicode('?')); + else + aBuf.append(aWord); + } + + return aBuf.makeStringAndClear(); +} + +void ScDBFunc::DataPilotInput( const ScAddress& rPos, const String& rString ) +{ + using namespace ::com::sun::star::sheet; + + String aNewName( rString ); + + ScDocument* pDoc = GetViewData()->GetDocument(); + ScDPObject* pDPObj = pDoc->GetDPAtCursor( rPos.Col(), rPos.Row(), rPos.Tab() ); + if (!pDPObj) + return; + + String aOldText; + pDoc->GetString( rPos.Col(), rPos.Row(), rPos.Tab(), aOldText ); + + if ( aOldText == rString ) + { + // nothing to do: silently exit + return; + } + + sal_uInt16 nErrorId = 0; + + pDPObj->BuildAllDimensionMembers(); + ScDPSaveData aData( *pDPObj->GetSaveData() ); + sal_Bool bChange = sal_False; + + sal_uInt16 nOrient = DataPilotFieldOrientation_HIDDEN; + long nField = pDPObj->GetHeaderDim( rPos, nOrient ); + if ( nField >= 0 ) + { + // changing a field title + if ( aData.GetExistingDimensionData() ) + { + // only group dimensions can be renamed + + ScDPDimensionSaveData* pDimData = aData.GetDimensionData(); + ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aOldText ); + if ( pGroupDim ) + { + // valid name: not empty, no existing dimension (group or other) + if ( rString.Len() && !pDPObj->IsDimNameInUse(rString) ) + { + pGroupDim->Rename( aNewName ); + + // also rename in SaveData to preserve the field settings + ScDPSaveDimension* pSaveDim = aData.GetDimensionByName( aOldText ); + pSaveDim->SetName( aNewName ); + + bChange = sal_True; + } + else + nErrorId = STR_INVALIDNAME; + } + } + else if (nOrient == DataPilotFieldOrientation_COLUMN || nOrient == DataPilotFieldOrientation_ROW) + { + sal_Bool bDataLayout = false; + String aDimName = pDPObj->GetDimName(nField, bDataLayout); + ScDPSaveDimension* pDim = bDataLayout ? aData.GetDataLayoutDimension() : aData.GetDimensionByName(aDimName); + if (pDim) + { + if (rString.Len()) + { + if (rString.EqualsIgnoreCaseAscii(aDimName)) + { + pDim->RemoveLayoutName(); + bChange = true; + } + else if (!pDPObj->IsDimNameInUse(rString)) + { + pDim->SetLayoutName(rString); + bChange = true; + } + else + nErrorId = STR_INVALIDNAME; + } + else + nErrorId = STR_INVALIDNAME; + } + } + } + else if (pDPObj->IsDataDescriptionCell(rPos)) + { + // There is only one data dimension. + ScDPSaveDimension* pDim = aData.GetFirstDimension(sheet::DataPilotFieldOrientation_DATA); + if (pDim) + { + if (rString.Len()) + { + if (rString.EqualsIgnoreCaseAscii(pDim->GetName())) + { + pDim->RemoveLayoutName(); + bChange = true; + } + else if (!pDPObj->IsDimNameInUse(rString)) + { + pDim->SetLayoutName(rString); + bChange = true; + } + else + nErrorId = STR_INVALIDNAME; + } + else + nErrorId = STR_INVALIDNAME; + } + } + else + { + // This is not a field header. + sheet::DataPilotTableHeaderData aPosData; + pDPObj->GetHeaderPositionData(rPos, aPosData); + + if ( (aPosData.Flags & MemberResultFlags::HASMEMBER) && aOldText.Len() ) + { + if ( aData.GetExistingDimensionData() && !(aPosData.Flags & MemberResultFlags::SUBTOTAL)) + { + sal_Bool bIsDataLayout; + String aDimName = pDPObj->GetDimName( aPosData.Dimension, bIsDataLayout ); + + ScDPDimensionSaveData* pDimData = aData.GetDimensionData(); + ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aDimName ); + if ( pGroupDim ) + { + // valid name: not empty, no existing group in this dimension + //! ignore case? + if ( aNewName.Len() && !pGroupDim->GetNamedGroup( aNewName ) ) + { + ScDPSaveGroupItem* pGroup = pGroupDim->GetNamedGroupAcc( aOldText ); + if ( pGroup ) + pGroup->Rename( aNewName ); // rename the existing group + else + { + // create a new group to replace the automatic group + ScDPSaveGroupItem aGroup( aNewName ); + aGroup.AddElement( aOldText ); + pGroupDim->AddGroupItem( aGroup ); + } + + // in both cases also adjust savedata, to preserve member settings (show details) + ScDPSaveDimension* pSaveDim = aData.GetDimensionByName( aDimName ); + ScDPSaveMember* pSaveMember = pSaveDim->GetExistingMemberByName( aOldText ); + if ( pSaveMember ) + pSaveMember->SetName( aNewName ); + + bChange = sal_True; + } + else + nErrorId = STR_INVALIDNAME; + } + } + else if ((aPosData.Flags & MemberResultFlags::GRANDTOTAL)) + { + aData.SetGrandTotalName(rString); + bChange = true; + } + else if (aPosData.Dimension >= 0 && aPosData.MemberName.getLength() > 0) + { + sal_Bool bDataLayout = false; + String aDimName = pDPObj->GetDimName(static_cast<long>(aPosData.Dimension), bDataLayout); + if (bDataLayout) + { + // data dimension + do + { + if ((aPosData.Flags & MemberResultFlags::SUBTOTAL)) + break; + + ScDPSaveDimension* pDim = aData.GetDimensionByName(aPosData.MemberName); + if (!pDim) + break; + + if (!rString.Len()) + { + nErrorId = STR_INVALIDNAME; + break; + } + + if (aPosData.MemberName.equalsIgnoreAsciiCase(rString)) + { + pDim->RemoveLayoutName(); + bChange = true; + } + else if (!pDPObj->IsDimNameInUse(rString)) + { + pDim->SetLayoutName(rString); + bChange = true; + } + else + nErrorId = STR_INVALIDNAME; + } + while (false); + } + else + { + // field member + do + { + ScDPSaveDimension* pDim = aData.GetDimensionByName(aDimName); + if (!pDim) + break; + + ScDPSaveMember* pMem = pDim->GetExistingMemberByName(aPosData.MemberName); + if (!pMem) + break; + + if ((aPosData.Flags & MemberResultFlags::SUBTOTAL)) + { + // Change subtotal only when the table has one data dimension. + if (aData.GetDataDimensionCount() > 1) + break; + + // display name for subtotal is allowed only if the subtotal type is 'Automatic'. + if (pDim->GetSubTotalsCount() != 1) + break; + + if (pDim->GetSubTotalFunc(0) != sheet::GeneralFunction_AUTO) + break; + + const OUString* pLayoutName = pMem->GetLayoutName(); + String aMemberName; + if (pLayoutName) + aMemberName = *pLayoutName; + else + aMemberName = aPosData.MemberName; + + String aNew = lcl_replaceMemberNameInSubtotal(rString, aMemberName); + pDim->SetSubtotalName(aNew); + bChange = true; + } + else + { + // Check to make sure the member name isn't + // already used. + if (rString.Len()) + { + if (rString.EqualsIgnoreCaseAscii(pMem->GetName())) + { + pMem->RemoveLayoutName(); + bChange = true; + } + else if (!pDim->IsMemberNameInUse(rString)) + { + pMem->SetLayoutName(rString); + bChange = true; + } + else + nErrorId = STR_INVALIDNAME; + } + else + nErrorId = STR_INVALIDNAME; + } + } + while (false); + } + } + } + } + + if ( bChange ) + { + // apply changes + ScDBDocFunc aFunc( *GetViewData()->GetDocShell() ); + ScDPObject* pNewObj = new ScDPObject( *pDPObj ); + pNewObj->SetSaveData( aData ); + aFunc.DataPilotUpdate( pDPObj, pNewObj, sal_True, sal_False ); + delete pNewObj; + } + else + { + if ( !nErrorId ) + nErrorId = STR_ERR_DATAPILOT_INPUT; + ErrorMessage( nErrorId ); + } +} + +void lcl_MoveToEnd( ScDPSaveDimension& rDim, const String& rItemName ) +{ + ScDPSaveMember* pNewMember = NULL; + const ScDPSaveMember* pOldMember = rDim.GetExistingMemberByName( rItemName ); + if ( pOldMember ) + pNewMember = new ScDPSaveMember( *pOldMember ); + else + pNewMember = new ScDPSaveMember( rItemName ); + rDim.AddMember( pNewMember ); + // AddMember takes ownership of the new pointer, + // puts it to the end of the list even if it was in the list before. +} + +struct ScOUStringCollate +{ + CollatorWrapper* mpCollator; + + ScOUStringCollate(CollatorWrapper* pColl) : mpCollator(pColl) {} + + bool operator()(const rtl::OUString& rStr1, const rtl::OUString& rStr2) const + { + return ( mpCollator->compareString(rStr1, rStr2) < 0 ); + } +}; + +bool ScDBFunc::DataPilotSort( const ScAddress& rPos, bool bAscending, sal_uInt16* pUserListId ) +{ + ScDocument* pDoc = GetViewData()->GetDocument(); + ScDPObject* pDPObj = pDoc->GetDPAtCursor(rPos.Col(), rPos.Row(), rPos.Tab()); + if (!pDPObj) + return false; + + // We need to run this to get all members later. + if ( pUserListId ) + pDPObj->BuildAllDimensionMembers(); + + sal_uInt16 nOrientation; + long nDimIndex = pDPObj->GetHeaderDim(rPos, nOrientation); + if (nDimIndex < 0) + // Invalid dimension index. Bail out. + return false; + + sal_Bool bDataLayout; + ScDPSaveData* pSaveData = pDPObj->GetSaveData(); + if (!pSaveData) + return false; + + ScDPSaveData aNewSaveData(*pSaveData); + String aDimName = pDPObj->GetDimName(nDimIndex, bDataLayout); + ScDPSaveDimension* pSaveDim = aNewSaveData.GetDimensionByName(aDimName); + if (!pSaveDim) + return false; + + // manual evaluation of sort order is only needed if a user list id is given + if ( pUserListId ) + { + typedef ScDPSaveDimension::MemberList MemList; + const MemList& rDimMembers = pSaveDim->GetMembers(); + list<OUString> aMembers; + hash_set<OUString, ::rtl::OUStringHash> aMemberSet; + size_t nMemberCount = 0; + for (MemList::const_iterator itr = rDimMembers.begin(), itrEnd = rDimMembers.end(); + itr != itrEnd; ++itr) + { + ScDPSaveMember* pMem = *itr; + aMembers.push_back(pMem->GetName()); + aMemberSet.insert(pMem->GetName()); + ++nMemberCount; + } + + // Sort the member list in ascending order. + ScOUStringCollate aCollate( ScGlobal::GetCollator() ); + aMembers.sort(aCollate); + + // Collect and rank those custom sort strings that also exist in the member name list. + + typedef hash_map<OUString, sal_uInt16, OUStringHash> UserSortMap; + UserSortMap aSubStrs; + sal_uInt16 nSubCount = 0; + if (pUserListId) + { + ScUserList* pUserList = ScGlobal::GetUserList(); + if (!pUserList) + return false; + + { + sal_uInt16 n = pUserList->GetCount(); + if (!n || *pUserListId >= n) + return false; + } + + ScUserListData* pData = static_cast<ScUserListData*>((*pUserList)[*pUserListId]); + if (pData) + { + sal_uInt16 n = pData->GetSubCount(); + for (sal_uInt16 i = 0; i < n; ++i) + { + OUString aSub = pData->GetSubStr(i); + if (!aMemberSet.count(aSub)) + // This string doesn't exist in the member name set. Don't add this. + continue; + + aSubStrs.insert(UserSortMap::value_type(aSub, nSubCount++)); + } + } + } + + // Rank all members. + + vector<OUString> aRankedNames(nMemberCount); + sal_uInt16 nCurStrId = 0; + for (list<OUString>::const_iterator itr = aMembers.begin(), itrEnd = aMembers.end(); + itr != itrEnd; ++itr) + { + OUString aName = *itr; + sal_uInt16 nRank = 0; + UserSortMap::const_iterator itrSub = aSubStrs.find(aName); + if (itrSub == aSubStrs.end()) + nRank = nSubCount + nCurStrId++; + else + nRank = itrSub->second; + + if (!bAscending) + nRank = static_cast< sal_uInt16 >( nMemberCount - nRank - 1 ); + + aRankedNames[nRank] = aName; + } + + // Re-order ScDPSaveMember instances with the new ranks. + + for (vector<OUString>::const_iterator itr = aRankedNames.begin(), itrEnd = aRankedNames.end(); + itr != itrEnd; ++itr) + { + const ScDPSaveMember* pOldMem = pSaveDim->GetExistingMemberByName(*itr); + if (!pOldMem) + // All members are supposed to be present. + continue; + + ScDPSaveMember* pNewMem = new ScDPSaveMember(*pOldMem); + pSaveDim->AddMember(pNewMem); + } + + // Set the sorting mode to manual for now. We may introduce a new sorting + // mode later on. + + sheet::DataPilotFieldSortInfo aSortInfo; + aSortInfo.Mode = sheet::DataPilotFieldSortMode::MANUAL; + pSaveDim->SetSortInfo(&aSortInfo); + } + else + { + // without user list id, just apply sorting mode + + sheet::DataPilotFieldSortInfo aSortInfo; + aSortInfo.Mode = sheet::DataPilotFieldSortMode::NAME; + aSortInfo.IsAscending = bAscending; + pSaveDim->SetSortInfo(&aSortInfo); + } + + // Update the datapilot with the newly sorted field members. + + auto_ptr<ScDPObject> pNewObj(new ScDPObject(*pDPObj)); + pNewObj->SetSaveData(aNewSaveData); + ScDBDocFunc aFunc(*GetViewData()->GetDocShell()); + + return aFunc.DataPilotUpdate(pDPObj, pNewObj.get(), true, false); +} + +sal_Bool ScDBFunc::DataPilotMove( const ScRange& rSource, const ScAddress& rDest ) +{ + sal_Bool bRet = sal_False; + ScDocument* pDoc = GetViewData()->GetDocument(); + ScDPObject* pDPObj = pDoc->GetDPAtCursor( rSource.aStart.Col(), rSource.aStart.Row(), rSource.aStart.Tab() ); + if ( pDPObj && pDPObj == pDoc->GetDPAtCursor( rDest.Col(), rDest.Row(), rDest.Tab() ) ) + { + sheet::DataPilotTableHeaderData aDestData; + pDPObj->GetHeaderPositionData( rDest, aDestData ); + bool bValid = ( aDestData.Dimension >= 0 ); // dropping onto a field + + // look through the source range + std::hash_set< rtl::OUString, rtl::OUStringHash, std::equal_to<rtl::OUString> > aMembersSet; // for lookup + std::vector< rtl::OUString > aMembersVector; // members in original order, for inserting + aMembersVector.reserve( std::max( static_cast<SCSIZE>( rSource.aEnd.Col() - rSource.aStart.Col() + 1 ), + static_cast<SCSIZE>( rSource.aEnd.Row() - rSource.aStart.Row() + 1 ) ) ); + for (SCROW nRow = rSource.aStart.Row(); bValid && nRow <= rSource.aEnd.Row(); ++nRow ) + for (SCCOL nCol = rSource.aStart.Col(); bValid && nCol <= rSource.aEnd.Col(); ++nCol ) + { + sheet::DataPilotTableHeaderData aSourceData; + pDPObj->GetHeaderPositionData( ScAddress( nCol, nRow, rSource.aStart.Tab() ), aSourceData ); + if ( aSourceData.Dimension == aDestData.Dimension && aSourceData.MemberName.getLength() ) + { + if ( aMembersSet.find( aSourceData.MemberName ) == aMembersSet.end() ) + { + aMembersSet.insert( aSourceData.MemberName ); + aMembersVector.push_back( aSourceData.MemberName ); + } + // duplicates are ignored + } + else + bValid = false; // empty (subtotal) or different field + } + + if ( bValid ) + { + sal_Bool bIsDataLayout; + String aDimName = pDPObj->GetDimName( aDestData.Dimension, bIsDataLayout ); + if ( !bIsDataLayout ) + { + ScDPSaveData aData( *pDPObj->GetSaveData() ); + ScDPSaveDimension* pDim = aData.GetDimensionByName( aDimName ); + + // get all member names in source order + uno::Sequence<rtl::OUString> aMemberNames; + pDPObj->GetMemberNames( aDestData.Dimension, aMemberNames ); + + bool bInserted = false; + + sal_Int32 nMemberCount = aMemberNames.getLength(); + for (sal_Int32 nMemberPos=0; nMemberPos<nMemberCount; ++nMemberPos) + { + String aMemberStr( aMemberNames[nMemberPos] ); + + if ( !bInserted && aMemberNames[nMemberPos] == aDestData.MemberName ) + { + // insert dragged items before this item + for ( std::vector<rtl::OUString>::const_iterator aIter = aMembersVector.begin(); + aIter != aMembersVector.end(); ++aIter ) + lcl_MoveToEnd( *pDim, *aIter ); + bInserted = true; + } + + if ( aMembersSet.find( aMemberStr ) == aMembersSet.end() ) // skip dragged items + lcl_MoveToEnd( *pDim, aMemberStr ); + } + // insert dragged item at end if dest wasn't found (for example, empty) + if ( !bInserted ) + for ( std::vector<rtl::OUString>::const_iterator aIter = aMembersVector.begin(); + aIter != aMembersVector.end(); ++aIter ) + lcl_MoveToEnd( *pDim, *aIter ); + + // Items that were in SaveData, but not in the source, end up at the start of the list. + + // set flag for manual sorting + sheet::DataPilotFieldSortInfo aSortInfo; + aSortInfo.Mode = sheet::DataPilotFieldSortMode::MANUAL; + pDim->SetSortInfo( &aSortInfo ); + + // apply changes + ScDBDocFunc aFunc( *GetViewData()->GetDocShell() ); + ScDPObject* pNewObj = new ScDPObject( *pDPObj ); + pNewObj->SetSaveData( aData ); + aFunc.DataPilotUpdate( pDPObj, pNewObj, sal_True, sal_False ); //! bApi for drag&drop? + delete pNewObj; + + Unmark(); // entry was moved - no use in leaving the old cell selected + + bRet = sal_True; + } + } + } + + return bRet; +} + +sal_Bool ScDBFunc::HasSelectionForDrillDown( sal_uInt16& rOrientation ) +{ + sal_Bool bRet = sal_False; + + ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(), + GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); + if ( pDPObj ) + { + ScStrCollection aEntries; + long nSelectDimension = -1; + GetSelectedMemberList( aEntries, nSelectDimension ); + + if ( aEntries.GetCount() > 0 ) + { + sal_Bool bIsDataLayout; + String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout ); + if ( !bIsDataLayout ) + { + ScDPSaveData* pSaveData = pDPObj->GetSaveData(); + ScDPSaveDimension* pDim = pSaveData->GetExistingDimensionByName( aDimName ); + if ( pDim ) + { + sal_uInt16 nDimOrient = pDim->GetOrientation(); + ScDPSaveDimension* pInner = pSaveData->GetInnermostDimension( nDimOrient ); + if ( pDim == pInner ) + { + rOrientation = nDimOrient; + bRet = sal_True; + } + } + } + } + } + + return bRet; +} + +void ScDBFunc::SetDataPilotDetails( sal_Bool bShow, const String* pNewDimensionName ) +{ + ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(), + GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); + if ( pDPObj ) + { + ScStrCollection aEntries; + long nSelectDimension = -1; + GetSelectedMemberList( aEntries, nSelectDimension ); + + if ( aEntries.GetCount() > 0 ) + { + sal_Bool bIsDataLayout; + String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout ); + if ( !bIsDataLayout ) + { + ScDPSaveData aData( *pDPObj->GetSaveData() ); + ScDPSaveDimension* pDim = aData.GetDimensionByName( aDimName ); + + if ( bShow && pNewDimensionName ) + { + // add the new dimension with the same orientation, at the end + + ScDPSaveDimension* pNewDim = aData.GetDimensionByName( *pNewDimensionName ); + ScDPSaveDimension* pDuplicated = NULL; + if ( pNewDim->GetOrientation() == sheet::DataPilotFieldOrientation_DATA ) + { + // Need to duplicate the dimension, create column/row in addition to data: + // The duplicated dimension inherits the existing settings, pNewDim is modified below. + pDuplicated = aData.DuplicateDimension( *pNewDimensionName ); + } + + sal_uInt16 nOrientation = pDim->GetOrientation(); + pNewDim->SetOrientation( nOrientation ); + + long nPosition = LONG_MAX; + aData.SetPosition( pNewDim, nPosition ); + + ScDPSaveDimension* pDataLayout = aData.GetDataLayoutDimension(); + if ( pDataLayout->GetOrientation() == nOrientation && + aData.GetDataDimensionCount() <= 1 ) + { + // If there is only one data dimension, the data layout dimension + // must still be the last one in its orientation. + aData.SetPosition( pDataLayout, nPosition ); + } + + if ( pDuplicated ) + { + // The duplicated (data) dimension needs to be behind the original dimension + aData.SetPosition( pDuplicated, nPosition ); + } + + // Hide details for all visible members (selected are changed below). + //! Use all members from source level instead (including non-visible)? + + ScStrCollection aVisibleEntries; + pDPObj->GetMemberResultNames( aVisibleEntries, nSelectDimension ); + + sal_uInt16 nVisCount = aVisibleEntries.GetCount(); + for (sal_uInt16 nVisPos=0; nVisPos<nVisCount; nVisPos++) + { + String aVisName = aVisibleEntries[nVisPos]->GetString(); + ScDPSaveMember* pMember = pDim->GetMemberByName( aVisName ); + pMember->SetShowDetails( sal_False ); + } + } + + sal_uInt16 nEntryCount = aEntries.GetCount(); + for (sal_uInt16 nEntry=0; nEntry<nEntryCount; nEntry++) + { + String aEntryName = aEntries[nEntry]->GetString(); + ScDPSaveMember* pMember = pDim->GetMemberByName( aEntryName ); + pMember->SetShowDetails( bShow ); + } + + // apply changes + ScDBDocFunc aFunc( *GetViewData()->GetDocShell() ); + ScDPObject* pNewObj = new ScDPObject( *pDPObj ); + pNewObj->SetSaveData( aData ); + aFunc.DataPilotUpdate( pDPObj, pNewObj, sal_True, sal_False ); + delete pNewObj; + + // unmark cell selection + Unmark(); + } + } + } +} + +void ScDBFunc::ShowDataPilotSourceData( ScDPObject& rDPObj, const Sequence<sheet::DataPilotFieldFilter>& rFilters ) +{ + ScDocument* pDoc = GetViewData()->GetDocument(); + if (pDoc->GetDocumentShell()->IsReadOnly()) + { + ErrorMessage(STR_READONLYERR); + return; + } + + Reference<sheet::XDimensionsSupplier> xDimSupplier = rDPObj.GetSource(); + Reference<container::XNameAccess> xDims = xDimSupplier->getDimensions(); + Reference<sheet::XDrillDownDataSupplier> xDDSupplier(xDimSupplier, UNO_QUERY); + if (!xDDSupplier.is()) + return; + + Sequence< Sequence<Any> > aTabData = xDDSupplier->getDrillDownData(rFilters); + sal_Int32 nRowSize = aTabData.getLength(); + if (nRowSize <= 1) + // There is no data to show. Bail out. + return; + + sal_Int32 nColSize = aTabData[0].getLength(); + + SCTAB nNewTab = GetViewData()->GetTabNo(); + + auto_ptr<ScDocument> pInsDoc(new ScDocument(SCDOCMODE_CLIP)); + pInsDoc->ResetClip( pDoc, nNewTab ); + for (SCROW nRow = 0; nRow < nRowSize; ++nRow) + { + for (SCCOL nCol = 0; nCol < nColSize; ++nCol) + { + const Any& rAny = aTabData[nRow][nCol]; + rtl::OUString aStr; + double fVal; + if (rAny >>= aStr) + pInsDoc->PutCell( ScAddress(nCol, nRow, nNewTab), new ScStringCell(String(aStr)) ); + else if (rAny >>= fVal) + pInsDoc->SetValue(nCol, nRow, nNewTab, fVal); + } + } + + // set number format (important for dates) + for (SCCOL nCol = 0; nCol < nColSize; ++nCol) + { + rtl::OUString aStr; + if (!(aTabData[0][nCol] >>= aStr)) + continue; + + Reference<XPropertySet> xPropSet(xDims->getByName(aStr), UNO_QUERY); + if (!xPropSet.is()) + continue; + + Any any = xPropSet->getPropertyValue( rtl::OUString::createFromAscii(SC_UNO_NUMBERFO) ); + sal_Int32 nNumFmt = 0; + if (!(any >>= nNumFmt)) + continue; + + ScPatternAttr aPattern( pInsDoc->GetPool() ); + aPattern.GetItemSet().Put( SfxUInt32Item(ATTR_VALUE_FORMAT, static_cast<sal_uInt32>(nNumFmt)) ); + pInsDoc->ApplyPatternAreaTab(nCol, 1, nCol, nRowSize-1, nNewTab, aPattern); + } + + SCCOL nEndCol = 0; + SCROW nEndRow = 0; + pInsDoc->GetCellArea( nNewTab, nEndCol, nEndRow ); + pInsDoc->SetClipArea( ScRange( 0, 0, nNewTab, nEndCol, nEndRow, nNewTab ) ); + + ::svl::IUndoManager* pMgr = GetViewData()->GetDocShell()->GetUndoManager(); + String aUndo = ScGlobal::GetRscString( STR_UNDO_DOOUTLINE ); + pMgr->EnterListAction( aUndo, aUndo ); + + String aNewTabName; + pDoc->CreateValidTabName(aNewTabName); + if ( InsertTable(aNewTabName, nNewTab) ) + PasteFromClip( IDF_ALL, pInsDoc.get() ); + + pMgr->LeaveListAction(); +} + +// +// DB-Operationen (Sortieren, Filtern, Teilergebnisse) wiederholen +// + +void ScDBFunc::RepeatDB( sal_Bool bRecord ) +{ + SCCOL nCurX = GetViewData()->GetCurX(); + SCROW nCurY = GetViewData()->GetCurY(); + SCTAB nTab = GetViewData()->GetTabNo(); + ScDocument* pDoc = GetViewData()->GetDocument(); + ScDBData* pDBData = GetDBData(); + if (bRecord && !pDoc->IsUndoEnabled()) + bRecord = sal_False; + + ScQueryParam aQueryParam; + pDBData->GetQueryParam( aQueryParam ); + sal_Bool bQuery = aQueryParam.GetEntry(0).bDoQuery; + + ScSortParam aSortParam; + pDBData->GetSortParam( aSortParam ); + sal_Bool bSort = aSortParam.bDoSort[0]; + + ScSubTotalParam aSubTotalParam; + pDBData->GetSubTotalParam( aSubTotalParam ); + sal_Bool bSubTotal = aSubTotalParam.bGroupActive[0] && !aSubTotalParam.bRemoveOnly; + + if ( bQuery || bSort || bSubTotal ) + { + sal_Bool bQuerySize = sal_False; + ScRange aOldQuery; + ScRange aNewQuery; + if (bQuery && !aQueryParam.bInplace) + { + ScDBData* pDest = pDoc->GetDBAtCursor( aQueryParam.nDestCol, aQueryParam.nDestRow, + aQueryParam.nDestTab, sal_True ); + if (pDest && pDest->IsDoSize()) + { + pDest->GetArea( aOldQuery ); + bQuerySize = sal_True; + } + } + + SCTAB nDummy; + SCCOL nStartCol; + SCROW nStartRow; + SCCOL nEndCol; + SCROW nEndRow; + pDBData->GetArea( nDummy, nStartCol, nStartRow, nEndCol, nEndRow ); + + //! Undo nur benoetigte Daten ? + + ScDocument* pUndoDoc = NULL; + ScOutlineTable* pUndoTab = NULL; + ScRangeName* pUndoRange = NULL; + ScDBCollection* pUndoDB = NULL; + + if (bRecord) + { + SCTAB nTabCount = pDoc->GetTableCount(); + pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab ); + if (pTable) + { + pUndoTab = new ScOutlineTable( *pTable ); + + SCCOLROW nOutStartCol; // Zeilen/Spaltenstatus + SCCOLROW nOutStartRow; + SCCOLROW nOutEndCol; + SCCOLROW nOutEndRow; + pTable->GetColArray()->GetRange( nOutStartCol, nOutEndCol ); + pTable->GetRowArray()->GetRange( nOutStartRow, nOutEndRow ); + + pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_True ); + pDoc->CopyToDocument( static_cast<SCCOL>(nOutStartCol), 0, nTab, static_cast<SCCOL>(nOutEndCol), MAXROW, nTab, IDF_NONE, sal_False, pUndoDoc ); + pDoc->CopyToDocument( 0, nOutStartRow, nTab, MAXCOL, nOutEndRow, nTab, IDF_NONE, sal_False, pUndoDoc ); + } + else + pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_False, sal_True ); + + // Datenbereich sichern - incl. Filter-Ergebnis + pDoc->CopyToDocument( 0,nStartRow,nTab, MAXCOL,nEndRow,nTab, IDF_ALL, sal_False, pUndoDoc ); + + // alle Formeln wegen Referenzen + pDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1, IDF_FORMULA, sal_False, pUndoDoc ); + + // DB- und andere Bereiche + ScRangeName* pDocRange = pDoc->GetRangeName(); + if (pDocRange->GetCount()) + pUndoRange = new ScRangeName( *pDocRange ); + ScDBCollection* pDocDB = pDoc->GetDBCollection(); + if (pDocDB->GetCount()) + pUndoDB = new ScDBCollection( *pDocDB ); + } + + if (bSort && bSubTotal) + { + // Sortieren ohne SubTotals + + aSubTotalParam.bRemoveOnly = sal_True; // wird unten wieder zurueckgesetzt + DoSubTotals( aSubTotalParam, sal_False ); + } + + if (bSort) + { + pDBData->GetSortParam( aSortParam ); // Bereich kann sich geaendert haben + Sort( aSortParam, sal_False, sal_False); + } + if (bQuery) + { + pDBData->GetQueryParam( aQueryParam ); // Bereich kann sich geaendert haben + ScRange aAdvSource; + if (pDBData->GetAdvancedQuerySource(aAdvSource)) + { + pDoc->CreateQueryParam( + aAdvSource.aStart.Col(), aAdvSource.aStart.Row(), + aAdvSource.aEnd.Col(), aAdvSource.aEnd.Row(), + aAdvSource.aStart.Tab(), aQueryParam ); + Query( aQueryParam, &aAdvSource, sal_False ); + } + else + Query( aQueryParam, NULL, sal_False ); + + // bei nicht-inplace kann die Tabelle umgestellt worden sein + if ( !aQueryParam.bInplace && aQueryParam.nDestTab != nTab ) + SetTabNo( nTab ); + } + if (bSubTotal) + { + pDBData->GetSubTotalParam( aSubTotalParam ); // Bereich kann sich geaendert haben + aSubTotalParam.bRemoveOnly = sal_False; + DoSubTotals( aSubTotalParam, sal_False ); + } + + if (bRecord) + { + SCTAB nDummyTab; + SCCOL nDummyCol; + SCROW nDummyRow, nNewEndRow; + pDBData->GetArea( nDummyTab, nDummyCol,nDummyRow, nDummyCol,nNewEndRow ); + + const ScRange* pOld = NULL; + const ScRange* pNew = NULL; + if (bQuerySize) + { + ScDBData* pDest = pDoc->GetDBAtCursor( aQueryParam.nDestCol, aQueryParam.nDestRow, + aQueryParam.nDestTab, sal_True ); + if (pDest) + { + pDest->GetArea( aNewQuery ); + pOld = &aOldQuery; + pNew = &aNewQuery; + } + } + + GetViewData()->GetDocShell()->GetUndoManager()->AddUndoAction( + new ScUndoRepeatDB( GetViewData()->GetDocShell(), nTab, + nStartCol, nStartRow, nEndCol, nEndRow, + nNewEndRow, + nCurX, nCurY, + pUndoDoc, pUndoTab, + pUndoRange, pUndoDB, + pOld, pNew ) ); + } + + GetViewData()->GetDocShell()->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, + PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE ); + } + else // "Keine Operationen auszufuehren" + ErrorMessage(STR_MSSG_REPEATDB_0); +} + + + + diff --git a/sc/source/ui/view/dbfunc4.cxx b/sc/source/ui/view/dbfunc4.cxx new file mode 100644 index 000000000000..cb2c049f3200 --- /dev/null +++ b/sc/source/ui/view/dbfunc4.cxx @@ -0,0 +1,102 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +//------------------------------------------------------------------ + +// INCLUDE --------------------------------------------------------------- + +#include <svx/svditer.hxx> +#include <svx/svdoole2.hxx> +#include <svx/svdpage.hxx> + +#include "dbfunc.hxx" +#include "drwlayer.hxx" +#include "document.hxx" + +// ----------------------------------------------------------------------- + +#ifdef _MSC_VER +#pragma optimize ( "", off ) +#endif + +using namespace com::sun::star; + +//================================================================== + +// static +sal_uInt16 ScDBFunc::DoUpdateCharts( const ScAddress& rPos, ScDocument* pDoc, sal_Bool bAllCharts ) +{ + ScDrawLayer* pModel = pDoc->GetDrawLayer(); + if (!pModel) + return 0; + + sal_uInt16 nFound = 0; + + sal_uInt16 nPageCount = pModel->GetPageCount(); + for (sal_uInt16 nPageNo=0; nPageNo<nPageCount; nPageNo++) + { + SdrPage* pPage = pModel->GetPage(nPageNo); + DBG_ASSERT(pPage,"Page ?"); + + SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); + SdrObject* pObject = aIter.Next(); + while (pObject) + { + if ( pObject->GetObjIdentifier() == OBJ_OLE2 && pDoc->IsChart( pObject ) ) + { + String aName = ((SdrOle2Obj*)pObject)->GetPersistName(); + sal_Bool bHit = sal_True; + if ( !bAllCharts ) + { + ScRangeList aRanges; + sal_Bool bColHeaders = sal_False; + sal_Bool bRowHeaders = sal_False; + pDoc->GetOldChartParameters( aName, aRanges, bColHeaders, bRowHeaders ); + bHit = aRanges.In( rPos ); + } + if ( bHit ) + { + pDoc->UpdateChart( aName ); + ++nFound; + } + } + pObject = aIter.Next(); + } + } + return nFound; +} + + + + + + diff --git a/sc/source/ui/view/drawattr.cxx b/sc/source/ui/view/drawattr.cxx new file mode 100644 index 000000000000..4f79673bcc91 --- /dev/null +++ b/sc/source/ui/view/drawattr.cxx @@ -0,0 +1,82 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + +#include "drawattr.hxx" +#include "global.hxx" + +//------------------------------------------------------------------------ + +String __EXPORT SvxDrawToolItem::GetValueText() const +{ + return GetValueText(GetValue()); +} + +//------------------------------------------------------------------------ + +String __EXPORT SvxDrawToolItem::GetValueText( sal_uInt16 nVal ) const +{ + const sal_Char* p; + + switch (nVal) + { + case 0 : p = "SVX_SNAP_DRAW_SELECT" ; break; + // + case 1 : p = "SVX_SNAP_DRAW_LINE" ; break; + case 2 : p = "SVX_SNAP_DRAW_RECT" ; break; + case 3 : p = "SVX_SNAP_DRAW_ELLIPSE" ; break; + case 4 : p = "SVX_SNAP_DRAW_POLYGON" ; break; + case 5 : p = "SVX_SNAP_DRAW_ARC" ; break; + case 6 : p = "SVX_SNAP_DRAW_PIE" ; break; + case 7 : p = "SVX_SNAP_DRAW_CIRCLECUT" ; break; + case 8 : p = "SVX_SNAP_DRAW_TEXT" ; break; + default : return EMPTY_STRING; + } + return String::CreateFromAscii( p ); +} + +//------------------------------------------------------------------------ + +SfxPoolItem* __EXPORT SvxDrawToolItem::Clone( SfxItemPool * ) const +{ + return new SvxDrawToolItem(*this); +} + +//------------------------------------------------------------------------ + +SfxPoolItem* __EXPORT SvxDrawToolItem::Create( SvStream& rStream, sal_uInt16 nVer ) const +{ + sal_uInt16 nVal; + rStream >> nVal; + return new SvxDrawToolItem(nVal); +} + + + diff --git a/sc/source/ui/view/drawutil.cxx b/sc/source/ui/view/drawutil.cxx new file mode 100644 index 000000000000..a5a4a7ee1c1d --- /dev/null +++ b/sc/source/ui/view/drawutil.cxx @@ -0,0 +1,116 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include <vcl/outdev.hxx> + +#include "drawutil.hxx" +#include "document.hxx" +#include "global.hxx" +#include "viewdata.hxx" + +// STATIC DATA ----------------------------------------------------------- + +// ----------------------------------------------------------------------- + + +inline Fraction MakeFraction( long nA, long nB ) +{ + return ( nA && nB ) ? Fraction(nA,nB) : Fraction(1,1); +} + +void ScDrawUtil::CalcScale( ScDocument* pDoc, SCTAB nTab, + SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, + OutputDevice* pDev, + const Fraction& rZoomX, const Fraction& rZoomY, + double nPPTX, double nPPTY, + Fraction& rScaleX, Fraction& rScaleY ) +{ + long nPixelX = 0; + long nTwipsX = 0; + long nPixelY = 0; + long nTwipsY = 0; + for (SCCOL i=nStartCol; i<nEndCol; i++) + { + sal_uInt16 nWidth = pDoc->GetColWidth(i,nTab); + nTwipsX += (long) nWidth; + nPixelX += ScViewData::ToPixel( nWidth, nPPTX ); + } + + for (SCROW nRow = nStartRow; nRow <= nEndRow-1; ++nRow) + { + SCROW nLastRow = nRow; + if (pDoc->RowHidden(nRow, nTab, NULL, &nLastRow)) + { + nRow = nLastRow; + continue; + } + + sal_uInt16 nHeight = pDoc->GetRowHeight(nRow, nTab); + nTwipsY += static_cast<long>(nHeight); + nPixelY += ScViewData::ToPixel(nHeight, nPPTY); + } + + MapMode aHMMMode( MAP_100TH_MM, Point(), rZoomX, rZoomY ); + Point aPixelLog = pDev->PixelToLogic( Point( nPixelX,nPixelY ), aHMMMode ); + + // Fraction(double) ctor can be used here (and avoid overflows of PixelLog * Zoom) + // because ReduceInaccurate is called later anyway. + + if ( aPixelLog.X() && nTwipsX ) + rScaleX = Fraction( ((double)aPixelLog.X()) * + ((double)rZoomX.GetNumerator()) / + ((double)nTwipsX) / + ((double)HMM_PER_TWIPS) / + ((double)rZoomX.GetDenominator()) ); + else + rScaleX = Fraction( 1, 1 ); + + if ( aPixelLog.Y() && nTwipsY ) + rScaleY = Fraction( ((double)aPixelLog.Y()) * + ((double)rZoomY.GetNumerator()) / + ((double)nTwipsY) / + ((double)HMM_PER_TWIPS) / + ((double)rZoomY.GetDenominator()) ); + else + rScaleY = Fraction( 1, 1 ); + + // 25 bits of accuracy are needed to always hit the right part of + // cells in the last rows (was 17 before 1M rows). + rScaleX.ReduceInaccurate( 25 ); + rScaleY.ReduceInaccurate( 25 ); +} + + + + diff --git a/sc/source/ui/view/drawvie2.cxx b/sc/source/ui/view/drawvie2.cxx new file mode 100644 index 000000000000..c760ce86a3d7 --- /dev/null +++ b/sc/source/ui/view/drawvie2.cxx @@ -0,0 +1,62 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include "drawview.hxx" + +// STATIC DATA ----------------------------------------------------------- + +// ----------------------------------------------------------------------- + + +// UpdateBrowser in MarkListHasChanged gerufen + +void ScDrawView::UpdateBrowser() +{ + // VC's und den Browser dazu gibts nicht mehr... +} + +void ScDrawView::VCAddWin( Window* /* pWin */ ) +{ + // GetSbxForm gibt's nicht mehr, muss auch nichts mehr angemeldet werden +} + +void ScDrawView::VCRemoveWin( Window* /* pWin */ ) +{ + // GetSbxForm gibt's nicht mehr, muss auch nichts mehr angemeldet werden +} + + + + + diff --git a/sc/source/ui/view/drawvie3.cxx b/sc/source/ui/view/drawvie3.cxx new file mode 100644 index 000000000000..670782f5af9c --- /dev/null +++ b/sc/source/ui/view/drawvie3.cxx @@ -0,0 +1,182 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include <svx/svdograf.hxx> +#include <svx/svdoole2.hxx> +#include <sfx2/app.hxx> +#include <sfx2/viewfrm.hxx> + +#include "drawview.hxx" +#include "drwlayer.hxx" +#include "viewdata.hxx" +#include "dbfunc.hxx" +#include "document.hxx" +#include "userdat.hxx" +#include "tabvwsh.hxx" +#include "docsh.hxx" + +void ScIMapDlgSet( const Graphic& rGraphic, const ImageMap* pImageMap, + const TargetList* pTargetList, void* pEditingObj ); // imapwrap +sal_uInt16 ScIMapChildWindowId(); + +// STATIC DATA ----------------------------------------------------------- + +ScDrawView::ScDrawView( OutputDevice* pOut, ScViewData* pData ) : + FmFormView( pData->GetDocument()->GetDrawLayer(), pOut ), + pViewData( pData ), + pDev( pOut ), + pDoc( pData->GetDocument() ), + nTab( pData->GetTabNo() ), + pDropMarker( NULL ), + pDropMarkObj( NULL ), + bInConstruct( sal_True ) + //HMHbDisableHdl( sal_False ) +{ + // #i73602# Use default from the configuration + SetBufferedOverlayAllowed(getOptionsDrawinglayer().IsOverlayBuffer_Calc()); + + // #i74769#, #i75172# Use default from the configuration + SetBufferedOutputAllowed(getOptionsDrawinglayer().IsPaintBuffer_Calc()); + + Construct(); +} + +// Verankerung setzen + +void ScDrawView::SetAnchor( ScAnchorType eType ) +{ + SdrObject* pObj = NULL; + if( AreObjectsMarked() ) + { + const SdrMarkList* pMark = &GetMarkedObjectList(); + sal_uLong nCount = pMark->GetMarkCount(); + for( sal_uLong i=0; i<nCount; i++ ) + { + pObj = pMark->GetMark(i)->GetMarkedSdrObj(); + ScDrawLayer::SetAnchor( pObj, eType ); + } + + if ( pViewData ) + pViewData->GetDocShell()->SetDrawModified(); + } +} + +ScAnchorType ScDrawView::GetAnchor() const +{ + sal_Bool bPage = sal_False; + sal_Bool bCell = sal_False; + const SdrObject* pObj = NULL; + if( AreObjectsMarked() ) + { + const SdrMarkList* pMark = &GetMarkedObjectList(); + sal_uLong nCount = pMark->GetMarkCount(); + Point p0; + for( sal_uLong i=0; i<nCount; i++ ) + { + pObj = pMark->GetMark(i)->GetMarkedSdrObj(); + if( ScDrawLayer::GetAnchor( pObj ) == SCA_CELL ) + bCell =sal_True; + else + bPage = sal_True; + } + } + if( bPage && !bCell ) + return SCA_PAGE; + if( !bPage && bCell ) + return SCA_CELL; + return SCA_DONTKNOW; +} + +void __EXPORT ScDrawView::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) +{ + if (rHint.ISA(ScTabDeletedHint)) // Tabelle geloescht + { + SCTAB nDelTab = ((ScTabDeletedHint&)rHint).GetTab(); + if (ValidTab(nDelTab)) + { + // used to be: HidePagePgNum(nDelTab) - hide only if the deleted sheet is shown here + if ( nDelTab == nTab ) + HideSdrPage(); + } + } + else if (rHint.ISA(ScTabSizeChangedHint)) // Groesse geaendert + { + if ( nTab == ((ScTabSizeChangedHint&)rHint).GetTab() ) + UpdateWorkArea(); + } + else + FmFormView::Notify( rBC,rHint ); +} + +void ScDrawView::UpdateIMap( SdrObject* pObj ) +{ + if ( pViewData && + pViewData->GetViewShell()->GetViewFrame()->HasChildWindow( ScIMapChildWindowId() ) && + pObj && ( pObj->ISA(SdrGrafObj) || pObj->ISA(SdrOle2Obj) ) ) + { + Graphic aGraphic; + TargetList aTargetList; + ScIMapInfo* pIMapInfo = ScDrawLayer::GetIMapInfo( pObj ); + const ImageMap* pImageMap = NULL; + if ( pIMapInfo ) + pImageMap = &pIMapInfo->GetImageMap(); + + // Target-Liste besorgen + pViewData->GetViewShell()->GetViewFrame()->GetTargetList( aTargetList ); + + // Grafik vom Objekt besorgen + if ( pObj->ISA( SdrGrafObj ) ) + aGraphic = ( (SdrGrafObj*) pObj )->GetGraphic(); + else + { + Graphic* pGraphic = ((const SdrOle2Obj*) pObj )->GetGraphic(); + if ( pGraphic ) + aGraphic = *pGraphic; + } + + ScIMapDlgSet( aGraphic, pImageMap, &aTargetList, pObj ); // aus imapwrap + + // TargetListe kann von uns wieder geloescht werden + String* pEntry = aTargetList.First(); + while( pEntry ) + { + delete pEntry; + pEntry = aTargetList.Next(); + } + } +} + + + + diff --git a/sc/source/ui/view/drawvie4.cxx b/sc/source/ui/view/drawvie4.cxx new file mode 100644 index 000000000000..1c0d38ee18e5 --- /dev/null +++ b/sc/source/ui/view/drawvie4.cxx @@ -0,0 +1,394 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" +#include <com/sun/star/embed/NoVisualAreaSizeException.hpp> + + + +// INCLUDE --------------------------------------------------------------- +#include <svx/svditer.hxx> +#include <svx/svdograf.hxx> +#include <svx/svdogrp.hxx> +#include <svx/svdoole2.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdundo.hxx> +#include <sfx2/docfile.hxx> +#include <tools/urlobj.hxx> +#include <toolkit/helper/vclunohelper.hxx> + +#include "drawview.hxx" +#include "global.hxx" +#include "drwlayer.hxx" +#include "viewdata.hxx" +#include "document.hxx" +#include "docsh.hxx" +#include "drwtrans.hxx" +#include "transobj.hxx" // SetDrawClipDoc +#include "drawutil.hxx" +#include "scmod.hxx" +#include "globstr.hrc" +#include "chartarr.hxx" + +using namespace com::sun::star; + +// STATIC DATA ----------------------------------------------------------- + +Point aDragStartDiff; + +// ----------------------------------------------------------------------- + +//! welche Funktionen aus drawview/drawvie4 muessen wirklich ohne Optimierung sein? + +#ifdef _MSC_VER +#pragma optimize ( "", off ) +#endif + +// ----------------------------------------------------------------------- + +void lcl_CheckOle( const SdrMarkList& rMarkList, sal_Bool& rAnyOle, sal_Bool& rOneOle ) +{ + rAnyOle = rOneOle = sal_False; + sal_uLong nCount = rMarkList.GetMarkCount(); + for (sal_uLong i=0; i<nCount; i++) + { + SdrMark* pMark = rMarkList.GetMark(i); + SdrObject* pObj = pMark->GetMarkedSdrObj(); + sal_uInt16 nSdrObjKind = pObj->GetObjIdentifier(); + if (nSdrObjKind == OBJ_OLE2) + { + rAnyOle = sal_True; + rOneOle = (nCount == 1); + break; + } + else if ( pObj->ISA(SdrObjGroup) ) + { + SdrObjListIter aIter( *pObj, IM_DEEPNOGROUPS ); + SdrObject* pSubObj = aIter.Next(); + while (pSubObj) + { + if ( pSubObj->GetObjIdentifier() == OBJ_OLE2 ) + { + rAnyOle = sal_True; + // rOneOle remains sal_False - a group isn't treated like a single OLE object + return; + } + pSubObj = aIter.Next(); + } + } + } +} + +#if 0 +void lcl_RefreshChartData( SdrModel* pModel, ScDocument* pSourceDoc ) +{ + sal_uInt16 nPages = pModel->GetPageCount(); + for (SCTAB nTab=0; nTab<nPages; nTab++) + { + SdrPage* pPage = pModel->GetPage(nTab); + SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); + SdrObject* pObject = aIter.Next(); + while (pObject) + { + if ( pObject->GetObjIdentifier() == OBJ_OLE2 ) + { + SvInPlaceObjectRef aIPObj = ((SdrOle2Obj*)pObject)->GetObjRef(); + if ( aIPObj.Is() && SotExchange::IsChart( aIPObj->GetStorage()->GetClassName() ) ) + { + SchMemChart* pOldData = SchDLL::GetChartData(aIPObj); + if ( pOldData ) + { + // create data from source document + ScChartArray aArray( pSourceDoc, *pOldData ); + if ( aArray.IsValid() ) + { + SchMemChart* pNewData = aArray.CreateMemChart(); + SchDLL::Update( aIPObj, pNewData ); + delete pNewData; + ((SdrOle2Obj*)pObject)->GetNewReplacement(); + } + } + } + } + pObject = aIter.Next(); + } + } +} +#endif + + +sal_Bool ScDrawView::BeginDrag( Window* pWindow, const Point& rStartPos ) +{ + sal_Bool bReturn = sal_False; + + if ( AreObjectsMarked() ) + { + BrkAction(); + + Rectangle aMarkedRect = GetAllMarkedRect(); + Region aRegion( aMarkedRect ); + + aDragStartDiff = rStartPos - aMarkedRect.TopLeft(); + + sal_Bool bAnyOle, bOneOle; + const SdrMarkList& rMarkList = GetMarkedObjectList(); + lcl_CheckOle( rMarkList, bAnyOle, bOneOle ); + + ScDocShellRef aDragShellRef; + if (bAnyOle) + { + aDragShellRef = new ScDocShell; // DocShell needs a Ref immediately + aDragShellRef->DoInitNew(NULL); + } + ScDrawLayer::SetGlobalDrawPersist(aDragShellRef); + SdrModel* pModel = GetAllMarkedModel(); + ScDrawLayer::SetGlobalDrawPersist(NULL); + + // Charts now always copy their data in addition to the source reference, so + // there's no need to call SchDLL::Update for the charts in the clipboard doc. + // Update with the data (including NumberFormatter) from the live document would + // also store the NumberFormatter in the clipboard chart (#88749#) + // lcl_RefreshChartData( pModel, pViewData->GetDocument() ); + + ScDocShell* pDocSh = pViewData->GetDocShell(); + + TransferableObjectDescriptor aObjDesc; + pDocSh->FillTransferableObjectDescriptor( aObjDesc ); + aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass(); + // maSize is set in ScDrawTransferObj ctor + + ScDrawTransferObj* pTransferObj = new ScDrawTransferObj( pModel, pDocSh, aObjDesc ); + uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj ); + + pTransferObj->SetDrawPersist( &aDragShellRef ); // keep persist for ole objects alive + pTransferObj->SetDragSource( this ); // copies selection + + SC_MOD()->SetDragObject( NULL, pTransferObj ); // for internal D&D + pTransferObj->StartDrag( pWindow, DND_ACTION_COPYMOVE | DND_ACTION_LINK ); + } + + return bReturn; +} + +void ScDrawView::DoCopy() +{ + sal_Bool bAnyOle, bOneOle; + const SdrMarkList& rMarkList = GetMarkedObjectList(); + lcl_CheckOle( rMarkList, bAnyOle, bOneOle ); + + // update ScGlobal::pDrawClipDocShellRef + ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) ); + SdrModel* pModel = GetAllMarkedModel(); + ScDrawLayer::SetGlobalDrawPersist(NULL); + + // Charts now always copy their data in addition to the source reference, so + // there's no need to call SchDLL::Update for the charts in the clipboard doc. + // Update with the data (including NumberFormatter) from the live document would + // also store the NumberFormatter in the clipboard chart (#88749#) + // lcl_RefreshChartData( pModel, pViewData->GetDocument() ); + + ScDocShell* pDocSh = pViewData->GetDocShell(); + + TransferableObjectDescriptor aObjDesc; + pDocSh->FillTransferableObjectDescriptor( aObjDesc ); + aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass(); + // maSize is set in ScDrawTransferObj ctor + + ScDrawTransferObj* pTransferObj = new ScDrawTransferObj( pModel, pDocSh, aObjDesc ); + uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj ); + + if ( ScGlobal::pDrawClipDocShellRef ) + { + pTransferObj->SetDrawPersist( &(*ScGlobal::pDrawClipDocShellRef) ); // keep persist for ole objects alive + } + + pTransferObj->CopyToClipboard( pViewData->GetActiveWin() ); // system clipboard + SC_MOD()->SetClipObject( NULL, pTransferObj ); // internal clipboard +} + +uno::Reference<datatransfer::XTransferable> ScDrawView::CopyToTransferable() +{ + sal_Bool bAnyOle, bOneOle; + const SdrMarkList& rMarkList = GetMarkedObjectList(); + lcl_CheckOle( rMarkList, bAnyOle, bOneOle ); + + // update ScGlobal::pDrawClipDocShellRef + ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) ); + SdrModel* pModel = GetAllMarkedModel(); + ScDrawLayer::SetGlobalDrawPersist(NULL); + + // Charts now always copy their data in addition to the source reference, so + // there's no need to call SchDLL::Update for the charts in the clipboard doc. + // Update with the data (including NumberFormatter) from the live document would + // also store the NumberFormatter in the clipboard chart (#88749#) + // lcl_RefreshChartData( pModel, pViewData->GetDocument() ); + + ScDocShell* pDocSh = pViewData->GetDocShell(); + + TransferableObjectDescriptor aObjDesc; + pDocSh->FillTransferableObjectDescriptor( aObjDesc ); + aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass(); + // maSize is set in ScDrawTransferObj ctor + + ScDrawTransferObj* pTransferObj = new ScDrawTransferObj( pModel, pDocSh, aObjDesc ); + uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj ); + + if ( ScGlobal::pDrawClipDocShellRef ) + { + pTransferObj->SetDrawPersist( &(*ScGlobal::pDrawClipDocShellRef) ); // keep persist for ole objects alive + } + + return xTransferable; +} + +// Korrektur fuer 100% berechnen, unabhaengig von momentanen Einstellungen + +void ScDrawView::CalcNormScale( Fraction& rFractX, Fraction& rFractY ) const +{ + Point aLogic = pDev->LogicToPixel( Point(1000,1000), MAP_TWIP ); + double nPPTX = ScGlobal::nScreenPPTX; + double nPPTY = ScGlobal::nScreenPPTY; + + if (pViewData) + nPPTX /= pViewData->GetDocShell()->GetOutputFactor(); + + SCCOL nEndCol = 0; + SCROW nEndRow = 0; + pDoc->GetTableArea( nTab, nEndCol, nEndRow ); + if (nEndCol<20) + nEndCol = 20; + if (nEndRow<20) + nEndRow = 1000; + + Fraction aZoom(1,1); + ScDrawUtil::CalcScale( pDoc, nTab, 0,0, nEndCol,nEndRow, pDev, aZoom,aZoom, + nPPTX, nPPTY, rFractX,rFractY ); +} + +void ScDrawView::SetMarkedOriginalSize() +{ + SdrUndoGroup* pUndoGroup = new SdrUndoGroup(*GetModel()); + + const SdrMarkList& rMarkList = GetMarkedObjectList(); + long nDone = 0; + sal_uLong nCount = rMarkList.GetMarkCount(); + for (sal_uLong i=0; i<nCount; i++) + { + SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj(); + sal_uInt16 nIdent = pObj->GetObjIdentifier(); + sal_Bool bDo = sal_False; + Size aOriginalSize; + if (nIdent == OBJ_OLE2) + { + // TODO/LEAN: working with visual area can switch object to running state + uno::Reference < embed::XEmbeddedObject > xObj( ((SdrOle2Obj*)pObj)->GetObjRef(), uno::UNO_QUERY ); + if ( xObj.is() ) // #121612# NULL for an invalid object that couldn't be loaded + { + sal_Int64 nAspect = ((SdrOle2Obj*)pObj)->GetAspect(); + + if ( nAspect == embed::Aspects::MSOLE_ICON ) + { + MapMode aMapMode( MAP_100TH_MM ); + aOriginalSize = ((SdrOle2Obj*)pObj)->GetOrigObjSize( &aMapMode ); + bDo = sal_True; + } + else + { + MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( ((SdrOle2Obj*)pObj)->GetAspect() ) ); + awt::Size aSz; + try + { + aSz = xObj->getVisualAreaSize( ((SdrOle2Obj*)pObj)->GetAspect() ); + aOriginalSize = OutputDevice::LogicToLogic( + Size( aSz.Width, aSz.Height ), + aUnit, MAP_100TH_MM ); + bDo = sal_True; + } catch( embed::NoVisualAreaSizeException& ) + { + OSL_ENSURE( sal_False, "Can't get the original size of the object!" ); + } + } + } + } + else if (nIdent == OBJ_GRAF) + { + const Graphic& rGraphic = ((SdrGrafObj*)pObj)->GetGraphic(); + + MapMode aSourceMap = rGraphic.GetPrefMapMode(); + MapMode aDestMap( MAP_100TH_MM ); + if (aSourceMap.GetMapUnit() == MAP_PIXEL) + { + // Pixel-Korrektur beruecksichtigen, damit Bitmap auf dem Bildschirm stimmt + + Fraction aNormScaleX, aNormScaleY; + CalcNormScale( aNormScaleX, aNormScaleY ); + aDestMap.SetScaleX(aNormScaleX); + aDestMap.SetScaleY(aNormScaleY); + } + if (pViewData) + { + Window* pActWin = pViewData->GetActiveWin(); + if (pActWin) + { + aOriginalSize = pActWin->LogicToLogic( + rGraphic.GetPrefSize(), &aSourceMap, &aDestMap ); + bDo = sal_True; + } + } + } + + if ( bDo ) + { + Rectangle aDrawRect = pObj->GetLogicRect(); + + pUndoGroup->AddAction( new SdrUndoGeoObj( *pObj ) ); + pObj->Resize( aDrawRect.TopLeft(), Fraction( aOriginalSize.Width(), aDrawRect.GetWidth() ), + Fraction( aOriginalSize.Height(), aDrawRect.GetHeight() ) ); + ++nDone; + } + } + + if (nDone) + { + pUndoGroup->SetComment(ScGlobal::GetRscString( STR_UNDO_ORIGINALSIZE )); + ScDocShell* pDocSh = pViewData->GetDocShell(); + pDocSh->GetUndoManager()->AddUndoAction(pUndoGroup); + pDocSh->SetDrawModified(); + } + else + delete pUndoGroup; +} + + +#ifdef _MSC_VER +#pragma optimize ( "", on ) +#endif + + + + diff --git a/sc/source/ui/view/drawview.cxx b/sc/source/ui/view/drawview.cxx new file mode 100644 index 000000000000..cc63f9b97a62 --- /dev/null +++ b/sc/source/ui/view/drawview.cxx @@ -0,0 +1,845 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +// INCLUDE --------------------------------------------------------------- + +#include <com/sun/star/embed/EmbedStates.hpp> + +#include <svx/svditer.hxx> +#include <svx/svdograf.hxx> +#include <svx/svdomedia.hxx> +#include <svx/svdogrp.hxx> +#include <svx/svdoole2.hxx> +#include <svx/svdouno.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdundo.hxx> +#include <svx/svdocapt.hxx> +#include <editeng/outlobj.hxx> +#include <editeng/writingmodeitem.hxx> +#include <svx/sdrpaintwindow.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/viewfrm.hxx> + +#include "drawview.hxx" +#include "global.hxx" +#include "viewdata.hxx" +#include "document.hxx" +#include "drawutil.hxx" +#include "futext.hxx" +#include "globstr.hrc" +#include "tabvwsh.hxx" +#include "client.hxx" +#include "scmod.hxx" +#include "drwlayer.hxx" +#include "docsh.hxx" +#include "viewuno.hxx" +#include "userdat.hxx" +#include "postit.hxx" +#include "undocell.hxx" + +#include "sc.hrc" + +using namespace com::sun::star; + +// ----------------------------------------------------------------------- + +#define SC_HANDLESIZE_BIG 9 +#define SC_HANDLESIZE_SMALL 7 + +// ----------------------------------------------------------------------- + +#ifdef _MSC_VER +#pragma optimize ( "", off ) +#endif + + +void ScDrawView::Construct() +{ + EnableExtendedKeyInputDispatcher(sal_False); + EnableExtendedMouseEventDispatcher(sal_False); + EnableExtendedCommandEventDispatcher(sal_False); + + SetFrameDragSingles(sal_True); +// SetSolidMarkHdl(sal_True); // einstellbar -> UpdateUserViewOptions + + SetMinMoveDistancePixel( 2 ); + SetHitTolerancePixel( 2 ); + + if (pViewData) + { + SCTAB nViewTab = pViewData->GetTabNo(); + ShowSdrPage(GetModel()->GetPage(nViewTab)); + + sal_Bool bEx = pViewData->GetViewShell()->IsDrawSelMode(); + sal_Bool bProt = pDoc->IsTabProtected( nViewTab ) || + pViewData->GetSfxDocShell()->IsReadOnly(); + + SdrLayer* pLayer; + SdrLayerAdmin& rAdmin = GetModel()->GetLayerAdmin(); + pLayer = rAdmin.GetLayerPerID(SC_LAYER_BACK); + if (pLayer) + SetLayerLocked( pLayer->GetName(), bProt || !bEx ); + pLayer = rAdmin.GetLayerPerID(SC_LAYER_INTERN); + if (pLayer) + SetLayerLocked( pLayer->GetName(), sal_True ); + pLayer = rAdmin.GetLayerPerID(SC_LAYER_FRONT); + if (pLayer) + { + SetLayerLocked( pLayer->GetName(), bProt ); + SetActiveLayer( pLayer->GetName() ); // FRONT als aktiven Layer setzen + } + pLayer = rAdmin.GetLayerPerID(SC_LAYER_CONTROLS); + if (pLayer) + SetLayerLocked( pLayer->GetName(), bProt ); + pLayer = rAdmin.GetLayerPerID(SC_LAYER_HIDDEN); + if (pLayer) + { + SetLayerLocked( pLayer->GetName(), bProt ); + SetLayerVisible( pLayer->GetName(), sal_False); + } + + SetSwapAsynchron(sal_True); + } + else + { + ShowSdrPage(GetModel()->GetPage(nTab)); + } + + UpdateUserViewOptions(); + RecalcScale(); + UpdateWorkArea(); + + bInConstruct = sal_False; +} + +void ScDrawView::ImplClearCalcDropMarker() +{ + if(pDropMarker) + { + delete pDropMarker; + pDropMarker = 0L; + } +} + +__EXPORT ScDrawView::~ScDrawView() +{ + ImplClearCalcDropMarker(); +} + +void ScDrawView::AddCustomHdl() +{ + sal_Bool bNegativePage = pDoc->IsNegativePage( nTab ); + + const SdrMarkList &rMrkList = GetMarkedObjectList(); + sal_uInt32 nCount = rMrkList.GetMarkCount(); + for(sal_uInt32 nPos=0; nPos<nCount; nPos++ ) + { + const SdrObject* pObj = rMrkList.GetMark(nPos)->GetMarkedSdrObj(); + if(ScDrawLayer::GetAnchor(pObj) == SCA_CELL) + { + const sal_Int32 nDelta = 1; + + Rectangle aBoundRect = pObj->GetCurrentBoundRect(); + Point aPos; + if (bNegativePage) + { + aPos = aBoundRect.TopRight(); + aPos.X() = -aPos.X(); // so the loop below is the same + } + else + aPos = aBoundRect.TopLeft(); + long nPosX = (long) (aPos.X() / HMM_PER_TWIPS) + nDelta; + long nPosY = (long) (aPos.Y() / HMM_PER_TWIPS) + nDelta; + + SCCOL nCol; + sal_Int32 nWidth = 0; + + for(nCol=0; nCol<=MAXCOL && nWidth<=nPosX; nCol++) + nWidth += pDoc->GetColWidth(nCol,nTab); + + if(nCol > 0) + --nCol; + + SCROW nRow = nPosY <= 0 ? 0 : pDoc->GetRowForHeight( nTab, + (sal_uLong) nPosY); + if(nRow > 0) + --nRow; + + ScTabView* pView = pViewData->GetView(); + ScAddress aScAddress(nCol, nRow, nTab); + pView->CreateAnchorHandles(aHdl, aScAddress); + } + } +} + +void ScDrawView::InvalidateAttribs() +{ + if (!pViewData) return; + SfxBindings& rBindings = pViewData->GetBindings(); + + // echte Statuswerte: + rBindings.InvalidateAll( sal_True ); +} + +void ScDrawView::InvalidateDrawTextAttrs() +{ + if (!pViewData) return; + SfxBindings& rBindings = pViewData->GetBindings(); + + // cjk/ctl font items have no configured slots, + // need no invalidate + + rBindings.Invalidate( SID_ATTR_CHAR_FONT ); + rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT ); + rBindings.Invalidate( SID_ATTR_CHAR_WEIGHT ); + rBindings.Invalidate( SID_ATTR_CHAR_POSTURE ); + rBindings.Invalidate( SID_ATTR_CHAR_UNDERLINE ); + rBindings.Invalidate( SID_ULINE_VAL_NONE ); + rBindings.Invalidate( SID_ULINE_VAL_SINGLE ); + rBindings.Invalidate( SID_ULINE_VAL_DOUBLE ); + rBindings.Invalidate( SID_ULINE_VAL_DOTTED ); + rBindings.Invalidate( SID_ATTR_CHAR_OVERLINE ); + rBindings.Invalidate( SID_ATTR_CHAR_COLOR ); + rBindings.Invalidate( SID_ALIGNLEFT ); + rBindings.Invalidate( SID_ALIGNCENTERHOR ); + rBindings.Invalidate( SID_ALIGNRIGHT ); + rBindings.Invalidate( SID_ALIGNBLOCK ); + rBindings.Invalidate( SID_ATTR_PARA_LINESPACE_10 ); + rBindings.Invalidate( SID_ATTR_PARA_LINESPACE_15 ); + rBindings.Invalidate( SID_ATTR_PARA_LINESPACE_20 ); + rBindings.Invalidate( SID_SET_SUPER_SCRIPT ); + rBindings.Invalidate( SID_SET_SUB_SCRIPT ); + rBindings.Invalidate( SID_TEXTDIRECTION_LEFT_TO_RIGHT ); + rBindings.Invalidate( SID_TEXTDIRECTION_TOP_TO_BOTTOM ); + rBindings.Invalidate( SID_ATTR_PARA_LEFT_TO_RIGHT ); + rBindings.Invalidate( SID_ATTR_PARA_RIGHT_TO_LEFT ); + // pseudo slots for Format menu + rBindings.Invalidate( SID_ALIGN_ANY_LEFT ); + rBindings.Invalidate( SID_ALIGN_ANY_HCENTER ); + rBindings.Invalidate( SID_ALIGN_ANY_RIGHT ); + rBindings.Invalidate( SID_ALIGN_ANY_JUSTIFIED ); +} + +//void ScDrawView::DrawMarks( OutputDevice* pOut ) const +//{ +// DBG_ASSERT(pOut, "ScDrawView::DrawMarks: No OutputDevice (!)"); +// SdrPaintWindow* pPaintWindow = FindPaintWindow(*pOut); +// +// if(pPaintWindow) +// { +// if(pPaintWindow->isXorVisible()) +// { +// ToggleShownXor(pOut, 0L); +// } +// } +//} + +void ScDrawView::SetMarkedToLayer( sal_uInt8 nLayerNo ) +{ + if (AreObjectsMarked()) + { + // #i11702# use SdrUndoObjectLayerChange for undo + // STR_UNDO_SELATTR is "Attributes" - should use a different text later + BegUndo( ScGlobal::GetRscString( STR_UNDO_SELATTR ) ); + + const SdrMarkList& rMark = GetMarkedObjectList(); + sal_uLong nCount = rMark.GetMarkCount(); + for (sal_uLong i=0; i<nCount; i++) + { + SdrObject* pObj = rMark.GetMark(i)->GetMarkedSdrObj(); + if ( !pObj->ISA(SdrUnoObj) && (pObj->GetLayer() != SC_LAYER_INTERN) ) + { + AddUndo( new SdrUndoObjectLayerChange( *pObj, pObj->GetLayer(), (SdrLayerID)nLayerNo) ); + pObj->SetLayer( nLayerNo ); + } + } + + EndUndo(); + + // repaint is done in SetLayer + + pViewData->GetDocShell()->SetDrawModified(); + + // #84073# check mark list now instead of later in a timer + CheckMarked(); + MarkListHasChanged(); + } +} + +bool ScDrawView::HasMarkedControl() const +{ + SdrObjListIter aIter( GetMarkedObjectList() ); + for( SdrObject* pObj = aIter.Next(); pObj; pObj = aIter.Next() ) + if( pObj->ISA( SdrUnoObj ) ) + return true; + return false; +} + +bool ScDrawView::HasMarkedInternal() const +{ + // internal objects should not be inside a group, but who knows... + SdrObjListIter aIter( GetMarkedObjectList() ); + for( SdrObject* pObj = aIter.Next(); pObj; pObj = aIter.Next() ) + if( pObj->GetLayer() == SC_LAYER_INTERN ) + return true; + return false; +} + +void ScDrawView::UpdateWorkArea() +{ + SdrPage* pPage = GetModel()->GetPage(static_cast<sal_uInt16>(nTab)); + if (pPage) + { + Point aPos; + Size aPageSize( pPage->GetSize() ); + Rectangle aNewArea( aPos, aPageSize ); + if ( aPageSize.Width() < 0 ) + { + // RTL: from max.negative (left) to zero (right) + aNewArea.Right() = 0; + aNewArea.Left() = aPageSize.Width() + 1; + } + SetWorkArea( aNewArea ); + } + else + { + DBG_ERROR("Page nicht gefunden"); + } +} + +void ScDrawView::DoCut() +{ + DoCopy(); + BegUndo( ScGlobal::GetRscString( STR_UNDO_CUT ) ); + DeleteMarked(); // auf dieser View - von der 505f Umstellung nicht betroffen + EndUndo(); +} + +void ScDrawView::GetScale( Fraction& rFractX, Fraction& rFractY ) const +{ + rFractX = aScaleX; + rFractY = aScaleY; +} + +void ScDrawView::RecalcScale() +{ + double nPPTX; + double nPPTY; + Fraction aZoomX(1,1); + Fraction aZoomY(1,1); + + if (pViewData) + { + nTab = pViewData->GetTabNo(); + nPPTX = pViewData->GetPPTX(); + nPPTY = pViewData->GetPPTY(); + aZoomX = pViewData->GetZoomX(); + aZoomY = pViewData->GetZoomY(); + } + else + { + Point aLogic = pDev->LogicToPixel( Point(1000,1000), MAP_TWIP ); + nPPTX = aLogic.X() / 1000.0; + nPPTY = aLogic.Y() / 1000.0; + //! Zoom uebergeben ??? + } + + SCCOL nEndCol = 0; + SCROW nEndRow = 0; + pDoc->GetTableArea( nTab, nEndCol, nEndRow ); + if (nEndCol<20) + nEndCol = 20; + if (nEndRow<20) + nEndRow = 1000; + + ScDrawUtil::CalcScale( pDoc, nTab, 0,0, nEndCol,nEndRow, pDev,aZoomX,aZoomY,nPPTX,nPPTY, + aScaleX,aScaleY ); +} + +void ScDrawView::DoConnect(SdrOle2Obj* pOleObj) +{ + if ( pViewData ) + pViewData->GetViewShell()->ConnectObject( pOleObj ); +} + +void ScDrawView::MarkListHasChanged() +{ + FmFormView::MarkListHasChanged(); + + UpdateBrowser(); + + ScTabViewShell* pViewSh = pViewData->GetViewShell(); + + // #i110829# remove the cell selection only if drawing objects are selected + if ( !bInConstruct && GetMarkedObjectList().GetMarkCount() ) + { + pViewSh->Unmark(); // remove cell selection + + // #65379# end cell edit mode if drawing objects are selected + SC_MOD()->InputEnterHandler(); + } + + // IP deaktivieren + + ScModule* pScMod = SC_MOD(); + bool bUnoRefDialog = pScMod->IsRefDialogOpen() && pScMod->GetCurRefDlgId() == WID_SIMPLE_REF; + + ScClient* pClient = (ScClient*) pViewSh->GetIPClient(); + if ( pClient && pClient->IsObjectInPlaceActive() && !bUnoRefDialog ) + { + // #41730# beim ViewShell::Activate aus dem Reset2Open nicht die Handles anzeigen + //HMHbDisableHdl = sal_True; + pClient->DeactivateObject(); + //HMHbDisableHdl = sal_False; + // Image-Ole wieder durch Grafik ersetzen passiert jetzt in ScClient::UIActivate + } + + // Ole-Objekt selektiert? + + SdrOle2Obj* pOle2Obj = NULL; + SdrGrafObj* pGrafObj = NULL; + SdrMediaObj* pMediaObj = NULL; + + const SdrMarkList& rMarkList = GetMarkedObjectList(); + sal_uLong nMarkCount = rMarkList.GetMarkCount(); + + if ( nMarkCount == 0 && !pViewData->GetViewShell()->IsDrawSelMode() && !bInConstruct ) + { + // relock layers that may have been unlocked before + LockBackgroundLayer(); + LockInternalLayer(); + } + + sal_Bool bSubShellSet = sal_False; + if (nMarkCount == 1) + { + SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + if (pObj->GetObjIdentifier() == OBJ_OLE2) + { + pOle2Obj = (SdrOle2Obj*) pObj; + if (!pDoc->IsChart(pObj) ) + pViewSh->SetOleObjectShell(sal_True); + else + pViewSh->SetChartShell(sal_True); + bSubShellSet = sal_True; + } + else if (pObj->GetObjIdentifier() == OBJ_GRAF) + { + pGrafObj = (SdrGrafObj*) pObj; + pViewSh->SetGraphicShell(sal_True); + bSubShellSet = sal_True; + } + else if (pObj->GetObjIdentifier() == OBJ_MEDIA) + { + pMediaObj = (SdrMediaObj*) pObj; + pViewSh->SetMediaShell(sal_True); + bSubShellSet = sal_True; + } + else if (pObj->GetObjIdentifier() != OBJ_TEXT // Verhindern, das beim Anlegen + || !pViewSh->IsDrawTextShell()) // eines TextObjekts auf die + { // DrawShell umgeschaltet wird. + pViewSh->SetDrawShell(sal_True); //@#70206# + } + } + + if ( nMarkCount && !bSubShellSet ) + { + sal_Bool bOnlyControls = sal_True; + sal_Bool bOnlyGraf = sal_True; + for (sal_uLong i=0; i<nMarkCount; i++) + { + SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj(); + if ( pObj->ISA( SdrObjGroup ) ) + { + const SdrObjList *pLst = ((SdrObjGroup*)pObj)->GetSubList(); + sal_uLong nListCount = pLst->GetObjCount(); + if ( nListCount == 0 ) + { + // #104156# An empty group (may occur during Undo) is no control or graphics object. + // Creating the form shell during undo would lead to problems with the undo manager. + bOnlyControls = sal_False; + bOnlyGraf = sal_False; + } + for ( sal_uInt16 j = 0; j < nListCount; ++j ) + { + SdrObject *pSubObj = pLst->GetObj( j ); + + if (!pSubObj->ISA(SdrUnoObj)) + bOnlyControls = sal_False; + if (pSubObj->GetObjIdentifier() != OBJ_GRAF) + bOnlyGraf = sal_False; + + if ( !bOnlyControls && !bOnlyGraf ) break; + } + } + else + { + if (!pObj->ISA(SdrUnoObj)) + bOnlyControls = sal_False; + if (pObj->GetObjIdentifier() != OBJ_GRAF) + bOnlyGraf = sal_False; + } + + if ( !bOnlyControls && !bOnlyGraf ) break; + } + + if(bOnlyControls) + { + pViewSh->SetDrawFormShell(sal_True); // jetzt UNO-Controls + } + else if(bOnlyGraf) + { + pViewSh->SetGraphicShell(sal_True); + } + else if(nMarkCount>1) + { + pViewSh->SetDrawShell(sal_True); + } + } + + + + // Verben anpassen + + SfxViewFrame* pViewFrame = pViewSh->GetViewFrame(); + sal_Bool bOle = pViewSh->GetViewFrame()->GetFrame().IsInPlace(); + uno::Sequence< embed::VerbDescriptor > aVerbs; + if ( pOle2Obj && !bOle ) + { + uno::Reference < embed::XEmbeddedObject > xObj = pOle2Obj->GetObjRef(); + DBG_ASSERT( xObj.is(), "SdrOle2Obj ohne ObjRef" ); + if (xObj.is()) + aVerbs = xObj->getSupportedVerbs(); + } + pViewSh->SetVerbs( aVerbs ); + + // Image-Map Editor + + if ( pOle2Obj ) + UpdateIMap( pOle2Obj ); + else if ( pGrafObj ) + UpdateIMap( pGrafObj ); + + InvalidateAttribs(); // nach dem IMap-Editor Update + InvalidateDrawTextAttrs(); + + for(sal_uInt32 a(0L); a < PaintWindowCount(); a++) + { + SdrPaintWindow* pPaintWindow = GetPaintWindow(a); + OutputDevice& rOutDev = pPaintWindow->GetOutputDevice(); + + if(OUTDEV_WINDOW == rOutDev.GetOutDevType()) + { + ((Window&)rOutDev).Update(); + } + } + + // uno object for view returns drawing objects as selection, + // so it must notify its SelectionChangeListeners + + if (pViewFrame) + { + SfxFrame& rFrame = pViewFrame->GetFrame(); + uno::Reference<frame::XController> xController = rFrame.GetController(); + if (xController.is()) + { + ScTabViewObj* pImp = ScTabViewObj::getImplementation( xController ); + if (pImp) + pImp->SelectionChanged(); + } + } + + // update selection transfer object + + pViewSh->CheckSelectionTransfer(); + +} + +void __EXPORT ScDrawView::ModelHasChanged() +{ + SdrObject* pEditObj = GetTextEditObject(); + if ( pEditObj && !pEditObj->IsInserted() && pViewData ) + { + // #111700# SdrObjEditView::ModelHasChanged will end text edit in this case, + // so make sure the EditEngine's undo manager is no longer used. + pViewData->GetViewShell()->SetDrawTextUndo(NULL); + SetCreateMode(); // don't leave FuText in a funny state + } + + FmFormView::ModelHasChanged(); +} + +void __EXPORT ScDrawView::UpdateUserViewOptions() +{ + if (pViewData) + { + const ScViewOptions& rOpt = pViewData->GetOptions(); + const ScGridOptions& rGrid = rOpt.GetGridOptions(); + + sal_Bool bBigHdl = rOpt.GetOption( VOPT_BIGHANDLES ); + + SetDragStripes( rOpt.GetOption( VOPT_HELPLINES ) ); + SetSolidMarkHdl( rOpt.GetOption( VOPT_SOLIDHANDLES ) ); + SetMarkHdlSizePixel( bBigHdl ? SC_HANDLESIZE_BIG : SC_HANDLESIZE_SMALL ); + + SetGridVisible( rGrid.GetGridVisible() ); + SetSnapEnabled( rGrid.GetUseGridSnap() ); + SetGridSnap( rGrid.GetUseGridSnap() ); + + // Snap from grid options is no longer used +// SetSnapGrid( Size( rGrid.GetFldSnapX(), rGrid.GetFldSnapY() ) ); + + Fraction aFractX( rGrid.GetFldDrawX(), rGrid.GetFldDivisionX() + 1 ); + Fraction aFractY( rGrid.GetFldDrawY(), rGrid.GetFldDivisionY() + 1 ); + SetSnapGridWidth( aFractX, aFractY ); + + SetGridCoarse( Size( rGrid.GetFldDrawX(), rGrid.GetFldDrawY() ) ); + SetGridFine( Size( rGrid.GetFldDrawX() / (rGrid.GetFldDivisionX() + 1), + rGrid.GetFldDrawY() / (rGrid.GetFldDivisionY() + 1) ) ); + } +} + +#ifdef _MSC_VER +#pragma optimize ( "", on ) +#endif + +sal_Bool ScDrawView::SelectObject( const String& rName ) +{ + UnmarkAll(); + + SCTAB nObjectTab = 0; + SdrObject* pFound = NULL; + + SfxObjectShell* pShell = pDoc->GetDocumentShell(); + if (pShell) + { + SdrModel* pDrawLayer = GetModel(); + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB i=0; i<nTabCount && !pFound; i++) + { + SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(i)); + DBG_ASSERT(pPage,"Page ?"); + if (pPage) + { + SdrObjListIter aIter( *pPage, IM_DEEPWITHGROUPS ); + SdrObject* pObject = aIter.Next(); + while (pObject && !pFound) + { + if ( ScDrawLayer::GetVisibleName( pObject ) == rName ) + { + pFound = pObject; + nObjectTab = i; + } + pObject = aIter.Next(); + } + } + } + } + + if ( pFound ) + { + ScTabView* pView = pViewData->GetView(); + if ( nObjectTab != nTab ) // Tabelle umschalten + pView->SetTabNo( nObjectTab ); + + DBG_ASSERT( nTab == nObjectTab, "Tabellen umschalten hat nicht geklappt" ); + + pView->ScrollToObject( pFound ); + + /* #61585# To select an object on the background layer, the layer has to + be unlocked even if exclusive drawing selection mode is not active + (this is reversed in MarkListHasChanged when nothing is selected) */ + if ( pFound->GetLayer() == SC_LAYER_BACK && + !pViewData->GetViewShell()->IsDrawSelMode() && + !pDoc->IsTabProtected( nTab ) && + !pViewData->GetSfxDocShell()->IsReadOnly() ) + { + UnlockBackgroundLayer(); + } + + SdrPageView* pPV = GetSdrPageView(); + MarkObj( pFound, pPV ); + } + + return ( pFound != NULL ); +} + +//UNUSED2008-05 String ScDrawView::GetSelectedChartName() const +//UNUSED2008-05 { +//UNUSED2008-05 // used for modifying a chart's data area - PersistName must always be used +//UNUSED2008-05 // (as in ScDocument::FindChartData and UpdateChartArea) +//UNUSED2008-05 +//UNUSED2008-05 const SdrMarkList& rMarkList = GetMarkedObjectList(); +//UNUSED2008-05 if (rMarkList.GetMarkCount() == 1) +//UNUSED2008-05 { +//UNUSED2008-05 SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); +//UNUSED2008-05 if (pObj->GetObjIdentifier() == OBJ_OLE2) +//UNUSED2008-05 if ( pDoc->IsChart(pObj) ) +//UNUSED2008-05 return static_cast<SdrOle2Obj*>(pObj)->GetPersistName(); +//UNUSED2008-05 } +//UNUSED2008-05 +//UNUSED2008-05 return EMPTY_STRING; // nichts gefunden +//UNUSED2008-05 } + +FASTBOOL ScDrawView::InsertObjectSafe(SdrObject* pObj, SdrPageView& rPV, sal_uLong nOptions) +{ + // Markierung nicht aendern, wenn Ole-Objekt aktiv + // (bei Drop aus Ole-Objekt wuerde sonst mitten im ExecuteDrag deaktiviert!) + + if (pViewData) + { + SfxInPlaceClient* pClient = pViewData->GetViewShell()->GetIPClient(); + if ( pClient && pClient->IsObjectInPlaceActive() ) + nOptions |= SDRINSERT_DONTMARK; + } + + return InsertObjectAtView( pObj, rPV, nOptions ); +} + +SdrObject* ScDrawView::GetMarkedNoteCaption( ScDrawObjData** ppCaptData ) +{ + const SdrMarkList& rMarkList = GetMarkedObjectList(); + if( pViewData && (rMarkList.GetMarkCount() == 1) ) + { + SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj(); + if( ScDrawObjData* pCaptData = ScDrawLayer::GetNoteCaptionData( pObj, pViewData->GetTabNo() ) ) + { + if( ppCaptData ) *ppCaptData = pCaptData; + return pObj; + } + } + return 0; +} + +void ScDrawView::LockCalcLayer( SdrLayerID nLayer, bool bLock ) +{ + SdrLayer* pLockLayer = GetModel()->GetLayerAdmin().GetLayerPerID( nLayer ); + if( pLockLayer && (IsLayerLocked( pLockLayer->GetName() ) != bLock) ) + SetLayerLocked( pLockLayer->GetName(), bLock ); +} + +void __EXPORT ScDrawView::MakeVisible( const Rectangle& rRect, Window& rWin ) +{ + //! rWin richtig auswerten + //! ggf Zoom aendern + + if ( pViewData && pViewData->GetActiveWin() == &rWin ) + pViewData->GetView()->MakeVisible( rRect ); +} + +void ScDrawView::DeleteMarked() +{ + // try to delete a note caption object with its cell note in the Calc document + ScDrawObjData* pCaptData = 0; + if( SdrObject* pCaptObj = GetMarkedNoteCaption( &pCaptData ) ) + { + (void)pCaptObj; // prevent 'unused variable' compiler warning in pro builds + ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer(); + ScDocShell* pDocShell = pViewData ? pViewData->GetDocShell() : 0; + ::svl::IUndoManager* pUndoMgr = pDocShell ? pDocShell->GetUndoManager() : 0; + bool bUndo = pDrawLayer && pDocShell && pUndoMgr && pDoc->IsUndoEnabled(); + + // remove the cell note from document, we are its owner now + ScPostIt* pNote = pDoc->ReleaseNote( pCaptData->maStart ); + DBG_ASSERT( pNote, "ScDrawView::DeleteMarked - cell note missing in document" ); + if( pNote ) + { + // rescue note data for undo (with pointer to caption object) + ScNoteData aNoteData = pNote->GetNoteData(); + DBG_ASSERT( aNoteData.mpCaption == pCaptObj, "ScDrawView::DeleteMarked - caption object does not match" ); + // collect the drawing undo action created while deleting the note + if( bUndo ) + pDrawLayer->BeginCalcUndo(); + // delete the note (already removed from document above) + delete pNote; + // add the undo action for the note + if( bUndo ) + pUndoMgr->AddUndoAction( new ScUndoReplaceNote( *pDocShell, pCaptData->maStart, aNoteData, false, pDrawLayer->GetCalcUndo() ) ); + // repaint the cell to get rid of the note marker + if( pDocShell ) + pDocShell->PostPaintCell( pCaptData->maStart ); + // done, return now to skip call of FmFormView::DeleteMarked() + return; + } + } + + FmFormView::DeleteMarked(); +} + +SdrEndTextEditKind ScDrawView::ScEndTextEdit() +{ + sal_Bool bIsTextEdit = IsTextEdit(); + SdrEndTextEditKind eKind = SdrEndTextEdit(); + + if ( bIsTextEdit && pViewData ) + pViewData->GetViewShell()->SetDrawTextUndo(NULL); // "normaler" Undo-Manager + + return eKind; +} + +void ScDrawView::MarkDropObj( SdrObject* pObj ) +{ + if ( pDropMarkObj != pObj ) + { + pDropMarkObj = pObj; + ImplClearCalcDropMarker(); + + if(pDropMarkObj) + { + pDropMarker = new SdrDropMarkerOverlay(*this, *pDropMarkObj); + } + } +} + +//UNUSED2009-05 void ScDrawView::CaptionTextDirection( sal_uInt16 nSlot ) +//UNUSED2009-05 { +//UNUSED2009-05 if(nSlot != SID_TEXTDIRECTION_LEFT_TO_RIGHT && nSlot != SID_TEXTDIRECTION_TOP_TO_BOTTOM) +//UNUSED2009-05 return; +//UNUSED2009-05 +//UNUSED2009-05 SdrObject* pObject = GetTextEditObject(); +//UNUSED2009-05 if ( ScDrawLayer::IsNoteCaption( pObject ) ) +//UNUSED2009-05 { +//UNUSED2009-05 if( SdrCaptionObj* pCaption = dynamic_cast< SdrCaptionObj* >( pObject ) ) +//UNUSED2009-05 { +//UNUSED2009-05 SfxItemSet aAttr(pCaption->GetMergedItemSet()); +//UNUSED2009-05 aAttr.Put( SvxWritingModeItem( +//UNUSED2009-05 nSlot == SID_TEXTDIRECTION_LEFT_TO_RIGHT ? +//UNUSED2009-05 com::sun::star::text::WritingMode_LR_TB : com::sun::star::text::WritingMode_TB_RL, +//UNUSED2009-05 SDRATTR_TEXTDIRECTION ) ); +//UNUSED2009-05 pCaption->SetMergedItemSet(aAttr); +//UNUSED2009-05 FuPoor* pPoor = pViewData->GetView()->GetDrawFuncPtr(); +//UNUSED2009-05 if ( pPoor ) +//UNUSED2009-05 { +//UNUSED2009-05 FuText* pText = static_cast<FuText*>(pPoor); +//UNUSED2009-05 pText->StopEditMode(sal_True); +//UNUSED2009-05 } +//UNUSED2009-05 } +//UNUSED2009-05 } +//UNUSED2009-05 } diff --git a/sc/source/ui/view/editsh.cxx b/sc/source/ui/view/editsh.cxx new file mode 100644 index 000000000000..e07e15267198 --- /dev/null +++ b/sc/source/ui/view/editsh.cxx @@ -0,0 +1,1206 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +//------------------------------------------------------------------ + +#include <com/sun/star/linguistic2/XThesaurus.hpp> + +#include "scitems.hxx" +#include <editeng/eeitem.hxx> + +#include <svx/clipfmtitem.hxx> +#include <svx/svxdlg.hxx> +#include <editeng/cntritem.hxx> +#include <editeng/outliner.hxx> +#include <editeng/unolingu.hxx> +#include <editeng/crsditem.hxx> +#include <editeng/editeng.hxx> +#include <editeng/editview.hxx> +#include <editeng/escpitem.hxx> +#include <editeng/flditem.hxx> +#include <editeng/fontitem.hxx> +#include <svx/hlnkitem.hxx> +#include <editeng/postitem.hxx> +#include <editeng/scripttypeitem.hxx> +#include <editeng/shdditem.hxx> +#include <svl/srchitem.hxx> +#include <editeng/udlnitem.hxx> +#include <editeng/wghtitem.hxx> +#include <sfx2/basedlgs.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/msg.hxx> +#include <sfx2/objface.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/request.hxx> +#include <sfx2/viewfrm.hxx> +#include <sot/exchange.hxx> +#include <svtools/cliplistener.hxx> +#include <svl/whiter.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/sound.hxx> +#include <sot/formats.hxx> +#include <svtools/transfer.hxx> +#include <svl/stritem.hxx> + +#define _EDITSH_CXX +#include "editsh.hxx" + +#include "scresid.hxx" +#include "global.hxx" +#include "sc.hrc" +#include "scmod.hxx" +#include "inputhdl.hxx" +#include "viewutil.hxx" +#include "viewdata.hxx" +#include "document.hxx" +//CHINA001 #include "namepast.hxx" +#include "reffind.hxx" +#include "tabvwsh.hxx" +//CHINA001 #include "textdlgs.hxx" +#include "editutil.hxx" +#include "globstr.hrc" + +#define ScEditShell +#include "scslots.hxx" + +#include "scui_def.hxx" //CHINA001 +#include "scabstdlg.hxx" //CHINA001 + + +using namespace ::com::sun::star; + + +TYPEINIT1( ScEditShell, SfxShell ); + +SFX_IMPL_INTERFACE(ScEditShell, SfxShell, ScResId(SCSTR_EDITSHELL)) +{ + SFX_POPUPMENU_REGISTRATION( ScResId(RID_POPUP_EDIT) ); +} + + +ScEditShell::ScEditShell(EditView* pView, ScViewData* pData) : + pEditView (pView), + pViewData (pData), + pClipEvtLstnr (NULL), + bPastePossible (sal_False), + bIsInsertMode (sal_True) +{ + SetPool( pEditView->GetEditEngine()->GetEmptyItemSet().GetPool() ); + SetUndoManager( &pEditView->GetEditEngine()->GetUndoManager() ); + SetName(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("EditCell"))); +} + +ScEditShell::~ScEditShell() +{ + if ( pClipEvtLstnr ) + { + pClipEvtLstnr->AddRemoveListener( pViewData->GetActiveWin(), sal_False ); + + // #122057# The listener may just now be waiting for the SolarMutex and call the link + // afterwards, in spite of RemoveListener. So the link has to be reset, too. + pClipEvtLstnr->ClearCallbackLink(); + + pClipEvtLstnr->release(); + } +} + +ScInputHandler* ScEditShell::GetMyInputHdl() +{ + return SC_MOD()->GetInputHdl( pViewData->GetViewShell() ); +} + +void ScEditShell::SetEditView(EditView* pView) +{ + pEditView = pView; + pEditView->SetInsertMode( bIsInsertMode ); + SetPool( pEditView->GetEditEngine()->GetEmptyItemSet().GetPool() ); + SetUndoManager( &pEditView->GetEditEngine()->GetUndoManager() ); +} + +void lcl_RemoveAttribs( EditView& rEditView ) +{ + ScEditEngineDefaulter* pEngine = static_cast<ScEditEngineDefaulter*>(rEditView.GetEditEngine()); + + sal_Bool bOld = pEngine->GetUpdateMode(); + pEngine->SetUpdateMode(sal_False); + + String aName = ScGlobal::GetRscString( STR_UNDO_DELETECONTENTS ); + pEngine->GetUndoManager().EnterListAction( aName, aName ); + + rEditView.RemoveAttribs(sal_True); + pEngine->RepeatDefaults(); // #97226# paragraph attributes from cell formats must be preserved + + pEngine->GetUndoManager().LeaveListAction(); + + pEngine->SetUpdateMode(bOld); +} + +void lclInsertCharacter( EditView* pTableView, EditView* pTopView, sal_Unicode cChar ) +{ + String aString( cChar ); + if( pTableView ) + pTableView->InsertText( aString ); + if( pTopView ) + pTopView->InsertText( aString ); +} + +void ScEditShell::Execute( SfxRequest& rReq ) +{ + const SfxItemSet* pReqArgs = rReq.GetArgs(); + sal_uInt16 nSlot = rReq.GetSlot(); + SfxBindings& rBindings = pViewData->GetBindings(); + + ScInputHandler* pHdl = GetMyInputHdl(); + DBG_ASSERT(pHdl,"kein ScInputHandler"); + + EditView* pTopView = pHdl->GetTopView(); // hat Eingabezeile den Focus? + EditView* pTableView = pHdl->GetTableView(); + + DBG_ASSERT(pTableView,"no EditView :-("); + /* #i91683# No EditView if spell-check dialog is active and positioned on + * an error and user immediately (without double click or F2) selected a + * text portion of that cell with the mouse and wanted to modify it. */ + /* FIXME: Bailing out only cures the symptom and prevents a crash, no edit + * action is possible. A real fix somehow would need to create a valid + * EditView from the spell-check view. */ + if (!pTableView) + return; + + EditEngine* pEngine = pTableView->GetEditEngine(); + + pHdl->DataChanging(); + sal_Bool bSetSelIsRef = sal_False; + + switch ( nSlot ) + { + case FID_INS_CELL_CONTENTS: // Insert-Taste, weil als Acc definiert + bIsInsertMode = !pTableView->IsInsertMode(); + pTableView->SetInsertMode( bIsInsertMode ); + if (pTopView) + pTopView->SetInsertMode( bIsInsertMode ); + rBindings.Invalidate( SID_ATTR_INSERT ); + break; + + case SID_ATTR_INSERT: + if ( pReqArgs ) + { + bIsInsertMode = ((const SfxBoolItem&)pReqArgs->Get(nSlot)).GetValue(); + pTableView->SetInsertMode( bIsInsertMode ); + if (pTopView) + pTopView->SetInsertMode( bIsInsertMode ); + rBindings.Invalidate( SID_ATTR_INSERT ); + } + break; + + case SID_THES: + { + String aReplaceText; + SFX_REQUEST_ARG( rReq, pItem2, SfxStringItem, SID_THES , sal_False ); + if (pItem2) + aReplaceText = pItem2->GetValue(); + if (aReplaceText.Len() > 0) + ReplaceTextWithSynonym( *pEditView, aReplaceText ); + } + break; + + case SID_COPY: + pTableView->Copy(); + break; + + case SID_CUT: + pTableView->Cut(); + if (pTopView) + pTopView->DeleteSelected(); + break; + + case SID_PASTE: + pTableView->PasteSpecial(); + if (pTopView) + pTopView->Paste(); + break; + + case SID_DELETE: + pTableView->DeleteSelected(); + if (pTopView) + pTopView->DeleteSelected(); + break; + + case SID_CELL_FORMAT_RESET: // "Standard" + lcl_RemoveAttribs( *pTableView ); + if ( pTopView ) + lcl_RemoveAttribs( *pTopView ); + break; + + case SID_CLIPBOARD_FORMAT_ITEMS: + { + sal_uLong nFormat = 0; + const SfxPoolItem* pItem; + if ( pReqArgs && + pReqArgs->GetItemState(nSlot, sal_True, &pItem) == SFX_ITEM_SET && + pItem->ISA(SfxUInt32Item) ) + { + nFormat = ((const SfxUInt32Item*)pItem)->GetValue(); + } + + if ( nFormat ) + { + if (SOT_FORMAT_STRING == nFormat) + pTableView->Paste(); + else + pTableView->PasteSpecial(); + + if (pTopView) + pTopView->Paste(); + } + } + break; + + case SID_PASTE_SPECIAL: + { + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + SfxAbstractPasteDialog* pDlg = pFact->CreatePasteDialog( pViewData->GetDialogParent() ); + sal_uLong nFormat = 0; + if ( pDlg ) + { + pDlg->Insert( SOT_FORMAT_STRING, EMPTY_STRING ); + pDlg->Insert( SOT_FORMAT_RTF, EMPTY_STRING ); + + TransferableDataHelper aDataHelper( + TransferableDataHelper::CreateFromSystemClipboard( pViewData->GetActiveWin() ) ); + + nFormat = pDlg->GetFormat( aDataHelper.GetTransferable() ); + DELETEZ(pDlg); + } + + // while the dialog was open, edit mode may have been stopped + if (!SC_MOD()->IsInputMode()) + { + Sound::Beep(); + return; + } + + if (nFormat > 0) + { + if (SOT_FORMAT_STRING == nFormat) + pTableView->Paste(); + else + pTableView->PasteSpecial(); + + if (pTopView) + pTopView->Paste(); + } + + if (pTopView) + pTopView->GetWindow()->GrabFocus(); + } + break; + + case SID_SELECTALL: + { + sal_uInt16 nPar = pEngine->GetParagraphCount(); + if (nPar) + { + xub_StrLen nLen = pEngine->GetTextLen(nPar-1); + pTableView->SetSelection(ESelection(0,0,nPar-1,nLen)); + if (pTopView) + pTopView->SetSelection(ESelection(0,0,nPar-1,nLen)); + } + } + break; + + case SID_CHARMAP: + { + sal_uInt16 nScript = pTableView->GetSelectedScriptType(); + sal_uInt16 nFontWhich = ( nScript == SCRIPTTYPE_ASIAN ) ? EE_CHAR_FONTINFO_CJK : + ( ( nScript == SCRIPTTYPE_COMPLEX ) ? EE_CHAR_FONTINFO_CTL : + EE_CHAR_FONTINFO ); + const SvxFontItem& rItem = (const SvxFontItem&) + pTableView->GetAttribs().Get(nFontWhich); + + String aString; + SvxFontItem aNewItem( EE_CHAR_FONTINFO ); + + const SfxItemSet *pArgs = rReq.GetArgs(); + const SfxPoolItem* pItem = 0; + if( pArgs ) + pArgs->GetItemState(GetPool().GetWhich(SID_CHARMAP), sal_False, &pItem); + + if ( pItem ) + { + aString = ((const SfxStringItem*)pItem)->GetValue(); + const SfxPoolItem* pFtItem = NULL; + pArgs->GetItemState( GetPool().GetWhich(SID_ATTR_SPECIALCHAR), sal_False, &pFtItem); + const SfxStringItem* pFontItem = PTR_CAST( SfxStringItem, pFtItem ); + if ( pFontItem ) + { + String aFontName(pFontItem->GetValue()); + Font aFont(aFontName, Size(1,1)); // Size nur wg. CTOR + aNewItem = SvxFontItem( aFont.GetFamily(), aFont.GetName(), + aFont.GetStyleName(), aFont.GetPitch(), + aFont.GetCharSet(), ATTR_FONT ); + } + else + aNewItem = rItem; + } + else + { + ScViewUtil::ExecuteCharMap( rItem, *pViewData->GetViewShell()->GetViewFrame(), aNewItem, aString ); + + // while the dialog was open, edit mode may have been stopped + if (!SC_MOD()->IsInputMode()) + { + Sound::Beep(); + return; + } + } + + if ( aString.Len() ) + { + // if string contains WEAK characters, set all fonts + sal_uInt8 nSetScript; + ScDocument* pDoc = pViewData->GetDocument(); + if ( pDoc->HasStringWeakCharacters( aString ) ) + nSetScript = SCRIPTTYPE_LATIN | SCRIPTTYPE_ASIAN | SCRIPTTYPE_COMPLEX; + else + nSetScript = pDoc->GetStringScriptType( aString ); + + SfxItemSet aSet( pTableView->GetEmptyItemSet() ); + SvxScriptSetItem aSetItem( SID_ATTR_CHAR_FONT, GetPool() ); + aSetItem.PutItemForScriptType( nSetScript, aNewItem ); + aSet.Put( aSetItem.GetItemSet(), sal_False ); + + // SetAttribs an der View selektiert ein Wort, wenn nichts selektiert ist + pTableView->GetEditEngine()->QuickSetAttribs( aSet, pTableView->GetSelection() ); + pTableView->InsertText(aString); + if (pTopView) + pTopView->InsertText(aString); + + SfxStringItem aStringItem( SID_CHARMAP, aString ); + SfxStringItem aFontItem( SID_ATTR_SPECIALCHAR, aNewItem.GetFamilyName() ); + rReq.AppendItem( aFontItem ); + rReq.AppendItem( aStringItem ); + rReq.Done(); + + + } + + if (pTopView) + pTopView->GetWindow()->GrabFocus(); + } + break; + + case FID_INSERT_NAME: + { + ScDocument* pDoc = pViewData->GetDocument(); + //CHINA001 ScNamePasteDlg* pDlg = new ScNamePasteDlg( pViewData->GetDialogParent(), + //CHINA001 pDoc->GetRangeName(), sal_False ); + // "Liste" disablen + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + AbstractScNamePasteDlg* pDlg = pFact->CreateScNamePasteDlg( pViewData->GetDialogParent(), pDoc->GetRangeName(), RID_SCDLG_NAMES_PASTE, sal_False ); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + short nRet = pDlg->Execute(); + // pDlg is needed below + + // while the dialog was open, edit mode may have been stopped + if (!SC_MOD()->IsInputMode()) + { + Sound::Beep(); + delete pDlg; + return; + } + + if ( nRet == BTN_PASTE_NAME ) + { + String aName = pDlg->GetSelectedName(); + pTableView->InsertText(aName); + if (pTopView) + pTopView->InsertText(aName); + } + delete pDlg; + + if (pTopView) + pTopView->GetWindow()->GrabFocus(); + } + break; + + case SID_CHAR_DLG: + { + SfxItemSet aAttrs( pTableView->GetAttribs() ); + + SfxObjectShell* pObjSh = pViewData->GetSfxDocShell(); + + //CHINA001 ScCharDlg* pDlg = new ScCharDlg( pViewData->GetDialogParent(), &aAttrs, pObjSh ); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + SfxAbstractTabDialog* pDlg = pFact->CreateScCharDlg( pViewData->GetDialogParent(), &aAttrs, + pObjSh, RID_SCDLG_CHAR ); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + short nRet = pDlg->Execute(); + // pDlg is needed below + + // while the dialog was open, edit mode may have been stopped + if (!SC_MOD()->IsInputMode()) + { + Sound::Beep(); + delete pDlg; + return; + } + + if ( nRet == RET_OK ) + { + const SfxItemSet* pOut = pDlg->GetOutputItemSet(); + pTableView->SetAttribs( *pOut ); + } + delete pDlg; + } + break; + + case SID_TOGGLE_REL: + { + sal_Bool bOk = sal_False; + if (pEngine->GetParagraphCount() == 1) + { + String aText = pEngine->GetText(); + ESelection aSel = pEditView->GetSelection(); // aktuelle View + + ScRefFinder aFinder( aText, pViewData->GetDocument() ); + aFinder.ToggleRel( aSel.nStartPos, aSel.nEndPos ); + if (aFinder.GetFound()) + { + String aNew = aFinder.GetText(); + ESelection aNewSel( 0,aFinder.GetSelStart(), 0,aFinder.GetSelEnd() ); + pEngine->SetText( aNew ); + pTableView->SetSelection( aNewSel ); + if ( pTopView ) + { + pTopView->GetEditEngine()->SetText( aNew ); + pTopView->SetSelection( aNewSel ); + } + bOk = sal_True; + + // Referenz wird selektiert -> beim Tippen nicht ueberschreiben + bSetSelIsRef = sal_True; + } + } + if (!bOk) + Sound::Beep(); // keine Referenzen oder mehrere Absaetze + } + break; + + case SID_HYPERLINK_SETLINK: + if( pReqArgs ) + { + const SfxPoolItem* pItem; + if ( pReqArgs->GetItemState( SID_HYPERLINK_SETLINK, sal_True, &pItem ) == SFX_ITEM_SET ) + { + const SvxHyperlinkItem* pHyper = (const SvxHyperlinkItem*) pItem; + const String& rName = pHyper->GetName(); + const String& rURL = pHyper->GetURL(); + const String& rTarget = pHyper->GetTargetFrame(); + SvxLinkInsertMode eMode = pHyper->GetInsertMode(); + + sal_Bool bDone = sal_False; + if ( eMode == HLINK_DEFAULT || eMode == HLINK_FIELD ) + { + const SvxURLField* pURLField = GetURLField(); + if ( pURLField ) + { + // altes Feld selektieren + + ESelection aSel = pTableView->GetSelection(); + aSel.Adjust(); + aSel.nEndPara = aSel.nStartPara; + aSel.nEndPos = aSel.nStartPos + 1; + pTableView->SetSelection( aSel ); + + // neues Feld einfuegen + + SvxURLField aURLField( rURL, rName, SVXURLFORMAT_REPR ); + aURLField.SetTargetFrame( rTarget ); + SvxFieldItem aURLItem( aURLField, EE_FEATURE_FIELD ); + pTableView->InsertField( aURLItem ); + pTableView->SetSelection( aSel ); // select inserted field + + // #57254# jetzt doch auch Felder in der Top-View + + if ( pTopView ) + { + aSel = pTopView->GetSelection(); + aSel.nEndPara = aSel.nStartPara; + aSel.nEndPos = aSel.nStartPos + 1; + pTopView->SetSelection( aSel ); + pTopView->InsertField( aURLItem ); + pTopView->SetSelection( aSel ); // select inserted field + } + + bDone = sal_True; + } + } + + if (!bDone) + { + pViewData->GetViewShell()-> + InsertURL( rName, rURL, rTarget, (sal_uInt16) eMode ); + + // InsertURL an der ViewShell schaltet bei "Button" + // die EditShell ab, darum sofort return + + return; + } + } + } + break; + + case SID_OPEN_HYPERLINK: + { + const SvxURLField* pURLField = GetURLField(); + if ( pURLField ) + ScGlobal::OpenURL( pURLField->GetURL(), pURLField->GetTargetFrame() ); + return; + } + //break; + + case FN_INSERT_SOFT_HYPHEN: + lclInsertCharacter( pTableView, pTopView, CHAR_SHY ); + break; + case FN_INSERT_HARDHYPHEN: + lclInsertCharacter( pTableView, pTopView, CHAR_NBHY ); + break; + case FN_INSERT_HARD_SPACE: + lclInsertCharacter( pTableView, pTopView, CHAR_NBSP ); + break; + case SID_INSERT_RLM: + lclInsertCharacter( pTableView, pTopView, CHAR_RLM ); + break; + case SID_INSERT_LRM: + lclInsertCharacter( pTableView, pTopView, CHAR_LRM ); + break; + case SID_INSERT_ZWSP: + lclInsertCharacter( pTableView, pTopView, CHAR_ZWSP ); + break; + case SID_INSERT_ZWNBSP: + lclInsertCharacter( pTableView, pTopView, CHAR_ZWNBSP ); + break; + } + + pHdl->DataChanged(); + if (bSetSelIsRef) + pHdl->SetSelIsRef(sal_True); +} + +void lcl_DisableAll( SfxItemSet& rSet ) // disable all slots +{ + SfxWhichIter aIter( rSet ); + sal_uInt16 nWhich = aIter.FirstWhich(); + while (nWhich) + { + rSet.DisableItem( nWhich ); + nWhich = aIter.NextWhich(); + } +} + +void __EXPORT ScEditShell::GetState( SfxItemSet& rSet ) +{ + // #125326# When deactivating the view, edit mode is stopped, but the EditShell is left active + // (a shell can't be removed from within Deactivate). In that state, the EditView isn't inserted + // into the EditEngine, so it can have an invalid selection and must not be used. + if ( !pViewData->HasEditView( pViewData->GetActivePart() ) ) + { + lcl_DisableAll( rSet ); + return; + } + + ScInputHandler* pHdl = GetMyInputHdl(); + EditView* pActiveView = pHdl ? pHdl->GetActiveView() : pEditView; + + SfxWhichIter aIter( rSet ); + sal_uInt16 nWhich = aIter.FirstWhich(); + while (nWhich) + { + switch (nWhich) + { + case SID_ATTR_INSERT: // Statuszeile + { + if ( pActiveView ) + rSet.Put( SfxBoolItem( nWhich, pActiveView->IsInsertMode() ) ); + else + rSet.Put( SfxBoolItem( nWhich, 42 ) ); + } + break; + + case SID_HYPERLINK_GETLINK: + { + SvxHyperlinkItem aHLinkItem; + const SvxURLField* pURLField = GetURLField(); + if ( pURLField ) + { + aHLinkItem.SetName( pURLField->GetRepresentation() ); + aHLinkItem.SetURL( pURLField->GetURL() ); + aHLinkItem.SetTargetFrame( pURLField->GetTargetFrame() ); + } + else if ( pActiveView ) + { + // use selected text as name for urls + String sReturn = pActiveView->GetSelected(); + sReturn.Erase(255); + sReturn.EraseTrailingChars(); + aHLinkItem.SetName(sReturn); + } + rSet.Put(aHLinkItem); + } + break; + + case SID_OPEN_HYPERLINK: + { + if ( !GetURLField() ) + rSet.DisableItem( nWhich ); + } + break; + + case SID_TRANSLITERATE_HALFWIDTH: + case SID_TRANSLITERATE_FULLWIDTH: + case SID_TRANSLITERATE_HIRAGANA: + case SID_TRANSLITERATE_KATAGANA: + case SID_INSERT_RLM: + case SID_INSERT_LRM: + case SID_INSERT_ZWNBSP: + case SID_INSERT_ZWSP: + ScViewUtil::HideDisabledSlot( rSet, pViewData->GetBindings(), nWhich ); + break; + + case SID_THES: + { + String aStatusVal; + LanguageType nLang = LANGUAGE_NONE; + bool bIsLookUpWord = GetStatusValueForThesaurusFromContext( aStatusVal, nLang, *pActiveView ); + rSet.Put( SfxStringItem( SID_THES, aStatusVal ) ); + + // disable thesaurus context menu entry if there is nothing to look up + sal_Bool bCanDoThesaurus = ScModule::HasThesaurusLanguage( nLang ); + if (!bIsLookUpWord || !bCanDoThesaurus) + rSet.DisableItem( SID_THES ); + } + break; + + + } + nWhich = aIter.NextWhich(); + } +} + +const SvxURLField* ScEditShell::GetURLField() +{ + ScInputHandler* pHdl = GetMyInputHdl(); + EditView* pActiveView = pHdl ? pHdl->GetActiveView() : pEditView; + if ( pActiveView ) + { + const SvxFieldItem* pFieldItem = pActiveView->GetFieldAtSelection(); + if (pFieldItem) + { + const SvxFieldData* pField = pFieldItem->GetField(); + if ( pField && pField->ISA(SvxURLField) ) + return (const SvxURLField*)pField; + } + } + + return NULL; +} + +IMPL_LINK( ScEditShell, ClipboardChanged, TransferableDataHelper*, pDataHelper ) +{ + if ( pDataHelper ) + { + bPastePossible = ( pDataHelper->HasFormat( SOT_FORMAT_STRING ) || pDataHelper->HasFormat( SOT_FORMAT_RTF ) ); + + SfxBindings& rBindings = pViewData->GetBindings(); + rBindings.Invalidate( SID_PASTE ); + rBindings.Invalidate( SID_PASTE_SPECIAL ); + rBindings.Invalidate( SID_CLIPBOARD_FORMAT_ITEMS ); + } + return 0; +} + +void __EXPORT ScEditShell::GetClipState( SfxItemSet& rSet ) +{ + if ( !pClipEvtLstnr ) + { + // create listener + pClipEvtLstnr = new TransferableClipboardListener( LINK( this, ScEditShell, ClipboardChanged ) ); + pClipEvtLstnr->acquire(); + Window* pWin = pViewData->GetActiveWin(); + pClipEvtLstnr->AddRemoveListener( pWin, sal_True ); + + // get initial state + TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pViewData->GetActiveWin() ) ); + bPastePossible = ( aDataHelper.HasFormat( SOT_FORMAT_STRING ) || aDataHelper.HasFormat( SOT_FORMAT_RTF ) ); + } + + SfxWhichIter aIter( rSet ); + sal_uInt16 nWhich = aIter.FirstWhich(); + while (nWhich) + { + switch (nWhich) + { + case SID_PASTE: + case SID_PASTE_SPECIAL: + if( !bPastePossible ) + rSet.DisableItem( nWhich ); + break; + case SID_CLIPBOARD_FORMAT_ITEMS: + if( bPastePossible ) + { + SvxClipboardFmtItem aFormats( SID_CLIPBOARD_FORMAT_ITEMS ); + TransferableDataHelper aDataHelper( + TransferableDataHelper::CreateFromSystemClipboard( pViewData->GetActiveWin() ) ); + + if ( aDataHelper.HasFormat( SOT_FORMAT_STRING ) ) + aFormats.AddClipbrdFormat( SOT_FORMAT_STRING ); + if ( aDataHelper.HasFormat( SOT_FORMAT_RTF ) ) + aFormats.AddClipbrdFormat( SOT_FORMAT_RTF ); + + rSet.Put( aFormats ); + } + else + rSet.DisableItem( nWhich ); + break; + } + nWhich = aIter.NextWhich(); + } +} + +void lcl_InvalidateUnder( SfxBindings& rBindings ) +{ + rBindings.Invalidate( SID_ATTR_CHAR_UNDERLINE ); + rBindings.Invalidate( SID_ULINE_VAL_NONE ); + rBindings.Invalidate( SID_ULINE_VAL_SINGLE ); + rBindings.Invalidate( SID_ULINE_VAL_DOUBLE ); + rBindings.Invalidate( SID_ULINE_VAL_DOTTED ); +} + +void ScEditShell::ExecuteAttr(SfxRequest& rReq) +{ + SfxItemSet aSet( pEditView->GetEmptyItemSet() ); + SfxBindings& rBindings = pViewData->GetBindings(); + const SfxItemSet* pArgs = rReq.GetArgs(); + sal_uInt16 nSlot = rReq.GetSlot(); + + switch ( nSlot ) + { + case SID_ATTR_CHAR_FONTHEIGHT: + case SID_ATTR_CHAR_FONT: + { + if (pArgs) + { + // #i78017 establish the same behaviour as in Writer + sal_uInt16 nScript = SCRIPTTYPE_LATIN | SCRIPTTYPE_ASIAN | SCRIPTTYPE_COMPLEX; + if (nSlot == SID_ATTR_CHAR_FONT) + { + nScript = pEditView->GetSelectedScriptType(); + if (nScript == 0) nScript = ScGlobal::GetDefaultScriptType(); + } + + SfxItemPool& rPool = GetPool(); + SvxScriptSetItem aSetItem( nSlot, rPool ); + sal_uInt16 nWhich = rPool.GetWhich( nSlot ); + aSetItem.PutItemForScriptType( nScript, pArgs->Get( nWhich ) ); + + aSet.Put( aSetItem.GetItemSet(), sal_False ); + } + } + break; + + case SID_ATTR_CHAR_COLOR: + { + if (pArgs) + { + aSet.Put( pArgs->Get( pArgs->GetPool()->GetWhich( nSlot ) ) ); + rBindings.Invalidate( nSlot ); + } + } + break; + + // Toggles + + case SID_ATTR_CHAR_WEIGHT: + { + // #i78017 establish the same behaviour as in Writer + sal_uInt16 nScript = SCRIPTTYPE_LATIN | SCRIPTTYPE_ASIAN | SCRIPTTYPE_COMPLEX; + + SfxItemPool& rPool = GetPool(); + + sal_Bool bOld = sal_False; + SvxScriptSetItem aOldSetItem( nSlot, rPool ); + aOldSetItem.GetItemSet().Put( pEditView->GetAttribs(), sal_False ); + const SfxPoolItem* pCore = aOldSetItem.GetItemOfScript( nScript ); + if ( pCore && ((const SvxWeightItem*)pCore)->GetWeight() > WEIGHT_NORMAL ) + bOld = sal_True; + + SvxScriptSetItem aSetItem( nSlot, rPool ); + aSetItem.PutItemForScriptType( nScript, + SvxWeightItem( bOld ? WEIGHT_NORMAL : WEIGHT_BOLD, EE_CHAR_WEIGHT ) ); + aSet.Put( aSetItem.GetItemSet(), sal_False ); + + rBindings.Invalidate( nSlot ); + } + break; + + case SID_ATTR_CHAR_POSTURE: + { + // #i78017 establish the same behaviour as in Writer + sal_uInt16 nScript = SCRIPTTYPE_LATIN | SCRIPTTYPE_ASIAN | SCRIPTTYPE_COMPLEX; + + SfxItemPool& rPool = GetPool(); + + sal_Bool bOld = sal_False; + SvxScriptSetItem aOldSetItem( nSlot, rPool ); + aOldSetItem.GetItemSet().Put( pEditView->GetAttribs(), sal_False ); + const SfxPoolItem* pCore = aOldSetItem.GetItemOfScript( nScript ); + if ( pCore && ((const SvxPostureItem*)pCore)->GetValue() != ITALIC_NONE ) + bOld = sal_True; + + SvxScriptSetItem aSetItem( nSlot, rPool ); + aSetItem.PutItemForScriptType( nScript, + SvxPostureItem( bOld ? ITALIC_NONE : ITALIC_NORMAL, EE_CHAR_ITALIC ) ); + aSet.Put( aSetItem.GetItemSet(), sal_False ); + + rBindings.Invalidate( nSlot ); + } + break; + + case SID_ULINE_VAL_NONE: + aSet.Put( SvxUnderlineItem( UNDERLINE_NONE, EE_CHAR_UNDERLINE ) ); + lcl_InvalidateUnder( rBindings ); + break; + + case SID_ATTR_CHAR_UNDERLINE: // Toggles + case SID_ULINE_VAL_SINGLE: + case SID_ULINE_VAL_DOUBLE: + case SID_ULINE_VAL_DOTTED: + { + FontUnderline eOld = ((const SvxUnderlineItem&) pEditView-> + GetAttribs().Get(EE_CHAR_UNDERLINE)).GetLineStyle(); + FontUnderline eNew = eOld; + switch (nSlot) + { + case SID_ATTR_CHAR_UNDERLINE: + eNew = ( eOld != UNDERLINE_NONE ) ? UNDERLINE_NONE : UNDERLINE_SINGLE; + break; + case SID_ULINE_VAL_SINGLE: + eNew = ( eOld == UNDERLINE_SINGLE ) ? UNDERLINE_NONE : UNDERLINE_SINGLE; + break; + case SID_ULINE_VAL_DOUBLE: + eNew = ( eOld == UNDERLINE_DOUBLE ) ? UNDERLINE_NONE : UNDERLINE_DOUBLE; + break; + case SID_ULINE_VAL_DOTTED: + eNew = ( eOld == UNDERLINE_DOTTED ) ? UNDERLINE_NONE : UNDERLINE_DOTTED; + break; + } + aSet.Put( SvxUnderlineItem( eNew, EE_CHAR_UNDERLINE ) ); + lcl_InvalidateUnder( rBindings ); + } + break; + + case SID_ATTR_CHAR_OVERLINE: + { + FontUnderline eOld = ((const SvxOverlineItem&) pEditView-> + GetAttribs().Get(EE_CHAR_OVERLINE)).GetLineStyle(); + FontUnderline eNew = ( eOld != UNDERLINE_NONE ) ? UNDERLINE_NONE : UNDERLINE_SINGLE; + aSet.Put( SvxOverlineItem( eNew, EE_CHAR_OVERLINE ) ); + rBindings.Invalidate( nSlot ); + } + break; + + case SID_ATTR_CHAR_STRIKEOUT: + { + sal_Bool bOld = ((const SvxCrossedOutItem&)pEditView->GetAttribs(). + Get(EE_CHAR_STRIKEOUT)).GetValue() != STRIKEOUT_NONE; + aSet.Put( SvxCrossedOutItem( bOld ? STRIKEOUT_NONE : STRIKEOUT_SINGLE, EE_CHAR_STRIKEOUT ) ); + rBindings.Invalidate( nSlot ); + } + break; + + case SID_ATTR_CHAR_SHADOWED: + { + sal_Bool bOld = ((const SvxShadowedItem&)pEditView->GetAttribs(). + Get(EE_CHAR_SHADOW)).GetValue(); + aSet.Put( SvxShadowedItem( !bOld, EE_CHAR_SHADOW ) ); + rBindings.Invalidate( nSlot ); + } + break; + + case SID_ATTR_CHAR_CONTOUR: + { + sal_Bool bOld = ((const SvxContourItem&)pEditView->GetAttribs(). + Get(EE_CHAR_OUTLINE)).GetValue(); + aSet.Put( SvxContourItem( !bOld, EE_CHAR_OUTLINE ) ); + rBindings.Invalidate( nSlot ); + } + break; + + case SID_SET_SUPER_SCRIPT: + { + SvxEscapement eOld = (SvxEscapement) ((const SvxEscapementItem&) + pEditView->GetAttribs().Get(EE_CHAR_ESCAPEMENT)).GetEnumValue(); + SvxEscapement eNew = (eOld == SVX_ESCAPEMENT_SUPERSCRIPT) ? + SVX_ESCAPEMENT_OFF : SVX_ESCAPEMENT_SUPERSCRIPT; + aSet.Put( SvxEscapementItem( eNew, EE_CHAR_ESCAPEMENT ) ); + rBindings.Invalidate( nSlot ); + } + break; + case SID_SET_SUB_SCRIPT: + { + SvxEscapement eOld = (SvxEscapement) ((const SvxEscapementItem&) + pEditView->GetAttribs().Get(EE_CHAR_ESCAPEMENT)).GetEnumValue(); + SvxEscapement eNew = (eOld == SVX_ESCAPEMENT_SUBSCRIPT) ? + SVX_ESCAPEMENT_OFF : SVX_ESCAPEMENT_SUBSCRIPT; + aSet.Put( SvxEscapementItem( eNew, EE_CHAR_ESCAPEMENT ) ); + rBindings.Invalidate( nSlot ); + } + break; + } + + // + // anwenden + // + + EditEngine* pEngine = pEditView->GetEditEngine(); + sal_Bool bOld = pEngine->GetUpdateMode(); + pEngine->SetUpdateMode(sal_False); + + pEditView->SetAttribs( aSet ); + + pEngine->SetUpdateMode(bOld); + pEditView->Invalidate(); + + ScInputHandler* pHdl = GetMyInputHdl(); + pHdl->SetModified(); + + rReq.Done(); +} + +void ScEditShell::GetAttrState(SfxItemSet &rSet) +{ + if ( !pViewData->HasEditView( pViewData->GetActivePart() ) ) // #125326# + { + lcl_DisableAll( rSet ); + return; + } + + SfxItemSet aAttribs = pEditView->GetAttribs(); + rSet.Put( aAttribs ); + + // choose font info according to selection script type + + sal_uInt16 nScript = pEditView->GetSelectedScriptType(); + if (nScript == 0) nScript = ScGlobal::GetDefaultScriptType(); + + // #i55929# input-language-dependent script type (depends on input language if nothing selected) + sal_uInt16 nInputScript = nScript; + if ( !pEditView->GetSelection().HasRange() ) + { + LanguageType nInputLang = pViewData->GetActiveWin()->GetInputLanguage(); + if (nInputLang != LANGUAGE_DONTKNOW && nInputLang != LANGUAGE_SYSTEM) + nInputScript = SvtLanguageOptions::GetScriptTypeOfLanguage( nInputLang ); + } + + // #i55929# according to spec, nInputScript is used for font and font height only + if ( rSet.GetItemState( EE_CHAR_FONTINFO ) != SFX_ITEM_UNKNOWN ) + ScViewUtil::PutItemScript( rSet, aAttribs, EE_CHAR_FONTINFO, nInputScript ); + if ( rSet.GetItemState( EE_CHAR_FONTHEIGHT ) != SFX_ITEM_UNKNOWN ) + ScViewUtil::PutItemScript( rSet, aAttribs, EE_CHAR_FONTHEIGHT, nInputScript ); + if ( rSet.GetItemState( EE_CHAR_WEIGHT ) != SFX_ITEM_UNKNOWN ) + ScViewUtil::PutItemScript( rSet, aAttribs, EE_CHAR_WEIGHT, nScript ); + if ( rSet.GetItemState( EE_CHAR_ITALIC ) != SFX_ITEM_UNKNOWN ) + ScViewUtil::PutItemScript( rSet, aAttribs, EE_CHAR_ITALIC, nScript ); + + // Unterstreichung + + SfxItemState eState = aAttribs.GetItemState( EE_CHAR_UNDERLINE, sal_True ); + if ( eState == SFX_ITEM_DONTCARE ) + { + rSet.InvalidateItem( SID_ULINE_VAL_NONE ); + rSet.InvalidateItem( SID_ULINE_VAL_SINGLE ); + rSet.InvalidateItem( SID_ULINE_VAL_DOUBLE ); + rSet.InvalidateItem( SID_ULINE_VAL_DOTTED ); + } + else + { + FontUnderline eUnderline = ((const SvxUnderlineItem&) + aAttribs.Get(EE_CHAR_UNDERLINE)).GetLineStyle(); + sal_uInt16 nId = SID_ULINE_VAL_NONE; + switch (eUnderline) + { + case UNDERLINE_SINGLE: nId = SID_ULINE_VAL_SINGLE; break; + case UNDERLINE_DOUBLE: nId = SID_ULINE_VAL_DOUBLE; break; + case UNDERLINE_DOTTED: nId = SID_ULINE_VAL_DOTTED; break; + default: + break; + } + rSet.Put( SfxBoolItem( nId, sal_True ) ); + } + + //! Testen, ob Klammer-Hervorhebung aktiv ist !!!! + ScInputHandler* pHdl = GetMyInputHdl(); + if ( pHdl && pHdl->IsFormulaMode() ) + rSet.ClearItem( EE_CHAR_WEIGHT ); // hervorgehobene Klammern hier nicht +} + +String ScEditShell::GetSelectionText( sal_Bool bWholeWord ) +{ + String aStrSelection; + + if ( pViewData->HasEditView( pViewData->GetActivePart() ) ) // #125326# + { + if ( bWholeWord ) + { + EditEngine* pEngine = pEditView->GetEditEngine(); + ESelection aSel = pEditView->GetSelection(); + String aStrCurrentDelimiters = pEngine->GetWordDelimiters(); + + pEngine->SetWordDelimiters( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(" .,;\"'")) ); + aStrSelection = pEngine->GetWord( aSel.nEndPara, aSel.nEndPos ); + pEngine->SetWordDelimiters( aStrCurrentDelimiters ); + } + else + { + aStrSelection = pEditView->GetSelected(); + } + } + + return aStrSelection; +} + +void ScEditShell::ExecuteUndo(SfxRequest& rReq) +{ + // #81733# Undo must be handled here because it's called for both EditViews + + ScInputHandler* pHdl = GetMyInputHdl(); + DBG_ASSERT(pHdl,"no ScInputHandler"); + EditView* pTopView = pHdl->GetTopView(); + EditView* pTableView = pHdl->GetTableView(); + DBG_ASSERT(pTableView,"no EditView"); + + pHdl->DataChanging(); + + const SfxItemSet* pReqArgs = rReq.GetArgs(); + sal_uInt16 nSlot = rReq.GetSlot(); + switch ( nSlot ) + { + case SID_UNDO: + case SID_REDO: + { + sal_Bool bIsUndo = ( nSlot == SID_UNDO ); + + sal_uInt16 nCount = 1; + const SfxPoolItem* pItem; + if ( pReqArgs && pReqArgs->GetItemState( nSlot, sal_True, &pItem ) == SFX_ITEM_SET ) + nCount = ((const SfxUInt16Item*)pItem)->GetValue(); + + for (sal_uInt16 i=0; i<nCount; i++) + { + if ( bIsUndo ) + { + pTableView->Undo(); + if (pTopView) + pTopView->Undo(); + } + else + { + pTableView->Redo(); + if (pTopView) + pTopView->Redo(); + } + } + } + break; + } + pViewData->GetBindings().InvalidateAll(sal_False); + + pHdl->DataChanged(); +} + +void ScEditShell::GetUndoState(SfxItemSet &rSet) +{ + // Undo state is taken from normal ViewFrame state function + + SfxViewFrame* pViewFrm = pViewData->GetViewShell()->GetViewFrame(); + if ( pViewFrm && GetUndoManager() ) + { + SfxWhichIter aIter(rSet); + sal_uInt16 nWhich = aIter.FirstWhich(); + while( nWhich ) + { + pViewFrm->GetSlotState( nWhich, NULL, &rSet ); + nWhich = aIter.NextWhich(); + } + } + + // disable if no action in input line EditView + + ScInputHandler* pHdl = GetMyInputHdl(); + DBG_ASSERT(pHdl,"no ScInputHandler"); + EditView* pTopView = pHdl->GetTopView(); + if (pTopView) + { + ::svl::IUndoManager& rTopMgr = pTopView->GetEditEngine()->GetUndoManager(); + if ( rTopMgr.GetUndoActionCount() == 0 ) + rSet.DisableItem( SID_UNDO ); + if ( rTopMgr.GetRedoActionCount() == 0 ) + rSet.DisableItem( SID_REDO ); + } +} + +void ScEditShell::ExecuteTrans( SfxRequest& rReq ) +{ + sal_Int32 nType = ScViewUtil::GetTransliterationType( rReq.GetSlot() ); + if ( nType ) + { + ScInputHandler* pHdl = GetMyInputHdl(); + DBG_ASSERT( pHdl, "no ScInputHandler" ); + + EditView* pTopView = pHdl->GetTopView(); + EditView* pTableView = pHdl->GetTableView(); + DBG_ASSERT( pTableView, "no EditView" ); + + pHdl->DataChanging(); + + pTableView->TransliterateText( nType ); + if (pTopView) + pTopView->TransliterateText( nType ); + + pHdl->DataChanged(); + } +} + diff --git a/sc/source/ui/view/formatsh.cxx b/sc/source/ui/view/formatsh.cxx new file mode 100644 index 000000000000..ecc6f19d43e5 --- /dev/null +++ b/sc/source/ui/view/formatsh.cxx @@ -0,0 +1,2165 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + +#include <com/sun/star/style/XStyleFamiliesSupplier.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XNameAccess.hpp> + +//------------------------------------------------------------------ + +//svdraw.hxx +#define _SDR_NOITEMS +#define _SDR_NOTOUCH +#define _SDR_NOTRANSFORM +#define _SI_NOSBXCONTROLS +#define _VCONT_HXX +#define _SI_NOOTHERFORMS +#define _VCTRLS_HXX +#define _SI_NOCONTROL +#define _SETBRW_HXX +#define _VCBRW_HXX +#define _SI_NOSBXCONTROLS + +//------------------------------------------------------------------ + +#include "scitems.hxx" +#include <editeng/eeitem.hxx> + +#include <sfx2/app.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/objface.hxx> +#include <sfx2/request.hxx> +#include <svl/whiter.hxx> +#include <vcl/msgbox.hxx> + +#define _ZFORLIST_DECLARE_TABLE +#include <svl/stritem.hxx> +#include <svl/zformat.hxx> +#include <svl/languageoptions.hxx> +#include <editeng/boxitem.hxx> +#include <editeng/langitem.hxx> +#include <svx/numinf.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/templdlg.hxx> +#include <sfx2/tplpitem.hxx> +#include <editeng/svxenum.hxx> +#include <svx/algitem.hxx> +#include <editeng/wghtitem.hxx> +#include <editeng/postitem.hxx> +#include <editeng/udlnitem.hxx> +#include <editeng/bolnitem.hxx> +#include <editeng/colritem.hxx> +#include <editeng/brshitem.hxx> +#include <editeng/frmdiritem.hxx> +#include <editeng/scripttypeitem.hxx> +#include <svtools/colorcfg.hxx> +#include <editeng/shaditem.hxx> + +#include "formatsh.hxx" +#include "sc.hrc" +#include "globstr.hrc" +#include "docsh.hxx" +#include "patattr.hxx" +#include "scmod.hxx" +//CHINA001 #include "styledlg.hxx" +#include "attrdlg.hrc" +#include "stlpool.hxx" +#include "stlsheet.hxx" +#include "printfun.hxx" +#include "docpool.hxx" +#include "scresid.hxx" +#include "tabvwsh.hxx" +#include "undostyl.hxx" + + +#define ScFormatShell +#define TableFont +#define FormatForSelection +#include "scslots.hxx" + +#include "scabstdlg.hxx" //CHINA001 + +namespace { + +SvxCellHorJustify lclConvertSlotToHAlign( sal_uInt16 nSlot ) +{ + SvxCellHorJustify eHJustify = SVX_HOR_JUSTIFY_STANDARD; + switch( nSlot ) + { + case SID_ALIGN_ANY_HDEFAULT: eHJustify = SVX_HOR_JUSTIFY_STANDARD; break; + case SID_ALIGN_ANY_LEFT: eHJustify = SVX_HOR_JUSTIFY_LEFT; break; + case SID_ALIGN_ANY_HCENTER: eHJustify = SVX_HOR_JUSTIFY_CENTER; break; + case SID_ALIGN_ANY_RIGHT: eHJustify = SVX_HOR_JUSTIFY_RIGHT; break; + case SID_ALIGN_ANY_JUSTIFIED: eHJustify = SVX_HOR_JUSTIFY_BLOCK; break; + default: DBG_ERRORFILE( "lclConvertSlotToHAlign - invalid slot" ); + } + return eHJustify; +} + +SvxCellVerJustify lclConvertSlotToVAlign( sal_uInt16 nSlot ) +{ + SvxCellVerJustify eVJustify = SVX_VER_JUSTIFY_STANDARD; + switch( nSlot ) + { + case SID_ALIGN_ANY_VDEFAULT: eVJustify = SVX_VER_JUSTIFY_STANDARD; break; + case SID_ALIGN_ANY_TOP: eVJustify = SVX_VER_JUSTIFY_TOP; break; + case SID_ALIGN_ANY_VCENTER: eVJustify = SVX_VER_JUSTIFY_CENTER; break; + case SID_ALIGN_ANY_BOTTOM: eVJustify = SVX_VER_JUSTIFY_BOTTOM; break; + default: DBG_ERRORFILE( "lclConvertSlotToVAlign - invalid slot" ); + } + return eVJustify; +} + +} // namespace + +TYPEINIT1( ScFormatShell, SfxShell ); + +SFX_IMPL_INTERFACE(ScFormatShell, SfxShell, ScResId(SCSTR_FORMATSHELL) ) +{ + SFX_OBJECTBAR_REGISTRATION( SFX_OBJECTBAR_OBJECT | SFX_VISIBILITY_STANDARD | + SFX_VISIBILITY_SERVER, + ScResId(RID_OBJECTBAR_FORMAT)); + +} + + +ScFormatShell::ScFormatShell(ScViewData* pData) : + SfxShell(pData->GetViewShell()), + pViewData(pData) +{ + ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell(); + + SetPool( &pTabViewShell->GetPool() ); + ::svl::IUndoManager* pMgr = pViewData->GetSfxDocShell()->GetUndoManager(); + SetUndoManager( pMgr ); + if ( !pViewData->GetDocument()->IsUndoEnabled() ) + { + pMgr->SetMaxUndoActionCount( 0 ); + } + SetHelpId(HID_SCSHELL_FORMATSH); + SetName(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Format"))); +} + +ScFormatShell::~ScFormatShell() +{ +} + +//------------------------------------------------------------------ + +void __EXPORT ScFormatShell::GetStyleState( SfxItemSet& rSet ) +{ + ScDocument* pDoc = GetViewData()->GetDocument(); + ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell(); + SfxStyleSheetBasePool* pStylePool = pDoc->GetStyleSheetPool(); + + sal_Bool bProtected = sal_False; + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB i=0; i<nTabCount; i++) + if (pDoc->IsTabProtected(i)) // ueberhaupt eine Tabelle geschuetzt? + bProtected = sal_True; + + SfxWhichIter aIter(rSet); + sal_uInt16 nWhich = aIter.FirstWhich(); + sal_uInt16 nSlotId = 0; + + while ( nWhich ) + { + nSlotId = SfxItemPool::IsWhich( nWhich ) + ? GetPool().GetSlotId( nWhich ) + : nWhich; + + switch ( nSlotId ) + { + case SID_STYLE_APPLY: + if ( !pStylePool ) + rSet.DisableItem( nSlotId ); + break; + + case SID_STYLE_FAMILY2: // Zellvorlagen + { + SfxStyleSheet* pStyleSheet = (SfxStyleSheet*) + pTabViewShell->GetStyleSheetFromMarked(); + + if ( pStyleSheet ) + rSet.Put( SfxTemplateItem( nSlotId, pStyleSheet->GetName() ) ); + else + rSet.Put( SfxTemplateItem( nSlotId, String() ) ); + } + break; + + case SID_STYLE_FAMILY4: // Seitenvorlagen + { + SCTAB nCurTab = GetViewData()->GetTabNo(); + String aPageStyle = pDoc->GetPageStyle( nCurTab ); + SfxStyleSheet* pStyleSheet = (SfxStyleSheet*)pStylePool-> + Find( aPageStyle, SFX_STYLE_FAMILY_PAGE ); + + if ( pStyleSheet ) + rSet.Put( SfxTemplateItem( nSlotId, aPageStyle ) ); + else + rSet.Put( SfxTemplateItem( nSlotId, String() ) ); + } + break; + + case SID_STYLE_WATERCAN: + { + rSet.Put( SfxBoolItem( nSlotId, SC_MOD()->GetIsWaterCan() ) ); + } + break; + + case SID_STYLE_UPDATE_BY_EXAMPLE: + { + ISfxTemplateCommon* pDesigner = SFX_APP()-> + GetCurrentTemplateCommon(pTabViewShell->GetViewFrame()->GetBindings()); + sal_Bool bPage = pDesigner && SFX_STYLE_FAMILY_PAGE == pDesigner->GetActualFamily(); + + if ( bProtected || bPage ) + rSet.DisableItem( nSlotId ); + } + break; + + case SID_STYLE_EDIT: + case SID_STYLE_DELETE: + { + ISfxTemplateCommon* pDesigner = SFX_APP()-> + GetCurrentTemplateCommon(pTabViewShell->GetViewFrame()->GetBindings()); + sal_Bool bPage = pDesigner && SFX_STYLE_FAMILY_PAGE == pDesigner->GetActualFamily(); + + if ( bProtected && !bPage ) + rSet.DisableItem( nSlotId ); + } + break; + + default: + break; + } + + nWhich = aIter.NextWhich(); + } +} + +//------------------------------------------------------------------ + +void __EXPORT ScFormatShell::ExecuteStyle( SfxRequest& rReq ) +{ + // Wenn ToolBar vertikal : + if ( !rReq.GetArgs() ) + { + pViewData->GetDispatcher().Execute( SID_STYLE_DESIGNER, SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD ); + return; + } + + //-------------------------------------------------------------------- + SfxBindings& rBindings = pViewData->GetBindings(); + const SfxItemSet* pArgs = rReq.GetArgs(); + const sal_uInt16 nSlotId = rReq.GetSlot(); + const SCTAB nCurTab = GetViewData()->GetTabNo(); + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScTabViewShell* pTabViewShell= GetViewData()->GetViewShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + ScModule* pScMod = SC_MOD(); + String aRefName; + sal_Bool bUndo = pDoc->IsUndoEnabled(); + + if ( (nSlotId == SID_STYLE_NEW) + || (nSlotId == SID_STYLE_EDIT) + || (nSlotId == SID_STYLE_DELETE) + || (nSlotId == SID_STYLE_APPLY) + || (nSlotId == SID_STYLE_WATERCAN) + || (nSlotId == SID_STYLE_FAMILY) + || (nSlotId == SID_STYLE_NEW_BY_EXAMPLE) + || (nSlotId == SID_STYLE_UPDATE_BY_EXAMPLE) ) + { + SfxStyleSheetBasePool* pStylePool = pDoc->GetStyleSheetPool(); + SfxStyleSheetBase* pStyleSheet = NULL; + + sal_Bool bStyleToMarked = sal_False; + sal_Bool bListAction = sal_False; + sal_Bool bAddUndo = sal_False; // add ScUndoModifyStyle (style modified) + ScStyleSaveData aOldData; // for undo/redo + ScStyleSaveData aNewData; + + SfxStyleFamily eFamily = SFX_STYLE_FAMILY_PARA; + const SfxPoolItem* pFamItem; + if ( pArgs && SFX_ITEM_SET == pArgs->GetItemState( SID_STYLE_FAMILY, sal_True, &pFamItem ) ) + eFamily = (SfxStyleFamily)((const SfxUInt16Item*)pFamItem)->GetValue(); + else + if ( pArgs && SFX_ITEM_SET == pArgs->GetItemState( SID_STYLE_FAMILYNAME, sal_True, &pFamItem ) ) + { + String sFamily = ((const SfxStringItem*)pFamItem)->GetValue(); + if (sFamily.CompareToAscii("CellStyles") == COMPARE_EQUAL) + eFamily = SFX_STYLE_FAMILY_PARA; + else + if (sFamily.CompareToAscii("PageStyles") == COMPARE_EQUAL) + eFamily = SFX_STYLE_FAMILY_PAGE; + } + + String aStyleName; + sal_uInt16 nRetMask = 0xffff; +// #96983# only stylist sends focus to sheet +// sal_Bool bGrabFocus = ( SID_STYLE_APPLY == nSlotId ); + + pStylePool->SetSearchMask( eFamily, SFXSTYLEBIT_ALL ); + + switch ( nSlotId ) + { + case SID_STYLE_NEW: + { + const SfxPoolItem* pNameItem; + if (pArgs && SFX_ITEM_SET == pArgs->GetItemState( nSlotId, sal_True, &pNameItem )) + aStyleName = ((const SfxStringItem*)pNameItem)->GetValue(); + + const SfxPoolItem* pRefItem=NULL; + if (pArgs && SFX_ITEM_SET == pArgs->GetItemState( SID_STYLE_REFERENCE, sal_True, &pRefItem )) + { + if(pRefItem!=NULL) + aRefName = ((const SfxStringItem*)pRefItem)->GetValue(); + } + + pStyleSheet = &(pStylePool->Make( aStyleName, eFamily, + SFXSTYLEBIT_USERDEF ) ); + + if ( pStyleSheet && pStyleSheet->HasParentSupport() ) + pStyleSheet->SetParent(aRefName); + } + break; + + case SID_STYLE_APPLY: + { + SFX_REQUEST_ARG( rReq, pNameItem, SfxStringItem, SID_APPLY_STYLE, sal_False ); + SFX_REQUEST_ARG( rReq, pFamilyItem, SfxStringItem, SID_STYLE_FAMILYNAME, sal_False ); + if ( pFamilyItem && pNameItem ) + { + com::sun::star::uno::Reference< com::sun::star::style::XStyleFamiliesSupplier > xModel(pDocSh->GetModel(), com::sun::star::uno::UNO_QUERY); + try + { + com::sun::star::uno::Reference< com::sun::star::container::XNameAccess > xStyles; + com::sun::star::uno::Reference< com::sun::star::container::XNameAccess > xCont = xModel->getStyleFamilies(); + xCont->getByName(pFamilyItem->GetValue()) >>= xStyles; + com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet > xInfo; + xStyles->getByName( pNameItem->GetValue() ) >>= xInfo; + ::rtl::OUString aUIName; + xInfo->getPropertyValue( ::rtl::OUString::createFromAscii("DisplayName") ) >>= aUIName; + if ( aUIName.getLength() ) + rReq.AppendItem( SfxStringItem( SID_STYLE_APPLY, aUIName ) ); + } + catch( com::sun::star::uno::Exception& ) + { + } + } + } + case SID_STYLE_EDIT: + case SID_STYLE_DELETE: + case SID_STYLE_NEW_BY_EXAMPLE: + { + const SfxPoolItem* pNameItem; + if (pArgs && SFX_ITEM_SET == pArgs->GetItemState( nSlotId, sal_True, &pNameItem )) + aStyleName = ((const SfxStringItem*)pNameItem)->GetValue(); + pStyleSheet = pStylePool->Find( aStyleName, eFamily ); + + aOldData.InitFromStyle( pStyleSheet ); + } + break; + + case SID_STYLE_WATERCAN: + { + sal_Bool bWaterCan = pScMod->GetIsWaterCan(); + + if( !bWaterCan ) + { + const SfxPoolItem* pItem; + + if ( SFX_ITEM_SET == + pArgs->GetItemState( nSlotId, sal_True, &pItem ) ) + { + const SfxStringItem* pStrItem = PTR_CAST(SfxStringItem,pItem); + if ( pStrItem ) + { + aStyleName = pStrItem->GetValue(); + pStyleSheet = pStylePool->Find( aStyleName, eFamily ); + + if ( pStyleSheet ) + { + ((ScStyleSheetPool*)pStylePool)-> + SetActualStyleSheet( pStyleSheet ); + rReq.Done(); + } + } + } + } + + if ( !bWaterCan && pStyleSheet ) + { + pScMod->SetWaterCan( sal_True ); + pTabViewShell->SetActivePointer( Pointer(POINTER_FILL) ); + rReq.Done(); + } + else + { + pScMod->SetWaterCan( sal_False ); + pTabViewShell->SetActivePointer( Pointer(POINTER_ARROW) ); + rReq.Done(); + } + } + break; + + default: + break; + } + + // Neuen Style fuer WaterCan-Mode setzen + if ( nSlotId == SID_STYLE_APPLY && pScMod->GetIsWaterCan() && pStyleSheet ) + ((ScStyleSheetPool*)pStylePool)->SetActualStyleSheet( pStyleSheet ); + + switch ( eFamily ) + { + case SFX_STYLE_FAMILY_PARA: + { + switch ( nSlotId ) + { + case SID_STYLE_DELETE: + { + if ( pStyleSheet ) + { + pTabViewShell->RemoveStyleSheetInUse( pStyleSheet ); + pStylePool->Remove( pStyleSheet ); + pTabViewShell->InvalidateAttribs(); + nRetMask = sal_True; + bAddUndo = sal_True; + rReq.Done(); + } + else + nRetMask = sal_False; + } + break; + + case SID_STYLE_APPLY: + { + if ( pStyleSheet && !pScMod->GetIsWaterCan() ) + { + // Anwenden der Vorlage auf das Dokument + pTabViewShell->SetStyleSheetToMarked( (SfxStyleSheet*)pStyleSheet ); + pTabViewShell->InvalidateAttribs(); + rReq.Done(); + } + } + break; + + case SID_STYLE_NEW_BY_EXAMPLE: + case SID_STYLE_UPDATE_BY_EXAMPLE: + { + // Vorlage erzeugen/ersetzen durch Attribute + // an der Cursor-Position: + + const ScPatternAttr* pAttrItem = NULL; + + // Die Abfrage, ob markiert ist, war hier immer falsch, + // darum jetzt gar nicht mehr, und einfach vom Cursor. + // Wenn Attribute aus der Selektion genommen werden sollen, + // muss noch darauf geachtet werden, Items aus Vorlagen nicht + // zu uebernehmen (GetSelectionPattern sammelt auch Items aus + // Vorlagen zusammen) (#44748#) + // pAttrItem = GetSelectionPattern(); + + // ScViewData* pViewData = GetViewData(); + SCCOL nCol = pViewData->GetCurX(); + SCROW nRow = pViewData->GetCurY(); + pAttrItem = pDoc->GetPattern( nCol, nRow, nCurTab ); + + SfxItemSet aAttrSet = pAttrItem->GetItemSet(); + aAttrSet.ClearItem( ATTR_MERGE ); + aAttrSet.ClearItem( ATTR_MERGE_FLAG ); + // bedingte Formatierung und Gueltigkeit nicht uebernehmen, + // weil sie in der Vorlage nicht editiert werden koennen + aAttrSet.ClearItem( ATTR_VALIDDATA ); + aAttrSet.ClearItem( ATTR_CONDITIONAL ); + + if ( SID_STYLE_NEW_BY_EXAMPLE == nSlotId ) + { + if ( bUndo ) + { + String aUndo = ScGlobal::GetRscString( STR_UNDO_EDITCELLSTYLE ); + pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo ); + bListAction = sal_True; + } + + sal_Bool bConvertBack = sal_False; + SfxStyleSheet* pSheetInUse = (SfxStyleSheet*) + pTabViewShell->GetStyleSheetFromMarked(); + + // wenn neuer Style vorhanden und in der Selektion + // verwendet wird, so darf der Parent nicht uebernommen + // werden: + + if ( pStyleSheet && pSheetInUse && pStyleSheet == pSheetInUse ) + pSheetInUse = NULL; + + // wenn bereits vorhanden, erstmal entfernen... + if ( pStyleSheet ) + { + // Style-Pointer zu Namen vor Erase, + // weil Zellen sonst ungueltige Pointer + // enthalten. + //!!! bei Gelenheit mal eine Methode, die + // das fuer einen bestimmten Style macht + pDoc->StylesToNames(); + bConvertBack = sal_True; + pStylePool->Remove(pStyleSheet); + } + + // ...und neu anlegen + pStyleSheet = &pStylePool->Make( aStyleName, eFamily, + SFXSTYLEBIT_USERDEF ); + + // wenn ein Style vorhanden ist, so wird dieser + // Parent der neuen Vorlage: + if ( pSheetInUse && pStyleSheet->HasParentSupport() ) + pStyleSheet->SetParent( pSheetInUse->GetName() ); + + if ( bConvertBack ) + // Namen zu Style-Pointer + pDoc->UpdStlShtPtrsFrmNms(); + else + pDoc->GetPool()->CellStyleCreated( aStyleName ); + + // Attribute uebernehmen und Style anwenden + pStyleSheet->GetItemSet().Put( aAttrSet ); + pTabViewShell->UpdateStyleSheetInUse( pStyleSheet ); + + // call SetStyleSheetToMarked after adding the ScUndoModifyStyle + // (pStyleSheet pointer is used!) + bStyleToMarked = sal_True; + } + else // ( nSlotId == SID_STYLE_UPDATE_BY_EXAMPLE ) + { + pStyleSheet = (SfxStyleSheet*)pTabViewShell->GetStyleSheetFromMarked(); + + if ( pStyleSheet ) + { + aOldData.InitFromStyle( pStyleSheet ); + + if ( bUndo ) + { + String aUndo = ScGlobal::GetRscString( STR_UNDO_EDITCELLSTYLE ); + pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo ); + bListAction = sal_True; + } + + pStyleSheet->GetItemSet().Put( aAttrSet ); + pTabViewShell->UpdateStyleSheetInUse( pStyleSheet ); + + // call SetStyleSheetToMarked after adding the ScUndoModifyStyle + // (pStyleSheet pointer is used!) + bStyleToMarked = sal_True; + } + } + + aNewData.InitFromStyle( pStyleSheet ); + bAddUndo = sal_True; + rReq.Done(); + } + break; + + default: + break; + } + } // case SFX_STYLE_FAMILY_PARA: + break; + + case SFX_STYLE_FAMILY_PAGE: + { + switch ( nSlotId ) + { + case SID_STYLE_DELETE: + { + nRetMask = ( NULL != pStyleSheet ); + if ( pStyleSheet ) + { + if ( pDoc->RemovePageStyleInUse( pStyleSheet->GetName() ) ) + { + ScPrintFunc( pDocSh, pTabViewShell->GetPrinter(sal_True), nCurTab ).UpdatePages(); + rBindings.Invalidate( SID_STATUS_PAGESTYLE ); + rBindings.Invalidate( FID_RESET_PRINTZOOM ); + } + pStylePool->Remove( pStyleSheet ); + rBindings.Invalidate( SID_STYLE_FAMILY4 ); + pDocSh->SetDocumentModified(); + bAddUndo = sal_True; + rReq.Done(); + } + } + break; + + case SID_STYLE_APPLY: + { + nRetMask = ( NULL != pStyleSheet ); + if ( pStyleSheet && !pScMod->GetIsWaterCan() ) + { + ScUndoApplyPageStyle* pUndoAction = 0; + for( SCTAB nTab = 0, nTabCount = pDoc->GetTableCount(); nTab < nTabCount; ++nTab ) + { + if( rMark.GetTableSelect( nTab ) ) + { + String aOldName = pDoc->GetPageStyle( nTab ); + if ( aOldName != aStyleName ) + { + pDoc->SetPageStyle( nTab, aStyleName ); + ScPrintFunc( pDocSh, pTabViewShell->GetPrinter(sal_True), nTab ).UpdatePages(); + if( !pUndoAction ) + pUndoAction = new ScUndoApplyPageStyle( pDocSh, aStyleName ); + pUndoAction->AddSheetAction( nTab, aOldName ); + } + } + } + if( pUndoAction ) + { + pDocSh->GetUndoManager()->AddUndoAction( pUndoAction ); + pDocSh->SetDocumentModified(); + rBindings.Invalidate( SID_STYLE_FAMILY4 ); + rBindings.Invalidate( SID_STATUS_PAGESTYLE ); + rBindings.Invalidate( FID_RESET_PRINTZOOM ); + } + rReq.Done(); + } + } + break; + + case SID_STYLE_NEW_BY_EXAMPLE: + { + const String& rStrCurStyle = pDoc->GetPageStyle( nCurTab ); + + if ( rStrCurStyle != aStyleName ) + { + SfxStyleSheetBase* pCurStyle = pStylePool->Find( rStrCurStyle, eFamily ); + SfxItemSet aAttrSet = pCurStyle->GetItemSet(); + SCTAB nInTab; + sal_Bool bUsed = pDoc->IsPageStyleInUse( aStyleName, &nInTab ); + + // wenn bereits vorhanden, erstmal entfernen... + if ( pStyleSheet ) + pStylePool->Remove( pStyleSheet ); + + // ...und neu anlegen + pStyleSheet = &pStylePool->Make( aStyleName, eFamily, + SFXSTYLEBIT_USERDEF ); + + // Attribute uebernehmen + pStyleSheet->GetItemSet().Put( aAttrSet ); + pDocSh->SetDocumentModified(); + + // wenn in Verwendung -> Update + if ( bUsed ) + ScPrintFunc( pDocSh, pTabViewShell->GetPrinter(sal_True), nInTab ).UpdatePages(); + + aNewData.InitFromStyle( pStyleSheet ); + bAddUndo = sal_True; + rReq.Done(); + nRetMask = sal_True; + } + } + break; + + default: + break; + } // switch ( nSlotId ) + } // case SFX_STYLE_FAMILY_PAGE: + break; + + default: + break; + } // switch ( eFamily ) + + // Neu anlegen oder bearbeiten ueber Dialog: + if ( nSlotId == SID_STYLE_NEW || nSlotId == SID_STYLE_EDIT ) + { + if ( pStyleSheet ) + { + SvxNumberInfoItem* pNumberInfoItem = NULL; + + SfxStyleFamily eFam = pStyleSheet->GetFamily(); + // ScDocument* pDoc = GetViewData()->GetDocument(); + // ScDocShell* pDocSh = GetViewData()->GetDocShell(); + //CHINA001 ScStyleDlg* pDlg = NULL; + SfxAbstractTabDialog* pDlg = NULL; //CHINA001 + sal_uInt16 nRsc = 0; + + // #37034#/#37245# alte Items aus der Vorlage merken + SfxItemSet aOldSet = pStyleSheet->GetItemSet(); + String aOldName = pStyleSheet->GetName(); + + switch ( eFam ) + { + case SFX_STYLE_FAMILY_PAGE: + nRsc = RID_SCDLG_STYLES_PAGE; + break; + + case SFX_STYLE_FAMILY_PARA: + default: + { + SfxItemSet& rSet = pStyleSheet->GetItemSet(); + + const SfxPoolItem* pItem; + if ( rSet.GetItemState( ATTR_VALUE_FORMAT, + sal_False, &pItem ) == SFX_ITEM_SET ) + { + // NumberFormat Value aus Value und Language + // erzeugen und eintueten + sal_uLong nFormat = + ((SfxUInt32Item*)pItem)->GetValue(); + LanguageType eLang = + ((SvxLanguageItem*)&rSet.Get( + ATTR_LANGUAGE_FORMAT ))->GetLanguage(); + sal_uLong nLangFormat = pDoc->GetFormatTable()-> + GetFormatForLanguageIfBuiltIn( nFormat, eLang ); + if ( nLangFormat != nFormat ) + { + SfxUInt32Item aNewItem( ATTR_VALUE_FORMAT, nLangFormat ); + rSet.Put( aNewItem ); + aOldSet.Put( aNewItem ); + // auch in aOldSet fuer Vergleich nach dem Dialog, + // sonst geht evtl. eine Aenderung der Sprache verloren + } + } + + pTabViewShell->MakeNumberInfoItem( pDoc, GetViewData(), &pNumberInfoItem ); + pDocSh->PutItem( *pNumberInfoItem ); + nRsc = RID_SCDLG_STYLES_PAR; + + // auf jeden Fall ein SvxBoxInfoItem mit Table = sal_False im Set: + // (wenn gar kein Item da ist, loescht der Dialog auch das + // BORDER_OUTER SvxBoxItem aus dem Vorlagen-Set) + + if ( rSet.GetItemState( ATTR_BORDER_INNER, sal_False ) != SFX_ITEM_SET ) + { + SvxBoxInfoItem aBoxInfoItem( ATTR_BORDER_INNER ); + aBoxInfoItem.SetTable(sal_False); // keine inneren Linien + aBoxInfoItem.SetDist(sal_True); + aBoxInfoItem.SetMinDist(sal_False); + rSet.Put( aBoxInfoItem ); + } + } + break; + } + + // If GetDefDialogParent is a dialog, it must be used + // (style catalog) + + Window* pParent = Application::GetDefDialogParent(); + if ( !pParent || !pParent->IsDialog() ) + { + // #107256# GetDefDialogParent currently doesn't return the window + // that was set with SetDefDialogParent (but dynamically finds the + // topmost parent of the focus window), so IsDialog above is FALSE + // even if called from the style catalog. + // -> Use NULL if a modal dialog is open, to enable the Dialog's + // default parent handling. + if ( Application::IsInModalMode() ) + pParent = NULL; + else + pParent = pTabViewShell->GetDialogParent(); + } + + pTabViewShell->SetInFormatDialog(sal_True); + + //CHINA001 pDlg = new ScStyleDlg( pParent, *pStyleSheet, nRsc ); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + pDlg = pFact->CreateScStyleDlg( pParent, *pStyleSheet, nRsc, nRsc ); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + short nResult = pDlg->Execute(); + pTabViewShell->SetInFormatDialog(sal_False); + + if ( nResult == RET_OK ) + { + const SfxItemSet* pOutSet = pDlg->GetOutputItemSet(); + + if ( pOutSet ) + { + nRetMask = pStyleSheet->GetMask(); + + // #37034#/#37245# Attribut-Vergleiche (frueher in ModifyStyleSheet) + // jetzt hier mit den alten Werten (Style ist schon veraendert) + + if ( SFX_STYLE_FAMILY_PARA == eFam ) + { +// pDoc->CellStyleChanged( *pStyleSheet, aOldSet ); + + SfxItemSet& rNewSet = pStyleSheet->GetItemSet(); + sal_Bool bNumFormatChanged; + if ( ScGlobal::CheckWidthInvalidate( + bNumFormatChanged, aOldSet, rNewSet ) ) + pDoc->InvalidateTextWidth( NULL, NULL, bNumFormatChanged ); + + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB nTab=0; nTab<nTabCount; nTab++) + if (pDoc->IsStreamValid(nTab)) + pDoc->SetStreamValid(nTab, sal_False); + + sal_uLong nOldFormat = ((const SfxUInt32Item&)aOldSet. + Get( ATTR_VALUE_FORMAT )).GetValue(); + sal_uLong nNewFormat = ((const SfxUInt32Item&)rNewSet. + Get( ATTR_VALUE_FORMAT )).GetValue(); + if ( nNewFormat != nOldFormat ) + { + SvNumberFormatter* pFormatter = pDoc->GetFormatTable(); + const SvNumberformat* pOld = pFormatter->GetEntry( nOldFormat ); + const SvNumberformat* pNew = pFormatter->GetEntry( nNewFormat ); + if ( pOld && pNew && pOld->GetLanguage() != pNew->GetLanguage() ) + rNewSet.Put( SvxLanguageItem( + pNew->GetLanguage(), ATTR_LANGUAGE_FORMAT ) ); + } + + pDoc->GetPool()->CellStyleCreated( pStyleSheet->GetName() ); + } + else + { + //! auch fuer Seitenvorlagen die Abfragen hier + + String aNewName = pStyleSheet->GetName(); + if ( aNewName != aOldName && + pDoc->RenamePageStyleInUse( aOldName, aNewName ) ) + { + rBindings.Invalidate( SID_STATUS_PAGESTYLE ); + rBindings.Invalidate( FID_RESET_PRINTZOOM ); + } + + pDoc->ModifyStyleSheet( *pStyleSheet, *pOutSet ); + rBindings.Invalidate( FID_RESET_PRINTZOOM ); + } + + pDocSh->SetDocumentModified(); + + if ( SFX_STYLE_FAMILY_PARA == eFam ) + { + pTabViewShell->UpdateNumberFormatter( pDoc, + (const SvxNumberInfoItem&) + *(pDocSh->GetItem(SID_ATTR_NUMBERFORMAT_INFO)) ); + + pTabViewShell->UpdateStyleSheetInUse( pStyleSheet ); + pTabViewShell->InvalidateAttribs(); + } + + aNewData.InitFromStyle( pStyleSheet ); + bAddUndo = sal_True; + } + } + else + { + if ( nSlotId == SID_STYLE_NEW ) + pStylePool->Remove( pStyleSheet ); + else + { + // falls zwischendurch etwas mit dem temporaer geaenderten + // ItemSet gepainted wurde: + pDocSh->PostPaintGridAll(); + } + } + delete pDlg; + } + } + +// if ( nRetMask != 0xffff )// Irgendein Wert MUSS geliefert werden JN + rReq.SetReturnValue( SfxUInt16Item( nSlotId, nRetMask ) ); + +// #96983# only stylist sends focus to sheet +// if ( bGrabFocus ) +// pTabViewShell->GetActiveWin()->GrabFocus(); + + if ( bAddUndo && bUndo) + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoModifyStyle( pDocSh, eFamily, aOldData, aNewData ) ); + + if ( bStyleToMarked ) + { + // call SetStyleSheetToMarked after adding the ScUndoModifyStyle, + // so redo will find the modified style + pTabViewShell->SetStyleSheetToMarked( (SfxStyleSheet*)pStyleSheet ); + pTabViewShell->InvalidateAttribs(); + } + + if ( bListAction ) + pDocSh->GetUndoManager()->LeaveListAction(); + } + else + { + DBG_ERROR( "Unknown slot (ScViewShell::ExecuteStyle)" ); + } +} + +void ScFormatShell::ExecuteNumFormat( SfxRequest& rReq ) +{ + ScModule* pScMod = SC_MOD(); + ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell(); + const SfxItemSet* pReqArgs = rReq.GetArgs(); + sal_uInt16 nSlot = rReq.GetSlot(); + + pTabViewShell->HideListBox(); // Autofilter-DropDown-Listbox + + // Eingabe beenden + if ( GetViewData()->HasEditView( GetViewData()->GetActivePart() ) ) + { + switch ( nSlot ) + { + case SID_NUMBER_TWODEC: + case SID_NUMBER_SCIENTIFIC: + case SID_NUMBER_DATE: + case SID_NUMBER_CURRENCY: + case SID_NUMBER_PERCENT: + case SID_NUMBER_STANDARD: + case SID_NUMBER_FORMAT: + case SID_NUMBER_INCDEC: + case SID_NUMBER_DECDEC: + case FID_DEFINE_NAME: + case FID_USE_NAME: + case FID_INSERT_NAME: + case SID_SPELL_DIALOG: + case SID_HANGUL_HANJA_CONVERSION: + + pScMod->InputEnterHandler(); + pTabViewShell->UpdateInputHandler(); + break; + + default: + break; + } + } + + switch ( nSlot ) + { + case SID_NUMBER_TWODEC: + pTabViewShell->SetNumberFormat( NUMBERFORMAT_NUMBER, 4 ); // Standard+4 = #.##0,00 + rReq.Done(); + break; + case SID_NUMBER_SCIENTIFIC: + pTabViewShell->SetNumberFormat( NUMBERFORMAT_SCIENTIFIC ); + rReq.Done(); + break; + case SID_NUMBER_DATE: + pTabViewShell->SetNumberFormat( NUMBERFORMAT_DATE ); + rReq.Done(); + break; + case SID_NUMBER_TIME: + pTabViewShell->SetNumberFormat( NUMBERFORMAT_TIME ); + rReq.Done(); + break; + case SID_NUMBER_CURRENCY: + pTabViewShell->SetNumberFormat( NUMBERFORMAT_CURRENCY ); + rReq.Done(); + break; + case SID_NUMBER_PERCENT: + pTabViewShell->SetNumberFormat( NUMBERFORMAT_PERCENT ); + rReq.Done(); + break; + case SID_NUMBER_STANDARD: + pTabViewShell->SetNumberFormat( NUMBERFORMAT_NUMBER ); + rReq.Done(); + break; + case SID_NUMBER_INCDEC: + pTabViewShell->ChangeNumFmtDecimals( sal_True ); + rReq.Done(); + break; + case SID_NUMBER_DECDEC: + pTabViewShell->ChangeNumFmtDecimals( sal_False ); + rReq.Done(); + break; + + case SID_NUMBER_FORMAT: + if ( pReqArgs ) + { + const SfxPoolItem* pItem; + if(pReqArgs->GetItemState(nSlot, sal_True, &pItem) == SFX_ITEM_SET) + { + String aCode = ((const SfxStringItem*)pItem)->GetValue(); + pTabViewShell->SetNumFmtByStr( aCode ); + } + } + break; + + case SID_ATTR_NUMBERFORMAT_VALUE: + if ( pReqArgs ) + { + const SfxPoolItem* pItem; + if ( pReqArgs->GetItemState( ATTR_VALUE_FORMAT, sal_True, &pItem ) == SFX_ITEM_SET ) + { + // We have to accomplish this using ApplyAttributes() + // because we also need the language information to be + // considered. + const SfxItemSet& rOldSet = + pTabViewShell->GetSelectionPattern()->GetItemSet(); + SfxItemPool* pDocPool = GetViewData()->GetDocument()->GetPool(); + SfxItemSet aNewSet( *pDocPool, ATTR_PATTERN_START, ATTR_PATTERN_END ); + aNewSet.Put( *pItem ); + pTabViewShell->ApplyAttributes( &aNewSet, &rOldSet, sal_True ); + } + } + break; + + default: + DBG_ERROR("falscher Slot bei ExecuteEdit"); + break; + } +} + + +//------------------------------------------------------------------ + +#define APPLY_HOR_JUSTIFY(j) \ + { \ + if ( !pHorJustify || (eHorJustify != (j) ) ) \ + pTabViewShell->ApplyAttr( SvxHorJustifyItem( (j) ) ); \ + else \ + pTabViewShell->ApplyAttr( SvxHorJustifyItem( SVX_HOR_JUSTIFY_STANDARD ) ); \ + } + +#define APPLY_VER_JUSTIFY(j) \ + { \ + if ( !pVerJustify || (eVerJustify != (j) ) ) \ + pTabViewShell->ApplyAttr( SvxVerJustifyItem( (j) ) ); \ + else \ + pTabViewShell->ApplyAttr( SvxVerJustifyItem( SVX_VER_JUSTIFY_STANDARD ) ); \ + } + +void ScFormatShell::ExecuteAlignment( SfxRequest& rReq ) +{ + ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell(); + SfxBindings& rBindings = pViewData->GetBindings(); + const SfxItemSet* pSet = rReq.GetArgs(); + sal_uInt16 nSlot = rReq.GetSlot(); + + pTabViewShell->HideListBox(); // Autofilter-DropDown-Listbox + + switch( nSlot ) + { + // pseudo slots for Format menu + case SID_ALIGN_ANY_HDEFAULT: + case SID_ALIGN_ANY_LEFT: + case SID_ALIGN_ANY_HCENTER: + case SID_ALIGN_ANY_RIGHT: + case SID_ALIGN_ANY_JUSTIFIED: + pTabViewShell->ApplyAttr( SvxHorJustifyItem( lclConvertSlotToHAlign( nSlot ), ATTR_HOR_JUSTIFY ) ); + break; + case SID_ALIGN_ANY_VDEFAULT: + case SID_ALIGN_ANY_TOP: + case SID_ALIGN_ANY_VCENTER: + case SID_ALIGN_ANY_BOTTOM: + pTabViewShell->ApplyAttr( SvxVerJustifyItem( lclConvertSlotToVAlign( nSlot ), ATTR_VER_JUSTIFY ) ); + break; + + default: + if( pSet ) + { + const SfxPoolItem* pItem = NULL; + if( pSet->GetItemState(GetPool().GetWhich(nSlot), sal_True, &pItem ) == SFX_ITEM_SET ) + { + + switch ( nSlot ) + { + case SID_ATTR_ALIGN_HOR_JUSTIFY: + case SID_ATTR_ALIGN_VER_JUSTIFY: + case SID_ATTR_ALIGN_INDENT: + case SID_ATTR_ALIGN_HYPHENATION: + case SID_ATTR_ALIGN_DEGREES: + case SID_ATTR_ALIGN_LOCKPOS: + case SID_ATTR_ALIGN_MARGIN: + case SID_ATTR_ALIGN_STACKED: + pTabViewShell->ApplyAttr( *pItem ); + break; + + case SID_H_ALIGNCELL: + { + SvxCellHorJustify eJust = (SvxCellHorJustify)((const SvxHorJustifyItem*)pItem)->GetValue(); + // #i78476# update alignment of text in cell edit mode + pTabViewShell->UpdateInputHandlerCellAdjust( eJust ); + pTabViewShell->ApplyAttr( SvxHorJustifyItem( eJust, ATTR_HOR_JUSTIFY ) ); + } + break; + case SID_V_ALIGNCELL: + pTabViewShell->ApplyAttr( SvxVerJustifyItem( (SvxCellVerJustify)((const SvxVerJustifyItem*)pItem)->GetValue(), ATTR_VER_JUSTIFY ) ); + break; + default: + DBG_ERROR( "ExecuteAlignment: invalid slot" ); + return; + } + } + } + } + + rBindings.Invalidate( SID_ALIGNLEFT ); + rBindings.Invalidate( SID_ALIGNRIGHT ); + rBindings.Invalidate( SID_ALIGNCENTERHOR ); + rBindings.Invalidate( SID_ALIGNBLOCK ); + rBindings.Invalidate( SID_ALIGNTOP ); + rBindings.Invalidate( SID_ALIGNBOTTOM ); + rBindings.Invalidate( SID_ALIGNCENTERVER ); + rBindings.Invalidate( SID_V_ALIGNCELL ); + rBindings.Invalidate( SID_H_ALIGNCELL ); + // pseudo slots for Format menu + rBindings.Invalidate( SID_ALIGN_ANY_HDEFAULT ); + rBindings.Invalidate( SID_ALIGN_ANY_LEFT ); + rBindings.Invalidate( SID_ALIGN_ANY_HCENTER ); + rBindings.Invalidate( SID_ALIGN_ANY_RIGHT ); + rBindings.Invalidate( SID_ALIGN_ANY_JUSTIFIED ); + rBindings.Invalidate( SID_ALIGN_ANY_VDEFAULT ); + rBindings.Invalidate( SID_ALIGN_ANY_TOP ); + rBindings.Invalidate( SID_ALIGN_ANY_VCENTER ); + rBindings.Invalidate( SID_ALIGN_ANY_BOTTOM ); + rBindings.Update(); + + if( ! rReq.IsAPI() ) + rReq.Done(); +} + +void ScFormatShell::ExecuteTextAttr( SfxRequest& rReq ) +{ + ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell(); + SfxBindings& rBindings = pViewData->GetBindings(); + const ScPatternAttr* pAttrs = pTabViewShell->GetSelectionPattern(); + const SfxItemSet* pSet = rReq.GetArgs(); + sal_uInt16 nSlot = rReq.GetSlot(); + SfxAllItemSet* pNewSet = 0; + + pTabViewShell->HideListBox(); // Autofilter-DropDown-Listbox + + if ( (nSlot == SID_ATTR_CHAR_WEIGHT) + ||(nSlot == SID_ATTR_CHAR_POSTURE) + ||(nSlot == SID_ATTR_CHAR_UNDERLINE) + ||(nSlot == SID_ULINE_VAL_NONE) + ||(nSlot == SID_ULINE_VAL_SINGLE) + ||(nSlot == SID_ULINE_VAL_DOUBLE) + ||(nSlot == SID_ULINE_VAL_DOTTED) ) + { + pNewSet = new SfxAllItemSet( GetPool() ); + + switch ( nSlot ) + { + case SID_ATTR_CHAR_WEIGHT: + { + // #i78017 establish the same behaviour as in Writer + sal_uInt8 nScript = SCRIPTTYPE_LATIN | SCRIPTTYPE_ASIAN | SCRIPTTYPE_COMPLEX; + + SfxItemPool& rPool = GetPool(); + SvxScriptSetItem aSetItem( nSlot, rPool ); + if ( pSet ) + aSetItem.PutItemForScriptType( nScript, pSet->Get( ATTR_FONT_WEIGHT ) ); + else + { + // toggle manually + + FontWeight eWeight = WEIGHT_BOLD; + SvxScriptSetItem aOldSetItem( nSlot, rPool ); + aOldSetItem.GetItemSet().Put( pAttrs->GetItemSet(), sal_False ); + const SfxPoolItem* pCore = aOldSetItem.GetItemOfScript( nScript ); + if ( pCore && ((const SvxWeightItem*)pCore)->GetWeight() == WEIGHT_BOLD ) + eWeight = WEIGHT_NORMAL; + + aSetItem.PutItemForScriptType( nScript, SvxWeightItem( eWeight, ATTR_FONT_WEIGHT ) ); + } + pTabViewShell->ApplyUserItemSet( aSetItem.GetItemSet() ); + pNewSet->Put( aSetItem.GetItemSet(), sal_False ); + } + break; + + case SID_ATTR_CHAR_POSTURE: + { + // #i78017 establish the same behaviour as in Writer + sal_uInt8 nScript = SCRIPTTYPE_LATIN | SCRIPTTYPE_ASIAN | SCRIPTTYPE_COMPLEX; + + SfxItemPool& rPool = GetPool(); + SvxScriptSetItem aSetItem( nSlot, rPool ); + if ( pSet ) + aSetItem.PutItemForScriptType( nScript, pSet->Get( ATTR_FONT_POSTURE ) ); + else + { + // toggle manually + + FontItalic eItalic = ITALIC_NORMAL; + SvxScriptSetItem aOldSetItem( nSlot, rPool ); + aOldSetItem.GetItemSet().Put( pAttrs->GetItemSet(), sal_False ); + const SfxPoolItem* pCore = aOldSetItem.GetItemOfScript( nScript ); + if ( pCore && ((const SvxPostureItem*)pCore)->GetPosture() == ITALIC_NORMAL ) + eItalic = ITALIC_NONE; + + aSetItem.PutItemForScriptType( nScript, SvxPostureItem( eItalic, ATTR_FONT_POSTURE ) ); + } + pTabViewShell->ApplyUserItemSet( aSetItem.GetItemSet() ); + pNewSet->Put( aSetItem.GetItemSet(), sal_False ); + } + break; + + case SID_ATTR_CHAR_UNDERLINE: + { + FontUnderline eUnderline; + + if( pSet ) + { + const SvxUnderlineItem& rUnderline = (const SvxUnderlineItem&)pSet->Get( ATTR_FONT_UNDERLINE ); + + if( rUnderline.ISA(SvxUnderlineItem) ) + { + pTabViewShell->ApplyAttr( rUnderline ); + pNewSet->Put( rUnderline,rUnderline.Which() ); + } + } + else + { + SvxUnderlineItem aUnderline( (const SvxUnderlineItem&) + pAttrs->GetItem( + ATTR_FONT_UNDERLINE ) ); + eUnderline = (UNDERLINE_NONE != aUnderline.GetLineStyle()) + ? UNDERLINE_NONE + : UNDERLINE_SINGLE; + aUnderline.SetLineStyle( eUnderline ); + pTabViewShell->ApplyAttr( aUnderline ); + pNewSet->Put( aUnderline,aUnderline.Which() ); + } + } + break; + + case SID_ULINE_VAL_NONE: + pTabViewShell->ApplyAttr( SvxUnderlineItem( UNDERLINE_NONE, ATTR_FONT_UNDERLINE ) ); + break; + case SID_ULINE_VAL_SINGLE: // Toggles + case SID_ULINE_VAL_DOUBLE: + case SID_ULINE_VAL_DOTTED: + { + FontUnderline eOld = ((const SvxUnderlineItem&) + pAttrs->GetItem(ATTR_FONT_UNDERLINE)).GetLineStyle(); + FontUnderline eNew = eOld; + switch (nSlot) + { + case SID_ULINE_VAL_SINGLE: + eNew = ( eOld == UNDERLINE_SINGLE ) ? UNDERLINE_NONE : UNDERLINE_SINGLE; + break; + case SID_ULINE_VAL_DOUBLE: + eNew = ( eOld == UNDERLINE_DOUBLE ) ? UNDERLINE_NONE : UNDERLINE_DOUBLE; + break; + case SID_ULINE_VAL_DOTTED: + eNew = ( eOld == UNDERLINE_DOTTED ) ? UNDERLINE_NONE : UNDERLINE_DOTTED; + break; + } + pTabViewShell->ApplyAttr( SvxUnderlineItem( eNew, ATTR_FONT_UNDERLINE ) ); + } + break; + + default: + break; + } + rBindings.Invalidate( nSlot ); + } + else + { + /* + * "Selbstgemachte" RadioButton-Funktionalitaet + * Beim Toggle gibt es den Standard-State, d.h. kein + * Button ist gedrueckt + */ + + const SfxItemSet& rAttrSet = pTabViewShell->GetSelectionPattern()->GetItemSet(); + const SfxPoolItem* pItem = NULL; + const SvxHorJustifyItem* pHorJustify = NULL; + const SvxVerJustifyItem* pVerJustify = NULL; + SvxCellHorJustify eHorJustify = SVX_HOR_JUSTIFY_STANDARD; + SvxCellVerJustify eVerJustify = SVX_VER_JUSTIFY_STANDARD; + + if (rAttrSet.GetItemState(ATTR_HOR_JUSTIFY, sal_True,&pItem ) == SFX_ITEM_SET) + { + pHorJustify = (const SvxHorJustifyItem*)pItem; + eHorJustify = SvxCellHorJustify( pHorJustify->GetValue() ); + } + if (rAttrSet.GetItemState(ATTR_VER_JUSTIFY, sal_True,&pItem ) == SFX_ITEM_SET) + { + pVerJustify = (const SvxVerJustifyItem*)pItem; + eVerJustify = SvxCellVerJustify( pVerJustify->GetValue() ); + } + + switch ( nSlot ) + { + case SID_ALIGNLEFT: + rReq.SetSlot( SID_H_ALIGNCELL ); + rReq.AppendItem( SvxHorJustifyItem( + !pHorJustify || (eHorJustify != SVX_HOR_JUSTIFY_LEFT) ? + SVX_HOR_JUSTIFY_LEFT : SVX_HOR_JUSTIFY_STANDARD, SID_H_ALIGNCELL ) ); + ExecuteSlot( rReq, GetInterface() ); + return; +// APPLY_HOR_JUSTIFY( SVX_HOR_JUSTIFY_LEFT ); + //break; + + case SID_ALIGNRIGHT: + rReq.SetSlot( SID_H_ALIGNCELL ); + rReq.AppendItem( SvxHorJustifyItem( + !pHorJustify || (eHorJustify != SVX_HOR_JUSTIFY_RIGHT) ? + SVX_HOR_JUSTIFY_RIGHT : SVX_HOR_JUSTIFY_STANDARD, SID_H_ALIGNCELL ) ); + ExecuteSlot( rReq, GetInterface() ); + return; +// APPLY_HOR_JUSTIFY( SVX_HOR_JUSTIFY_RIGHT ); + //break; + + case SID_ALIGNCENTERHOR: + rReq.SetSlot( SID_H_ALIGNCELL ); + rReq.AppendItem( SvxHorJustifyItem( + !pHorJustify || (eHorJustify != SVX_HOR_JUSTIFY_CENTER) ? + SVX_HOR_JUSTIFY_CENTER : SVX_HOR_JUSTIFY_STANDARD, SID_H_ALIGNCELL ) ); + ExecuteSlot( rReq, GetInterface() ); + return; +// APPLY_HOR_JUSTIFY( SVX_HOR_JUSTIFY_CENTER ); + //break; + + case SID_ALIGNBLOCK: + rReq.SetSlot( SID_H_ALIGNCELL ); + rReq.AppendItem( SvxHorJustifyItem( + !pHorJustify || (eHorJustify != SVX_HOR_JUSTIFY_BLOCK) ? + SVX_HOR_JUSTIFY_BLOCK : SVX_HOR_JUSTIFY_STANDARD, SID_H_ALIGNCELL ) ); + ExecuteSlot( rReq, GetInterface() ); + return; +// APPLY_HOR_JUSTIFY( SVX_HOR_JUSTIFY_BLOCK ); + //break; + + case SID_ALIGNTOP: + rReq.SetSlot( SID_V_ALIGNCELL ); + rReq.AppendItem( SvxVerJustifyItem( + !pVerJustify || (eVerJustify != SVX_VER_JUSTIFY_TOP) ? + SVX_VER_JUSTIFY_TOP : SVX_VER_JUSTIFY_STANDARD, SID_V_ALIGNCELL ) ); + ExecuteSlot( rReq, GetInterface() ); + return; +// APPLY_VER_JUSTIFY( SVX_VER_JUSTIFY_TOP ); + //break; + + case SID_ALIGNBOTTOM: + rReq.SetSlot( SID_V_ALIGNCELL ); + rReq.AppendItem( SvxVerJustifyItem( + !pVerJustify || (eVerJustify != SVX_VER_JUSTIFY_BOTTOM) ? + SVX_VER_JUSTIFY_BOTTOM : SVX_VER_JUSTIFY_STANDARD, SID_V_ALIGNCELL ) ); + ExecuteSlot( rReq, GetInterface() ); + return; +// APPLY_VER_JUSTIFY( SVX_VER_JUSTIFY_BOTTOM ); + //break; + + case SID_ALIGNCENTERVER: + rReq.SetSlot( SID_V_ALIGNCELL ); + rReq.AppendItem( SvxVerJustifyItem( + !pVerJustify || (eVerJustify != SVX_VER_JUSTIFY_CENTER) ? + SVX_VER_JUSTIFY_CENTER : SVX_VER_JUSTIFY_STANDARD, SID_V_ALIGNCELL ) ); + ExecuteSlot( rReq, GetInterface() ); + return; +// APPLY_VER_JUSTIFY( SVX_VER_JUSTIFY_CENTER ); + //break; + + default: + break; + } + + } + + rBindings.Update(); +// rReq.Done(); + + if( pNewSet ) + { + rReq.Done( *pNewSet ); + delete pNewSet; + } + else + { + rReq.Done(); + } + +} + +#undef APPLY_HOR_JUSTIFY +#undef APPLY_VER_JUSTIFY + +//------------------------------------------------------------------ + +void ScFormatShell::ExecuteAttr( SfxRequest& rReq ) +{ + ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell(); + SfxBindings& rBindings = pViewData->GetBindings(); + const SfxItemSet* pNewAttrs = rReq.GetArgs(); + + pTabViewShell->HideListBox(); // Autofilter-DropDown-Listbox + + if ( !pNewAttrs ) + { + sal_uInt16 nSlot = rReq.GetSlot(); + + switch ( nSlot ) + { + case SID_ATTR_CHAR_FONT: + case SID_ATTR_CHAR_FONTHEIGHT: + pTabViewShell->ExecuteCellFormatDlg( rReq, TP_FONT ); // wenn ToolBar vertikal + break; + + case SID_ATTR_ALIGN_LINEBREAK: // ohne Parameter als Toggle + { + const ScPatternAttr* pAttrs = pTabViewShell->GetSelectionPattern(); + sal_Bool bOld = ((const SfxBoolItem&)pAttrs->GetItem(ATTR_LINEBREAK)).GetValue(); + SfxBoolItem aBreakItem( ATTR_LINEBREAK, !bOld ); + pTabViewShell->ApplyAttr( aBreakItem ); + + SfxAllItemSet aNewSet( GetPool() ); + aNewSet.Put( aBreakItem,aBreakItem.Which() ); + rReq.Done( aNewSet ); + + rBindings.Invalidate( nSlot ); + } + break; + + case SID_BACKGROUND_COLOR: + { + // SID_BACKGROUND_COLOR without arguments -> set transparent background + + SvxBrushItem aBrushItem( (const SvxBrushItem&) + pTabViewShell->GetSelectionPattern()-> + GetItem( ATTR_BACKGROUND ) ); + + aBrushItem.SetColor( COL_TRANSPARENT ); + + pTabViewShell->ApplyAttr( aBrushItem ); + } + break; + } + } + else + { + sal_uInt16 nSlot = rReq.GetSlot(); + + switch ( nSlot ) + { + case SID_ATTR_CHAR_OVERLINE: + case SID_ATTR_CHAR_STRIKEOUT: + case SID_ATTR_ALIGN_LINEBREAK: + case SID_ATTR_CHAR_COLOR: + case SID_ATTR_CHAR_CONTOUR: + case SID_ATTR_CHAR_SHADOWED: + case SID_ATTR_CHAR_RELIEF: + case SID_SCATTR_PROTECTION : + pTabViewShell->ApplyAttr( pNewAttrs->Get( pNewAttrs->GetPool()->GetWhich( nSlot ) ) ); + rBindings.Invalidate( nSlot ); + rBindings.Update( nSlot ); + break; + + case SID_ATTR_CHAR_FONT: + case SID_ATTR_CHAR_FONTHEIGHT: + { + // #i78017 establish the same behaviour as in Writer + sal_uInt8 nScript = SCRIPTTYPE_LATIN | SCRIPTTYPE_ASIAN | SCRIPTTYPE_COMPLEX; + if (nSlot == SID_ATTR_CHAR_FONT) + nScript = pTabViewShell->GetSelectionScriptType(); + + SfxItemPool& rPool = GetPool(); + SvxScriptSetItem aSetItem( nSlot, rPool ); + sal_uInt16 nWhich = rPool.GetWhich( nSlot ); + aSetItem.PutItemForScriptType( nScript, pNewAttrs->Get( nWhich ) ); + + pTabViewShell->ApplyUserItemSet( aSetItem.GetItemSet() ); + + rBindings.Invalidate( nSlot ); + rBindings.Update( nSlot ); + } + break; + + case SID_FRAME_LINESTYLE: + { + // Default-Linie aktualisieren + const SvxBorderLine* pLine = + ((const SvxLineItem&) + pNewAttrs->Get( SID_FRAME_LINESTYLE )). + GetLine(); + + if ( pLine ) + { + SvxBorderLine* pDefLine = pTabViewShell->GetDefaultFrameLine(); + + if ( pDefLine ) + { + pDefLine->SetOutWidth( pLine->GetOutWidth() ); + pDefLine->SetInWidth ( pLine->GetInWidth() ); + pDefLine->SetDistance( pLine->GetDistance() ); + pTabViewShell->SetSelectionFrameLines( pDefLine, sal_False ); + } + else + { + pTabViewShell->SetDefaultFrameLine( pLine ); + pTabViewShell->GetDefaultFrameLine()->SetColor( COL_BLACK ); + pTabViewShell->SetSelectionFrameLines( pLine, sal_False ); + } + } + else + { + Color aColorBlack( COL_BLACK ); + SvxBorderLine aDefLine( &aColorBlack, 20, 0, 0 ); + pTabViewShell->SetDefaultFrameLine( &aDefLine ); + pTabViewShell->SetSelectionFrameLines( NULL, sal_False ); + } + } + break; + + case SID_FRAME_LINECOLOR: + { + SvxBorderLine* pDefLine = pTabViewShell->GetDefaultFrameLine(); + const Color& rColor = ((const SvxColorItem&) + pNewAttrs->Get( SID_FRAME_LINECOLOR )). + GetValue(); + + // Default-Linie aktualisieren + if ( pDefLine ) + { + pDefLine->SetColor( rColor ); + pTabViewShell->SetSelectionFrameLines( pDefLine, sal_True ); + } + else + { + SvxBorderLine aDefLine( &rColor, 20, 0, 0 ); + pTabViewShell->SetDefaultFrameLine( &aDefLine ); + pTabViewShell->SetSelectionFrameLines( &aDefLine, sal_False ); + } + } + break; + + case SID_ATTR_BORDER_OUTER: + case SID_ATTR_BORDER: + { + SvxBorderLine* pDefLine = pTabViewShell->GetDefaultFrameLine(); + const ScPatternAttr* pOldAttrs = pTabViewShell->GetSelectionPattern(); + ScDocument* pDoc = GetViewData()->GetDocument(); + SfxItemSet* pOldSet = + new SfxItemSet( + *(pDoc->GetPool()), + ATTR_PATTERN_START, + ATTR_PATTERN_END ); + SfxItemSet* pNewSet = + new SfxItemSet( + *(pDoc->GetPool()), + ATTR_PATTERN_START, + ATTR_PATTERN_END ); + const SfxPoolItem& rBorderAttr = + pOldAttrs->GetItemSet(). + Get( ATTR_BORDER ); + + // Border-Items vom Controller auswerten: + const SfxPoolItem* pItem = 0; + + if ( pNewAttrs->GetItemState( ATTR_BORDER, sal_True, &pItem ) + == SFX_ITEM_SET ) + { + // #100959# The SvxFrameToolBoxControl toolbox controller uses a default + // SvxBorderLine (all widths 0) to mark the lines that should be set. + // Macro recording uses a SvxBoxItem with the real values (OutWidth > 0) + // or NULL pointers for no lines. + // -> Substitute existing lines with pDefLine only if widths are 0. + SvxBoxItem aBoxItem ( *(const SvxBoxItem*)pItem ); + if ( aBoxItem.GetTop() && aBoxItem.GetTop()->GetOutWidth() == 0 ) + aBoxItem.SetLine( pDefLine, BOX_LINE_TOP ); + if ( aBoxItem.GetBottom() && aBoxItem.GetBottom()->GetOutWidth() == 0 ) + aBoxItem.SetLine( pDefLine, BOX_LINE_BOTTOM ); + if ( aBoxItem.GetLeft() && aBoxItem.GetLeft()->GetOutWidth() == 0 ) + aBoxItem.SetLine( pDefLine, BOX_LINE_LEFT ); + if ( aBoxItem.GetRight() && aBoxItem.GetRight()->GetOutWidth() == 0 ) + aBoxItem.SetLine( pDefLine, BOX_LINE_RIGHT ); + pNewSet->Put( aBoxItem ); + rReq.AppendItem( aBoxItem ); + } + + if ( pNewAttrs->GetItemState( ATTR_BORDER_INNER, sal_True, &pItem ) + == SFX_ITEM_SET ) + { + SvxBoxInfoItem aBoxInfoItem( *(const SvxBoxInfoItem*)pItem ); + if ( aBoxInfoItem.GetHori() && aBoxInfoItem.GetHori()->GetOutWidth() == 0 ) + aBoxInfoItem.SetLine( pDefLine, BOXINFO_LINE_HORI ); + if ( aBoxInfoItem.GetVert() && aBoxInfoItem.GetVert()->GetOutWidth() == 0 ) + aBoxInfoItem.SetLine( pDefLine, BOXINFO_LINE_VERT ); + pNewSet->Put( aBoxInfoItem ); + rReq.AppendItem( aBoxInfoItem ); + } + else + { + SvxBoxInfoItem aBoxInfoItem( ATTR_BORDER_INNER ); + aBoxInfoItem.SetLine( NULL, BOXINFO_LINE_HORI ); + aBoxInfoItem.SetLine( NULL, BOXINFO_LINE_VERT ); + pNewSet->Put( aBoxInfoItem ); + } + + pOldSet->Put( rBorderAttr ); + pTabViewShell->ApplyAttributes( pNewSet, pOldSet ); + + delete pOldSet; + delete pNewSet; + } + break; + + // ATTR_BACKGROUND (=SID_ATTR_BRUSH) muss ueber zwei IDs + // gesetzt werden: + case SID_BACKGROUND_COLOR: + { + const SvxColorItem rNewColorItem = (const SvxColorItem&) + pNewAttrs->Get( SID_BACKGROUND_COLOR ); + + SvxBrushItem aBrushItem( (const SvxBrushItem&) + pTabViewShell->GetSelectionPattern()-> + GetItem( ATTR_BACKGROUND ) ); + + aBrushItem.SetColor( rNewColorItem.GetValue() ); + + pTabViewShell->ApplyAttr( aBrushItem ); + } + break; + + case SID_ATTR_BRUSH: + { + SvxBrushItem aBrushItem( (const SvxBrushItem&) + pTabViewShell->GetSelectionPattern()-> + GetItem( ATTR_BACKGROUND ) ); + const SvxBrushItem& rNewBrushItem = (const SvxBrushItem&) + pNewAttrs->Get( GetPool().GetWhich(nSlot) ); + aBrushItem.SetColor(rNewBrushItem.GetColor()); + pTabViewShell->ApplyAttr( aBrushItem ); + } + break; + + case SID_ATTR_BORDER_SHADOW: + { + const SvxShadowItem& rNewShadowItem = (const SvxShadowItem&) + pNewAttrs->Get( ATTR_SHADOW ); + pTabViewShell->ApplyAttr( rNewShadowItem ); + } + break; + + default: + break; + } + + if( ! rReq.IsAPI() ) + if( ! rReq.IsDone() ) + rReq.Done(); + } +} + +void ScFormatShell::GetAttrState( SfxItemSet& rSet ) +{ + ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell(); + const SfxItemSet& rAttrSet = pTabViewShell->GetSelectionPattern()->GetItemSet(); + const SvxBorderLine* pLine = pTabViewShell->GetDefaultFrameLine(); + const SvxBrushItem& rBrushItem = (const SvxBrushItem&)rAttrSet.Get( ATTR_BACKGROUND ); + SfxWhichIter aIter( rSet ); + sal_uInt16 nWhich = aIter.FirstWhich(); + + rSet.Put( rAttrSet, sal_False ); + + // choose font info according to selection script type + sal_uInt8 nScript = 0; // GetSelectionScriptType never returns 0 + if ( rSet.GetItemState( ATTR_FONT ) != SFX_ITEM_UNKNOWN ) + { + if (!nScript) nScript = pTabViewShell->GetSelectionScriptType(); + ScViewUtil::PutItemScript( rSet, rAttrSet, ATTR_FONT, nScript ); + } + if ( rSet.GetItemState( ATTR_FONT_HEIGHT ) != SFX_ITEM_UNKNOWN ) + { + if (!nScript) nScript = pTabViewShell->GetSelectionScriptType(); + ScViewUtil::PutItemScript( rSet, rAttrSet, ATTR_FONT_HEIGHT, nScript ); + } + + while ( nWhich ) + { + switch(nWhich) + { + case SID_BACKGROUND_COLOR: + { + rSet.Put( SvxColorItem( rBrushItem.GetColor(), SID_BACKGROUND_COLOR ) ); + } + break; + case SID_FRAME_LINECOLOR: + { + rSet.Put( SvxColorItem( pLine ? pLine->GetColor() : Color(), SID_FRAME_LINECOLOR ) ); + } + break; + case SID_ATTR_BRUSH: + { + rSet.Put( rBrushItem, GetPool().GetWhich(nWhich) ); + } + break; +/* case SID_ATTR_ALIGN_LINEBREAK: + { + const SfxBoolItem& rBreakItem = (const SfxBoolItem&)rAttrSet.Get( ATTR_LINEBREAK ); + rSet.Put( rBreakItem, GetPool().GetWhich(nWhich) ); + } + break; +*/ + } + nWhich = aIter.NextWhich(); + } +} + +//------------------------------------------------------------------ + +void ScFormatShell::GetTextAttrState( SfxItemSet& rSet ) +{ + ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell(); + const SfxItemSet& rAttrSet = pTabViewShell->GetSelectionPattern()->GetItemSet(); + rSet.Put( rAttrSet, sal_False ); // ItemStates mitkopieren + + // choose font info according to selection script type + sal_uInt8 nScript = 0; // GetSelectionScriptType never returns 0 + if ( rSet.GetItemState( ATTR_FONT_WEIGHT ) != SFX_ITEM_UNKNOWN ) + { + if (!nScript) nScript = pTabViewShell->GetSelectionScriptType(); + ScViewUtil::PutItemScript( rSet, rAttrSet, ATTR_FONT_WEIGHT, nScript ); + } + if ( rSet.GetItemState( ATTR_FONT_POSTURE ) != SFX_ITEM_UNKNOWN ) + { + if (!nScript) nScript = pTabViewShell->GetSelectionScriptType(); + ScViewUtil::PutItemScript( rSet, rAttrSet, ATTR_FONT_POSTURE, nScript ); + } + + SfxItemState eState; +// const SfxPoolItem* pItem; + + //-------------------------------------------------------------------- + // eigene Kontrolle ueber RadioButton-Funktionalitaet: + //-------------------------------------------------------------------- + // Unterstreichung + //------------------------ + + eState = rAttrSet.GetItemState( ATTR_FONT_UNDERLINE, sal_True ); + if ( eState == SFX_ITEM_DONTCARE ) + { + rSet.InvalidateItem( SID_ULINE_VAL_NONE ); + rSet.InvalidateItem( SID_ULINE_VAL_SINGLE ); + rSet.InvalidateItem( SID_ULINE_VAL_DOUBLE ); + rSet.InvalidateItem( SID_ULINE_VAL_DOTTED ); + } + else + { + FontUnderline eUnderline = ((const SvxUnderlineItem&) + rAttrSet.Get(ATTR_FONT_UNDERLINE)).GetLineStyle(); + sal_uInt16 nId = SID_ULINE_VAL_NONE; + switch (eUnderline) + { + case UNDERLINE_SINGLE: nId = SID_ULINE_VAL_SINGLE; break; + case UNDERLINE_DOUBLE: nId = SID_ULINE_VAL_DOUBLE; break; + case UNDERLINE_DOTTED: nId = SID_ULINE_VAL_DOTTED; break; + default: + break; + } + rSet.Put( SfxBoolItem( nId, sal_True ) ); + } + + //------------------------ + // horizontale Ausrichtung + //------------------------ + + const SvxHorJustifyItem* pHorJustify = NULL; + const SvxVerJustifyItem* pVerJustify = NULL; + SvxCellHorJustify eHorJustify = SVX_HOR_JUSTIFY_STANDARD; + SvxCellVerJustify eVerJustify = SVX_VER_JUSTIFY_STANDARD; + sal_uInt16 nWhich = 0; + sal_Bool bJustifyStd = sal_False; + SfxBoolItem aBoolItem ( 0, sal_True ); + + eState = rAttrSet.GetItemState( ATTR_HOR_JUSTIFY, sal_True, + (const SfxPoolItem**)&pHorJustify ); + switch ( eState ) + { + case SFX_ITEM_SET: + { + eHorJustify = SvxCellHorJustify( pHorJustify->GetValue() ); + + switch ( SvxCellHorJustify( pHorJustify->GetValue() ) ) + { + case SVX_HOR_JUSTIFY_STANDARD: + break; + + case SVX_HOR_JUSTIFY_LEFT: + nWhich = SID_ALIGNLEFT; + break; + + case SVX_HOR_JUSTIFY_RIGHT: + nWhich = SID_ALIGNRIGHT; + break; + + case SVX_HOR_JUSTIFY_CENTER: + nWhich = SID_ALIGNCENTERHOR; + break; + + case SVX_HOR_JUSTIFY_BLOCK: + nWhich = SID_ALIGNBLOCK; + break; + + case SVX_HOR_JUSTIFY_REPEAT: + default: + bJustifyStd = sal_True; + break; + } + } + break; + + case SFX_ITEM_DONTCARE: + rSet.InvalidateItem( SID_ALIGNLEFT ); + rSet.InvalidateItem( SID_ALIGNRIGHT ); + rSet.InvalidateItem( SID_ALIGNCENTERHOR ); + rSet.InvalidateItem( SID_ALIGNBLOCK ); + break; + + default: + bJustifyStd = sal_True; + break; + } + + if ( nWhich ) + { + aBoolItem.SetWhich( nWhich ); + rSet.Put( aBoolItem ); + } + else if ( bJustifyStd ) + { + aBoolItem.SetValue( sal_False ); + aBoolItem.SetWhich( SID_ALIGNLEFT ); rSet.Put( aBoolItem ); + aBoolItem.SetWhich( SID_ALIGNRIGHT ); rSet.Put( aBoolItem ); + aBoolItem.SetWhich( SID_ALIGNCENTERHOR ); rSet.Put( aBoolItem ); + aBoolItem.SetWhich( SID_ALIGNBLOCK ); rSet.Put( aBoolItem ); + bJustifyStd = sal_False; + } + + //------------------------ + // vertikale Ausrichtung + //------------------------ + + nWhich = 0; + aBoolItem.SetValue( sal_True ); + + eState = rAttrSet.GetItemState( ATTR_VER_JUSTIFY, sal_True, + (const SfxPoolItem**)&pVerJustify ); + + switch ( eState ) + { + case SFX_ITEM_SET: + { + eVerJustify = SvxCellVerJustify( pVerJustify->GetValue() ); + + switch ( eVerJustify ) + { + case SVX_VER_JUSTIFY_TOP: + nWhich = SID_ALIGNTOP; + break; + + case SVX_VER_JUSTIFY_BOTTOM: + nWhich = SID_ALIGNBOTTOM; + break; + + case SVX_VER_JUSTIFY_CENTER: + nWhich = SID_ALIGNCENTERVER; + break; + + case SVX_VER_JUSTIFY_STANDARD: + default: + bJustifyStd = sal_True; + break; + } + } + break; + + case SFX_ITEM_DONTCARE: + rSet.InvalidateItem( SID_ALIGNTOP ); + rSet.InvalidateItem( SID_ALIGNBOTTOM ); + rSet.InvalidateItem( SID_ALIGNCENTERVER ); + break; + + default: + bJustifyStd = sal_True; + break; + } + + if ( nWhich ) + { + aBoolItem.SetWhich( nWhich ); + rSet.Put( aBoolItem ); + } + else if ( bJustifyStd ) + { + aBoolItem.SetValue( sal_False ); + aBoolItem.SetWhich( SID_ALIGNTOP ); rSet.Put( aBoolItem ); + aBoolItem.SetWhich( SID_ALIGNBOTTOM ); rSet.Put( aBoolItem ); + aBoolItem.SetWhich( SID_ALIGNCENTERVER ); rSet.Put( aBoolItem ); + } +} + + +//------------------------------------------------------------------ + +void ScFormatShell::GetBorderState( SfxItemSet& rSet ) +{ + ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell(); + SvxBoxItem aBoxItem( ATTR_BORDER ); + SvxBoxInfoItem aInfoItem( ATTR_BORDER_INNER ); + + pTabViewShell->GetSelectionFrame( aBoxItem, aInfoItem ); + + if ( rSet.GetItemState( ATTR_BORDER ) != SFX_ITEM_UNKNOWN ) + rSet.Put( aBoxItem ); + if ( rSet.GetItemState( ATTR_BORDER_INNER ) != SFX_ITEM_UNKNOWN ) + rSet.Put( aInfoItem ); +} + +//------------------------------------------------------------------ + +void ScFormatShell::GetAlignState( SfxItemSet& rSet ) +{ + ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell(); + const SfxItemSet& rAttrSet = pTabViewShell->GetSelectionPattern()->GetItemSet(); + SfxWhichIter aIter(rSet); + sal_uInt16 nWhich = aIter.FirstWhich(); + + SvxCellHorJustify eHAlign = SVX_HOR_JUSTIFY_STANDARD; + bool bHasHAlign = rAttrSet.GetItemState( ATTR_HOR_JUSTIFY ) != SFX_ITEM_DONTCARE; + if( bHasHAlign ) + eHAlign = (SvxCellHorJustify)((const SvxHorJustifyItem&) rAttrSet.Get( ATTR_HOR_JUSTIFY )).GetValue(); + + SvxCellVerJustify eVAlign = SVX_VER_JUSTIFY_STANDARD; + bool bHasVAlign = rAttrSet.GetItemState( ATTR_VER_JUSTIFY ) != SFX_ITEM_DONTCARE; + if( bHasVAlign ) + eVAlign = (SvxCellVerJustify)((const SvxVerJustifyItem&) rAttrSet.Get( ATTR_VER_JUSTIFY )).GetValue(); + + while ( nWhich ) + { + switch ( nWhich ) + { + case SID_H_ALIGNCELL: + if ( bHasHAlign ) + rSet.Put( SvxHorJustifyItem( eHAlign, nWhich )); + break; + case SID_V_ALIGNCELL: + if ( bHasVAlign ) + rSet.Put( SvxVerJustifyItem( eVAlign, nWhich )); + break; + + // pseudo slots for Format menu + case SID_ALIGN_ANY_HDEFAULT: + case SID_ALIGN_ANY_LEFT: + case SID_ALIGN_ANY_HCENTER: + case SID_ALIGN_ANY_RIGHT: + case SID_ALIGN_ANY_JUSTIFIED: + rSet.Put( SfxBoolItem( nWhich, bHasHAlign && (eHAlign == lclConvertSlotToHAlign( nWhich )) ) ); + break; + case SID_ALIGN_ANY_VDEFAULT: + case SID_ALIGN_ANY_TOP: + case SID_ALIGN_ANY_VCENTER: + case SID_ALIGN_ANY_BOTTOM: + rSet.Put( SfxBoolItem( nWhich, bHasVAlign && (eVAlign == lclConvertSlotToVAlign( nWhich )) ) ); + break; + } + nWhich = aIter.NextWhich(); + } +} + +void ScFormatShell::GetNumFormatState( SfxItemSet& rSet ) +{ + ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell(); + + // ScViewData* pViewData = GetViewData(); + ScDocument* pDoc = pViewData->GetDocument(); + + SfxWhichIter aIter(rSet); + sal_uInt16 nWhich = aIter.FirstWhich(); + while ( nWhich ) + { + switch ( nWhich ) + { + case SID_NUMBER_FORMAT: + { + String aFormatCode; // bleibt leer, wenn dont-care + + const SfxItemSet& rAttrSet = pTabViewShell->GetSelectionPattern()->GetItemSet(); + if ( rAttrSet.GetItemState( ATTR_VALUE_FORMAT ) != SFX_ITEM_DONTCARE ) + { + sal_uLong nNumberFormat = ((const SfxUInt32Item&)rAttrSet.Get( + ATTR_VALUE_FORMAT )).GetValue(); + + SvNumberFormatter* pFormatter = pDoc->GetFormatTable(); + const SvNumberformat* pFormatEntry = pFormatter->GetEntry( nNumberFormat ); + if ( pFormatEntry ) + aFormatCode = pFormatEntry->GetFormatstring(); + } + + rSet.Put( SfxStringItem( nWhich, aFormatCode ) ); + } + break; + + } + nWhich = aIter.NextWhich(); + } +} + + +void ScFormatShell::ExecuteTextDirection( SfxRequest& rReq ) +{ + ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell(); + pTabViewShell->HideListBox(); // Autofilter-DropDown-Listbox + if ( GetViewData()->HasEditView( GetViewData()->GetActivePart() ) ) + { + SC_MOD()->InputEnterHandler(); + pTabViewShell->UpdateInputHandler(); + } + + sal_uInt16 nSlot = rReq.GetSlot(); + switch( nSlot ) + { + case SID_TEXTDIRECTION_LEFT_TO_RIGHT: + case SID_TEXTDIRECTION_TOP_TO_BOTTOM: + { + sal_Bool bVert = (nSlot == SID_TEXTDIRECTION_TOP_TO_BOTTOM); + ScPatternAttr aAttr( GetViewData()->GetDocument()->GetPool() ); + SfxItemSet& rItemSet = aAttr.GetItemSet(); + rItemSet.Put( SfxBoolItem( ATTR_STACKED, bVert ) ); + rItemSet.Put( SfxBoolItem( ATTR_VERTICAL_ASIAN, bVert ) ); + pTabViewShell->ApplySelectionPattern( aAttr ); + pTabViewShell->AdjustBlockHeight(); + } + break; + + case SID_ATTR_PARA_LEFT_TO_RIGHT: + case SID_ATTR_PARA_RIGHT_TO_LEFT: + { + SvxFrameDirection eDirection = ( nSlot == SID_ATTR_PARA_LEFT_TO_RIGHT ) ? + FRMDIR_HORI_LEFT_TOP : FRMDIR_HORI_RIGHT_TOP; + pTabViewShell->ApplyAttr( SvxFrameDirectionItem( eDirection, ATTR_WRITINGDIR ) ); + } + break; + } +} + +void ScFormatShell::GetTextDirectionState( SfxItemSet& rSet ) +{ + ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell(); + const SfxItemSet& rAttrSet = pTabViewShell->GetSelectionPattern()->GetItemSet(); + + sal_Bool bVertDontCare = + (rAttrSet.GetItemState( ATTR_VERTICAL_ASIAN ) == SFX_ITEM_DONTCARE) || + (rAttrSet.GetItemState( ATTR_STACKED ) == SFX_ITEM_DONTCARE); + sal_Bool bLeftRight = !bVertDontCare && + !((const SfxBoolItem&) rAttrSet.Get( ATTR_STACKED )).GetValue(); + sal_Bool bTopBottom = !bVertDontCare && !bLeftRight && + ((const SfxBoolItem&) rAttrSet.Get( ATTR_VERTICAL_ASIAN )).GetValue(); + + sal_Bool bBidiDontCare = (rAttrSet.GetItemState( ATTR_WRITINGDIR ) == SFX_ITEM_DONTCARE); + EEHorizontalTextDirection eBidiDir = EE_HTEXTDIR_DEFAULT; + if ( !bBidiDontCare ) + { + SvxFrameDirection eCellDir = (SvxFrameDirection)((const SvxFrameDirectionItem&) + rAttrSet.Get( ATTR_WRITINGDIR )).GetValue(); + if ( eCellDir == FRMDIR_ENVIRONMENT ) + eBidiDir = (EEHorizontalTextDirection)GetViewData()->GetDocument()-> + GetEditTextDirection( GetViewData()->GetTabNo() ); + else if ( eCellDir == FRMDIR_HORI_RIGHT_TOP ) + eBidiDir = EE_HTEXTDIR_R2L; + else + eBidiDir = EE_HTEXTDIR_L2R; + } + + SvtLanguageOptions aLangOpt; + sal_Bool bDisableCTLFont = !aLangOpt.IsCTLFontEnabled(); + sal_Bool bDisableVerticalText = !aLangOpt.IsVerticalTextEnabled(); + + SfxWhichIter aIter( rSet ); + sal_uInt16 nWhich = aIter.FirstWhich(); + while( nWhich ) + { + switch( nWhich ) + { + case SID_TEXTDIRECTION_LEFT_TO_RIGHT: + case SID_TEXTDIRECTION_TOP_TO_BOTTOM: + if ( bDisableVerticalText ) + rSet.DisableItem( nWhich ); + else + { + if( bVertDontCare ) + rSet.InvalidateItem( nWhich ); + else if ( nWhich == SID_TEXTDIRECTION_LEFT_TO_RIGHT ) + rSet.Put( SfxBoolItem( nWhich, bLeftRight ) ); + else + rSet.Put( SfxBoolItem( nWhich, bTopBottom ) ); + } + break; + + case SID_ATTR_PARA_LEFT_TO_RIGHT: + case SID_ATTR_PARA_RIGHT_TO_LEFT: + if ( bDisableCTLFont ) + rSet.DisableItem( nWhich ); + else + { + if ( bTopBottom ) + rSet.DisableItem( nWhich ); + else if ( bBidiDontCare ) + rSet.InvalidateItem( nWhich ); + else if ( nWhich == SID_ATTR_PARA_LEFT_TO_RIGHT ) + rSet.Put( SfxBoolItem( nWhich, eBidiDir == EE_HTEXTDIR_L2R ) ); + else + rSet.Put( SfxBoolItem( nWhich, eBidiDir == EE_HTEXTDIR_R2L ) ); + } + } + nWhich = aIter.NextWhich(); + } +} + +void ScFormatShell::ExecFormatPaintbrush( SfxRequest& rReq ) +{ + ScViewFunc* pView = pViewData->GetView(); + if ( pView->HasPaintBrush() ) + { + // cancel paintbrush mode + pView->ResetBrushDocument(); + } + else + { + sal_Bool bLock = sal_False; + const SfxItemSet *pArgs = rReq.GetArgs(); + if( pArgs && pArgs->Count() >= 1 ) + bLock = static_cast<const SfxBoolItem&>(pArgs->Get(SID_FORMATPAINTBRUSH)).GetValue(); + + // in case of multi selection, deselect all and use the cursor position + ScRange aDummy; + if ( pViewData->GetSimpleArea(aDummy) != SC_MARK_SIMPLE ) + pView->Unmark(); + + ScDocument* pBrushDoc = new ScDocument( SCDOCMODE_CLIP ); + pView->CopyToClip( pBrushDoc, sal_False, sal_True ); + pView->SetBrushDocument( pBrushDoc, bLock ); + } +} + +void ScFormatShell::StateFormatPaintbrush( SfxItemSet& rSet ) +{ + if ( pViewData->HasEditView( pViewData->GetActivePart() ) ) + rSet.DisableItem( SID_FORMATPAINTBRUSH ); + else + rSet.Put( SfxBoolItem( SID_FORMATPAINTBRUSH, pViewData->GetView()->HasPaintBrush() ) ); +} + diff --git a/sc/source/ui/view/galwrap.cxx b/sc/source/ui/view/galwrap.cxx new file mode 100644 index 000000000000..2be622ced2c8 --- /dev/null +++ b/sc/source/ui/view/galwrap.cxx @@ -0,0 +1,79 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + + +// INCLUDE --------------------------------------------------------------- + +#include <vcl/graph.hxx> +#include <svx/gallery.hxx> +#include <sfx2/app.hxx> + +// ----------------------------------------------------------------------- + +Graphic GalleryGetGraphic() +{ + GalleryExplorer* pGal = SVX_GALLERY(); + DBG_ASSERT( pGal, "Wo ist die Gallery?" ); + return pGal->GetGraphic(); +} + +sal_uInt16 GallerySGA_FORMAT_GRAPHIC() +{ + return SGA_FORMAT_GRAPHIC; +} + +sal_Bool GalleryIsLinkage() +{ + GalleryExplorer* pGal = SVX_GALLERY(); + DBG_ASSERT( pGal, "Wo ist die Gallery?" ); + return pGal->IsLinkage(); +} + +String GalleryGetFullPath() +{ + GalleryExplorer* pGal = SVX_GALLERY(); + DBG_ASSERT( pGal, "Wo ist die Gallery?" ); +// return pGal->GetPath().GetFull(); + return pGal->GetURL().GetMainURL(INetURLObject::NO_DECODE); + // URL as stored in GraphicLink must be encoded +} + +String GalleryGetFilterName() +{ + GalleryExplorer* pGal = SVX_GALLERY(); + DBG_ASSERT( pGal, "Wo ist die Gallery?" ); + return pGal->GetFilterName(); +} + + + + diff --git a/sc/source/ui/view/gridmerg.cxx b/sc/source/ui/view/gridmerg.cxx new file mode 100644 index 000000000000..6bcc4ad42f30 --- /dev/null +++ b/sc/source/ui/view/gridmerg.cxx @@ -0,0 +1,174 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +#include <vcl/outdev.hxx> + +#include "gridmerg.hxx" + +//------------------------------------------------------------------ + +ScGridMerger::ScGridMerger( OutputDevice* pOutDev, long nOnePixelX, long nOnePixelY ) : + pDev( pOutDev ), + nOneX( nOnePixelX ), + nOneY( nOnePixelY ), + nCount( 0 ), + bVertical( sal_False ) +{ + // optimize (DrawGrid) only for pixel MapMode, + // to avoid rounding errors + + bOptimize = ( pDev->GetMapMode().GetMapUnit() == MAP_PIXEL ); +} + +ScGridMerger::~ScGridMerger() +{ + Flush(); +} + +void ScGridMerger::AddLine( long nStart, long nEnd, long nPos ) +{ + if ( nCount ) + { + // not first line - test fix position + // more than one previous line - test distance + + if ( nStart != nFixStart || nEnd != nFixEnd ) + { + if ( nCount == 1 && nPos == nVarStart && + ( nStart == nFixEnd || + nStart == nFixEnd + ( bVertical ? nOneY : nOneX ) ) ) + { + // additional optimization: extend connected lines + // keep nCount at 1 + nFixEnd = nEnd; + } + else + Flush(); + } + else if ( nCount == 1 ) + { + nVarDiff = nPos - nVarStart; + ++nCount; + } + else if ( nPos != nVarStart + nCount * nVarDiff ) //! keep VarEnd? + Flush(); + else + ++nCount; + } + + if ( !nCount ) + { + // first line (or flushed above) - just store + + nFixStart = nStart; + nFixEnd = nEnd; + nVarStart = nPos; + nVarDiff = 0; + nCount = 1; + } +} + +void ScGridMerger::AddHorLine( long nX1, long nX2, long nY ) +{ + if ( bOptimize ) + { + if ( bVertical ) + { + Flush(); + bVertical = sal_False; + } + AddLine( nX1, nX2, nY ); + } + else + pDev->DrawLine( Point( nX1, nY ), Point( nX2, nY ) ); +} + +void ScGridMerger::AddVerLine( long nX, long nY1, long nY2 ) +{ + if ( bOptimize ) + { + if ( !bVertical ) + { + Flush(); + bVertical = sal_True; + } + AddLine( nY1, nY2, nX ); + } + else + pDev->DrawLine( Point( nX, nY1 ), Point( nX, nY2 ) ); +} + +void ScGridMerger::Flush() +{ + if (nCount) + { + if (bVertical) + { + if ( nCount == 1 ) + pDev->DrawLine( Point( nVarStart, nFixStart ), Point( nVarStart, nFixEnd ) ); + else + { + long nVarEnd = nVarStart + ( nCount - 1 ) * nVarDiff; + if ( nVarDiff < 0 ) + { + // nVarDiff is negative in RTL layout mode + // Change the positions so DrawGrid is called with a positive distance + // (nVarStart / nVarDiff can be modified, aren't used after Flush) + + nVarDiff = -nVarDiff; + long nTemp = nVarStart; + nVarStart = nVarEnd; + nVarEnd = nTemp; + } + pDev->DrawGrid( Rectangle( nVarStart, nFixStart, nVarEnd, nFixEnd ), + Size( nVarDiff, nFixEnd - nFixStart ), + GRID_VERTLINES ); + } + } + else + { + if ( nCount == 1 ) + pDev->DrawLine( Point( nFixStart, nVarStart ), Point( nFixEnd, nVarStart ) ); + else + { + long nVarEnd = nVarStart + ( nCount - 1 ) * nVarDiff; + pDev->DrawGrid( Rectangle( nFixStart, nVarStart, nFixEnd, nVarEnd ), + Size( nFixEnd - nFixStart, nVarDiff ), + GRID_HORZLINES ); + } + } + nCount = 0; + } +} + + + diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx new file mode 100644 index 000000000000..d350da754433 --- /dev/null +++ b/sc/source/ui/view/gridwin.cxx @@ -0,0 +1,5706 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +#include "scitems.hxx" + +#include <memory> //auto_ptr +#include <editeng/adjitem.hxx> +#include <svx/algitem.hxx> +#include <svx/dbexch.hrc> +#include <editeng/editview.hxx> +#include <editeng/editstat.hxx> +#include <editeng/flditem.hxx> +#include <svx/svdetc.hxx> +#include <editeng/editobj.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/docfile.hxx> +#include <svl/stritem.hxx> +#include <svtools/svlbox.hxx> +#include <svtools/svtabbx.hxx> +#include <svl/urlbmk.hxx> +#include <tools/urlobj.hxx> +#include <vcl/cursor.hxx> +#include <vcl/sound.hxx> +#include <vcl/graph.hxx> +#include <vcl/hatch.hxx> +#include <sot/formats.hxx> +#include <sot/clsids.hxx> + +#include <svx/svdview.hxx> // fuer Command-Handler (COMMAND_INSERTTEXT) +#include <editeng/outliner.hxx> // fuer Command-Handler (COMMAND_INSERTTEXT) +#include <svx/svditer.hxx> +#include <svx/svdocapt.hxx> +#include <svx/svdpagv.hxx> + +#include <com/sun/star/sheet/DataPilotFieldFilter.hpp> +#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp> +#include <com/sun/star/sheet/DataPilotTableHeaderData.hpp> +#include <com/sun/star/sheet/DataPilotTableResultData.hpp> +#include <com/sun/star/sheet/DataPilotTablePositionData.hpp> +#include <com/sun/star/sheet/DataPilotTablePositionType.hpp> +#include <com/sun/star/sheet/MemberResultFlags.hpp> +#include <com/sun/star/awt/KeyModifier.hpp> +#include <com/sun/star/awt/MouseButton.hpp> +#include <com/sun/star/script/vba/VBAEventId.hpp> +#include <com/sun/star/script/vba/XVBAEventProcessor.hpp> + +#include "gridwin.hxx" +#include "tabvwsh.hxx" +#include "docsh.hxx" +#include "viewdata.hxx" +#include "tabview.hxx" +#include "select.hxx" +#include "scmod.hxx" +#include "document.hxx" +#include "attrib.hxx" +#include "dbcolect.hxx" +#include "stlpool.hxx" +#include "printfun.hxx" +#include "cbutton.hxx" +#include "sc.hrc" +#include "globstr.hrc" +#include "editutil.hxx" +#include "scresid.hxx" +#include "inputhdl.hxx" +#include "uiitems.hxx" // Filter-Dialog - auslagern !!! +#include "filtdlg.hxx" +#include "impex.hxx" // Sylk-ID fuer CB +#include "cell.hxx" // fuer Edit-Felder +#include "patattr.hxx" +#include "notemark.hxx" +#include "rfindlst.hxx" +#include "docpool.hxx" +#include "output.hxx" +#include "docfunc.hxx" +#include "dbdocfun.hxx" +#include "dpobject.hxx" +#include "dpoutput.hxx" +#include "transobj.hxx" +#include "drwtrans.hxx" +#include "seltrans.hxx" +#include "sizedev.hxx" +#include "AccessibilityHints.hxx" +#include "dpsave.hxx" +#include "viewuno.hxx" +#include "compiler.hxx" +#include "editable.hxx" +#include "fillinfo.hxx" +#include "scitems.hxx" +#include "userdat.hxx" +#include "drwlayer.hxx" +#include "attrib.hxx" +#include "validat.hxx" +#include "tabprotection.hxx" +#include "postit.hxx" +#include "dpcontrol.hxx" +#include "cellsuno.hxx" + +#include "drawview.hxx" +#include <svx/sdrpagewindow.hxx> +#include <svx/sdr/overlay/overlaymanager.hxx> +#include <vcl/svapp.hxx> +#include <svx/sdr/overlay/overlayselection.hxx> + +using namespace com::sun::star; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Any; + +const sal_uInt8 SC_NESTEDBUTTON_NONE = 0; +const sal_uInt8 SC_NESTEDBUTTON_DOWN = 1; +const sal_uInt8 SC_NESTEDBUTTON_UP = 2; + +#define SC_AUTOFILTER_ALL 0 +#define SC_AUTOFILTER_TOP10 1 +#define SC_AUTOFILTER_CUSTOM 2 + +// Modi fuer die FilterListBox +enum ScFilterBoxMode +{ + SC_FILTERBOX_FILTER, + SC_FILTERBOX_DATASELECT, + SC_FILTERBOX_SCENARIO, + SC_FILTERBOX_PAGEFIELD +}; + +extern SfxViewShell* pScActiveViewShell; // global.cxx +extern sal_uInt16 nScClickMouseModifier; // global.cxx +extern sal_uInt16 nScFillModeMouseModifier; // global.cxx + +#define SC_FILTERLISTBOX_LINES 12 + +// ============================================================================ + +ScGridWindow::VisibleRange::VisibleRange() : + mnCol1(0), mnCol2(MAXCOL), mnRow1(0), mnRow2(MAXROW) +{ +} + +bool ScGridWindow::VisibleRange::isInside(SCCOL nCol, SCROW nRow) const +{ + return mnCol1 <= nCol && nCol <= mnCol2 && mnRow1 <= nRow && nRow <= mnRow2; +} + +// ============================================================================ + +class ScFilterListBox : public ListBox +{ +private: + ScGridWindow* pGridWin; + SCCOL nCol; + SCROW nRow; + sal_Bool bButtonDown; + sal_Bool bInit; + sal_Bool bCancelled; + sal_Bool bInSelect; + bool mbListHasDates; + sal_uLong nSel; + ScFilterBoxMode eMode; + +protected: + virtual void LoseFocus(); + void SelectHdl(); + +public: + ScFilterListBox( Window* pParent, ScGridWindow* pGrid, + SCCOL nNewCol, SCROW nNewRow, ScFilterBoxMode eNewMode ); + ~ScFilterListBox(); + + virtual long PreNotify( NotifyEvent& rNEvt ); + virtual void Select(); + + SCCOL GetCol() const { return nCol; } + SCROW GetRow() const { return nRow; } + ScFilterBoxMode GetMode() const { return eMode; } + sal_Bool IsDataSelect() const { return (eMode == SC_FILTERBOX_DATASELECT); } + void EndInit(); + sal_Bool IsInInit() const { return bInit; } + void SetCancelled() { bCancelled = sal_True; } + sal_Bool IsInSelect() const { return bInSelect; } + void SetListHasDates(bool b) { mbListHasDates = b; } + bool HasDates() const { return mbListHasDates; } +}; + +//------------------------------------------------------------------- + +// ListBox in einem FloatingWindow (pParent) +ScFilterListBox::ScFilterListBox( Window* pParent, ScGridWindow* pGrid, + SCCOL nNewCol, SCROW nNewRow, ScFilterBoxMode eNewMode ) : + ListBox( pParent, WB_AUTOHSCROLL ), + pGridWin( pGrid ), + nCol( nNewCol ), + nRow( nNewRow ), + bButtonDown( sal_False ), + bInit( sal_True ), + bCancelled( sal_False ), + bInSelect( sal_False ), + mbListHasDates(false), + nSel( 0 ), + eMode( eNewMode ) +{ +} + +__EXPORT ScFilterListBox::~ScFilterListBox() +{ + if (IsMouseCaptured()) + ReleaseMouse(); +} + +void ScFilterListBox::EndInit() +{ + sal_uInt16 nPos = GetSelectEntryPos(); + if ( LISTBOX_ENTRY_NOTFOUND == nPos ) + nSel = 0; + else + nSel = nPos; + + bInit = sal_False; +} + +void __EXPORT ScFilterListBox::LoseFocus() +{ +#ifndef UNX + Hide(); +#endif +} + +// ----------------------------------------------------------------------- + +long ScFilterListBox::PreNotify( NotifyEvent& rNEvt ) +{ + long nDone = 0; + if ( rNEvt.GetType() == EVENT_KEYINPUT ) + { + KeyEvent aKeyEvt = *rNEvt.GetKeyEvent(); + KeyCode aCode = aKeyEvt.GetKeyCode(); + if ( !aCode.GetModifier() ) // ohne alle Modifiers + { + sal_uInt16 nKey = aCode.GetCode(); + if ( nKey == KEY_RETURN ) + { + SelectHdl(); // auswaehlen + nDone = 1; + } + else if ( nKey == KEY_ESCAPE ) + { + pGridWin->ClickExtern(); // loescht die List-Box !!! + nDone = 1; + } + } + } + + return nDone ? nDone : ListBox::PreNotify( rNEvt ); +} + +void __EXPORT ScFilterListBox::Select() +{ + ListBox::Select(); + SelectHdl(); +} + +void __EXPORT ScFilterListBox::SelectHdl() +{ + if ( !IsTravelSelect() && !bInit && !bCancelled ) + { + sal_uInt16 nPos = GetSelectEntryPos(); + if ( LISTBOX_ENTRY_NOTFOUND != nPos ) + { + nSel = nPos; + if (!bButtonDown) + { + // #i81298# set bInSelect flag, so the box isn't deleted from modifications within FilterSelect + bInSelect = sal_True; + pGridWin->FilterSelect( nSel ); + bInSelect = sal_False; + } + } + } +} + +// ============================================================================ + +// use a System floating window for the above filter listbox +class ScFilterFloatingWindow : public FloatingWindow +{ +public: + ScFilterFloatingWindow( Window* pParent, WinBits nStyle = WB_STDFLOATWIN ); + virtual ~ScFilterFloatingWindow(); + // required for System FloatingWindows that will not process KeyInput by themselves + virtual Window* GetPreferredKeyInputWindow(); +}; + +ScFilterFloatingWindow::ScFilterFloatingWindow( Window* pParent, WinBits nStyle ) : + FloatingWindow( pParent, nStyle|WB_SYSTEMWINDOW ) // make it a system floater + {} + +ScFilterFloatingWindow::~ScFilterFloatingWindow() +{ + EndPopupMode(); +} + +Window* ScFilterFloatingWindow::GetPreferredKeyInputWindow() +{ + // redirect keyinput in the child window + return GetWindow(WINDOW_FIRSTCHILD) ? GetWindow(WINDOW_FIRSTCHILD)->GetPreferredKeyInputWindow() : NULL; // will be the FilterBox +} + +// ============================================================================ + +sal_Bool lcl_IsEditableMatrix( ScDocument* pDoc, const ScRange& rRange ) +{ + // wenn es ein editierbarer Bereich ist, und rechts unten eine Matrix-Zelle + // mit Origin links oben liegt, enthaelt der Bereich genau die Matrix. + //! Direkt die MatrixEdges Funktionen von der Column herausreichen ??? + + if ( !pDoc->IsBlockEditable( rRange.aStart.Tab(), rRange.aStart.Col(),rRange.aStart.Row(), + rRange.aEnd.Col(),rRange.aEnd.Row() ) ) + return sal_False; + + ScAddress aPos; + const ScBaseCell* pCell = pDoc->GetCell( rRange.aEnd ); + return ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA && + ((ScFormulaCell*)pCell)->GetMatrixOrigin(aPos) && aPos == rRange.aStart ); + +} + +void lcl_UnLockComment( ScDrawView* pView, SdrPageView* pPV, SdrModel* pDrDoc, const Point& rPos, ScViewData* pViewData ) +{ + if (!pView && !pPV && !pDrDoc && !pViewData) + return; + + ScDocument& rDoc = *pViewData->GetDocument(); + ScAddress aCellPos( pViewData->GetCurX(), pViewData->GetCurY(), pViewData->GetTabNo() ); + ScPostIt* pNote = rDoc.GetNote( aCellPos ); + SdrObject* pObj = pNote ? pNote->GetCaption() : 0; + if( pObj && pObj->GetLogicRect().IsInside( rPos ) && ScDrawLayer::IsNoteCaption( pObj ) ) + { + const ScProtectionAttr* pProtAttr = static_cast< const ScProtectionAttr* > (rDoc.GetAttr( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab(), ATTR_PROTECTION ) ); + bool bProtectAttr = pProtAttr->GetProtection() || pProtAttr->GetHideCell() ; + bool bProtectDoc = rDoc.IsTabProtected( aCellPos.Tab() ) || pViewData->GetSfxDocShell()->IsReadOnly() ; + // unlock internal layer (if not protected), will be relocked in ScDrawView::MarkListHasChanged() + pView->LockInternalLayer( bProtectDoc && bProtectAttr ); + } +} + +sal_Bool lcl_GetHyperlinkCell(ScDocument* pDoc, SCCOL& rPosX, SCROW& rPosY, SCTAB nTab, ScBaseCell*& rpCell ) +{ + sal_Bool bFound = sal_False; + do + { + pDoc->GetCell( rPosX, rPosY, nTab, rpCell ); + if ( !rpCell || rpCell->GetCellType() == CELLTYPE_NOTE ) + { + if ( rPosX <= 0 ) + return sal_False; // alles leer bis links + else + --rPosX; // weitersuchen + } + else if ( rpCell->GetCellType() == CELLTYPE_EDIT) + bFound = sal_True; + else if (rpCell->GetCellType() == CELLTYPE_FORMULA && + static_cast<ScFormulaCell*>(rpCell)->IsHyperLinkCell()) + bFound = sal_True; + else + return sal_False; // andere Zelle + } + while ( !bFound ); + + return bFound; +} + +// --------------------------------------------------------------------------- +// WB_DIALOGCONTROL noetig fuer UNO-Controls +ScGridWindow::ScGridWindow( Window* pParent, ScViewData* pData, ScSplitPos eWhichPos ) +: Window( pParent, WB_CLIPCHILDREN | WB_DIALOGCONTROL ), + DropTargetHelper( this ), + DragSourceHelper( this ), + mpOOCursors( NULL ), + mpOOSelection( NULL ), + mpOOAutoFill( NULL ), + mpOODragRect( NULL ), + mpOOHeader( NULL ), + mpOOShrink( NULL ), + mpAutoFillRect(static_cast<Rectangle*>(NULL)), + pViewData( pData ), + eWhich( eWhichPos ), + pNoteMarker( NULL ), + pFilterBox( NULL ), + pFilterFloat( NULL ), + mpDPFieldPopup(NULL), + mpFilterButton(NULL), + nCursorHideCount( 0 ), + bMarking( sal_False ), + nButtonDown( 0 ), + bEEMouse( sal_False ), + nMouseStatus( SC_GM_NONE ), + nNestedButtonState( SC_NESTEDBUTTON_NONE ), + bDPMouse( sal_False ), + bRFMouse( sal_False ), + nPagebreakMouse( SC_PD_NONE ), + bPagebreakDrawn( sal_False ), + nPageScript( 0 ), + bDragRect( sal_False ), + meDragInsertMode( INS_NONE ), + nCurrentPointer( 0 ), + bIsInScroll( sal_False ), + bIsInPaint( sal_False ), + aComboButton( this ), + aCurMousePos( 0,0 ), + nPaintCount( 0 ), + bNeedsRepaint( sal_False ), + bAutoMarkVisible( sal_False ), + bListValButton( sal_False ) +{ + switch(eWhich) + { + case SC_SPLIT_TOPLEFT: + eHWhich = SC_SPLIT_LEFT; + eVWhich = SC_SPLIT_TOP; + break; + case SC_SPLIT_TOPRIGHT: + eHWhich = SC_SPLIT_RIGHT; + eVWhich = SC_SPLIT_TOP; + break; + case SC_SPLIT_BOTTOMLEFT: + eHWhich = SC_SPLIT_LEFT; + eVWhich = SC_SPLIT_BOTTOM; + break; + case SC_SPLIT_BOTTOMRIGHT: + eHWhich = SC_SPLIT_RIGHT; + eVWhich = SC_SPLIT_BOTTOM; + break; + default: + DBG_ERROR("GridWindow: falsche Position"); + } + + SetBackground(); + + SetMapMode(pViewData->GetLogicMode(eWhich)); +// EnableDrop(); + EnableChildTransparentMode(); + SetDialogControlFlags( WINDOW_DLGCTRL_RETURN | WINDOW_DLGCTRL_WANTFOCUS ); + + SetHelpId( HID_SC_WIN_GRIDWIN ); + SetUniqueId( HID_SC_WIN_GRIDWIN ); + + SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() ); + EnableRTL( sal_False ); +} + +__EXPORT ScGridWindow::~ScGridWindow() +{ + // #114409# + ImpDestroyOverlayObjects(); + + delete pFilterBox; + delete pFilterFloat; + delete pNoteMarker; +} + +void __EXPORT ScGridWindow::Resize( const Size& ) +{ + // gar nix +} + +void ScGridWindow::ClickExtern() +{ + do + { + // #i81298# don't delete the filter box when called from its select handler + // (possible through row header size update) + // #i84277# when initializing the filter box, a Basic error can deactivate the view + if ( pFilterBox && ( pFilterBox->IsInSelect() || pFilterBox->IsInInit() ) ) + { + break; + } + + DELETEZ(pFilterBox); + DELETEZ(pFilterFloat); + } + while (false); + + if (mpDPFieldPopup.get()) + { + mpDPFieldPopup->close(false); + mpDPFieldPopup.reset(); + } +} + +IMPL_LINK( ScGridWindow, PopupModeEndHdl, FloatingWindow*, EMPTYARG ) +{ + if (pFilterBox) + pFilterBox->SetCancelled(); // nicht mehr auswaehlen + GrabFocus(); + return 0; +} + +IMPL_LINK( ScGridWindow, PopupSpellingHdl, SpellCallbackInfo*, pInfo ) +{ + if( pInfo->nCommand == SPELLCMD_STARTSPELLDLG ) + pViewData->GetDispatcher().Execute( SID_SPELL_DIALOG, SFX_CALLMODE_ASYNCHRON ); + return 0; +} + +void ScGridWindow::ExecPageFieldSelect( SCCOL nCol, SCROW nRow, sal_Bool bHasSelection, const String& rStr ) +{ + //! gridwin2 ? + + ScDocument* pDoc = pViewData->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + ScDPObject* pDPObj = pDoc->GetDPAtCursor(nCol, nRow, nTab); + if ( pDPObj && nCol > 0 ) + { + // look for the dimension header left of the drop-down arrow + sal_uInt16 nOrient = sheet::DataPilotFieldOrientation_HIDDEN; + long nField = pDPObj->GetHeaderDim( ScAddress( nCol-1, nRow, nTab ), nOrient ); + if ( nField >= 0 && nOrient == sheet::DataPilotFieldOrientation_PAGE ) + { + ScDPSaveData aSaveData( *pDPObj->GetSaveData() ); + + sal_Bool bIsDataLayout; + String aDimName = pDPObj->GetDimName( nField, bIsDataLayout ); + if ( !bIsDataLayout ) + { + ScDPSaveDimension* pDim = aSaveData.GetDimensionByName(aDimName); + + if ( bHasSelection ) + pDim->SetCurrentPage( &rStr ); + else + pDim->SetCurrentPage( NULL ); + + ScDPObject aNewObj( *pDPObj ); + aNewObj.SetSaveData( aSaveData ); + ScDBDocFunc aFunc( *pViewData->GetDocShell() ); + aFunc.DataPilotUpdate( pDPObj, &aNewObj, sal_True, sal_False ); + pViewData->GetView()->CursorPosChanged(); // shells may be switched + } + } + } +} + +void ScGridWindow::LaunchPageFieldMenu( SCCOL nCol, SCROW nRow ) +{ + //! merge position/size handling with DoAutoFilterMenue + + delete pFilterBox; + delete pFilterFloat; + + sal_uInt16 i; + ScDocument* pDoc = pViewData->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); + + long nSizeX = 0; + long nSizeY = 0; + long nHeight = 0; + pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY ); + Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich ); + if ( bLayoutRTL ) + aPos.X() -= nSizeX; + + Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) ); + + aPos.X() -= 1; + aPos.Y() += nSizeY - 1; + + pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) ); // not resizable etc. + pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) ); + pFilterBox = new ScFilterListBox( pFilterFloat, this, nCol, nRow, SC_FILTERBOX_PAGEFIELD ); + if ( bLayoutRTL ) + pFilterBox->EnableMirroring(); + + nSizeX += 1; + + { + Font aOldFont = GetFont(); SetFont( pFilterBox->GetFont() ); + MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL ); + + nHeight = GetTextHeight(); + nHeight *= SC_FILTERLISTBOX_LINES; + + SetMapMode( aOldMode ); + SetFont( aOldFont ); + } + + // SetSize comes later + + TypedScStrCollection aStrings( 128, 128 ); + + // get list box entries and selection + sal_Bool bHasCurrentPage = sal_False; + String aCurrentPage; + ScDPObject* pDPObj = pDoc->GetDPAtCursor(nCol, nRow, nTab); + if ( pDPObj && nCol > 0 ) + { + // look for the dimension header left of the drop-down arrow + sal_uInt16 nOrient = sheet::DataPilotFieldOrientation_HIDDEN; + long nField = pDPObj->GetHeaderDim( ScAddress( nCol-1, nRow, nTab ), nOrient ); + if ( nField >= 0 && nOrient == sheet::DataPilotFieldOrientation_PAGE ) + { + pDPObj->FillPageList( aStrings, nField ); + + // get current page from SaveData + + ScDPSaveData* pSaveData = pDPObj->GetSaveData(); + sal_Bool bIsDataLayout; + String aDimName = pDPObj->GetDimName( nField, bIsDataLayout ); + if ( pSaveData && !bIsDataLayout ) + { + ScDPSaveDimension* pDim = pSaveData->GetExistingDimensionByName(aDimName); + if ( pDim && pDim->HasCurrentPage() ) + { + aCurrentPage = pDim->GetCurrentPage(); + bHasCurrentPage = sal_True; + } + } + } + } + + // include all entry widths for the size of the drop-down + long nMaxText = 0; + sal_uInt16 nCount = aStrings.GetCount(); + for (i=0; i<nCount; i++) + { + TypedStrData* pData = aStrings[i]; + long nTextWidth = pFilterBox->GetTextWidth( pData->GetString() ); + if ( nTextWidth > nMaxText ) + nMaxText = nTextWidth; + } + + // add scrollbar width if needed (string entries are counted here) + // (scrollbar is shown if the box is exactly full?) + if ( nCount >= SC_FILTERLISTBOX_LINES ) + nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize(); + + nMaxText += 4; // for borders + + if ( nMaxText > nSizeX ) + nSizeX = nMaxText; // just modify width - starting position is unchanged + + // adjust position and size to window + + Size aParentSize = GetParent()->GetOutputSizePixel(); + Size aSize( nSizeX, nHeight ); + + if ( aSize.Height() > aParentSize.Height() ) + aSize.Height() = aParentSize.Height(); + if ( aPos.Y() + aSize.Height() > aParentSize.Height() ) + aPos.Y() = aParentSize.Height() - aSize.Height(); + + pFilterBox->SetSizePixel( aSize ); + pFilterBox->Show(); // Show must be called before SetUpdateMode + pFilterBox->SetUpdateMode(sal_False); + + pFilterFloat->SetOutputSizePixel( aSize ); + pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS); + + // fill the list box + sal_Bool bWait = ( nCount > 100 ); + + if (bWait) + EnterWait(); + + for (i=0; i<nCount; i++) + pFilterBox->InsertEntry( aStrings[i]->GetString() ); + + pFilterBox->SetSeparatorPos( 0 ); + + if (bWait) + LeaveWait(); + + pFilterBox->SetUpdateMode(sal_True); + + sal_uInt16 nSelPos = LISTBOX_ENTRY_NOTFOUND; + if (bHasCurrentPage) + nSelPos = pFilterBox->GetEntryPos( aCurrentPage ); + + if ( nSelPos == LISTBOX_ENTRY_NOTFOUND ) + nSelPos = 0; // first entry + + pFilterBox->GrabFocus(); + + // call Select after GrabFocus, so the focus rectangle ends up in the right position + if ( nSelPos != LISTBOX_ENTRY_NOTFOUND ) + pFilterBox->SelectEntryPos( nSelPos ); + + pFilterBox->EndInit(); + + nMouseStatus = SC_GM_FILTER; + CaptureMouse(); +} + +void ScGridWindow::LaunchDPFieldMenu( SCCOL nCol, SCROW nRow ) +{ + SCTAB nTab = pViewData->GetTabNo(); + ScDPObject* pDPObj = pViewData->GetDocument()->GetDPAtCursor(nCol, nRow, nTab); + if (!pDPObj) + return; + + // Get the geometry of the cell. + Point aScrPos = pViewData->GetScrPos(nCol, nRow, eWhich); + long nSizeX, nSizeY; + pViewData->GetMergeSizePixel(nCol, nRow, nSizeX, nSizeY); + Size aScrSize(nSizeX-1, nSizeY-1); + + DPLaunchFieldPopupMenu(OutputToScreenPixel(aScrPos), aScrSize, ScAddress(nCol, nRow, nTab), pDPObj); +} + +void ScGridWindow::DoScenarioMenue( const ScRange& rScenRange ) +{ + delete pFilterBox; + delete pFilterFloat; + + SCCOL nCol = rScenRange.aEnd.Col(); // Zelle unterhalb des Buttons + SCROW nRow = rScenRange.aStart.Row(); + if (nRow == 0) + { + nRow = rScenRange.aEnd.Row() + 1; // Bereich ganz oben -> Button unterhalb + if (nRow>MAXROW) nRow = MAXROW; + //! Texthoehe addieren (wenn sie an der View gespeichert ist...) + } + + ScDocument* pDoc = pViewData->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); + + long nSizeX = 0; + long nSizeY = 0; + long nHeight = 0; + pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY ); + Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich ); + if ( bLayoutRTL ) + aPos.X() -= nSizeX; + Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) ); + aCellRect.Top() -= nSizeY; + aCellRect.Bottom() -= nSizeY - 1; + // Die ListBox direkt unter der schwarzen Linie auf dem Zellgitter + // (wenn die Linie verdeckt wird, sieht es komisch aus...) + + pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) ); // nicht resizable etc. + pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) ); + pFilterBox = new ScFilterListBox( pFilterFloat, this, nCol, nRow, SC_FILTERBOX_SCENARIO ); + if ( bLayoutRTL ) + pFilterBox->EnableMirroring(); + + nSizeX += 1; + + { + Font aOldFont = GetFont(); SetFont( pFilterBox->GetFont() ); + MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL ); + + nHeight = GetTextHeight(); + nHeight *= SC_FILTERLISTBOX_LINES; + + SetMapMode( aOldMode ); + SetFont( aOldFont ); + } + + // SetSize spaeter +/* + pFilterBox->SetSelectionMode( SINGLE_SELECTION ); + pFilterBox->SetTabs( nFilterBoxTabs, MapUnit( MAP_APPFONT )); + pFilterBox->SetTabJustify( 1, bLayoutRTL ? AdjustRight : AdjustLeft ); +*/ + + // ParentSize Abfrage fehlt + Size aSize( nSizeX, nHeight ); + pFilterBox->SetSizePixel( aSize ); + pFilterBox->Show(); // Show muss vor SetUpdateMode kommen !!! + pFilterBox->SetUpdateMode(sal_False); + + // SetOutputSizePixel/StartPopupMode erst unten, wenn die Groesse feststeht + + // Listbox fuellen + + long nMaxText = 0; + String aCurrent; + String aTabName; + SCTAB nTabCount = pDoc->GetTableCount(); + SCTAB nEntryCount = 0; + for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++) + { + if (pDoc->HasScenarioRange( i, rScenRange )) + if (pDoc->GetName( i, aTabName )) + { + pFilterBox->InsertEntry( aTabName ); + if (pDoc->IsActiveScenario(i)) + aCurrent = aTabName; + long nTextWidth = pFilterBox->GetTextWidth( aTabName ); + if ( nTextWidth > nMaxText ) + nMaxText = nTextWidth; + ++nEntryCount; + } + } + if (nEntryCount > SC_FILTERLISTBOX_LINES) + nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize(); + nMaxText += 4; // fuer Rand + if ( nMaxText > 300 ) + nMaxText = 300; // auch nicht uebertreiben (Pixel) + + if (nMaxText > nSizeX) // Groesse auf benoetigte Groesse anpassen + { + long nDiff = nMaxText - nSizeX; + aSize = Size( nMaxText, nHeight ); + pFilterBox->SetSizePixel( aSize ); + pFilterFloat->SetOutputSizePixel( aSize ); + + if ( !bLayoutRTL ) + { + // also move popup position + long nNewX = aCellRect.Left() - nDiff; + if ( nNewX < 0 ) + nNewX = 0; + aCellRect.Left() = nNewX; + } + } + + pFilterFloat->SetOutputSizePixel( aSize ); + pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS ); + + pFilterBox->SetUpdateMode(sal_True); + pFilterBox->GrabFocus(); + + // Select erst nach GrabFocus, damit das Focus-Rechteck richtig landet +//! SvLBoxEntry* pSelect = NULL; + sal_uInt16 nPos = LISTBOX_ENTRY_NOTFOUND; + if (aCurrent.Len()) + { + nPos = pFilterBox->GetEntryPos( aCurrent ); +//! pSelect = pFilterBox->GetEntry( nPos ); + } + if (/*!pSelect*/ LISTBOX_ENTRY_NOTFOUND == nPos && pFilterBox->GetEntryCount() > 0 ) + nPos = 0; +//! pSelect = pFilterBox->GetEntry(0); // einer sollte immer selektiert sein + if (/*pSelect*/ LISTBOX_ENTRY_NOTFOUND != nPos ) + pFilterBox->SelectEntryPos(nPos); + + pFilterBox->EndInit(); + + // Szenario-Auswahl kommt aus MouseButtonDown: + // der naechste MouseMove auf die Filterbox ist wie ein ButtonDown + + nMouseStatus = SC_GM_FILTER; + CaptureMouse(); +} + +void ScGridWindow::DoAutoFilterMenue( SCCOL nCol, SCROW nRow, sal_Bool bDataSelect ) +{ + delete pFilterBox; + delete pFilterFloat; + + sal_uInt16 i; + ScDocument* pDoc = pViewData->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); + + long nSizeX = 0; + long nSizeY = 0; + long nHeight = 0; + pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY ); + Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich ); + if ( bLayoutRTL ) + aPos.X() -= nSizeX; + + Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) ); + + aPos.X() -= 1; + aPos.Y() += nSizeY - 1; + + pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) ); // nicht resizable etc. + pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) ); + pFilterBox = new ScFilterListBox( + pFilterFloat, this, nCol, nRow, bDataSelect ? SC_FILTERBOX_DATASELECT : SC_FILTERBOX_FILTER ); + if ( bLayoutRTL ) + pFilterBox->EnableMirroring(); + + nSizeX += 1; + + { + Font aOldFont = GetFont(); SetFont( pFilterBox->GetFont() ); + MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL ); + + nHeight = GetTextHeight(); + nHeight *= SC_FILTERLISTBOX_LINES; + + SetMapMode( aOldMode ); + SetFont( aOldFont ); + } + + // SetSize spaeter +/* + pFilterBox->SetSelectionMode( SINGLE_SELECTION ); + pFilterBox->SetTabs( nFilterBoxTabs, MapUnit( MAP_APPFONT )); + pFilterBox->SetTabJustify( 1, bLayoutRTL ? AdjustRight : AdjustLeft ); +*/ + + sal_Bool bEmpty = sal_False; + TypedScStrCollection aStrings( 128, 128 ); + if ( bDataSelect ) // Auswahl-Liste + { + // Liste fuellen + aStrings.SetCaseSensitive( sal_True ); + pDoc->GetDataEntries( nCol, nRow, nTab, aStrings ); + if ( aStrings.GetCount() == 0 ) + bEmpty = sal_True; + } + else // AutoFilter + { + //! wird der Titel ueberhaupt ausgewertet ??? + String aString; + pDoc->GetString( nCol, nRow, nTab, aString ); + pFilterBox->SetText( aString ); + + long nMaxText = 0; + + // default entries + static const sal_uInt16 nDefIDs[] = { SCSTR_ALLFILTER, SCSTR_TOP10FILTER, SCSTR_STDFILTER }; + const sal_uInt16 nDefCount = sizeof(nDefIDs) / sizeof(sal_uInt16); + for (i=0; i<nDefCount; i++) + { + String aEntry( (ScResId) nDefIDs[i] ); + pFilterBox->InsertEntry( aEntry ); + long nTextWidth = pFilterBox->GetTextWidth( aEntry ); + if ( nTextWidth > nMaxText ) + nMaxText = nTextWidth; + } + pFilterBox->SetSeparatorPos( nDefCount - 1 ); + + // get list entries + bool bHasDates = false; + pDoc->GetFilterEntries( nCol, nRow, nTab, true, aStrings, bHasDates); + pFilterBox->SetListHasDates(bHasDates); + + // check widths of numerical entries (string entries are not included) + // so all numbers are completely visible + sal_uInt16 nCount = aStrings.GetCount(); + for (i=0; i<nCount; i++) + { + TypedStrData* pData = aStrings[i]; + if ( !pData->IsStrData() ) // only numerical entries + { + long nTextWidth = pFilterBox->GetTextWidth( pData->GetString() ); + if ( nTextWidth > nMaxText ) + nMaxText = nTextWidth; + } + } + + // add scrollbar width if needed (string entries are counted here) + // (scrollbar is shown if the box is exactly full?) + if ( nCount + nDefCount >= SC_FILTERLISTBOX_LINES ) + nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize(); + + nMaxText += 4; // for borders + + if ( nMaxText > nSizeX ) + nSizeX = nMaxText; // just modify width - starting position is unchanged + } + + if (!bEmpty) + { + // Position und Groesse an Fenster anpassen + //! vorher Abfrage, ob die Eintraege hineinpassen (Breite) + + Size aParentSize = GetParent()->GetOutputSizePixel(); + Size aSize( nSizeX, nHeight ); + + if ( aSize.Height() > aParentSize.Height() ) + aSize.Height() = aParentSize.Height(); + if ( aPos.Y() + aSize.Height() > aParentSize.Height() ) + aPos.Y() = aParentSize.Height() - aSize.Height(); + + pFilterBox->SetSizePixel( aSize ); + pFilterBox->Show(); // Show muss vor SetUpdateMode kommen !!! + pFilterBox->SetUpdateMode(sal_False); + + pFilterFloat->SetOutputSizePixel( aSize ); + pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS); + + // Listbox fuellen + sal_uInt16 nCount = aStrings.GetCount(); + sal_Bool bWait = ( nCount > 100 ); + + if (bWait) + EnterWait(); + + for (i=0; i<nCount; i++) + pFilterBox->InsertEntry( aStrings[i]->GetString() ); + + if (bWait) + LeaveWait(); + + pFilterBox->SetUpdateMode(sal_True); + } + +//! SvLBoxEntry* pSelect = NULL; + sal_uInt16 nSelPos = LISTBOX_ENTRY_NOTFOUND; + + if (!bDataSelect) // AutoFilter: aktiven Eintrag selektieren + { + ScDBData* pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab ); + if (pDBData) + { + ScQueryParam aParam; + pDBData->GetQueryParam( aParam ); // kann nur MAXQUERY Eintraege ergeben + + sal_Bool bValid = sal_True; + for (SCSIZE j=0; j<MAXQUERY && bValid; j++) // bisherige Filter-Einstellungen + if (aParam.GetEntry(j).bDoQuery) + { + //! Abfrage mit DrawButtons zusammenfassen! + + ScQueryEntry& rEntry = aParam.GetEntry(j); + if (j>0) + if (rEntry.eConnect != SC_AND) + bValid = sal_False; + if (rEntry.nField == nCol) + { + if (rEntry.eOp == SC_EQUAL) + { + String* pStr = rEntry.pStr; + if (pStr) + { + nSelPos = pFilterBox->GetEntryPos( *pStr ); +//! pSelect = pFilterBox->GetEntry( nPos ); + } + } + else if (rEntry.eOp == SC_TOPVAL && rEntry.pStr && + rEntry.pStr->EqualsAscii("10")) + nSelPos = SC_AUTOFILTER_TOP10; + else + nSelPos = SC_AUTOFILTER_CUSTOM; + } + } + + if (!bValid) + nSelPos = SC_AUTOFILTER_CUSTOM; + } + } + else + { + + sal_uLong nIndex = ((SfxUInt32Item*)pDoc->GetAttr( + nCol, nRow, nTab, ATTR_VALIDDATA ))->GetValue(); + if ( nIndex ) + { + const ScValidationData* pData = pDoc->GetValidationEntry( nIndex ); + if (pData) + { + TypedStrData* pNew = NULL; + String aDocStr; + pDoc->GetString( nCol, nRow, nTab, aDocStr ); + if ( pDoc->HasValueData( nCol, nRow, nTab ) ) + { + double fVal = pDoc->GetValue(ScAddress(nCol, nRow, nTab)); + pNew = new TypedStrData( aDocStr, fVal, SC_STRTYPE_VALUE ); + } + else + pNew = new TypedStrData( aDocStr, 0.0, SC_STRTYPE_STANDARD ); + + bool bSortList = ( pData->GetListType() == ValidListType::SORTEDASCENDING); + if ( bSortList ) + { + sal_uInt16 nStrIndex; + if (aStrings.Search(pNew,nStrIndex)) + nSelPos = nStrIndex; + } + else + { + sal_uInt16 nCount = aStrings.GetCount(); + for (i = 0; ((i < nCount) && ( LISTBOX_ENTRY_NOTFOUND == nSelPos)); i++) + { + if ( aStrings.Compare(aStrings[i], pNew)==0 ) + nSelPos = i; + } + } + delete pNew; + } + } + } + + // neu (309): irgendwas muss immer selektiert sein: + if ( LISTBOX_ENTRY_NOTFOUND == nSelPos && pFilterBox->GetEntryCount() > 0 && !bDataSelect) + nSelPos = 0; + + // keine leere Auswahl-Liste anzeigen: + + if ( bEmpty ) + { + DELETEZ(pFilterBox); // war nix + DELETEZ(pFilterFloat); + Sound::Beep(); // bemerkbar machen + } + else + { +// pFilterBox->Show(); // schon vorne + pFilterBox->GrabFocus(); + + // Select erst nach GrabFocus, damit das Focus-Rechteck richtig landet + if ( LISTBOX_ENTRY_NOTFOUND != nSelPos ) + pFilterBox->SelectEntryPos( nSelPos ); + else + { + if (bDataSelect) + pFilterBox->SetNoSelection(); + } + + pFilterBox->EndInit(); + + if (!bDataSelect) + { + // AutoFilter (aus MouseButtonDown): + // der naechste MouseMove auf die Filterbox ist wie ein ButtonDown + + nMouseStatus = SC_GM_FILTER; + CaptureMouse(); + } + } +} + +void ScGridWindow::FilterSelect( sal_uLong nSel ) +{ + String aString; +/* + SvLBoxEntry* pEntry = pFilterBox->GetEntry( nSel ); + if (pEntry) + { + SvLBoxString* pStringEntry = (SvLBoxString*) pEntry->GetFirstItem( SV_ITEM_ID_LBOXSTRING ); + if ( pStringEntry ) + aString = pStringEntry->GetText(); + } +*/ + aString = pFilterBox->GetEntry( static_cast< sal_uInt16 >( nSel ) ); + + SCCOL nCol = pFilterBox->GetCol(); + SCROW nRow = pFilterBox->GetRow(); + switch ( pFilterBox->GetMode() ) + { + case SC_FILTERBOX_DATASELECT: + ExecDataSelect( nCol, nRow, aString ); + break; + case SC_FILTERBOX_FILTER: + ExecFilter( nSel, nCol, nRow, aString, pFilterBox->HasDates() ); + break; + case SC_FILTERBOX_SCENARIO: + pViewData->GetView()->UseScenario( aString ); + break; + case SC_FILTERBOX_PAGEFIELD: + // first entry is "all" + ExecPageFieldSelect( nCol, nRow, (nSel != 0), aString ); + break; + } + + if (pFilterFloat) + pFilterFloat->EndPopupMode(); + + GrabFocus(); // unter OS/2 stimmt der Focus sonst nicht +} + +void ScGridWindow::ExecDataSelect( SCCOL nCol, SCROW nRow, const String& rStr ) +{ + if ( rStr.Len() ) + { + SCTAB nTab = pViewData->GetTabNo(); + ScViewFunc* pView = pViewData->GetView(); + pView->EnterData( nCol, nRow, nTab, rStr ); + + // #i52307# CellContentChanged is not in EnterData so it isn't called twice + // if the cursor is moved afterwards. + pView->CellContentChanged(); + } +} + +void ScGridWindow::ExecFilter( sal_uLong nSel, + SCCOL nCol, SCROW nRow, + const String& aValue, bool bCheckForDates ) +{ + SCTAB nTab = pViewData->GetTabNo(); + ScDocument* pDoc = pViewData->GetDocument(); + + ScDBData* pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab ); + if (pDBData) + { + ScQueryParam aParam; + pDBData->GetQueryParam( aParam ); // kann nur MAXQUERY Eintraege ergeben + + if (SC_AUTOFILTER_CUSTOM == nSel) + { + SCTAB nAreaTab; + SCCOL nStartCol; + SCROW nStartRow; + SCCOL nEndCol; + SCROW nEndRow; + pDBData->GetArea( nAreaTab, nStartCol,nStartRow,nEndCol,nEndRow ); + pViewData->GetView()->MarkRange( ScRange( nStartCol,nStartRow,nAreaTab,nEndCol,nEndRow,nAreaTab)); + pViewData->GetView()->SetCursor(nCol,nRow); //! auch ueber Slot ?? + pViewData->GetDispatcher().Execute( SID_FILTER, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD ); + } + else + { + sal_Bool bDeleteOld = sal_False; + SCSIZE nQueryPos = 0; + sal_Bool bFound = sal_False; + if (!aParam.bInplace) + bDeleteOld = sal_True; + if (aParam.bRegExp) + bDeleteOld = sal_True; + for (SCSIZE i=0; i<MAXQUERY && !bDeleteOld; i++) // bisherige Filter-Einstellungen + if (aParam.GetEntry(i).bDoQuery) + { + //! Abfrage mit DrawButtons zusammenfassen! + + ScQueryEntry& rEntry = aParam.GetEntry(i); + if (i>0) + if (rEntry.eConnect != SC_AND) + bDeleteOld = sal_True; + + if (rEntry.nField == nCol) + { + if (bFound) // diese Spalte zweimal? + bDeleteOld = sal_True; + nQueryPos = i; + bFound = sal_True; + } + if (!bFound) + nQueryPos = i + 1; + } + + if (bDeleteOld) + { + SCSIZE nEC = aParam.GetEntryCount(); + for (SCSIZE i=0; i<nEC; i++) + aParam.GetEntry(i).Clear(); + nQueryPos = 0; + aParam.bInplace = sal_True; + aParam.bRegExp = sal_False; + } + + if ( nQueryPos < MAXQUERY || SC_AUTOFILTER_ALL == nSel ) // loeschen geht immer + { + if (nSel) + { + ScQueryEntry& rNewEntry = aParam.GetEntry(nQueryPos); + + rNewEntry.bDoQuery = sal_True; + rNewEntry.bQueryByString = sal_True; + rNewEntry.nField = nCol; + rNewEntry.bQueryByDate = bCheckForDates; + if ( nSel == SC_AUTOFILTER_TOP10 ) + { + rNewEntry.eOp = SC_TOPVAL; + *rNewEntry.pStr = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("10")); + } + else + { + rNewEntry.eOp = SC_EQUAL; + *rNewEntry.pStr = aValue; + } + if (nQueryPos > 0) + rNewEntry.eConnect = SC_AND; + } + else + { + if (bFound) + aParam.DeleteQuery(nQueryPos); + } + + // #100597# end edit mode - like in ScCellShell::ExecuteDB + if ( pViewData->HasEditView( pViewData->GetActivePart() ) ) + { + SC_MOD()->InputEnterHandler(); + pViewData->GetViewShell()->UpdateInputHandler(); + } + + pViewData->GetView()->Query( aParam, NULL, sal_True ); + pDBData->SetQueryParam( aParam ); // speichern + } + else // "Zuviele Bedingungen" + pViewData->GetView()->ErrorMessage( STR_FILTER_TOOMANY ); + } + } + else + { + DBG_ERROR("Wo ist der Datenbankbereich?"); + } +} + +void ScGridWindow::SetPointer( const Pointer& rPointer ) +{ + nCurrentPointer = 0; + Window::SetPointer( rPointer ); +} + +void ScGridWindow::MoveMouseStatus( ScGridWindow& rDestWin ) +{ + if (nButtonDown) + { + rDestWin.nButtonDown = nButtonDown; + rDestWin.nMouseStatus = nMouseStatus; + } + + if (bRFMouse) + { + rDestWin.bRFMouse = bRFMouse; + rDestWin.bRFSize = bRFSize; + rDestWin.nRFIndex = nRFIndex; + rDestWin.nRFAddX = nRFAddX; + rDestWin.nRFAddY = nRFAddY; + bRFMouse = sal_False; + } + + if (nPagebreakMouse) + { + rDestWin.nPagebreakMouse = nPagebreakMouse; + rDestWin.nPagebreakBreak = nPagebreakBreak; + rDestWin.nPagebreakPrev = nPagebreakPrev; + rDestWin.aPagebreakSource = aPagebreakSource; + rDestWin.aPagebreakDrag = aPagebreakDrag; + nPagebreakMouse = SC_PD_NONE; + } +} + +sal_Bool ScGridWindow::TestMouse( const MouseEvent& rMEvt, sal_Bool bAction ) +{ + // MouseEvent buttons must only be checked if bAction==TRUE + // to allow changing the mouse pointer in MouseMove, + // but not start AutoFill with right button (#74229#). + // with bAction==sal_True, SetFillMode / SetDragMode is called + + if ( bAction && !rMEvt.IsLeft() ) + return sal_False; + + sal_Bool bNewPointer = sal_False; + + SfxInPlaceClient* pClient = pViewData->GetViewShell()->GetIPClient(); + sal_Bool bOleActive = ( pClient && pClient->IsObjectInPlaceActive() ); + + if ( pViewData->IsActive() && !bOleActive ) + { + ScDocument* pDoc = pViewData->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); + + // Auto-Fill + + ScRange aMarkRange; + if (pViewData->GetSimpleArea( aMarkRange ) == SC_MARK_SIMPLE) + { + if (aMarkRange.aStart.Tab() == pViewData->GetTabNo() && mpAutoFillRect) + { + Point aMousePos = rMEvt.GetPosPixel(); + if (mpAutoFillRect->IsInside(aMousePos)) + { + SetPointer( Pointer( POINTER_CROSS ) ); //! dickeres Kreuz ? + if (bAction) + { + SCCOL nX = aMarkRange.aEnd.Col(); + SCROW nY = aMarkRange.aEnd.Row(); + + if ( lcl_IsEditableMatrix( pViewData->GetDocument(), aMarkRange ) ) + pViewData->SetDragMode( + aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nX, nY, SC_FILL_MATRIX ); + else + pViewData->SetFillMode( + aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nX, nY ); + + // #108266# The simple selection must also be recognized when dragging, + // where the Marking flag is set and MarkToSimple won't work anymore. + pViewData->GetMarkData().MarkToSimple(); + } + bNewPointer = sal_True; + } + } + } + + // Embedded-Rechteck + + if (pDoc->IsEmbedded()) + { + ScRange aRange; + pDoc->GetEmbedded( aRange ); + if ( pViewData->GetTabNo() == aRange.aStart.Tab() ) + { + Point aStartPos = pViewData->GetScrPos( aRange.aStart.Col(), aRange.aStart.Row(), eWhich ); + Point aEndPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aEnd.Row()+1, eWhich ); + Point aMousePos = rMEvt.GetPosPixel(); + if ( bLayoutRTL ) + { + aStartPos.X() += 2; + aEndPos.X() += 2; + } + sal_Bool bTop = ( aMousePos.X() >= aStartPos.X()-3 && aMousePos.X() <= aStartPos.X()+1 && + aMousePos.Y() >= aStartPos.Y()-3 && aMousePos.Y() <= aStartPos.Y()+1 ); + sal_Bool bBottom = ( aMousePos.X() >= aEndPos.X()-3 && aMousePos.X() <= aEndPos.X()+1 && + aMousePos.Y() >= aEndPos.Y()-3 && aMousePos.Y() <= aEndPos.Y()+1 ); + if ( bTop || bBottom ) + { + SetPointer( Pointer( POINTER_CROSS ) ); + if (bAction) + { + sal_uInt8 nMode = bTop ? SC_FILL_EMBED_LT : SC_FILL_EMBED_RB; + pViewData->SetDragMode( + aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Col(), aRange.aEnd.Row(), nMode ); + } + bNewPointer = sal_True; + } + } + } + } + + if (!bNewPointer && bAction) + { +// SetPointer( POINTER_ARROW ); // in Fu... + pViewData->ResetFillMode(); + } + + return bNewPointer; +} + +void __EXPORT ScGridWindow::MouseButtonDown( const MouseEvent& rMEvt ) +{ + nNestedButtonState = SC_NESTEDBUTTON_DOWN; + + HandleMouseButtonDown( rMEvt ); + + if ( nNestedButtonState == SC_NESTEDBUTTON_UP ) + { + // #i41690# If an object is deactivated from MouseButtonDown, it might reschedule, + // so MouseButtonUp comes before the MouseButtonDown call is finished. In this case, + // simulate another MouseButtonUp call, so the selection state is consistent. + + nButtonDown = rMEvt.GetButtons(); + FakeButtonUp(); + + if ( IsTracking() ) + EndTracking(); // normally done in VCL as part of MouseButtonUp handling + } + nNestedButtonState = SC_NESTEDBUTTON_NONE; +} + +void ScGridWindow::HandleMouseButtonDown( const MouseEvent& rMEvt ) +{ + // We have to check if a context menu is shown and we have an UI + // active inplace client. In that case we have to ignore the event. + // Otherwise we would crash (context menu has been + // opened by inplace client and we would deactivate the inplace client, + // the contex menu is closed by VCL asynchronously which in the end + // would work on deleted objects or the context menu has no parent anymore) + // See #126086# and #128122# + SfxViewShell* pViewSh = pViewData->GetViewShell(); + SfxInPlaceClient* pClient = pViewSh->GetIPClient(); + if ( pClient && + pClient->IsObjectInPlaceActive() && + PopupMenu::IsInExecute() ) + return; + + aCurMousePos = rMEvt.GetPosPixel(); + + // Filter-Popup beendet sich mit eigenem Mausklick, nicht erst beim Klick + // in das GridWindow, darum ist die folgende Abfrage nicht mehr noetig: +#if 0 + // merken, dass FilterBox geloescht wird, damit sichergestellt + // ist, dass in diesem Handler nicht an gleicher Stelle wieder + // eine neue geoeffnet wird. + sal_Bool bWasFilterBox = ( pFilterBox != NULL && + ((Window*)pFilterBox)->IsVisible() && + !pFilterBox->IsDataSelect() ); + SCCOL nOldColFBox = bWasFilterBox ? pFilterBox->GetCol() : 0; + SCROW nOldRowFBox = bWasFilterBox ? pFilterBox->GetRow() : 0; +#endif + + ClickExtern(); // loescht FilterBox, wenn vorhanden + + HideNoteMarker(); // Notiz-Anzeige + + bEEMouse = sal_False; + + ScModule* pScMod = SC_MOD(); + if (pScMod->IsModalMode(pViewData->GetSfxDocShell())) + { + Sound::Beep(); + return; + } + + pScActiveViewShell = pViewData->GetViewShell(); // falls auf Link geklickt wird + nScClickMouseModifier = rMEvt.GetModifier(); // um Control-Klick immer zu erkennen + + sal_Bool bDetective = pViewData->GetViewShell()->IsAuditShell(); + sal_Bool bRefMode = pViewData->IsRefMode(); // Referenz angefangen + sal_Bool bFormulaMode = pScMod->IsFormulaMode(); // naechster Klick -> Referenz + sal_Bool bEditMode = pViewData->HasEditView(eWhich); // auch bei Mode==SC_INPUT_TYPE + sal_Bool bDouble = (rMEvt.GetClicks() == 2); + + // DeactivateIP passiert nur noch bei MarkListHasChanged + + // im GrabFocus Aufruf kann eine Fehlermeldung hochkommen + // (z.B. beim Umbenennen von Tabellen per Tab-Reiter) + + if ( !nButtonDown || !bDouble ) // single (first) click is always valid + nButtonDown = rMEvt.GetButtons(); // set nButtonDown first, so StopMarking works + +// pViewData->GetViewShell()->GetViewFrame()->GetWindow().GrabFocus(); + if ( ( bEditMode && pViewData->GetActivePart() == eWhich ) || !bFormulaMode ) + GrabFocus(); + + // #i31846# need to cancel a double click if the first click has set the "ignore" state, + // but a single (first) click is always valid + if ( nMouseStatus == SC_GM_IGNORE && bDouble ) + { + nButtonDown = 0; + nMouseStatus = SC_GM_NONE; + return; + } + + if ( bDetective ) // Detektiv-Fuell-Modus + { + if ( rMEvt.IsLeft() && !rMEvt.GetModifier() ) + { + Point aPos = rMEvt.GetPosPixel(); + SCsCOL nPosX; + SCsROW nPosY; + pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); + + SfxInt16Item aPosXItem( SID_RANGE_COL, nPosX ); + SfxInt32Item aPosYItem( SID_RANGE_ROW, nPosY ); + pViewData->GetDispatcher().Execute( SID_FILL_SELECT, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD, + &aPosXItem, &aPosYItem, (void*)0L ); + + } + nButtonDown = 0; + nMouseStatus = SC_GM_NONE; + return; + } + + if (!bDouble) + nMouseStatus = SC_GM_NONE; + + if (!bFormulaMode) + { + if ( pViewData->GetActivePart() != eWhich ) + pViewData->GetView()->ActivatePart( eWhich ); + } + else + { + ScViewSelectionEngine* pSelEng = pViewData->GetView()->GetSelEngine(); + pSelEng->SetWindow(this); + pSelEng->SetWhich(eWhich); + pSelEng->SetVisibleArea( Rectangle(Point(), GetOutputSizePixel()) ); + } + + if (bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo())) + { + Point aPos = rMEvt.GetPosPixel(); + SCsCOL nPosX; + SCsROW nPosY; + pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); + + EditView* pEditView; + SCCOL nEditCol; + SCROW nEditRow; + pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow ); + SCCOL nEndCol = pViewData->GetEditEndCol(); + SCROW nEndRow = pViewData->GetEditEndRow(); + + if ( nPosX >= (SCsCOL) nEditCol && nPosX <= (SCsCOL) nEndCol && + nPosY >= (SCsROW) nEditRow && nPosY <= (SCsROW) nEndRow ) + { + // #53966# beim Klick in die Tabellen-EditView immer den Focus umsetzen + if (bFormulaMode) // sonst ist es oben schon passiert + GrabFocus(); + + pScMod->SetInputMode( SC_INPUT_TABLE ); + bEEMouse = sal_True; + bEditMode = pEditView->MouseButtonDown( rMEvt ); + return; + } + } + + if (pScMod->GetIsWaterCan()) + { + //! was is mit'm Mac ??? + if ( rMEvt.GetModifier() + rMEvt.GetButtons() == MOUSE_RIGHT ) + { + nMouseStatus = SC_GM_WATERUNDO; + return; + } + } + + // Reihenfolge passend zum angezeigten Cursor: + // RangeFinder, AutoFill, PageBreak, Drawing + + if ( HitRangeFinder( rMEvt.GetPosPixel(), bRFSize, &nRFIndex, &nRFAddX, &nRFAddY ) ) + { + bRFMouse = sal_True; // die anderen Variablen sind oben initialisiert + + if ( pViewData->GetActivePart() != eWhich ) + pViewData->GetView()->ActivatePart( eWhich ); //! schon oben immer ??? + + // CaptureMouse(); + StartTracking(); + return; + } + + sal_Bool bCrossPointer = TestMouse( rMEvt, sal_True ); + if ( bCrossPointer ) + { + if ( bDouble ) + pViewData->GetView()->FillCrossDblClick(); + else + pScMod->InputEnterHandler(); // Autofill etc. + } + + if ( !bCrossPointer ) + { + nPagebreakMouse = HitPageBreak( rMEvt.GetPosPixel(), &aPagebreakSource, + &nPagebreakBreak, &nPagebreakPrev ); + if (nPagebreakMouse) + { + bPagebreakDrawn = sal_False; + // CaptureMouse(); + StartTracking(); + PagebreakMove( rMEvt, sal_False ); + return; + } + } + + if (!bFormulaMode && !bEditMode && rMEvt.IsLeft()) + { + if ( !bCrossPointer && DrawMouseButtonDown(rMEvt) ) + { + //if (DrawHasMarkedObj()) + // pViewData->GetViewShell()->SetDrawShellOrSub(); // Draw-Objekt selektiert + return; + } + + pViewData->GetViewShell()->SetDrawShell( sal_False ); // kein Draw-Objekt selektiert + + // TestMouse schon oben passiert + } + + Point aPos = rMEvt.GetPosPixel(); + SCsCOL nPosX; + SCsROW nPosY; + pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); + SCTAB nTab = pViewData->GetTabNo(); + ScDocument* pDoc = pViewData->GetDocument(); + + + // + // AutoFilter buttons + // + + if ( !bDouble && !bFormulaMode && rMEvt.IsLeft() ) + { + ScMergeFlagAttr* pAttr = (ScMergeFlagAttr*) + pDoc->GetAttr( nPosX, nPosY, nTab, ATTR_MERGE_FLAG ); + if (pAttr->HasAutoFilter()) + { + if (DoAutoFilterButton(nPosX, nPosY, rMEvt)) + return; + } + if (pAttr->HasButton()) + { + DoPushButton( nPosX, nPosY, rMEvt ); // setzt evtl. bPivotMouse / bDPMouse + return; + } + + // List Validity drop-down button + + if ( bListValButton ) + { + Rectangle aButtonRect = GetListValButtonRect( aListValPos ); + if ( aButtonRect.IsInside( aPos ) ) + { + DoAutoFilterMenue( aListValPos.Col(), aListValPos.Row(), sal_True ); + + nMouseStatus = SC_GM_FILTER; // not set in DoAutoFilterMenue for bDataSelect + CaptureMouse(); + return; + } + } + } + + // + // scenario selection + // + + ScRange aScenRange; + if ( rMEvt.IsLeft() && HasScenarioButton( aPos, aScenRange ) ) + { + DoScenarioMenue( aScenRange ); + return; + } + + // + // Doppelklick angefangen ? + // + + // StopMarking kann aus DrawMouseButtonDown gerufen werden + + if ( nMouseStatus != SC_GM_IGNORE && !bRefMode ) + { + if ( bDouble && !bCrossPointer ) + { + if (nMouseStatus == SC_GM_TABDOWN) + nMouseStatus = SC_GM_DBLDOWN; + } + else + nMouseStatus = SC_GM_TABDOWN; + } + + // + // Links in Edit-Zellen + // + + sal_Bool bAlt = rMEvt.IsMod2(); + if ( !bAlt && rMEvt.IsLeft() && + GetEditUrl(rMEvt.GetPosPixel()) ) // Klick auf Link: Cursor nicht bewegen + { + SetPointer( Pointer( POINTER_REFHAND ) ); + nMouseStatus = SC_GM_URLDOWN; // auch nur dann beim ButtonUp ausfuehren + return; + } + + // + // Gridwin - SelectionEngine + // + + if ( rMEvt.IsLeft() ) + { + ScViewSelectionEngine* pSelEng = pViewData->GetView()->GetSelEngine(); + pSelEng->SetWindow(this); + pSelEng->SetWhich(eWhich); + pSelEng->SetVisibleArea( Rectangle(Point(), GetOutputSizePixel()) ); + + // SelMouseButtonDown an der View setzt noch das bMoveIsShift Flag + if ( pViewData->GetView()->SelMouseButtonDown( rMEvt ) ) + { + if (IsMouseCaptured()) + { + // Tracking statt CaptureMouse, damit sauber abgebrochen werden kann + //! Irgendwann sollte die SelectionEngine selber StartTracking rufen!?! + ReleaseMouse(); + StartTracking(); + } + pViewData->GetMarkData().SetMarking(sal_True); + return; + } + } +} + +void __EXPORT ScGridWindow::MouseButtonUp( const MouseEvent& rMEvt ) +{ + aCurMousePos = rMEvt.GetPosPixel(); + ScDocument* pDoc = pViewData->GetDocument(); + ScMarkData& rMark = pViewData->GetMarkData(); + + // #i41690# detect a MouseButtonUp call from within MouseButtonDown + // (possible through Reschedule from storing an OLE object that is deselected) + + if ( nNestedButtonState == SC_NESTEDBUTTON_DOWN ) + nNestedButtonState = SC_NESTEDBUTTON_UP; + + if (nButtonDown != rMEvt.GetButtons()) + nMouseStatus = SC_GM_IGNORE; // reset und return + + nButtonDown = 0; + + if (nMouseStatus == SC_GM_IGNORE) + { + nMouseStatus = SC_GM_NONE; + // Selection-Engine: Markieren abbrechen + pViewData->GetView()->GetSelEngine()->Reset(); + rMark.SetMarking(sal_False); + if (pViewData->IsAnyFillMode()) + { + pViewData->GetView()->StopRefMode(); + pViewData->ResetFillMode(); + } + StopMarking(); + DrawEndAction(); // Markieren/Verschieben auf Drawing-Layer abbrechen + ReleaseMouse(); + return; + } + + if (nMouseStatus == SC_GM_FILTER) + { + if ( pFilterBox && pFilterBox->GetMode() == SC_FILTERBOX_FILTER ) + { + if (mpFilterButton.get()) + { + bool bFilterActive = IsAutoFilterActive( + pFilterBox->GetCol(), pFilterBox->GetRow(), pViewData->GetTabNo() ); + + mpFilterButton->setHasHiddenMember(bFilterActive); + mpFilterButton->setPopupPressed(false); + HideCursor(); + mpFilterButton->draw(); + ShowCursor(); + } + } + nMouseStatus = SC_GM_NONE; + ReleaseMouse(); + return; // da muss nix mehr passieren + } + + ScModule* pScMod = SC_MOD(); + if (pScMod->IsModalMode(pViewData->GetSfxDocShell())) + return; + + SfxBindings& rBindings = pViewData->GetBindings(); + if (bEEMouse && pViewData->HasEditView( eWhich )) + { + EditView* pEditView; + SCCOL nEditCol; + SCROW nEditRow; + pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow ); + pEditView->MouseButtonUp( rMEvt ); + + if ( rMEvt.IsMiddle() && + GetSettings().GetMouseSettings().GetMiddleButtonAction() == MOUSE_MIDDLE_PASTESELECTION ) + { + // EditView may have pasted from selection + pScMod->InputChanged( pEditView ); + } + else + pScMod->InputSelection( pEditView ); // parentheses etc. + + pViewData->GetView()->InvalidateAttribs(); + rBindings.Invalidate( SID_HYPERLINK_GETLINK ); + bEEMouse = sal_False; + return; + } + + if (bDPMouse) + { + DPMouseButtonUp( rMEvt ); // resets bDPMouse + return; + } + + if (bRFMouse) + { + RFMouseMove( rMEvt, sal_True ); // Range wieder richtigherum + bRFMouse = sal_False; + SetPointer( Pointer( POINTER_ARROW ) ); + ReleaseMouse(); + return; + } + + if (nPagebreakMouse) + { + PagebreakMove( rMEvt, sal_True ); + nPagebreakMouse = SC_PD_NONE; + SetPointer( Pointer( POINTER_ARROW ) ); + ReleaseMouse(); + return; + } + + if (nMouseStatus == SC_GM_WATERUNDO) // Undo im Giesskannenmodus + { + ::svl::IUndoManager* pMgr = pViewData->GetDocShell()->GetUndoManager(); + if ( pMgr->GetUndoActionCount() && pMgr->GetUndoActionId() == STR_UNDO_APPLYCELLSTYLE ) + pMgr->Undo(); + else + Sound::Beep(); + return; + } + + if (DrawMouseButtonUp(rMEvt)) // includes format paint brush handling for drawing objects + return; + + rMark.SetMarking(sal_False); + + SetPointer( Pointer( POINTER_ARROW ) ); + + if (pViewData->IsFillMode() || + ( pViewData->GetFillMode() == SC_FILL_MATRIX && rMEvt.IsMod1() )) + { + nScFillModeMouseModifier = rMEvt.GetModifier(); + SCCOL nStartCol; + SCROW nStartRow; + SCCOL nEndCol; + SCROW nEndRow; + pViewData->GetFillData( nStartCol, nStartRow, nEndCol, nEndRow ); +// DBG_ASSERT( nStartCol==pViewData->GetRefStartX() && nStartRow==pViewData->GetRefStartY(), +// "Block falsch fuer AutoFill" ); + ScRange aDelRange; + sal_Bool bIsDel = pViewData->GetDelMark( aDelRange ); + + ScViewFunc* pView = pViewData->GetView(); + pView->StopRefMode(); + pViewData->ResetFillMode(); + pView->GetFunctionSet()->SetAnchorFlag( sal_False ); // #i5819# don't use AutoFill anchor flag for selection + + if ( bIsDel ) + { + pView->MarkRange( aDelRange, sal_False ); + pView->DeleteContents( IDF_CONTENTS ); + SCTAB nTab = pViewData->GetTabNo(); + ScRange aBlockRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab ); + if ( aBlockRange != aDelRange ) + { + if ( aDelRange.aStart.Row() == nStartRow ) + aBlockRange.aEnd.SetCol( aDelRange.aStart.Col() - 1 ); + else + aBlockRange.aEnd.SetRow( aDelRange.aStart.Row() - 1 ); + pView->MarkRange( aBlockRange, sal_False ); + } + } + else + pViewData->GetDispatcher().Execute( FID_FILL_AUTO, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD ); + } + else if (pViewData->GetFillMode() == SC_FILL_MATRIX) + { + SCTAB nTab = pViewData->GetTabNo(); + SCCOL nStartCol; + SCROW nStartRow; + SCCOL nEndCol; + SCROW nEndRow; + pViewData->GetFillData( nStartCol, nStartRow, nEndCol, nEndRow ); + ScRange aBlockRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab ); + SCCOL nFillCol = pViewData->GetRefEndX(); + SCROW nFillRow = pViewData->GetRefEndY(); + ScAddress aEndPos( nFillCol, nFillRow, nTab ); + + ScTabView* pView = pViewData->GetView(); + pView->StopRefMode(); + pViewData->ResetFillMode(); + pView->GetFunctionSet()->SetAnchorFlag( sal_False ); + + if ( aEndPos != aBlockRange.aEnd ) + { + pViewData->GetDocShell()->GetDocFunc().ResizeMatrix( aBlockRange, aEndPos, sal_False ); + pViewData->GetView()->MarkRange( ScRange( aBlockRange.aStart, aEndPos ) ); + } + } + else if (pViewData->IsAnyFillMode()) + { + // Embedded-Area has been changed + ScTabView* pView = pViewData->GetView(); + pView->StopRefMode(); + pViewData->ResetFillMode(); + pView->GetFunctionSet()->SetAnchorFlag( sal_False ); + pViewData->GetDocShell()->UpdateOle(pViewData); + } + + sal_Bool bRefMode = pViewData->IsRefMode(); + if (bRefMode) + pScMod->EndReference(); + + // + // Giesskannen-Modus (Gestalter) + // + + if (pScMod->GetIsWaterCan()) + { + // Abfrage auf Undo schon oben + + ScStyleSheetPool* pStylePool = (ScStyleSheetPool*) + (pViewData->GetDocument()-> + GetStyleSheetPool()); + if ( pStylePool ) + { + SfxStyleSheet* pStyleSheet = (SfxStyleSheet*) + pStylePool->GetActualStyleSheet(); + + if ( pStyleSheet ) + { + SfxStyleFamily eFamily = pStyleSheet->GetFamily(); + + switch ( eFamily ) + { + case SFX_STYLE_FAMILY_PARA: + pViewData->GetView()->SetStyleSheetToMarked( pStyleSheet ); + pViewData->GetView()->DoneBlockMode(); + break; + + case SFX_STYLE_FAMILY_PAGE: + pViewData->GetDocument()->SetPageStyle( pViewData->GetTabNo(), + pStyleSheet->GetName() ); + + ScPrintFunc( pViewData->GetDocShell(), + pViewData->GetViewShell()->GetPrinter(sal_True), + pViewData->GetTabNo() ).UpdatePages(); + + rBindings.Invalidate( SID_STATUS_PAGESTYLE ); + break; + + default: + break; + } + } + } + } + + ScDBFunc* pView = pViewData->GetView(); + ScDocument* pBrushDoc = pView->GetBrushDocument(); + if ( pBrushDoc ) + { + pView->PasteFromClip( IDF_ATTRIB, pBrushDoc ); + if ( !pView->IsPaintBrushLocked() ) + pView->ResetBrushDocument(); // invalidates pBrushDoc pointer + } + + // + // double click (only left button) + // + + sal_Bool bDouble = ( rMEvt.GetClicks() == 2 && rMEvt.IsLeft() ); + if ( bDouble && !bRefMode && nMouseStatus == SC_GM_DBLDOWN && !pScMod->IsRefDialogOpen() ) + { + // data pilot table + Point aPos = rMEvt.GetPosPixel(); + SCsCOL nPosX; + SCsROW nPosY; + SCTAB nTab = pViewData->GetTabNo(); + pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); + ScDPObject* pDPObj = pDoc->GetDPAtCursor( nPosX, nPosY, nTab ); + if ( pDPObj && pDPObj->GetSaveData()->GetDrillDown() ) + { + ScAddress aCellPos( nPosX, nPosY, pViewData->GetTabNo() ); + + // Check for header drill-down first. + sheet::DataPilotTableHeaderData aData; + pDPObj->GetHeaderPositionData(aCellPos, aData); + + if ( ( aData.Flags & sheet::MemberResultFlags::HASMEMBER ) && + ! ( aData.Flags & sheet::MemberResultFlags::SUBTOTAL ) ) + { + sal_uInt16 nDummy; + if ( pView->HasSelectionForDrillDown( nDummy ) ) + { + // execute slot to show dialog + pViewData->GetDispatcher().Execute( SID_OUTLINE_SHOW, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD ); + } + else + { + // toggle single entry + ScDPObject aNewObj( *pDPObj ); + pDPObj->ToggleDetails( aData, &aNewObj ); + ScDBDocFunc aFunc( *pViewData->GetDocShell() ); + aFunc.DataPilotUpdate( pDPObj, &aNewObj, sal_True, sal_False ); + pViewData->GetView()->CursorPosChanged(); // shells may be switched + } + } + else + { + // Check if the data area is double-clicked. + + Sequence<sheet::DataPilotFieldFilter> aFilters; + if ( pDPObj->GetDataFieldPositionData(aCellPos, aFilters) ) + pViewData->GetView()->ShowDataPilotSourceData( *pDPObj, aFilters ); + else + Sound::Beep(); // nothing to expand/collapse/show + } + + return; + } + + // Check for cell protection attribute. + ScTableProtection* pProtect = pDoc->GetTabProtection( nTab ); + bool bEditAllowed = true; + if ( pProtect && pProtect->isProtected() ) + { + bool bCellProtected = pDoc->HasAttrib(nPosX, nPosY, nTab, nPosX, nPosY, nTab, HASATTR_PROTECTED); + bool bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS); + bool bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS); + + if ( bSkipProtected && bSkipUnprotected ) + bEditAllowed = false; + else if ( (bCellProtected && bSkipProtected) || (!bCellProtected && bSkipUnprotected) ) + bEditAllowed = false; + } + + if ( bEditAllowed ) + { + // edit cell contents + pViewData->GetViewShell()->UpdateInputHandler(); + pScMod->SetInputMode( SC_INPUT_TABLE ); + if (pViewData->HasEditView(eWhich)) + { + // Text-Cursor gleich an die geklickte Stelle setzen + EditView* pEditView = pViewData->GetEditView( eWhich ); + MouseEvent aEditEvt( rMEvt.GetPosPixel(), 1, MOUSE_SYNTHETIC, MOUSE_LEFT, 0 ); + pEditView->MouseButtonDown( aEditEvt ); + pEditView->MouseButtonUp( aEditEvt ); + } + } + return; + } + + // + // Links in edit cells + // + + sal_Bool bAlt = rMEvt.IsMod2(); + if ( !bAlt && !bRefMode && !bDouble && nMouseStatus == SC_GM_URLDOWN ) + { + // beim ButtonUp nur ausfuehren, wenn ButtonDown auch ueber einer URL war + + String aName, aUrl, aTarget; + if ( GetEditUrl( rMEvt.GetPosPixel(), &aName, &aUrl, &aTarget ) ) + { + nMouseStatus = SC_GM_NONE; // keinen Doppelklick anfangen + ScGlobal::OpenURL( aUrl, aTarget ); + + // fire worksheet_followhyperlink event + uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents = pDoc->GetVbaEventProcessor(); + if( xVbaEvents.is() ) try + { + Point aPos = rMEvt.GetPosPixel(); + SCsCOL nPosX; + SCsROW nPosY; + SCTAB nTab = pViewData->GetTabNo(); + pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); + ScBaseCell* pCell = NULL; + if( lcl_GetHyperlinkCell( pDoc, nPosX, nPosY, nTab, pCell ) ) + { + ScAddress aCellPos( nPosX, nPosY, nTab ); + uno::Reference< table::XCell > xCell( new ScCellObj( pViewData->GetDocShell(), aCellPos ) ); + uno::Sequence< uno::Any > aArgs(1); + aArgs[0] <<= xCell; + xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKSHEET_FOLLOWHYPERLINK, aArgs ); + } + } + catch( uno::Exception& ) + { + } + + return; + } + } + + // + // Gridwin - SelectionEngine + // + + // SelMouseButtonDown is called only for left button, but SelMouseButtonUp would return + // sal_True for any call, so IsLeft must be checked here, too. + + if ( rMEvt.IsLeft() && pViewData->GetView()->GetSelEngine()->SelMouseButtonUp( rMEvt ) ) + { +// rMark.MarkToSimple(); + pViewData->GetView()->UpdateAutoFillMark(); + + SfxDispatcher* pDisp = pViewData->GetViewShell()->GetDispatcher(); + sal_Bool bFormulaMode = pScMod->IsFormulaMode(); + DBG_ASSERT( pDisp || bFormulaMode, "Cursor auf nicht aktiver View bewegen ?" ); + + // #i14927# execute SID_CURRENTCELL (for macro recording) only if there is no + // multiple selection, so the argument string completely describes the selection, + // and executing the slot won't change the existing selection (executing the slot + // here and from a recorded macro is treated equally) + + if ( pDisp && !bFormulaMode && !rMark.IsMultiMarked() ) + { + String aAddr; // CurrentCell + if( rMark.IsMarked() ) + { +// sal_Bool bKeep = rMark.IsMultiMarked(); //! wohin damit ??? + + ScRange aScRange; + rMark.GetMarkArea( aScRange ); + aScRange.Format( aAddr, SCR_ABS ); + if ( aScRange.aStart == aScRange.aEnd ) + { + // make sure there is a range selection string even for a single cell + String aSingle = aAddr; + aAddr.Append( (sal_Char) ':' ); + aAddr.Append( aSingle ); + } + + //! SID_MARKAREA gibts nicht mehr ??? + //! was passiert beim Markieren mit dem Cursor ??? + } + else // nur Cursor bewegen + { + ScAddress aScAddress( pViewData->GetCurX(), pViewData->GetCurY(), 0 ); + aScAddress.Format( aAddr, SCA_ABS ); + } + + SfxStringItem aPosItem( SID_CURRENTCELL, aAddr ); + pDisp->Execute( SID_CURRENTCELL, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD, + &aPosItem, (void*)0L ); + + pViewData->GetView()->InvalidateAttribs(); + } + return; + } +} + +void ScGridWindow::FakeButtonUp() +{ + if ( nButtonDown ) + { + MouseEvent aEvent( aCurMousePos ); // nButtons = 0 -> ignore + MouseButtonUp( aEvent ); + } +} + +void __EXPORT ScGridWindow::MouseMove( const MouseEvent& rMEvt ) +{ + aCurMousePos = rMEvt.GetPosPixel(); + + if ( rMEvt.IsLeaveWindow() && pNoteMarker && !pNoteMarker->IsByKeyboard() ) + HideNoteMarker(); + + ScModule* pScMod = SC_MOD(); + if (pScMod->IsModalMode(pViewData->GetSfxDocShell())) + return; + + // Ob aus dem Edit-Modus Drag&Drop gestartet wurde, bekommt man leider + // nicht anders mit: + + if (bEEMouse && nButtonDown && !rMEvt.GetButtons()) + { + bEEMouse = sal_False; + nButtonDown = 0; + nMouseStatus = SC_GM_NONE; + return; + } + + if (nMouseStatus == SC_GM_IGNORE) + return; + + if (nMouseStatus == SC_GM_WATERUNDO) // Undo im Giesskannenmodus -> nur auf Up warten + return; + + if ( pViewData->GetViewShell()->IsAuditShell() ) // Detektiv-Fuell-Modus + { + SetPointer( Pointer( POINTER_FILL ) ); + return; + } + + if (nMouseStatus == SC_GM_FILTER && pFilterBox) + { + Point aRelPos = pFilterBox->ScreenToOutputPixel( OutputToScreenPixel( rMEvt.GetPosPixel() ) ); + if ( Rectangle(Point(),pFilterBox->GetOutputSizePixel()).IsInside(aRelPos) ) + { + nButtonDown = 0; + nMouseStatus = SC_GM_NONE; + if ( pFilterBox->GetMode() == SC_FILTERBOX_FILTER ) + { + if (mpFilterButton.get()) + { + mpFilterButton->setHasHiddenMember(false); + mpFilterButton->setPopupPressed(false); + HideCursor(); + mpFilterButton->draw(); + ShowCursor(); + } + } + ReleaseMouse(); + pFilterBox->MouseButtonDown( MouseEvent( aRelPos, 1, MOUSE_SIMPLECLICK, MOUSE_LEFT ) ); + return; + } + } + + sal_Bool bFormulaMode = pScMod->IsFormulaMode(); // naechster Klick -> Referenz + + if (bEEMouse && pViewData->HasEditView( eWhich )) + { + EditView* pEditView; + SCCOL nEditCol; + SCROW nEditRow; + pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow ); + pEditView->MouseMove( rMEvt ); + return; + } + + if (bDPMouse) + { + DPMouseMove( rMEvt ); + return; + } + + if (bRFMouse) + { + RFMouseMove( rMEvt, sal_False ); + return; + } + + if (nPagebreakMouse) + { + PagebreakMove( rMEvt, sal_False ); + return; + } + + // anderen Mauszeiger anzeigen? + + sal_Bool bEditMode = pViewData->HasEditView(eWhich); + + //! Testen ob RefMode-Dragging !!! + if ( bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()) ) + { + Point aPos = rMEvt.GetPosPixel(); + SCsCOL nPosX; + SCsROW nPosY; + pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); + + EditView* pEditView; + SCCOL nEditCol; + SCROW nEditRow; + pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow ); + SCCOL nEndCol = pViewData->GetEditEndCol(); + SCROW nEndRow = pViewData->GetEditEndRow(); + + if ( nPosX >= (SCsCOL) nEditCol && nPosX <= (SCsCOL) nEndCol && + nPosY >= (SCsROW) nEditRow && nPosY <= (SCsROW) nEndRow ) + { + // Field can only be URL field + sal_Bool bAlt = rMEvt.IsMod2(); + if ( !bAlt && !nButtonDown && pEditView && pEditView->GetFieldUnderMousePointer() ) + SetPointer( Pointer( POINTER_REFHAND ) ); + else if ( pEditView && pEditView->GetEditEngine()->IsVertical() ) + SetPointer( Pointer( POINTER_TEXT_VERTICAL ) ); + else + SetPointer( Pointer( POINTER_TEXT ) ); + return; + } + } + + sal_Bool bWater = SC_MOD()->GetIsWaterCan() || pViewData->GetView()->HasPaintBrush(); + if (bWater) + SetPointer( Pointer(POINTER_FILL) ); + + if (!bWater) + { + sal_Bool bCross = sal_False; + + // Range-Finder + + sal_Bool bCorner; + if ( HitRangeFinder( rMEvt.GetPosPixel(), bCorner ) ) + { + if (bCorner) + SetPointer( Pointer( POINTER_CROSS ) ); + else + SetPointer( Pointer( POINTER_HAND ) ); + bCross = sal_True; + } + + // Page-Break-Modus + + sal_uInt16 nBreakType; + if ( !nButtonDown && pViewData->IsPagebreakMode() && + ( nBreakType = HitPageBreak( rMEvt.GetPosPixel() ) ) != 0 ) + { + PointerStyle eNew = POINTER_ARROW; + switch ( nBreakType ) + { + case SC_PD_RANGE_L: + case SC_PD_RANGE_R: + case SC_PD_BREAK_H: + eNew = POINTER_ESIZE; + break; + case SC_PD_RANGE_T: + case SC_PD_RANGE_B: + case SC_PD_BREAK_V: + eNew = POINTER_SSIZE; + break; + case SC_PD_RANGE_TL: + case SC_PD_RANGE_BR: + eNew = POINTER_SESIZE; + break; + case SC_PD_RANGE_TR: + case SC_PD_RANGE_BL: + eNew = POINTER_NESIZE; + break; + } + SetPointer( Pointer( eNew ) ); + bCross = sal_True; + } + + // Fill-Cursor anzeigen ? + + if ( !bFormulaMode && !nButtonDown ) + if (TestMouse( rMEvt, sal_False )) + bCross = sal_True; + + if ( nButtonDown && pViewData->IsAnyFillMode() ) + { + SetPointer( Pointer( POINTER_CROSS ) ); + bCross = sal_True; + nScFillModeMouseModifier = rMEvt.GetModifier(); // ausgewertet bei AutoFill und Matrix + } + + if (!bCross) + { + sal_Bool bAlt = rMEvt.IsMod2(); + + if (bEditMode) // Edit-Mode muss zuerst kommen! + SetPointer( Pointer( POINTER_ARROW ) ); + else if ( !bAlt && !nButtonDown && + GetEditUrl(rMEvt.GetPosPixel()) ) + SetPointer( Pointer( POINTER_REFHAND ) ); + else if ( DrawMouseMove(rMEvt) ) // setzt Pointer um + return; + } + } + + if ( pViewData->GetView()->GetSelEngine()->SelMouseMove( rMEvt ) ) + return; +} + +void lcl_InitMouseEvent( ::com::sun::star::awt::MouseEvent& rEvent, const MouseEvent& rEvt ) +{ + rEvent.Modifiers = 0; + if ( rEvt.IsShift() ) + rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::SHIFT; + if ( rEvt.IsMod1() ) + rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD1; + if ( rEvt.IsMod2() ) + rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD2; + if ( rEvt.IsMod3() ) + rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD3; + + rEvent.Buttons = 0; + if ( rEvt.IsLeft() ) + rEvent.Buttons |= ::com::sun::star::awt::MouseButton::LEFT; + if ( rEvt.IsRight() ) + rEvent.Buttons |= ::com::sun::star::awt::MouseButton::RIGHT; + if ( rEvt.IsMiddle() ) + rEvent.Buttons |= ::com::sun::star::awt::MouseButton::MIDDLE; + + rEvent.X = rEvt.GetPosPixel().X(); + rEvent.Y = rEvt.GetPosPixel().Y(); + rEvent.ClickCount = rEvt.GetClicks(); + rEvent.PopupTrigger = sal_False; +} + +long ScGridWindow::PreNotify( NotifyEvent& rNEvt ) +{ + bool bDone = false; + sal_uInt16 nType = rNEvt.GetType(); + if ( nType == EVENT_MOUSEBUTTONUP || nType == EVENT_MOUSEBUTTONDOWN ) + { + Window* pWindow = rNEvt.GetWindow(); + if (pWindow == this && pViewData) + { + SfxViewFrame* pViewFrame = pViewData->GetViewShell()->GetViewFrame(); + if (pViewFrame) + { + com::sun::star::uno::Reference<com::sun::star::frame::XController> xController = pViewFrame->GetFrame().GetController(); + if (xController.is()) + { + ScTabViewObj* pImp = ScTabViewObj::getImplementation( xController ); + if (pImp && pImp->IsMouseListening()) + { + ::com::sun::star::awt::MouseEvent aEvent; + lcl_InitMouseEvent( aEvent, *rNEvt.GetMouseEvent() ); + if ( rNEvt.GetWindow() ) + aEvent.Source = rNEvt.GetWindow()->GetComponentInterface(); + if ( nType == EVENT_MOUSEBUTTONDOWN) + bDone = pImp->MousePressed( aEvent ); + else + bDone = pImp->MouseReleased( aEvent ); + } + } + } + } + } + if (bDone) // event consumed by a listener + { + if ( nType == EVENT_MOUSEBUTTONDOWN ) + { + const MouseEvent* pMouseEvent = rNEvt.GetMouseEvent(); + if ( pMouseEvent->IsRight() && pMouseEvent->GetClicks() == 1 ) + { + // If a listener returned true for a right-click call, also prevent opening the context menu + // (this works only if the context menu is opened on mouse-down) + nMouseStatus = SC_GM_IGNORE; + } + } + + return 1; + } + else + return Window::PreNotify( rNEvt ); +} + +void ScGridWindow::Tracking( const TrackingEvent& rTEvt ) +{ + // Weil die SelectionEngine kein Tracking kennt, die Events nur auf + // die verschiedenen MouseHandler verteilen... + + const MouseEvent& rMEvt = rTEvt.GetMouseEvent(); + + if ( rTEvt.IsTrackingCanceled() ) // alles abbrechen... + { + if (!pViewData->GetView()->IsInActivatePart()) + { + if (bDPMouse) + bDPMouse = sal_False; // gezeichnet wird per bDragRect + if (bDragRect) + { + // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich ); + bDragRect = sal_False; + UpdateDragRectOverlay(); + } + if (bRFMouse) + { + RFMouseMove( rMEvt, sal_True ); // richtig abbrechen geht dabei nicht... + bRFMouse = sal_False; + } + if (nPagebreakMouse) + { + // if (bPagebreakDrawn) + // DrawDragRect( aPagebreakDrag.aStart.Col(), aPagebreakDrag.aStart.Row(), + // aPagebreakDrag.aEnd.Col(), aPagebreakDrag.aEnd.Row(), sal_False ); + bPagebreakDrawn = sal_False; + UpdateDragRectOverlay(); + nPagebreakMouse = SC_PD_NONE; + } + + SetPointer( Pointer( POINTER_ARROW ) ); + StopMarking(); + MouseButtonUp( rMEvt ); // mit Status SC_GM_IGNORE aus StopMarking + + sal_Bool bRefMode = pViewData->IsRefMode(); + if (bRefMode) + SC_MOD()->EndReference(); // #63148# Dialog nicht verkleinert lassen + } + } + else if ( rTEvt.IsTrackingEnded() ) + { + // MouseButtonUp immer mit passenden Buttons (z.B. wegen Testtool, #63148#) + // Schliesslich behauptet der Tracking-Event ja, dass normal beendet und nicht + // abgebrochen wurde. + + MouseEvent aUpEvt( rMEvt.GetPosPixel(), rMEvt.GetClicks(), + rMEvt.GetMode(), nButtonDown, rMEvt.GetModifier() ); + MouseButtonUp( aUpEvt ); + } + else + MouseMove( rMEvt ); +} + +void ScGridWindow::StartDrag( sal_Int8 /* nAction */, const Point& rPosPixel ) +{ + if ( pFilterBox || nPagebreakMouse ) + return; + + HideNoteMarker(); + + CommandEvent aDragEvent( rPosPixel, COMMAND_STARTDRAG, sal_True ); + + if (bEEMouse && pViewData->HasEditView( eWhich )) + { + EditView* pEditView; + SCCOL nEditCol; + SCROW nEditRow; + pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow ); + + // #63263# don't remove the edit view while switching views + ScModule* pScMod = SC_MOD(); + pScMod->SetInEditCommand( sal_True ); + + pEditView->Command( aDragEvent ); + + ScInputHandler* pHdl = pScMod->GetInputHdl(); + if (pHdl) + pHdl->DataChanged(); + + pScMod->SetInEditCommand( sal_False ); + if (!pViewData->IsActive()) // dropped to different view? + { + ScInputHandler* pViewHdl = pScMod->GetInputHdl( pViewData->GetViewShell() ); + if ( pViewHdl && pViewData->HasEditView( eWhich ) ) + { + pViewHdl->CancelHandler(); + ShowCursor(); // missing from KillEditView + } + } + } + else + if ( !DrawCommand(aDragEvent) ) + pViewData->GetView()->GetSelEngine()->Command( aDragEvent ); +} + +void lcl_SetTextCursorPos( ScViewData* pViewData, ScSplitPos eWhich, Window* pWin ) +{ + SCCOL nCol = pViewData->GetCurX(); + SCROW nRow = pViewData->GetCurY(); + Rectangle aEditArea = pViewData->GetEditArea( eWhich, nCol, nRow, pWin, NULL, sal_True ); + aEditArea.Right() = aEditArea.Left(); + aEditArea = pWin->PixelToLogic( aEditArea ); + pWin->SetCursorRect( &aEditArea ); +} + +void __EXPORT ScGridWindow::Command( const CommandEvent& rCEvt ) +{ + // The command event is send to the window after a possible context + // menu from an inplace client is closed. Now we have the chance to + // deactivate the inplace client without any problem regarding parent + // windows and code on the stack. + // For more information, see #126086# and #128122# + sal_uInt16 nCmd = rCEvt.GetCommand(); + ScTabViewShell* pTabViewSh = pViewData->GetViewShell(); + SfxInPlaceClient* pClient = pTabViewSh->GetIPClient(); + if ( pClient && + pClient->IsObjectInPlaceActive() && + nCmd == COMMAND_CONTEXTMENU ) + { + pTabViewSh->DeactivateOle(); + return; + } + + ScModule* pScMod = SC_MOD(); + DBG_ASSERT( nCmd != COMMAND_STARTDRAG, "ScGridWindow::Command called with COMMAND_STARTDRAG" ); + + if ( nCmd == COMMAND_STARTEXTTEXTINPUT || + nCmd == COMMAND_ENDEXTTEXTINPUT || + nCmd == COMMAND_EXTTEXTINPUT || + nCmd == COMMAND_CURSORPOS ) + { + sal_Bool bEditView = pViewData->HasEditView( eWhich ); + if (!bEditView) + { + // only if no cell editview is active, look at drawview + SdrView* pSdrView = pViewData->GetView()->GetSdrView(); + if ( pSdrView ) + { + OutlinerView* pOlView = pSdrView->GetTextEditOutlinerView(); + if ( pOlView && pOlView->GetWindow() == this ) + { + pOlView->Command( rCEvt ); + return; // done + } + } + } + + if ( nCmd == COMMAND_CURSORPOS && !bEditView ) + { + // #88458# CURSORPOS may be called without following text input, + // to set the input method window position + // -> input mode must not be started, + // manually calculate text insert position if not in input mode + + lcl_SetTextCursorPos( pViewData, eWhich, this ); + return; + } + + ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() ); + if ( pHdl ) + { + pHdl->InputCommand( rCEvt, sal_True ); + return; // done + } + + Window::Command( rCEvt ); + return; + } + + if ( nCmd == COMMAND_VOICE ) + { + // Der Handler wird nur gerufen, wenn ein Text-Cursor aktiv ist, + // also muss es eine EditView oder ein editiertes Zeichenobjekt geben + + ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() ); + if ( pHdl && pViewData->HasEditView( eWhich ) ) + { + EditView* pEditView = pViewData->GetEditView( eWhich ); // ist dann nicht 0 + pHdl->DataChanging(); + pEditView->Command( rCEvt ); + pHdl->DataChanged(); + return; // erledigt + } + SdrView* pSdrView = pViewData->GetView()->GetSdrView(); + if ( pSdrView ) + { + OutlinerView* pOlView = pSdrView->GetTextEditOutlinerView(); + if ( pOlView && pOlView->GetWindow() == this ) + { + pOlView->Command( rCEvt ); + return; // erledigt + } + } + Window::Command(rCEvt); // sonst soll sich die Basisklasse drum kuemmern... + return; + } + + if ( nCmd == COMMAND_PASTESELECTION ) + { + if ( bEEMouse ) + { + // EditEngine handles selection in MouseButtonUp - no action + // needed in command handler + } + else + { + PasteSelection( rCEvt.GetMousePosPixel() ); + } + return; + } + + if ( nCmd == COMMAND_INPUTLANGUAGECHANGE ) + { + // #i55929# Font and font size state depends on input language if nothing is selected, + // so the slots have to be invalidated when the input language is changed. + + SfxBindings& rBindings = pViewData->GetBindings(); + rBindings.Invalidate( SID_ATTR_CHAR_FONT ); + rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT ); + return; + } + + if ( nCmd == COMMAND_WHEEL || nCmd == COMMAND_STARTAUTOSCROLL || nCmd == COMMAND_AUTOSCROLL ) + { + sal_Bool bDone = pViewData->GetView()->ScrollCommand( rCEvt, eWhich ); + if (!bDone) + Window::Command(rCEvt); + return; + } + // #i7560# FormulaMode check is below scrolling - scrolling is allowed during formula input + sal_Bool bDisable = pScMod->IsFormulaMode() || + pScMod->IsModalMode(pViewData->GetSfxDocShell()); + if (bDisable) + return; + + if ( nCmd == COMMAND_CONTEXTMENU && !SC_MOD()->GetIsWaterCan() ) + { + sal_Bool bMouse = rCEvt.IsMouseEvent(); + if ( bMouse && nMouseStatus == SC_GM_IGNORE ) + return; + + if (pViewData->IsAnyFillMode()) + { + pViewData->GetView()->StopRefMode(); + pViewData->ResetFillMode(); + } + ReleaseMouse(); + StopMarking(); + + Point aPosPixel = rCEvt.GetMousePosPixel(); + Point aMenuPos = aPosPixel; + + if ( bMouse ) + { + SCsCOL nCellX = -1; + SCsROW nCellY = -1; + pViewData->GetPosFromPixel(aPosPixel.X(), aPosPixel.Y(), eWhich, nCellX, nCellY); + ScDocument* pDoc = pViewData->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + const ScTableProtection* pProtect = pDoc->GetTabProtection(nTab); + bool bSelectAllowed = true; + if ( pProtect && pProtect->isProtected() ) + { + // This sheet is protected. Check if a context menu is allowed on this cell. + bool bCellProtected = pDoc->HasAttrib(nCellX, nCellY, nTab, nCellX, nCellY, nTab, HASATTR_PROTECTED); + bool bSelProtected = pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS); + bool bSelUnprotected = pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS); + + if (bCellProtected) + bSelectAllowed = bSelProtected; + else + bSelectAllowed = bSelUnprotected; + } + if (!bSelectAllowed) + // Selecting this cell is not allowed, neither is context menu. + return; + + // #i18735# First select the item under the mouse pointer. + // This can change the selection, and the view state (edit mode, etc). + SelectForContextMenu( aPosPixel, nCellX, nCellY ); + } + + sal_Bool bDone = sal_False; + sal_Bool bEdit = pViewData->HasEditView(eWhich); + if ( !bEdit ) + { + // Edit-Zelle mit Spelling-Errors ? + if ( bMouse && GetEditUrlOrError( sal_True, aPosPixel ) ) + { + // GetEditUrlOrError hat den Cursor schon bewegt + + pScMod->SetInputMode( SC_INPUT_TABLE ); + bEdit = pViewData->HasEditView(eWhich); // hat's geklappt ? + + DBG_ASSERT( bEdit, "kann nicht in Edit-Modus schalten" ); + } + } + if ( bEdit ) + { + EditView* pEditView = pViewData->GetEditView( eWhich ); // ist dann nicht 0 + + if ( !bMouse ) + { + Cursor* pCur = pEditView->GetCursor(); + if ( pCur ) + { + Point aLogicPos = pCur->GetPos(); + // use the position right of the cursor (spell popup is opened if + // the cursor is before the word, but not if behind it) + aLogicPos.X() += pCur->GetWidth(); + aLogicPos.Y() += pCur->GetHeight() / 2; // center vertically + aMenuPos = LogicToPixel( aLogicPos ); + } + } + + // if edit mode was just started above, online spelling may be incomplete + pEditView->GetEditEngine()->CompleteOnlineSpelling(); + + // IsCursorAtWrongSpelledWord could be used for !bMouse + // if there was a corresponding ExecuteSpellPopup call + + if( pEditView->IsWrongSpelledWordAtPos( aMenuPos ) ) + { + // Wenn man unter OS/2 neben das Popupmenue klickt, kommt MouseButtonDown + // vor dem Ende des Menue-Execute, darum muss SetModified vorher kommen + // (Bug #40968#) + ScInputHandler* pHdl = pScMod->GetInputHdl(); + if (pHdl) + pHdl->SetModified(); + + Link aLink = LINK( this, ScGridWindow, PopupSpellingHdl ); + pEditView->ExecuteSpellPopup( aMenuPos, &aLink ); + + bDone = sal_True; + } + } + else if ( !bMouse ) + { + // non-edit menu by keyboard -> use lower right of cell cursor position + + SCCOL nCurX = pViewData->GetCurX(); + SCROW nCurY = pViewData->GetCurY(); + aMenuPos = pViewData->GetScrPos( nCurX, nCurY, eWhich, sal_True ); + long nSizeXPix; + long nSizeYPix; + pViewData->GetMergeSizePixel( nCurX, nCurY, nSizeXPix, nSizeYPix ); + aMenuPos.X() += nSizeXPix; + aMenuPos.Y() += nSizeYPix; + + if (pViewData) + { + ScTabViewShell* pViewSh = pViewData->GetViewShell(); + if (pViewSh) + { + // Is a draw object selected? + + SdrView* pDrawView = pViewSh->GetSdrView(); + if (pDrawView && pDrawView->AreObjectsMarked()) + { + // #100442#; the conext menu should open in the middle of the selected objects + Rectangle aSelectRect(LogicToPixel(pDrawView->GetAllMarkedBoundRect())); + aMenuPos = aSelectRect.Center(); + } + } + } + } + + if (!bDone) + { + SfxDispatcher::ExecutePopup( 0, this, &aMenuPos ); + } + } +} + +void ScGridWindow::SelectForContextMenu( const Point& rPosPixel, SCsCOL nCellX, SCsROW nCellY ) +{ + // #i18735# if the click was outside of the current selection, + // the cursor is moved or an object at the click position selected. + // (see SwEditWin::SelectMenuPosition in Writer) + + ScTabView* pView = pViewData->GetView(); + ScDrawView* pDrawView = pView->GetScDrawView(); + + // check cell edit mode + + if ( pViewData->HasEditView(eWhich) ) + { + ScModule* pScMod = SC_MOD(); + SCCOL nEditStartCol = pViewData->GetEditViewCol(); //! change to GetEditStartCol after calcrtl is integrated + SCROW nEditStartRow = pViewData->GetEditViewRow(); + SCCOL nEditEndCol = pViewData->GetEditEndCol(); + SCROW nEditEndRow = pViewData->GetEditEndRow(); + + if ( nCellX >= (SCsCOL) nEditStartCol && nCellX <= (SCsCOL) nEditEndCol && + nCellY >= (SCsROW) nEditStartRow && nCellY <= (SCsROW) nEditEndRow ) + { + // handle selection within the EditView + + EditView* pEditView = pViewData->GetEditView( eWhich ); // not NULL (HasEditView) + EditEngine* pEditEngine = pEditView->GetEditEngine(); + Rectangle aOutputArea = pEditView->GetOutputArea(); + Rectangle aVisArea = pEditView->GetVisArea(); + + Point aTextPos = PixelToLogic( rPosPixel ); + if ( pEditEngine->IsVertical() ) // have to manually transform position + { + aTextPos -= aOutputArea.TopRight(); + long nTemp = -aTextPos.X(); + aTextPos.X() = aTextPos.Y(); + aTextPos.Y() = nTemp; + } + else + aTextPos -= aOutputArea.TopLeft(); + aTextPos += aVisArea.TopLeft(); // position in the edit document + + EPosition aDocPosition = pEditEngine->FindDocPosition(aTextPos); + ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex); + ESelection aSelection = pEditView->GetSelection(); + aSelection.Adjust(); // needed for IsLess/IsGreater + if ( aCompare.IsLess(aSelection) || aCompare.IsGreater(aSelection) ) + { + // clicked outside the selected text - deselect and move text cursor + MouseEvent aEvent( rPosPixel ); + pEditView->MouseButtonDown( aEvent ); + pEditView->MouseButtonUp( aEvent ); + pScMod->InputSelection( pEditView ); + } + + return; // clicked within the edit view - keep edit mode + } + else + { + // outside of the edit view - end edit mode, regardless of cell selection, then continue + pScMod->InputEnterHandler(); + } + } + + // check draw text edit mode + + Point aLogicPos = PixelToLogic( rPosPixel ); // after cell edit mode is ended + if ( pDrawView && pDrawView->GetTextEditObject() && pDrawView->GetTextEditOutlinerView() ) + { + OutlinerView* pOlView = pDrawView->GetTextEditOutlinerView(); + Rectangle aOutputArea = pOlView->GetOutputArea(); + if ( aOutputArea.IsInside( aLogicPos ) ) + { + // handle selection within the OutlinerView + + Outliner* pOutliner = pOlView->GetOutliner(); + const EditEngine& rEditEngine = pOutliner->GetEditEngine(); + Rectangle aVisArea = pOlView->GetVisArea(); + + Point aTextPos = aLogicPos; + if ( pOutliner->IsVertical() ) // have to manually transform position + { + aTextPos -= aOutputArea.TopRight(); + long nTemp = -aTextPos.X(); + aTextPos.X() = aTextPos.Y(); + aTextPos.Y() = nTemp; + } + else + aTextPos -= aOutputArea.TopLeft(); + aTextPos += aVisArea.TopLeft(); // position in the edit document + + EPosition aDocPosition = rEditEngine.FindDocPosition(aTextPos); + ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex); + ESelection aSelection = pOlView->GetSelection(); + aSelection.Adjust(); // needed for IsLess/IsGreater + if ( aCompare.IsLess(aSelection) || aCompare.IsGreater(aSelection) ) + { + // clicked outside the selected text - deselect and move text cursor + // use DrawView to allow extra handling there (none currently) + MouseEvent aEvent( rPosPixel ); + pDrawView->MouseButtonDown( aEvent, this ); + pDrawView->MouseButtonUp( aEvent, this ); + } + + return; // clicked within the edit area - keep edit mode + } + else + { + // Outside of the edit area - end text edit mode, then continue. + // DrawDeselectAll also ends text edit mode and updates the shells. + // If the click was on the edited object, it will be selected again below. + pView->DrawDeselectAll(); + } + } + + // look for existing selection + + sal_Bool bHitSelected = sal_False; + if ( pDrawView && pDrawView->IsMarkedObjHit( aLogicPos ) ) + { + // clicked on selected object -> don't change anything + bHitSelected = sal_True; + } + else if ( pViewData->GetMarkData().IsCellMarked(nCellX, nCellY) ) + { + // clicked on selected cell -> don't change anything + bHitSelected = sal_True; + } + + // select drawing object or move cell cursor + + if ( !bHitSelected ) + { + sal_Bool bWasDraw = ( pDrawView && pDrawView->AreObjectsMarked() ); + sal_Bool bHitDraw = sal_False; + if ( pDrawView ) + { + pDrawView->UnmarkAllObj(); + // Unlock the Internal Layer in order to activate the context menu. + // re-lock in ScDrawView::MarkListHasChanged() + lcl_UnLockComment( pDrawView, pDrawView->GetSdrPageView(), pDrawView->GetModel(), aLogicPos ,pViewData); + bHitDraw = pDrawView->MarkObj( aLogicPos ); + // draw shell is activated in MarkListHasChanged + } + if ( !bHitDraw ) + { + pView->Unmark(); + pView->SetCursor(nCellX, nCellY); + if ( bWasDraw ) + pViewData->GetViewShell()->SetDrawShell( sal_False ); // switch shells + } + } +} + +void __EXPORT ScGridWindow::KeyInput(const KeyEvent& rKEvt) +{ + // #96965# Cursor control for ref input dialog + if( SC_MOD()->IsRefDialogOpen() ) + { + const KeyCode& rKeyCode = rKEvt.GetKeyCode(); + if( !rKeyCode.GetModifier() && (rKeyCode.GetCode() == KEY_F2) ) + { + SC_MOD()->EndReference(); + return; + } + else if( pViewData->GetViewShell()->MoveCursorKeyInput( rKEvt ) ) + { + ScRange aRef( + pViewData->GetRefStartX(), pViewData->GetRefStartY(), pViewData->GetRefStartZ(), + pViewData->GetRefEndX(), pViewData->GetRefEndY(), pViewData->GetRefEndZ() ); + SC_MOD()->SetReference( aRef, pViewData->GetDocument() ); + return; + } + } + // wenn semi-Modeless-SfxChildWindow-Dialog oben, keine KeyInputs: + else if( !pViewData->IsAnyFillMode() ) + { + // query for existing note marker before calling ViewShell's keyboard handling + // which may remove the marker + sal_Bool bHadKeyMarker = ( pNoteMarker && pNoteMarker->IsByKeyboard() ); + ScTabViewShell* pViewSh = pViewData->GetViewShell(); + + if (pViewData->GetDocShell()->GetProgress()) + return; + + if (DrawKeyInput(rKEvt)) + return; + + if (!pViewData->GetView()->IsDrawSelMode() && !DrawHasMarkedObj()) // keine Eingaben im Zeichenmodus + { //! DrawShell abfragen !!! + if (pViewSh->TabKeyInput(rKEvt)) + return; + } + else + if (pViewSh->SfxViewShell::KeyInput(rKEvt)) // von SfxViewShell + return; + + KeyCode aCode = rKEvt.GetKeyCode(); + if ( aCode.GetCode() == KEY_ESCAPE && aCode.GetModifier() == 0 ) + { + if ( bHadKeyMarker ) + HideNoteMarker(); + else + pViewSh->Escape(); + return; + } + if ( aCode.GetCode() == KEY_F1 && aCode.GetModifier() == KEY_MOD1 ) + { + // ctrl-F1 shows or hides the note or redlining info for the cursor position + // (hard-coded because F1 can't be configured) + + if ( bHadKeyMarker ) + HideNoteMarker(); // hide when previously visible + else + ShowNoteMarker( pViewData->GetCurX(), pViewData->GetCurY(), sal_True ); + return; + } + } + + Window::KeyInput(rKEvt); +} + +void ScGridWindow::StopMarking() +{ + DrawEndAction(); // Markieren/Verschieben auf Drawing-Layer abbrechen + + if (nButtonDown) + { + pViewData->GetMarkData().SetMarking(sal_False); + nMouseStatus = SC_GM_IGNORE; + } +} + +void ScGridWindow::UpdateInputContext() +{ + sal_Bool bReadOnly = pViewData->GetDocShell()->IsReadOnly(); + sal_uLong nOptions = bReadOnly ? 0 : ( INPUTCONTEXT_TEXT | INPUTCONTEXT_EXTTEXTINPUT ); + + // when font from InputContext is used, + // it must be taken from the cursor position's cell attributes + + InputContext aContext; + aContext.SetOptions( nOptions ); + SetInputContext( aContext ); +} + +//-------------------------------------------------------- + + // sensitiver Bereich (Pixel) +#define SCROLL_SENSITIVE 20 + +sal_Bool ScGridWindow::DropScroll( const Point& rMousePos ) +{ +/* doch auch auf nicht aktiven Views... + if ( !pViewData->IsActive() ) + return sal_False; +*/ + SCsCOL nDx = 0; + SCsROW nDy = 0; + Size aSize = GetOutputSizePixel(); + + if (aSize.Width() > SCROLL_SENSITIVE * 3) + { + if ( rMousePos.X() < SCROLL_SENSITIVE && pViewData->GetPosX(WhichH(eWhich)) > 0 ) + nDx = -1; + if ( rMousePos.X() >= aSize.Width() - SCROLL_SENSITIVE + && pViewData->GetPosX(WhichH(eWhich)) < MAXCOL ) + nDx = 1; + } + if (aSize.Height() > SCROLL_SENSITIVE * 3) + { + if ( rMousePos.Y() < SCROLL_SENSITIVE && pViewData->GetPosY(WhichV(eWhich)) > 0 ) + nDy = -1; + if ( rMousePos.Y() >= aSize.Height() - SCROLL_SENSITIVE + && pViewData->GetPosY(WhichV(eWhich)) < MAXROW ) + nDy = 1; + } + + if ( nDx != 0 || nDy != 0 ) + { +// if (bDragRect) +// pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich ); + + if ( nDx != 0 ) + pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) ); + if ( nDy != 0 ) + pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) ); + +// if (bDragRect) +// pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich ); + } + + return sal_False; +} + +sal_Bool lcl_TestScenarioRedliningDrop( ScDocument* pDoc, const ScRange& aDragRange) +{ + // Testet, ob bei eingeschalteten RedLining, + // bei einem Drop ein Scenario betroffen ist. + + sal_Bool bReturn = sal_False; + SCTAB nTab = aDragRange.aStart.Tab(); + SCTAB nTabCount = pDoc->GetTableCount(); + + if(pDoc->GetChangeTrack()!=NULL) + { + if( pDoc->IsScenario(nTab) && pDoc->HasScenarioRange(nTab, aDragRange)) + { + bReturn = sal_True; + } + else + { + for(SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++) + { + if(pDoc->HasScenarioRange(i, aDragRange)) + { + bReturn = sal_True; + break; + } + } + } + } + return bReturn; +} + +ScRange lcl_MakeDropRange( SCCOL nPosX, SCROW nPosY, SCTAB nTab, const ScRange& rSource ) +{ + SCCOL nCol1 = nPosX; + SCCOL nCol2 = nCol1 + ( rSource.aEnd.Col() - rSource.aStart.Col() ); + if ( nCol2 > MAXCOL ) + { + nCol1 -= nCol2 - MAXCOL; + nCol2 = MAXCOL; + } + SCROW nRow1 = nPosY; + SCROW nRow2 = nRow1 + ( rSource.aEnd.Row() - rSource.aStart.Row() ); + if ( nRow2 > MAXROW ) + { + nRow1 -= nRow2 - MAXROW; + nRow2 = MAXROW; + } + + return ScRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab ); +} + +//-------------------------------------------------------- + +extern sal_Bool bPasteIsDrop; // viewfun4 -> move to header +extern sal_Bool bPasteIsMove; // viewfun7 -> move to header + +//-------------------------------------------------------- + +sal_Int8 ScGridWindow::AcceptPrivateDrop( const AcceptDropEvent& rEvt ) +{ + if ( rEvt.mbLeaving ) + { + // if (bDragRect) + // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich ); + bDragRect = sal_False; + UpdateDragRectOverlay(); + return rEvt.mnAction; + } + + const ScDragData& rData = SC_MOD()->GetDragData(); + if ( rData.pCellTransfer ) + { + // Don't move source that would include filtered rows. + if ((rEvt.mnAction & DND_ACTION_MOVE) && rData.pCellTransfer->HasFilteredRows()) + { + if (bDragRect) + { + bDragRect = sal_False; + UpdateDragRectOverlay(); + } + return DND_ACTION_NONE; + } + + Point aPos = rEvt.maPosPixel; + + ScDocument* pSourceDoc = rData.pCellTransfer->GetSourceDocument(); + ScDocument* pThisDoc = pViewData->GetDocument(); + if (pSourceDoc == pThisDoc) + { + if ( pThisDoc->HasChartAtPoint(pViewData->GetTabNo(), PixelToLogic(aPos)) ) + { + if (bDragRect) // Rechteck loeschen + { + // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich ); + bDragRect = sal_False; + UpdateDragRectOverlay(); + } + + //! highlight chart? (selection border?) + + sal_Int8 nRet = rEvt.mnAction; +//! if ( rEvt.GetAction() == DROP_LINK ) +//! bOk = rEvt.SetAction( DROP_COPY ); // can't link onto chart + return nRet; + } + } +//! else +//! if ( rEvt.GetAction() == DROP_MOVE ) +//! rEvt.SetAction( DROP_COPY ); // different doc: default=COPY + + + if ( rData.pCellTransfer->GetDragSourceFlags() & SC_DROP_TABLE ) // whole sheet? + { + sal_Bool bOk = pThisDoc->IsDocEditable(); + return bOk ? rEvt.mnAction : 0; // don't draw selection frame + } + + SCsCOL nPosX; + SCsROW nPosY; + pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); + + ScRange aSourceRange = rData.pCellTransfer->GetRange(); + SCCOL nSourceStartX = aSourceRange.aStart.Col(); + SCROW nSourceStartY = aSourceRange.aStart.Row(); + SCCOL nSourceEndX = aSourceRange.aEnd.Col(); + SCROW nSourceEndY = aSourceRange.aEnd.Row(); + SCCOL nSizeX = nSourceEndX - nSourceStartX + 1; + SCROW nSizeY = nSourceEndY - nSourceStartY + 1; + + if ( rEvt.mnAction != DND_ACTION_MOVE ) + nSizeY = rData.pCellTransfer->GetNonFilteredRows(); // copy/link: no filtered rows + + SCsCOL nNewDragX = nPosX - rData.pCellTransfer->GetDragHandleX(); + if (nNewDragX<0) nNewDragX=0; + if (nNewDragX+(nSizeX-1) > MAXCOL) + nNewDragX = MAXCOL-(nSizeX-1); + SCsROW nNewDragY = nPosY - rData.pCellTransfer->GetDragHandleY(); + if (nNewDragY<0) nNewDragY=0; + if (nNewDragY+(nSizeY-1) > MAXROW) + nNewDragY = MAXROW-(nSizeY-1); + + // don't break scenario ranges, don't drop on filtered + SCTAB nTab = pViewData->GetTabNo(); + ScRange aDropRange = lcl_MakeDropRange( nNewDragX, nNewDragY, nTab, aSourceRange ); + if ( lcl_TestScenarioRedliningDrop( pThisDoc, aDropRange ) || + lcl_TestScenarioRedliningDrop( pSourceDoc, aSourceRange ) || + ScViewUtil::HasFiltered( aDropRange, pThisDoc) ) + { + if (bDragRect) + { + // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich ); + bDragRect = sal_False; + UpdateDragRectOverlay(); + } + return DND_ACTION_NONE; + } + + InsCellCmd eDragInsertMode = INS_NONE; + Window::PointerState aState = GetPointerState(); + + // check for datapilot item sorting + ScDPObject* pDPObj = NULL; + if ( pThisDoc == pSourceDoc && ( pDPObj = pThisDoc->GetDPAtCursor( nNewDragX, nNewDragY, nTab ) ) != NULL ) + { + // drop on DataPilot table: sort or nothing + + bool bDPSort = false; + if ( pThisDoc->GetDPAtCursor( nSourceStartX, nSourceStartY, aSourceRange.aStart.Tab() ) == pDPObj ) + { + sheet::DataPilotTableHeaderData aDestData; + pDPObj->GetHeaderPositionData( ScAddress(nNewDragX, nNewDragY, nTab), aDestData ); + bool bValid = ( aDestData.Dimension >= 0 ); // dropping onto a field + + // look through the source range + for (SCROW nRow = aSourceRange.aStart.Row(); bValid && nRow <= aSourceRange.aEnd.Row(); ++nRow ) + for (SCCOL nCol = aSourceRange.aStart.Col(); bValid && nCol <= aSourceRange.aEnd.Col(); ++nCol ) + { + sheet::DataPilotTableHeaderData aSourceData; + pDPObj->GetHeaderPositionData( ScAddress( nCol, nRow, aSourceRange.aStart.Tab() ), aSourceData ); + if ( aSourceData.Dimension != aDestData.Dimension || !aSourceData.MemberName.getLength() ) + bValid = false; // empty (subtotal) or different field + } + + if ( bValid ) + { + sal_Bool bIsDataLayout; + String aDimName = pDPObj->GetDimName( aDestData.Dimension, bIsDataLayout ); + const ScDPSaveDimension* pDim = pDPObj->GetSaveData()->GetExistingDimensionByName( aDimName ); + if ( pDim ) + { + ScRange aOutRange = pDPObj->GetOutRange(); + + sal_uInt16 nOrient = pDim->GetOrientation(); + if ( nOrient == sheet::DataPilotFieldOrientation_COLUMN ) + { + eDragInsertMode = INS_CELLSRIGHT; + nSizeY = aOutRange.aEnd.Row() - nNewDragY + 1; + bDPSort = true; + } + else if ( nOrient == sheet::DataPilotFieldOrientation_ROW ) + { + eDragInsertMode = INS_CELLSDOWN; + nSizeX = aOutRange.aEnd.Col() - nNewDragX + 1; + bDPSort = true; + } + } + } + } + + if ( !bDPSort ) + { + // no valid sorting in a DataPilot table -> disallow + if ( bDragRect ) + { + bDragRect = sal_False; + UpdateDragRectOverlay(); + } + return DND_ACTION_NONE; + } + } + else if ( aState.mnState & KEY_MOD2 ) + { + if ( pThisDoc == pSourceDoc && nTab == aSourceRange.aStart.Tab() ) + { + long nDeltaX = labs( static_cast< long >( nNewDragX - nSourceStartX ) ); + long nDeltaY = labs( static_cast< long >( nNewDragY - nSourceStartY ) ); + if ( nDeltaX <= nDeltaY ) + { + eDragInsertMode = INS_CELLSDOWN; + } + else + { + eDragInsertMode = INS_CELLSRIGHT; + } + + if ( ( eDragInsertMode == INS_CELLSDOWN && nNewDragY <= nSourceEndY && + ( nNewDragX + nSizeX - 1 ) >= nSourceStartX && nNewDragX <= nSourceEndX && + ( nNewDragX != nSourceStartX || nNewDragY >= nSourceStartY ) ) || + ( eDragInsertMode == INS_CELLSRIGHT && nNewDragX <= nSourceEndX && + ( nNewDragY + nSizeY - 1 ) >= nSourceStartY && nNewDragY <= nSourceEndY && + ( nNewDragY != nSourceStartY || nNewDragX >= nSourceStartX ) ) ) + { + if ( bDragRect ) + { + bDragRect = sal_False; + UpdateDragRectOverlay(); + } + return DND_ACTION_NONE; + } + } + else + { + if ( static_cast< long >( nSizeX ) >= static_cast< long >( nSizeY ) ) + { + eDragInsertMode = INS_CELLSDOWN; + + } + else + { + eDragInsertMode = INS_CELLSRIGHT; + } + } + } + + if ( nNewDragX != (SCsCOL) nDragStartX || nNewDragY != (SCsROW) nDragStartY || + nDragStartX+nSizeX-1 != nDragEndX || nDragStartY+nSizeY-1 != nDragEndY || + !bDragRect || eDragInsertMode != meDragInsertMode ) + { + // if (bDragRect) + // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich ); + + nDragStartX = nNewDragX; + nDragStartY = nNewDragY; + nDragEndX = nDragStartX+nSizeX-1; + nDragEndY = nDragStartY+nSizeY-1; + bDragRect = sal_True; + meDragInsertMode = eDragInsertMode; + + // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich ); + + UpdateDragRectOverlay(); + + // show target position as tip help +#if 0 + if (Help::IsQuickHelpEnabled()) + { + ScRange aRange( nDragStartX, nDragStartY, nTab, nDragEndX, nDragEndY, nTab ); + String aHelpStr; + aRange.Format( aHelpStr, SCA_VALID ); // non-3D + + Point aPos = Pointer::GetPosPixel(); + sal_uInt16 nAlign = QUICKHELP_BOTTOM|QUICKHELP_RIGHT; + Rectangle aRect( aPos, aPos ); + Help::ShowQuickHelp(aRect, aHelpStr, nAlign); + } +#endif + } + } + + return rEvt.mnAction; +} + +sal_Int8 ScGridWindow::AcceptDrop( const AcceptDropEvent& rEvt ) +{ + const ScDragData& rData = SC_MOD()->GetDragData(); + if ( rEvt.mbLeaving ) + { + DrawMarkDropObj( NULL ); + if ( rData.pCellTransfer ) + return AcceptPrivateDrop( rEvt ); // hide drop marker for internal D&D + else + return rEvt.mnAction; + } + + if ( pViewData->GetDocShell()->IsReadOnly() ) + return DND_ACTION_NONE; + + + sal_Int8 nRet = DND_ACTION_NONE; + + if (rData.pCellTransfer) + { + ScRange aSource = rData.pCellTransfer->GetRange(); + if ( aSource.aStart.Col() != 0 || aSource.aEnd.Col() != MAXCOL || + aSource.aStart.Row() != 0 || aSource.aEnd.Row() != MAXROW ) + DropScroll( rEvt.maPosPixel ); + + nRet = AcceptPrivateDrop( rEvt ); + } + else + { + if ( rData.aLinkDoc.Len() ) + { + String aThisName; + ScDocShell* pDocSh = pViewData->GetDocShell(); + if (pDocSh && pDocSh->HasName()) + aThisName = pDocSh->GetMedium()->GetName(); + + if ( rData.aLinkDoc != aThisName ) + nRet = rEvt.mnAction; + } + else if (rData.aJumpTarget.Len()) + { + // internal bookmarks (from Navigator) + // local jumps from an unnamed document are possible only within a document + + if ( !rData.pJumpLocalDoc || rData.pJumpLocalDoc == pViewData->GetDocument() ) + nRet = rEvt.mnAction; + } + else + { + sal_Int8 nMyAction = rEvt.mnAction; + + if ( !rData.pDrawTransfer || + !IsMyModel(rData.pDrawTransfer->GetDragSourceView()) ) // drawing within the document + if ( rEvt.mbDefault && nMyAction == DND_ACTION_MOVE ) + nMyAction = DND_ACTION_COPY; + + ScDocument* pThisDoc = pViewData->GetDocument(); + SdrObject* pHitObj = pThisDoc->GetObjectAtPoint( + pViewData->GetTabNo(), PixelToLogic(rEvt.maPosPixel) ); + if ( pHitObj && nMyAction == DND_ACTION_LINK && !rData.pDrawTransfer ) + { + if ( IsDropFormatSupported(SOT_FORMATSTR_ID_SVXB) + || IsDropFormatSupported(SOT_FORMAT_GDIMETAFILE) + || IsDropFormatSupported(SOT_FORMAT_BITMAP) ) + { + // graphic dragged onto drawing object + DrawMarkDropObj( pHitObj ); + nRet = nMyAction; + } + } + if (!nRet) + DrawMarkDropObj( NULL ); + + if (!nRet) + { + switch ( nMyAction ) + { + case DND_ACTION_COPY: + case DND_ACTION_MOVE: + case DND_ACTION_COPYMOVE: + { + sal_Bool bMove = ( nMyAction == DND_ACTION_MOVE ); + if ( IsDropFormatSupported( SOT_FORMATSTR_ID_EMBED_SOURCE ) || + IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE ) || + IsDropFormatSupported( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) || + IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) || + IsDropFormatSupported( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) || + IsDropFormatSupported( SOT_FORMAT_STRING ) || + IsDropFormatSupported( SOT_FORMATSTR_ID_SYLK ) || + IsDropFormatSupported( SOT_FORMATSTR_ID_LINK ) || + IsDropFormatSupported( SOT_FORMATSTR_ID_HTML ) || + IsDropFormatSupported( SOT_FORMATSTR_ID_HTML_SIMPLE ) || + IsDropFormatSupported( SOT_FORMATSTR_ID_DIF ) || + IsDropFormatSupported( SOT_FORMATSTR_ID_DRAWING ) || + IsDropFormatSupported( SOT_FORMATSTR_ID_SVXB ) || + IsDropFormatSupported( SOT_FORMAT_RTF ) || + IsDropFormatSupported( SOT_FORMAT_GDIMETAFILE ) || + IsDropFormatSupported( SOT_FORMAT_BITMAP ) || + IsDropFormatSupported( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) || + IsDropFormatSupported( SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE ) || + ( !bMove && ( + IsDropFormatSupported( SOT_FORMAT_FILE_LIST ) || + IsDropFormatSupported( SOT_FORMAT_FILE ) || + IsDropFormatSupported( SOT_FORMATSTR_ID_SOLK ) || + IsDropFormatSupported( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) || + IsDropFormatSupported( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) || + IsDropFormatSupported( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) ) ) ) + { + nRet = nMyAction; + } + } + break; + case DND_ACTION_LINK: + if ( IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE ) || + IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) || + IsDropFormatSupported( SOT_FORMATSTR_ID_LINK ) || + IsDropFormatSupported( SOT_FORMAT_FILE_LIST ) || + IsDropFormatSupported( SOT_FORMAT_FILE ) || + IsDropFormatSupported( SOT_FORMATSTR_ID_SOLK ) || + IsDropFormatSupported( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) || + IsDropFormatSupported( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) || + IsDropFormatSupported( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) ) + { + nRet = nMyAction; + } + break; + } + + if ( nRet ) + { + // Simple check for protection: It's not known here if the drop will result + // in cells or drawing objects (some formats can be both) and how many cells + // the result will be. But if IsFormatEditable for the drop cell position + // is sal_False (ignores matrix formulas), nothing can be pasted, so the drop + // can already be rejected here. + + Point aPos = rEvt.maPosPixel; + SCsCOL nPosX; + SCsROW nPosY; + pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); + SCTAB nTab = pViewData->GetTabNo(); + ScDocument* pDoc = pViewData->GetDocument(); + + ScEditableTester aTester( pDoc, nTab, nPosX,nPosY, nPosX,nPosY ); + if ( !aTester.IsFormatEditable() ) + nRet = DND_ACTION_NONE; // forbidden + } + } + } + + // scroll only for accepted formats + if (nRet) + DropScroll( rEvt.maPosPixel ); + } + + return nRet; +} + +sal_uLong lcl_GetDropFormatId( const uno::Reference<datatransfer::XTransferable>& xTransfer, bool bPreferText = false ) +{ + TransferableDataHelper aDataHelper( xTransfer ); + + if ( !aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) ) + { + // use bookmark formats if no sba is present + + if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SOLK ) ) + return SOT_FORMATSTR_ID_SOLK; + else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) ) + return SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR; + else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) ) + return SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK; + else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) ) + return SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR; + } + + sal_uLong nFormatId = 0; + if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING ) ) + nFormatId = SOT_FORMATSTR_ID_DRAWING; + else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ) ) + nFormatId = SOT_FORMATSTR_ID_SVXB; + else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ) ) + { + // If it's a Writer object, insert RTF instead of OLE + + sal_Bool bDoRtf = sal_False; + SotStorageStreamRef xStm; + TransferableObjectDescriptor aObjDesc; + if( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) && + aDataHelper.GetSotStorageStream( SOT_FORMATSTR_ID_EMBED_SOURCE, xStm ) ) + { + SotStorageRef xStore( new SotStorage( *xStm ) ); + bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) || + aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) ) + && aDataHelper.HasFormat( SOT_FORMAT_RTF ) ); + } + if ( bDoRtf ) + nFormatId = FORMAT_RTF; + else + nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE; + } + else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) ) + nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE; + else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) ) + nFormatId = SOT_FORMATSTR_ID_SBA_DATAEXCHANGE; + else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE ) ) + nFormatId = SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE; + else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_BIFF_8 ) ) + nFormatId = SOT_FORMATSTR_ID_BIFF_8; + else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_BIFF_5 ) ) + nFormatId = SOT_FORMATSTR_ID_BIFF_5; + else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) ) + nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE_OLE; + else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) ) + nFormatId = SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE; + else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ) + nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE; + else if ( aDataHelper.HasFormat( SOT_FORMAT_RTF ) ) + nFormatId = SOT_FORMAT_RTF; + else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_HTML ) ) + nFormatId = SOT_FORMATSTR_ID_HTML; + else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_HTML_SIMPLE ) ) + nFormatId = SOT_FORMATSTR_ID_HTML_SIMPLE; + else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SYLK ) ) + nFormatId = SOT_FORMATSTR_ID_SYLK; + else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK ) ) + nFormatId = SOT_FORMATSTR_ID_LINK; + else if ( bPreferText && aDataHelper.HasFormat( SOT_FORMAT_STRING ) ) // #i86734# the behaviour introduced in #i62773# is wrong when pasting + nFormatId = SOT_FORMAT_STRING; + else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) ) + nFormatId = SOT_FORMAT_FILE_LIST; + else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE ) ) // #i62773# FILE_LIST/FILE before STRING (Unix file managers) + nFormatId = SOT_FORMAT_FILE; + else if ( aDataHelper.HasFormat( SOT_FORMAT_STRING ) ) + nFormatId = SOT_FORMAT_STRING; + else if ( aDataHelper.HasFormat( SOT_FORMAT_GDIMETAFILE ) ) + nFormatId = SOT_FORMAT_GDIMETAFILE; + else if ( aDataHelper.HasFormat( SOT_FORMAT_BITMAP ) ) + nFormatId = SOT_FORMAT_BITMAP; + + return nFormatId; +} + +sal_uLong lcl_GetDropLinkId( const uno::Reference<datatransfer::XTransferable>& xTransfer ) +{ + TransferableDataHelper aDataHelper( xTransfer ); + + sal_uLong nFormatId = 0; + if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) ) + nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE; + else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ) + nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE; + else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK ) ) + nFormatId = SOT_FORMATSTR_ID_LINK; + else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) ) + nFormatId = SOT_FORMAT_FILE_LIST; + else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE ) ) + nFormatId = SOT_FORMAT_FILE; + else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SOLK ) ) + nFormatId = SOT_FORMATSTR_ID_SOLK; + else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) ) + nFormatId = SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR; + else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) ) + nFormatId = SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK; + else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) ) + nFormatId = SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR; + + return nFormatId; +} + + +sal_Int8 ScGridWindow::ExecutePrivateDrop( const ExecuteDropEvent& rEvt ) +{ + // hide drop marker + // if (bDragRect) + // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich ); + bDragRect = sal_False; + UpdateDragRectOverlay(); + + ScModule* pScMod = SC_MOD(); + const ScDragData& rData = pScMod->GetDragData(); + + return DropTransferObj( rData.pCellTransfer, nDragStartX, nDragStartY, + PixelToLogic(rEvt.maPosPixel), rEvt.mnAction ); +} + +sal_Int8 ScGridWindow::DropTransferObj( ScTransferObj* pTransObj, SCCOL nDestPosX, SCROW nDestPosY, + const Point& rLogicPos, sal_Int8 nDndAction ) +{ + if ( !pTransObj ) + return 0; + + ScDocument* pSourceDoc = pTransObj->GetSourceDocument(); + ScDocShell* pDocSh = pViewData->GetDocShell(); + ScDocument* pThisDoc = pViewData->GetDocument(); + ScViewFunc* pView = pViewData->GetView(); + SCTAB nThisTab = pViewData->GetTabNo(); + sal_uInt16 nFlags = pTransObj->GetDragSourceFlags(); + + sal_Bool bIsNavi = ( nFlags & SC_DROP_NAVIGATOR ) != 0; + sal_Bool bIsMove = ( nDndAction == DND_ACTION_MOVE && !bIsNavi ); + + // workaround for wrong nDndAction on Windows when pressing solely + // the Alt key during drag and drop; + // can be removed after #i79215# has been fixed + if ( meDragInsertMode != INS_NONE ) + { + bIsMove = ( nDndAction & DND_ACTION_MOVE && !bIsNavi ); + } + + sal_Bool bIsLink = ( nDndAction == DND_ACTION_LINK ); + + ScRange aSource = pTransObj->GetRange(); + + // only use visible tab from source range - when dragging within one table, + // all selected tables at the time of dropping are used (handled in MoveBlockTo) + SCTAB nSourceTab = pTransObj->GetVisibleTab(); + aSource.aStart.SetTab( nSourceTab ); + aSource.aEnd.SetTab( nSourceTab ); + + SCCOL nSizeX = aSource.aEnd.Col() - aSource.aStart.Col() + 1; + SCROW nSizeY = (bIsMove ? (aSource.aEnd.Row() - aSource.aStart.Row() + 1) : + pTransObj->GetNonFilteredRows()); // copy/link: no filtered rows + ScRange aDest( nDestPosX, nDestPosY, nThisTab, + nDestPosX + nSizeX - 1, nDestPosY + nSizeY - 1, nThisTab ); + + + /* NOTE: AcceptPrivateDrop() already checked for filtered conditions during + * dragging and adapted drawing of the selection frame. We check here + * (again) because this may actually also be called from PasteSelection(), + * we would have to duplicate determination of flags and destination range + * and would lose the context of the "filtered destination is OK" cases + * below, which is already awkward enough as is. */ + + // Don't move filtered source. + bool bFiltered = (bIsMove && pTransObj->HasFilteredRows()); + if (!bFiltered) + { + if (pSourceDoc != pThisDoc && ((nFlags & SC_DROP_TABLE) || + (!bIsLink && meDragInsertMode == INS_NONE))) + { + // Nothing. Either entire sheet to be dropped, or the one case + // where PasteFromClip() is to be called that handles a filtered + // destination itself. Drag-copy from another document without + // inserting cells. + } + else + // Don't copy or move to filtered destination. + bFiltered = ScViewUtil::HasFiltered( aDest, pThisDoc); + } + + sal_Bool bDone = sal_False; + + if (!bFiltered && pSourceDoc == pThisDoc) + { + if ( nFlags & SC_DROP_TABLE ) // whole sheet? + { + if ( pThisDoc->IsDocEditable() ) + { + SCTAB nSrcTab = aSource.aStart.Tab(); + pViewData->GetDocShell()->MoveTable( nSrcTab, nThisTab, !bIsMove, sal_True ); // with Undo + pView->SetTabNo( nThisTab, sal_True ); + bDone = sal_True; + } + } + else // move/copy block + { + String aChartName; + if (pThisDoc->HasChartAtPoint( nThisTab, rLogicPos, &aChartName )) + { + String aRangeName; + aSource.Format( aRangeName, SCR_ABS_3D, pThisDoc ); + SfxStringItem aNameItem( SID_CHART_NAME, aChartName ); + SfxStringItem aRangeItem( SID_CHART_SOURCE, aRangeName ); + sal_uInt16 nId = bIsMove ? SID_CHART_SOURCE : SID_CHART_ADDSOURCE; + pViewData->GetDispatcher().Execute( nId, SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD, + &aRangeItem, &aNameItem, (void*) NULL ); + bDone = sal_True; + } + else if ( pThisDoc->GetDPAtCursor( nDestPosX, nDestPosY, nThisTab ) ) + { + // drop on DataPilot table: try to sort, fail if that isn't possible + + ScAddress aDestPos( nDestPosX, nDestPosY, nThisTab ); + if ( aDestPos != aSource.aStart ) + bDone = pViewData->GetView()->DataPilotMove( aSource, aDestPos ); + else + bDone = sal_True; // same position: nothing + } + else if ( nDestPosX != aSource.aStart.Col() || nDestPosY != aSource.aStart.Row() || + nSourceTab != nThisTab ) + { + String aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY ); + pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo ); + + bDone = sal_True; + if ( meDragInsertMode != INS_NONE ) + { + // call with bApi = sal_True to avoid error messages in drop handler + bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, sal_True /*bRecord*/, sal_True /*bApi*/, sal_True /*bPartOfPaste*/ ); + if ( bDone ) + { + if ( nThisTab == nSourceTab ) + { + if ( meDragInsertMode == INS_CELLSDOWN && + nDestPosX == aSource.aStart.Col() && nDestPosY < aSource.aStart.Row() ) + { + bDone = aSource.Move( 0, nSizeY, 0, pSourceDoc ); + } + else if ( meDragInsertMode == INS_CELLSRIGHT && + nDestPosY == aSource.aStart.Row() && nDestPosX < aSource.aStart.Col() ) + { + bDone = aSource.Move( nSizeX, 0, 0, pSourceDoc ); + } + } + pDocSh->UpdateOle( pViewData ); + pView->CellContentChanged(); + } + } + + if ( bDone ) + { + if ( bIsLink ) + { + // call with bApi = sal_True to avoid error messages in drop handler + bDone = pView->LinkBlock( aSource, aDest.aStart, sal_True /*bApi*/ ); + } + else + { + // call with bApi = sal_True to avoid error messages in drop handler + bDone = pView->MoveBlockTo( aSource, aDest.aStart, bIsMove, sal_True /*bRecord*/, sal_True /*bPaint*/, sal_True /*bApi*/ ); + } + } + + if ( bDone && meDragInsertMode != INS_NONE && bIsMove && nThisTab == nSourceTab ) + { + DelCellCmd eCmd = DEL_NONE; + if ( meDragInsertMode == INS_CELLSDOWN ) + { + eCmd = DEL_CELLSUP; + } + else if ( meDragInsertMode == INS_CELLSRIGHT ) + { + eCmd = DEL_CELLSLEFT; + } + + if ( ( eCmd == DEL_CELLSUP && nDestPosX == aSource.aStart.Col() ) || + ( eCmd == DEL_CELLSLEFT && nDestPosY == aSource.aStart.Row() ) ) + { + // call with bApi = sal_True to avoid error messages in drop handler + bDone = pDocSh->GetDocFunc().DeleteCells( aSource, NULL, eCmd, sal_True /*bRecord*/, sal_True /*bApi*/ ); + if ( bDone ) + { + if ( eCmd == DEL_CELLSUP && nDestPosY > aSource.aEnd.Row() ) + { + bDone = aDest.Move( 0, -nSizeY, 0, pThisDoc ); + } + else if ( eCmd == DEL_CELLSLEFT && nDestPosX > aSource.aEnd.Col() ) + { + bDone = aDest.Move( -nSizeX, 0, 0, pThisDoc ); + } + pDocSh->UpdateOle( pViewData ); + pView->CellContentChanged(); + } + } + } + + if ( bDone ) + { + pView->MarkRange( aDest, sal_False, sal_False ); + pView->SetCursor( aDest.aEnd.Col(), aDest.aEnd.Row() ); + } + + pDocSh->GetUndoManager()->LeaveListAction(); + + if (!bDone) + Sound::Beep(); // instead of error message in drop handler + } + else + bDone = sal_True; // nothing to do + } + + if (bDone) + pTransObj->SetDragWasInternal(); // don't delete source in DragFinished + } + else if ( !bFiltered && pSourceDoc ) // between documents + { + if ( nFlags & SC_DROP_TABLE ) // copy/link sheets between documents + { + if ( pThisDoc->IsDocEditable() ) + { + ScDocShell* pSrcShell = pTransObj->GetSourceDocShell(); + + SCTAB nTabs[MAXTABCOUNT]; + + ScMarkData aMark = pTransObj->GetSourceMarkData(); + SCTAB nTabCount = pSourceDoc->GetTableCount(); + SCTAB nTabSelCount = 0; + + for(SCTAB i=0; i<nTabCount; i++) + { + if(aMark.GetTableSelect(i)) + { + nTabs[nTabSelCount++]=i; + for(SCTAB j=i+1;j<nTabCount;j++) + { + if((!pSourceDoc->IsVisible(j))&&(pSourceDoc->IsScenario(j))) + { + nTabs[nTabSelCount++]=j; + i=j; + } + else break; + } + } + } + + pView->ImportTables( pSrcShell,nTabSelCount, nTabs, bIsLink, nThisTab ); + bDone = sal_True; + } + } + else if ( bIsLink ) + { + // as in PasteDDE + // (external references might be used instead?) + + SfxObjectShell* pSourceSh = pSourceDoc->GetDocumentShell(); + DBG_ASSERT(pSourceSh, "drag document has no shell"); + if (pSourceSh) + { + String aUndo = ScGlobal::GetRscString( STR_UNDO_COPY ); + pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo ); + + bDone = sal_True; + if ( meDragInsertMode != INS_NONE ) + { + // call with bApi = sal_True to avoid error messages in drop handler + bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, sal_True /*bRecord*/, sal_True /*bApi*/, sal_True /*bPartOfPaste*/ ); + if ( bDone ) + { + pDocSh->UpdateOle( pViewData ); + pView->CellContentChanged(); + } + } + + if ( bDone ) + { + String aApp = Application::GetAppName(); + String aTopic = pSourceSh->GetTitle( SFX_TITLE_FULLNAME ); + String aItem; + aSource.Format( aItem, SCA_VALID | SCA_TAB_3D, pSourceDoc ); + + // TODO: we could define ocQuote for " + const String aQuote( '"' ); + const String& sSep = ScCompiler::GetNativeSymbol( ocSep); + String aFormula( '=' ); + aFormula += ScCompiler::GetNativeSymbol( ocDde); + aFormula += ScCompiler::GetNativeSymbol( ocOpen); + aFormula += aQuote; + aFormula += aApp; + aFormula += aQuote; + aFormula += sSep; + aFormula += aQuote; + aFormula += aTopic; + aFormula += aQuote; + aFormula += sSep; + aFormula += aQuote; + aFormula += aItem; + aFormula += aQuote; + aFormula += ScCompiler::GetNativeSymbol( ocClose); + + pView->DoneBlockMode(); + pView->InitBlockMode( nDestPosX, nDestPosY, nThisTab ); + pView->MarkCursor( nDestPosX + nSizeX - 1, + nDestPosY + nSizeY - 1, nThisTab ); + + pView->EnterMatrix( aFormula ); + + pView->MarkRange( aDest, sal_False, sal_False ); + pView->SetCursor( aDest.aEnd.Col(), aDest.aEnd.Row() ); + } + + pDocSh->GetUndoManager()->LeaveListAction(); + } + } + else + { + //! HasSelectedBlockMatrixFragment without selected sheet? + //! or don't start dragging on a part of a matrix + + String aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY ); + pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo ); + + bDone = sal_True; + if ( meDragInsertMode != INS_NONE ) + { + // call with bApi = sal_True to avoid error messages in drop handler + bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, sal_True /*bRecord*/, sal_True /*bApi*/, sal_True /*bPartOfPaste*/ ); + if ( bDone ) + { + pDocSh->UpdateOle( pViewData ); + pView->CellContentChanged(); + } + } + + if ( bDone ) + { + pView->Unmark(); // before SetCursor, so CheckSelectionTransfer isn't called with a selection + pView->SetCursor( nDestPosX, nDestPosY ); + bDone = pView->PasteFromClip( IDF_ALL, pTransObj->GetDocument() ); // clip-doc + if ( bDone ) + { + pView->MarkRange( aDest, sal_False, sal_False ); + pView->SetCursor( aDest.aEnd.Col(), aDest.aEnd.Row() ); + } + } + + pDocSh->GetUndoManager()->LeaveListAction(); + + // no longer call ResetMark here - the inserted block has been selected + // and may have been copied to primary selection + } + } + + sal_Int8 nRet = bDone ? nDndAction : DND_ACTION_NONE; + return nRet; +} + +sal_Int8 ScGridWindow::ExecuteDrop( const ExecuteDropEvent& rEvt ) +{ + DrawMarkDropObj( NULL ); // drawing layer + + ScModule* pScMod = SC_MOD(); + const ScDragData& rData = pScMod->GetDragData(); + if (rData.pCellTransfer) + return ExecutePrivateDrop( rEvt ); + + Point aPos = rEvt.maPosPixel; + + if ( rData.aLinkDoc.Len() ) + { + // try to insert a link + + sal_Bool bOk = sal_True; + String aThisName; + ScDocShell* pDocSh = pViewData->GetDocShell(); + if (pDocSh && pDocSh->HasName()) + aThisName = pDocSh->GetMedium()->GetName(); + + if ( rData.aLinkDoc == aThisName ) // error - no link within a document + bOk = sal_False; + else + { + ScViewFunc* pView = pViewData->GetView(); + if ( rData.aLinkTable.Len() ) + pView->InsertTableLink( rData.aLinkDoc, EMPTY_STRING, EMPTY_STRING, + rData.aLinkTable ); + else if ( rData.aLinkArea.Len() ) + { + SCsCOL nPosX; + SCsROW nPosY; + pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); + pView->MoveCursorAbs( nPosX, nPosY, SC_FOLLOW_NONE, sal_False, sal_False ); + + pView->InsertAreaLink( rData.aLinkDoc, EMPTY_STRING, EMPTY_STRING, + rData.aLinkArea, 0 ); + } + else + { + DBG_ERROR("drop with link: no sheet nor area"); + bOk = sal_False; + } + } + + return bOk ? rEvt.mnAction : DND_ACTION_NONE; // don't try anything else + } + + Point aLogicPos = PixelToLogic(aPos); + + if (rData.pDrawTransfer) + { + sal_uInt16 nFlags = rData.pDrawTransfer->GetDragSourceFlags(); + + sal_Bool bIsNavi = ( nFlags & SC_DROP_NAVIGATOR ) != 0; + sal_Bool bIsMove = ( rEvt.mnAction == DND_ACTION_MOVE && !bIsNavi ); + + bPasteIsMove = bIsMove; + + pViewData->GetView()->PasteDraw( aLogicPos, rData.pDrawTransfer->GetModel() ); + + if (bPasteIsMove) + rData.pDrawTransfer->SetDragWasInternal(); + bPasteIsMove = sal_False; + + return rEvt.mnAction; + } + + + SCsCOL nPosX; + SCsROW nPosY; + pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); + + if (rData.aJumpTarget.Len()) + { + // internal bookmark (from Navigator) + // bookmark clipboard formats are in PasteScDataObject + + if ( !rData.pJumpLocalDoc || rData.pJumpLocalDoc == pViewData->GetDocument() ) + { + pViewData->GetViewShell()->InsertBookmark( rData.aJumpText, rData.aJumpTarget, + nPosX, nPosY ); + return rEvt.mnAction; + } + } + + sal_Bool bIsLink = ( rEvt.mnAction == DND_ACTION_LINK ); + + ScDocument* pThisDoc = pViewData->GetDocument(); + SdrObject* pHitObj = pThisDoc->GetObjectAtPoint( pViewData->GetTabNo(), PixelToLogic(aPos) ); + if ( pHitObj && bIsLink ) + { + // dropped on drawing object + // PasteOnDrawObject checks for valid formats + if ( pViewData->GetView()->PasteOnDrawObject( rEvt.maDropEvent.Transferable, pHitObj, sal_True ) ) + return rEvt.mnAction; + } + + sal_Bool bDone = sal_False; + + sal_uLong nFormatId = bIsLink ? + lcl_GetDropLinkId( rEvt.maDropEvent.Transferable ) : + lcl_GetDropFormatId( rEvt.maDropEvent.Transferable ); + if ( nFormatId ) + { + pScMod->SetInExecuteDrop( sal_True ); // #i28468# prevent error messages from PasteDataFormat + bPasteIsDrop = sal_True; + bDone = pViewData->GetView()->PasteDataFormat( + nFormatId, rEvt.maDropEvent.Transferable, nPosX, nPosY, &aLogicPos, bIsLink ); + bPasteIsDrop = sal_False; + pScMod->SetInExecuteDrop( sal_False ); + } + + sal_Int8 nRet = bDone ? rEvt.mnAction : DND_ACTION_NONE; + return nRet; +} + +//-------------------------------------------------------- + +void ScGridWindow::PasteSelection( const Point& rPosPixel ) +{ + Point aLogicPos = PixelToLogic( rPosPixel ); + + SCsCOL nPosX; + SCsROW nPosY; + pViewData->GetPosFromPixel( rPosPixel.X(), rPosPixel.Y(), eWhich, nPosX, nPosY ); + + ScSelectionTransferObj* pOwnSelection = SC_MOD()->GetSelectionTransfer(); + if ( pOwnSelection ) + { + // within Calc + + ScTransferObj* pCellTransfer = pOwnSelection->GetCellData(); + if ( pCellTransfer ) + { + // keep a reference to the data in case the selection is changed during paste + uno::Reference<datatransfer::XTransferable> xRef( pCellTransfer ); + DropTransferObj( pCellTransfer, nPosX, nPosY, aLogicPos, DND_ACTION_COPY ); + } + else + { + ScDrawTransferObj* pDrawTransfer = pOwnSelection->GetDrawData(); + if ( pDrawTransfer ) + { + // keep a reference to the data in case the selection is changed during paste + uno::Reference<datatransfer::XTransferable> xRef( pDrawTransfer ); + + // #96821# bSameDocClipboard argument for PasteDraw is needed + // because only DragData is checked directly inside PasteDraw + pViewData->GetView()->PasteDraw( aLogicPos, pDrawTransfer->GetModel(), sal_False, + pDrawTransfer->GetSourceDocID() == pViewData->GetDocument()->GetDocumentID() ); + } + } + } + else + { + // get selection from system + + TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSelection( this ) ); + uno::Reference<datatransfer::XTransferable> xTransferable = aDataHelper.GetTransferable(); + if ( xTransferable.is() ) + { + sal_uLong nFormatId = lcl_GetDropFormatId( xTransferable, true ); + if ( nFormatId ) + { + bPasteIsDrop = sal_True; + pViewData->GetView()->PasteDataFormat( nFormatId, xTransferable, nPosX, nPosY, &aLogicPos ); + bPasteIsDrop = sal_False; + } + } + } +} + +//-------------------------------------------------------- + +void ScGridWindow::UpdateEditViewPos() +{ + if (pViewData->HasEditView(eWhich)) + { + EditView* pView; + SCCOL nCol; + SCROW nRow; + pViewData->GetEditView( eWhich, pView, nCol, nRow ); + SCCOL nEndCol = pViewData->GetEditEndCol(); + SCROW nEndRow = pViewData->GetEditEndRow(); + + // hide EditView? + + sal_Bool bHide = ( nEndCol<pViewData->GetPosX(eHWhich) || nEndRow<pViewData->GetPosY(eVWhich) ); + if ( SC_MOD()->IsFormulaMode() ) + if ( pViewData->GetTabNo() != pViewData->GetRefTabNo() ) + bHide = sal_True; + + if (bHide) + { + Rectangle aRect = pView->GetOutputArea(); + long nHeight = aRect.Bottom() - aRect.Top(); + aRect.Top() = PixelToLogic(GetOutputSizePixel(), pViewData->GetLogicMode()). + Height() * 2; + aRect.Bottom() = aRect.Top() + nHeight; + pView->SetOutputArea( aRect ); + pView->HideCursor(); + } + else + { + // bForceToTop = sal_True for editing + Rectangle aPixRect = pViewData->GetEditArea( eWhich, nCol, nRow, this, NULL, sal_True ); + Point aScrPos = PixelToLogic( aPixRect.TopLeft(), pViewData->GetLogicMode() ); + + Rectangle aRect = pView->GetOutputArea(); + aRect.SetPos( aScrPos ); + pView->SetOutputArea( aRect ); + pView->ShowCursor(); + } + } +} + +void ScGridWindow::ScrollPixel( long nDifX, long nDifY ) +{ + ClickExtern(); + HideNoteMarker(); + + bIsInScroll = sal_True; + //sal_Bool bXor=DrawBeforeScroll(); + + SetMapMode(MAP_PIXEL); + Scroll( nDifX, nDifY, SCROLL_CHILDREN ); + SetMapMode( GetDrawMapMode() ); // verschobenen MapMode erzeugen + + UpdateEditViewPos(); + + DrawAfterScroll(); //bXor); + bIsInScroll = sal_False; +} + +// Formeln neu zeichnen ------------------------------------------------- + +void ScGridWindow::UpdateFormulas() +{ + if (pViewData->GetView()->IsMinimized()) + return; + + if ( nPaintCount ) + { + // nicht anfangen, verschachtelt zu painten + // (dann wuerde zumindest der MapMode nicht mehr stimmen) + + bNeedsRepaint = sal_True; // -> am Ende vom Paint nochmal Invalidate auf alles + aRepaintPixel = Rectangle(); // alles + return; + } + + SCCOL nX1 = pViewData->GetPosX( eHWhich ); + SCROW nY1 = pViewData->GetPosY( eVWhich ); + SCCOL nX2 = nX1 + pViewData->VisibleCellsX( eHWhich ); + SCROW nY2 = nY1 + pViewData->VisibleCellsY( eVWhich ); + + if (nX2 > MAXCOL) nX2 = MAXCOL; + if (nY2 > MAXROW) nY2 = MAXROW; + + // Draw( nX1, nY1, nX2, nY2, SC_UPDATE_CHANGED ); + + // don't draw directly - instead use OutputData to find changed area and invalidate + + SCROW nPosY = nY1; + + ScDocShell* pDocSh = pViewData->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + + pDoc->ExtendHidden( nX1, nY1, nX2, nY2, nTab ); + + Point aScrPos = pViewData->GetScrPos( nX1, nY1, eWhich ); + long nMirrorWidth = GetSizePixel().Width(); + sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); + // unused variable long nLayoutSign = bLayoutRTL ? -1 : 1; + if ( bLayoutRTL ) + { + long nEndPixel = pViewData->GetScrPos( nX2+1, nPosY, eWhich ).X(); + nMirrorWidth = aScrPos.X() - nEndPixel; + aScrPos.X() = nEndPixel + 1; + } + + long nScrX = aScrPos.X(); + long nScrY = aScrPos.Y(); + + double nPPTX = pViewData->GetPPTX(); + double nPPTY = pViewData->GetPPTY(); + + ScTableInfo aTabInfo; + pDoc->FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nTab, nPPTX, nPPTY, sal_False, sal_False ); + + Fraction aZoomX = pViewData->GetZoomX(); + Fraction aZoomY = pViewData->GetZoomY(); + ScOutputData aOutputData( this, OUTTYPE_WINDOW, aTabInfo, pDoc, nTab, + nScrX, nScrY, nX1, nY1, nX2, nY2, nPPTX, nPPTY, + &aZoomX, &aZoomY ); + aOutputData.SetMirrorWidth( nMirrorWidth ); + + aOutputData.FindChanged(); + + PolyPolygon aChangedPoly( aOutputData.GetChangedArea() ); // logic (PixelToLogic) + if ( aChangedPoly.Count() ) + { + Invalidate( aChangedPoly ); + } + + CheckNeedsRepaint(); // #i90362# used to be called via Draw() - still needed here +} + +void ScGridWindow::UpdateAutoFillMark(sal_Bool bMarked, const ScRange& rMarkRange) +{ + if ( bMarked != bAutoMarkVisible || ( bMarked && rMarkRange.aEnd != aAutoMarkPos ) ) + { + HideCursor(); + bAutoMarkVisible = bMarked; + if ( bMarked ) + aAutoMarkPos = rMarkRange.aEnd; + ShowCursor(); + + UpdateAutoFillOverlay(); + } +} + +void ScGridWindow::UpdateListValPos( sal_Bool bVisible, const ScAddress& rPos ) +{ + sal_Bool bOldButton = bListValButton; + ScAddress aOldPos = aListValPos; + + bListValButton = bVisible; + aListValPos = rPos; + + if ( bListValButton ) + { + if ( !bOldButton || aListValPos != aOldPos ) + { + // paint area of new button + Invalidate( PixelToLogic( GetListValButtonRect( aListValPos ) ) ); + } + } + if ( bOldButton ) + { + if ( !bListValButton || aListValPos != aOldPos ) + { + // paint area of old button + Invalidate( PixelToLogic( GetListValButtonRect( aOldPos ) ) ); + } + } +} + +void ScGridWindow::HideCursor() +{ + ++nCursorHideCount; + if (nCursorHideCount==1) + { + DrawCursor(); + DrawAutoFillMark(); + } +} + +void ScGridWindow::ShowCursor() +{ + if (nCursorHideCount==0) + { + DBG_ERROR("zuviel ShowCursor"); + return; + } + + if (nCursorHideCount==1) + { + // #i57745# Draw the cursor before setting the variable, in case the + // GetSizePixel call from drawing causes a repaint (resize handler is called) + DrawAutoFillMark(); + DrawCursor(); + } + + --nCursorHideCount; +} + +void __EXPORT ScGridWindow::GetFocus() +{ + ScTabViewShell* pViewShell = pViewData->GetViewShell(); + pViewShell->GotFocus(); + pViewShell->SetFormShellAtTop( sal_False ); // focus in GridWindow -> FormShell no longer on top + + if (pViewShell->HasAccessibilityObjects()) + pViewShell->BroadcastAccessibility(ScAccGridWinFocusGotHint(eWhich, GetAccessible())); + + + if ( !SC_MOD()->IsFormulaMode() ) + { + pViewShell->UpdateInputHandler(); +// StopMarking(); // falls Dialog (Fehler), weil dann kein ButtonUp + // MO: nur wenn nicht im RefInput-Modus + // -> GetFocus/MouseButtonDown-Reihenfolge + // auf dem Mac + } + + Window::GetFocus(); +} + +void __EXPORT ScGridWindow::LoseFocus() +{ + ScTabViewShell* pViewShell = pViewData->GetViewShell(); + pViewShell->LostFocus(); + + if (pViewShell->HasAccessibilityObjects()) + pViewShell->BroadcastAccessibility(ScAccGridWinFocusLostHint(eWhich, GetAccessible())); + + Window::LoseFocus(); +} + +Point ScGridWindow::GetMousePosPixel() const { return aCurMousePos; } + +//------------------------------------------------------------------------ + +sal_Bool ScGridWindow::HitRangeFinder( const Point& rMouse, sal_Bool& rCorner, + sal_uInt16* pIndex, SCsCOL* pAddX, SCsROW* pAddY ) +{ + sal_Bool bFound = sal_False; + ScInputHandler* pHdl = SC_MOD()->GetInputHdl( pViewData->GetViewShell() ); + if (pHdl) + { + ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList(); + if ( pRangeFinder && !pRangeFinder->IsHidden() && + pRangeFinder->GetDocName() == pViewData->GetDocShell()->GetTitle() ) + { + ScDocument* pDoc = pViewData->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); + long nLayoutSign = bLayoutRTL ? -1 : 1; + + SCsCOL nPosX; + SCsROW nPosY; + pViewData->GetPosFromPixel( rMouse.X(), rMouse.Y(), eWhich, nPosX, nPosY ); + // zusammengefasste (einzeln/Bereich) ??? + ScAddress aAddr( nPosX, nPosY, nTab ); + +// Point aNext = pViewData->GetScrPos( nPosX+1, nPosY+1, eWhich ); + + Point aNext = pViewData->GetScrPos( nPosX, nPosY, eWhich, sal_True ); + long nSizeXPix; + long nSizeYPix; + pViewData->GetMergeSizePixel( nPosX, nPosY, nSizeXPix, nSizeYPix ); + aNext.X() += nSizeXPix * nLayoutSign; + aNext.Y() += nSizeYPix; + + sal_Bool bCornerHor; + if ( bLayoutRTL ) + bCornerHor = ( rMouse.X() >= aNext.X() && rMouse.X() <= aNext.X() + 8 ); + else + bCornerHor = ( rMouse.X() >= aNext.X() - 8 && rMouse.X() <= aNext.X() ); + + sal_Bool bCellCorner = ( bCornerHor && + rMouse.Y() >= aNext.Y() - 8 && rMouse.Y() <= aNext.Y() ); + // corner is hit only if the mouse is within the cell + + sal_uInt16 nCount = (sal_uInt16)pRangeFinder->Count(); + for (sal_uInt16 i=nCount; i;) + { + // rueckwaerts suchen, damit der zuletzt gepaintete Rahmen gefunden wird + --i; + ScRangeFindData* pData = pRangeFinder->GetObject(i); + if ( pData && pData->aRef.In(aAddr) ) + { + if (pIndex) *pIndex = i; + if (pAddX) *pAddX = nPosX - pData->aRef.aStart.Col(); + if (pAddY) *pAddY = nPosY - pData->aRef.aStart.Row(); + bFound = sal_True; + rCorner = ( bCellCorner && aAddr == pData->aRef.aEnd ); + break; + } + } + } + } + return bFound; +} + +#define SCE_TOP 1 +#define SCE_BOTTOM 2 +#define SCE_LEFT 4 +#define SCE_RIGHT 8 +#define SCE_ALL 15 + +void lcl_PaintOneRange( ScDocShell* pDocSh, const ScRange& rRange, sal_uInt16 nEdges ) +{ + // der Range ist immer richtigherum + + SCCOL nCol1 = rRange.aStart.Col(); + SCROW nRow1 = rRange.aStart.Row(); + SCTAB nTab1 = rRange.aStart.Tab(); + SCCOL nCol2 = rRange.aEnd.Col(); + SCROW nRow2 = rRange.aEnd.Row(); + SCTAB nTab2 = rRange.aEnd.Tab(); + sal_Bool bHiddenEdge = sal_False; + SCROW nTmp; + + ScDocument* pDoc = pDocSh->GetDocument(); + while ( nCol1 > 0 && pDoc->ColHidden(nCol1, nTab1) ) + { + --nCol1; + bHiddenEdge = sal_True; + } + while ( nCol2 < MAXCOL && pDoc->ColHidden(nCol2, nTab1) ) + { + ++nCol2; + bHiddenEdge = sal_True; + } + nTmp = pDoc->FirstVisibleRow(0, nRow1, nTab1); + if (!ValidRow(nTmp)) + nTmp = 0; + if (nTmp < nRow1) + { + nRow1 = nTmp; + bHiddenEdge = sal_True; + } + nTmp = pDoc->FirstVisibleRow(nRow2, MAXROW, nTab1); + if (!ValidRow(nTmp)) + nTmp = MAXROW; + if (nTmp > nRow2) + { + nRow2 = nTmp; + bHiddenEdge = sal_True; + } + + if ( nCol2 > nCol1 + 1 && nRow2 > nRow1 + 1 && !bHiddenEdge ) + { + // nur an den Raendern entlang + // (die Ecken werden evtl. zweimal getroffen) + + if ( nEdges & SCE_TOP ) + pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol2, nRow1, nTab2, PAINT_MARKS ); + if ( nEdges & SCE_LEFT ) + pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol1, nRow2, nTab2, PAINT_MARKS ); + if ( nEdges & SCE_RIGHT ) + pDocSh->PostPaint( nCol2, nRow1, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS ); + if ( nEdges & SCE_BOTTOM ) + pDocSh->PostPaint( nCol1, nRow2, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS ); + } + else // everything in one call + pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS ); +} + +void lcl_PaintRefChanged( ScDocShell* pDocSh, const ScRange& rOldUn, const ScRange& rNewUn ) +{ + // Repaint fuer die Teile des Rahmens in Old, die bei New nicht mehr da sind + + ScRange aOld = rOldUn; + ScRange aNew = rNewUn; + aOld.Justify(); + aNew.Justify(); + + if ( aOld.aStart == aOld.aEnd ) //! Tab ignorieren? + pDocSh->GetDocument()->ExtendMerge(aOld); + if ( aNew.aStart == aNew.aEnd ) //! Tab ignorieren? + pDocSh->GetDocument()->ExtendMerge(aNew); + + SCCOL nOldCol1 = aOld.aStart.Col(); + SCROW nOldRow1 = aOld.aStart.Row(); + SCCOL nOldCol2 = aOld.aEnd.Col(); + SCROW nOldRow2 = aOld.aEnd.Row(); + SCCOL nNewCol1 = aNew.aStart.Col(); + SCROW nNewRow1 = aNew.aStart.Row(); + SCCOL nNewCol2 = aNew.aEnd.Col(); + SCROW nNewRow2 = aNew.aEnd.Row(); + SCTAB nTab1 = aOld.aStart.Tab(); // Tab aendert sich nicht + SCTAB nTab2 = aOld.aEnd.Tab(); + + if ( nNewRow2 < nOldRow1 || nNewRow1 > nOldRow2 || + nNewCol2 < nOldCol1 || nNewCol1 > nOldCol2 || + ( nNewCol1 != nOldCol1 && nNewRow1 != nOldRow1 && + nNewCol2 != nOldCol2 && nNewRow2 != nOldRow2 ) ) + { + // komplett weggeschoben oder alle Seiten veraendert + // (Abfrage <= statt < geht schief bei einzelnen Zeilen/Spalten) + + lcl_PaintOneRange( pDocSh, aOld, SCE_ALL ); + } + else // alle vier Kanten einzeln testen + { + // oberer Teil + if ( nNewRow1 < nOldRow1 ) // nur obere Linie loeschen + lcl_PaintOneRange( pDocSh, ScRange( + nOldCol1, nOldRow1, nTab1, nOldCol2, nOldRow1, nTab2 ), SCE_ALL ); + else if ( nNewRow1 > nOldRow1 ) // den Teil, der oben wegkommt + lcl_PaintOneRange( pDocSh, ScRange( + nOldCol1, nOldRow1, nTab1, nOldCol2, nNewRow1-1, nTab2 ), + SCE_ALL &~ SCE_BOTTOM ); + + // unterer Teil + if ( nNewRow2 > nOldRow2 ) // nur untere Linie loeschen + lcl_PaintOneRange( pDocSh, ScRange( + nOldCol1, nOldRow2, nTab1, nOldCol2, nOldRow2, nTab2 ), SCE_ALL ); + else if ( nNewRow2 < nOldRow2 ) // den Teil, der unten wegkommt + lcl_PaintOneRange( pDocSh, ScRange( + nOldCol1, nNewRow2+1, nTab1, nOldCol2, nOldRow2, nTab2 ), + SCE_ALL &~ SCE_TOP ); + + // linker Teil + if ( nNewCol1 < nOldCol1 ) // nur linke Linie loeschen + lcl_PaintOneRange( pDocSh, ScRange( + nOldCol1, nOldRow1, nTab1, nOldCol1, nOldRow2, nTab2 ), SCE_ALL ); + else if ( nNewCol1 > nOldCol1 ) // den Teil, der links wegkommt + lcl_PaintOneRange( pDocSh, ScRange( + nOldCol1, nOldRow1, nTab1, nNewCol1-1, nOldRow2, nTab2 ), + SCE_ALL &~ SCE_RIGHT ); + + // rechter Teil + if ( nNewCol2 > nOldCol2 ) // nur rechte Linie loeschen + lcl_PaintOneRange( pDocSh, ScRange( + nOldCol2, nOldRow1, nTab1, nOldCol2, nOldRow2, nTab2 ), SCE_ALL ); + else if ( nNewCol2 < nOldCol2 ) // den Teil, der rechts wegkommt + lcl_PaintOneRange( pDocSh, ScRange( + nNewCol2+1, nOldRow1, nTab1, nOldCol2, nOldRow2, nTab2 ), + SCE_ALL &~ SCE_LEFT ); + } +} + +void ScGridWindow::RFMouseMove( const MouseEvent& rMEvt, sal_Bool bUp ) +{ + ScInputHandler* pHdl = SC_MOD()->GetInputHdl( pViewData->GetViewShell() ); + if (!pHdl) + return; + ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList(); + if (!pRangeFinder || nRFIndex >= pRangeFinder->Count()) + return; + ScRangeFindData* pData = pRangeFinder->GetObject( nRFIndex ); + if (!pData) + return; + + // Mauszeiger + + if (bRFSize) + SetPointer( Pointer( POINTER_CROSS ) ); + else + SetPointer( Pointer( POINTER_HAND ) ); + + // Scrolling + + sal_Bool bTimer = sal_False; + Point aPos = rMEvt.GetPosPixel(); + SCsCOL nDx = 0; + SCsROW nDy = 0; + if ( aPos.X() < 0 ) nDx = -1; + if ( aPos.Y() < 0 ) nDy = -1; + Size aSize = GetOutputSizePixel(); + if ( aPos.X() >= aSize.Width() ) + nDx = 1; + if ( aPos.Y() >= aSize.Height() ) + nDy = 1; + if ( nDx != 0 || nDy != 0 ) + { + if ( nDx != 0) pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) ); + if ( nDy != 0 ) pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) ); + bTimer = sal_True; + } + + // Umschalten bei Fixierung (damit Scrolling funktioniert) + + if ( eWhich == pViewData->GetActivePart() ) //?? + { + if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX ) + if ( nDx > 0 ) + { + if ( eWhich == SC_SPLIT_TOPLEFT ) + pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT ); + else if ( eWhich == SC_SPLIT_BOTTOMLEFT ) + pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ); + } + + if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX ) + if ( nDy > 0 ) + { + if ( eWhich == SC_SPLIT_TOPLEFT ) + pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT ); + else if ( eWhich == SC_SPLIT_TOPRIGHT ) + pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ); + } + } + + // Verschieben + + SCsCOL nPosX; + SCsROW nPosY; + pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); + + ScRange aOld = pData->aRef; + ScRange aNew = aOld; + if ( bRFSize ) + { + aNew.aEnd.SetCol((SCCOL)nPosX); + aNew.aEnd.SetRow((SCROW)nPosY); + } + else + { + long nStartX = nPosX - nRFAddX; + if ( nStartX < 0 ) nStartX = 0; + long nStartY = nPosY - nRFAddY; + if ( nStartY < 0 ) nStartY = 0; + long nEndX = nStartX + aOld.aEnd.Col() - aOld.aStart.Col(); + if ( nEndX > MAXCOL ) + { + nStartX -= ( nEndX - MAXROW ); + nEndX = MAXCOL; + } + long nEndY = nStartY + aOld.aEnd.Row() - aOld.aStart.Row(); + if ( nEndY > MAXROW ) + { + nStartY -= ( nEndY - MAXROW ); + nEndY = MAXROW; + } + + aNew.aStart.SetCol((SCCOL)nStartX); + aNew.aStart.SetRow((SCROW)nStartY); + aNew.aEnd.SetCol((SCCOL)nEndX); + aNew.aEnd.SetRow((SCROW)nEndY); + } + + if ( bUp ) + aNew.Justify(); // beim ButtonUp wieder richtigherum + + if ( aNew != aOld ) + { + pHdl->UpdateRange( nRFIndex, aNew ); + + ScDocShell* pDocSh = pViewData->GetDocShell(); + + // nur das neuzeichnen, was sich veraendert hat... + lcl_PaintRefChanged( pDocSh, aOld, aNew ); + + // neuen Rahmen nur drueberzeichnen (synchron) + pDocSh->Broadcast( ScIndexHint( SC_HINT_SHOWRANGEFINDER, nRFIndex ) ); + + Update(); // was man bewegt, will man auch sofort sehen + } + + // Timer fuer Scrolling + + if (bTimer) + pViewData->GetView()->SetTimer( this, rMEvt ); // Event wiederholen + else + pViewData->GetView()->ResetTimer(); +} + +//------------------------------------------------------------------------ + +sal_Bool ScGridWindow::GetEditUrl( const Point& rPos, + String* pName, String* pUrl, String* pTarget ) +{ + return GetEditUrlOrError( sal_False, rPos, pName, pUrl, pTarget ); +} + +sal_Bool ScGridWindow::GetEditUrlOrError( sal_Bool bSpellErr, const Point& rPos, + String* pName, String* pUrl, String* pTarget ) +{ + //! nPosX/Y mit uebergeben? + SCsCOL nPosX; + SCsROW nPosY; + pViewData->GetPosFromPixel( rPos.X(), rPos.Y(), eWhich, nPosX, nPosY ); + + SCTAB nTab = pViewData->GetTabNo(); + ScDocShell* pDocSh = pViewData->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + ScBaseCell* pCell = NULL; + + sal_Bool bFound = lcl_GetHyperlinkCell( pDoc, nPosX, nPosY, nTab, pCell ); + if( !bFound ) + return sal_False; + + ScHideTextCursor aHideCursor( pViewData, eWhich ); // before GetEditArea (MapMode is changed) + + const ScPatternAttr* pPattern = pDoc->GetPattern( nPosX, nPosY, nTab ); + // bForceToTop = sal_False, use the cell's real position + Rectangle aEditRect = pViewData->GetEditArea( eWhich, nPosX, nPosY, this, pPattern, sal_False ); + if (rPos.Y() < aEditRect.Top()) + return sal_False; + + // vertikal kann (noch) nicht angeklickt werden: + + if (pPattern->GetCellOrientation() != SVX_ORIENTATION_STANDARD) + return sal_False; + + sal_Bool bBreak = ((SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK)).GetValue() || + ((SvxCellHorJustify)((const SvxHorJustifyItem&)pPattern-> + GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_BLOCK); + SvxCellHorJustify eHorJust = (SvxCellHorJustify)((SvxHorJustifyItem&)pPattern-> + GetItem(ATTR_HOR_JUSTIFY)).GetValue(); + + // EditEngine + + ScFieldEditEngine aEngine( pDoc->GetEditPool() ); + ScSizeDeviceProvider aProv(pDocSh); + aEngine.SetRefDevice( aProv.GetDevice() ); + aEngine.SetRefMapMode( MAP_100TH_MM ); + SfxItemSet aDefault( aEngine.GetEmptyItemSet() ); + pPattern->FillEditItemSet( &aDefault ); + SvxAdjust eSvxAdjust = SVX_ADJUST_LEFT; + switch (eHorJust) + { + case SVX_HOR_JUSTIFY_LEFT: + case SVX_HOR_JUSTIFY_REPEAT: // nicht implementiert + case SVX_HOR_JUSTIFY_STANDARD: // always Text if an EditCell type + eSvxAdjust = SVX_ADJUST_LEFT; + break; + case SVX_HOR_JUSTIFY_RIGHT: + eSvxAdjust = SVX_ADJUST_RIGHT; + break; + case SVX_HOR_JUSTIFY_CENTER: + eSvxAdjust = SVX_ADJUST_CENTER; + break; + case SVX_HOR_JUSTIFY_BLOCK: + eSvxAdjust = SVX_ADJUST_BLOCK; + break; + } + aDefault.Put( SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) ); + aEngine.SetDefaults( aDefault ); + if (bSpellErr) + aEngine.SetControlWord( aEngine.GetControlWord() | EE_CNTRL_ONLINESPELLING ); + + MapMode aEditMode = pViewData->GetLogicMode(eWhich); // ohne Drawing-Skalierung + Rectangle aLogicEdit = PixelToLogic( aEditRect, aEditMode ); + long nThisColLogic = aLogicEdit.Right() - aLogicEdit.Left() + 1; + Size aPaperSize = Size( 1000000, 1000000 ); + if(pCell->GetCellType() == CELLTYPE_FORMULA) + { + long nSizeX = 0; + long nSizeY = 0; + pViewData->GetMergeSizePixel( nPosX, nPosY, nSizeX, nSizeY ); + aPaperSize = Size(nSizeX, nSizeY ); + aPaperSize = PixelToLogic(aPaperSize); + } + + if (bBreak) + aPaperSize.Width() = nThisColLogic; + aEngine.SetPaperSize( aPaperSize ); + + ::std::auto_ptr< EditTextObject > pTextObj; + const EditTextObject* pData; + if(pCell->GetCellType() == CELLTYPE_EDIT) + { + ((ScEditCell*)pCell)->GetData(pData); + if (pData) + aEngine.SetText(*pData); + } + else // HyperLink Formula cell + { + pTextObj.reset((static_cast<ScFormulaCell*>(pCell))->CreateURLObject()); + if (pTextObj.get()) + aEngine.SetText(*pTextObj); + } + + long nStartX = aLogicEdit.Left(); + + long nTextWidth = aEngine.CalcTextWidth(); + long nTextHeight = aEngine.GetTextHeight(); + if ( nTextWidth < nThisColLogic ) + { + if (eHorJust == SVX_HOR_JUSTIFY_RIGHT) + nStartX += nThisColLogic - nTextWidth; + else if (eHorJust == SVX_HOR_JUSTIFY_CENTER) + nStartX += (nThisColLogic - nTextWidth) / 2; + } + + aLogicEdit.Left() = nStartX; + if (!bBreak) + aLogicEdit.Right() = nStartX + nTextWidth; + + // There is one glitch when dealing with a hyperlink cell and + // the cell content is NUMERIC. This defaults to right aligned and + // we need to adjust accordingly. + if(pCell->GetCellType() == CELLTYPE_FORMULA && + static_cast<ScFormulaCell*>(pCell)->IsValue() && + eHorJust == SVX_HOR_JUSTIFY_STANDARD) + { + aLogicEdit.Right() = aLogicEdit.Left() + nThisColLogic - 1; + aLogicEdit.Left() = aLogicEdit.Right() - nTextWidth; + } + aLogicEdit.Bottom() = aLogicEdit.Top() + nTextHeight; + + + Point aLogicClick = PixelToLogic(rPos,aEditMode); + if ( aLogicEdit.IsInside(aLogicClick) ) + { +// aEngine.SetUpdateMode(sal_False); + EditView aTempView( &aEngine, this ); + aTempView.SetOutputArea( aLogicEdit ); + + sal_Bool bRet = sal_False; + MapMode aOld = GetMapMode(); + SetMapMode(aEditMode); // kein return mehr + + if (bSpellErr) // Spelling-Fehler suchen + { + bRet = aTempView.IsWrongSpelledWordAtPos( rPos ); + if ( bRet ) + pViewData->GetView()->SetCursor( nPosX, nPosY ); // Cursor setzen + } + else // URL suchen + { + const SvxFieldItem* pFieldItem = aTempView.GetFieldUnderMousePointer(); + + if (pFieldItem) + { + const SvxFieldData* pField = pFieldItem->GetField(); + if ( pField && pField->ISA(SvxURLField) ) + { + if ( pName || pUrl || pTarget ) + { + const SvxURLField* pURLField = (const SvxURLField*)pField; + if (pName) + *pName = pURLField->GetRepresentation(); + if (pUrl) + *pUrl = pURLField->GetURL(); + if (pTarget) + *pTarget = pURLField->GetTargetFrame(); + } + bRet = sal_True; + } + } + } + + SetMapMode(aOld); + + // text cursor is restored in ScHideTextCursor dtor + + return bRet; + } + return sal_False; +} + +sal_Bool ScGridWindow::HasScenarioButton( const Point& rPosPixel, ScRange& rScenRange ) +{ + ScDocument* pDoc = pViewData->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + SCTAB nTabCount = pDoc->GetTableCount(); + if ( nTab+1<nTabCount && pDoc->IsScenario(nTab+1) && !pDoc->IsScenario(nTab) ) + { + sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); + + Size aButSize = pViewData->GetScenButSize(); + long nBWidth = aButSize.Width(); + if (!nBWidth) + return sal_False; // noch kein Button gezeichnet -> da ist auch keiner + long nBHeight = aButSize.Height(); + long nHSpace = (long)( SC_SCENARIO_HSPACE * pViewData->GetPPTX() ); + + //! Ranges an der Table cachen!!!! + + ScMarkData aMarks; + for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++) + pDoc->MarkScenario( i, nTab, aMarks, sal_False, SC_SCENARIO_SHOWFRAME ); + ScRangeList aRanges; + aMarks.FillRangeListWithMarks( &aRanges, sal_False ); + + + sal_uLong nRangeCount = aRanges.Count(); + for (sal_uLong j=0; j<nRangeCount; j++) + { + ScRange aRange = *aRanges.GetObject(j); + // Szenario-Rahmen immer dann auf zusammengefasste Zellen erweitern, wenn + // dadurch keine neuen nicht-ueberdeckten Zellen mit umrandet werden + pDoc->ExtendTotalMerge( aRange ); + + sal_Bool bTextBelow = ( aRange.aStart.Row() == 0 ); + + Point aButtonPos; + if ( bTextBelow ) + { + aButtonPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aEnd.Row()+1, + eWhich, sal_True ); + } + else + { + aButtonPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aStart.Row(), + eWhich, sal_True ); + aButtonPos.Y() -= nBHeight; + } + if ( bLayoutRTL ) + aButtonPos.X() -= nHSpace - 1; + else + aButtonPos.X() -= nBWidth - nHSpace; // same for top or bottom + + Rectangle aButRect( aButtonPos, Size(nBWidth,nBHeight) ); + if ( aButRect.IsInside( rPosPixel ) ) + { + rScenRange = aRange; + return sal_True; + } + } + } + + return sal_False; +} + +// #114409# +void ScGridWindow::DrawLayerCreated() +{ + SetMapMode( GetDrawMapMode() ); + + // initially create overlay objects + ImpCreateOverlayObjects(); +} + +// #114409# +void ScGridWindow::CursorChanged() +{ + // here the created OverlayObjects may be transformed in later versions. For + // now, just re-create them + + UpdateCursorOverlay(); +} + +// #114409# +void ScGridWindow::ImpCreateOverlayObjects() +{ + UpdateCursorOverlay(); + UpdateSelectionOverlay(); + UpdateAutoFillOverlay(); + UpdateDragRectOverlay(); + UpdateHeaderOverlay(); + UpdateShrinkOverlay(); +} + +// #114409# +void ScGridWindow::ImpDestroyOverlayObjects() +{ + DeleteCursorOverlay(); + DeleteSelectionOverlay(); + DeleteAutoFillOverlay(); + DeleteDragRectOverlay(); + DeleteHeaderOverlay(); + DeleteShrinkOverlay(); +} + +void ScGridWindow::UpdateAllOverlays() +{ + // delete and re-allocate all overlay objects + + ImpDestroyOverlayObjects(); + ImpCreateOverlayObjects(); +} + +void ScGridWindow::DeleteCursorOverlay() +{ + DELETEZ( mpOOCursors ); +} + +void ScGridWindow::UpdateCursorOverlay() +{ + MapMode aDrawMode = GetDrawMapMode(); + MapMode aOldMode = GetMapMode(); + if ( aOldMode != aDrawMode ) + SetMapMode( aDrawMode ); + + // Existing OverlayObjects may be transformed in later versions. + // For now, just re-create them. + + DeleteCursorOverlay(); + + std::vector<Rectangle> aPixelRects; + + // + // determine the cursor rectangles in pixels (moved from ScGridWindow::DrawCursor) + // + + SCTAB nTab = pViewData->GetTabNo(); + SCCOL nX = pViewData->GetCurX(); + SCROW nY = pViewData->GetCurY(); + + if (!maVisibleRange.isInside(nX, nY)) + return; + + // don't show the cursor in overlapped cells + + ScDocument* pDoc = pViewData->GetDocument(); + const ScPatternAttr* pPattern = pDoc->GetPattern(nX,nY,nTab); + const ScMergeFlagAttr& rMergeFlag = (const ScMergeFlagAttr&) pPattern->GetItem(ATTR_MERGE_FLAG); + sal_Bool bOverlapped = rMergeFlag.IsOverlapped(); + + // left or above of the screen? + + sal_Bool bVis = ( nX>=pViewData->GetPosX(eHWhich) && nY>=pViewData->GetPosY(eVWhich) ); + if (!bVis) + { + SCCOL nEndX = nX; + SCROW nEndY = nY; + const ScMergeAttr& rMerge = (const ScMergeAttr&) pPattern->GetItem(ATTR_MERGE); + if (rMerge.GetColMerge() > 1) + nEndX += rMerge.GetColMerge()-1; + if (rMerge.GetRowMerge() > 1) + nEndY += rMerge.GetRowMerge()-1; + bVis = ( nEndX>=pViewData->GetPosX(eHWhich) && nEndY>=pViewData->GetPosY(eVWhich) ); + } + + if ( bVis && !bOverlapped && !pViewData->HasEditView(eWhich) && pViewData->IsActive() ) + { + Point aScrPos = pViewData->GetScrPos( nX, nY, eWhich, sal_True ); + sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); + + // completely right of/below the screen? + // (test with logical start position in aScrPos) + sal_Bool bMaybeVisible; + if ( bLayoutRTL ) + bMaybeVisible = ( aScrPos.X() >= -2 && aScrPos.Y() >= -2 ); + else + { + Size aOutSize = GetOutputSizePixel(); + bMaybeVisible = ( aScrPos.X() <= aOutSize.Width() + 2 && aScrPos.Y() <= aOutSize.Height() + 2 ); + } + if ( bMaybeVisible ) + { + long nSizeXPix; + long nSizeYPix; + pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix ); + + if ( bLayoutRTL ) + aScrPos.X() -= nSizeXPix - 2; // move instead of mirroring + + sal_Bool bFix = ( pViewData->GetHSplitMode() == SC_SPLIT_FIX || + pViewData->GetVSplitMode() == SC_SPLIT_FIX ); + if ( pViewData->GetActivePart()==eWhich || bFix ) + { + aScrPos.X() -= 2; + aScrPos.Y() -= 2; + Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) ); + + aPixelRects.push_back(Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() )); + aPixelRects.push_back(Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() )); + aPixelRects.push_back(Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 )); + aPixelRects.push_back(Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() )); + } + else + { + Rectangle aRect( aScrPos, Size( nSizeXPix - 1, nSizeYPix - 1 ) ); + aPixelRects.push_back( aRect ); + } + } + } + + if ( aPixelRects.size() ) + { + // #i70788# get the OverlayManager safely + ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager(); + + if(pOverlayManager) + { + const Color aCursorColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor ); + std::vector< basegfx::B2DRange > aRanges; + const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation()); + + for(sal_uInt32 a(0); a < aPixelRects.size(); a++) + { + const Rectangle aRA(aPixelRects[a]); + basegfx::B2DRange aRB(aRA.Left(), aRA.Top(), aRA.Right() + 1, aRA.Bottom() + 1); + aRB.transform(aTransform); + aRanges.push_back(aRB); + } + + sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection( + sdr::overlay::OVERLAY_SOLID, + aCursorColor, + aRanges, + false); + + pOverlayManager->add(*pOverlay); + mpOOCursors = new ::sdr::overlay::OverlayObjectList; + mpOOCursors->append(*pOverlay); + } + } + + if ( aOldMode != aDrawMode ) + SetMapMode( aOldMode ); +} + +void ScGridWindow::DeleteSelectionOverlay() +{ + DELETEZ( mpOOSelection ); +} + +void ScGridWindow::UpdateSelectionOverlay() +{ + MapMode aDrawMode = GetDrawMapMode(); + MapMode aOldMode = GetMapMode(); + if ( aOldMode != aDrawMode ) + SetMapMode( aDrawMode ); + + DeleteSelectionOverlay(); + std::vector<Rectangle> aPixelRects; + GetSelectionRects( aPixelRects ); + + if ( aPixelRects.size() && pViewData->IsActive() ) + { + // #i70788# get the OverlayManager safely + ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager(); + + if(pOverlayManager) + { + std::vector< basegfx::B2DRange > aRanges; + const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation()); + + for(sal_uInt32 a(0); a < aPixelRects.size(); a++) + { + const Rectangle aRA(aPixelRects[a]); + basegfx::B2DRange aRB(aRA.Left() - 1, aRA.Top() - 1, aRA.Right(), aRA.Bottom()); + aRB.transform(aTransform); + aRanges.push_back(aRB); + } + + // #i97672# get the system's hilight color and limit it to the maximum + // allowed luminance. This is needed to react on too bright hilight colors + // which would otherwise vive a bad visualisation + Color aHighlight(GetSettings().GetStyleSettings().GetHighlightColor()); + const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer; + const basegfx::BColor aSelection(aHighlight.getBColor()); + const double fLuminance(aSelection.luminance()); + const double fMaxLum(aSvtOptionsDrawinglayer.GetSelectionMaximumLuminancePercent() / 100.0); + + if(fLuminance > fMaxLum) + { + const double fFactor(fMaxLum / fLuminance); + const basegfx::BColor aNewSelection( + aSelection.getRed() * fFactor, + aSelection.getGreen() * fFactor, + aSelection.getBlue() * fFactor); + + aHighlight = Color(aNewSelection); + } + + sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection( + sdr::overlay::OVERLAY_TRANSPARENT, + aHighlight, + aRanges, + true); + + pOverlayManager->add(*pOverlay); + mpOOSelection = new ::sdr::overlay::OverlayObjectList; + mpOOSelection->append(*pOverlay); + } + } + + if ( aOldMode != aDrawMode ) + SetMapMode( aOldMode ); +} + +void ScGridWindow::DeleteAutoFillOverlay() +{ + DELETEZ( mpOOAutoFill ); + mpAutoFillRect.reset(); +} + +void ScGridWindow::UpdateAutoFillOverlay() +{ + MapMode aDrawMode = GetDrawMapMode(); + MapMode aOldMode = GetMapMode(); + if ( aOldMode != aDrawMode ) + SetMapMode( aDrawMode ); + + DeleteAutoFillOverlay(); + + // + // get the AutoFill handle rectangle in pixels (moved from ScGridWindow::DrawAutoFillMark) + // + + if ( bAutoMarkVisible && aAutoMarkPos.Tab() == pViewData->GetTabNo() && + !pViewData->HasEditView(eWhich) && pViewData->IsActive() ) + { + SCCOL nX = aAutoMarkPos.Col(); + SCROW nY = aAutoMarkPos.Row(); + + if (!maVisibleRange.isInside(nX, nY)) + // Autofill mark is not visible. Bail out. + return; + + SCTAB nTab = pViewData->GetTabNo(); + ScDocument* pDoc = pViewData->GetDocument(); + sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); + + Point aFillPos = pViewData->GetScrPos( nX, nY, eWhich, sal_True ); + long nSizeXPix; + long nSizeYPix; + pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix ); + if ( bLayoutRTL ) + aFillPos.X() -= nSizeXPix + 3; + else + aFillPos.X() += nSizeXPix - 2; + + aFillPos.Y() += nSizeYPix; + aFillPos.Y() -= 2; + mpAutoFillRect.reset(new Rectangle(aFillPos, Size(6, 6))); + + // #i70788# get the OverlayManager safely + ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager(); + + if(pOverlayManager) + { + const Color aHandleColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor ); + std::vector< basegfx::B2DRange > aRanges; + const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation()); + basegfx::B2DRange aRB(mpAutoFillRect->Left(), mpAutoFillRect->Top(), mpAutoFillRect->Right() + 1, mpAutoFillRect->Bottom() + 1); + + aRB.transform(aTransform); + aRanges.push_back(aRB); + + sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection( + sdr::overlay::OVERLAY_SOLID, + aHandleColor, + aRanges, + false); + + pOverlayManager->add(*pOverlay); + mpOOAutoFill = new ::sdr::overlay::OverlayObjectList; + mpOOAutoFill->append(*pOverlay); + } + + if ( aOldMode != aDrawMode ) + SetMapMode( aOldMode ); + } +} + +void ScGridWindow::DeleteDragRectOverlay() +{ + DELETEZ( mpOODragRect ); +} + +void ScGridWindow::UpdateDragRectOverlay() +{ + MapMode aDrawMode = GetDrawMapMode(); + MapMode aOldMode = GetMapMode(); + if ( aOldMode != aDrawMode ) + SetMapMode( aDrawMode ); + + DeleteDragRectOverlay(); + + // + // get the rectangles in pixels (moved from DrawDragRect) + // + + if ( bDragRect || bPagebreakDrawn ) + { + std::vector<Rectangle> aPixelRects; + + SCCOL nX1 = bDragRect ? nDragStartX : aPagebreakDrag.aStart.Col(); + SCROW nY1 = bDragRect ? nDragStartY : aPagebreakDrag.aStart.Row(); + SCCOL nX2 = bDragRect ? nDragEndX : aPagebreakDrag.aEnd.Col(); + SCROW nY2 = bDragRect ? nDragEndY : aPagebreakDrag.aEnd.Row(); + + SCTAB nTab = pViewData->GetTabNo(); + + SCCOL nPosX = pViewData->GetPosX(WhichH(eWhich)); + SCROW nPosY = pViewData->GetPosY(WhichV(eWhich)); + if (nX1 < nPosX) nX1 = nPosX; + if (nX2 < nPosX) nX2 = nPosX; + if (nY1 < nPosY) nY1 = nPosY; + if (nY2 < nPosY) nY2 = nPosY; + + Point aScrPos( pViewData->GetScrPos( nX1, nY1, eWhich ) ); + + long nSizeXPix=0; + long nSizeYPix=0; + ScDocument* pDoc = pViewData->GetDocument(); + double nPPTX = pViewData->GetPPTX(); + double nPPTY = pViewData->GetPPTY(); + SCCOLROW i; + + sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); + long nLayoutSign = bLayoutRTL ? -1 : 1; + + if (ValidCol(nX2) && nX2>=nX1) + for (i=nX1; i<=nX2; i++) + nSizeXPix += ScViewData::ToPixel( pDoc->GetColWidth( static_cast<SCCOL>(i), nTab ), nPPTX ); + else + { + aScrPos.X() -= nLayoutSign; + nSizeXPix += 2; + } + + if (ValidRow(nY2) && nY2>=nY1) + for (i=nY1; i<=nY2; i++) + nSizeYPix += ScViewData::ToPixel( pDoc->GetRowHeight( i, nTab ), nPPTY ); + else + { + aScrPos.Y() -= 1; + nSizeYPix += 2; + } + + aScrPos.X() -= 2 * nLayoutSign; + aScrPos.Y() -= 2; +// Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) ); + Rectangle aRect( aScrPos.X(), aScrPos.Y(), + aScrPos.X() + ( nSizeXPix + 2 ) * nLayoutSign, aScrPos.Y() + nSizeYPix + 2 ); + if ( bLayoutRTL ) + { + aRect.Left() = aRect.Right(); // end position is left + aRect.Right() = aScrPos.X(); + } + + if ( meDragInsertMode == INS_CELLSDOWN ) + { + aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Top()+3, aRect.Left()+1, aRect.Bottom()-2 ) ); + aPixelRects.push_back( Rectangle( aRect.Right()-1, aRect.Top()+3, aRect.Right()-1, aRect.Bottom()-2 ) ); + aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Top(), aRect.Right()-1, aRect.Top()+2 ) ); + aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Bottom()-1, aRect.Right()-1, aRect.Bottom()-1 ) ); + } + else if ( meDragInsertMode == INS_CELLSRIGHT ) + { + aPixelRects.push_back( Rectangle( aRect.Left(), aRect.Top()+1, aRect.Left()+2, aRect.Bottom()-1 ) ); + aPixelRects.push_back( Rectangle( aRect.Right()-1, aRect.Top()+1, aRect.Right()-1, aRect.Bottom()-1 ) ); + aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Top()+1, aRect.Right()-2, aRect.Top()+1 ) ); + aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Bottom()-1, aRect.Right()-2, aRect.Bottom()-1 ) ); + } + else + { + aPixelRects.push_back( Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() ) ); + aPixelRects.push_back( Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() ) ); + aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 ) ); + aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() ) ); + } + + // #i70788# get the OverlayManager safely + ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager(); + + if(pOverlayManager) + { + // Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor(); + std::vector< basegfx::B2DRange > aRanges; + const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation()); + + for(sal_uInt32 a(0); a < aPixelRects.size(); a++) + { + const Rectangle aRA(aPixelRects[a]); + basegfx::B2DRange aRB(aRA.Left(), aRA.Top(), aRA.Right() + 1, aRA.Bottom() + 1); + aRB.transform(aTransform); + aRanges.push_back(aRB); + } + + sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection( + sdr::overlay::OVERLAY_INVERT, + Color(COL_BLACK), + aRanges, + false); + + pOverlayManager->add(*pOverlay); + mpOODragRect = new ::sdr::overlay::OverlayObjectList; + mpOODragRect->append(*pOverlay); + } + } + + if ( aOldMode != aDrawMode ) + SetMapMode( aOldMode ); +} + +void ScGridWindow::DeleteHeaderOverlay() +{ + DELETEZ( mpOOHeader ); +} + +void ScGridWindow::UpdateHeaderOverlay() +{ + MapMode aDrawMode = GetDrawMapMode(); + MapMode aOldMode = GetMapMode(); + if ( aOldMode != aDrawMode ) + SetMapMode( aDrawMode ); + + DeleteHeaderOverlay(); + + // Pixel rectangle is in aInvertRect + if ( !aInvertRect.IsEmpty() ) + { + // #i70788# get the OverlayManager safely + ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager(); + + if(pOverlayManager) + { + // Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor(); + std::vector< basegfx::B2DRange > aRanges; + const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation()); + basegfx::B2DRange aRB(aInvertRect.Left(), aInvertRect.Top(), aInvertRect.Right() + 1, aInvertRect.Bottom() + 1); + + aRB.transform(aTransform); + aRanges.push_back(aRB); + + sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection( + sdr::overlay::OVERLAY_INVERT, + Color(COL_BLACK), + aRanges, + false); + + pOverlayManager->add(*pOverlay); + mpOOHeader = new ::sdr::overlay::OverlayObjectList; + mpOOHeader->append(*pOverlay); + } + } + + if ( aOldMode != aDrawMode ) + SetMapMode( aOldMode ); +} + +void ScGridWindow::DeleteShrinkOverlay() +{ + DELETEZ( mpOOShrink ); +} + +void ScGridWindow::UpdateShrinkOverlay() +{ + MapMode aDrawMode = GetDrawMapMode(); + MapMode aOldMode = GetMapMode(); + if ( aOldMode != aDrawMode ) + SetMapMode( aDrawMode ); + + DeleteShrinkOverlay(); + + // + // get the rectangle in pixels + // + + Rectangle aPixRect; + ScRange aRange; + SCTAB nTab = pViewData->GetTabNo(); + if ( pViewData->IsRefMode() && nTab >= pViewData->GetRefStartZ() && nTab <= pViewData->GetRefEndZ() && + pViewData->GetDelMark( aRange ) ) + { + //! limit to visible area + if ( aRange.aStart.Col() <= aRange.aEnd.Col() && + aRange.aStart.Row() <= aRange.aEnd.Row() ) + { + Point aStart = pViewData->GetScrPos( aRange.aStart.Col(), + aRange.aStart.Row(), eWhich ); + Point aEnd = pViewData->GetScrPos( aRange.aEnd.Col()+1, + aRange.aEnd.Row()+1, eWhich ); + aEnd.X() -= 1; + aEnd.Y() -= 1; + + aPixRect = Rectangle( aStart,aEnd ); + } + } + + if ( !aPixRect.IsEmpty() ) + { + // #i70788# get the OverlayManager safely + ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager(); + + if(pOverlayManager) + { + // Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor(); + std::vector< basegfx::B2DRange > aRanges; + const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation()); + basegfx::B2DRange aRB(aPixRect.Left(), aPixRect.Top(), aPixRect.Right() + 1, aPixRect.Bottom() + 1); + + aRB.transform(aTransform); + aRanges.push_back(aRB); + + sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection( + sdr::overlay::OVERLAY_INVERT, + Color(COL_BLACK), + aRanges, + false); + + pOverlayManager->add(*pOverlay); + mpOOShrink = new ::sdr::overlay::OverlayObjectList; + mpOOShrink->append(*pOverlay); + } + } + + if ( aOldMode != aDrawMode ) + SetMapMode( aOldMode ); +} + +// #i70788# central method to get the OverlayManager safely +::sdr::overlay::OverlayManager* ScGridWindow::getOverlayManager() +{ + SdrPageView* pPV = pViewData->GetView()->GetScDrawView()->GetSdrPageView(); + + if(pPV) + { + SdrPageWindow* pPageWin = pPV->FindPageWindow( *this ); + + if ( pPageWin ) + { + return (pPageWin->GetOverlayManager()); + } + } + + return 0L; +} + +void ScGridWindow::flushOverlayManager() +{ + // #i70788# get the OverlayManager safely + ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager(); + + if(pOverlayManager) + { + pOverlayManager->flush(); + } +} + +// --------------------------------------------------------------------------- +// eof diff --git a/sc/source/ui/view/gridwin2.cxx b/sc/source/ui/view/gridwin2.cxx new file mode 100644 index 000000000000..4a3689653ab6 --- /dev/null +++ b/sc/source/ui/view/gridwin2.cxx @@ -0,0 +1,1061 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include "scitems.hxx" +#include <vcl/msgbox.hxx> +#include <vcl/sound.hxx> + +#include "gridwin.hxx" +#include "tabvwsh.hxx" +#include "docsh.hxx" +#include "viewdata.hxx" +#include "pivot.hxx" +//CHINA001 #include "pfiltdlg.hxx" +#include "uiitems.hxx" +#include "scresid.hxx" +#include "sc.hrc" +#include "globstr.hrc" +#include "pagedata.hxx" +#include "dpobject.hxx" +#include "dpsave.hxx" +#include "dpoutput.hxx" // ScDPPositionData +#include "dpshttab.hxx" +#include "dbdocfun.hxx" +#include "dpcontrol.hxx" +#include "dpcontrol.hrc" +#include "strload.hxx" +#include "userlist.hxx" + +#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp> +#include "scabstdlg.hxx" //CHINA001 + +#include <vector> +#include <hash_map> + +using namespace com::sun::star; +using ::com::sun::star::sheet::DataPilotFieldOrientation; +using ::std::vector; +using ::std::auto_ptr; +using ::std::hash_map; +using ::rtl::OUString; +using ::rtl::OUStringHash; + +// STATIC DATA ----------------------------------------------------------- + +// ----------------------------------------------------------------------- + +DataPilotFieldOrientation ScGridWindow::GetDPFieldOrientation( SCCOL nCol, SCROW nRow ) const +{ + using namespace ::com::sun::star::sheet; + + ScDocument* pDoc = pViewData->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + ScDPObject* pDPObj = pDoc->GetDPAtCursor(nCol, nRow, nTab); + if (!pDPObj) + return DataPilotFieldOrientation_HIDDEN; + + sal_uInt16 nOrient = DataPilotFieldOrientation_HIDDEN; + + // Check for page field first. + if (nCol > 0) + { + // look for the dimension header left of the drop-down arrow + long nField = pDPObj->GetHeaderDim( ScAddress( nCol-1, nRow, nTab ), nOrient ); + if ( nField >= 0 && nOrient == DataPilotFieldOrientation_PAGE ) + { + sal_Bool bIsDataLayout = sal_False; + String aFieldName = pDPObj->GetDimName( nField, bIsDataLayout ); + if ( aFieldName.Len() && !bIsDataLayout ) + return DataPilotFieldOrientation_PAGE; + } + } + + nOrient = sheet::DataPilotFieldOrientation_HIDDEN; + + // Now, check for row/column field. + long nField = pDPObj->GetHeaderDim(ScAddress(nCol, nRow, nTab), nOrient); + if (nField >= 0 && (nOrient == DataPilotFieldOrientation_COLUMN || nOrient == DataPilotFieldOrientation_ROW) ) + { + sal_Bool bIsDataLayout = sal_False; + String aFieldName = pDPObj->GetDimName(nField, bIsDataLayout); + if (aFieldName.Len() && !bIsDataLayout) + return static_cast<DataPilotFieldOrientation>(nOrient); + } + + return DataPilotFieldOrientation_HIDDEN; +} + +// private method for mouse button handling +sal_Bool ScGridWindow::DoPageFieldSelection( SCCOL nCol, SCROW nRow ) +{ + if (GetDPFieldOrientation( nCol, nRow ) == sheet::DataPilotFieldOrientation_PAGE) + { + LaunchPageFieldMenu( nCol, nRow ); + return sal_True; + } + return sal_False; +} + +bool ScGridWindow::DoAutoFilterButton( SCCOL nCol, SCROW nRow, const MouseEvent& rMEvt ) +{ + ScDocument* pDoc = pViewData->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + Point aScrPos = pViewData->GetScrPos(nCol, nRow, eWhich); + Point aDiffPix = rMEvt.GetPosPixel(); + + aDiffPix -= aScrPos; + sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); + if ( bLayoutRTL ) + aDiffPix.X() = -aDiffPix.X(); + + long nSizeX, nSizeY; + pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY ); + Size aScrSize(nSizeX-1, nSizeY-1); + + // Check if the mouse cursor is clicking on the popup arrow box. + mpFilterButton.reset(new ScDPFieldButton(this, &GetSettings().GetStyleSettings(), &pViewData->GetZoomX(), &pViewData->GetZoomY(), pDoc)); + mpFilterButton->setBoundingBox(aScrPos, aScrSize, bLayoutRTL); + mpFilterButton->setPopupLeft(bLayoutRTL); // #i114944# AutoFilter button is left-aligned in RTL + Point aPopupPos; + Size aPopupSize; + mpFilterButton->getPopupBoundingBox(aPopupPos, aPopupSize); + Rectangle aRec(aPopupPos, aPopupSize); + if (aRec.IsInside(rMEvt.GetPosPixel())) + { + if ( DoPageFieldSelection( nCol, nRow ) ) + return true; + + bool bFilterActive = IsAutoFilterActive(nCol, nRow, nTab); + mpFilterButton->setHasHiddenMember(bFilterActive); + mpFilterButton->setDrawBaseButton(false); + mpFilterButton->setDrawPopupButton(true); + mpFilterButton->setPopupPressed(true); + HideCursor(); + mpFilterButton->draw(); + ShowCursor(); + DoAutoFilterMenue(nCol, nRow, false); + return true; + } + + return false; +} + +void ScGridWindow::DoPushButton( SCCOL nCol, SCROW nRow, const MouseEvent& rMEvt ) +{ + ScDocument* pDoc = pViewData->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + + ScDPObject* pDPObj = pDoc->GetDPAtCursor(nCol, nRow, nTab); + + if (pDPObj) + { + sal_uInt16 nOrient = sheet::DataPilotFieldOrientation_HIDDEN; + ScAddress aPos( nCol, nRow, nTab ); + long nField = pDPObj->GetHeaderDim( aPos, nOrient ); + if ( nField >= 0 ) + { + bDPMouse = sal_True; + nDPField = nField; + pDragDPObj = pDPObj; + + if (DPTestFieldPopupArrow(rMEvt, aPos, pDPObj)) + { + // field name pop up menu has been launched. Don't activate + // field move. + bDPMouse = false; + return; + } + + DPTestMouse( rMEvt, sal_True ); + StartTracking(); + } + else if ( pDPObj->IsFilterButton(aPos) ) + { + ReleaseMouse(); // may have been captured in ButtonDown + + ScQueryParam aQueryParam; + SCTAB nSrcTab = 0; + const ScSheetSourceDesc* pDesc = pDPObj->GetSheetDesc(); + DBG_ASSERT(pDesc, "no sheet source for filter button"); + if (pDesc) + { + aQueryParam = pDesc->aQueryParam; + nSrcTab = pDesc->aSourceRange.aStart.Tab(); + } + + SfxItemSet aArgSet( pViewData->GetViewShell()->GetPool(), + SCITEM_QUERYDATA, SCITEM_QUERYDATA ); + aArgSet.Put( ScQueryItem( SCITEM_QUERYDATA, pViewData, &aQueryParam ) ); + +//CHINA001 ScPivotFilterDlg* pDlg = new ScPivotFilterDlg( +//CHINA001 pViewData->GetViewShell()->GetDialogParent(), +//CHINA001 aArgSet, nSrcTab ); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + AbstractScPivotFilterDlg* pDlg = pFact->CreateScPivotFilterDlg( pViewData->GetViewShell()->GetDialogParent(), + aArgSet, nSrcTab, + RID_SCDLG_PIVOTFILTER); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + if ( pDlg->Execute() == RET_OK ) + { + ScSheetSourceDesc aNewDesc; + if (pDesc) + aNewDesc = *pDesc; + + const ScQueryItem& rQueryItem = pDlg->GetOutputItem(); + aNewDesc.aQueryParam = rQueryItem.GetQueryData(); + + ScDPObject aNewObj( *pDPObj ); + aNewObj.SetSheetDesc( aNewDesc ); + ScDBDocFunc aFunc( *pViewData->GetDocShell() ); + aFunc.DataPilotUpdate( pDPObj, &aNewObj, sal_True, sal_False ); + pViewData->GetView()->CursorPosChanged(); // shells may be switched + } + delete pDlg; + } + else + Sound::Beep(); + } + else + { + DBG_ERROR("Da is ja garnix"); + } +} + +// ----------------------------------------------------------------------- +// +// Data Pilot interaction +// + +void ScGridWindow::DPTestMouse( const MouseEvent& rMEvt, sal_Bool bMove ) +{ + DBG_ASSERT(pDragDPObj, "pDragDPObj missing"); + + // scroll window if at edges + //! move this to separate method + + sal_Bool bTimer = sal_False; + Point aPixel = rMEvt.GetPosPixel(); + + SCsCOL nDx = 0; + SCsROW nDy = 0; + if ( aPixel.X() < 0 ) + nDx = -1; + if ( aPixel.Y() < 0 ) + nDy = -1; + Size aSize = GetOutputSizePixel(); + if ( aPixel.X() >= aSize.Width() ) + nDx = 1; + if ( aPixel.Y() >= aSize.Height() ) + nDy = 1; + if ( nDx != 0 || nDy != 0 ) + { + UpdateDragRect( sal_False, Rectangle() ); + + if ( nDx != 0) + pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) ); + if ( nDy != 0 ) + pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) ); + + bTimer = sal_True; + } + + // --- + + SCsCOL nPosX; + SCsROW nPosY; + pViewData->GetPosFromPixel( aPixel.X(), aPixel.Y(), eWhich, nPosX, nPosY ); + sal_Bool bMouseLeft; + sal_Bool bMouseTop; + pViewData->GetMouseQuadrant( aPixel, eWhich, nPosX, nPosY, bMouseLeft, bMouseTop ); + + ScAddress aPos( nPosX, nPosY, pViewData->GetTabNo() ); + + Rectangle aPosRect; + sal_uInt16 nOrient; + long nDimPos; + sal_Bool bHasRange = pDragDPObj->GetHeaderDrag( aPos, bMouseLeft, bMouseTop, nDPField, + aPosRect, nOrient, nDimPos ); + UpdateDragRect( bHasRange && bMove, aPosRect ); + + sal_Bool bIsDataLayout; + sal_Int32 nDimFlags = 0; + String aDimName = pDragDPObj->GetDimName( nDPField, bIsDataLayout, &nDimFlags ); + bool bAllowed = !bHasRange || ScDPObject::IsOrientationAllowed( nOrient, nDimFlags ); + + if (bMove) // set mouse pointer + { + PointerStyle ePointer = POINTER_PIVOT_DELETE; + if ( !bAllowed ) + ePointer = POINTER_NOTALLOWED; + else if ( bHasRange ) + switch (nOrient) + { + case sheet::DataPilotFieldOrientation_COLUMN: ePointer = POINTER_PIVOT_COL; break; + case sheet::DataPilotFieldOrientation_ROW: ePointer = POINTER_PIVOT_ROW; break; + case sheet::DataPilotFieldOrientation_PAGE: + case sheet::DataPilotFieldOrientation_DATA: ePointer = POINTER_PIVOT_FIELD; break; + } + SetPointer( ePointer ); + } + else // execute change + { + if (!bHasRange) + nOrient = sheet::DataPilotFieldOrientation_HIDDEN; + + if ( bIsDataLayout && ( nOrient != sheet::DataPilotFieldOrientation_COLUMN && + nOrient != sheet::DataPilotFieldOrientation_ROW ) ) + { + // removing data layout is not allowed + pViewData->GetView()->ErrorMessage(STR_PIVOT_MOVENOTALLOWED); + } + else if ( bAllowed ) + { + ScDPSaveData aSaveData( *pDragDPObj->GetSaveData() ); + + ScDPSaveDimension* pDim; + if ( bIsDataLayout ) + pDim = aSaveData.GetDataLayoutDimension(); + else + pDim = aSaveData.GetDimensionByName(aDimName); + pDim->SetOrientation( nOrient ); + aSaveData.SetPosition( pDim, nDimPos ); + + //! docfunc method with ScDPSaveData as argument? + + ScDPObject aNewObj( *pDragDPObj ); + aNewObj.SetSaveData( aSaveData ); + ScDBDocFunc aFunc( *pViewData->GetDocShell() ); + // when dragging fields, allow re-positioning (bAllowMove) + aFunc.DataPilotUpdate( pDragDPObj, &aNewObj, sal_True, sal_False, sal_True ); + pViewData->GetView()->CursorPosChanged(); // shells may be switched + } + } + + if (bTimer && bMove) + pViewData->GetView()->SetTimer( this, rMEvt ); // repeat event + else + pViewData->GetView()->ResetTimer(); +} + +bool ScGridWindow::DPTestFieldPopupArrow(const MouseEvent& rMEvt, const ScAddress& rPos, ScDPObject* pDPObj) +{ + sal_Bool bLayoutRTL = pViewData->GetDocument()->IsLayoutRTL( pViewData->GetTabNo() ); + + // Get the geometry of the cell. + Point aScrPos = pViewData->GetScrPos(rPos.Col(), rPos.Row(), eWhich); + long nSizeX, nSizeY; + pViewData->GetMergeSizePixel(rPos.Col(), rPos.Row(), nSizeX, nSizeY); + Size aScrSize(nSizeX-1, nSizeY-1); + + // Check if the mouse cursor is clicking on the popup arrow box. + ScDPFieldButton aBtn(this, &GetSettings().GetStyleSettings()); + aBtn.setBoundingBox(aScrPos, aScrSize, bLayoutRTL); + aBtn.setPopupLeft(false); // DataPilot popup is always right-aligned for now + Point aPopupPos; + Size aPopupSize; + aBtn.getPopupBoundingBox(aPopupPos, aPopupSize); + Rectangle aRec(aPopupPos, aPopupSize); + if (aRec.IsInside(rMEvt.GetPosPixel())) + { + // Mouse cursor inside the popup arrow box. Launch the field menu. + DPLaunchFieldPopupMenu(OutputToScreenPixel(aScrPos), aScrSize, rPos, pDPObj); + return true; + } + + return false; +} + +namespace { + +struct DPFieldPopupData : public ScDPFieldPopupWindow::ExtendedData +{ + ScPivotParam maDPParam; + ScDPObject* mpDPObj; + long mnDim; +}; + +class DPFieldPopupOKAction : public ScMenuFloatingWindow::Action +{ +public: + explicit DPFieldPopupOKAction(ScGridWindow* p) : + mpGridWindow(p) {} + + virtual void execute() + { + mpGridWindow->UpdateDPFromFieldPopupMenu(); + } +private: + ScGridWindow* mpGridWindow; +}; + +class PopupSortAction : public ScMenuFloatingWindow::Action +{ +public: + enum SortType { ASCENDING, DESCENDING, CUSTOM }; + + explicit PopupSortAction(const ScAddress& rPos, SortType eType, sal_uInt16 nUserListIndex, ScTabViewShell* pViewShell) : + maPos(rPos), meType(eType), mnUserListIndex(nUserListIndex), mpViewShell(pViewShell) {} + + virtual void execute() + { + switch (meType) + { + case ASCENDING: + mpViewShell->DataPilotSort(maPos, true); + break; + case DESCENDING: + mpViewShell->DataPilotSort(maPos, false); + break; + case CUSTOM: + mpViewShell->DataPilotSort(maPos, true, &mnUserListIndex); + break; + default: + ; + } + } + +private: + ScAddress maPos; + SortType meType; + sal_uInt16 mnUserListIndex; + ScTabViewShell* mpViewShell; +}; + +} + +void ScGridWindow::DPLaunchFieldPopupMenu( + const Point& rScrPos, const Size& rScrSize, const ScAddress& rPos, ScDPObject* pDPObj) +{ + // We need to get the list of field members. + auto_ptr<DPFieldPopupData> pDPData(new DPFieldPopupData); + pDPObj->FillLabelData(pDPData->maDPParam); + pDPData->mpDPObj = pDPObj; + + sal_uInt16 nOrient; + pDPData->mnDim = pDPObj->GetHeaderDim(rPos, nOrient); + + if (pDPData->maDPParam.maLabelArray.size() <= static_cast<size_t>(pDPData->mnDim)) + // out-of-bound dimension ID. This should never happen! + return; + + const ScDPLabelData& rLabelData = *pDPData->maDPParam.maLabelArray[pDPData->mnDim]; + + mpDPFieldPopup.reset(new ScDPFieldPopupWindow(this, pViewData->GetDocument())); + mpDPFieldPopup->setName(OUString::createFromAscii("DataPilot field member popup")); + mpDPFieldPopup->setExtendedData(pDPData.release()); + mpDPFieldPopup->setOKAction(new DPFieldPopupOKAction(this)); + { + // Populate field members. + size_t n = rLabelData.maMembers.size(); + mpDPFieldPopup->setMemberSize(n); + for (size_t i = 0; i < n; ++i) + { + const ScDPLabelData::Member& rMem = rLabelData.maMembers[i]; + mpDPFieldPopup->addMember(rMem.getDisplayName(), rMem.mbVisible); + } + mpDPFieldPopup->initMembers(); + } + + vector<OUString> aUserSortNames; + ScUserList* pUserList = ScGlobal::GetUserList(); + if (pUserList) + { + sal_uInt16 n = pUserList->GetCount(); + aUserSortNames.reserve(n); + for (sal_uInt16 i = 0; i < n; ++i) + { + ScUserListData* pData = static_cast<ScUserListData*>((*pUserList)[i]); + aUserSortNames.push_back(pData->GetString()); + } + } + + // Populate the menus. + ScTabViewShell* pViewShell = pViewData->GetViewShell(); + mpDPFieldPopup->addMenuItem( + ScRscStrLoader(RID_POPUP_FILTER, STR_MENU_SORT_ASC).GetString(), true, + new PopupSortAction(rPos, PopupSortAction::ASCENDING, 0, pViewShell)); + mpDPFieldPopup->addMenuItem( + ScRscStrLoader(RID_POPUP_FILTER, STR_MENU_SORT_DESC).GetString(), true, + new PopupSortAction(rPos, PopupSortAction::DESCENDING, 0, pViewShell)); + ScMenuFloatingWindow* pSubMenu = mpDPFieldPopup->addSubMenuItem( + ScRscStrLoader(RID_POPUP_FILTER, STR_MENU_SORT_CUSTOM).GetString(), !aUserSortNames.empty()); + + if (pSubMenu && !aUserSortNames.empty()) + { + size_t n = aUserSortNames.size(); + for (size_t i = 0; i < n; ++i) + { + pSubMenu->addMenuItem( + aUserSortNames[i], true, + new PopupSortAction(rPos, PopupSortAction::CUSTOM, static_cast<sal_uInt16>(i), pViewShell)); + } + } + + sal_Bool bLayoutRTL = pViewData->GetDocument()->IsLayoutRTL( pViewData->GetTabNo() ); + + Rectangle aCellRect(rScrPos, rScrSize); + const Size& rPopupSize = mpDPFieldPopup->getWindowSize(); + if (bLayoutRTL) + { + // RTL: rScrPos is logical-left (visual right) position, always right-align with that + aCellRect.SetPos(Point(rScrPos.X() - rPopupSize.Width() + 1, rScrPos.Y())); + } + else if (rScrSize.getWidth() > rPopupSize.getWidth()) + { + // If the cell width is larger than the popup window width, launch it + // right-aligned with the cell. + long nXOffset = rScrSize.getWidth() - rPopupSize.getWidth(); + aCellRect.SetPos(Point(rScrPos.X() + nXOffset, rScrPos.Y())); + } + mpDPFieldPopup->SetPopupModeEndHdl( LINK(this, ScGridWindow, PopupModeEndHdl) ); + mpDPFieldPopup->StartPopupMode(aCellRect, (FLOATWIN_POPUPMODE_DOWN | FLOATWIN_POPUPMODE_GRABFOCUS)); +} + +void ScGridWindow::UpdateDPFromFieldPopupMenu() +{ + typedef hash_map<OUString, OUString, OUStringHash> MemNameMapType; + typedef hash_map<OUString, bool, OUStringHash> MemVisibilityType; + + if (!mpDPFieldPopup.get()) + return; + + DPFieldPopupData* pDPData = static_cast<DPFieldPopupData*>(mpDPFieldPopup->getExtendedData()); + if (!pDPData) + return; + + ScDPObject* pDPObj = pDPData->mpDPObj; + ScDPObject aNewDPObj(*pDPObj); + aNewDPObj.BuildAllDimensionMembers(); + ScDPSaveData* pSaveData = aNewDPObj.GetSaveData(); + + sal_Bool bIsDataLayout; + String aDimName = pDPObj->GetDimName(pDPData->mnDim, bIsDataLayout); + ScDPSaveDimension* pDim = pSaveData->GetDimensionByName(aDimName); + if (!pDim) + return; + + // Build a map of layout names to original names. + const ScDPLabelData& rLabelData = *pDPData->maDPParam.maLabelArray[pDPData->mnDim]; + MemNameMapType aMemNameMap; + for (vector<ScDPLabelData::Member>::const_iterator itr = rLabelData.maMembers.begin(), itrEnd = rLabelData.maMembers.end(); + itr != itrEnd; ++itr) + aMemNameMap.insert(MemNameMapType::value_type(itr->maLayoutName, itr->maName)); + + // The raw result may contain a mixture of layout names and original names. + MemVisibilityType aRawResult; + mpDPFieldPopup->getResult(aRawResult); + + MemVisibilityType aResult; + for (MemVisibilityType::const_iterator itr = aRawResult.begin(), itrEnd = aRawResult.end(); itr != itrEnd; ++itr) + { + MemNameMapType::const_iterator itrNameMap = aMemNameMap.find(itr->first); + if (itrNameMap == aMemNameMap.end()) + // This is an original member name. Use it as-is. + aResult.insert(MemVisibilityType::value_type(itr->first, itr->second)); + else + { + // This is a layout name. Get the original member name and use it. + aResult.insert(MemVisibilityType::value_type(itrNameMap->second, itr->second)); + } + } + pDim->UpdateMemberVisibility(aResult); + + ScDBDocFunc aFunc(*pViewData->GetDocShell()); + aFunc.DataPilotUpdate(pDPObj, &aNewDPObj, true, false); +} + +void ScGridWindow::DPMouseMove( const MouseEvent& rMEvt ) +{ + DPTestMouse( rMEvt, sal_True ); +} + +void ScGridWindow::DPMouseButtonUp( const MouseEvent& rMEvt ) +{ + bDPMouse = sal_False; + ReleaseMouse(); + + DPTestMouse( rMEvt, sal_False ); + SetPointer( Pointer( POINTER_ARROW ) ); +} + +// ----------------------------------------------------------------------- + +void ScGridWindow::UpdateDragRect( sal_Bool bShowRange, const Rectangle& rPosRect ) +{ + SCCOL nStartX = ( rPosRect.Left() >= 0 ) ? static_cast<SCCOL>(rPosRect.Left()) : SCCOL_MAX; + SCROW nStartY = ( rPosRect.Top() >= 0 ) ? static_cast<SCROW>(rPosRect.Top()) : SCROW_MAX; + SCCOL nEndX = ( rPosRect.Right() >= 0 ) ? static_cast<SCCOL>(rPosRect.Right()) : SCCOL_MAX; + SCROW nEndY = ( rPosRect.Bottom() >= 0 ) ? static_cast<SCROW>(rPosRect.Bottom()) : SCROW_MAX; + + if ( bShowRange == bDragRect && nDragStartX == nStartX && nDragEndX == nEndX && + nDragStartY == nStartY && nDragEndY == nEndY ) + { + return; // everything unchanged + } + + // if ( bDragRect ) + // DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, sal_False ); + if ( bShowRange ) + { + nDragStartX = nStartX; + nDragStartY = nStartY; + nDragEndX = nEndX; + nDragEndY = nEndY; + bDragRect = sal_True; + // DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, sal_False ); + } + else + bDragRect = sal_False; + + UpdateDragRectOverlay(); +} + +// ----------------------------------------------------------------------- + +// Page-Break-Modus + +sal_uInt16 ScGridWindow::HitPageBreak( const Point& rMouse, ScRange* pSource, + SCCOLROW* pBreak, SCCOLROW* pPrev ) +{ + sal_uInt16 nFound = SC_PD_NONE; // 0 + ScRange aSource; + SCCOLROW nBreak = 0; + SCCOLROW nPrev = 0; + + ScPageBreakData* pPageData = pViewData->GetView()->GetPageBreakData(); + if ( pPageData ) + { + sal_Bool bHori = sal_False; + sal_Bool bVert = sal_False; + SCCOL nHitX = 0; + SCROW nHitY = 0; + + long nMouseX = rMouse.X(); + long nMouseY = rMouse.Y(); + SCsCOL nPosX; + SCsROW nPosY; + pViewData->GetPosFromPixel( nMouseX, nMouseY, eWhich, nPosX, nPosY ); + Point aTL = pViewData->GetScrPos( nPosX, nPosY, eWhich ); + Point aBR = pViewData->GetScrPos( nPosX+1, nPosY+1, eWhich ); + + // Horizontal mehr Toleranz als vertikal, weil mehr Platz ist + if ( nMouseX <= aTL.X() + 4 ) + { + bHori = sal_True; + nHitX = nPosX; + } + else if ( nMouseX >= aBR.X() - 6 ) + { + bHori = sal_True; + nHitX = nPosX+1; // linker Rand der naechsten Zelle + } + if ( nMouseY <= aTL.Y() + 2 ) + { + bVert = sal_True; + nHitY = nPosY; + } + else if ( nMouseY >= aBR.Y() - 4 ) + { + bVert = sal_True; + nHitY = nPosY+1; // oberer Rand der naechsten Zelle + } + + if ( bHori || bVert ) + { + sal_uInt16 nCount = sal::static_int_cast<sal_uInt16>( pPageData->GetCount() ); + for (sal_uInt16 nPos=0; nPos<nCount && !nFound; nPos++) + { + ScPrintRangeData& rData = pPageData->GetData(nPos); + ScRange aRange = rData.GetPrintRange(); + sal_Bool bLHit = ( bHori && nHitX == aRange.aStart.Col() ); + sal_Bool bRHit = ( bHori && nHitX == aRange.aEnd.Col() + 1 ); + sal_Bool bTHit = ( bVert && nHitY == aRange.aStart.Row() ); + sal_Bool bBHit = ( bVert && nHitY == aRange.aEnd.Row() + 1 ); + sal_Bool bInsideH = ( nPosX >= aRange.aStart.Col() && nPosX <= aRange.aEnd.Col() ); + sal_Bool bInsideV = ( nPosY >= aRange.aStart.Row() && nPosY <= aRange.aEnd.Row() ); + + if ( bLHit ) + { + if ( bTHit ) + nFound = SC_PD_RANGE_TL; + else if ( bBHit ) + nFound = SC_PD_RANGE_BL; + else if ( bInsideV ) + nFound = SC_PD_RANGE_L; + } + else if ( bRHit ) + { + if ( bTHit ) + nFound = SC_PD_RANGE_TR; + else if ( bBHit ) + nFound = SC_PD_RANGE_BR; + else if ( bInsideV ) + nFound = SC_PD_RANGE_R; + } + else if ( bTHit && bInsideH ) + nFound = SC_PD_RANGE_T; + else if ( bBHit && bInsideH ) + nFound = SC_PD_RANGE_B; + if (nFound) + aSource = aRange; + + // Umbrueche + + if ( bVert && bInsideH && !nFound ) + { + size_t nRowCount = rData.GetPagesY(); + const SCROW* pRowEnd = rData.GetPageEndY(); + for (size_t nRowPos=0; nRowPos+1<nRowCount; nRowPos++) + if ( pRowEnd[nRowPos]+1 == nHitY ) + { + nFound = SC_PD_BREAK_V; + aSource = aRange; + nBreak = nHitY; + if ( nRowPos ) + nPrev = pRowEnd[nRowPos-1]+1; + else + nPrev = aRange.aStart.Row(); + } + } + if ( bHori && bInsideV && !nFound ) + { + size_t nColCount = rData.GetPagesX(); + const SCCOL* pColEnd = rData.GetPageEndX(); + for (size_t nColPos=0; nColPos+1<nColCount; nColPos++) + if ( pColEnd[nColPos]+1 == nHitX ) + { + nFound = SC_PD_BREAK_H; + aSource = aRange; + nBreak = nHitX; + if ( nColPos ) + nPrev = pColEnd[nColPos-1]+1; + else + nPrev = aRange.aStart.Col(); + } + } + } + } + } + + if (pSource) + *pSource = aSource; // Druckbereich + if (pBreak) + *pBreak = nBreak; // X/Y Position des verchobenen Seitenumbruchs + if (pPrev) + *pPrev = nPrev; // X/Y Anfang der Seite, die am Umbruch zuende ist + return nFound; +} + +void ScGridWindow::PagebreakMove( const MouseEvent& rMEvt, sal_Bool bUp ) +{ + //! Scrolling und Umschalten mit RFMouseMove zusammenfassen ! + //! (Weginvertieren vor dem Scrolling ist anders) + + // Scrolling + + sal_Bool bTimer = sal_False; + Point aPos = rMEvt.GetPosPixel(); + SCsCOL nDx = 0; + SCsROW nDy = 0; + if ( aPos.X() < 0 ) nDx = -1; + if ( aPos.Y() < 0 ) nDy = -1; + Size aSize = GetOutputSizePixel(); + if ( aPos.X() >= aSize.Width() ) + nDx = 1; + if ( aPos.Y() >= aSize.Height() ) + nDy = 1; + if ( nDx != 0 || nDy != 0 ) + { + if ( bPagebreakDrawn ) // weginvertieren + { + // DrawDragRect( aPagebreakDrag.aStart.Col(), aPagebreakDrag.aStart.Row(), + // aPagebreakDrag.aEnd.Col(), aPagebreakDrag.aEnd.Row(), sal_False ); + bPagebreakDrawn = sal_False; + UpdateDragRectOverlay(); + } + + if ( nDx != 0 ) pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) ); + if ( nDy != 0 ) pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) ); + bTimer = sal_True; + } + + // Umschalten bei Fixierung (damit Scrolling funktioniert) + + if ( eWhich == pViewData->GetActivePart() ) //?? + { + if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX ) + if ( nDx > 0 ) + { + if ( eWhich == SC_SPLIT_TOPLEFT ) + pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT ); + else if ( eWhich == SC_SPLIT_BOTTOMLEFT ) + pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ); + } + + if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX ) + if ( nDy > 0 ) + { + if ( eWhich == SC_SPLIT_TOPLEFT ) + pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT ); + else if ( eWhich == SC_SPLIT_TOPRIGHT ) + pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ); + } + } + + // ab hier neu + + // gesucht wird eine Position zwischen den Zellen (vor nPosX / nPosY) + SCsCOL nPosX; + SCsROW nPosY; + pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); + sal_Bool bLeft, bTop; + pViewData->GetMouseQuadrant( aPos, eWhich, nPosX, nPosY, bLeft, bTop ); + if ( !bLeft ) ++nPosX; + if ( !bTop ) ++nPosY; + + sal_Bool bBreak = ( nPagebreakMouse == SC_PD_BREAK_H || nPagebreakMouse == SC_PD_BREAK_V ); + sal_Bool bHide = sal_False; + sal_Bool bToEnd = sal_False; + ScRange aDrawRange = aPagebreakSource; + if ( bBreak ) + { + if ( nPagebreakMouse == SC_PD_BREAK_H ) + { + if ( nPosX > aPagebreakSource.aStart.Col() && + nPosX <= aPagebreakSource.aEnd.Col() + 1 ) // ans Ende ist auch erlaubt + { + bToEnd = ( nPosX == aPagebreakSource.aEnd.Col() + 1 ); + aDrawRange.aStart.SetCol( nPosX ); + aDrawRange.aEnd.SetCol( nPosX - 1 ); + } + else + bHide = sal_True; + } + else + { + if ( nPosY > aPagebreakSource.aStart.Row() && + nPosY <= aPagebreakSource.aEnd.Row() + 1 ) // ans Ende ist auch erlaubt + { + bToEnd = ( nPosY == aPagebreakSource.aEnd.Row() + 1 ); + aDrawRange.aStart.SetRow( nPosY ); + aDrawRange.aEnd.SetRow( nPosY - 1 ); + } + else + bHide = sal_True; + } + } + else + { + if ( nPagebreakMouse & SC_PD_RANGE_L ) + aDrawRange.aStart.SetCol( nPosX ); + if ( nPagebreakMouse & SC_PD_RANGE_T ) + aDrawRange.aStart.SetRow( nPosY ); + if ( nPagebreakMouse & SC_PD_RANGE_R ) + { + if ( nPosX > 0 ) + aDrawRange.aEnd.SetCol( nPosX-1 ); + else + bHide = sal_True; + } + if ( nPagebreakMouse & SC_PD_RANGE_B ) + { + if ( nPosY > 0 ) + aDrawRange.aEnd.SetRow( nPosY-1 ); + else + bHide = sal_True; + } + if ( aDrawRange.aStart.Col() > aDrawRange.aEnd.Col() || + aDrawRange.aStart.Row() > aDrawRange.aEnd.Row() ) + bHide = sal_True; + } + + if ( !bPagebreakDrawn || bUp || aDrawRange != aPagebreakDrag ) + { + // zeichnen... + + if ( bPagebreakDrawn ) + { + // weginvertieren + // DrawDragRect( aPagebreakDrag.aStart.Col(), aPagebreakDrag.aStart.Row(), + // aPagebreakDrag.aEnd.Col(), aPagebreakDrag.aEnd.Row(), sal_False ); + bPagebreakDrawn = sal_False; + } + aPagebreakDrag = aDrawRange; + if ( !bUp && !bHide ) + { + // hininvertieren + // DrawDragRect( aPagebreakDrag.aStart.Col(), aPagebreakDrag.aStart.Row(), + // aPagebreakDrag.aEnd.Col(), aPagebreakDrag.aEnd.Row(), sal_False ); + bPagebreakDrawn = sal_True; + } + UpdateDragRectOverlay(); + } + + // bei ButtonUp die Aenderung ausfuehren + + if ( bUp ) + { + ScViewFunc* pViewFunc = pViewData->GetView(); + ScDocShell* pDocSh = pViewData->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + sal_Bool bUndo (pDoc->IsUndoEnabled()); + + if ( bBreak ) + { + sal_Bool bColumn = ( nPagebreakMouse == SC_PD_BREAK_H ); + SCCOLROW nNew = bColumn ? static_cast<SCCOLROW>(nPosX) : static_cast<SCCOLROW>(nPosY); + if ( nNew != nPagebreakBreak ) + { + if (bUndo) + { + String aUndo = ScGlobal::GetRscString( STR_UNDO_DRAG_BREAK ); + pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo ); + } + + sal_Bool bGrow = !bHide && nNew > nPagebreakBreak; + if ( bColumn ) + { + if (pDoc->HasColBreak(static_cast<SCCOL>(nPagebreakBreak), nTab) & BREAK_MANUAL) + { + ScAddress aOldAddr( static_cast<SCCOL>(nPagebreakBreak), nPosY, nTab ); + pViewFunc->DeletePageBreak( sal_True, sal_True, &aOldAddr, sal_False ); + } + if ( !bHide && !bToEnd ) // am Ende nicht + { + ScAddress aNewAddr( static_cast<SCCOL>(nNew), nPosY, nTab ); + pViewFunc->InsertPageBreak( sal_True, sal_True, &aNewAddr, sal_False ); + } + if ( bGrow ) + { + // vorigen Break auf hart, und Skalierung aendern + bool bManualBreak = (pDoc->HasColBreak(static_cast<SCCOL>(nPagebreakPrev), nTab) & BREAK_MANUAL); + if ( static_cast<SCCOL>(nPagebreakPrev) > aPagebreakSource.aStart.Col() && !bManualBreak ) + { + ScAddress aPrev( static_cast<SCCOL>(nPagebreakPrev), nPosY, nTab ); + pViewFunc->InsertPageBreak( sal_True, sal_True, &aPrev, sal_False ); + } + + if (!pDocSh->AdjustPrintZoom( ScRange( + static_cast<SCCOL>(nPagebreakPrev),0,nTab, static_cast<SCCOL>(nNew-1),0,nTab ) )) + bGrow = sal_False; + } + } + else + { + if (pDoc->HasRowBreak(nPagebreakBreak, nTab) & BREAK_MANUAL) + { + ScAddress aOldAddr( nPosX, nPagebreakBreak, nTab ); + pViewFunc->DeletePageBreak( sal_False, sal_True, &aOldAddr, sal_False ); + } + if ( !bHide && !bToEnd ) // am Ende nicht + { + ScAddress aNewAddr( nPosX, nNew, nTab ); + pViewFunc->InsertPageBreak( sal_False, sal_True, &aNewAddr, sal_False ); + } + if ( bGrow ) + { + // vorigen Break auf hart, und Skalierung aendern + bool bManualBreak = (pDoc->HasRowBreak(nPagebreakPrev, nTab) & BREAK_MANUAL); + if ( nPagebreakPrev > aPagebreakSource.aStart.Row() && !bManualBreak ) + { + ScAddress aPrev( nPosX, nPagebreakPrev, nTab ); + pViewFunc->InsertPageBreak( sal_False, sal_True, &aPrev, sal_False ); + } + + if (!pDocSh->AdjustPrintZoom( ScRange( + 0,nPagebreakPrev,nTab, 0,nNew-1,nTab ) )) + bGrow = sal_False; + } + } + + if (bUndo) + { + pDocSh->GetUndoManager()->LeaveListAction(); + } + + if (!bGrow) // sonst in AdjustPrintZoom schon passiert + { + pViewFunc->UpdatePageBreakData( sal_True ); + pDocSh->SetDocumentModified(); + } + } + } + else if ( bHide || aPagebreakDrag != aPagebreakSource ) + { + // Druckbereich setzen + + String aNewRanges; + sal_uInt16 nOldCount = pDoc->GetPrintRangeCount( nTab ); + if ( nOldCount ) + { + for (sal_uInt16 nPos=0; nPos<nOldCount; nPos++) + { + const ScRange* pOld = pDoc->GetPrintRange( nTab, nPos ); + if ( pOld ) + { + String aTemp; + if ( *pOld != aPagebreakSource ) + pOld->Format( aTemp, SCA_VALID ); + else if ( !bHide ) + aPagebreakDrag.Format( aTemp, SCA_VALID ); + if (aTemp.Len()) + { + if ( aNewRanges.Len() ) + aNewRanges += ';'; + aNewRanges += aTemp; + } + } + } + } + else if (!bHide) + aPagebreakDrag.Format( aNewRanges, SCA_VALID ); + + pViewFunc->SetPrintRanges( pDoc->IsPrintEntireSheet( nTab ), &aNewRanges, NULL, NULL, sal_False ); + } + } + + // Timer fuer Scrolling + + if (bTimer && !bUp) + pViewData->GetView()->SetTimer( this, rMEvt ); // Event wiederholen + else + pViewData->GetView()->ResetTimer(); +} + + + + diff --git a/sc/source/ui/view/gridwin3.cxx b/sc/source/ui/view/gridwin3.cxx new file mode 100644 index 000000000000..295caae639af --- /dev/null +++ b/sc/source/ui/view/gridwin3.cxx @@ -0,0 +1,443 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +#include "scitems.hxx" +#include <editeng/eeitem.hxx> + +#include <svx/svdoutl.hxx> +#include <svx/svdotext.hxx> +#include <svx/svdpagv.hxx> +#include <editeng/sizeitem.hxx> +#include <sfx2/bindings.hxx> +#include <svl/ptitem.hxx> + +#include "tabvwsh.hxx" +#include "gridwin.hxx" +#include "dbfunc.hxx" +#include "viewdata.hxx" +#include "output.hxx" +#include "drawview.hxx" +#include "fupoor.hxx" + +#include "drawutil.hxx" +#include "document.hxx" +#include "drwlayer.hxx" +#include <vcl/svapp.hxx> + +// ----------------------------------------------------------------------- + +sal_Bool ScGridWindow::DrawMouseButtonDown(const MouseEvent& rMEvt) +{ + sal_Bool bRet = sal_False; + FuPoor* pDraw = pViewData->GetView()->GetDrawFuncPtr(); + if (pDraw && !pViewData->IsRefMode()) + { + pDraw->SetWindow( this ); + Point aLogicPos = PixelToLogic(rMEvt.GetPosPixel()); + if ( pDraw->IsDetectiveHit( aLogicPos ) ) + { + // auf Detektiv-Pfeilen gar nichts (Doppelklick wird bei ButtonUp ausgewertet) + bRet = sal_True; + } + else + { + bRet = pDraw->MouseButtonDown( rMEvt ); + if ( bRet ) + UpdateStatusPosSize(); + } + } + + // bei rechter Taste Draw-Aktion abbrechen + + ScDrawView* pDrView = pViewData->GetScDrawView(); + if ( pDrView && !rMEvt.IsLeft() && !bRet ) + { + pDrView->BrkAction(); + bRet = sal_True; + } + return bRet; +} + +sal_Bool ScGridWindow::DrawMouseButtonUp(const MouseEvent& rMEvt) +{ + ScViewFunc* pView = pViewData->GetView(); + sal_Bool bRet = sal_False; + FuPoor* pDraw = pView->GetDrawFuncPtr(); + if (pDraw && !pViewData->IsRefMode()) + { + pDraw->SetWindow( this ); + bRet = pDraw->MouseButtonUp( rMEvt ); + + // execute "format paint brush" for drawing objects + SfxItemSet* pDrawBrush = pView->GetDrawBrushSet(); + if ( pDrawBrush ) + { + ScDrawView* pDrView = pViewData->GetScDrawView(); + if ( pDrView ) + { + sal_Bool bReplaceAll = sal_True; + pDrView->SetAttrToMarked(*pDrawBrush, bReplaceAll); + } + + if ( !pView->IsPaintBrushLocked() ) + pView->ResetBrushDocument(); // end paint brush mode if not locked + } + } + + return bRet; +} + +sal_Bool ScGridWindow::DrawMouseMove(const MouseEvent& rMEvt) +{ + FuPoor* pDraw = pViewData->GetView()->GetDrawFuncPtr(); + if (pDraw && !pViewData->IsRefMode()) + { + pDraw->SetWindow( this ); + sal_Bool bRet = pDraw->MouseMove( rMEvt ); + if ( bRet ) + UpdateStatusPosSize(); + return bRet; + } + else + { + SetPointer( Pointer( POINTER_ARROW ) ); + return sal_False; + } +} + +void ScGridWindow::DrawEndAction() +{ + ScDrawView* pDrView = pViewData->GetScDrawView(); + if ( pDrView && pDrView->IsAction() ) + pDrView->BrkAction(); + + FuPoor* pDraw = pViewData->GetView()->GetDrawFuncPtr(); + if (pDraw) + pDraw->StopDragTimer(); + + // ReleaseMouse beim Aufruf +} + +sal_Bool ScGridWindow::DrawCommand(const CommandEvent& rCEvt) +{ + ScDrawView* pDrView = pViewData->GetScDrawView(); + FuPoor* pDraw = pViewData->GetView()->GetDrawFuncPtr(); + if (pDrView && pDraw && !pViewData->IsRefMode()) + { + pDraw->SetWindow( this ); + sal_uInt8 nUsed = pDraw->Command( rCEvt ); + if( nUsed == SC_CMD_USED ) + nButtonDown = 0; // MouseButtonUp wird verschluckt... + if( nUsed || pDrView->IsAction() ) + return sal_True; + } + + return sal_False; +} + +sal_Bool ScGridWindow::DrawKeyInput(const KeyEvent& rKEvt) +{ + ScDrawView* pDrView = pViewData->GetScDrawView(); + FuPoor* pDraw = pViewData->GetView()->GetDrawFuncPtr(); + if (pDrView && pDraw && !pViewData->IsRefMode()) + { + pDraw->SetWindow( this ); + sal_Bool bOldMarked = pDrView->AreObjectsMarked(); + if (pDraw->KeyInput( rKEvt )) + { + sal_Bool bLeaveDraw = sal_False; + sal_Bool bUsed = sal_True; + sal_Bool bNewMarked = pDrView->AreObjectsMarked(); + if ( !pViewData->GetView()->IsDrawSelMode() ) + if ( !bNewMarked ) + { + pViewData->GetViewShell()->SetDrawShell( sal_False ); + bLeaveDraw = sal_True; + if ( !bOldMarked && + rKEvt.GetKeyCode().GetCode() == KEY_DELETE ) + bUsed = sal_False; // nichts geloescht + } + if (!bLeaveDraw) + UpdateStatusPosSize(); // #108137# for moving/resizing etc. by keyboard + return bUsed; + } + } + + return sal_False; +} + +void ScGridWindow::DrawRedraw( ScOutputData& rOutputData, ScUpdateMode eMode, sal_uLong nLayer ) +{ + // #109985# + const ScViewOptions& rOpts = pViewData->GetOptions(); + + // use new flags at SdrPaintView for hiding objects + const bool bDrawOle(VOBJ_MODE_SHOW == rOpts.GetObjMode(VOBJ_TYPE_OLE)); + const bool bDrawChart(VOBJ_MODE_SHOW == rOpts.GetObjMode(VOBJ_TYPE_CHART)); + const bool bDrawDraw(VOBJ_MODE_SHOW == rOpts.GetObjMode(VOBJ_TYPE_DRAW)); + + if(bDrawOle || bDrawChart || bDrawDraw) + { + ScDrawView* pDrView = pViewData->GetView()->GetScDrawView(); + + if(pDrView) + { + pDrView->setHideOle(!bDrawOle); + pDrView->setHideChart(!bDrawChart); + pDrView->setHideDraw(!bDrawDraw); + pDrView->setHideFormControl(!bDrawDraw); + } + + if(SC_UPDATE_CHANGED == eMode) + { + rOutputData.DrawingSingle((sal_uInt16)nLayer); + } + else + { + rOutputData.DrawSelectiveObjects((sal_uInt16)nLayer); + } + } +} + +void ScGridWindow::DrawSdrGrid( const Rectangle& rDrawingRect, OutputDevice* pContentDev ) +{ + // Draw-Gitterlinien + + ScDrawView* pDrView = pViewData->GetView()->GetScDrawView(); + if ( pDrView && pDrView->IsGridVisible() ) + { + SdrPageView* pPV = pDrView->GetSdrPageView(); + DBG_ASSERT(pPV, "keine PageView"); + if (pPV) + { + pContentDev->SetLineColor(COL_GRAY); + + pPV->DrawPageViewGrid( *pContentDev, rDrawingRect ); + } + } +} + +MapMode ScGridWindow::GetDrawMapMode( sal_Bool bForce ) +{ + ScDocument* pDoc = pViewData->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + sal_Bool bNegativePage = pDoc->IsNegativePage( nTab ); + + MapMode aDrawMode = pViewData->GetLogicMode(); + + ScDrawView* pDrView = pViewData->GetView()->GetScDrawView(); + if ( pDrView || bForce ) + { + Fraction aScaleX; + Fraction aScaleY; + if (pDrView) + pDrView->GetScale( aScaleX, aScaleY ); + else + { + SCCOL nEndCol = 0; + SCROW nEndRow = 0; + pDoc->GetTableArea( nTab, nEndCol, nEndRow ); + if (nEndCol<20) nEndCol = 20; + if (nEndRow<20) nEndRow = 1000; + ScDrawUtil::CalcScale( pDoc, nTab, 0,0, nEndCol,nEndRow, this, + pViewData->GetZoomX(),pViewData->GetZoomY(), + pViewData->GetPPTX(),pViewData->GetPPTY(), + aScaleX,aScaleY ); + } + aDrawMode.SetScaleX(aScaleX); + aDrawMode.SetScaleY(aScaleY); + } + aDrawMode.SetOrigin(Point()); + Point aStartPos = pViewData->GetPixPos(eWhich); + if ( bNegativePage ) + { + // RTL uses negative positions for drawing objects + aStartPos.X() = -aStartPos.X() + GetOutputSizePixel().Width() - 1; + } + aDrawMode.SetOrigin( PixelToLogic( aStartPos, aDrawMode ) ); + + return aDrawMode; +} + +//sal_Bool ScGridWindow::DrawBeforeScroll() +//{ +// ScDrawView* pDrView = pViewData->GetView()->GetScDrawView(); +// +// sal_Bool bXor = sal_False; +// if (pDrView) +// { +// bXor=pDrView->IsShownXorVisible(this); +// if (bXor) pDrView->HideShownXor(this); +// } +// return bXor; +//} + +void ScGridWindow::DrawAfterScroll(/*sal_Bool bVal*/) +{ + Update(); // immer, damit das Verhalten mit/ohne DrawingLayer gleich ist + + ScDrawView* pDrView = pViewData->GetView()->GetScDrawView(); + if (pDrView) + { + //if (bVal) + // pDrView->ShowShownXor(this); + + OutlinerView* pOlView = pDrView->GetTextEditOutlinerView(); + if (pOlView && pOlView->GetWindow() == this) + pOlView->ShowCursor(sal_False); // ist beim Scrollen weggekommen + } +} + +//void ScGridWindow::DrawMarks() +//{ +// ScDrawView* pDrView = pViewData->GetView()->GetScDrawView(); +// if (pDrView) +// pDrView->DrawMarks(this); +//} + +//sal_Bool ScGridWindow::NeedDrawMarks() +//{ +// ScDrawView* pDrView = pViewData->GetView()->GetScDrawView(); +// return pDrView && pDrView->IsMarkHdlShown() && pDrView->AreObjectsMarked(); +//} + +void ScGridWindow::CreateAnchorHandle(SdrHdlList& rHdl, const ScAddress& rAddress) +{ + ScDrawView* pDrView = pViewData->GetView()->GetScDrawView(); + if (pDrView) + { + const ScViewOptions& rOpts = pViewData->GetOptions(); + if(rOpts.GetOption( VOPT_ANCHOR )) + { + sal_Bool bNegativePage = pViewData->GetDocument()->IsNegativePage( pViewData->GetTabNo() ); + Point aPos = pViewData->GetScrPos( rAddress.Col(), rAddress.Row(), eWhich, sal_True ); + aPos = PixelToLogic(aPos); + rHdl.AddHdl(new SdrHdl(aPos, bNegativePage ? HDL_ANCHOR_TR : HDL_ANCHOR)); + } + } +} + +SdrObject* ScGridWindow::GetEditObject() +{ + ScDrawView* pDrView = pViewData->GetView()->GetScDrawView(); + if (pDrView) + { + OutlinerView* pOlView = pDrView->GetTextEditOutlinerView(); + if (pOlView && pOlView->GetWindow() == this) + return pDrView->GetTextEditObject(); + } + + return NULL; +} + +void ScGridWindow::UpdateStatusPosSize() +{ + ScDrawView* pDrView = pViewData->GetView()->GetScDrawView(); + if (!pDrView) + return; // shouldn't be called in that case + + SdrPageView* pPV = pDrView->GetSdrPageView(); + if (!pPV) + return; // shouldn't be called in that case either + + SfxItemSet aSet(pViewData->GetViewShell()->GetPool(), SID_ATTR_POSITION, SID_ATTR_SIZE); + + // Fill items for position and size: + // #108137# show action rectangle during action, + // position and size of selected object(s) if something is selected, + // mouse position otherwise + + sal_Bool bActionItem = sal_False; + if ( pDrView->IsAction() ) // action rectangle + { + Rectangle aRect; + pDrView->TakeActionRect( aRect ); + if ( !aRect.IsEmpty() ) + { + pPV->LogicToPagePos(aRect); + aSet.Put( SfxPointItem( SID_ATTR_POSITION, aRect.TopLeft() ) ); + aSet.Put( SvxSizeItem( SID_ATTR_SIZE, + Size( aRect.Right() - aRect.Left(), aRect.Bottom() - aRect.Top() ) ) ); + bActionItem = sal_True; + } + } + if ( !bActionItem ) + { + if ( pDrView->AreObjectsMarked() ) // selected objects + { + Rectangle aRect = pDrView->GetAllMarkedRect(); + pPV->LogicToPagePos(aRect); + aSet.Put( SfxPointItem( SID_ATTR_POSITION, aRect.TopLeft() ) ); + aSet.Put( SvxSizeItem( SID_ATTR_SIZE, + Size( aRect.Right() - aRect.Left(), aRect.Bottom() - aRect.Top() ) ) ); + } + else // mouse position + { + Point aPos = PixelToLogic(aCurMousePos); + pPV->LogicToPagePos(aPos); + aSet.Put( SfxPointItem( SID_ATTR_POSITION, aPos ) ); + aSet.Put( SvxSizeItem( SID_ATTR_SIZE, Size( 0, 0 ) ) ); + } + } + + pViewData->GetBindings().SetState(aSet); +} + +sal_Bool ScGridWindow::DrawHasMarkedObj() +{ + ScDrawView* p = pViewData->GetScDrawView(); + return p ? p->AreObjectsMarked() : sal_False; +} + +//void ScGridWindow::DrawStartTimer() +//{ + //ScDrawView* pDrView = pViewData->GetView()->GetScDrawView(); + //if (pDrView) + //{ + /* jetzt in DrawMarks + sal_uInt16 nWinNum = pDrView->FindWin(this); + if (nWinNum!=SDRVIEWWIN_NOTFOUND) + pDrView->AfterInitRedraw(nWinNum); + */ + + // pDrView->PostPaint(); + // pDrView->RestartAfterPaintTimer(); + //} +//} + +void ScGridWindow::DrawMarkDropObj( SdrObject* pObj ) +{ + ScDrawView* pDrView = pViewData->GetView()->GetScDrawView(); + if (pDrView) + pDrView->MarkDropObj(pObj); +} + + + diff --git a/sc/source/ui/view/gridwin4.cxx b/sc/source/ui/view/gridwin4.cxx new file mode 100644 index 000000000000..8e0e964de821 --- /dev/null +++ b/sc/source/ui/view/gridwin4.cxx @@ -0,0 +1,2069 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include "scitems.hxx" +#include <editeng/eeitem.hxx> + + +#include <svtools/colorcfg.hxx> +#include <editeng/colritem.hxx> +#include <editeng/editview.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/scripttypeitem.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/printer.hxx> + +#include <svx/svdview.hxx> +#include "tabvwsh.hxx" + +#include "gridwin.hxx" +#include "viewdata.hxx" +#include "output.hxx" +#include "document.hxx" +#include "attrib.hxx" +#include "patattr.hxx" // InvertSimple +#include "dbcolect.hxx" +#include "docoptio.hxx" +#include "notemark.hxx" +#include "dbfunc.hxx" // oder GetPageBreakData an die ViewData +#include "scmod.hxx" +#include "inputhdl.hxx" +#include "rfindlst.hxx" +#include "hiranges.hxx" +#include "pagedata.hxx" +#include "docpool.hxx" +#include "globstr.hrc" +#include "docsh.hxx" // oder GetSfxInPlaceObject +#include "cbutton.hxx" +#include "invmerge.hxx" +#include "editutil.hxx" +#include "inputopt.hxx" +#include "fillinfo.hxx" +#include "dpcontrol.hxx" +#include "queryparam.hxx" +#include "sc.hrc" +#include <vcl/virdev.hxx> + +// #i74769# +#include <svx/sdrpaintwindow.hxx> + +//#include "tabvwsh.hxx" //! Test !!!! + +//------------------------------------------------------------------------ + +void lcl_LimitRect( Rectangle& rRect, const Rectangle& rVisible ) +{ + if ( rRect.Top() < rVisible.Top()-1 ) rRect.Top() = rVisible.Top()-1; +// if ( rRect.Left() < rVisible.Left()-1 ) rRect.Left() = rVisible.Left()-1; + if ( rRect.Bottom() > rVisible.Bottom()+1 ) rRect.Bottom() = rVisible.Bottom()+1; +// if ( rRect.Right() > rVisible.Right()+1 ) rRect.Right() = rVisible.Right()+1; + + // #51122# auch wenn das inner-Rectangle nicht sichtbar ist, muss evtl. + // die Titelzeile gezeichnet werden, darum kein Rueckgabewert mehr. + // Wenn's weit daneben liegt, wird lcl_DrawOneFrame erst gar nicht gerufen. +} + +void lcl_DrawOneFrame( OutputDevice* pDev, const Rectangle& rInnerPixel, + const String& rTitle, const Color& rColor, sal_Bool bTextBelow, + double nPPTX, double nPPTY, const Fraction& rZoomY, + ScDocument* pDoc, ScViewData* pButtonViewData, sal_Bool bLayoutRTL ) +{ + // pButtonViewData wird nur benutzt, um die Button-Groesse zu setzen, + // darf ansonsten NULL sein! + + Rectangle aInner = rInnerPixel; + if ( bLayoutRTL ) + { + aInner.Left() = rInnerPixel.Right(); + aInner.Right() = rInnerPixel.Left(); + } + + Rectangle aVisible( Point(0,0), pDev->GetOutputSizePixel() ); + lcl_LimitRect( aInner, aVisible ); + + Rectangle aOuter = aInner; + long nHor = (long) ( SC_SCENARIO_HSPACE * nPPTX ); + long nVer = (long) ( SC_SCENARIO_VSPACE * nPPTY ); + aOuter.Left() -= nHor; + aOuter.Right() += nHor; + aOuter.Top() -= nVer; + aOuter.Bottom() += nVer; + + // use ScPatternAttr::GetFont only for font size + Font aAttrFont; + ((const ScPatternAttr&)pDoc->GetPool()->GetDefaultItem(ATTR_PATTERN)). + GetFont(aAttrFont,SC_AUTOCOL_BLACK,pDev,&rZoomY); + + // everything else from application font + Font aAppFont = pDev->GetSettings().GetStyleSettings().GetAppFont(); + aAppFont.SetSize( aAttrFont.GetSize() ); + + aAppFont.SetAlign( ALIGN_TOP ); + pDev->SetFont( aAppFont ); + + Size aTextSize( pDev->GetTextWidth( rTitle ), pDev->GetTextHeight() ); + + if ( bTextBelow ) + aOuter.Bottom() += aTextSize.Height(); + else + aOuter.Top() -= aTextSize.Height(); + + pDev->SetLineColor(); + pDev->SetFillColor( rColor ); + // links, oben, rechts, unten + pDev->DrawRect( Rectangle( aOuter.Left(), aOuter.Top(), aInner.Left(), aOuter.Bottom() ) ); + pDev->DrawRect( Rectangle( aOuter.Left(), aOuter.Top(), aOuter.Right(), aInner.Top() ) ); + pDev->DrawRect( Rectangle( aInner.Right(), aOuter.Top(), aOuter.Right(), aOuter.Bottom() ) ); + pDev->DrawRect( Rectangle( aOuter.Left(), aInner.Bottom(), aOuter.Right(), aOuter.Bottom() ) ); + + long nButtonY = bTextBelow ? aInner.Bottom() : aOuter.Top(); + + ScDDComboBoxButton aComboButton((Window*)pDev); + aComboButton.SetOptSizePixel(); + long nBWidth = ( aComboButton.GetSizePixel().Width() * rZoomY.GetNumerator() ) + / rZoomY.GetDenominator(); + long nBHeight = nVer + aTextSize.Height() + 1; + Size aButSize( nBWidth, nBHeight ); + long nButtonPos = bLayoutRTL ? aOuter.Left() : aOuter.Right()-nBWidth+1; + aComboButton.Draw( Point(nButtonPos, nButtonY), aButSize, sal_False ); + if (pButtonViewData) + pButtonViewData->SetScenButSize( aButSize ); + + long nTextStart = bLayoutRTL ? aInner.Right() - aTextSize.Width() + 1 : aInner.Left(); + + sal_Bool bWasClip = sal_False; + Region aOldClip; + sal_Bool bClip = ( aTextSize.Width() > aOuter.Right() - nBWidth - aInner.Left() ); + if ( bClip ) + { + if (pDev->IsClipRegion()) + { + bWasClip = sal_True; + aOldClip = pDev->GetActiveClipRegion(); + } + long nClipStartX = bLayoutRTL ? aOuter.Left() + nBWidth : aInner.Left(); + long nClipEndX = bLayoutRTL ? aInner.Right() : aOuter.Right() - nBWidth; + pDev->SetClipRegion( Rectangle( nClipStartX, nButtonY + nVer/2, + nClipEndX, nButtonY + nVer/2 + aTextSize.Height() ) ); + } + + pDev->DrawText( Point( nTextStart, nButtonY + nVer/2 ), rTitle ); + + if ( bClip ) + { + if ( bWasClip ) + pDev->SetClipRegion(aOldClip); + else + pDev->SetClipRegion(); + } + + pDev->SetFillColor(); + pDev->SetLineColor( COL_BLACK ); + pDev->DrawRect( aInner ); + pDev->DrawRect( aOuter ); +} + +void lcl_DrawScenarioFrames( OutputDevice* pDev, ScViewData* pViewData, ScSplitPos eWhich, + SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2 ) +{ + ScDocument* pDoc = pViewData->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + SCTAB nTabCount = pDoc->GetTableCount(); + if ( nTab+1<nTabCount && pDoc->IsScenario(nTab+1) && !pDoc->IsScenario(nTab) ) + { + if ( nX1 > 0 ) --nX1; + if ( nY1>=2 ) nY1 -= 2; // Hack: Titelzeile beruehrt zwei Zellen + else if ( nY1 > 0 ) --nY1; + if ( nX2 < MAXCOL ) ++nX2; + if ( nY2 < MAXROW-1 ) nY2 += 2; // Hack: Titelzeile beruehrt zwei Zellen + else if ( nY2 < MAXROW ) ++nY2; + ScRange aViewRange( nX1,nY1,nTab, nX2,nY2,nTab ); + + //! Ranges an der Table cachen!!!! + + ScMarkData aMarks; + for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++) + pDoc->MarkScenario( i, nTab, aMarks, sal_False, SC_SCENARIO_SHOWFRAME ); + ScRangeListRef xRanges = new ScRangeList; + aMarks.FillRangeListWithMarks( xRanges, sal_False ); + + sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); + long nLayoutSign = bLayoutRTL ? -1 : 1; + + sal_uInt16 nRangeCount = (sal_uInt16)xRanges->Count(); + for (sal_uInt16 j=0; j<nRangeCount; j++) + { + ScRange aRange = *xRanges->GetObject(j); + // Szenario-Rahmen immer dann auf zusammengefasste Zellen erweitern, wenn + // dadurch keine neuen nicht-ueberdeckten Zellen mit umrandet werden + pDoc->ExtendTotalMerge( aRange ); + + //! -> Repaint beim Zusammenfassen erweitern !!! + + if ( aRange.Intersects( aViewRange ) ) //! Platz fuer Text/Button? + { + Point aStartPos = pViewData->GetScrPos( + aRange.aStart.Col(), aRange.aStart.Row(), eWhich, sal_True ); + Point aEndPos = pViewData->GetScrPos( + aRange.aEnd.Col()+1, aRange.aEnd.Row()+1, eWhich, sal_True ); + // on the grid: + aStartPos.X() -= nLayoutSign; + aStartPos.Y() -= 1; + aEndPos.X() -= nLayoutSign; + aEndPos.Y() -= 1; + + sal_Bool bTextBelow = ( aRange.aStart.Row() == 0 ); + + String aCurrent; + Color aColor( COL_LIGHTGRAY ); + for (SCTAB nAct=nTab+1; nAct<nTabCount && pDoc->IsScenario(nAct); nAct++) + if ( pDoc->IsActiveScenario(nAct) && pDoc->HasScenarioRange(nAct,aRange) ) + { + String aDummyComment; + sal_uInt16 nDummyFlags; + pDoc->GetName( nAct, aCurrent ); + pDoc->GetScenarioData( nAct, aDummyComment, aColor, nDummyFlags ); + } + + if (!aCurrent.Len()) + aCurrent = ScGlobal::GetRscString( STR_EMPTYDATA ); + + //! eigener Text "(keins)" statt "(leer)" ??? + + lcl_DrawOneFrame( pDev, Rectangle( aStartPos, aEndPos ), + aCurrent, aColor, bTextBelow, + pViewData->GetPPTX(), pViewData->GetPPTY(), pViewData->GetZoomY(), + pDoc, pViewData, bLayoutRTL ); + } + } + } +} + +//------------------------------------------------------------------------ + +void lcl_DrawHighlight( ScOutputData& rOutputData, ScViewData* pViewData, + ScHighlightRanges& rHighlightRanges ) +{ + SCTAB nTab = pViewData->GetTabNo(); + sal_uLong nCount = rHighlightRanges.Count(); + for (sal_uLong i=0; i<nCount; i++) + { + ScHighlightEntry* pEntry = rHighlightRanges.GetObject( i ); + if (pEntry) + { + ScRange aRange = pEntry->aRef; + if ( nTab >= aRange.aStart.Tab() && nTab <= aRange.aEnd.Tab() ) + { + rOutputData.DrawRefMark( + aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Col(), aRange.aEnd.Row(), + pEntry->aColor, sal_False ); + } + } + } +} + +//------------------------------------------------------------------------ + +void ScGridWindow::DoInvertRect( const Rectangle& rPixel ) +{ +// Invert( PixelToLogic(rPixel) ); + + if ( rPixel == aInvertRect ) + aInvertRect = Rectangle(); // aufheben + else + { + DBG_ASSERT( aInvertRect.IsEmpty(), "DoInvertRect nicht paarig" ); + + aInvertRect = rPixel; // neues Rechteck merken + } + + UpdateHeaderOverlay(); // uses aInvertRect +} + +//------------------------------------------------------------------------ + +void __EXPORT ScGridWindow::PrePaint() +{ + // forward PrePaint to DrawingLayer + ScTabViewShell* pTabViewShell = pViewData->GetViewShell(); + + if(pTabViewShell) + { + SdrView* pDrawView = pTabViewShell->GetSdrView(); + + if(pDrawView) + { + pDrawView->PrePaint(); + } + } +} + +//------------------------------------------------------------------------ + +void __EXPORT ScGridWindow::Paint( const Rectangle& rRect ) +{ + //TODO/LATER: how to get environment? Do we need that?! + /* + ScDocShell* pDocSh = pViewData->GetDocShell(); + SvInPlaceEnvironment* pEnv = pDocSh->GetIPEnv(); + if (pEnv && pEnv->GetRectsChangedLockCount()) + { + Invalidate(rRect); + return; + }*/ + + ScDocument* pDoc = pViewData->GetDocument(); + if ( pDoc->IsInInterpreter() ) + { + // via Reschedule, interpretierende Zellen nicht nochmal anstossen + // hier kein Invalidate, sonst kommt z.B. eine Error-Box nie an die Reihe + // (Bug 36381). Durch bNeedsRepaint wird spaeter alles nochmal gemalt. + + if ( bNeedsRepaint ) + { + //! Rechtecke zusammenfassen? + aRepaintPixel = Rectangle(); // mehrfach -> alles painten + } + else + { + bNeedsRepaint = sal_True; + aRepaintPixel = LogicToPixel(rRect); // nur betroffenen Bereich + } + return; + } + + if (bIsInPaint) + return; + + bIsInPaint = sal_True; + + Rectangle aPixRect = LogicToPixel( rRect ); + + SCCOL nX1 = pViewData->GetPosX(eHWhich); + SCROW nY1 = pViewData->GetPosY(eVWhich); + + SCTAB nTab = pViewData->GetTabNo(); + + double nPPTX = pViewData->GetPPTX(); + double nPPTY = pViewData->GetPPTY(); + + Rectangle aMirroredPixel = aPixRect; + if ( pDoc->IsLayoutRTL( nTab ) ) + { + // mirror and swap + long nWidth = GetSizePixel().Width(); + aMirroredPixel.Left() = nWidth - 1 - aPixRect.Right(); + aMirroredPixel.Right() = nWidth - 1 - aPixRect.Left(); + } + + long nScrX = ScViewData::ToPixel( pDoc->GetColWidth( nX1, nTab ), nPPTX ); + while ( nScrX <= aMirroredPixel.Left() && nX1 < MAXCOL ) + { + ++nX1; + nScrX += ScViewData::ToPixel( pDoc->GetColWidth( nX1, nTab ), nPPTX ); + } + SCCOL nX2 = nX1; + while ( nScrX <= aMirroredPixel.Right() && nX2 < MAXCOL ) + { + ++nX2; + nScrX += ScViewData::ToPixel( pDoc->GetColWidth( nX2, nTab ), nPPTX ); + } + + long nScrY = 0; + ScViewData::AddPixelsWhile( nScrY, aPixRect.Top(), nY1, MAXROW, nPPTY, pDoc, nTab); + SCROW nY2 = nY1; + if (nScrY <= aPixRect.Bottom() && nY2 < MAXROW) + { + ++nY2; + ScViewData::AddPixelsWhile( nScrY, aPixRect.Bottom(), nY2, MAXROW, nPPTY, pDoc, nTab); + } + + Draw( nX1,nY1,nX2,nY2, SC_UPDATE_MARKS ); // nicht weiterzeichnen + + bIsInPaint = sal_False; +} + +// +// Draw ---------------------------------------------------------------- +// + +void ScGridWindow::Draw( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, ScUpdateMode eMode ) +{ + ScModule* pScMod = SC_MOD(); + sal_Bool bTextWysiwyg = pScMod->GetInputOptions().GetTextWysiwyg(); + sal_Bool bGridFirst = sal_True; //! entscheiden!!! + + if (pViewData->IsMinimized()) + return; + + PutInOrder( nX1, nX2 ); + PutInOrder( nY1, nY2 ); + + DBG_ASSERT( ValidCol(nX2) && ValidRow(nY2), "GridWin Draw Bereich zu gross" ); + + SCCOL nPosX = pViewData->GetPosX( eHWhich ); + SCROW nPosY = pViewData->GetPosY( eVWhich ); + if (nX2 < nPosX || nY2 < nPosY) + return; // unsichtbar + if (nX1 < nPosX) nX1 = nPosX; + if (nY1 < nPosY) nY1 = nPosY; + + SCCOL nXRight = nPosX + pViewData->VisibleCellsX(eHWhich); + if (nXRight > MAXCOL) nXRight = MAXCOL; + SCROW nYBottom = nPosY + pViewData->VisibleCellsY(eVWhich); + if (nYBottom > MAXROW) nYBottom = MAXROW; + + // Store the current visible range. + maVisibleRange.mnCol1 = nPosX; + maVisibleRange.mnCol2 = nXRight; + maVisibleRange.mnRow1 = nPosY; + maVisibleRange.mnRow2 = nYBottom; + + if (nX1 > nXRight || nY1 > nYBottom) + return; // unsichtbar + if (nX2 > nXRight) nX2 = nXRight; + if (nY2 > nYBottom) nY2 = nYBottom; + + if ( eMode != SC_UPDATE_MARKS ) + if (nX2 < nXRight) + nX2 = nXRight; // zum Weiterzeichnen + + // ab hier kein return mehr + + ++nPaintCount; // merken, dass gemalt wird (wichtig beim Invertieren) + + ScDocShell* pDocSh = pViewData->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + + pDoc->ExtendHidden( nX1, nY1, nX2, nY2, nTab ); + + Point aScrPos = pViewData->GetScrPos( nX1, nY1, eWhich ); + long nMirrorWidth = GetSizePixel().Width(); + sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); + long nLayoutSign = bLayoutRTL ? -1 : 1; + if ( bLayoutRTL ) + { + long nEndPixel = pViewData->GetScrPos( nX2+1, nPosY, eWhich ).X(); + nMirrorWidth = aScrPos.X() - nEndPixel; + aScrPos.X() = nEndPixel + 1; + } + + long nScrX = aScrPos.X(); + long nScrY = aScrPos.Y(); + + SCCOL nCurX = pViewData->GetCurX(); + SCROW nCurY = pViewData->GetCurY(); + SCCOL nCurEndX = nCurX; + SCROW nCurEndY = nCurY; + pDoc->ExtendMerge( nCurX, nCurY, nCurEndX, nCurEndY, nTab ); + sal_Bool bCurVis = nCursorHideCount==0 && + ( nCurEndX+1 >= nX1 && nCurX <= nX2+1 && nCurEndY+1 >= nY1 && nCurY <= nY2+1 ); + + // AutoFill-Anfasser + if ( !bCurVis && nCursorHideCount==0 && bAutoMarkVisible && aAutoMarkPos.Tab() == nTab && + ( aAutoMarkPos.Col() != nCurX || aAutoMarkPos.Row() != nCurY ) ) + { + SCCOL nHdlX = aAutoMarkPos.Col(); + SCROW nHdlY = aAutoMarkPos.Row(); + pDoc->ExtendMerge( nHdlX, nHdlY, nHdlX, nHdlY, nTab ); + bCurVis = ( nHdlX+1 >= nX1 && nHdlX <= nX2 && nHdlY+1 >= nY1 && nHdlY <= nY2 ); + // links und oben ist nicht betroffen + + //! AutoFill-Anfasser alleine (ohne Cursor) zeichnen ??? + } + + double nPPTX = pViewData->GetPPTX(); + double nPPTY = pViewData->GetPPTY(); + + const ScViewOptions& rOpts = pViewData->GetOptions(); + sal_Bool bFormulaMode = rOpts.GetOption( VOPT_FORMULAS ); + sal_Bool bMarkClipped = rOpts.GetOption( VOPT_CLIPMARKS ); + + // Datenblock + + ScTableInfo aTabInfo; + pDoc->FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nTab, + nPPTX, nPPTY, sal_False, bFormulaMode, + &pViewData->GetMarkData() ); + + //-------------------------------------------------------------------- + + Fraction aZoomX = pViewData->GetZoomX(); + Fraction aZoomY = pViewData->GetZoomY(); + ScOutputData aOutputData( this, OUTTYPE_WINDOW, aTabInfo, pDoc, nTab, + nScrX, nScrY, nX1, nY1, nX2, nY2, nPPTX, nPPTY, + &aZoomX, &aZoomY ); + + aOutputData.SetMirrorWidth( nMirrorWidth ); // needed for RTL + + std::auto_ptr< VirtualDevice > xFmtVirtDev; + sal_Bool bLogicText = bTextWysiwyg; // call DrawStrings in logic MapMode? + + if ( bTextWysiwyg ) + { + // use printer for text formatting + + OutputDevice* pFmtDev = pDoc->GetPrinter(); + pFmtDev->SetMapMode( pViewData->GetLogicMode(eWhich) ); + aOutputData.SetFmtDevice( pFmtDev ); + } + else if ( aZoomX != aZoomY && pViewData->IsOle() ) + { + // #i45033# For OLE inplace editing with different zoom factors, + // use a virtual device with 1/100th mm as text formatting reference + + xFmtVirtDev.reset( new VirtualDevice ); + xFmtVirtDev->SetMapMode( MAP_100TH_MM ); + aOutputData.SetFmtDevice( xFmtVirtDev.get() ); + + bLogicText = sal_True; // use logic MapMode + } + + const svtools::ColorConfig& rColorCfg = pScMod->GetColorConfig(); + Color aGridColor( rColorCfg.GetColorValue( svtools::CALCGRID, sal_False ).nColor ); + if ( aGridColor.GetColor() == COL_TRANSPARENT ) + { + // use view options' grid color only if color config has "automatic" color + aGridColor = rOpts.GetGridColor(); + } + + aOutputData.SetSyntaxMode ( pViewData->IsSyntaxMode() ); + aOutputData.SetGridColor ( aGridColor ); + aOutputData.SetShowNullValues ( rOpts.GetOption( VOPT_NULLVALS ) ); + aOutputData.SetShowFormulas ( bFormulaMode ); + aOutputData.SetShowSpellErrors ( pDoc->GetDocOptions().IsAutoSpell() ); + aOutputData.SetMarkClipped ( bMarkClipped ); + + aOutputData.SetUseStyleColor( sal_True ); // always set in table view + + aOutputData.SetEditObject( GetEditObject() ); + aOutputData.SetViewShell( pViewData->GetViewShell() ); + + sal_Bool bGrid = rOpts.GetOption( VOPT_GRID ); + sal_Bool bPage = rOpts.GetOption( VOPT_PAGEBREAKS ); + + if ( eMode == SC_UPDATE_CHANGED ) + { + aOutputData.FindChanged(); + aOutputData.SetSingleGrid(sal_True); + } + + sal_Bool bPageMode = pViewData->IsPagebreakMode(); + if (bPageMode) // nach FindChanged + { + // SetPagebreakMode initialisiert auch bPrinted Flags + aOutputData.SetPagebreakMode( pViewData->GetView()->GetPageBreakData() ); + } + + EditView* pEditView = NULL; + sal_Bool bEditMode = pViewData->HasEditView(eWhich); + if ( bEditMode && pViewData->GetRefTabNo() == nTab ) + { + SCCOL nEditCol; + SCROW nEditRow; + pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow ); + SCCOL nEditEndCol = pViewData->GetEditEndCol(); + SCROW nEditEndRow = pViewData->GetEditEndRow(); + + if ( nEditEndCol >= nX1 && nEditCol <= nX2 && nEditEndRow >= nY1 && nEditRow <= nY2 ) + aOutputData.SetEditCell( nEditCol, nEditRow ); + else + bEditMode = sal_False; + + // nur Edit-Area zu zeichnen? + //! dann muss trotzdem noch der Rand / das Gitter gemalt werden! + +// if ( nEditCol <= nX1 && nEditEndCol >= nX2 && nEditRow <= nY1 && nEditEndRow >= nY2 ) +// bOnlyEdit = sal_True; + } + + // define drawing layer map mode and paint rectangle + const MapMode aDrawMode = GetDrawMapMode(); + Rectangle aDrawingRectLogic; + + { + // get drawing pixel rect + Rectangle aDrawingRectPixel(Point(nScrX, nScrY), Size(aOutputData.GetScrW(), aOutputData.GetScrH())); + + // correct for border (left/right) + if(MAXCOL == nX2) + { + if(bLayoutRTL) + { + aDrawingRectPixel.Left() = 0L; + } + else + { + aDrawingRectPixel.Right() = GetOutputSizePixel().getWidth(); + } + } + + // correct for border (bottom) + if(MAXROW == nY2) + { + aDrawingRectPixel.Bottom() = GetOutputSizePixel().getHeight(); + } + + // get logic positions + aDrawingRectLogic = PixelToLogic(aDrawingRectPixel, aDrawMode); + } + +// not necessary with overlay +// if (bCurVis) +// HideCursor(); + + OutputDevice* pContentDev = this; // device for document content, used by overlay manager + SdrPaintWindow* pTargetPaintWindow = 0; // #i74769# work with SdrPaintWindow directly + + { + // init redraw + ScTabViewShell* pTabViewShell = pViewData->GetViewShell(); + + if(pTabViewShell) + { + MapMode aCurrentMapMode(pContentDev->GetMapMode()); + pContentDev->SetMapMode(aDrawMode); + SdrView* pDrawView = pTabViewShell->GetSdrView(); + + if(pDrawView) + { + // #i74769# Use new BeginDrawLayers() interface + Region aDrawingRegion(aDrawingRectLogic); + pTargetPaintWindow = pDrawView->BeginDrawLayers(this, aDrawingRegion); + OSL_ENSURE(pTargetPaintWindow, "BeginDrawLayers: Got no SdrPaintWindow (!)"); + + // #i74769# get target device from SdrPaintWindow, this may be the prerender + // device now, too. + pContentDev = &(pTargetPaintWindow->GetTargetOutputDevice()); + aOutputData.SetContentDevice( pContentDev ); + } + + pContentDev->SetMapMode(aCurrentMapMode); + } + } + + // Rand (Wiese) (Pixel) + if ( nX2==MAXCOL || nY2==MAXROW ) + { + // save MapMode and set to pixel + MapMode aCurrentMapMode(pContentDev->GetMapMode()); + pContentDev->SetMapMode(MAP_PIXEL); + + Rectangle aPixRect = Rectangle( Point(), GetOutputSizePixel() ); + pContentDev->SetFillColor( rColorCfg.GetColorValue(svtools::APPBACKGROUND).nColor ); + pContentDev->SetLineColor(); + if ( nX2==MAXCOL ) + { + Rectangle aDrawRect( aPixRect ); + if ( bLayoutRTL ) + aDrawRect.Right() = nScrX - 1; + else + aDrawRect.Left() = nScrX + aOutputData.GetScrW(); + if (aDrawRect.Right() >= aDrawRect.Left()) + pContentDev->DrawRect( aDrawRect ); + } + if ( nY2==MAXROW ) + { + Rectangle aDrawRect( aPixRect ); + aDrawRect.Top() = nScrY + aOutputData.GetScrH(); + if ( nX2==MAXCOL ) + { + // no double painting of the corner + if ( bLayoutRTL ) + aDrawRect.Left() = nScrX; + else + aDrawRect.Right() = nScrX + aOutputData.GetScrW() - 1; + } + if (aDrawRect.Bottom() >= aDrawRect.Top()) + pContentDev->DrawRect( aDrawRect ); + } + + // restore MapMode + pContentDev->SetMapMode(aCurrentMapMode); + } + + if ( pDoc->HasBackgroundDraw( nTab, aDrawingRectLogic ) ) + { + pContentDev->SetMapMode(MAP_PIXEL); + aOutputData.DrawClear(); + + // Drawing Hintergrund + + pContentDev->SetMapMode(aDrawMode); + DrawRedraw( aOutputData, eMode, SC_LAYER_BACK ); + } + else + aOutputData.SetSolidBackground(sal_True); + + pContentDev->SetMapMode(MAP_PIXEL); + aOutputData.DrawBackground(); + if ( bGridFirst && ( bGrid || bPage ) ) + aOutputData.DrawGrid( bGrid, bPage ); + if ( bPageMode ) + { + // #87655# DrawPagePreview draws complete lines/page numbers, must always be clipped + if ( aOutputData.SetChangedClip() ) + { + DrawPagePreview(nX1,nY1,nX2,nY2, pContentDev); + pContentDev->SetClipRegion(); + } + } + aOutputData.DrawShadow(); + aOutputData.DrawFrame(); + if ( !bLogicText ) + aOutputData.DrawStrings(sal_False); // in pixel MapMode + + // edit cells and printer-metrics text must be before the buttons + // (DataPilot buttons contain labels in UI font) + + pContentDev->SetMapMode(pViewData->GetLogicMode(eWhich)); + if ( bLogicText ) + aOutputData.DrawStrings(sal_True); // in logic MapMode if bTextWysiwyg is set + aOutputData.DrawEdit(sal_True); + pContentDev->SetMapMode(MAP_PIXEL); + + // Autofilter- und Pivot-Buttons + + DrawButtons( nX1, nY1, nX2, nY2, aTabInfo, pContentDev ); // Pixel + + // Notiz-Anzeiger + + if ( rOpts.GetOption( VOPT_NOTES ) ) + aOutputData.DrawNoteMarks(); + + if ( !bGridFirst && ( bGrid || bPage ) ) + { + aOutputData.DrawGrid( bGrid, bPage ); + } + aOutputData.DrawClipMarks(); + + // Szenario / ChangeTracking muss auf jeden Fall nach DrawGrid sein, auch bei !bGridFirst + + //! Test, ob ChangeTrack-Anzeige aktiv ist + //! Szenario-Rahmen per View-Optionen abschaltbar? + + SCTAB nTabCount = pDoc->GetTableCount(); + ScHighlightRanges* pHigh = pViewData->GetView()->GetHighlightRanges(); + sal_Bool bHasScenario = ( nTab+1<nTabCount && pDoc->IsScenario(nTab+1) && !pDoc->IsScenario(nTab) ); + sal_Bool bHasChange = ( pDoc->GetChangeTrack() != NULL ); + + if ( bHasChange || bHasScenario || pHigh != NULL ) + { + + //! SetChangedClip() mit DrawMarks() zusammenfassen?? (anderer MapMode!) + + sal_Bool bAny = sal_True; + if (eMode == SC_UPDATE_CHANGED) + bAny = aOutputData.SetChangedClip(); + if (bAny) + { + if ( bHasChange ) + aOutputData.DrawChangeTrack(); + + if ( bHasScenario ) + lcl_DrawScenarioFrames( pContentDev, pViewData, eWhich, nX1,nY1,nX2,nY2 ); + + if ( pHigh ) + lcl_DrawHighlight( aOutputData, pViewData, *pHigh ); + + if (eMode == SC_UPDATE_CHANGED) + pContentDev->SetClipRegion(); + } + } + + // Drawing Vordergrund + + pContentDev->SetMapMode(aDrawMode); + + DrawRedraw( aOutputData, eMode, SC_LAYER_FRONT ); + DrawRedraw( aOutputData, eMode, SC_LAYER_INTERN ); + DrawSdrGrid( aDrawingRectLogic, pContentDev ); + + if (!bIsInScroll) // Drawing Markierungen + { + if(eMode == SC_UPDATE_CHANGED && aOutputData.SetChangedClip()) + { + pContentDev->SetClipRegion(); + } + + //sal_Bool bDraw = sal_True; + //if (eMode == SC_UPDATE_CHANGED) + // bDraw = NeedDrawMarks() && aOutputData.SetChangedClip(); + //if (bDraw) + //{ + // DrawMarks(); + // if (eMode == SC_UPDATE_CHANGED) + // pContentDev->SetClipRegion(); + //} + } + + pContentDev->SetMapMode(MAP_PIXEL); + +#ifdef OLD_SELECTION_PAINT + if (pViewData->IsActive()) + aOutputData.DrawMark( this ); +#endif + + if ( pViewData->IsRefMode() && nTab >= pViewData->GetRefStartZ() && nTab <= pViewData->GetRefEndZ() ) + { + // The AutoFill shrink area has an own overlay now +#if 0 + // Schraffur beim Loeschen per AutoFill + if ( pViewData->GetRefType() == SC_REFTYPE_FILL ) + { + ScRange aRange; + if ( pViewData->GetDelMark( aRange ) ) + { + if ( aRange.aStart.Col() < nX1 ) aRange.aStart.SetCol(nX1); + if ( aRange.aEnd.Col() > nX2 ) aRange.aEnd.SetCol(nX2); + if ( aRange.aStart.Row() < nY1 ) aRange.aStart.SetRow(nY1); + if ( aRange.aEnd.Row() > nY2 ) aRange.aEnd.SetRow(nY2); + if ( aRange.aStart.Col() <= aRange.aEnd.Col() && + aRange.aStart.Row() <= aRange.aEnd.Row() ) + { + Point aStart = pViewData->GetScrPos( aRange.aStart.Col(), + aRange.aStart.Row(), eWhich ); + Point aEnd = pViewData->GetScrPos( aRange.aEnd.Col()+1, + aRange.aEnd.Row()+1, eWhich ); + aEnd.X() -= 1; + aEnd.Y() -= 1; + + // Markierung aufheben - roter Rahmen bleibt stehen + Rectangle aRect( aStart,aEnd ); + Invert( aRect, INVERT_HIGHLIGHT ); + + //! Delete-Bereich extra kennzeichnen?!?!? + } + } + } +#endif + + Color aRefColor( rColorCfg.GetColorValue(svtools::CALCREFERENCE).nColor ); + aOutputData.DrawRefMark( pViewData->GetRefStartX(), pViewData->GetRefStartY(), + pViewData->GetRefEndX(), pViewData->GetRefEndY(), + aRefColor, sal_False ); + } + + // Range-Finder + + ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() ); + if (pHdl) + { + ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList(); + if ( pRangeFinder && !pRangeFinder->IsHidden() && + pRangeFinder->GetDocName() == pDocSh->GetTitle() ) + { + sal_uInt16 nCount = (sal_uInt16)pRangeFinder->Count(); + for (sal_uInt16 i=0; i<nCount; i++) + { + ScRangeFindData* pData = pRangeFinder->GetObject(i); + if (pData) + { + ScRange aRef = pData->aRef; + aRef.Justify(); + if ( aRef.aStart.Tab() >= nTab && aRef.aEnd.Tab() <= nTab ) + aOutputData.DrawRefMark( aRef.aStart.Col(), aRef.aStart.Row(), + aRef.aEnd.Col(), aRef.aEnd.Row(), + Color( ScRangeFindList::GetColorName( i ) ), + sal_True ); + } + } + } + } + + { + // end redraw + ScTabViewShell* pTabViewShell = pViewData->GetViewShell(); + + if(pTabViewShell) + { + MapMode aCurrentMapMode(pContentDev->GetMapMode()); + pContentDev->SetMapMode(aDrawMode); + SdrView* pDrawView = pTabViewShell->GetSdrView(); + + if(pDrawView) + { + // #i74769# work with SdrPaintWindow directly + pDrawView->EndDrawLayers(*pTargetPaintWindow, true); + } + + pContentDev->SetMapMode(aCurrentMapMode); + } + } + + // InPlace Edit-View + // moved after EndDrawLayers() to get it outside the overlay buffer and + // on top of everything + if ( bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()) ) + { + //! use pContentDev for EditView? + SetMapMode(MAP_PIXEL); + SCCOL nCol1 = pViewData->GetEditStartCol(); + SCROW nRow1 = pViewData->GetEditStartRow(); + SCCOL nCol2 = pViewData->GetEditEndCol(); + SCROW nRow2 = pViewData->GetEditEndRow(); + SetLineColor(); + SetFillColor( pEditView->GetBackgroundColor() ); + Point aStart = pViewData->GetScrPos( nCol1, nRow1, eWhich ); + Point aEnd = pViewData->GetScrPos( nCol2+1, nRow2+1, eWhich ); + aEnd.X() -= 2 * nLayoutSign; // don't overwrite grid + aEnd.Y() -= 2; + DrawRect( Rectangle( aStart,aEnd ) ); + + SetMapMode(pViewData->GetLogicMode()); + pEditView->Paint( PixelToLogic( Rectangle( Point( nScrX, nScrY ), + Size( aOutputData.GetScrW(), aOutputData.GetScrH() ) ) ) ); + SetMapMode(MAP_PIXEL); + } + + if (pViewData->HasEditView(eWhich)) + { + // flush OverlayManager before changing the MapMode + flushOverlayManager(); + + // set MapMode for text edit + SetMapMode(pViewData->GetLogicMode()); + } + else + SetMapMode(aDrawMode); + + if ( pNoteMarker ) + pNoteMarker->Draw(); // ueber den Cursor, im Drawing-MapMode + + //DrawStartTimer(); // fuer bunte Handles ohne System-Clipping + + // + // Wenn waehrend des Paint etwas invertiert wurde (Selektion geaendert aus Basic-Macro), + // ist das jetzt durcheinandergekommen und es muss neu gemalt werden + // + + DBG_ASSERT(nPaintCount, "nPaintCount falsch"); + --nPaintCount; + if (!nPaintCount) + CheckNeedsRepaint(); +} + +void ScGridWindow::CheckNeedsRepaint() +{ + // called at the end of painting, and from timer after background text width calculation + + if (bNeedsRepaint) + { + bNeedsRepaint = sal_False; + if (aRepaintPixel.IsEmpty()) + Invalidate(); + else + Invalidate(PixelToLogic(aRepaintPixel)); + aRepaintPixel = Rectangle(); + + // selection function in status bar might also be invalid + SfxBindings& rBindings = pViewData->GetBindings(); + rBindings.Invalidate( SID_STATUS_SUM ); + rBindings.Invalidate( SID_ATTR_SIZE ); + rBindings.Invalidate( SID_TABLE_CELL ); + } +} + +void ScGridWindow::DrawPagePreview( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, OutputDevice* pContentDev ) +{ + ScPageBreakData* pPageData = pViewData->GetView()->GetPageBreakData(); + if (pPageData) + { + ScDocument* pDoc = pViewData->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + Size aWinSize = GetOutputSizePixel(); + const svtools::ColorConfig& rColorCfg = SC_MOD()->GetColorConfig(); + Color aManual( rColorCfg.GetColorValue(svtools::CALCPAGEBREAKMANUAL).nColor ); + Color aAutomatic( rColorCfg.GetColorValue(svtools::CALCPAGEBREAK).nColor ); + + String aPageText = ScGlobal::GetRscString( STR_PAGE ); + if ( nPageScript == 0 ) + { + // get script type of translated "Page" string only once + nPageScript = pDoc->GetStringScriptType( aPageText ); + if (nPageScript == 0) + nPageScript = ScGlobal::GetDefaultScriptType(); + } + aPageText += ' '; + + Font aFont; + ScEditEngineDefaulter* pEditEng = NULL; + const ScPatternAttr& rDefPattern = ((const ScPatternAttr&)pDoc->GetPool()->GetDefaultItem(ATTR_PATTERN)); + if ( nPageScript == SCRIPTTYPE_LATIN ) + { + // use single font and call DrawText directly + rDefPattern.GetFont( aFont, SC_AUTOCOL_BLACK ); + aFont.SetColor( Color( COL_LIGHTGRAY ) ); + // font size is set as needed + } + else + { + // use EditEngine to draw mixed-script string + pEditEng = new ScEditEngineDefaulter( EditEngine::CreatePool(), sal_True ); + pEditEng->SetRefMapMode( pContentDev->GetMapMode() ); + SfxItemSet* pEditDefaults = new SfxItemSet( pEditEng->GetEmptyItemSet() ); + rDefPattern.FillEditItemSet( pEditDefaults ); + pEditDefaults->Put( SvxColorItem( Color( COL_LIGHTGRAY ), EE_CHAR_COLOR ) ); + pEditEng->SetDefaults( pEditDefaults ); + } + + sal_uInt16 nCount = sal::static_int_cast<sal_uInt16>( pPageData->GetCount() ); + for (sal_uInt16 nPos=0; nPos<nCount; nPos++) + { + ScPrintRangeData& rData = pPageData->GetData(nPos); + ScRange aRange = rData.GetPrintRange(); + if ( aRange.aStart.Col() <= nX2+1 && aRange.aEnd.Col()+1 >= nX1 && + aRange.aStart.Row() <= nY2+1 && aRange.aEnd.Row()+1 >= nY1 ) + { + // 3 Pixel Rahmen um den Druckbereich + // (mittlerer Pixel auf den Gitterlinien) + + pContentDev->SetLineColor(); + if (rData.IsAutomatic()) + pContentDev->SetFillColor( aAutomatic ); + else + pContentDev->SetFillColor( aManual ); + + Point aStart = pViewData->GetScrPos( + aRange.aStart.Col(), aRange.aStart.Row(), eWhich, sal_True ); + Point aEnd = pViewData->GetScrPos( + aRange.aEnd.Col() + 1, aRange.aEnd.Row() + 1, eWhich, sal_True ); + aStart.X() -= 2; + aStart.Y() -= 2; + + // Ueberlaeufe verhindern: + if ( aStart.X() < -10 ) aStart.X() = -10; + if ( aStart.Y() < -10 ) aStart.Y() = -10; + if ( aEnd.X() > aWinSize.Width() + 10 ) + aEnd.X() = aWinSize.Width() + 10; + if ( aEnd.Y() > aWinSize.Height() + 10 ) + aEnd.Y() = aWinSize.Height() + 10; + + pContentDev->DrawRect( Rectangle( aStart, Point(aEnd.X(),aStart.Y()+2) ) ); + pContentDev->DrawRect( Rectangle( aStart, Point(aStart.X()+2,aEnd.Y()) ) ); + pContentDev->DrawRect( Rectangle( Point(aStart.X(),aEnd.Y()-2), aEnd ) ); + pContentDev->DrawRect( Rectangle( Point(aEnd.X()-2,aStart.Y()), aEnd ) ); + + // Seitenumbrueche + //! anders darstellen (gestrichelt ????) + + size_t nColBreaks = rData.GetPagesX(); + const SCCOL* pColEnd = rData.GetPageEndX(); + size_t nColPos; + for (nColPos=0; nColPos+1<nColBreaks; nColPos++) + { + SCCOL nBreak = pColEnd[nColPos]+1; + if ( nBreak >= nX1 && nBreak <= nX2+1 ) + { + //! hidden suchen + if (pDoc->HasColBreak(nBreak, nTab) & BREAK_MANUAL) + pContentDev->SetFillColor( aManual ); + else + pContentDev->SetFillColor( aAutomatic ); + Point aBreak = pViewData->GetScrPos( + nBreak, aRange.aStart.Row(), eWhich, sal_True ); + pContentDev->DrawRect( Rectangle( aBreak.X()-1, aStart.Y(), aBreak.X(), aEnd.Y() ) ); + } + } + + size_t nRowBreaks = rData.GetPagesY(); + const SCROW* pRowEnd = rData.GetPageEndY(); + size_t nRowPos; + for (nRowPos=0; nRowPos+1<nRowBreaks; nRowPos++) + { + SCROW nBreak = pRowEnd[nRowPos]+1; + if ( nBreak >= nY1 && nBreak <= nY2+1 ) + { + //! hidden suchen + if (pDoc->HasRowBreak(nBreak, nTab) & BREAK_MANUAL) + pContentDev->SetFillColor( aManual ); + else + pContentDev->SetFillColor( aAutomatic ); + Point aBreak = pViewData->GetScrPos( + aRange.aStart.Col(), nBreak, eWhich, sal_True ); + pContentDev->DrawRect( Rectangle( aStart.X(), aBreak.Y()-1, aEnd.X(), aBreak.Y() ) ); + } + } + + // Seitenzahlen + + SCROW nPrStartY = aRange.aStart.Row(); + for (nRowPos=0; nRowPos<nRowBreaks; nRowPos++) + { + SCROW nPrEndY = pRowEnd[nRowPos]; + if ( nPrEndY >= nY1 && nPrStartY <= nY2 ) + { + SCCOL nPrStartX = aRange.aStart.Col(); + for (nColPos=0; nColPos<nColBreaks; nColPos++) + { + SCCOL nPrEndX = pColEnd[nColPos]; + if ( nPrEndX >= nX1 && nPrStartX <= nX2 ) + { + Point aPageStart = pViewData->GetScrPos( + nPrStartX, nPrStartY, eWhich, sal_True ); + Point aPageEnd = pViewData->GetScrPos( + nPrEndX+1,nPrEndY+1, eWhich, sal_True ); + + long nPageNo = rData.GetFirstPage(); + if ( rData.IsTopDown() ) + nPageNo += ((long)nColPos)*nRowBreaks+nRowPos; + else + nPageNo += ((long)nRowPos)*nColBreaks+nColPos; + String aPageStr = aPageText; + aPageStr += String::CreateFromInt32(nPageNo); + + if ( pEditEng ) + { + // find right font size with EditEngine + long nHeight = 100; + pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) ); + pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) ); + pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) ); + pEditEng->SetText( aPageStr ); + Size aSize100( pEditEng->CalcTextWidth(), pEditEng->GetTextHeight() ); + + // 40% of width or 60% of height + long nSizeX = 40 * ( aPageEnd.X() - aPageStart.X() ) / aSize100.Width(); + long nSizeY = 60 * ( aPageEnd.Y() - aPageStart.Y() ) / aSize100.Height(); + nHeight = Min(nSizeX,nSizeY); + pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) ); + pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) ); + pEditEng->SetDefaultItem( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) ); + + // centered output with EditEngine + Size aTextSize( pEditEng->CalcTextWidth(), pEditEng->GetTextHeight() ); + Point aPos( (aPageStart.X()+aPageEnd.X()-aTextSize.Width())/2, + (aPageStart.Y()+aPageEnd.Y()-aTextSize.Height())/2 ); + pEditEng->Draw( pContentDev, aPos ); + } + else + { + // find right font size for DrawText + aFont.SetSize( Size( 0,100 ) ); + pContentDev->SetFont( aFont ); + Size aSize100( pContentDev->GetTextWidth( aPageStr ), pContentDev->GetTextHeight() ); + + // 40% of width or 60% of height + long nSizeX = 40 * ( aPageEnd.X() - aPageStart.X() ) / aSize100.Width(); + long nSizeY = 60 * ( aPageEnd.Y() - aPageStart.Y() ) / aSize100.Height(); + aFont.SetSize( Size( 0,Min(nSizeX,nSizeY) ) ); + pContentDev->SetFont( aFont ); + + // centered output with DrawText + Size aTextSize( pContentDev->GetTextWidth( aPageStr ), pContentDev->GetTextHeight() ); + Point aPos( (aPageStart.X()+aPageEnd.X()-aTextSize.Width())/2, + (aPageStart.Y()+aPageEnd.Y()-aTextSize.Height())/2 ); + pContentDev->DrawText( aPos, aPageStr ); + } + } + nPrStartX = nPrEndX + 1; + } + } + nPrStartY = nPrEndY + 1; + } + } + } + + delete pEditEng; + } +} + +void ScGridWindow::DrawButtons( SCCOL nX1, SCROW /*nY1*/, SCCOL nX2, SCROW /*nY2*/, ScTableInfo& rTabInfo, OutputDevice* pContentDev ) +{ + aComboButton.SetOutputDevice( pContentDev ); + + ScDocument* pDoc = pViewData->GetDocument(); + ScDPFieldButton aCellBtn(pContentDev, &GetSettings().GetStyleSettings(), &pViewData->GetZoomX(), &pViewData->GetZoomY(), pDoc); + + SCCOL nCol; + SCROW nRow; + SCSIZE nArrY; + SCSIZE nQuery; + SCTAB nTab = pViewData->GetTabNo(); + ScDBData* pDBData = NULL; + ScQueryParam* pQueryParam = NULL; + + RowInfo* pRowInfo = rTabInfo.mpRowInfo; + sal_uInt16 nArrCount = rTabInfo.mnArrCount; + + sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); + + Point aOldPos = aComboButton.GetPosPixel(); // Zustand fuer MouseDown/Up + Size aOldSize = aComboButton.GetSizePixel(); // merken + + for (nArrY=1; nArrY+1<nArrCount; nArrY++) + { + if ( pRowInfo[nArrY].bAutoFilter && pRowInfo[nArrY].bChanged ) + { + RowInfo* pThisRowInfo = &pRowInfo[nArrY]; + + nRow = pThisRowInfo->nRowNo; + + + for (nCol=nX1; nCol<=nX2; nCol++) + { + CellInfo* pInfo = &pThisRowInfo->pCellInfo[nCol+1]; + if ( pInfo->bAutoFilter && !pInfo->bHOverlapped && !pInfo->bVOverlapped ) + { + if (!pQueryParam) + pQueryParam = new ScQueryParam; + + sal_Bool bNewData = sal_True; + if (pDBData) + { + SCCOL nStartCol; + SCROW nStartRow; + SCCOL nEndCol; + SCROW nEndRow; + SCTAB nAreaTab; + pDBData->GetArea( nAreaTab, nStartCol, nStartRow, nEndCol, nEndRow ); + if ( nCol >= nStartCol && nCol <= nEndCol && + nRow >= nStartRow && nRow <= nEndRow ) + bNewData = sal_False; + } + if (bNewData) + { + pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab ); + if (pDBData) + pDBData->GetQueryParam( *pQueryParam ); + else + { + // can also be part of DataPilot table + // DBG_ERROR("Auto-Filter-Button ohne DBData"); + } + } + + // pQueryParam kann nur MAXQUERY Eintraege enthalten + + sal_Bool bSimpleQuery = sal_True; + sal_Bool bColumnFound = sal_False; + if (!pQueryParam->bInplace) + bSimpleQuery = sal_False; + for (nQuery=0; nQuery<MAXQUERY && bSimpleQuery; nQuery++) + if (pQueryParam->GetEntry(nQuery).bDoQuery) + { + // hier nicht auf EQUAL beschraenken + // (auch bei ">1" soll der Spaltenkopf blau werden) + + if (pQueryParam->GetEntry(nQuery).nField == nCol) + bColumnFound = sal_True; + if (nQuery > 0) + if (pQueryParam->GetEntry(nQuery).eConnect != SC_AND) + bSimpleQuery = sal_False; + } + + bool bArrowState = bSimpleQuery && bColumnFound; + long nSizeX; + long nSizeY; + pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY ); + Point aScrPos = pViewData->GetScrPos( nCol, nRow, eWhich ); + + aCellBtn.setBoundingBox(aScrPos, Size(nSizeX-1, nSizeY-1), bLayoutRTL); + aCellBtn.setPopupLeft(bLayoutRTL); // #i114944# AutoFilter button is left-aligned in RTL + aCellBtn.setDrawBaseButton(false); + aCellBtn.setDrawPopupButton(true); + aCellBtn.setHasHiddenMember(bArrowState); + aCellBtn.draw(); + } + } + } + + if ( pRowInfo[nArrY].bPushButton && pRowInfo[nArrY].bChanged ) + { + RowInfo* pThisRowInfo = &pRowInfo[nArrY]; + nRow = pThisRowInfo->nRowNo; + for (nCol=nX1; nCol<=nX2; nCol++) + { + CellInfo* pInfo = &pThisRowInfo->pCellInfo[nCol+1]; + if ( pInfo->bPushButton && !pInfo->bHOverlapped && !pInfo->bVOverlapped ) + { + Point aScrPos = pViewData->GetScrPos( nCol, nRow, eWhich ); + long nSizeX; + long nSizeY; + pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY ); + long nPosX = aScrPos.X(); + long nPosY = aScrPos.Y(); + // bLayoutRTL is handled in setBoundingBox + + String aStr; + pDoc->GetString(nCol, nRow, nTab, aStr); + aCellBtn.setText(aStr); + aCellBtn.setBoundingBox(Point(nPosX, nPosY), Size(nSizeX-1, nSizeY-1), bLayoutRTL); + aCellBtn.setPopupLeft(false); // DataPilot popup is always right-aligned for now + aCellBtn.setDrawBaseButton(true); + aCellBtn.setDrawPopupButton(pInfo->bPopupButton); + aCellBtn.setHasHiddenMember(pInfo->bFilterActive); + aCellBtn.draw(); + } + } + } + + if ( bListValButton && pRowInfo[nArrY].nRowNo == aListValPos.Row() && pRowInfo[nArrY].bChanged ) + { + Rectangle aRect = GetListValButtonRect( aListValPos ); + aComboButton.SetPosPixel( aRect.TopLeft() ); + aComboButton.SetSizePixel( aRect.GetSize() ); + pContentDev->SetClipRegion( aRect ); + aComboButton.Draw( sal_False, sal_False ); + pContentDev->SetClipRegion(); // always called from Draw() without clip region + aComboButton.SetPosPixel( aOldPos ); // restore old state + aComboButton.SetSizePixel( aOldSize ); // for MouseUp/Down (AutoFilter) + } + } + + delete pQueryParam; + aComboButton.SetOutputDevice( this ); +} + +Rectangle ScGridWindow::GetListValButtonRect( const ScAddress& rButtonPos ) +{ + ScDocument* pDoc = pViewData->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); + long nLayoutSign = bLayoutRTL ? -1 : 1; + + ScDDComboBoxButton aButton( this ); // for optimal size + Size aBtnSize = aButton.GetSizePixel(); + + SCCOL nCol = rButtonPos.Col(); + SCROW nRow = rButtonPos.Row(); + + long nCellSizeX; // width of this cell, including merged + long nDummy; + pViewData->GetMergeSizePixel( nCol, nRow, nCellSizeX, nDummy ); + + // for height, only the cell's row is used, excluding merged cells + long nCellSizeY = ScViewData::ToPixel( pDoc->GetRowHeight( nRow, nTab ), pViewData->GetPPTY() ); + long nAvailable = nCellSizeX; + + // left edge of next cell if there is a non-hidden next column + SCCOL nNextCol = nCol + 1; + const ScMergeAttr* pMerge = static_cast<const ScMergeAttr*>(pDoc->GetAttr( nCol,nRow,nTab, ATTR_MERGE )); + if ( pMerge->GetColMerge() > 1 ) + nNextCol = nCol + pMerge->GetColMerge(); // next cell after the merged area + while ( nNextCol <= MAXCOL && pDoc->ColHidden(nNextCol, nTab) ) + ++nNextCol; + sal_Bool bNextCell = ( nNextCol <= MAXCOL ); + if ( bNextCell ) + nAvailable = ScViewData::ToPixel( pDoc->GetColWidth( nNextCol, nTab ), pViewData->GetPPTX() ); + + if ( nAvailable < aBtnSize.Width() ) + aBtnSize.Width() = nAvailable; + if ( nCellSizeY < aBtnSize.Height() ) + aBtnSize.Height() = nCellSizeY; + + Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich, sal_True ); + aPos.X() += nCellSizeX * nLayoutSign; // start of next cell + if (!bNextCell) + aPos.X() -= aBtnSize.Width() * nLayoutSign; // right edge of cell if next cell not available + aPos.Y() += nCellSizeY - aBtnSize.Height(); + // X remains at the left edge + + if ( bLayoutRTL ) + aPos.X() -= aBtnSize.Width()-1; // align right edge of button with cell border + + return Rectangle( aPos, aBtnSize ); +} + +sal_Bool ScGridWindow::IsAutoFilterActive( SCCOL nCol, SCROW nRow, SCTAB nTab ) +{ + ScDocument* pDoc = pViewData->GetDocument(); + ScDBData* pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab ); + ScQueryParam aQueryParam; + + if ( pDBData ) + pDBData->GetQueryParam( aQueryParam ); + else + { + DBG_ERROR("Auto-Filter-Button ohne DBData"); + } + + sal_Bool bSimpleQuery = sal_True; + sal_Bool bColumnFound = sal_False; + SCSIZE nQuery; + + if ( !aQueryParam.bInplace ) + bSimpleQuery = sal_False; + + // aQueryParam kann nur MAXQUERY Eintraege enthalten + + for ( nQuery=0; nQuery<MAXQUERY && bSimpleQuery; nQuery++ ) + if ( aQueryParam.GetEntry(nQuery).bDoQuery ) + { + if (aQueryParam.GetEntry(nQuery).nField == nCol) + bColumnFound = sal_True; + + if (nQuery > 0) + if (aQueryParam.GetEntry(nQuery).eConnect != SC_AND) + bSimpleQuery = sal_False; + } + + return ( bSimpleQuery && bColumnFound ); +} + +void ScGridWindow::DrawComboButton( const Point& rCellPos, + long nCellSizeX, + long nCellSizeY, + sal_Bool bArrowState, + sal_Bool bBtnIn ) +{ + Point aScrPos = rCellPos; + Size aBtnSize = aComboButton.GetSizePixel(); + + if ( nCellSizeX < aBtnSize.Width() || nCellSizeY < aBtnSize.Height() ) + { + if ( nCellSizeX < aBtnSize.Width() ) + aBtnSize.Width() = nCellSizeX; + + if ( nCellSizeY < aBtnSize.Height() ) + aBtnSize.Height() = nCellSizeY; + + aComboButton.SetSizePixel( aBtnSize ); + } + + sal_Bool bLayoutRTL = pViewData->GetDocument()->IsLayoutRTL( pViewData->GetTabNo() ); + + if ( bLayoutRTL ) + aScrPos.X() -= nCellSizeX - 1; + else + aScrPos.X() += nCellSizeX - aBtnSize.Width(); + aScrPos.Y() += nCellSizeY - aBtnSize.Height(); + + aComboButton.SetPosPixel( aScrPos ); + + HideCursor(); + aComboButton.Draw( bArrowState, bBtnIn ); + ShowCursor(); +} + +void ScGridWindow::InvertSimple( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, + sal_Bool bTestMerge, sal_Bool bRepeat ) +{ + //! if INVERT_HIGHLIGHT swaps foreground and background (like on Mac), + //! use INVERT_HIGHLIGHT only for cells that have no background color set + //! (here and in ScOutputData::DrawMark) + + PutInOrder( nX1, nX2 ); + PutInOrder( nY1, nY2 ); + + ScMarkData& rMark = pViewData->GetMarkData(); + ScDocument* pDoc = pViewData->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + + sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); + long nLayoutSign = bLayoutRTL ? -1 : 1; + + SCCOL nTestX2 = nX2; + SCROW nTestY2 = nY2; + if (bTestMerge) + pDoc->ExtendMerge( nX1,nY1, nTestX2,nTestY2, nTab ); + + SCCOL nPosX = pViewData->GetPosX( eHWhich ); + SCROW nPosY = pViewData->GetPosY( eVWhich ); + if (nTestX2 < nPosX || nTestY2 < nPosY) + return; // unsichtbar + SCCOL nRealX1 = nX1; + if (nX1 < nPosX) + nX1 = nPosX; + if (nY1 < nPosY) + nY1 = nPosY; + + SCCOL nXRight = nPosX + pViewData->VisibleCellsX(eHWhich); + if (nXRight > MAXCOL) nXRight = MAXCOL; + SCROW nYBottom = nPosY + pViewData->VisibleCellsY(eVWhich); + if (nYBottom > MAXROW) nYBottom = MAXROW; + + if (nX1 > nXRight || nY1 > nYBottom) + return; // unsichtbar + if (nX2 > nXRight) nX2 = nXRight; + if (nY2 > nYBottom) nY2 = nYBottom; + + MapMode aOld = GetMapMode(); SetMapMode(MAP_PIXEL); // erst nach den return's !!! + + double nPPTX = pViewData->GetPPTX(); + double nPPTY = pViewData->GetPPTY(); + + ScInvertMerger aInvert( this ); + + Point aScrPos = pViewData->GetScrPos( nX1, nY1, eWhich ); + long nScrY = aScrPos.Y(); + sal_Bool bWasHidden = sal_False; + for (SCROW nY=nY1; nY<=nY2; nY++) + { + sal_Bool bFirstRow = ( nY == nPosY ); // first visible row? + sal_Bool bDoHidden = sal_False; // versteckte nachholen ? + sal_uInt16 nHeightTwips = pDoc->GetRowHeight( nY,nTab ); + sal_Bool bDoRow = ( nHeightTwips != 0 ); + if (bDoRow) + { + if (bTestMerge) + if (bWasHidden) // auf versteckte zusammengefasste testen + { +// --nY; // nY geaendert -> vorherige zeichnen + bDoHidden = sal_True; + bDoRow = sal_True; + } + + bWasHidden = sal_False; + } + else + { + bWasHidden = sal_True; + if (bTestMerge) + if (nY==nY2) + bDoRow = sal_True; // letzte Zeile aus Block + } + + if ( bDoRow ) + { + SCCOL nLoopEndX = nX2; + if (nX2 < nX1) // Rest von zusammengefasst + { + SCCOL nStartX = nX1; + while ( ((const ScMergeFlagAttr*)pDoc-> + GetAttr(nStartX,nY,nTab,ATTR_MERGE_FLAG))->IsHorOverlapped() ) + --nStartX; + if (nStartX <= nX2) + nLoopEndX = nX1; + } + + long nEndY = nScrY + ScViewData::ToPixel( nHeightTwips, nPPTY ) - 1; + long nScrX = aScrPos.X(); + for (SCCOL nX=nX1; nX<=nLoopEndX; nX++) + { + long nWidth = ScViewData::ToPixel( pDoc->GetColWidth( nX,nTab ), nPPTX ); + if ( nWidth > 0 ) + { + long nEndX = nScrX + ( nWidth - 1 ) * nLayoutSign; + if (bTestMerge) + { + SCROW nThisY = nY; + const ScPatternAttr* pPattern = pDoc->GetPattern( nX, nY, nTab ); + const ScMergeFlagAttr* pMergeFlag = (const ScMergeFlagAttr*) &pPattern-> + GetItem(ATTR_MERGE_FLAG); + if ( pMergeFlag->IsVerOverlapped() && ( bDoHidden || bFirstRow ) ) + { + while ( pMergeFlag->IsVerOverlapped() && nThisY > 0 && + (pDoc->RowHidden(nThisY-1, nTab) || bFirstRow) ) + { + --nThisY; + pPattern = pDoc->GetPattern( nX, nThisY, nTab ); + pMergeFlag = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG); + } + } + + // nur Rest von zusammengefasster zu sehen ? + SCCOL nThisX = nX; + if ( pMergeFlag->IsHorOverlapped() && nX == nPosX && nX > nRealX1 ) + { + while ( pMergeFlag->IsHorOverlapped() ) + { + --nThisX; + pPattern = pDoc->GetPattern( nThisX, nThisY, nTab ); + pMergeFlag = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG); + } + } + + if ( rMark.IsCellMarked( nThisX, nThisY, sal_True ) == bRepeat ) + { + if ( !pMergeFlag->IsOverlapped() ) + { + ScMergeAttr* pMerge = (ScMergeAttr*)&pPattern->GetItem(ATTR_MERGE); + if (pMerge->GetColMerge() > 0 || pMerge->GetRowMerge() > 0) + { + Point aEndPos = pViewData->GetScrPos( + nThisX + pMerge->GetColMerge(), + nThisY + pMerge->GetRowMerge(), eWhich ); + if ( aEndPos.X() * nLayoutSign > nScrX * nLayoutSign && aEndPos.Y() > nScrY ) + { + aInvert.AddRect( Rectangle( nScrX,nScrY, + aEndPos.X()-nLayoutSign,aEndPos.Y()-1 ) ); + } + } + else if ( nEndX * nLayoutSign >= nScrX * nLayoutSign && nEndY >= nScrY ) + { + aInvert.AddRect( Rectangle( nScrX,nScrY,nEndX,nEndY ) ); + } + } + } + } + else // !bTestMerge + { + if ( rMark.IsCellMarked( nX, nY, sal_True ) == bRepeat && + nEndX * nLayoutSign >= nScrX * nLayoutSign && nEndY >= nScrY ) + { + aInvert.AddRect( Rectangle( nScrX,nScrY,nEndX,nEndY ) ); + } + } + + nScrX = nEndX + nLayoutSign; + } + } + nScrY = nEndY + 1; + } + } + + aInvert.Flush(); // before restoring MapMode + + SetMapMode(aOld); + + CheckInverted(); +} + +void ScGridWindow::GetSelectionRects( ::std::vector< Rectangle >& rPixelRects ) +{ + // transformed from ScGridWindow::InvertSimple + +// ScMarkData& rMark = pViewData->GetMarkData(); + ScMarkData aMultiMark( pViewData->GetMarkData() ); + aMultiMark.SetMarking( sal_False ); + aMultiMark.MarkToMulti(); + + ScDocument* pDoc = pViewData->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + + sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); + long nLayoutSign = bLayoutRTL ? -1 : 1; + + if ( !aMultiMark.IsMultiMarked() ) + return; + + ScRange aMultiRange; + aMultiMark.GetMultiMarkArea( aMultiRange ); + SCCOL nX1 = aMultiRange.aStart.Col(); + SCROW nY1 = aMultiRange.aStart.Row(); + SCCOL nX2 = aMultiRange.aEnd.Col(); + SCROW nY2 = aMultiRange.aEnd.Row(); + + PutInOrder( nX1, nX2 ); + PutInOrder( nY1, nY2 ); + + sal_Bool bTestMerge = sal_True; + sal_Bool bRepeat = sal_True; + + SCCOL nTestX2 = nX2; + SCROW nTestY2 = nY2; + if (bTestMerge) + pDoc->ExtendMerge( nX1,nY1, nTestX2,nTestY2, nTab ); + + SCCOL nPosX = pViewData->GetPosX( eHWhich ); + SCROW nPosY = pViewData->GetPosY( eVWhich ); + if (nTestX2 < nPosX || nTestY2 < nPosY) + return; // unsichtbar + SCCOL nRealX1 = nX1; + if (nX1 < nPosX) + nX1 = nPosX; + if (nY1 < nPosY) + nY1 = nPosY; + + SCCOL nXRight = nPosX + pViewData->VisibleCellsX(eHWhich); + if (nXRight > MAXCOL) nXRight = MAXCOL; + SCROW nYBottom = nPosY + pViewData->VisibleCellsY(eVWhich); + if (nYBottom > MAXROW) nYBottom = MAXROW; + + if (nX1 > nXRight || nY1 > nYBottom) + return; // unsichtbar + if (nX2 > nXRight) nX2 = nXRight; + if (nY2 > nYBottom) nY2 = nYBottom; + +// MapMode aOld = GetMapMode(); SetMapMode(MAP_PIXEL); // erst nach den return's !!! + + double nPPTX = pViewData->GetPPTX(); + double nPPTY = pViewData->GetPPTY(); + + ScInvertMerger aInvert( &rPixelRects ); + + Point aScrPos = pViewData->GetScrPos( nX1, nY1, eWhich ); + long nScrY = aScrPos.Y(); + sal_Bool bWasHidden = sal_False; + for (SCROW nY=nY1; nY<=nY2; nY++) + { + sal_Bool bFirstRow = ( nY == nPosY ); // first visible row? + sal_Bool bDoHidden = sal_False; // versteckte nachholen ? + sal_uInt16 nHeightTwips = pDoc->GetRowHeight( nY,nTab ); + sal_Bool bDoRow = ( nHeightTwips != 0 ); + if (bDoRow) + { + if (bTestMerge) + if (bWasHidden) // auf versteckte zusammengefasste testen + { + bDoHidden = sal_True; + bDoRow = sal_True; + } + + bWasHidden = sal_False; + } + else + { + bWasHidden = sal_True; + if (bTestMerge) + if (nY==nY2) + bDoRow = sal_True; // letzte Zeile aus Block + } + + if ( bDoRow ) + { + SCCOL nLoopEndX = nX2; + if (nX2 < nX1) // Rest von zusammengefasst + { + SCCOL nStartX = nX1; + while ( ((const ScMergeFlagAttr*)pDoc-> + GetAttr(nStartX,nY,nTab,ATTR_MERGE_FLAG))->IsHorOverlapped() ) + --nStartX; + if (nStartX <= nX2) + nLoopEndX = nX1; + } + + long nEndY = nScrY + ScViewData::ToPixel( nHeightTwips, nPPTY ) - 1; + long nScrX = aScrPos.X(); + for (SCCOL nX=nX1; nX<=nLoopEndX; nX++) + { + long nWidth = ScViewData::ToPixel( pDoc->GetColWidth( nX,nTab ), nPPTX ); + if ( nWidth > 0 ) + { + long nEndX = nScrX + ( nWidth - 1 ) * nLayoutSign; + if (bTestMerge) + { + SCROW nThisY = nY; + const ScPatternAttr* pPattern = pDoc->GetPattern( nX, nY, nTab ); + const ScMergeFlagAttr* pMergeFlag = (const ScMergeFlagAttr*) &pPattern-> + GetItem(ATTR_MERGE_FLAG); + if ( pMergeFlag->IsVerOverlapped() && ( bDoHidden || bFirstRow ) ) + { + while ( pMergeFlag->IsVerOverlapped() && nThisY > 0 && + (pDoc->RowHidden(nThisY-1, nTab) || bFirstRow) ) + { + --nThisY; + pPattern = pDoc->GetPattern( nX, nThisY, nTab ); + pMergeFlag = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG); + } + } + + // nur Rest von zusammengefasster zu sehen ? + SCCOL nThisX = nX; + if ( pMergeFlag->IsHorOverlapped() && nX == nPosX && nX > nRealX1 ) + { + while ( pMergeFlag->IsHorOverlapped() ) + { + --nThisX; + pPattern = pDoc->GetPattern( nThisX, nThisY, nTab ); + pMergeFlag = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG); + } + } + + if ( aMultiMark.IsCellMarked( nThisX, nThisY, sal_True ) == bRepeat ) + { + if ( !pMergeFlag->IsOverlapped() ) + { + ScMergeAttr* pMerge = (ScMergeAttr*)&pPattern->GetItem(ATTR_MERGE); + if (pMerge->GetColMerge() > 0 || pMerge->GetRowMerge() > 0) + { + Point aEndPos = pViewData->GetScrPos( + nThisX + pMerge->GetColMerge(), + nThisY + pMerge->GetRowMerge(), eWhich ); + if ( aEndPos.X() * nLayoutSign > nScrX * nLayoutSign && aEndPos.Y() > nScrY ) + { + aInvert.AddRect( Rectangle( nScrX,nScrY, + aEndPos.X()-nLayoutSign,aEndPos.Y()-1 ) ); + } + } + else if ( nEndX * nLayoutSign >= nScrX * nLayoutSign && nEndY >= nScrY ) + { + aInvert.AddRect( Rectangle( nScrX,nScrY,nEndX,nEndY ) ); + } + } + } + } + else // !bTestMerge + { + if ( aMultiMark.IsCellMarked( nX, nY, sal_True ) == bRepeat && + nEndX * nLayoutSign >= nScrX * nLayoutSign && nEndY >= nScrY ) + { + aInvert.AddRect( Rectangle( nScrX,nScrY,nEndX,nEndY ) ); + } + } + + nScrX = nEndX + nLayoutSign; + } + } + nScrY = nEndY + 1; + } + } + +// aInvert.Flush(); // before restoring MapMode +} + +// ------------------------------------------------------------------------- + +//UNUSED2008-05 void ScGridWindow::DrawDragRect( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2 ) +//UNUSED2008-05 { +//UNUSED2008-05 if ( nX2 < pViewData->GetPosX(eHWhich) || nY2 < pViewData->GetPosY(eVWhich) ) +//UNUSED2008-05 return; +//UNUSED2008-05 +//UNUSED2008-05 Update(); // wegen XOR +//UNUSED2008-05 +//UNUSED2008-05 MapMode aOld = GetMapMode(); SetMapMode(MAP_PIXEL); +//UNUSED2008-05 +//UNUSED2008-05 SCTAB nTab = pViewData->GetTabNo(); +//UNUSED2008-05 +//UNUSED2008-05 SCCOL nPosX = pViewData->GetPosX(WhichH(eWhich)); +//UNUSED2008-05 SCROW nPosY = pViewData->GetPosY(WhichV(eWhich)); +//UNUSED2008-05 if (nX1 < nPosX) nX1 = nPosX; +//UNUSED2008-05 if (nX2 < nPosX) nX2 = nPosX; +//UNUSED2008-05 if (nY1 < nPosY) nY1 = nPosY; +//UNUSED2008-05 if (nY2 < nPosY) nY2 = nPosY; +//UNUSED2008-05 +//UNUSED2008-05 Point aScrPos( pViewData->GetScrPos( nX1, nY1, eWhich ) ); +//UNUSED2008-05 +//UNUSED2008-05 long nSizeXPix=0; +//UNUSED2008-05 long nSizeYPix=0; +//UNUSED2008-05 ScDocument* pDoc = pViewData->GetDocument(); +//UNUSED2008-05 double nPPTX = pViewData->GetPPTX(); +//UNUSED2008-05 double nPPTY = pViewData->GetPPTY(); +//UNUSED2008-05 SCCOLROW i; +//UNUSED2008-05 +//UNUSED2008-05 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); +//UNUSED2008-05 long nLayoutSign = bLayoutRTL ? -1 : 1; +//UNUSED2008-05 +//UNUSED2008-05 if (ValidCol(nX2) && nX2>=nX1) +//UNUSED2008-05 for (i=nX1; i<=nX2; i++) +//UNUSED2008-05 nSizeXPix += ScViewData::ToPixel( pDoc->GetColWidth( static_cast<SCCOL>(i), nTab ), nPPTX ); +//UNUSED2008-05 else +//UNUSED2008-05 { +//UNUSED2008-05 aScrPos.X() -= nLayoutSign; +//UNUSED2008-05 nSizeXPix += 2; +//UNUSED2008-05 } +//UNUSED2008-05 +//UNUSED2008-05 if (ValidRow(nY2) && nY2>=nY1) +//UNUSED2008-05 for (i=nY1; i<=nY2; i++) +//UNUSED2008-05 nSizeYPix += ScViewData::ToPixel( pDoc->GetRowHeight( i, nTab ), nPPTY ); +//UNUSED2008-05 else +//UNUSED2008-05 { +//UNUSED2008-05 aScrPos.Y() -= 1; +//UNUSED2008-05 nSizeYPix += 2; +//UNUSED2008-05 } +//UNUSED2008-05 +//UNUSED2008-05 aScrPos.X() -= 2 * nLayoutSign; +//UNUSED2008-05 aScrPos.Y() -= 2; +//UNUSED2008-05 // Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) ); +//UNUSED2008-05 Rectangle aRect( aScrPos.X(), aScrPos.Y(), +//UNUSED2008-05 aScrPos.X() + ( nSizeXPix + 2 ) * nLayoutSign, aScrPos.Y() + nSizeYPix + 2 ); +//UNUSED2008-05 if ( bLayoutRTL ) +//UNUSED2008-05 { +//UNUSED2008-05 aRect.Left() = aRect.Right(); // end position is left +//UNUSED2008-05 aRect.Right() = aScrPos.X(); +//UNUSED2008-05 } +//UNUSED2008-05 +//UNUSED2008-05 Invert(Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() )); +//UNUSED2008-05 Invert(Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() )); +//UNUSED2008-05 Invert(Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 )); +//UNUSED2008-05 Invert(Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() )); +//UNUSED2008-05 +//UNUSED2008-05 SetMapMode(aOld); +//UNUSED2008-05 } + +// ------------------------------------------------------------------------- + +void ScGridWindow::DrawCursor() +{ +// #114409# +// SCTAB nTab = pViewData->GetTabNo(); +// SCCOL nX = pViewData->GetCurX(); +// SCROW nY = pViewData->GetCurY(); +// +// // in verdeckten Zellen nicht zeichnen +// +// ScDocument* pDoc = pViewData->GetDocument(); +// const ScPatternAttr* pPattern = pDoc->GetPattern(nX,nY,nTab); +// const ScMergeFlagAttr& rMerge = (const ScMergeFlagAttr&) pPattern->GetItem(ATTR_MERGE_FLAG); +// if (rMerge.IsOverlapped()) +// return; +// +// // links/oben ausserhalb des Bildschirms ? +// +// sal_Bool bVis = ( nX>=pViewData->GetPosX(eHWhich) && nY>=pViewData->GetPosY(eVWhich) ); +// if (!bVis) +// { +// SCCOL nEndX = nX; +// SCROW nEndY = nY; +// ScDocument* pDoc = pViewData->GetDocument(); +// const ScMergeAttr& rMerge = (const ScMergeAttr&) pPattern->GetItem(ATTR_MERGE); +// if (rMerge.GetColMerge() > 1) +// nEndX += rMerge.GetColMerge()-1; +// if (rMerge.GetRowMerge() > 1) +// nEndY += rMerge.GetRowMerge()-1; +// bVis = ( nEndX>=pViewData->GetPosX(eHWhich) && nEndY>=pViewData->GetPosY(eVWhich) ); +// } +// +// if ( bVis ) +// { +// // hier kein Update, da aus Paint gerufen und laut Zaehler Cursor schon da +// // wenn Update noetig, dann bei Hide/Showcursor vor dem Hoch-/Runterzaehlen +// +// MapMode aOld = GetMapMode(); SetMapMode(MAP_PIXEL); +// +// Point aScrPos = pViewData->GetScrPos( nX, nY, eWhich, sal_True ); +// sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); +// +// // completely right of/below the screen? +// // (test with logical start position in aScrPos) +// sal_Bool bMaybeVisible; +// if ( bLayoutRTL ) +// bMaybeVisible = ( aScrPos.X() >= -2 && aScrPos.Y() >= -2 ); +// else +// { +// Size aOutSize = GetOutputSizePixel(); +// bMaybeVisible = ( aScrPos.X() <= aOutSize.Width() + 2 && aScrPos.Y() <= aOutSize.Height() + 2 ); +// } +// if ( bMaybeVisible ) +// { +// long nSizeXPix; +// long nSizeYPix; +// pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix ); +// +// if ( bLayoutRTL ) +// aScrPos.X() -= nSizeXPix - 2; // move instead of mirroring +// +// sal_Bool bFix = ( pViewData->GetHSplitMode() == SC_SPLIT_FIX || +// pViewData->GetVSplitMode() == SC_SPLIT_FIX ); +// if ( pViewData->GetActivePart()==eWhich || bFix ) +// { +// // old UNX version with two Invert calls causes flicker. +// // if optimization is needed, a new flag should be added +// // to InvertTracking +// +// aScrPos.X() -= 2; +// aScrPos.Y() -= 2; +// Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) ); +// +// Invert(Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() )); +// Invert(Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() )); +// Invert(Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 )); +// Invert(Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() )); +// } +// else +// { +// Rectangle aRect( aScrPos, Size( nSizeXPix - 1, nSizeYPix - 1 ) ); +// Invert( aRect ); +// } +// } +// +// SetMapMode(aOld); +// } +} + + // AutoFill-Anfasser: + +void ScGridWindow::DrawAutoFillMark() +{ +// #114409# +// if ( bAutoMarkVisible && aAutoMarkPos.Tab() == pViewData->GetTabNo() ) +// { +// SCCOL nX = aAutoMarkPos.Col(); +// SCROW nY = aAutoMarkPos.Row(); +// SCTAB nTab = pViewData->GetTabNo(); +// ScDocument* pDoc = pViewData->GetDocument(); +// sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); +// +// Point aFillPos = pViewData->GetScrPos( nX, nY, eWhich, sal_True ); +// long nSizeXPix; +// long nSizeYPix; +// pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix ); +// if ( bLayoutRTL ) +// aFillPos.X() -= nSizeXPix + 3; +// else +// aFillPos.X() += nSizeXPix - 2; +// +// aFillPos.Y() += nSizeYPix; +// aFillPos.Y() -= 2; +// Rectangle aFillRect( aFillPos, Size(6,6) ); +// // Anfasser von Zeichenobjekten sind 7*7 +// +// MapMode aOld = GetMapMode(); SetMapMode(MAP_PIXEL); +// Invert( aFillRect ); +// SetMapMode(aOld); +// } +} + +// ------------------------------------------------------------------------- + +void ScGridWindow::DataChanged( const DataChangedEvent& rDCEvt ) +{ + Window::DataChanged(rDCEvt); + + if ( (rDCEvt.GetType() == DATACHANGED_PRINTER) || + (rDCEvt.GetType() == DATACHANGED_DISPLAY) || + (rDCEvt.GetType() == DATACHANGED_FONTS) || + (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) || + ((rDCEvt.GetType() == DATACHANGED_SETTINGS) && + (rDCEvt.GetFlags() & SETTINGS_STYLE)) ) + { + if ( rDCEvt.GetType() == DATACHANGED_FONTS && eWhich == pViewData->GetActivePart() ) + pViewData->GetDocShell()->UpdateFontList(); + + if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && + (rDCEvt.GetFlags() & SETTINGS_STYLE) ) + { + if ( eWhich == pViewData->GetActivePart() ) // only once for the view + { + ScTabView* pView = pViewData->GetView(); + + // update scale in case the UI ScreenZoom has changed + ScGlobal::UpdatePPT(this); + pView->RecalcPPT(); + + // RepeatResize in case scroll bar sizes have changed + pView->RepeatResize(); + pView->UpdateAllOverlays(); + + // invalidate cell attribs in input handler, in case the + // EditEngine BackgroundColor has to be changed + if ( pViewData->IsActive() ) + { + ScInputHandler* pHdl = SC_MOD()->GetInputHdl(); + if (pHdl) + pHdl->ForgetLastPattern(); + } + } + } + + Invalidate(); + } +} + + + + diff --git a/sc/source/ui/view/gridwin5.cxx b/sc/source/ui/view/gridwin5.cxx new file mode 100644 index 000000000000..06e0e7f02f0e --- /dev/null +++ b/sc/source/ui/view/gridwin5.cxx @@ -0,0 +1,439 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +// INCLUDE --------------------------------------------------------------- + +#include <editeng/eeitem.hxx> + +#include <editeng/flditem.hxx> + +#include <editeng/editview.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdpagv.hxx> +#include <svtools/imapobj.hxx> +#include <vcl/cursor.hxx> +#include <vcl/help.hxx> +#include <tools/urlobj.hxx> +#include <sfx2/viewfrm.hxx> + +#include <unotools/localedatawrapper.hxx> + +#include "viewuno.hxx" +#include "AccessibleDocument.hxx" +#include <com/sun/star/accessibility/XAccessible.hpp> + +#include "gridwin.hxx" +#include "viewdata.hxx" +#include "drawview.hxx" +#include "drwlayer.hxx" +#include "drawpage.hxx" +#include "document.hxx" +#include "notemark.hxx" +#include "chgtrack.hxx" +#include "chgviset.hxx" +#include "dbfunc.hxx" +#include "tabvwsh.hxx" +#include "userdat.hxx" +#include "postit.hxx" + +// ----------------------------------------------------------------------- + +ScHideTextCursor::ScHideTextCursor( ScViewData* pData, ScSplitPos eW ) : + pViewData(pData), + eWhich(eW) +{ + Window* pWin = pViewData->GetView()->GetWindowByPos( eWhich ); + if (pWin) + { + Cursor* pCur = pWin->GetCursor(); + if ( pCur && pCur->IsVisible() ) + pCur->Hide(); + } +} + +ScHideTextCursor::~ScHideTextCursor() +{ + Window* pWin = pViewData->GetView()->GetWindowByPos( eWhich ); + if (pWin) + { + // restore text cursor + if ( pViewData->HasEditView(eWhich) && pWin->HasFocus() ) + pViewData->GetEditView(eWhich)->ShowCursor( sal_False, sal_True ); + } +} + +// ----------------------------------------------------------------------- + +sal_Bool ScGridWindow::ShowNoteMarker( SCsCOL nPosX, SCsROW nPosY, sal_Bool bKeyboard ) +{ + sal_Bool bDone = sal_False; + + ScDocument* pDoc = pViewData->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + ScAddress aCellPos( nPosX, nPosY, nTab ); + + String aTrackText; + sal_Bool bLeftEdge = sal_False; + + // Change-Tracking + + ScChangeTrack* pTrack = pDoc->GetChangeTrack(); + ScChangeViewSettings* pSettings = pDoc->GetChangeViewSettings(); + if ( pTrack && pTrack->GetFirst() && pSettings && pSettings->ShowChanges()) + { + const ScChangeAction* pFound = NULL; + const ScChangeAction* pFoundContent = NULL; + const ScChangeAction* pFoundMove = NULL; + long nModified = 0; + const ScChangeAction* pAction = pTrack->GetFirst(); + while (pAction) + { + if ( pAction->IsVisible() && + ScViewUtil::IsActionShown( *pAction, *pSettings, *pDoc ) ) + { + ScChangeActionType eType = pAction->GetType(); + const ScBigRange& rBig = pAction->GetBigRange(); + if ( rBig.aStart.Tab() == nTab ) + { + ScRange aRange = rBig.MakeRange(); + + if ( eType == SC_CAT_DELETE_ROWS ) + aRange.aEnd.SetRow( aRange.aStart.Row() ); + else if ( eType == SC_CAT_DELETE_COLS ) + aRange.aEnd.SetCol( aRange.aStart.Col() ); + + if ( aRange.In( aCellPos ) ) + { + pFound = pAction; // der letzte gewinnt + switch ( eType ) + { + case SC_CAT_CONTENT : + pFoundContent = pAction; + break; + case SC_CAT_MOVE : + pFoundMove = pAction; + break; + default: + { + // added to avoid warnings + } + } + ++nModified; + } + } + if ( eType == SC_CAT_MOVE ) + { + ScRange aRange = + ((const ScChangeActionMove*)pAction)-> + GetFromRange().MakeRange(); + if ( aRange.In( aCellPos ) ) + { + pFound = pAction; + ++nModified; + } + } + } + pAction = pAction->GetNext(); + } + + if ( pFound ) + { + if ( pFoundContent && pFound->GetType() != SC_CAT_CONTENT ) + pFound = pFoundContent; // Content gewinnt + if ( pFoundMove && pFound->GetType() != SC_CAT_MOVE && + pFoundMove->GetActionNumber() > + pFound->GetActionNumber() ) + pFound = pFoundMove; // Move gewinnt + + // bei geloeschten Spalten: Pfeil auf die linke Seite der Zelle + if ( pFound->GetType() == SC_CAT_DELETE_COLS ) + bLeftEdge = sal_True; + + DateTime aDT = pFound->GetDateTime(); + aTrackText = pFound->GetUser(); + aTrackText.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ", " )); + aTrackText += ScGlobal::pLocaleData->getDate(aDT); + aTrackText += ' '; + aTrackText += ScGlobal::pLocaleData->getTime(aDT); + aTrackText.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ":\n" )); + String aComStr=pFound->GetComment(); + if(aComStr.Len()>0) + { + aTrackText += aComStr; + aTrackText.AppendAscii(RTL_CONSTASCII_STRINGPARAM( "\n( " )); + } + pFound->GetDescription( aTrackText, pDoc ); + if(aComStr.Len()>0) + { + aTrackText +=')'; + } + } + } + + // Notiz nur, wenn sie nicht schon auf dem Drawing-Layer angezeigt wird: + const ScPostIt* pNote = pDoc->GetNote( aCellPos ); + if ( (aTrackText.Len() > 0) || (pNote && !pNote->IsCaptionShown()) ) + { + sal_Bool bNew = sal_True; + sal_Bool bFast = sal_False; + if ( pNoteMarker ) // schon eine Notiz angezeigt + { + if ( pNoteMarker->GetDocPos() == aCellPos ) // dieselbe + bNew = sal_False; // dann stehenlassen + else + bFast = sal_True; // sonst sofort + + // marker which was shown for ctrl-F1 isn't removed by mouse events + if ( pNoteMarker->IsByKeyboard() && !bKeyboard ) + bNew = sal_False; + } + if ( bNew ) + { + if ( bKeyboard ) + bFast = sal_True; // keyboard also shows the marker immediately + + delete pNoteMarker; + + bool bHSplit = pViewData->GetHSplitMode() != SC_SPLIT_NONE; + bool bVSplit = pViewData->GetVSplitMode() != SC_SPLIT_NONE; + + Window* pLeft = pViewData->GetView()->GetWindowByPos( bVSplit ? SC_SPLIT_TOPLEFT : SC_SPLIT_BOTTOMLEFT ); + Window* pRight = bHSplit ? pViewData->GetView()->GetWindowByPos( bVSplit ? SC_SPLIT_TOPRIGHT : SC_SPLIT_BOTTOMRIGHT ) : 0; + Window* pBottom = bVSplit ? pViewData->GetView()->GetWindowByPos( SC_SPLIT_BOTTOMLEFT ) : 0; + Window* pDiagonal = (bHSplit && bVSplit) ? pViewData->GetView()->GetWindowByPos( SC_SPLIT_BOTTOMRIGHT ) : 0; + DBG_ASSERT( pLeft, "ScGridWindow::ShowNoteMarker - missing top-left grid window" ); + + /* If caption is shown from right or bottom windows, adjust + mapmode to include size of top-left window. */ + MapMode aMapMode = GetDrawMapMode( sal_True ); + Size aLeftSize = pLeft->PixelToLogic( pLeft->GetOutputSizePixel(), aMapMode ); + Point aOrigin = aMapMode.GetOrigin(); + if( (this == pRight) || (this == pDiagonal) ) + aOrigin.X() += aLeftSize.Width(); + if( (this == pBottom) || (this == pDiagonal) ) + aOrigin.Y() += aLeftSize.Height(); + aMapMode.SetOrigin( aOrigin ); + + pNoteMarker = new ScNoteMarker( pLeft, pRight, pBottom, pDiagonal, + pDoc, aCellPos, aTrackText, + aMapMode, bLeftEdge, bFast, bKeyboard ); + } + + bDone = sal_True; // something is shown (old or new) + } + + return bDone; +} + +// ----------------------------------------------------------------------- + +void ScGridWindow::RequestHelp(const HelpEvent& rHEvt) +{ + sal_Bool bDone = sal_False; + sal_Bool bHelpEnabled = ( rHEvt.GetMode() & ( HELPMODE_BALLOON | HELPMODE_QUICK ) ) != 0; + SdrView* pDrView = pViewData->GetScDrawView(); + + sal_Bool bDrawTextEdit = sal_False; + if (pDrView) + bDrawTextEdit = pDrView->IsTextEdit(); + + // notes or change tracking + + if ( bHelpEnabled && !bDrawTextEdit ) + { + Point aPosPixel = ScreenToOutputPixel( rHEvt.GetMousePosPixel() ); + SCsCOL nPosX; + SCsROW nPosY; + pViewData->GetPosFromPixel( aPosPixel.X(), aPosPixel.Y(), eWhich, nPosX, nPosY ); + + if ( ShowNoteMarker( nPosX, nPosY, sal_False ) ) + { + Window::RequestHelp( rHEvt ); // alte Tip/Balloon ausschalten + bDone = sal_True; + } + } + + if ( !bDone && pNoteMarker ) + { + if ( pNoteMarker->IsByKeyboard() ) + { + // marker which was shown for ctrl-F1 isn't removed by mouse events + } + else + DELETEZ(pNoteMarker); + } + + // Image-Map / Text-URL + + if ( bHelpEnabled && !bDone && !nButtonDown ) // nur ohne gedrueckten Button + { + String aHelpText; + Rectangle aPixRect; + Point aPosPixel = ScreenToOutputPixel( rHEvt.GetMousePosPixel() ); + + if ( pDrView ) // URL / Image-Map + { + SdrViewEvent aVEvt; + MouseEvent aMEvt( aPosPixel, 1, 0, MOUSE_LEFT ); + SdrHitKind eHit = pDrView->PickAnything( aMEvt, SDRMOUSEBUTTONDOWN, aVEvt ); + + if ( eHit != SDRHIT_NONE && aVEvt.pObj != NULL ) + { + // URL fuer IMapObject unter Pointer ist Hilfetext + if ( ScDrawLayer::GetIMapInfo( aVEvt.pObj ) ) + { + Point aLogicPos = PixelToLogic( aPosPixel ); + IMapObject* pIMapObj = ScDrawLayer::GetHitIMapObject( + aVEvt.pObj, aLogicPos, *this ); + + if ( pIMapObj ) + { + // #44990# Bei ImageMaps die Description anzeigen, wenn vorhanden + aHelpText = pIMapObj->GetAltText(); + if (!aHelpText.Len()) + aHelpText = pIMapObj->GetURL(); + aPixRect = LogicToPixel(aVEvt.pObj->GetLogicRect()); + } + } + // URL in shape text or at shape itself (URL in text overrides object URL) + if ( aHelpText.Len() == 0 ) + { + if( aVEvt.eEvent == SDREVENT_EXECUTEURL ) + { + aHelpText = aVEvt.pURLField->GetURL(); + aPixRect = LogicToPixel(aVEvt.pObj->GetLogicRect()); + } + else + { + SdrObject* pObj = 0; + SdrPageView* pPV = 0; + Point aMDPos = PixelToLogic( aPosPixel ); + if ( pDrView->PickObj(aMDPos, pDrView->getHitTolLog(), pObj, pPV, SDRSEARCH_ALSOONMASTER) ) + { + if ( pObj->IsGroupObject() ) + { + SdrObject* pHit = 0; + if ( pDrView->PickObj(aMDPos, pDrView->getHitTolLog(), pHit, pPV, SDRSEARCH_DEEP ) ) + pObj = pHit; + } +#ifdef ISSUE66550_HLINK_FOR_SHAPES + ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( pObj ); + if ( pInfo && (pInfo->GetHlink().getLength() > 0) ) + { + aPixRect = LogicToPixel(aVEvt.pObj->GetLogicRect()); + aHelpText = pInfo->GetHlink(); + } +#endif + } + } + } + } + } + + if ( !aHelpText.Len() ) // Text-URL + { + String aUrl; + if ( GetEditUrl( aPosPixel, NULL, &aUrl, NULL ) ) + { + aHelpText = INetURLObject::decode( aUrl, INET_HEX_ESCAPE, + INetURLObject::DECODE_UNAMBIGUOUS ); + + ScDocument* pDoc = pViewData->GetDocument(); + SCsCOL nPosX; + SCsROW nPosY; + SCTAB nTab = pViewData->GetTabNo(); + pViewData->GetPosFromPixel( aPosPixel.X(), aPosPixel.Y(), eWhich, nPosX, nPosY ); + const ScPatternAttr* pPattern = pDoc->GetPattern( nPosX, nPosY, nTab ); + + ScHideTextCursor aHideCursor( pViewData, eWhich ); // MapMode is changed in GetEditArea + + // bForceToTop = sal_False, use the cell's real position + aPixRect = pViewData->GetEditArea( eWhich, nPosX, nPosY, this, pPattern, sal_False ); + } + } + + if ( aHelpText.Len() ) + { + Rectangle aScreenRect(OutputToScreenPixel(aPixRect.TopLeft()), + OutputToScreenPixel(aPixRect.BottomRight())); + + if ( rHEvt.GetMode() & HELPMODE_BALLOON ) + Help::ShowBalloon(this,rHEvt.GetMousePosPixel(), aScreenRect, aHelpText); + else if ( rHEvt.GetMode() & HELPMODE_QUICK ) + Help::ShowQuickHelp(this,aScreenRect, aHelpText); + + bDone = sal_True; + } + } + + // Basic-Controls + + if ( pDrView && bHelpEnabled && !bDone ) + { + SdrPageView* pPV = pDrView->GetSdrPageView(); + DBG_ASSERT( pPV, "SdrPageView* ist NULL" ); + if (pPV) + bDone = ((ScDrawPage*)pPV->GetPage())->RequestHelp( this, pDrView, rHEvt ); + } + + // Wenn QuickHelp fuer AutoFill angezeigt wird, nicht wieder wegnehmen lassen + + if ( nMouseStatus == SC_GM_TABDOWN && pViewData->GetRefType() == SC_REFTYPE_FILL && + Help::IsQuickHelpEnabled() ) + bDone = sal_True; + + if (!bDone) + Window::RequestHelp( rHEvt ); +} + +sal_Bool ScGridWindow::IsMyModel(SdrEditView* pSdrView) +{ + return pSdrView && + pSdrView->GetModel() == pViewData->GetDocument()->GetDrawLayer(); +} + +void ScGridWindow::HideNoteMarker() +{ + DELETEZ(pNoteMarker); +} + +com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > + ScGridWindow::CreateAccessible() +{ + ScAccessibleDocument* pAccessibleDocument = + new ScAccessibleDocument(GetAccessibleParentWindow()->GetAccessible(), + pViewData->GetViewShell(), eWhich); + + com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessible > xAccessible = pAccessibleDocument; + + pAccessibleDocument->Init(); + + return xAccessible; +} diff --git a/sc/source/ui/view/hdrcont.cxx b/sc/source/ui/view/hdrcont.cxx new file mode 100644 index 000000000000..a3f30ba7ba59 --- /dev/null +++ b/sc/source/ui/view/hdrcont.cxx @@ -0,0 +1,1046 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include <sfx2/dispatch.hxx> +#include <vcl/help.hxx> +#include <tools/poly.hxx> +#include <svtools/colorcfg.hxx> + +#include "scresid.hxx" +#include "sc.hrc" +#include "tabvwsh.hxx" +#include "hdrcont.hxx" +#include "scmod.hxx" // Optionen +#include "inputopt.hxx" // Optionen +#include "gridmerg.hxx" +#include "document.hxx" + +// ----------------------------------------------------------------------- + +#define SC_DRAG_MIN 2 + +// passes in paint +// (selection left/right must be first because the continuous lines +// are partly overwritten later) + +#define SC_HDRPAINT_SEL_RIGHT 0 +#define SC_HDRPAINT_SEL_LEFT 1 +#define SC_HDRPAINT_TOP 2 +#define SC_HDRPAINT_SEL_TOP 3 +#define SC_HDRPAINT_SEL_BOTTOM 4 +#define SC_HDRPAINT_BOTTOM 5 +#define SC_HDRPAINT_TEXT 6 +#define SC_HDRPAINT_COUNT 7 + +//================================================================== + +ScHeaderControl::ScHeaderControl( Window* pParent, SelectionEngine* pSelectionEngine, + SCCOLROW nNewSize, sal_uInt16 nNewFlags ) : + Window ( pParent ), + pSelEngine ( pSelectionEngine ), + nFlags ( nNewFlags ), + bVertical ( (nNewFlags & HDR_VERTICAL) != 0 ), + nSize ( nNewSize ), + nMarkStart ( 0 ), + nMarkEnd ( 0 ), + bMarkRange ( sal_False ), + bDragging ( sal_False ), + bIgnoreMove ( sal_False ) +{ + // --- RTL --- no default mirroring for this window, the spreadsheet itself + // is also not mirrored + // #107811# mirror the vertical window for correct border drawing + // #106948# table layout depends on sheet format, not UI setting, so the + // borders of the vertical window have to be handled manually, too. + EnableRTL( sal_False ); + + aNormFont = GetFont(); + aNormFont.SetTransparent( sal_True ); //! WEIGHT_NORMAL hart setzen ??? + aBoldFont = aNormFont; + aBoldFont.SetWeight( WEIGHT_BOLD ); + + SetFont(aBoldFont); + bBoldSet = sal_True; + + Size aSize = LogicToPixel( Size( + GetTextWidth( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("8888")) ), + GetTextHeight() ) ); + aSize.Width() += 4; // Platz fuer hervorgehobene Umrandung + aSize.Height() += 3; + SetSizePixel( aSize ); + + nWidth = nSmallWidth = aSize.Width(); + nBigWidth = LogicToPixel( Size( GetTextWidth( + String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("8888888")) ), 0 ) ).Width() + 5; + + SetBackground(); // sonst Probleme auf OS/2 !?!?! +} + +void ScHeaderControl::SetWidth( long nNew ) +{ + DBG_ASSERT( bVertical, "SetDigits nur fuer Zeilenkoepfe erlaubt" ); + if ( nNew != nWidth ) + { + Size aSize( nNew, GetSizePixel().Height() ); // Hoehe nicht aendern + SetSizePixel( aSize ); + + nWidth = nNew; + + Invalidate(); // neu zentrieren + } +} + +ScHeaderControl::~ScHeaderControl() +{ +} + +void ScHeaderControl::DoPaint( SCCOLROW nStart, SCCOLROW nEnd ) +{ + sal_Bool bLayoutRTL = IsLayoutRTL(); + long nLayoutSign = bLayoutRTL ? -1 : 1; + + Rectangle aRect( Point(0,0), GetOutputSizePixel() ); + if ( bVertical ) + { + aRect.Top() = GetScrPos( nStart )-nLayoutSign; // extra pixel for line at top of selection + aRect.Bottom() = GetScrPos( nEnd+1 )-nLayoutSign; + } + else + { + aRect.Left() = GetScrPos( nStart )-nLayoutSign; // extra pixel for line left of selection + aRect.Right() = GetScrPos( nEnd+1 )-nLayoutSign; + } + Invalidate(aRect); +} + +void ScHeaderControl::SetMark( sal_Bool bNewSet, SCCOLROW nNewStart, SCCOLROW nNewEnd ) +{ + sal_Bool bEnabled = SC_MOD()->GetInputOptions().GetMarkHeader(); //! cachen? + if (!bEnabled) + bNewSet = sal_False; + + // Variablen setzen + + sal_Bool bOldSet = bMarkRange; + SCCOLROW nOldStart = nMarkStart; + SCCOLROW nOldEnd = nMarkEnd; + PutInOrder( nNewStart, nNewEnd ); + bMarkRange = bNewSet; + nMarkStart = nNewStart; + nMarkEnd = nNewEnd; + + // Paint + + if ( bNewSet ) + { + if ( bOldSet ) + { + if ( nNewStart == nOldStart ) + { + if ( nNewEnd != nOldEnd ) + DoPaint( Min( nNewEnd, nOldEnd ) + 1, Max( nNewEnd, nOldEnd ) ); + // sonst nix + } + else if ( nNewEnd == nOldEnd ) + DoPaint( Min( nNewStart, nOldStart ), Max( nNewStart, nOldStart ) - 1 ); + else if ( nNewStart > nOldEnd || nNewEnd < nOldStart ) + { + // zwei Bereiche... + DoPaint( nOldStart, nOldEnd ); + DoPaint( nNewStart, nNewEnd ); + } + else // irgendwie ueberlappend... (kommt eh nicht oft vor) + DoPaint( Min( nNewStart, nOldStart ), Max( nNewEnd, nOldEnd ) ); + } + else + DoPaint( nNewStart, nNewEnd ); // komplett neu + } + else if ( bOldSet ) + DoPaint( nOldStart, nOldEnd ); // komplett aufheben + + // sonst war nix, is nix +} + +long ScHeaderControl::GetScrPos( SCCOLROW nEntryNo ) +{ + long nScrPos; + + long nMax = ( bVertical ? GetOutputSizePixel().Height() : GetOutputSizePixel().Width() ) + 1; + if (nEntryNo >= nSize) + nScrPos = nMax; + else + { + nScrPos = 0; + for (SCCOLROW i=GetPos(); i<nEntryNo && nScrPos<nMax; i++) + { + sal_uInt16 nAdd = GetEntrySize(i); + if (nAdd) + nScrPos += nAdd; + else + { + SCCOLROW nHidden = GetHiddenCount(i); + if (nHidden > 0) + i += nHidden - 1; + } + } + } + + if ( IsLayoutRTL() ) + nScrPos = nMax - nScrPos - 2; + + return nScrPos; +} + +// draw a rectangle across the window's width/height, with the outer part in a lighter color + +void ScHeaderControl::DrawShadedRect( long nStart, long nEnd, const Color& rBaseColor ) +{ + Color aWhite( COL_WHITE ); + + Color aInner( rBaseColor ); // highlight color, unchanged + Color aCenter( rBaseColor ); + aCenter.Merge( aWhite, 0xd0 ); // lighten up a bit + Color aOuter( rBaseColor ); + aOuter.Merge( aWhite, 0xa0 ); // lighten up more + + if ( IsMirrored() ) + std::swap( aInner, aOuter ); // just swap colors instead of positions + + Size aWinSize = GetSizePixel(); + long nBarSize = bVertical ? aWinSize.Width() : aWinSize.Height(); + long nCenterPos = (nBarSize / 2) - 1; + + SetLineColor(); + SetFillColor( aOuter ); + if (bVertical) + DrawRect( Rectangle( 0, nStart, nCenterPos-1, nEnd ) ); + else + DrawRect( Rectangle( nStart, 0, nEnd, nCenterPos-1 ) ); + SetFillColor( aCenter ); + if (bVertical) + DrawRect( Rectangle( nCenterPos, nStart, nCenterPos, nEnd ) ); + else + DrawRect( Rectangle( nStart, nCenterPos, nEnd, nCenterPos ) ); + SetFillColor( aInner ); + if (bVertical) + DrawRect( Rectangle( nCenterPos+1, nStart, nBarSize-1, nEnd ) ); + else + DrawRect( Rectangle( nStart, nCenterPos+1, nEnd, nBarSize-1 ) ); +} + +// +// Paint +// + +void ScHeaderControl::Paint( const Rectangle& rRect ) +{ + // fuer VCL ist es wichtig, wenig Aufrufe zu haben, darum werden die aeusseren + // Linien zusammengefasst + + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + sal_Bool bHighContrast = rStyleSettings.GetHighContrastMode(); + sal_Bool bDark = rStyleSettings.GetFaceColor().IsDark(); + // Use the same distinction for bDark as in Window::DrawSelectionBackground + + Color aTextColor = rStyleSettings.GetButtonTextColor(); + Color aSelTextColor = rStyleSettings.GetHighlightTextColor(); + aNormFont.SetColor( aTextColor ); + if ( bHighContrast ) + aBoldFont.SetColor( aTextColor ); + else + aBoldFont.SetColor( aSelTextColor ); + SetTextColor( ( bBoldSet && !bHighContrast ) ? aSelTextColor : aTextColor ); + + Color aBlack( COL_BLACK ); + Color aSelLineColor = rStyleSettings.GetHighlightColor(); + aSelLineColor.Merge( aBlack, 0xe0 ); // darken just a little bit + + sal_Bool bLayoutRTL = IsLayoutRTL(); + long nLayoutSign = bLayoutRTL ? -1 : 1; + sal_Bool bMirrored = IsMirrored(); + +// const FunctionSet* pFuncSet = pSelEngine->GetFunctionSet(); + String aString; + sal_uInt16 nBarSize; + Point aScrPos; + Size aTextSize; +// Size aSize = GetOutputSizePixel(); + + if (bVertical) + nBarSize = (sal_uInt16) GetSizePixel().Width(); + else + nBarSize = (sal_uInt16) GetSizePixel().Height(); + + SCCOLROW nPos = GetPos(); + + long nPStart = bVertical ? rRect.Top() : rRect.Left(); + long nPEnd = bVertical ? rRect.Bottom() : rRect.Right(); + + long nTransStart = nPEnd + 1; + long nTransEnd = 0; + + long nInitScrPos = 0; + if ( bLayoutRTL ) + { + long nTemp = nPStart; // swap nPStart / nPEnd + nPStart = nPEnd; + nPEnd = nTemp; + nTemp = nTransStart; // swap nTransStart / nTransEnd + nTransStart = nTransEnd; + nTransEnd = nTemp; + if ( bVertical ) // start loops from the end + nInitScrPos = GetSizePixel().Height() - 1; + else + nInitScrPos = GetSizePixel().Width() - 1; + } + + // aeussere Linien komplett durchzeichnen + // Zuerst Ende der letzten Zelle finden + +// long nLineEnd = -1; + long nLineEnd = nInitScrPos - nLayoutSign; + + for (SCCOLROW i=nPos; i<nSize; i++) + { + sal_uInt16 nSizePix = GetEntrySize( i ); + if (nSizePix) + { + nLineEnd += nSizePix * nLayoutSign; + + if ( bMarkRange && i >= nMarkStart && i <= nMarkEnd ) + { + long nLineStart = nLineEnd - ( nSizePix - 1 ) * nLayoutSign; + if ( nLineStart * nLayoutSign < nTransStart * nLayoutSign ) + nTransStart = nLineStart; + if ( nLineEnd * nLayoutSign > nTransEnd * nLayoutSign ) + nTransEnd = nLineEnd; + } + + if ( nLineEnd * nLayoutSign > nPEnd * nLayoutSign ) + { + nLineEnd = nPEnd; + break; + } + } + else + { + SCCOLROW nHidden = GetHiddenCount(i); + if (nHidden > 0) + i += nHidden - 1; + } + } + + // background is different for entry area and behind the entries + + Rectangle aFillRect; + SetLineColor(); + + if ( nLineEnd * nLayoutSign >= nInitScrPos * nLayoutSign ) + { + if ( bHighContrast ) + { + // high contrast: single-color background + SetFillColor( rStyleSettings.GetFaceColor() ); + if ( bVertical ) + aFillRect = Rectangle( 0, nInitScrPos, nBarSize-1, nLineEnd ); + else + aFillRect = Rectangle( nInitScrPos, 0, nLineEnd, nBarSize-1 ); + DrawRect( aFillRect ); + } + else + { + // normal: 3-part background + DrawShadedRect( nInitScrPos, nLineEnd, rStyleSettings.GetFaceColor() ); + } + } + + if ( nLineEnd * nLayoutSign < nPEnd * nLayoutSign ) + { + SetFillColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::APPBACKGROUND).nColor ); + if ( bVertical ) + aFillRect = Rectangle( 0, nLineEnd+nLayoutSign, nBarSize-1, nPEnd ); + else + aFillRect = Rectangle( nLineEnd+nLayoutSign, 0, nPEnd, nBarSize-1 ); + DrawRect( aFillRect ); + } + + if ( nLineEnd * nLayoutSign >= nPStart * nLayoutSign ) + { + if ( nTransEnd * nLayoutSign >= nTransStart * nLayoutSign ) + { + if ( bHighContrast ) + { + if ( bDark ) + { + // solid grey background for dark face color is drawn before lines + + SetLineColor(); + SetFillColor( COL_LIGHTGRAY ); + if (bVertical) + DrawRect( Rectangle( 0, nTransStart, nBarSize-1, nTransEnd ) ); + else + DrawRect( Rectangle( nTransStart, 0, nTransEnd, nBarSize-1 ) ); + } + } + else + { + // background for selection + + DrawShadedRect( nTransStart, nTransEnd, rStyleSettings.GetHighlightColor() ); + } + } + +#if 0 + // 3D border is no longer used + SetLineColor( rStyleSettings.GetLightColor() ); + if (bVertical) + DrawLine( Point( 0, nPStart ), Point( 0, nLineEnd ) ); + else + DrawLine( Point( nPStart, 0 ), Point( nLineEnd, 0 ) ); +#endif + + SetLineColor( rStyleSettings.GetDarkShadowColor() ); + if (bVertical) + { + long nDarkPos = bMirrored ? 0 : nBarSize-1; + DrawLine( Point( nDarkPos, nPStart ), Point( nDarkPos, nLineEnd ) ); + } + else + DrawLine( Point( nPStart, nBarSize-1 ), Point( nLineEnd, nBarSize-1 ) ); + + // line in different color for selection + if ( nTransEnd * nLayoutSign >= nTransStart * nLayoutSign && !bHighContrast ) + { + SetLineColor( aSelLineColor ); + if (bVertical) + { + long nDarkPos = bMirrored ? 0 : nBarSize-1; + DrawLine( Point( nDarkPos, nTransStart ), Point( nDarkPos, nTransEnd ) ); + } + else + DrawLine( Point( nTransStart, nBarSize-1 ), Point( nTransEnd, nBarSize-1 ) ); + } + } + + // + // loop through entries several times to avoid changing the line color too often + // and to allow merging of lines + // + + ScGridMerger aGrid( this, 1, 1 ); + + // start at SC_HDRPAINT_BOTTOM instead of 0 - selection doesn't get different + // borders, light border at top isn't used anymore + // use SC_HDRPAINT_SEL_BOTTOM for different color + + for (sal_uInt16 nPass = SC_HDRPAINT_SEL_BOTTOM; nPass < SC_HDRPAINT_COUNT; nPass++) + { + // set line color etc. before entry loop + switch ( nPass ) + { + case SC_HDRPAINT_SEL_BOTTOM: + // same as non-selected for high contrast + SetLineColor( bHighContrast ? rStyleSettings.GetDarkShadowColor() : aSelLineColor ); + break; + case SC_HDRPAINT_BOTTOM: + SetLineColor( rStyleSettings.GetDarkShadowColor() ); + break; + case SC_HDRPAINT_TEXT: + // DrawSelectionBackground is used only for high contrast on light background + if ( nTransEnd * nLayoutSign >= nTransStart * nLayoutSign && bHighContrast && !bDark ) + { + // Transparent selection background is drawn after lines, before text. + // #109814# Use DrawSelectionBackground to make sure there is a visible + // difference. The case of a dark face color, where DrawSelectionBackground + // would just paint over the lines, is handled separately (bDark). + // Otherwise, GetHighlightColor is used with 80% transparency. + // The window's background color (SetBackground) has to be the background + // of the cell area, for the contrast comparison in DrawSelectionBackground. + + Rectangle aTransRect; + if (bVertical) + aTransRect = Rectangle( 0, nTransStart, nBarSize-1, nTransEnd ); + else + aTransRect = Rectangle( nTransStart, 0, nTransEnd, nBarSize-1 ); + SetBackground( Color( rStyleSettings.GetFaceColor() ) ); + DrawSelectionBackground( aTransRect, 0, sal_True, sal_False, sal_False ); + SetBackground(); + } + break; + } + + SCCOLROW nCount=0; + long nScrPos=nInitScrPos; + do + { + if (bVertical) + aScrPos = Point( 0, nScrPos ); + else + aScrPos = Point( nScrPos, 0 ); + + SCCOLROW nEntryNo = nCount + nPos; + if ( nEntryNo >= nSize ) // MAXCOL/MAXROW + nScrPos = nPEnd + nLayoutSign; // beyond nPEnd -> stop + else + { + sal_uInt16 nSizePix = GetEntrySize( nEntryNo ); + + if (nSizePix == 0) + { + SCCOLROW nHidden = GetHiddenCount(nEntryNo); + if (nHidden > 0) + nCount += nHidden - 1; + } + else if ((nScrPos+nSizePix*nLayoutSign)*nLayoutSign >= nPStart*nLayoutSign) + { + Point aEndPos(aScrPos); + if (bVertical) + aEndPos = Point( aScrPos.X()+nBarSize-1, aScrPos.Y()+(nSizePix-1)*nLayoutSign ); + else + aEndPos = Point( aScrPos.X()+(nSizePix-1)*nLayoutSign, aScrPos.Y()+nBarSize-1 ); + + sal_Bool bMark = bMarkRange && nEntryNo >= nMarkStart && nEntryNo <= nMarkEnd; + sal_Bool bNextToMark = bMarkRange && nEntryNo + 1 >= nMarkStart && nEntryNo <= nMarkEnd; + + switch ( nPass ) + { + case SC_HDRPAINT_SEL_BOTTOM: + case SC_HDRPAINT_BOTTOM: + if ( nPass == ( bNextToMark ? SC_HDRPAINT_SEL_BOTTOM : SC_HDRPAINT_BOTTOM ) ) + { + if (bVertical) + aGrid.AddHorLine( aScrPos.X(), aEndPos.X(), aEndPos.Y() ); + else + aGrid.AddVerLine( aEndPos.X(), aScrPos.Y(), aEndPos.Y() ); + + // thick bottom for hidden rows + // (drawn directly, without aGrid) + if ( nEntryNo+1 < nSize ) + if ( GetEntrySize(nEntryNo+1)==0 ) + { + if (bVertical) + DrawLine( Point(aScrPos.X(),aEndPos.Y()-nLayoutSign), + Point(aEndPos.X(),aEndPos.Y()-nLayoutSign) ); + else + DrawLine( Point(aEndPos.X()-nLayoutSign,aScrPos.Y()), + Point(aEndPos.X()-nLayoutSign,aEndPos.Y()) ); + } + } + break; + + case SC_HDRPAINT_TEXT: + if ( nSizePix > 1 ) // minimal check for small columns/rows + { + if ( bMark != bBoldSet ) + { + if (bMark) + SetFont(aBoldFont); + else + SetFont(aNormFont); + bBoldSet = bMark; + } + aString = GetEntryText( nEntryNo ); + aTextSize.Width() = GetTextWidth( aString ); + aTextSize.Height() = GetTextHeight(); + + Point aTxtPos(aScrPos); + if (bVertical) + { + aTxtPos.X() += (nBarSize-aTextSize.Width())/2; + aTxtPos.Y() += (nSizePix*nLayoutSign-aTextSize.Height())/2; + if ( bMirrored ) + aTxtPos.X() += 1; // dark border is left instead of right + } + else + { + aTxtPos.X() += (nSizePix*nLayoutSign-aTextSize.Width()+1)/2; + aTxtPos.Y() += (nBarSize-aTextSize.Height())/2; + } + DrawText( aTxtPos, aString ); + } + break; + } + + // bei Selektion der ganzen Zeile/Spalte: + // InvertRect( Rectangle( aScrPos, aEndPos ) ); + } + nScrPos += nSizePix * nLayoutSign; // also if before the visible area + } + ++nCount; + } + while ( nScrPos * nLayoutSign <= nPEnd * nLayoutSign ); + + aGrid.Flush(); + } +} + +// +// Maus - Handling +// + +SCCOLROW ScHeaderControl::GetMousePos( const MouseEvent& rMEvt, sal_Bool& rBorder ) +{ + sal_Bool bFound=sal_False; + SCCOLROW nCount = 1; + SCCOLROW nPos = GetPos(); + SCCOLROW nHitNo = nPos; + long nScrPos; + long nMousePos = bVertical ? rMEvt.GetPosPixel().Y() : rMEvt.GetPosPixel().X(); + long nDif; + Size aSize = GetOutputSizePixel(); + long nWinSize = bVertical ? aSize.Height() : aSize.Width(); + + sal_Bool bLayoutRTL = IsLayoutRTL(); + long nLayoutSign = bLayoutRTL ? -1 : 1; + long nEndPos = bLayoutRTL ? -1 : nWinSize; + + nScrPos = GetScrPos( nPos ) - nLayoutSign; + do + { + SCCOLROW nEntryNo = nCount + nPos; + +// nScrPos = GetScrPos( nEntryNo ) - 1; + + if (nEntryNo > nSize) + nScrPos = nEndPos + nLayoutSign; + else + nScrPos += GetEntrySize( nEntryNo - 1 ) * nLayoutSign; //! GetHiddenCount() ?? + + nDif = nMousePos - nScrPos; + if (nDif >= -2 && nDif <= 2 && nCount > 0) + { + bFound=sal_True; + nHitNo=nEntryNo-1; + } + else if (nDif * nLayoutSign >= 0 && nEntryNo < nSize) + nHitNo = nEntryNo; + ++nCount; + } + while ( nScrPos * nLayoutSign < nEndPos * nLayoutSign && nDif * nLayoutSign > 0 ); + + rBorder = bFound; + return nHitNo; +} + +bool ScHeaderControl::IsSelectionAllowed(SCCOLROW nPos) const +{ + ScTabViewShell* pViewSh = dynamic_cast<ScTabViewShell*>(SfxViewShell::Current()); + if (!pViewSh) + return false; + + ScViewData* pViewData = pViewSh->GetViewData(); + sal_uInt16 nTab = pViewData->GetTabNo(); + ScDocument* pDoc = pViewData->GetDocument(); + const ScTableProtection* pProtect = pDoc->GetTabProtection(nTab); + bool bSelectAllowed = true; + if ( pProtect && pProtect->isProtected() ) + { + // This sheet is protected. Check if a context menu is allowed on this cell. + bool bCellsProtected = false; + if (bVertical) + { + // row header + SCROW nRPos = static_cast<SCROW>(nPos); + bCellsProtected = pDoc->HasAttrib(0, nRPos, nTab, MAXCOL, nRPos, nTab, HASATTR_PROTECTED); + } + else + { + // column header + SCCOL nCPos = static_cast<SCCOL>(nPos); + bCellsProtected = pDoc->HasAttrib(nCPos, 0, nTab, nCPos, MAXROW, nTab, HASATTR_PROTECTED); + } + + bool bSelProtected = pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS); + bool bSelUnprotected = pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS); + + if (bCellsProtected) + bSelectAllowed = bSelProtected; + else + bSelectAllowed = bSelUnprotected; + } + return bSelectAllowed; +} + +void ScHeaderControl::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if (IsDisabled()) + return; + + bIgnoreMove = sal_False; + SelectWindow(); + + sal_Bool bFound; + SCCOLROW nHitNo = GetMousePos( rMEvt, bFound ); + if (!IsSelectionAllowed(nHitNo)) + return; + + if ( bFound && rMEvt.IsLeft() && ResizeAllowed() ) + { + nDragNo = nHitNo; + sal_uInt16 nClicks = rMEvt.GetClicks(); + if ( nClicks && nClicks%2==0 ) + { + SetEntrySize( nDragNo, HDR_SIZE_OPTIMUM ); + SetPointer( Pointer( POINTER_ARROW ) ); + } + else + { + if (bVertical) + nDragStart = rMEvt.GetPosPixel().Y(); + else + nDragStart = rMEvt.GetPosPixel().X(); + nDragPos = nDragStart; + ShowDragHelp(); + DrawInvert( nDragPos ); + + // CaptureMouse(); + StartTracking(); + bDragging = sal_True; + bDragMoved = sal_False; + } + } + else if (rMEvt.IsLeft()) + { + pSelEngine->SetWindow( this ); + Point aPoint; + Rectangle aVis( aPoint,GetOutputSizePixel() ); + if (bVertical) + aVis.Left() = LONG_MIN, aVis.Right() = LONG_MAX; + else + aVis.Top() = LONG_MIN, aVis.Bottom() = LONG_MAX; + pSelEngine->SetVisibleArea( aVis ); + + SetMarking( sal_True ); // muss vor SelMouseButtonDown sein + pSelEngine->SelMouseButtonDown( rMEvt ); + + // #74215# In column/row headers a simple click already is a selection. + // -> Call SelMouseMove to ensure CreateAnchor is called (and DestroyAnchor + // if the next click is somewhere else with Control key). + pSelEngine->SelMouseMove( rMEvt ); + + if (IsMouseCaptured()) + { + // Tracking statt CaptureMouse, damit sauber abgebrochen werden kann + //! Irgendwann sollte die SelectionEngine selber StartTracking rufen!?! + ReleaseMouse(); + StartTracking(); + } + } +} + +void ScHeaderControl::MouseButtonUp( const MouseEvent& rMEvt ) +{ + if ( IsDisabled() ) + return; + + SetMarking( sal_False ); + bIgnoreMove = sal_False; +// sal_Bool bFound; +// SCCOLROW nHitNo = GetMousePos( rMEvt, bFound ); + + if ( bDragging ) + { + DrawInvert( nDragPos ); + ReleaseMouse(); + bDragging = sal_False; + + long nScrPos = GetScrPos( nDragNo ); + long nMousePos = bVertical ? rMEvt.GetPosPixel().Y() : rMEvt.GetPosPixel().X(); + sal_Bool bLayoutRTL = IsLayoutRTL(); + long nNewWidth = bLayoutRTL ? ( nScrPos - nMousePos + 1 ) + : ( nMousePos + 2 - nScrPos ); + + if ( nNewWidth < 0 /* && !IsSelected(nDragNo) */ ) + { + SCCOLROW nStart = 0; + SCCOLROW nEnd = nDragNo; + while (nNewWidth < 0) + { + nStart = nDragNo; + if (nDragNo>0) + { + --nDragNo; + nNewWidth += GetEntrySize( nDragNo ); //! GetHiddenCount() ??? + } + else + nNewWidth = 0; + } + HideEntries( nStart, nEnd ); + } + else + { + if (nNewWidth<0) nNewWidth=0; + if (bDragMoved) + SetEntrySize( nDragNo, (sal_uInt16) nNewWidth ); + } + } + else + { + pSelEngine->SelMouseButtonUp( rMEvt ); + ReleaseMouse(); + } +} + +void ScHeaderControl::MouseMove( const MouseEvent& rMEvt ) +{ + if ( IsDisabled() ) + { + SetPointer( Pointer( POINTER_ARROW ) ); + return; + } + + sal_Bool bFound; + (void)GetMousePos( rMEvt, bFound ); + + if ( bDragging ) + { + long nNewPos = bVertical ? rMEvt.GetPosPixel().Y() : rMEvt.GetPosPixel().X(); + if ( nNewPos != nDragPos ) + { + DrawInvert( nDragPos ); + nDragPos = nNewPos; + ShowDragHelp(); + DrawInvert( nDragPos ); + + if (nDragPos <= nDragStart-SC_DRAG_MIN || nDragPos >= nDragStart+SC_DRAG_MIN) + bDragMoved = sal_True; + } + } + else + { + if ( bFound && rMEvt.GetButtons()==0 && ResizeAllowed() ) + SetPointer( Pointer( bVertical ? POINTER_VSIZEBAR : POINTER_HSIZEBAR ) ); + else + SetPointer( Pointer( POINTER_ARROW ) ); + + if (!bIgnoreMove) + pSelEngine->SelMouseMove( rMEvt ); + } +} + +void ScHeaderControl::Tracking( const TrackingEvent& rTEvt ) +{ + // Weil die SelectionEngine kein Tracking kennt, die Events nur auf + // die verschiedenen MouseHandler verteilen... + + if ( rTEvt.IsTrackingCanceled() ) + StopMarking(); + else if ( rTEvt.IsTrackingEnded() ) + MouseButtonUp( rTEvt.GetMouseEvent() ); + else + MouseMove( rTEvt.GetMouseEvent() ); +} + +void ScHeaderControl::Command( const CommandEvent& rCEvt ) +{ + sal_uInt16 nCmd = rCEvt.GetCommand(); + if ( nCmd == COMMAND_CONTEXTMENU ) + { + StopMarking(); // Selektion / Dragging beenden + + // Popup ausfuehren + + ScTabViewShell* pViewSh = PTR_CAST( ScTabViewShell, + SfxViewShell::Current() ); + if ( pViewSh ) + { + if ( rCEvt.IsMouseEvent() ) + { + // #i18735# select the column/row under the mouse pointer + ScViewData* pViewData = pViewSh->GetViewData(); + + SelectWindow(); // also deselects drawing objects, stops draw text edit + if ( pViewData->HasEditView( pViewData->GetActivePart() ) ) + SC_MOD()->InputEnterHandler(); // always end edit mode + + MouseEvent aMEvt( rCEvt.GetMousePosPixel() ); + sal_Bool bBorder; + SCCOLROW nPos = GetMousePos( aMEvt, bBorder ); + if (!IsSelectionAllowed(nPos)) + // Selecting this cell is not allowed, neither is context menu. + return; + + SCTAB nTab = pViewData->GetTabNo(); + ScRange aNewRange; + if ( bVertical ) + aNewRange = ScRange( 0, sal::static_int_cast<SCROW>(nPos), nTab, + MAXCOL, sal::static_int_cast<SCROW>(nPos), nTab ); + else + aNewRange = ScRange( sal::static_int_cast<SCCOL>(nPos), 0, nTab, + sal::static_int_cast<SCCOL>(nPos), MAXROW, nTab ); + + // see if any part of the range is already selected + sal_Bool bSelected = sal_False; + ScRangeList aRanges; + pViewData->GetMarkData().FillRangeListWithMarks( &aRanges, sal_False ); + sal_uLong nRangeCount = aRanges.Count(); + for (sal_uLong i=0; i<nRangeCount && !bSelected; i++) + if ( aRanges.GetObject(i)->Intersects( aNewRange ) ) + bSelected = sal_True; + + // select the range if no part of it was selected + if ( !bSelected ) + pViewSh->MarkRange( aNewRange ); + } + + ScResId aResId( bVertical ? RID_POPUP_ROWHEADER : RID_POPUP_COLHEADER ); + pViewSh->GetDispatcher()->ExecutePopup( aResId ); + } + } + else if ( nCmd == COMMAND_STARTDRAG ) + { + pSelEngine->Command( rCEvt ); + } +} + +void ScHeaderControl::StopMarking() +{ + if ( bDragging ) + { + DrawInvert( nDragPos ); + bDragging = sal_False; + } + + SetMarking( sal_False ); + bIgnoreMove = sal_True; + + // #86260# don't call pSelEngine->Reset, so selection across the parts of + // a split/frozen view is possible + + ReleaseMouse(); +} + +void ScHeaderControl::ShowDragHelp() +{ + if (Help::IsQuickHelpEnabled()) + { + long nScrPos = GetScrPos( nDragNo ); + sal_Bool bLayoutRTL = IsLayoutRTL(); + long nVal = bLayoutRTL ? ( nScrPos - nDragPos + 1 ) + : ( nDragPos + 2 - nScrPos ); + + String aHelpStr = GetDragHelp( nVal ); + Point aPos = OutputToScreenPixel( Point(0,0) ); + Size aSize = GetSizePixel(); + + Point aMousePos = OutputToScreenPixel(GetPointerPosPixel()); + + Rectangle aRect; + sal_uInt16 nAlign; + if (!bVertical) + { + // oberhalb + aRect.Left() = aMousePos.X(); + aRect.Top() = aPos.Y() - 4; + nAlign = QUICKHELP_BOTTOM|QUICKHELP_CENTER; + } + else + { + // rechts oben + aRect.Left() = aPos.X() + aSize.Width() + 8; + aRect.Top() = aMousePos.Y() - 2; + nAlign = QUICKHELP_LEFT|QUICKHELP_BOTTOM; + } + + aRect.Right() = aRect.Left(); + aRect.Bottom() = aRect.Top(); + + Help::ShowQuickHelp(this, aRect, aHelpStr, nAlign); + } +} + +void ScHeaderControl::RequestHelp( const HelpEvent& rHEvt ) +{ + // Wenn eigene QuickHelp angezeigt wird, nicht durch RequestHelp + // wieder wegnehmen lassen + + sal_Bool bOwn = bDragging && Help::IsQuickHelpEnabled(); + if (!bOwn) + Window::RequestHelp(rHEvt); +} + +// ----------------------------------------------------------------------- +// Dummys fuer virtuelle Methoden +// ----------------------------------------------------------------------- + +SCCOLROW ScHeaderControl::GetHiddenCount( SCCOLROW nEntryNo ) +{ + SCCOLROW nHidden = 0; + while ( nEntryNo < nSize && GetEntrySize( nEntryNo ) == 0 ) + { + ++nEntryNo; + ++nHidden; + } + return nHidden; +} + +sal_Bool ScHeaderControl::IsLayoutRTL() +{ + return sal_False; +} + +sal_Bool ScHeaderControl::IsMirrored() +{ + return sal_False; +} + +sal_Bool ScHeaderControl::IsDisabled() +{ + return sal_False; +} + +sal_Bool ScHeaderControl::ResizeAllowed() +{ + return sal_True; +} + +void ScHeaderControl::SelectWindow() +{ +} + +void ScHeaderControl::DrawInvert( long /* nDragPos */ ) +{ +} + +String ScHeaderControl::GetDragHelp( long /* nVal */ ) +{ + return EMPTY_STRING; +} + +void ScHeaderControl::SetMarking( sal_Bool /* bSet */ ) +{ +} + + + diff --git a/sc/source/ui/view/hintwin.cxx b/sc/source/ui/view/hintwin.cxx new file mode 100644 index 000000000000..1828cbd83e55 --- /dev/null +++ b/sc/source/ui/view/hintwin.cxx @@ -0,0 +1,108 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +// System - Includes ----------------------------------------------------- + + + +// INCLUDE --------------------------------------------------------------- + +#include "hintwin.hxx" +#include "global.hxx" + +#define HINT_LINESPACE 2 +#define HINT_INDENT 3 +#define HINT_MARGIN 4 + +//================================================================== + +ScHintWindow::ScHintWindow( Window* pParent, const String& rTit, const String& rMsg ) : + Window( pParent, WinBits( WB_BORDER ) ), + aTitle( rTit ), + aMessage( rMsg ) +{ + aMessage.ConvertLineEnd( LINEEND_CR ); + + // Hellgelb, wie Notizen in detfunc.cxx + Color aYellow( 255,255,192 ); // hellgelb + SetBackground( aYellow ); + + aTextFont = GetFont(); + aTextFont.SetTransparent( sal_True ); + aTextFont.SetWeight( WEIGHT_NORMAL ); + aHeadFont = aTextFont; + aHeadFont.SetWeight( WEIGHT_BOLD ); + + SetFont( aHeadFont ); + Size aHeadSize( GetTextWidth( aTitle ), GetTextHeight() ); + SetFont( aTextFont ); + + Size aTextSize; + xub_StrLen nIndex = 0; + while ( nIndex != STRING_NOTFOUND ) + { + String aLine = aMessage.GetToken( 0, CHAR_CR, nIndex ); + Size aLineSize( GetTextWidth( aLine ), GetTextHeight() ); + nTextHeight = aLineSize.Height(); + aTextSize.Height() += nTextHeight; + if ( aLineSize.Width() > aTextSize.Width() ) + aTextSize.Width() = aLineSize.Width(); + } + aTextSize.Width() += HINT_INDENT; + + aTextStart = Point( HINT_MARGIN + HINT_INDENT, + aHeadSize.Height() + HINT_MARGIN + HINT_LINESPACE ); + + Size aWinSize( Max( aHeadSize.Width(), aTextSize.Width() ) + 2 * HINT_MARGIN + 1, + aHeadSize.Height() + aTextSize.Height() + HINT_LINESPACE + 2 * HINT_MARGIN + 1 ); + SetOutputSizePixel( aWinSize ); +} + + +ScHintWindow::~ScHintWindow() +{ +} + + +void __EXPORT ScHintWindow::Paint( const Rectangle& /* rRect */ ) +{ + SetFont( aHeadFont ); + DrawText( Point(HINT_MARGIN,HINT_MARGIN), aTitle ); + + SetFont( aTextFont ); + xub_StrLen nIndex = 0; + Point aLineStart = aTextStart; + while ( nIndex != STRING_NOTFOUND ) + { + String aLine = aMessage.GetToken( 0, CHAR_CR, nIndex ); + DrawText( aLineStart, aLine ); + aLineStart.Y() += nTextHeight; + } +} diff --git a/sc/source/ui/view/imapwrap.cxx b/sc/source/ui/view/imapwrap.cxx new file mode 100644 index 000000000000..0d1321e61709 --- /dev/null +++ b/sc/source/ui/view/imapwrap.cxx @@ -0,0 +1,76 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include <svx/imapdlg.hxx> +#include <sfx2/viewfrm.hxx> + + +sal_uInt16 ScIMapChildWindowId() +{ + return SvxIMapDlgChildWindow::GetChildWindowId(); +} + +SvxIMapDlg* ScGetIMapDlg() +{ + //! pass view frame here and in SVXIMAPDLG() + + SfxViewFrame* pViewFrm = SfxViewFrame::Current(); + if( pViewFrm && pViewFrm->HasChildWindow( SvxIMapDlgChildWindow::GetChildWindowId() ) ) + return SVXIMAPDLG(); + else + return NULL; +} + +void ScIMapDlgSet( const Graphic& rGraphic, const ImageMap* pImageMap, + const TargetList* pTargetList, void* pEditingObj ) +{ + SvxIMapDlgChildWindow::UpdateIMapDlg( rGraphic, pImageMap, pTargetList, pEditingObj ); +} + +const void* ScIMapDlgGetObj( SvxIMapDlg* pDlg ) +{ + if ( pDlg ) + return pDlg->GetEditingObject(); + else + return NULL; +} + +const ImageMap& ScIMapDlgGetMap( SvxIMapDlg* pDlg ) +{ + return pDlg->GetImageMap(); +} + + + + diff --git a/sc/source/ui/view/invmerge.cxx b/sc/source/ui/view/invmerge.cxx new file mode 100644 index 000000000000..587462d59267 --- /dev/null +++ b/sc/source/ui/view/invmerge.cxx @@ -0,0 +1,192 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +#include <vcl/window.hxx> +#include <tools/debug.hxx> + +#include "invmerge.hxx" + +//------------------------------------------------------------------ + +ScInvertMerger::ScInvertMerger( Window* pWindow ) : + pWin( pWindow ), + pRects( NULL ) +{ + // both rectangles empty +} + +ScInvertMerger::ScInvertMerger( ::std::vector< Rectangle >* pRectangles ) : + pWin( NULL ), + pRects( pRectangles ) +{ + // collect rectangles instead of inverting +} + +ScInvertMerger::~ScInvertMerger() +{ + Flush(); +} + +void ScInvertMerger::Flush() +{ + FlushLine(); + FlushTotal(); + + DBG_ASSERT( aLineRect.IsEmpty() && aTotalRect.IsEmpty(), "Flush: not empty" ); + + if ( pRects ) + { + // + // also join vertically if there are non-adjacent columns involved + // + + size_t nComparePos = 0; + while ( nComparePos < pRects->size() ) + { + Rectangle aCompRect = (*pRects)[nComparePos]; + sal_Int32 nBottom = aCompRect.Bottom(); + size_t nOtherPos = nComparePos + 1; + + while ( nOtherPos < pRects->size() ) + { + Rectangle aOtherRect = (*pRects)[nOtherPos]; + if ( aOtherRect.Top() > nBottom + 1 ) + { + // rectangles are sorted, so we can stop searching + break; + } + if ( aOtherRect.Top() == nBottom + 1 && + aOtherRect.Left() == aCompRect.Left() && + aOtherRect.Right() == aCompRect.Right() ) + { + // extend first rectangle + nBottom = aOtherRect.Bottom(); + aCompRect.Bottom() = nBottom; + (*pRects)[nComparePos].Bottom() = nBottom; + + // remove second rectangle + pRects->erase( pRects->begin() + nOtherPos ); + + // continue at unmodified nOtherPos + } + else + ++nOtherPos; + } + + ++nComparePos; + } + } +} + +void ScInvertMerger::FlushTotal() +{ + if( aTotalRect.IsEmpty() ) + return; // nothing to do + + if ( pWin ) + pWin->Invert( aTotalRect, INVERT_HIGHLIGHT ); + else if ( pRects ) + pRects->push_back( aTotalRect ); + + aTotalRect.SetEmpty(); +} + +void ScInvertMerger::FlushLine() +{ + if( aLineRect.IsEmpty() ) + return; // nothing to do + + if ( aTotalRect.IsEmpty() ) + { + aTotalRect = aLineRect; // start new total rect + } + else + { + if ( aLineRect.Left() == aTotalRect.Left() && + aLineRect.Right() == aTotalRect.Right() && + aLineRect.Top() == aTotalRect.Bottom() + 1 ) + { + // extend total rect + aTotalRect.Bottom() = aLineRect.Bottom(); + } + else + { + FlushTotal(); // draw old total rect + aTotalRect = aLineRect; // and start new one + } + } + + aLineRect.SetEmpty(); +} + +void ScInvertMerger::AddRect( const Rectangle& rRect ) +{ + Rectangle aJustified = rRect; + if ( rRect.Left() > rRect.Right() ) // switch for RTL layout + { + aJustified.Left() = rRect.Right(); + aJustified.Right() = rRect.Left(); + } + + if ( aLineRect.IsEmpty() ) + { + aLineRect = aJustified; // start new line rect + } + else + { + sal_Bool bDone = sal_False; + if ( aJustified.Top() == aLineRect.Top() && + aJustified.Bottom() == aLineRect.Bottom() ) + { + // try to extend line rect + if ( aJustified.Left() == aLineRect.Right() + 1 ) + { + aLineRect.Right() = aJustified.Right(); + bDone = sal_True; + } + else if ( aJustified.Right() + 1 == aLineRect.Left() ) // for RTL layout + { + aLineRect.Left() = aJustified.Left(); + bDone = sal_True; + } + } + if (!bDone) + { + FlushLine(); // use old line rect for total rect + aLineRect = aJustified; // and start new one + } + } +} + + + + diff --git a/sc/source/ui/view/makefile.mk b/sc/source/ui/view/makefile.mk new file mode 100644 index 000000000000..1b2fef913fc2 --- /dev/null +++ b/sc/source/ui/view/makefile.mk @@ -0,0 +1,173 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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. +# +#************************************************************************* +PRJ=..$/..$/.. + +PRJNAME=sc +TARGET=view + +# --- Settings ----------------------------------------------------- + +.INCLUDE : scpre.mk +.INCLUDE : settings.mk +.INCLUDE : sc.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- +# drawattr.cxx fuer IDL (enums), sollte in den Svx gehen?? + + +SLOFILES = \ + $(SLO)$/tabview.obj \ + $(SLO)$/tabview2.obj \ + $(SLO)$/tabview3.obj \ + $(SLO)$/tabview4.obj \ + $(SLO)$/tabview5.obj \ + $(SLO)$/viewfunc.obj \ + $(SLO)$/viewfun2.obj \ + $(SLO)$/viewfun3.obj \ + $(SLO)$/viewfun4.obj \ + $(SLO)$/viewfun5.obj \ + $(SLO)$/viewfun6.obj \ + $(SLO)$/viewfun7.obj \ + $(SLO)$/dbfunc.obj \ + $(SLO)$/dbfunc2.obj \ + $(SLO)$/dbfunc3.obj \ + $(SLO)$/dbfunc4.obj \ + $(SLO)$/tabvwsh.obj \ + $(SLO)$/tabvwsh2.obj \ + $(SLO)$/tabvwsh3.obj \ + $(SLO)$/tabvwsh4.obj \ + $(SLO)$/tabvwsh5.obj \ + $(SLO)$/tabvwsh8.obj \ + $(SLO)$/tabvwsh9.obj \ + $(SLO)$/tabvwsha.obj \ + $(SLO)$/tabvwshb.obj \ + $(SLO)$/tabvwshc.obj \ + $(SLO)$/tabvwshd.obj \ + $(SLO)$/tabvwshe.obj \ + $(SLO)$/tabvwshf.obj \ + $(SLO)$/tabvwshg.obj \ + $(SLO)$/tabvwshh.obj \ + $(SLO)$/printfun.obj \ + $(SLO)$/pfuncache.obj \ + $(SLO)$/preview.obj \ + $(SLO)$/prevwsh.obj \ + $(SLO)$/prevwsh2.obj \ + $(SLO)$/prevloc.obj \ + $(SLO)$/editsh.obj \ + $(SLO)$/pivotsh.obj \ + $(SLO)$/auditsh.obj \ + $(SLO)$/gridwin.obj \ + $(SLO)$/gridwin2.obj \ + $(SLO)$/gridwin3.obj \ + $(SLO)$/gridwin4.obj \ + $(SLO)$/gridwin5.obj \ + $(SLO)$/drawview.obj \ + $(SLO)$/drawvie2.obj \ + $(SLO)$/drawvie3.obj \ + $(SLO)$/drawvie4.obj \ + $(SLO)$/drawutil.obj \ + $(SLO)$/output.obj \ + $(SLO)$/output2.obj \ + $(SLO)$/output3.obj \ + $(SLO)$/gridmerg.obj \ + $(SLO)$/invmerge.obj \ + $(SLO)$/select.obj \ + $(SLO)$/olinewin.obj \ + $(SLO)$/hintwin.obj \ + $(SLO)$/notemark.obj \ + $(SLO)$/tabcont.obj \ + $(SLO)$/tabsplit.obj \ + $(SLO)$/viewutil.obj \ + $(SLO)$/hdrcont.obj \ + $(SLO)$/colrowba.obj \ + $(SLO)$/olkact.obj \ + $(SLO)$/galwrap.obj \ + $(SLO)$/imapwrap.obj \ + $(SLO)$/reffact.obj \ + $(SLO)$/selectionstate.obj \ + $(SLO)$/spelleng.obj \ + $(SLO)$/spelldialog.obj \ + $(SLO)$/waitoff.obj \ + $(SLO)$/cellsh.obj \ + $(SLO)$/cellsh1.obj\ + $(SLO)$/cellsh2.obj\ + $(SLO)$/cellsh3.obj\ + $(SLO)$/cellsh4.obj\ + $(SLO)$/formatsh.obj\ + $(SLO)$/pgbrksh.obj\ + $(SLO)$/viewdata.obj\ + $(SLO)$/scextopt.obj + +.IF "$(OS)$(COM)$(CPUNAME)"=="LINUXGCCSPARC" + NOOPTFILES= \ + $(SLO)$/drawview.obj \ + $(SLO)$/dbfunc2.obj \ + $(SLO)$/tabvwsh2.obj \ + $(SLO)$/viewfun4.obj \ + $(SLO)$/viewfun2.obj +.ELIF "$(OS)$(COM)$(CPUNAME)"=="SOLARISC52INTEL" + NOOPTFILES=\ + $(SLO)$/drawview.obj \ + $(SLO)$/dbfunc2.obj \ + $(SLO)$/tabvwsh2.obj +.ELSE + NOOPTFILES=\ + $(SLO)$/drawview.obj \ + $(SLO)$/dbfunc2.obj \ + $(SLO)$/tabvwsh2.obj +.ENDIF + +EXCEPTIONSFILES= \ + $(SLO)$/dbfunc3.obj \ + $(SLO)$/gridwin.obj \ + $(SLO)$/invmerge.obj \ + $(SLO)$/output2.obj \ + $(SLO)$/pfuncache.obj \ + $(SLO)$/spelldialog.obj \ + $(SLO)$/cellsh1.obj \ + $(SLO)$/drawvie4.obj \ + $(SLO)$/formatsh.obj \ + $(SLO)$/gridwin2.obj \ + $(SLO)$/scextopt.obj \ + $(SLO)$/tabvwshb.obj \ + $(SLO)$/tabvwshf.obj \ + $(SLO)$/viewdata.obj \ + $(SLO)$/viewfunc.obj \ + $(SLO)$/viewfun2.obj \ + $(SLO)$/viewfun3.obj \ + $(SLO)$/viewfun5.obj \ + $(SLO)$/viewfun7.obj \ + $(SLO)$/reffact.obj + +# goal seek -O2 + + +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk + diff --git a/sc/source/ui/view/notemark.cxx b/sc/source/ui/view/notemark.cxx new file mode 100644 index 000000000000..2bcbf481069e --- /dev/null +++ b/sc/source/ui/view/notemark.cxx @@ -0,0 +1,200 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +#include <svx/svdoutl.hxx> +#include <svx/svdmodel.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdocapt.hxx> +#include <sfx2/printer.hxx> +#include <unotools/pathoptions.hxx> +#include <svl/itempool.hxx> +#include <vcl/svapp.hxx> + +#include "notemark.hxx" +#include "document.hxx" +#include "postit.hxx" + +#define SC_NOTEMARK_TIME 800 +#define SC_NOTEMARK_SHORT 70 + +// ----------------------------------------------------------------------- + +ScNoteMarker::ScNoteMarker( Window* pWin, Window* pRight, Window* pBottom, Window* pDiagonal, + ScDocument* pD, ScAddress aPos, const String& rUser, + const MapMode& rMap, sal_Bool bLeftEdge, sal_Bool bForce, sal_Bool bKeyboard ) : + pWindow( pWin ), + pRightWin( pRight ), + pBottomWin( pBottom ), + pDiagWin( pDiagonal ), + pDoc( pD ), + aDocPos( aPos ), + aUserText( rUser ), + aMapMode( rMap ), + bLeft( bLeftEdge ), + bByKeyboard( bKeyboard ), + pModel( NULL ), + pObject( NULL ), + bVisible( sal_False ) +{ + Size aSizePixel = pWindow->GetOutputSizePixel(); + if( pRightWin ) + aSizePixel.Width() += pRightWin->GetOutputSizePixel().Width(); + if( pBottomWin ) + aSizePixel.Height() += pBottomWin->GetOutputSizePixel().Height(); + Rectangle aVisPixel( Point( 0, 0 ), aSizePixel ); + aVisRect = pWindow->PixelToLogic( aVisPixel, aMapMode ); + + aTimer.SetTimeoutHdl( LINK( this, ScNoteMarker, TimeHdl ) ); + aTimer.SetTimeout( bForce ? SC_NOTEMARK_SHORT : SC_NOTEMARK_TIME ); + aTimer.Start(); +} + +ScNoteMarker::~ScNoteMarker() +{ + InvalidateWin(); + + delete pModel; +} + +IMPL_LINK( ScNoteMarker, TimeHdl, Timer*, EMPTYARG ) +{ + if (!bVisible) + { + SvtPathOptions aPathOpt; + String aPath = aPathOpt.GetPalettePath(); + pModel = new SdrModel(aPath); + pModel->SetScaleUnit(MAP_100TH_MM); + SfxItemPool& rPool = pModel->GetItemPool(); + rPool.SetDefaultMetric(SFX_MAPUNIT_100TH_MM); + rPool.FreezeIdRanges(); + + OutputDevice* pPrinter = pDoc->GetRefDevice(); + if (pPrinter) + { + // Am Outliner des Draw-Model ist auch der Drucker als RefDevice gesetzt, + // und es soll einheitlich aussehen. + Outliner& rOutliner = pModel->GetDrawOutliner(); + rOutliner.SetRefDevice(pPrinter); + } + + if( SdrPage* pPage = pModel->AllocPage( sal_False ) ) + { + pObject = ScNoteUtil::CreateTempCaption( *pDoc, aDocPos, *pPage, aUserText, aVisRect, bLeft ); + if( pObject ) + aRect = pObject->GetCurrentBoundRect(); + + // #39351# Page einfuegen damit das Model sie kennt und auch deleted + pModel->InsertPage( pPage ); + + } + bVisible = sal_True; + } + + Draw(); + return 0; +} + +void lcl_DrawWin( SdrObject* pObject, Window* pWindow, const MapMode& rMap ) +{ + MapMode aOld = pWindow->GetMapMode(); + pWindow->SetMapMode( rMap ); + + sal_uLong nOldDrawMode = pWindow->GetDrawMode(); + if ( Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) + { + pWindow->SetDrawMode( nOldDrawMode | DRAWMODE_SETTINGSLINE | DRAWMODE_SETTINGSFILL | + DRAWMODE_SETTINGSTEXT | DRAWMODE_SETTINGSGRADIENT ); + } + + pObject->SingleObjectPainter( *pWindow ); // #110094#-17 + + pWindow->SetDrawMode( nOldDrawMode ); + pWindow->SetMapMode( aOld ); +} + +MapMode lcl_MoveMapMode( const MapMode& rMap, const Size& rMove ) +{ + MapMode aNew = rMap; + Point aOrigin = aNew.GetOrigin(); + aOrigin.X() -= rMove.Width(); + aOrigin.Y() -= rMove.Height(); + aNew.SetOrigin(aOrigin); + return aNew; +} + +void ScNoteMarker::Draw() +{ + if ( pObject && bVisible ) + { + lcl_DrawWin( pObject, pWindow, aMapMode ); + + if ( pRightWin || pBottomWin ) + { + Size aWinSize = pWindow->PixelToLogic( pWindow->GetOutputSizePixel(), aMapMode ); + if ( pRightWin ) + lcl_DrawWin( pObject, pRightWin, + lcl_MoveMapMode( aMapMode, Size( aWinSize.Width(), 0 ) ) ); + if ( pBottomWin ) + lcl_DrawWin( pObject, pBottomWin, + lcl_MoveMapMode( aMapMode, Size( 0, aWinSize.Height() ) ) ); + if ( pDiagWin ) + lcl_DrawWin( pObject, pDiagWin, lcl_MoveMapMode( aMapMode, aWinSize ) ); + } + } +} + +void ScNoteMarker::InvalidateWin() +{ + if (bVisible) + { + pWindow->Invalidate( pWindow->LogicToLogic(aRect, aMapMode, pWindow->GetMapMode()) ); + + if ( pRightWin || pBottomWin ) + { + Size aWinSize = pWindow->PixelToLogic( pWindow->GetOutputSizePixel(), aMapMode ); + if ( pRightWin ) + pRightWin->Invalidate( pRightWin->LogicToLogic(aRect, + lcl_MoveMapMode( aMapMode, Size( aWinSize.Width(), 0 ) ), + pRightWin->GetMapMode()) ); + if ( pBottomWin ) + pBottomWin->Invalidate( pBottomWin->LogicToLogic(aRect, + lcl_MoveMapMode( aMapMode, Size( 0, aWinSize.Height() ) ), + pBottomWin->GetMapMode()) ); + if ( pDiagWin ) + pDiagWin->Invalidate( pDiagWin->LogicToLogic(aRect, + lcl_MoveMapMode( aMapMode, aWinSize ), + pDiagWin->GetMapMode()) ); + } + } +} + + + + diff --git a/sc/source/ui/view/olinewin.cxx b/sc/source/ui/view/olinewin.cxx new file mode 100644 index 000000000000..d3a750845154 --- /dev/null +++ b/sc/source/ui/view/olinewin.cxx @@ -0,0 +1,1045 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + +#include <vcl/svapp.hxx> +#include <vcl/taskpanelist.hxx> + +#include "olinewin.hxx" +#include "olinetab.hxx" +#include "document.hxx" +#include "dbfunc.hxx" +#include "sc.hrc" + +// ============================================================================ + +const long SC_OL_BITMAPSIZE = 12; +const long SC_OL_POSOFFSET = 2; + +const size_t SC_OL_NOLEVEL = static_cast< size_t >( -1 ); +const size_t SC_OL_HEADERENTRY = static_cast< size_t >( -1 ); + +const sal_uInt16 SC_OL_IMAGE_PLUS = 9; +const sal_uInt16 SC_OL_IMAGE_MINUS = SC_OL_IMAGE_PLUS + 1; +const sal_uInt16 SC_OL_IMAGE_NOTPRESSED = SC_OL_IMAGE_MINUS + 1; +const sal_uInt16 SC_OL_IMAGE_PRESSED = SC_OL_IMAGE_NOTPRESSED + 1; + +// ============================================================================ + +ScOutlineWindow::ScOutlineWindow( Window* pParent, ScOutlineMode eMode, ScViewData* pViewData, ScSplitPos eWhich ) : + Window( pParent ), + mrViewData( *pViewData ), + meWhich( eWhich ), + mbHoriz( eMode == SC_OUTLINE_HOR ), + mbMirrorEntries( false ), // updated in SetHeaderSize + mbMirrorLevels( false ), // updated in SetHeaderSize + mpSymbols( NULL ), + maLineColor( COL_BLACK ), + mnHeaderSize( 0 ), + mnHeaderPos( 0 ), + mnMainFirstPos( 0 ), + mnMainLastPos( 0 ), + mbMTActive( false ), + mbMTPressed( false ), + mnFocusLevel( 0 ), + mnFocusEntry( SC_OL_HEADERENTRY ), + mbDontDrawFocus( false ) +{ + EnableRTL( sal_False ); // mirroring is done manually + + InitSettings(); + maFocusRect.SetEmpty(); + SetHeaderSize( 0 ); + + // insert the window into task pane list for "F6 cycling" + if( SystemWindow* pSysWin = GetSystemWindow() ) + if( TaskPaneList* pTaskPaneList = pSysWin->GetTaskPaneList() ) + pTaskPaneList->AddWindow( this ); +} + +ScOutlineWindow::~ScOutlineWindow() +{ + // remove the window from task pane list + if( SystemWindow* pSysWin = GetSystemWindow() ) + if( TaskPaneList* pTaskPaneList = pSysWin->GetTaskPaneList() ) + pTaskPaneList->RemoveWindow( this ); +} + +void ScOutlineWindow::SetHeaderSize( long nNewSize ) +{ + sal_Bool bLayoutRTL = GetDoc().IsLayoutRTL( GetTab() ); + mbMirrorEntries = bLayoutRTL && mbHoriz; + mbMirrorLevels = bLayoutRTL && !mbHoriz; + + bool bNew = (nNewSize != mnHeaderSize); + mnHeaderSize = nNewSize; + mnHeaderPos = mbMirrorEntries ? (GetOutputSizeEntry() - mnHeaderSize) : 0; + mnMainFirstPos = mbMirrorEntries ? 0 : mnHeaderSize; + mnMainLastPos = GetOutputSizeEntry() - (mbMirrorEntries ? mnHeaderSize : 0) - 1; + if ( bNew ) + Invalidate(); +} + +long ScOutlineWindow::GetDepthSize() const +{ + long nSize = GetLevelCount() * SC_OL_BITMAPSIZE; + if ( nSize > 0 ) + nSize += 2 * SC_OL_POSOFFSET + 1; + return nSize; +} + +void ScOutlineWindow::ScrollPixel( long nDiff ) +{ + HideFocus(); + mbDontDrawFocus = true; + + long nStart = mnMainFirstPos; + long nEnd = mnMainLastPos; + + long nInvStart, nInvEnd; + if (nDiff < 0) + { + nStart -= nDiff; + nInvStart = nEnd + nDiff; + nInvEnd = nEnd; + } + else + { + nEnd -= nDiff; + nInvStart = nStart; + nInvEnd = nStart + nDiff; + } + + ScrollRel( nDiff, nStart, nEnd ); + Invalidate( GetRectangle( 0, nInvStart, GetOutputSizeLevel() - 1, nInvEnd ) ); + Update(); + + // if focus becomes invisible, move it to next visible button + ImplMoveFocusToVisible( nDiff < 0 ); + + mbDontDrawFocus = false; + ShowFocus(); +} + +void ScOutlineWindow::ScrollRel( long nEntryDiff, long nEntryStart, long nEntryEnd ) +{ + Rectangle aRect( GetRectangle( 0, nEntryStart, GetOutputSizeLevel() - 1, nEntryEnd ) ); + if ( mbHoriz ) + Scroll( nEntryDiff, 0, aRect ); + else + Scroll( 0, nEntryDiff, aRect ); +} + +// internal ------------------------------------------------------------------- + +void ScOutlineWindow::InitSettings() +{ + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + SetBackground( rStyleSettings.GetFaceColor() ); + maLineColor = rStyleSettings.GetButtonTextColor(); + mpSymbols = ScGlobal::GetOutlineSymbols( rStyleSettings.GetHighContrastMode() ); + Invalidate(); +} + +const ScOutlineArray* ScOutlineWindow::GetOutlineArray() const +{ + const ScOutlineTable* pTable = GetDoc().GetOutlineTable( GetTab() ); + if ( !pTable ) return NULL; + return mbHoriz ? pTable->GetColArray() : pTable->GetRowArray(); +} + +const ScOutlineEntry* ScOutlineWindow::GetOutlineEntry( size_t nLevel, size_t nEntry ) const +{ + const ScOutlineArray* pArray = GetOutlineArray(); + return pArray ? pArray->GetEntry( sal::static_int_cast<sal_uInt16>(nLevel), sal::static_int_cast<sal_uInt16>(nEntry) ) : NULL; +} + +bool ScOutlineWindow::IsHidden( SCCOLROW nColRowIndex ) const +{ + return mbHoriz ? + GetDoc().ColHidden(static_cast<SCCOL>(nColRowIndex), GetTab()) : + GetDoc().RowHidden(static_cast<SCROW>(nColRowIndex), GetTab()); +} + +bool ScOutlineWindow::IsFiltered( SCCOLROW nColRowIndex ) const +{ + // columns cannot be filtered + return !mbHoriz && GetDoc().RowFiltered( static_cast<SCROW>(nColRowIndex), GetTab() ); +} + +bool ScOutlineWindow::IsFirstVisible( SCCOLROW nColRowIndex ) const +{ + bool bAllHidden = true; + for ( SCCOLROW nPos = 0; (nPos < nColRowIndex) && bAllHidden; ++nPos ) + bAllHidden = IsHidden( nPos ); + return bAllHidden; +} + +void ScOutlineWindow::GetVisibleRange( SCCOLROW& rnColRowStart, SCCOLROW& rnColRowEnd ) const +{ + if ( mbHoriz ) + { + rnColRowStart = mrViewData.GetPosX( WhichH( meWhich ) ); + rnColRowEnd = rnColRowStart + mrViewData.VisibleCellsX( WhichH( meWhich ) ); + } + else + { + rnColRowStart = mrViewData.GetPosY( WhichV( meWhich ) ); + rnColRowEnd = rnColRowStart + mrViewData.VisibleCellsY( WhichV( meWhich ) ); + } + + // include collapsed columns/rows in front of visible range + while ( (rnColRowStart > 0) && IsHidden( rnColRowStart - 1 ) ) + --rnColRowStart; +} + +Point ScOutlineWindow::GetPoint( long nLevelPos, long nEntryPos ) const +{ + return mbHoriz ? Point( nEntryPos, nLevelPos ) : Point( nLevelPos, nEntryPos ); +} + +Rectangle ScOutlineWindow::GetRectangle( + long nLevelStart, long nEntryStart, long nLevelEnd, long nEntryEnd ) const +{ + return Rectangle( GetPoint( nLevelStart, nEntryStart ), GetPoint( nLevelEnd, nEntryEnd ) ); +} + +long ScOutlineWindow::GetOutputSizeLevel() const +{ + Size aSize( GetOutputSizePixel() ); + return mbHoriz ? aSize.Height() : aSize.Width(); +} + +long ScOutlineWindow::GetOutputSizeEntry() const +{ + Size aSize( GetOutputSizePixel() ); + return mbHoriz ? aSize.Width() : aSize.Height(); +} + +size_t ScOutlineWindow::GetLevelCount() const +{ + const ScOutlineArray* pArray = GetOutlineArray(); + size_t nLevelCount = pArray ? pArray->GetDepth() : 0; + return nLevelCount ? (nLevelCount + 1) : 0; +} + +long ScOutlineWindow::GetLevelPos( size_t nLevel ) const +{ + // #i51970# must always return the *left* edge of the area used by a level + long nPos = static_cast< long >( SC_OL_POSOFFSET + nLevel * SC_OL_BITMAPSIZE ); + return mbMirrorLevels ? (GetOutputSizeLevel() - nPos - SC_OL_BITMAPSIZE) : nPos; +} + +size_t ScOutlineWindow::GetLevelFromPos( long nLevelPos ) const +{ + if( mbMirrorLevels ) nLevelPos = GetOutputSizeLevel() - nLevelPos - 1; + long nStart = SC_OL_POSOFFSET; + if ( nLevelPos < nStart ) return SC_OL_NOLEVEL; + size_t nLevel = static_cast< size_t >( (nLevelPos - nStart) / SC_OL_BITMAPSIZE ); + return (nLevel < GetLevelCount()) ? nLevel : SC_OL_NOLEVEL; +} + +long ScOutlineWindow::GetColRowPos( SCCOLROW nColRowIndex ) const +{ + long nDocPos = mbHoriz ? + mrViewData.GetScrPos( static_cast<SCCOL>(nColRowIndex), 0, meWhich, sal_True ).X() : + mrViewData.GetScrPos( 0, static_cast<SCROW>(nColRowIndex), meWhich, sal_True ).Y(); + return mnMainFirstPos + nDocPos; +} + +long ScOutlineWindow::GetHeaderEntryPos() const +{ + return mnHeaderPos + (mnHeaderSize - SC_OL_BITMAPSIZE) / 2; +} + +bool ScOutlineWindow::GetEntryPos( + size_t nLevel, size_t nEntry, + long& rnStartPos, long& rnEndPos, long& rnImagePos ) const +{ + const ScOutlineEntry* pEntry = GetOutlineEntry( nLevel, nEntry ); + if ( !pEntry || !pEntry->IsVisible() ) + return false; + + SCCOLROW nStart = pEntry->GetStart(); + SCCOLROW nEnd = pEntry->GetEnd(); + + long nEntriesSign = mbMirrorEntries ? -1 : 1; + + // --- common calculation --- + + rnStartPos = GetColRowPos( nStart ); + rnEndPos = GetColRowPos( nEnd + 1 ); + + bool bHidden = IsHidden( nStart ); + rnImagePos = bHidden ? + (rnStartPos - ( SC_OL_BITMAPSIZE / 2 ) * nEntriesSign) : + rnStartPos + nEntriesSign; + long nCenter = (rnStartPos + rnEndPos - SC_OL_BITMAPSIZE * nEntriesSign + + ( mbMirrorEntries ? 1 : 0 )) / 2L; + rnImagePos = mbMirrorEntries ? Max( rnImagePos, nCenter ) : Min( rnImagePos, nCenter ); + + // --- refinements --- + + // do not cut leftmost/topmost image + if ( bHidden && IsFirstVisible( nStart ) ) + rnImagePos = rnStartPos; + + // do not cover previous collapsed image + if ( !bHidden && nEntry ) + { + const ScOutlineEntry* pPrevEntry = GetOutlineEntry( nLevel, nEntry - 1 ); + SCCOLROW nPrevEnd = pPrevEntry->GetEnd(); + if ( (nPrevEnd + 1 == nStart) && IsHidden( nPrevEnd ) ) + { + if ( IsFirstVisible( pPrevEntry->GetStart() ) ) + rnStartPos += SC_OL_BITMAPSIZE * nEntriesSign; + else + rnStartPos += ( SC_OL_BITMAPSIZE / 2 ) * nEntriesSign; + rnImagePos = rnStartPos; + } + } + + // restrict rnStartPos...rnEndPos to valid area + rnStartPos = std::max( rnStartPos, mnMainFirstPos ); + rnEndPos = std::max( rnEndPos, mnMainFirstPos ); + + if ( mbMirrorEntries ) + rnImagePos -= SC_OL_BITMAPSIZE - 1; // start pos aligns with right edge of bitmap + + // --- all rows filtered? --- + + bool bVisible = true; + if ( !mbHoriz ) + { + bVisible = false; + for ( SCCOLROW nRow = nStart; (nRow <= nEnd) && !bVisible; ++nRow ) + bVisible = !IsFiltered( nRow ); + } + return bVisible; +} + +bool ScOutlineWindow::GetImagePos( size_t nLevel, size_t nEntry, Point& rPos ) const +{ + bool bRet = nLevel < GetLevelCount(); + if ( bRet ) + { + long nLevelPos = GetLevelPos( nLevel ); + if ( nEntry == SC_OL_HEADERENTRY ) + rPos = GetPoint( nLevelPos, GetHeaderEntryPos() ); + else + { + long nStartPos, nEndPos, nImagePos; + bRet = GetEntryPos( nLevel, nEntry, nStartPos, nEndPos, nImagePos ); + rPos = GetPoint( nLevelPos, nImagePos ); + } + } + return bRet; +} + +bool ScOutlineWindow::IsButtonVisible( size_t nLevel, size_t nEntry ) const +{ + bool bRet = false; + if ( nEntry == SC_OL_HEADERENTRY ) + bRet = (mnHeaderSize > 0) && (nLevel < GetLevelCount()); + else + { + const ScOutlineEntry* pEntry = GetOutlineEntry( nLevel, nEntry ); + if ( pEntry && pEntry->IsVisible() ) + { + SCCOLROW nStart, nEnd; + GetVisibleRange( nStart, nEnd ); + bRet = (nStart <= pEntry->GetStart()) && (pEntry->GetStart() <= nEnd); + } + } + return bRet; +} + +bool ScOutlineWindow::ItemHit( const Point& rPos, size_t& rnLevel, size_t& rnEntry, bool& rbButton ) const +{ + const ScOutlineArray* pArray = GetOutlineArray(); + if ( !pArray ) return false; + + SCCOLROW nStartIndex, nEndIndex; + GetVisibleRange( nStartIndex, nEndIndex ); + + size_t nLevel = GetLevelFromPos( mbHoriz ? rPos.Y() : rPos.X() ); + if ( nLevel == SC_OL_NOLEVEL ) + return false; + +// long nLevelPos = GetLevelPos( nLevel ); + long nEntryMousePos = mbHoriz ? rPos.X() : rPos.Y(); + + // --- level buttons --- + + if ( mnHeaderSize > 0 ) + { + long nImagePos = GetHeaderEntryPos(); + if ( (nImagePos <= nEntryMousePos) && (nEntryMousePos < nImagePos + SC_OL_BITMAPSIZE) ) + { + rnLevel = nLevel; + rnEntry = SC_OL_HEADERENTRY; + rbButton = true; + return true; + } + } + + // --- expand/collapse buttons and expanded lines --- + + // search outline entries backwards + size_t nEntry = pArray->GetCount( sal::static_int_cast<sal_uInt16>(nLevel) ); + while ( nEntry ) + { + --nEntry; + + const ScOutlineEntry* pEntry = pArray->GetEntry( sal::static_int_cast<sal_uInt16>(nLevel), + sal::static_int_cast<sal_uInt16>(nEntry) ); + SCCOLROW nStart = pEntry->GetStart(); + SCCOLROW nEnd = pEntry->GetEnd(); + + if ( (nEnd >= nStartIndex) && (nStart <= nEndIndex) ) + { + long nStartPos, nEndPos, nImagePos; + if ( GetEntryPos( nLevel, nEntry, nStartPos, nEndPos, nImagePos ) ) + { + rnLevel = nLevel; + rnEntry = nEntry; + + // button? + if ( (nStart >= nStartIndex) && (nImagePos <= nEntryMousePos) && (nEntryMousePos < nImagePos + SC_OL_BITMAPSIZE) ) + { + rbButton = true; + return true; + } + + // line? + if ( mbMirrorEntries ) + ::std::swap( nStartPos, nEndPos ); // in RTL mode, nStartPos is the larger value + if ( (nStartPos <= nEntryMousePos) && (nEntryMousePos <= nEndPos) ) + { + rbButton = false; + return true; + } + } + } + } + + return false; +} + +bool ScOutlineWindow::ButtonHit( const Point& rPos, size_t& rnLevel, size_t& rnEntry ) const +{ + bool bButton; + bool bRet = ItemHit( rPos, rnLevel, rnEntry, bButton ); + return bRet && bButton; +} + +bool ScOutlineWindow::LineHit( const Point& rPos, size_t& rnLevel, size_t& rnEntry ) const +{ + bool bButton; + bool bRet = ItemHit( rPos, rnLevel, rnEntry, bButton ); + return bRet && !bButton; +} + +void ScOutlineWindow::DoFunction( size_t nLevel, size_t nEntry ) const +{ + ScDBFunc& rFunc = *mrViewData.GetView(); + if ( nEntry == SC_OL_HEADERENTRY ) + rFunc.SelectLevel( mbHoriz, sal::static_int_cast<sal_uInt16>(nLevel) ); + else + { + const ScOutlineEntry* pEntry = GetOutlineEntry( nLevel, nEntry ); + if ( pEntry ) + { + if ( pEntry->IsHidden() ) + rFunc.ShowOutline( mbHoriz, sal::static_int_cast<sal_uInt16>(nLevel), sal::static_int_cast<sal_uInt16>(nEntry) ); + else + rFunc.HideOutline( mbHoriz, sal::static_int_cast<sal_uInt16>(nLevel), sal::static_int_cast<sal_uInt16>(nEntry) ); + } + } +} + +void ScOutlineWindow::DoExpand( size_t nLevel, size_t nEntry ) const +{ + const ScOutlineEntry* pEntry = GetOutlineEntry( nLevel, nEntry ); + if ( pEntry && pEntry->IsHidden() ) + DoFunction( nLevel, nEntry ); +} + +void ScOutlineWindow::DoCollapse( size_t nLevel, size_t nEntry ) const +{ + const ScOutlineEntry* pEntry = GetOutlineEntry( nLevel, nEntry ); + if ( pEntry && !pEntry->IsHidden() ) + DoFunction( nLevel, nEntry ); +} + +void ScOutlineWindow::Resize() +{ + Window::Resize(); + SetHeaderSize( mnHeaderSize ); // recalculates header/group positions + if ( !IsFocusButtonVisible() ) + { + HideFocus(); + ShowFocus(); // calculates valid position + } +} + +void ScOutlineWindow::DataChanged( const DataChangedEvent& rDCEvt ) +{ + if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && + (rDCEvt.GetFlags() & SETTINGS_STYLE) ) + { + InitSettings(); + Invalidate(); + } + Window::DataChanged( rDCEvt ); +} + +// drawing -------------------------------------------------------------------- + +void ScOutlineWindow::SetEntryAreaClipRegion() +{ + SetClipRegion( Rectangle( + GetPoint( 0, mnMainFirstPos ), + GetPoint( GetOutputSizeLevel() - 1, mnMainLastPos ) ) ); +} + +void ScOutlineWindow::DrawLineRel( + long nLevelStart, long nEntryStart, long nLevelEnd, long nEntryEnd ) +{ + DrawLine( GetPoint( nLevelStart, nEntryStart ), GetPoint( nLevelEnd, nEntryEnd ) ); +} + +void ScOutlineWindow::DrawRectRel( + long nLevelStart, long nEntryStart, long nLevelEnd, long nEntryEnd ) +{ + DrawRect( GetRectangle( nLevelStart, nEntryStart, nLevelEnd, nEntryEnd ) ); +} + +void ScOutlineWindow::DrawImageRel( long nLevelPos, long nEntryPos, sal_uInt16 nId ) +{ + DBG_ASSERT( mpSymbols, "ScOutlineWindow::DrawImageRel - no images" ); + const Image& rImage = mpSymbols->GetImage( nId ); + SetLineColor(); + SetFillColor( GetBackground().GetColor() ); + Point aPos( GetPoint( nLevelPos, nEntryPos ) ); + DrawRect( Rectangle( aPos, rImage.GetSizePixel() ) ); + DrawImage( aPos, rImage ); +} + +void ScOutlineWindow::DrawBorderRel( size_t nLevel, size_t nEntry, bool bPressed ) +{ + Point aPos; + if ( GetImagePos( nLevel, nEntry, aPos ) ) + { + DBG_ASSERT( mpSymbols, "ScOutlineWindow::DrawBorderRel - no images" ); + sal_uInt16 nId = bPressed ? SC_OL_IMAGE_PRESSED : SC_OL_IMAGE_NOTPRESSED; + bool bClip = (nEntry != SC_OL_HEADERENTRY); + if ( bClip ) + SetEntryAreaClipRegion(); + DrawImage( aPos, mpSymbols->GetImage( nId ) ); + if ( bClip ) + SetClipRegion(); + } + mbMTPressed = bPressed; +} + +void ScOutlineWindow::ShowFocus() +{ + if ( HasFocus() ) + { + // first move to a visible position + ImplMoveFocusToVisible( true ); + + if ( IsFocusButtonVisible() ) + { + Point aPos; + if ( GetImagePos( mnFocusLevel, mnFocusEntry, aPos ) ) + { + aPos += Point( 1, 1 ); + maFocusRect = Rectangle( aPos, Size( SC_OL_BITMAPSIZE - 2, SC_OL_BITMAPSIZE - 2 ) ); + bool bClip = (mnFocusEntry != SC_OL_HEADERENTRY); + if ( bClip ) + SetEntryAreaClipRegion(); + InvertTracking( maFocusRect, SHOWTRACK_SMALL | SHOWTRACK_WINDOW ); + if ( bClip ) + SetClipRegion(); + } + } + } +} + +void ScOutlineWindow::HideFocus() +{ + if ( !maFocusRect.IsEmpty() ) + { + bool bClip = (mnFocusEntry != SC_OL_HEADERENTRY); + if ( bClip ) + SetEntryAreaClipRegion(); + InvertTracking( maFocusRect, SHOWTRACK_SMALL | SHOWTRACK_WINDOW ); + if ( bClip ) + SetClipRegion(); + maFocusRect.SetEmpty(); + } +} + +void ScOutlineWindow::Paint( const Rectangle& /* rRect */ ) +{ + long nEntriesSign = mbMirrorEntries ? -1 : 1; + long nLevelsSign = mbMirrorLevels ? -1 : 1; + + Size aSize = GetOutputSizePixel(); + long nLevelEnd = (mbHoriz ? aSize.Height() : aSize.Width()) - 1; + long nEntryEnd = (mbHoriz ? aSize.Width() : aSize.Height()) - 1; + + SetLineColor( maLineColor ); + long nBorderPos = mbMirrorLevels ? 0 : nLevelEnd; + DrawLineRel( nBorderPos, 0, nBorderPos, nEntryEnd ); + + const ScOutlineArray* pArray = GetOutlineArray(); + if ( !pArray ) return; + + size_t nLevelCount = GetLevelCount(); + + // --- draw header images --- + + if ( mnHeaderSize > 0 ) + { + long nEntryPos = GetHeaderEntryPos(); + for ( size_t nLevel = 0; nLevel < nLevelCount; ++nLevel ) + DrawImageRel( GetLevelPos( nLevel ), nEntryPos, static_cast< sal_uInt16 >( nLevel + 1 ) ); + + SetLineColor( maLineColor ); + long nLinePos = mnHeaderPos + (mbMirrorEntries ? 0 : (mnHeaderSize - 1)); + DrawLineRel( 0, nLinePos, nLevelEnd, nLinePos ); + } + + // --- draw lines & collapse/expand images --- + + SetEntryAreaClipRegion(); + + SCCOLROW nStartIndex, nEndIndex; + GetVisibleRange( nStartIndex, nEndIndex ); + + for ( size_t nLevel = 0; nLevel + 1 < nLevelCount; ++nLevel ) + { + long nLevelPos = GetLevelPos( nLevel ); + long nEntryPos1 = 0, nEntryPos2 = 0, nImagePos = 0; + + size_t nEntryCount = pArray->GetCount( sal::static_int_cast<sal_uInt16>(nLevel) ); + size_t nEntry; + + // first draw all lines in the current level + SetLineColor(); + SetFillColor( maLineColor ); + for ( nEntry = 0; nEntry < nEntryCount; ++nEntry ) + { + const ScOutlineEntry* pEntry = pArray->GetEntry( sal::static_int_cast<sal_uInt16>(nLevel), + sal::static_int_cast<sal_uInt16>(nEntry) ); + SCCOLROW nStart = pEntry->GetStart(); + SCCOLROW nEnd = pEntry->GetEnd(); + + // visible range? + bool bDraw = (nEnd >= nStartIndex) && (nStart <= nEndIndex); + // find output coordinates + if ( bDraw ) + bDraw = GetEntryPos( nLevel, nEntry, nEntryPos1, nEntryPos2, nImagePos ); + // draw, if not collapsed + if ( bDraw && !pEntry->IsHidden() ) + { + if ( nStart >= nStartIndex ) + nEntryPos1 += nEntriesSign; + nEntryPos2 -= 2 * nEntriesSign; + long nLinePos = nLevelPos; + if ( mbMirrorLevels ) + nLinePos += SC_OL_BITMAPSIZE - 1; // align with right edge of bitmap + DrawRectRel( nLinePos, nEntryPos1, nLinePos + nLevelsSign, nEntryPos2 ); + + if ( nEnd <= nEndIndex ) + DrawRectRel( nLinePos, nEntryPos2 - nEntriesSign, + nLinePos + ( SC_OL_BITMAPSIZE / 3 ) * nLevelsSign, nEntryPos2 ); + } + } + + // draw all images in the level from last to first + nEntry = nEntryCount; + while ( nEntry ) + { + --nEntry; + + const ScOutlineEntry* pEntry = pArray->GetEntry( sal::static_int_cast<sal_uInt16>(nLevel), + sal::static_int_cast<sal_uInt16>(nEntry) ); + SCCOLROW nStart = pEntry->GetStart(); +// SCCOLROW nEnd = pEntry->GetEnd(); + + // visible range? + bool bDraw = (nStartIndex <= nStart) && (nStart <= nEndIndex + 1); + // find output coordinates + if ( bDraw ) + bDraw = GetEntryPos( nLevel, nEntry, nEntryPos1, nEntryPos2, nImagePos ); + // draw, if not hidden by higher levels + if ( bDraw ) + { + sal_uInt16 nImageId = pEntry->IsHidden() ? SC_OL_IMAGE_PLUS : SC_OL_IMAGE_MINUS; + DrawImageRel( nLevelPos, nImagePos, nImageId ); + } + } + } + + SetClipRegion(); + + if ( !mbDontDrawFocus ) + ShowFocus(); +} + +// focus ---------------------------------------------------------------------- + +/** Increments or decrements a value and wraps at the specified limits. + @return true = value wrapped. */ +bool lcl_RotateValue( size_t& rnValue, size_t nMin, size_t nMax, bool bForward ) +{ + DBG_ASSERT( nMin <= nMax, "lcl_RotateValue - invalid range" ); + DBG_ASSERT( nMax < static_cast< size_t >( -1 ), "lcl_RotateValue - range overflow" ); + bool bWrap = false; + if ( bForward ) + { + if ( rnValue < nMax ) + ++rnValue; + else + { + rnValue = nMin; + bWrap = true; + } + } + else + { + if ( rnValue > nMin ) + --rnValue; + else + { + rnValue = nMax; + bWrap = true; + } + } + return bWrap; +} + +bool ScOutlineWindow::IsFocusButtonVisible() const +{ + return IsButtonVisible( mnFocusLevel, mnFocusEntry ); +} + +bool ScOutlineWindow::ImplMoveFocusByEntry( bool bForward, bool bFindVisible ) +{ + const ScOutlineArray* pArray = GetOutlineArray(); + if ( !pArray ) + return false; + + bool bWrapped = false; + size_t nEntryCount = pArray->GetCount( sal::static_int_cast<sal_uInt16>(mnFocusLevel) ); + // #i29530# entry count may be decreased after changing active sheet + if( mnFocusEntry >= nEntryCount ) + mnFocusEntry = SC_OL_HEADERENTRY; + size_t nOldEntry = mnFocusEntry; + + do + { + if ( mnFocusEntry == SC_OL_HEADERENTRY ) + { + // move from header to first or last entry + if ( nEntryCount > 0 ) + mnFocusEntry = bForward ? 0 : (nEntryCount - 1); + /* wrapped, if forward from right header to first entry, + or if backward from left header to last entry */ + // Header and entries are now always in consistent order, + // so there's no need to check for mirroring here. + if ( !nEntryCount || !bForward ) + bWrapped = true; + } + else if ( lcl_RotateValue( mnFocusEntry, 0, nEntryCount - 1, bForward ) ) + { + // lcl_RotateValue returns true -> wrapped the entry range -> move to header + mnFocusEntry = SC_OL_HEADERENTRY; + /* wrapped, if forward from last entry to left header, + or if backward from first entry to right header */ + if ( bForward ) + bWrapped = true; + } + } + while ( bFindVisible && !IsFocusButtonVisible() && (nOldEntry != mnFocusEntry) ); + + return bWrapped; +} + +bool ScOutlineWindow::ImplMoveFocusByLevel( bool bForward ) +{ + const ScOutlineArray* pArray = GetOutlineArray(); + if ( !pArray ) + return false; + + bool bWrapped = false; + size_t nLevelCount = GetLevelCount(); + + if ( mnFocusEntry == SC_OL_HEADERENTRY ) + { + if ( nLevelCount > 0 ) + bWrapped = lcl_RotateValue( mnFocusLevel, 0, nLevelCount - 1, bForward ); + } + else + { + const ScOutlineEntry* pEntry = pArray->GetEntry( sal::static_int_cast<sal_uInt16>(mnFocusLevel), + sal::static_int_cast<sal_uInt16>(mnFocusEntry) ); + if ( pEntry ) + { + SCCOLROW nStart = pEntry->GetStart(); + SCCOLROW nEnd = pEntry->GetEnd(); + size_t nNewLevel = mnFocusLevel; + size_t nNewEntry = 0; + + bool bFound = false; + if ( bForward && (mnFocusLevel + 2 < nLevelCount) ) + { + // next level -> find first child entry + nNewLevel = mnFocusLevel + 1; + // TODO - change ScOutlineArray interface to size_t usage + sal_uInt16 nTmpEntry = 0; + bFound = pArray->GetEntryIndexInRange( sal::static_int_cast<sal_uInt16>(nNewLevel), nStart, nEnd, nTmpEntry ); + nNewEntry = nTmpEntry; + } + else if ( !bForward && (mnFocusLevel > 0) ) + { + // previous level -> find parent entry + nNewLevel = mnFocusLevel - 1; + // TODO - change ScOutlineArray interface to size_t usage + sal_uInt16 nTmpEntry = 0; + bFound = pArray->GetEntryIndex( sal::static_int_cast<sal_uInt16>(nNewLevel), nStart, nTmpEntry ); + nNewEntry = nTmpEntry; + } + + if ( bFound && IsButtonVisible( nNewLevel, nNewEntry ) ) + { + mnFocusLevel = nNewLevel; + mnFocusEntry = nNewEntry; + } + } + } + + return bWrapped; +} + +bool ScOutlineWindow::ImplMoveFocusByTabOrder( bool bForward, bool bFindVisible ) +{ + bool bRet = false; + size_t nOldLevel = mnFocusLevel; + size_t nOldEntry = mnFocusEntry; + + do + { + /* one level up, if backward from left header, + or one level down, if forward from right header */ + if ( (!bForward) && (mnFocusEntry == SC_OL_HEADERENTRY) ) + bRet |= ImplMoveFocusByLevel( bForward ); + // move to next/previous entry + bool bWrapInLevel = ImplMoveFocusByEntry( bForward, false ); + bRet |= bWrapInLevel; + /* one level up, if wrapped backward to right header, + or one level down, if wrapped forward to right header */ + if ( bForward && bWrapInLevel ) + bRet |= ImplMoveFocusByLevel( bForward ); + } + while ( bFindVisible && !IsFocusButtonVisible() && ((nOldLevel != mnFocusLevel) || (nOldEntry != mnFocusEntry)) ); + + return bRet; +} + +void ScOutlineWindow::ImplMoveFocusToVisible( bool bForward ) +{ + // first try to find an entry in the same level + if ( !IsFocusButtonVisible() ) + ImplMoveFocusByEntry( bForward, true ); + // then try to find any other entry + if ( !IsFocusButtonVisible() ) + ImplMoveFocusByTabOrder( bForward, true ); +} + +void ScOutlineWindow::MoveFocusByEntry( bool bForward ) +{ + HideFocus(); + ImplMoveFocusByEntry( bForward, true ); + ShowFocus(); +} + +void ScOutlineWindow::MoveFocusByLevel( bool bForward ) +{ + HideFocus(); + ImplMoveFocusByLevel( bForward ); + ShowFocus(); +} + +void ScOutlineWindow::MoveFocusByTabOrder( bool bForward ) +{ + HideFocus(); + ImplMoveFocusByTabOrder( bForward, true ); + ShowFocus(); +} + +void ScOutlineWindow::GetFocus() +{ + Window::GetFocus(); + ShowFocus(); +} + +void ScOutlineWindow::LoseFocus() +{ + HideFocus(); + Window::LoseFocus(); +} + + +// mouse ---------------------------------------------------------------------- + +void ScOutlineWindow::StartMouseTracking( size_t nLevel, size_t nEntry ) +{ + mbMTActive = true; + mnMTLevel = nLevel; + mnMTEntry = nEntry; + DrawBorderRel( nLevel, nEntry, true ); +} + +void ScOutlineWindow::EndMouseTracking() +{ + if ( mbMTPressed ) + DrawBorderRel( mnMTLevel, mnMTEntry, false ); + mbMTActive = false; +} + +void ScOutlineWindow::MouseMove( const MouseEvent& rMEvt ) +{ + if ( IsMouseTracking() ) + { + size_t nLevel, nEntry; + bool bHit = false; + + if ( ButtonHit( rMEvt.GetPosPixel(), nLevel, nEntry ) ) + bHit = (nLevel == mnMTLevel) && (nEntry == mnMTEntry); + + if ( bHit != mbMTPressed ) + DrawBorderRel( mnMTLevel, mnMTEntry, bHit ); + } +} + +void ScOutlineWindow::MouseButtonUp( const MouseEvent& rMEvt ) +{ + if ( IsMouseTracking() ) + { + EndMouseTracking(); + + size_t nLevel, nEntry; + if ( ButtonHit( rMEvt.GetPosPixel(), nLevel, nEntry ) ) + if ( (nLevel == mnMTLevel) && (nEntry == mnMTEntry) ) + DoFunction( nLevel, nEntry ); + } +} + +void ScOutlineWindow::MouseButtonDown( const MouseEvent& rMEvt ) +{ + size_t nLevel, nEntry; + bool bHit = ButtonHit( rMEvt.GetPosPixel(), nLevel, nEntry ); + if ( bHit ) + StartMouseTracking( nLevel, nEntry ); + else if ( rMEvt.GetClicks() == 2 ) + { + bHit = LineHit( rMEvt.GetPosPixel(), nLevel, nEntry ); + if ( bHit ) + DoFunction( nLevel, nEntry ); + } + + // if an item has been hit and window is focused, move focus to this item + if ( bHit && HasFocus() ) + { + HideFocus(); + mnFocusLevel = nLevel; + mnFocusEntry = nEntry; + ShowFocus(); + } +} + + +// keyboard ------------------------------------------------------------------- + +void ScOutlineWindow::KeyInput( const KeyEvent& rKEvt ) +{ + const KeyCode& rKCode = rKEvt.GetKeyCode(); + bool bNoMod = !rKCode.GetModifier(); + bool bShift = (rKCode.GetModifier() == KEY_SHIFT); + bool bCtrl = (rKCode.GetModifier() == KEY_MOD1); + + sal_uInt16 nCode = rKCode.GetCode(); + bool bUpDownKey = (nCode == KEY_UP) || (nCode == KEY_DOWN); + bool bLeftRightKey = (nCode == KEY_LEFT) || (nCode == KEY_RIGHT); + + // TAB key + if ( (nCode == KEY_TAB) && (bNoMod || bShift) ) + // move forward without SHIFT key + MoveFocusByTabOrder( bNoMod ); // TAB uses logical order, regardless of mirroring + + // LEFT/RIGHT/UP/DOWN keys + else if ( bNoMod && (bUpDownKey || bLeftRightKey) ) + { + bool bForward = (nCode == KEY_DOWN) || (nCode == KEY_RIGHT); + if ( mbHoriz == bLeftRightKey ) + // move inside level with LEFT/RIGHT in horizontal and with UP/DOWN in vertical + MoveFocusByEntry( bForward != mbMirrorEntries ); + else + // move to next/prev level with LEFT/RIGHT in vertical and with UP/DOWN in horizontal + MoveFocusByLevel( bForward != mbMirrorLevels ); + } + + // CTRL + number + else if ( bCtrl && (nCode >= KEY_1) && (nCode <= KEY_9) ) + { + size_t nLevel = static_cast< size_t >( nCode - KEY_1 ); + if ( nLevel < GetLevelCount() ) + DoFunction( nLevel, SC_OL_HEADERENTRY ); + } + + // other key codes + else switch ( rKCode.GetFullCode() ) + { + case KEY_ADD: DoExpand( mnFocusLevel, mnFocusEntry ); break; + case KEY_SUBTRACT: DoCollapse( mnFocusLevel, mnFocusEntry ); break; + case KEY_SPACE: + case KEY_RETURN: DoFunction( mnFocusLevel, mnFocusEntry ); break; + default: Window::KeyInput( rKEvt ); + } +} + + +// ============================================================================ + diff --git a/sc/source/ui/view/olkact.cxx b/sc/source/ui/view/olkact.cxx new file mode 100644 index 000000000000..248777f4e473 --- /dev/null +++ b/sc/source/ui/view/olkact.cxx @@ -0,0 +1,282 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +//------------------------------------------------------------------ + +#define _BIGINT_HXX +#define _CACHESTR_HXX +#define _CONFIG_HXX +#define _CURSOR_HXX +#define _CTRLTOOL_HXX +#define _DLGCFG_HXX +#define _DYNARR_HXX +#define _EXTATTR_HXX +#define _FILDLG_HXX +#define _FONTDLG_HXX +#define _FRM3D_HXX +#define _INTRO_HXX +#define _ISETBWR_HXX +#define _NO_SVRTF_PARSER_HXX +#define _MACRODLG_HXX +#define _MODALDLG_HXX +#define _MOREBUTTON_HXX +#define _OUTLINER_HXX +#define _PASSWD_HXX +#define _PRNDLG_HXX +//#define _POLY_HXX +#define _PVRWIN_HXX +#define _QUEUE_HXX +#define _RULER_HXX +#define _SCRWIN_HXX +#define _SETBRW_HXX +#define _STACK_HXX +//#define _STATUS_HXX *** +#define _STDMENU_HXX +#define _TABBAR_HXX +//#define _VCBRW_HXX +#define _VCTRLS_HXX +//#define _VCSBX_HXX +#define _VCONT_HXX +#define _VDRWOBJ_HXX + + +//sfx +#define _SFXAPPWIN_HXX +#define _SFXCTRLITEM +#define _SFXDISPATCH_HXX +#define _SFXFILEDLG_HXX +#define _SFXIMGMGR_HXX +#define _SFXIPFRM_HXX +#define _SFX_MACRO_HXX +#define _SFXMULTISEL_HXX +#define _SFX_MINFITEM_HXX + + +//sfxcore.hxx +//#define _SFXINIMGR_HXX *** +//#define _SFXCFGITEM_HXX +//#define _SFX_PRINTER_HXX +#define _SFXGENLINK_HXX +#define _SFXHINTPOST_HXX +#define _SFXDOCINF_HXX +#define _SFXLINKHDL_HXX +//#define _SFX_PROGRESS_HXX + +//sfxsh.hxx +//#define _SFX_SHELL_HXX +//#define _SFXAPP_HXX +//#define _SFXDISPATCH_HXX +//#define _SFXMSG_HXX *** +//#define _SFXOBJFACE_HXX *** +//#define _SFXREQUEST_HXX +#define _SFXMACRO_HXX + +// SFX +//#define _SFXAPPWIN_HXX *** +#define _SFX_SAVEOPT_HXX +//#define _SFX_CHILDWIN_HXX +//#define _SFXCTRLITEM_HXX +#define _SFXPRNMON_HXX +#define _INTRO_HXX +#define _SFXMSGDESCR_HXX +#define _SFXMSGPOOL_HXX +#define _SFXFILEDLG_HXX +#define _PASSWD_HXX +#define _SFXTBXCTRL_HXX +#define _SFXSTBITEM_HXX +#define _SFXMNUITEM_HXX +#define _SFXIMGMGR_HXX +#define _SFXTBXMGR_HXX +#define _SFXSTBMGR_HXX +#define _SFX_MINFITEM_HXX +#define _SFXEVENT_HXX + +//sfxdoc.hxx +//#define _SFX_OBJSH_HXX +//#define _SFX_CLIENTSH_HXX +//#define _SFXDOCINF_HXX +//#define _SFX_OBJFAC_HXX +#define _SFX_DOCFILT_HXX +//#define _SFXDOCFILE_HXX *** +//define _VIEWFAC_HXX +//#define _SFXVIEWFRM_HXX +//#define _SFXVIEWSH_HXX +//#define _MDIFRM_HXX *** +#define _SFX_IPFRM_HXX +//#define _SFX_INTERNO_HXX + +//sfxdlg.hxx +//#define _SFXTABDLG_HXX +//#define _BASEDLGS_HXX *** +#define _SFX_DINFDLG_HXX +#define _SFXDINFEDT_HXX +#define _SFX_MGETEMPL_HXX +#define _SFX_TPLPITEM_HXX +//#define _SFX_STYLEDLG_HXX +#define _NEWSTYLE_HXX +//#define _SFXDOCTEMPL_HXX *** +//#define _SFXDOCTDLG_HXX *** +//#define _SFX_TEMPLDLG_HXX *** +//#define _SFXNEW_HXX *** +#define _SFXDOCMAN_HXX +//#define _SFXDOCKWIN_HXX + +//sfxitems.hxx +#define _SFX_WHMAP_HXX +#define _ARGS_HXX +//#define _SFXPOOLITEM_HXX +//#define _SFXINTITEM_HXX +//#define _SFXENUMITEM_HXX +#define _SFXFLAGITEM_HXX +//#define _SFXSTRITEM_HXX +#define _SFXPTITEM_HXX +#define _SFXRECTITEM_HXX +//#define _SFXITEMPOOL_HXX +//#define _SFXITEMSET_HXX +#define _SFXITEMITER_HXX +#define _SFX_WHITER_HXX +#define _SFXPOOLCACH_HXX +//#define _AEITEM_HXX +#define _SFXRNGITEM_HXX +//#define _SFXSLSTITM_HXX +//#define _SFXSTYLE_HXX + +//xout.hxx +//#define _XENUM_HXX +//#define _XPOLY_HXX +//#define _XATTR_HXX +//#define _XOUTX_HXX +//#define _XPOOL_HXX +//#define _XTABLE_HXX + +//svdraw.hxx +#define _SDR_NOITEMS +#define _SDR_NOTOUCH +#define _SDR_NOTRANSFORM +//#define _SDR_NOOBJECTS +//#define _SDR_NOVIEWS + + + + +#define _SFXBASIC_HXX +#define _SFX_DOCFILE_HXX +#define _SFX_DOCFILT_HXX +#define _SFX_DOCINF_HXX +#define _SFX_DOCSH_HXX +#define _SFX_TEMPLDLG_HXX +#define _SFXSTBMGR_HXX +#define _SFXTBXMGR_HXX +#define _SFXIMGMGR_HXX +#define _SFXMNUITEM_HXX +#define _SFXMNUMGR_HXX +#define _SFXSTBITEM_HXX +#define _SFXTBXCTRL_HXX +#define _SFXFILEDLG_HXX +#define _SFXREQUEST_HXX +#define _SFXOBJFACE_HXX +#define _SFXMSGPOOL_HXX +#define _SFXMSGDESCR_HXX +#define _SFXMSG_HXX +#define _SFX_PRNMON_HXX + +//si +#define _SI_NOSBXCONTROLS +#define _SI_NOCONTROL +//#define SI_NOITEMS +//#define SI_NODRW +//#define SI_NOOTHERFORMS +#define _SIDLL_HXX +//#define _VCSBX_HXX +//#define _VCBRW_HXX + +//#define _SVDATTR_HXX <--- der wars +#define _SVDXOUT_HXX +#define _SVDEC_HXX +//#define _SVDIO_HXX +//#define _SVDLAYER_HXX +//#define _SVDRAG_HXX +#define _SVINCVW_HXX +//#define _SV_MULTISEL_HXX +#define _SVRTV_HXX +#define _SVTABBX_HXX + +#define _SVX_DAILDLL_HXX +#define _SVX_HYPHEN_HXX +#define _SVX_IMPGRF_HXX +#define _SVX_OPTITEMS_HXX +#define _SVX_OPTGERL_HXX +#define _SVX_OPTSAVE_HXX +#define _SVX_OPTSPELL_HXX +#define _SVX_OPTPATH_HXX +#define _SVX_OPTLINGU_HXX +#define _SVX_RULER_HXX +#define _SVX_RULRITEM_HXX +#define _SVX_SPLWRAP_HXX +#define _SVX_SPLDLG_HXX +#define _SVX_THESDLG_HXX + +// INCLUDE --------------------------------------------------------------- + +#include <sfx2/childwin.hxx> +#include <sfx2/objsh.hxx> + +#include "document.hxx" +#include "viewdata.hxx" +#include "drawview.hxx" +#include "drawpage.hxx" +#include "drwlayer.hxx" + +// STATIC DATA ----------------------------------------------------------- + +// ----------------------------------------------------------------------- + +void ActivateOlk( ScViewData* /* pViewData */ ) +{ + // Browser fuer Virtual Controls fuellen + // VC's und den Browser dazu gibts nicht mehr... + + // GetSbxForm gibt's nicht mehr, muss auch nichts mehr angemeldet werden +} + +void DeActivateOlk( ScViewData* /* pViewData */ ) +{ + // Browser fuer Virtual Controls fuellen + // VC's und den Browser dazu gibts nicht mehr... + + // GetSbxForm gibt's nicht mehr, muss auch nichts mehr angemeldet werden +} + + + + + diff --git a/sc/source/ui/view/output.cxx b/sc/source/ui/view/output.cxx new file mode 100644 index 000000000000..885a1ae2a778 --- /dev/null +++ b/sc/source/ui/view/output.cxx @@ -0,0 +1,2476 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +// INCLUDE --------------------------------------------------------------- + +#include <com/sun/star/embed/EmbedMisc.hpp> + +#include "scitems.hxx" +#include <editeng/boxitem.hxx> +#include <editeng/brshitem.hxx> +#include <editeng/editdata.hxx> +#include <svtools/colorcfg.hxx> +#include <svx/rotmodit.hxx> +#include <editeng/shaditem.hxx> +#include <editeng/svxfont.hxx> +#include <svx/svdoole2.hxx> +#include <tools/poly.hxx> +#include <vcl/svapp.hxx> +#include <vcl/pdfextoutdevdata.hxx> +#include <svtools/accessibilityoptions.hxx> +#include <svx/framelinkarray.hxx> + +#include "output.hxx" +#include "document.hxx" +#include "cell.hxx" +#include "attrib.hxx" +#include "patattr.hxx" +#include "docpool.hxx" +#include "tabvwsh.hxx" +#include "progress.hxx" +#include "pagedata.hxx" +#include "chgtrack.hxx" +#include "chgviset.hxx" +#include "viewutil.hxx" +#include "gridmerg.hxx" +#include "invmerge.hxx" +#include "fillinfo.hxx" +#include "scmod.hxx" +#include "appoptio.hxx" +#include "postit.hxx" + +#include <math.h> + +using namespace com::sun::star; + +// STATIC DATA ----------------------------------------------------------- + +// Farben fuer ChangeTracking "nach Autor" wie im Writer (swmodul1.cxx) + +#define SC_AUTHORCOLORCOUNT 9 + +static ColorData nAuthorColor[ SC_AUTHORCOLORCOUNT ] = { + COL_LIGHTRED, COL_LIGHTBLUE, COL_LIGHTMAGENTA, + COL_GREEN, COL_RED, COL_BLUE, + COL_BROWN, COL_MAGENTA, COL_CYAN }; + +// Hilfsklasse, fuer die Farbzuordnung, +// um nicht mehrfach hintereinander denselben User aus der Liste zu suchen + +class ScActionColorChanger +{ +private: + const ScAppOptions& rOpt; + const ScStrCollection& rUsers; + String aLastUserName; + sal_uInt16 nLastUserIndex; + ColorData nColor; + +public: + ScActionColorChanger( const ScChangeTrack& rTrack ); + ~ScActionColorChanger() {} + + void Update( const ScChangeAction& rAction ); + ColorData GetColor() const { return nColor; } +}; + +//------------------------------------------------------------------ + +ScActionColorChanger::ScActionColorChanger( const ScChangeTrack& rTrack ) : + rOpt( SC_MOD()->GetAppOptions() ), + rUsers( rTrack.GetUserCollection() ), + nLastUserIndex( 0 ), + nColor( COL_BLACK ) +{ +} + +void ScActionColorChanger::Update( const ScChangeAction& rAction ) +{ + ColorData nSetColor; + switch (rAction.GetType()) + { + case SC_CAT_INSERT_COLS: + case SC_CAT_INSERT_ROWS: + case SC_CAT_INSERT_TABS: + nSetColor = rOpt.GetTrackInsertColor(); + break; + case SC_CAT_DELETE_COLS: + case SC_CAT_DELETE_ROWS: + case SC_CAT_DELETE_TABS: + nSetColor = rOpt.GetTrackDeleteColor(); + break; + case SC_CAT_MOVE: + nSetColor = rOpt.GetTrackMoveColor(); + break; + default: + nSetColor = rOpt.GetTrackContentColor(); + break; + } + if ( nSetColor != COL_TRANSPARENT ) // Farbe eingestellt + nColor = nSetColor; + else // nach Autor + { + if ( rAction.GetUser() != aLastUserName ) + { + aLastUserName = rAction.GetUser(); + StrData aData(aLastUserName); + sal_uInt16 nIndex; + if (!rUsers.Search(&aData, nIndex)) + { + // empty string is possible if a name wasn't found while saving a 5.0 file + DBG_ASSERT( aLastUserName.Len() == 0, "Author not found" ); + nIndex = 0; + } + nLastUserIndex = nIndex % SC_AUTHORCOLORCOUNT; + } + nColor = nAuthorColor[nLastUserIndex]; + } +} + +//================================================================== + +ScOutputData::ScOutputData( OutputDevice* pNewDev, ScOutputType eNewType, + ScTableInfo& rTabInfo, ScDocument* pNewDoc, + SCTAB nNewTab, long nNewScrX, long nNewScrY, + SCCOL nNewX1, SCROW nNewY1, SCCOL nNewX2, SCROW nNewY2, + double nPixelPerTwipsX, double nPixelPerTwipsY, + const Fraction* pZoomX, const Fraction* pZoomY ) : + pDev( pNewDev ), + pRefDevice( pNewDev ), // default is output device + pFmtDevice( pNewDev ), // default is output device + mrTabInfo( rTabInfo ), + pRowInfo( rTabInfo.mpRowInfo ), + nArrCount( rTabInfo.mnArrCount ), + pDoc( pNewDoc ), + nTab( nNewTab ), + nScrX( nNewScrX ), + nScrY( nNewScrY ), + nX1( nNewX1 ), + nY1( nNewY1 ), + nX2( nNewX2 ), + nY2( nNewY2 ), + eType( eNewType ), + nPPTX( nPixelPerTwipsX ), + nPPTY( nPixelPerTwipsY ), + pEditObj( NULL ), + pViewShell( NULL ), + pDrawView( NULL ), // #114135# + bEditMode( sal_False ), + bMetaFile( sal_False ), + bSingleGrid( sal_False ), + bPagebreakMode( sal_False ), + bSolidBackground( sal_False ), + bUseStyleColor( sal_False ), + bForceAutoColor( SC_MOD()->GetAccessOptions().GetIsAutomaticFontColor() ), + bSyntaxMode( sal_False ), + pValueColor( NULL ), + pTextColor( NULL ), + pFormulaColor( NULL ), + aGridColor( COL_BLACK ), + bShowNullValues( sal_True ), + bShowFormulas( sal_False ), + bShowSpellErrors( sal_False ), + bMarkClipped( sal_False ), // sal_False fuer Drucker/Metafile etc. + bSnapPixel( sal_False ), + bAnyRotated( sal_False ), + bAnyClipped( sal_False ), + mpTargetPaintWindow(0) // #i74769# use SdrPaintWindow direct +{ + if (pZoomX) + aZoomX = *pZoomX; + else + aZoomX = Fraction(1,1); + if (pZoomY) + aZoomY = *pZoomY; + else + aZoomY = Fraction(1,1); + + nVisX1 = nX1; + nVisY1 = nY1; + nVisX2 = nX2; + nVisY2 = nY2; + pDoc->StripHidden( nVisX1, nVisY1, nVisX2, nVisY2, nTab ); + + nScrW = 0; + for (SCCOL nX=nVisX1; nX<=nVisX2; nX++) + nScrW += pRowInfo[0].pCellInfo[nX+1].nWidth; + + nMirrorW = nScrW; + + nScrH = 0; + for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++) + nScrH += pRowInfo[nArrY].nHeight; + + bTabProtected = pDoc->IsTabProtected( nTab ); + nTabTextDirection = pDoc->GetEditTextDirection( nTab ); + bLayoutRTL = pDoc->IsLayoutRTL( nTab ); +} + +ScOutputData::~ScOutputData() +{ + delete pValueColor; + delete pTextColor; + delete pFormulaColor; +} + +void ScOutputData::SetContentDevice( OutputDevice* pContentDev ) +{ + // use pContentDev instead of pDev where used + + if ( pRefDevice == pDev ) + pRefDevice = pContentDev; + if ( pFmtDevice == pDev ) + pFmtDevice = pContentDev; + pDev = pContentDev; +} + +void ScOutputData::SetMirrorWidth( long nNew ) +{ + nMirrorW = nNew; +} + +void ScOutputData::SetGridColor( const Color& rColor ) +{ + aGridColor = rColor; +} + +void ScOutputData::SetMarkClipped( sal_Bool bSet ) +{ + bMarkClipped = bSet; +} + +void ScOutputData::SetShowNullValues( sal_Bool bSet ) +{ + bShowNullValues = bSet; +} + +void ScOutputData::SetShowFormulas( sal_Bool bSet ) +{ + bShowFormulas = bSet; +} + +void ScOutputData::SetShowSpellErrors( sal_Bool bSet ) +{ + bShowSpellErrors = bSet; +} + +void ScOutputData::SetSnapPixel( sal_Bool bSet ) +{ + bSnapPixel = bSet; +} + +void ScOutputData::SetEditCell( SCCOL nCol, SCROW nRow ) +{ + nEditCol = nCol; + nEditRow = nRow; + bEditMode = sal_True; +} + +void ScOutputData::SetMetaFileMode( sal_Bool bNewMode ) +{ + bMetaFile = bNewMode; +} + +void ScOutputData::SetSingleGrid( sal_Bool bNewMode ) +{ + bSingleGrid = bNewMode; +} + +void ScOutputData::SetSyntaxMode( sal_Bool bNewMode ) +{ + bSyntaxMode = bNewMode; + if (bNewMode) + if (!pValueColor) + { + pValueColor = new Color( COL_LIGHTBLUE ); + pTextColor = new Color( COL_BLACK ); + pFormulaColor = new Color( COL_GREEN ); + } +} + +void ScOutputData::DrawGrid( sal_Bool bGrid, sal_Bool bPage ) +{ + SCCOL nX; + SCROW nY; + long nPosX; + long nPosY; + SCSIZE nArrY; + ScBreakType nBreak = BREAK_NONE; + ScBreakType nBreakOld = BREAK_NONE; + + sal_Bool bSingle; + Color aPageColor; + Color aManualColor; + + if (bPagebreakMode) + bPage = sal_False; // keine "normalen" Umbrueche ueber volle Breite/Hoehe + + //! um den einen Pixel sieht das Metafile (oder die Druck-Ausgabe) anders aus + //! als die Bildschirmdarstellung, aber wenigstens passen Druck und Metafile zusammen + + Size aOnePixel = pDev->PixelToLogic(Size(1,1)); + long nOneX = aOnePixel.Width(); + long nOneY = aOnePixel.Height(); + if (bMetaFile) + nOneX = nOneY = 1; + + long nLayoutSign = bLayoutRTL ? -1 : 1; + long nSignedOneX = nOneX * nLayoutSign; + + if ( eType == OUTTYPE_WINDOW ) + { + const svtools::ColorConfig& rColorCfg = SC_MOD()->GetColorConfig(); + aPageColor.SetColor( rColorCfg.GetColorValue(svtools::CALCPAGEBREAKAUTOMATIC).nColor ); + aManualColor.SetColor( rColorCfg.GetColorValue(svtools::CALCPAGEBREAKMANUAL).nColor ); + } + else + { + aPageColor = aGridColor; + aManualColor = aGridColor; + } + + pDev->SetLineColor( aGridColor ); + ScGridMerger aGrid( pDev, nOneX, nOneY ); + + // + // Vertikale Linien + // + + nPosX = nScrX; + if ( bLayoutRTL ) + nPosX += nMirrorW - nOneX; + + for (nX=nX1; nX<=nX2; nX++) + { + SCCOL nXplus1 = nX+1; + SCCOL nXplus2 = nX+2; + sal_uInt16 nWidth = pRowInfo[0].pCellInfo[nXplus1].nWidth; + if (nWidth) + { + nPosX += nWidth * nLayoutSign; + + if ( bPage ) + { + // Seitenumbrueche auch in ausgeblendeten suchen + SCCOL nCol = nXplus1; + while (nCol <= MAXCOL) + { + nBreak = pDoc->HasColBreak(nCol, nTab); + bool bHidden = pDoc->ColHidden(nCol, nTab); + + if ( nBreak || !bHidden ) + break; + ++nCol; + } + + if (nBreak != nBreakOld) + { + aGrid.Flush(); + pDev->SetLineColor( (nBreak & BREAK_MANUAL) ? aManualColor : + nBreak ? aPageColor : aGridColor ); + nBreakOld = nBreak; + } + } + + sal_Bool bDraw = bGrid || nBreakOld; // einfaches Gitter nur wenn eingestellt + + //! Mit dieser Abfrage wird zuviel weggelassen, wenn ein automatischer + //! Umbruch mitten in den Wiederholungsspalten liegt. + //! Dann lieber den aeusseren Rahmen zweimal ausgeben... +#if 0 + // auf dem Drucker die Aussen-Linien weglassen (werden getrennt ausgegeben) + if ( eType == OUTTYPE_PRINTER && !bMetaFile ) + { + if ( nX == MAXCOL ) + bDraw = sal_False; + else if (pDoc->HasColBreak(nXplus1, nTab)) + bDraw = sal_False; + } +#endif + + sal_uInt16 nWidthXplus2 = pRowInfo[0].pCellInfo[nXplus2].nWidth; + bSingle = bSingleGrid; //! in Fillinfo holen !!!!! + if ( nX<MAXCOL && !bSingle ) + { + bSingle = ( nWidthXplus2 == 0 ); + for (nArrY=1; nArrY+1<nArrCount && !bSingle; nArrY++) + { + if (pRowInfo[nArrY].pCellInfo[nXplus2].bHOverlapped) + bSingle = sal_True; + if (pRowInfo[nArrY].pCellInfo[nXplus1].bHideGrid) + bSingle = sal_True; + } + } + + if (bDraw) + { + if ( nX<MAXCOL && bSingle ) + { + SCCOL nVisX = nXplus1; + while ( nVisX < MAXCOL && !pDoc->GetColWidth(nVisX,nTab) ) + ++nVisX; + + nPosY = nScrY; + long nNextY; + for (nArrY=1; nArrY+1<nArrCount; nArrY++) + { + RowInfo* pThisRowInfo = &pRowInfo[nArrY]; + nNextY = nPosY + pThisRowInfo->nHeight; + + sal_Bool bHOver = pThisRowInfo->pCellInfo[nXplus1].bHideGrid; + if (!bHOver) + { + if (nWidthXplus2) + bHOver = pThisRowInfo->pCellInfo[nXplus2].bHOverlapped; + else + { + if (nVisX <= nX2) + bHOver = pThisRowInfo->pCellInfo[nVisX+1].bHOverlapped; + else + bHOver = ((ScMergeFlagAttr*)pDoc->GetAttr( + nVisX,pThisRowInfo->nRowNo,nTab,ATTR_MERGE_FLAG)) + ->IsHorOverlapped(); + if (bHOver) + bHOver = ((ScMergeFlagAttr*)pDoc->GetAttr( + nXplus1,pThisRowInfo->nRowNo,nTab,ATTR_MERGE_FLAG)) + ->IsHorOverlapped(); + } + } + + if (pThisRowInfo->bChanged && !bHOver) + { + //Point aStart( nPosX-nSignedOneX, nPosY ); + //Point aEnd( nPosX-nSignedOneX, nNextY-nOneY ); + //pDev->DrawLine( aStart, aEnd ); + aGrid.AddVerLine( nPosX-nSignedOneX, nPosY, nNextY-nOneY ); + } + nPosY = nNextY; + } + } + else + { + //Point aStart( nPosX-nSignedOneX, nScrY ); + //Point aEnd( nPosX-nSignedOneX, nScrY+nScrH-nOneY ); + //pDev->DrawLine( aStart, aEnd ); + aGrid.AddVerLine( nPosX-nSignedOneX, nScrY, nScrY+nScrH-nOneY ); + } + } + } + } + + // + // Horizontale Linien + // + + bool bHiddenRow = true; + SCROW nHiddenEndRow = -1; + nPosY = nScrY; + for (nArrY=1; nArrY+1<nArrCount; nArrY++) + { + SCSIZE nArrYplus1 = nArrY+1; + nY = pRowInfo[nArrY].nRowNo; + SCROW nYplus1 = nY+1; + nPosY += pRowInfo[nArrY].nHeight; + + if (pRowInfo[nArrY].bChanged) + { + if ( bPage ) + { + for (SCROW i = nYplus1; i <= MAXROW; ++i) + { + if (i > nHiddenEndRow) + bHiddenRow = pDoc->RowHidden(i, nTab, nHiddenEndRow); + /* TODO: optimize the row break thing for large hidden + * segments where HasRowBreak() has to be called + * nevertheless for each row, as a row break is drawn also + * for hidden rows, above them. This needed to be done only + * once per hidden segment, maybe giving manual breaks + * priority. Something like GetNextRowBreak() and + * GetNextManualRowBreak(). */ + nBreak = pDoc->HasRowBreak(i, nTab); + if (!bHiddenRow || nBreak) + break; + } + + if (nBreakOld != nBreak) + { + aGrid.Flush(); + pDev->SetLineColor( (nBreak & BREAK_MANUAL) ? aManualColor : + (nBreak) ? aPageColor : aGridColor ); + nBreakOld = nBreak; + } + } + + sal_Bool bDraw = bGrid || nBreakOld; // einfaches Gitter nur wenn eingestellt + + //! Mit dieser Abfrage wird zuviel weggelassen, wenn ein automatischer + //! Umbruch mitten in den Wiederholungszeilen liegt. + //! Dann lieber den aeusseren Rahmen zweimal ausgeben... +#if 0 + // auf dem Drucker die Aussen-Linien weglassen (werden getrennt ausgegeben) + if ( eType == OUTTYPE_PRINTER && !bMetaFile ) + { + if ( nY == MAXROW ) + bDraw = sal_False; + else if (pDoc->HasRowBreak(nYplus1, nTab)) + bDraw = sal_False; + } +#endif + + sal_Bool bNextYisNextRow = (pRowInfo[nArrYplus1].nRowNo == nYplus1); + bSingle = !bNextYisNextRow; // Hidden + for (SCCOL i=nX1; i<=nX2 && !bSingle; i++) + { + if (pRowInfo[nArrYplus1].pCellInfo[i+1].bVOverlapped) + bSingle = sal_True; + } + + if (bDraw) + { + if ( bSingle && nY<MAXROW ) + { + SCROW nVisY = pRowInfo[nArrYplus1].nRowNo; + + nPosX = nScrX; + if ( bLayoutRTL ) + nPosX += nMirrorW - nOneX; + + long nNextX; + for (SCCOL i=nX1; i<=nX2; i++) + { + nNextX = nPosX + pRowInfo[0].pCellInfo[i+1].nWidth * nLayoutSign; + if (nNextX != nPosX) // sichtbar + { + sal_Bool bVOver; + if ( bNextYisNextRow ) + bVOver = pRowInfo[nArrYplus1].pCellInfo[i+1].bVOverlapped; + else + { + bVOver = ((ScMergeFlagAttr*)pDoc->GetAttr( + i,nYplus1,nTab,ATTR_MERGE_FLAG)) + ->IsVerOverlapped() + && ((ScMergeFlagAttr*)pDoc->GetAttr( + i,nVisY,nTab,ATTR_MERGE_FLAG)) + ->IsVerOverlapped(); + //! nVisY aus Array ?? + } + if (!bVOver) + { + //Point aStart( nPosX, nPosY-nOneY ); + //Point aEnd( nNextX-nSignedOneX, nPosY-nOneY ); + //pDev->DrawLine( aStart, aEnd ); + aGrid.AddHorLine( nPosX, nNextX-nSignedOneX, nPosY-nOneY ); + } + } + nPosX = nNextX; + } + } + else + { + //Point aStart( nScrX, nPosY-nOneY ); + //Point aEnd( nScrX+nScrW-nOneX, nPosY-nOneY ); + //pDev->DrawLine( aStart, aEnd ); + aGrid.AddHorLine( nScrX, nScrX+nScrW-nOneX, nPosY-nOneY ); + } + } + } + } +} + +// ---------------------------------------------------------------------------- + +void ScOutputData::SetPagebreakMode( ScPageBreakData* pPageData ) +{ + bPagebreakMode = sal_True; + if (!pPageData) + return; // noch nicht initialisiert -> alles "nicht gedruckt" + + // gedruckten Bereich markieren + // (in FillInfo ist schon alles auf sal_False initialisiert) + + sal_uInt16 nRangeCount = sal::static_int_cast<sal_uInt16>(pPageData->GetCount()); + for (sal_uInt16 nPos=0; nPos<nRangeCount; nPos++) + { + ScRange aRange = pPageData->GetData( nPos ).GetPrintRange(); + + SCCOL nStartX = Max( aRange.aStart.Col(), nX1 ); + SCCOL nEndX = Min( aRange.aEnd.Col(), nX2 ); + SCROW nStartY = Max( aRange.aStart.Row(), nY1 ); + SCROW nEndY = Min( aRange.aEnd.Row(), nY2 ); + + for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++) + { + RowInfo* pThisRowInfo = &pRowInfo[nArrY]; + if ( pThisRowInfo->bChanged && pThisRowInfo->nRowNo >= nStartY && + pThisRowInfo->nRowNo <= nEndY ) + { + for (SCCOL nX=nStartX; nX<=nEndX; nX++) + pThisRowInfo->pCellInfo[nX+1].bPrinted = sal_True; + } + } + } +} + +void ScOutputData::FindRotated() +{ + //! nRotMax speichern + SCCOL nRotMax = nX2; + for (SCSIZE nRotY=0; nRotY<nArrCount; nRotY++) + if (pRowInfo[nRotY].nRotMaxCol != SC_ROTMAX_NONE && pRowInfo[nRotY].nRotMaxCol > nRotMax) + nRotMax = pRowInfo[nRotY].nRotMaxCol; + + for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++) + { + RowInfo* pThisRowInfo = &pRowInfo[nArrY]; + if ( pThisRowInfo->nRotMaxCol != SC_ROTMAX_NONE && + ( pThisRowInfo->bChanged || pRowInfo[nArrY-1].bChanged || + ( nArrY+1<nArrCount && pRowInfo[nArrY+1].bChanged ) ) ) + { + SCROW nY = pThisRowInfo->nRowNo; + + for (SCCOL nX=0; nX<=nRotMax; nX++) + { + CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1]; + const ScPatternAttr* pPattern = pInfo->pPatternAttr; + const SfxItemSet* pCondSet = pInfo->pConditionSet; + + if ( !pPattern && !pDoc->ColHidden(nX, nTab) ) + { + pPattern = pDoc->GetPattern( nX, nY, nTab ); + pCondSet = pDoc->GetCondResult( nX, nY, nTab ); + } + + if ( pPattern ) // Spalte nicht ausgeblendet + { + sal_uInt8 nDir = pPattern->GetRotateDir( pCondSet ); + if (nDir != SC_ROTDIR_NONE) + { + pInfo->nRotateDir = nDir; + bAnyRotated = sal_True; + } + } + } + } + } +} + +// ---------------------------------------------------------------------------- + +sal_uInt16 lcl_GetRotateDir( ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab ) +{ + const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab ); + const SfxItemSet* pCondSet = pDoc->GetCondResult( nCol, nRow, nTab ); + + sal_uInt16 nRet = SC_ROTDIR_NONE; + + long nAttrRotate = pPattern->GetRotateVal( pCondSet ); + if ( nAttrRotate ) + { + SvxRotateMode eRotMode = (SvxRotateMode)((const SvxRotateModeItem&) + pPattern->GetItem(ATTR_ROTATE_MODE, pCondSet)).GetValue(); + + if ( eRotMode == SVX_ROTATE_MODE_STANDARD ) + nRet = SC_ROTDIR_STANDARD; + else if ( eRotMode == SVX_ROTATE_MODE_CENTER ) + nRet = SC_ROTDIR_CENTER; + else if ( eRotMode == SVX_ROTATE_MODE_TOP || eRotMode == SVX_ROTATE_MODE_BOTTOM ) + { + long nRot180 = nAttrRotate % 18000; // 1/100 Grad + if ( nRot180 == 9000 ) + nRet = SC_ROTDIR_CENTER; + else if ( ( eRotMode == SVX_ROTATE_MODE_TOP && nRot180 < 9000 ) || + ( eRotMode == SVX_ROTATE_MODE_BOTTOM && nRot180 > 9000 ) ) + nRet = SC_ROTDIR_LEFT; + else + nRet = SC_ROTDIR_RIGHT; + } + } + + return nRet; +} + +const SvxBrushItem* lcl_FindBackground( ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab ) +{ + const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab ); + const SfxItemSet* pCondSet = pDoc->GetCondResult( nCol, nRow, nTab ); + const SvxBrushItem* pBackground = (const SvxBrushItem*) + &pPattern->GetItem( ATTR_BACKGROUND, pCondSet ); + + sal_uInt16 nDir = lcl_GetRotateDir( pDoc, nCol, nRow, nTab ); + + // CENTER wird wie RIGHT behandelt... + if ( nDir == SC_ROTDIR_RIGHT || nDir == SC_ROTDIR_CENTER ) + { + // Text geht nach rechts -> Hintergrund von links nehmen + while ( nCol > 0 && lcl_GetRotateDir( pDoc, nCol, nRow, nTab ) == nDir && + pBackground->GetColor().GetTransparency() != 255 ) + { + --nCol; + pPattern = pDoc->GetPattern( nCol, nRow, nTab ); + pCondSet = pDoc->GetCondResult( nCol, nRow, nTab ); + pBackground = (const SvxBrushItem*)&pPattern->GetItem( ATTR_BACKGROUND, pCondSet ); + } + } + else if ( nDir == SC_ROTDIR_LEFT ) + { + // Text geht nach links -> Hintergrund von rechts nehmen + while ( nCol < MAXCOL && lcl_GetRotateDir( pDoc, nCol, nRow, nTab ) == nDir && + pBackground->GetColor().GetTransparency() != 255 ) + { + ++nCol; + pPattern = pDoc->GetPattern( nCol, nRow, nTab ); + pCondSet = pDoc->GetCondResult( nCol, nRow, nTab ); + pBackground = (const SvxBrushItem*)&pPattern->GetItem( ATTR_BACKGROUND, pCondSet ); + } + } + + return pBackground; +} + +// ---------------------------------------------------------------------------- + +sal_Bool lcl_EqualBack( const RowInfo& rFirst, const RowInfo& rOther, + SCCOL nX1, SCCOL nX2, sal_Bool bShowProt, sal_Bool bPagebreakMode ) +{ + if ( rFirst.bChanged != rOther.bChanged || + rFirst.bEmptyBack != rOther.bEmptyBack ) + return sal_False; + + SCCOL nX; + if ( bShowProt ) + { + for ( nX=nX1; nX<=nX2; nX++ ) + { + const ScPatternAttr* pPat1 = rFirst.pCellInfo[nX+1].pPatternAttr; + const ScPatternAttr* pPat2 = rOther.pCellInfo[nX+1].pPatternAttr; + if ( !pPat1 || !pPat2 || + &pPat1->GetItem(ATTR_PROTECTION) != &pPat2->GetItem(ATTR_PROTECTION) ) + return sal_False; + } + } + else + { + for ( nX=nX1; nX<=nX2; nX++ ) + if ( rFirst.pCellInfo[nX+1].pBackground != rOther.pCellInfo[nX+1].pBackground ) + return sal_False; + } + + if ( rFirst.nRotMaxCol != SC_ROTMAX_NONE || rOther.nRotMaxCol != SC_ROTMAX_NONE ) + for ( nX=nX1; nX<=nX2; nX++ ) + if ( rFirst.pCellInfo[nX+1].nRotateDir != rOther.pCellInfo[nX+1].nRotateDir ) + return sal_False; + + if ( bPagebreakMode ) + for ( nX=nX1; nX<=nX2; nX++ ) + if ( rFirst.pCellInfo[nX+1].bPrinted != rOther.pCellInfo[nX+1].bPrinted ) + return sal_False; + + return sal_True; +} + +void ScOutputData::DrawBackground() +{ + FindRotated(); //! von aussen ? + + ScModule* pScMod = SC_MOD(); + + // used only if bSolidBackground is set (only for ScGridWindow): + Color aBgColor( pScMod->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor ); + + Rectangle aRect; + Size aOnePixel = pDev->PixelToLogic(Size(1,1)); + long nOneX = aOnePixel.Width(); + long nOneY = aOnePixel.Height(); + + if (bMetaFile) + nOneX = nOneY = 0; + + long nLayoutSign = bLayoutRTL ? -1 : 1; + long nSignedOneX = nOneX * nLayoutSign; + + pDev->SetLineColor(); + + sal_Bool bShowProt = bSyntaxMode && pDoc->IsTabProtected(nTab); + sal_Bool bDoAll = bShowProt || bPagebreakMode || bSolidBackground; + + // #105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed sal_True) + sal_Bool bCellContrast = bUseStyleColor && + Application::GetSettings().GetStyleSettings().GetHighContrastMode(); + + long nPosY = nScrY; + for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++) + { + RowInfo* pThisRowInfo = &pRowInfo[nArrY]; + long nRowHeight = pThisRowInfo->nHeight; + + if ( pThisRowInfo->bChanged ) + { + if ( ( ( pThisRowInfo->bEmptyBack ) || bSyntaxMode ) && !bDoAll ) + { + // nichts + } + else + { + // scan for rows with the same background: + SCSIZE nSkip = 0; + while ( nArrY+nSkip+2<nArrCount && + lcl_EqualBack( *pThisRowInfo, pRowInfo[nArrY+nSkip+1], + nX1, nX2, bShowProt, bPagebreakMode ) ) + { + ++nSkip; + nRowHeight += pRowInfo[nArrY+nSkip].nHeight; // after incrementing + } + + long nPosX = nScrX; + if ( bLayoutRTL ) + nPosX += nMirrorW - nOneX; + aRect = Rectangle( nPosX,nPosY, nPosX,nPosY+nRowHeight-nOneY ); + + const SvxBrushItem* pOldBackground = NULL; + const SvxBrushItem* pBackground; + for (SCCOL nX=nX1; nX<=nX2; nX++) + { + CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1]; + + if (bCellContrast) + { + // high contrast for cell borders and backgrounds -> empty background + pBackground = ScGlobal::GetEmptyBrushItem(); + } + else if (bShowProt) // show cell protection in syntax mode + { + const ScPatternAttr* pP = pInfo->pPatternAttr; + if (pP) + { + const ScProtectionAttr& rProt = (const ScProtectionAttr&) + pP->GetItem(ATTR_PROTECTION); + if (rProt.GetProtection() || rProt.GetHideCell()) + pBackground = ScGlobal::GetProtectedBrushItem(); + else + pBackground = ScGlobal::GetEmptyBrushItem(); + } + else + pBackground = NULL; + } + else + pBackground = pInfo->pBackground; + + if ( bPagebreakMode && !pInfo->bPrinted ) + pBackground = ScGlobal::GetProtectedBrushItem(); + + if ( pInfo->nRotateDir > SC_ROTDIR_STANDARD && + pBackground->GetColor().GetTransparency() != 255 && + !bCellContrast ) + { + SCROW nY = pRowInfo[nArrY].nRowNo; + pBackground = lcl_FindBackground( pDoc, nX, nY, nTab ); + } + + if ( pBackground != pOldBackground ) + { + aRect.Right() = nPosX-nSignedOneX; + if (pOldBackground) // ==0 if hidden + { + Color aBackCol = pOldBackground->GetColor(); + if ( bSolidBackground && aBackCol.GetTransparency() ) + aBackCol = aBgColor; + if ( !aBackCol.GetTransparency() ) //! partial transparency? + { + pDev->SetFillColor( aBackCol ); + pDev->DrawRect( aRect ); + } + } + aRect.Left() = nPosX; + pOldBackground = pBackground; + } + nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign; + } + aRect.Right() = nPosX-nSignedOneX; + if (pOldBackground) + { + Color aBackCol = pOldBackground->GetColor(); + if ( bSolidBackground && aBackCol.GetTransparency() ) + aBackCol = aBgColor; + if ( !aBackCol.GetTransparency() ) //! partial transparency? + { + pDev->SetFillColor( aBackCol ); + pDev->DrawRect( aRect ); + } + } + + nArrY += nSkip; + } + } + nPosY += nRowHeight; + } +} + +void ScOutputData::DrawShadow() +{ + DrawExtraShadow( sal_False, sal_False, sal_False, sal_False ); +} + +void ScOutputData::DrawExtraShadow(sal_Bool bLeft, sal_Bool bTop, sal_Bool bRight, sal_Bool bBottom) +{ + pDev->SetLineColor(); + + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + // #105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed sal_True) + sal_Bool bCellContrast = bUseStyleColor && rStyleSettings.GetHighContrastMode(); + Color aAutoTextColor; + if ( bCellContrast ) + aAutoTextColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor ); + + long nInitPosX = nScrX; + if ( bLayoutRTL ) + { + Size aOnePixel = pDev->PixelToLogic(Size(1,1)); + long nOneX = aOnePixel.Width(); + nInitPosX += nMirrorW - nOneX; + } + long nLayoutSign = bLayoutRTL ? -1 : 1; + + long nPosY = nScrY - pRowInfo[0].nHeight; + for (SCSIZE nArrY=0; nArrY<nArrCount; nArrY++) + { + sal_Bool bCornerY = ( nArrY == 0 ) || ( nArrY+1 == nArrCount ); + sal_Bool bSkipY = ( nArrY==0 && !bTop ) || ( nArrY+1 == nArrCount && !bBottom ); + + RowInfo* pThisRowInfo = &pRowInfo[nArrY]; + long nRowHeight = pThisRowInfo->nHeight; + + if ( pThisRowInfo->bChanged && !bSkipY ) + { + long nPosX = nInitPosX - pRowInfo[0].pCellInfo[nX1].nWidth * nLayoutSign; + for (SCCOL nArrX=nX1; nArrX<=nX2+2; nArrX++) + { + sal_Bool bCornerX = ( nArrX==nX1 || nArrX==nX2+2 ); + sal_Bool bSkipX = ( nArrX==nX1 && !bLeft ) || ( nArrX==nX2+2 && !bRight ); + + for (sal_uInt16 nPass=0; nPass<2; nPass++) // horizontal / vertikal + { + const SvxShadowItem* pAttr = nPass ? + pThisRowInfo->pCellInfo[nArrX].pVShadowOrigin : + pThisRowInfo->pCellInfo[nArrX].pHShadowOrigin; + if ( pAttr && !bSkipX ) + { + ScShadowPart ePart = nPass ? + pThisRowInfo->pCellInfo[nArrX].eVShadowPart : + pThisRowInfo->pCellInfo[nArrX].eHShadowPart; + + sal_Bool bDo = sal_True; + if ( (nPass==0 && bCornerX) || (nPass==1 && bCornerY) ) + if ( ePart != SC_SHADOW_CORNER ) + bDo = sal_False; + + if (bDo) + { + long nThisWidth = pRowInfo[0].pCellInfo[nArrX].nWidth; + long nMaxWidth = nThisWidth; + if (!nMaxWidth) + { + //! direction must depend on shadow location + SCCOL nWx = nArrX; // nX+1 + while (nWx<nX2 && !pRowInfo[0].pCellInfo[nWx+1].nWidth) + ++nWx; + nMaxWidth = pRowInfo[0].pCellInfo[nWx+1].nWidth; + } + +// Rectangle aRect( Point(nPosX,nPosY), +// Size( pRowInfo[0].pCellInfo[nArrX].nWidth, +// pRowInfo[nArrY].nHeight ) ); + + // rectangle is in logical orientation + Rectangle aRect( nPosX, nPosY, + nPosX + ( nThisWidth - 1 ) * nLayoutSign, + nPosY + pRowInfo[nArrY].nHeight - 1 ); + + long nSize = pAttr->GetWidth(); + long nSizeX = (long)(nSize*nPPTX); + if (nSizeX >= nMaxWidth) nSizeX = nMaxWidth-1; + long nSizeY = (long)(nSize*nPPTY); + if (nSizeY >= nRowHeight) nSizeY = nRowHeight-1; + + nSizeX *= nLayoutSign; // used only to add to rectangle values + + SvxShadowLocation eLoc = pAttr->GetLocation(); + if ( bLayoutRTL ) + { + // Shadow location is specified as "visual" (right is always right), + // so the attribute's location value is mirrored here and in FillInfo. + switch (eLoc) + { + case SVX_SHADOW_BOTTOMRIGHT: eLoc = SVX_SHADOW_BOTTOMLEFT; break; + case SVX_SHADOW_BOTTOMLEFT: eLoc = SVX_SHADOW_BOTTOMRIGHT; break; + case SVX_SHADOW_TOPRIGHT: eLoc = SVX_SHADOW_TOPLEFT; break; + case SVX_SHADOW_TOPLEFT: eLoc = SVX_SHADOW_TOPRIGHT; break; + default: + { + // added to avoid warnings + } + } + } + + if (ePart == SC_SHADOW_HORIZ || ePart == SC_SHADOW_HSTART || + ePart == SC_SHADOW_CORNER) + { + if (eLoc == SVX_SHADOW_TOPLEFT || eLoc == SVX_SHADOW_TOPRIGHT) + aRect.Top() = aRect.Bottom() - nSizeY; + else + aRect.Bottom() = aRect.Top() + nSizeY; + } + if (ePart == SC_SHADOW_VERT || ePart == SC_SHADOW_VSTART || + ePart == SC_SHADOW_CORNER) + { + if (eLoc == SVX_SHADOW_TOPLEFT || eLoc == SVX_SHADOW_BOTTOMLEFT) + aRect.Left() = aRect.Right() - nSizeX; + else + aRect.Right() = aRect.Left() + nSizeX; + } + if (ePart == SC_SHADOW_HSTART) + { + if (eLoc == SVX_SHADOW_TOPLEFT || eLoc == SVX_SHADOW_BOTTOMLEFT) + aRect.Right() -= nSizeX; + else + aRect.Left() += nSizeX; + } + if (ePart == SC_SHADOW_VSTART) + { + if (eLoc == SVX_SHADOW_TOPLEFT || eLoc == SVX_SHADOW_TOPRIGHT) + aRect.Bottom() -= nSizeY; + else + aRect.Top() += nSizeY; + } + + //! merge rectangles? + pDev->SetFillColor( bCellContrast ? aAutoTextColor : pAttr->GetColor() ); + pDev->DrawRect( aRect ); + } + } + } + + nPosX += pRowInfo[0].pCellInfo[nArrX].nWidth * nLayoutSign; + } + } + nPosY += nRowHeight; + } +} + +// +// Loeschen +// + +void ScOutputData::DrawClear() +{ + Rectangle aRect; + Size aOnePixel = pDev->PixelToLogic(Size(1,1)); + long nOneX = aOnePixel.Width(); + long nOneY = aOnePixel.Height(); + + // (called only for ScGridWindow) + Color aBgColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor ); + + if (bMetaFile) + nOneX = nOneY = 0; + + pDev->SetLineColor(); + + pDev->SetFillColor( aBgColor ); + + long nPosY = nScrY; + for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++) + { + RowInfo* pThisRowInfo = &pRowInfo[nArrY]; + long nRowHeight = pThisRowInfo->nHeight; + + if ( pThisRowInfo->bChanged ) + { + // scan for more rows which must be painted: + SCSIZE nSkip = 0; + while ( nArrY+nSkip+2<nArrCount && pRowInfo[nArrY+nSkip+1].bChanged ) + { + ++nSkip; + nRowHeight += pRowInfo[nArrY+nSkip].nHeight; // after incrementing + } + + aRect = Rectangle( Point( nScrX, nPosY ), + Size( nScrW+1-nOneX, nRowHeight+1-nOneY) ); + pDev->DrawRect( aRect ); + + nArrY += nSkip; + } + nPosY += nRowHeight; + } +} + + +// +// Linien +// + +long lclGetSnappedX( OutputDevice& rDev, long nPosX, bool bSnapPixel ) +{ + return (bSnapPixel && nPosX) ? rDev.PixelToLogic( rDev.LogicToPixel( Size( nPosX, 0 ) ) ).Width() : nPosX; +} + +long lclGetSnappedY( OutputDevice& rDev, long nPosY, bool bSnapPixel ) +{ + return (bSnapPixel && nPosY) ? rDev.PixelToLogic( rDev.LogicToPixel( Size( 0, nPosY ) ) ).Height() : nPosY; +} + +size_t lclGetArrayColFromCellInfoX( sal_uInt16 nCellInfoX, sal_uInt16 nCellInfoFirstX, sal_uInt16 nCellInfoLastX, bool bRTL ) +{ + return static_cast< size_t >( bRTL ? (nCellInfoLastX + 2 - nCellInfoX) : (nCellInfoX - nCellInfoFirstX) ); +} + +void ScOutputData::DrawFrame() +{ + sal_uLong nOldDrawMode = pDev->GetDrawMode(); + + Color aSingleColor; + sal_Bool bUseSingleColor = sal_False; + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + // #105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed sal_True) + sal_Bool bCellContrast = bUseStyleColor && rStyleSettings.GetHighContrastMode(); + + // #107519# if a Calc OLE object is embedded in Draw/Impress, the VCL DrawMode is used + // for display mode / B&W printing. The VCL DrawMode handling doesn't work for lines + // that are drawn with DrawRect, so if the line/background bits are set, the DrawMode + // must be reset and the border colors handled here. + + if ( ( nOldDrawMode & DRAWMODE_WHITEFILL ) && ( nOldDrawMode & DRAWMODE_BLACKLINE ) ) + { + pDev->SetDrawMode( nOldDrawMode & (~DRAWMODE_WHITEFILL) ); + aSingleColor.SetColor( COL_BLACK ); + bUseSingleColor = sal_True; + } + else if ( ( nOldDrawMode & DRAWMODE_SETTINGSFILL ) && ( nOldDrawMode & DRAWMODE_SETTINGSLINE ) ) + { + pDev->SetDrawMode( nOldDrawMode & (~DRAWMODE_SETTINGSFILL) ); + aSingleColor = rStyleSettings.GetWindowTextColor(); // same as used in VCL for DRAWMODE_SETTINGSLINE + bUseSingleColor = sal_True; + } + else if ( bCellContrast ) + { + aSingleColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor ); + bUseSingleColor = sal_True; + } + + const Color* pForceColor = bUseSingleColor ? &aSingleColor : 0; + + if (bAnyRotated) + DrawRotatedFrame( pForceColor ); // removes the lines that must not be painted here + + long nInitPosX = nScrX; + if ( bLayoutRTL ) + { + Size aOnePixel = pDev->PixelToLogic(Size(1,1)); + long nOneX = aOnePixel.Width(); + nInitPosX += nMirrorW - nOneX; + } + long nLayoutSign = bLayoutRTL ? -1 : 1; + + + // *** set column and row sizes of the frame border array *** + + svx::frame::Array& rArray = mrTabInfo.maArray; + size_t nColCount = rArray.GetColCount(); + size_t nRowCount = rArray.GetRowCount(); + + // row heights + + // row 0 is not visible (dummy for borders from top) - subtract its height from initial position + // subtract 1 unit more, because position 0 is first *in* cell, grid line is one unit before + long nOldPosY = nScrY - 1 - pRowInfo[ 0 ].nHeight; + long nOldSnapY = lclGetSnappedY( *pDev, nOldPosY, bSnapPixel ); + rArray.SetYOffset( nOldSnapY ); + for( size_t nRow = 0; nRow < nRowCount; ++nRow ) + { + long nNewPosY = nOldPosY + pRowInfo[ nRow ].nHeight; + long nNewSnapY = lclGetSnappedY( *pDev, nNewPosY, bSnapPixel ); + rArray.SetRowHeight( nRow, nNewSnapY - nOldSnapY ); + nOldPosY = nNewPosY; + nOldSnapY = nNewSnapY; + } + + // column widths + + // column nX1 is not visible (dummy for borders from left) - subtract its width from initial position + // subtract 1 unit more, because position 0 is first *in* cell, grid line is one unit above + long nOldPosX = nInitPosX - nLayoutSign * (1 + pRowInfo[ 0 ].pCellInfo[ nX1 ].nWidth); + long nOldSnapX = lclGetSnappedX( *pDev, nOldPosX, bSnapPixel ); + // set X offset for left-to-right sheets; for right-to-left sheets this is done after for() loop + if( !bLayoutRTL ) + rArray.SetXOffset( nOldSnapX ); + for( sal_uInt16 nInfoIdx = nX1; nInfoIdx <= nX2 + 2; ++nInfoIdx ) + { + size_t nCol = lclGetArrayColFromCellInfoX( nInfoIdx, nX1, nX2, bLayoutRTL ); + long nNewPosX = nOldPosX + pRowInfo[ 0 ].pCellInfo[ nInfoIdx ].nWidth * nLayoutSign; + long nNewSnapX = lclGetSnappedX( *pDev, nNewPosX, bSnapPixel ); + rArray.SetColWidth( nCol, Abs( nNewSnapX - nOldSnapX ) ); + nOldPosX = nNewPosX; + nOldSnapX = nNewSnapX; + } + if( bLayoutRTL ) + rArray.SetXOffset( nOldSnapX ); + + // *** draw the array *** + + size_t nFirstCol = 1; + size_t nFirstRow = 1; + size_t nLastCol = nColCount - 2; + size_t nLastRow = nRowCount - 2; + + if( mrTabInfo.mbPageMode ) + rArray.SetClipRange( nFirstCol, nFirstRow, nLastCol, nLastRow ); + + // draw only rows with set RowInfo::bChanged flag + size_t nRow1 = nFirstRow; + while( nRow1 <= nLastRow ) + { + while( (nRow1 <= nLastRow) && !pRowInfo[ nRow1 ].bChanged ) ++nRow1; + if( nRow1 <= nLastRow ) + { + size_t nRow2 = nRow1; + while( (nRow2 + 1 <= nLastRow) && pRowInfo[ nRow2 + 1 ].bChanged ) ++nRow2; + rArray.DrawRange( *pDev, nFirstCol, nRow1, nLastCol, nRow2, pForceColor ); + nRow1 = nRow2 + 1; + } + } + + pDev->SetDrawMode(nOldDrawMode); +} + +// ------------------------------------------------------------------------- + +// Linie unter der Zelle + +const SvxBorderLine* lcl_FindHorLine( ScDocument* pDoc, + SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nRotDir, + sal_Bool bTopLine ) +{ + if ( nRotDir != SC_ROTDIR_LEFT && nRotDir != SC_ROTDIR_RIGHT ) + return NULL; + + sal_Bool bFound = sal_False; + while (!bFound) + { + if ( nRotDir == SC_ROTDIR_LEFT ) + { + // Text nach links -> Linie von rechts + if ( nCol < MAXCOL ) + ++nCol; + else + return NULL; // war nix + } + else + { + // Text nach rechts -> Linie von links + if ( nCol > 0 ) + --nCol; + else + return NULL; // war nix + } + const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab ); + const SfxItemSet* pCondSet = pDoc->GetCondResult( nCol, nRow, nTab ); + if ( !pPattern->GetRotateVal( pCondSet ) || + ((const SvxRotateModeItem&)pPattern->GetItem( + ATTR_ROTATE_MODE, pCondSet)).GetValue() == SVX_ROTATE_MODE_STANDARD ) + bFound = sal_True; + } + + if (bTopLine) + --nRow; + const SvxBorderLine* pThisBottom; + if ( ValidRow(nRow) ) + pThisBottom = ((const SvxBoxItem*)pDoc->GetAttr( nCol, nRow, nTab, ATTR_BORDER ))->GetBottom(); + else + pThisBottom = NULL; + const SvxBorderLine* pNextTop; + if ( nRow < MAXROW ) + pNextTop = ((const SvxBoxItem*)pDoc->GetAttr( nCol, nRow+1, nTab, ATTR_BORDER ))->GetTop(); + else + pNextTop = NULL; + + if ( ScHasPriority( pThisBottom, pNextTop ) ) + return pThisBottom; + else + return pNextTop; +} + +// lcl_HorizLine muss genau zu normal ausgegebenen Linien passen! + +void lcl_HorizLine( OutputDevice& rDev, const Point& rLeft, const Point& rRight, + const svx::frame::Style& rLine, const Color* pForceColor ) +{ + svx::frame::DrawHorFrameBorder( rDev, rLeft, rRight, rLine, pForceColor ); +} + +void lcl_VertLineEnds( OutputDevice& rDev, const Point& rTop, const Point& rBottom, + const Color& rColor, long nXOffs, long nWidth, + const svx::frame::Style& rTopLine, const svx::frame::Style& rBottomLine ) +{ + rDev.SetLineColor(rColor); // PEN_NULL ??? + rDev.SetFillColor(rColor); + + // Position oben/unten muss unabhaengig von der Liniendicke sein, + // damit der Winkel stimmt (oder X-Position auch anpassen) + long nTopPos = rTop.Y(); + long nBotPos = rBottom.Y(); + + long nTopLeft = rTop.X() + nXOffs; + long nTopRight = nTopLeft + nWidth - 1; + + long nBotLeft = rBottom.X() + nXOffs; + long nBotRight = nBotLeft + nWidth - 1; + + // oben abschliessen + + if ( rTopLine.Prim() ) + { + long nLineW = rTopLine.GetWidth(); + if (nLineW >= 2) + { + Point aTriangle[3]; + aTriangle[0] = Point( nTopLeft, nTopPos ); // wie aPoints[0] + aTriangle[1] = Point( nTopRight, nTopPos ); // wie aPoints[1] + aTriangle[2] = Point( rTop.X(), nTopPos - (nLineW - 1) / 2 ); + Polygon aTriPoly( 3, aTriangle ); + rDev.DrawPolygon( aTriPoly ); + } + } + + // unten abschliessen + + if ( rBottomLine.Prim() ) + { + long nLineW = rBottomLine.GetWidth(); + if (nLineW >= 2) + { + Point aTriangle[3]; + aTriangle[0] = Point( nBotLeft, nBotPos ); // wie aPoints[3] + aTriangle[1] = Point( nBotRight, nBotPos ); // wie aPoints[2] + aTriangle[2] = Point( rBottom.X(), nBotPos - (nLineW - 1) / 2 + nLineW - 1 ); + Polygon aTriPoly( 3, aTriangle ); + rDev.DrawPolygon( aTriPoly ); + } + } +} + +void lcl_VertLine( OutputDevice& rDev, const Point& rTop, const Point& rBottom, + const svx::frame::Style& rLine, + const svx::frame::Style& rTopLine, const svx::frame::Style& rBottomLine, + const Color* pForceColor ) +{ + if( rLine.Prim() ) + { + svx::frame::DrawVerFrameBorderSlanted( rDev, rTop, rBottom, rLine, pForceColor ); + + svx::frame::Style aScaled( rLine ); + aScaled.ScaleSelf( 1.0 / cos( svx::frame::GetVerDiagAngle( rTop, rBottom ) ) ); + if( pForceColor ) + aScaled.SetColor( *pForceColor ); + + long nXOffs = (aScaled.GetWidth() - 1) / -2L; + + lcl_VertLineEnds( rDev, rTop, rBottom, aScaled.GetColor(), + nXOffs, aScaled.Prim(), rTopLine, rBottomLine ); + + if( aScaled.Secn() ) + lcl_VertLineEnds( rDev, rTop, rBottom, aScaled.GetColor(), + nXOffs + aScaled.Prim() + aScaled.Dist(), aScaled.Secn(), rTopLine, rBottomLine ); + } +} + +void ScOutputData::DrawRotatedFrame( const Color* pForceColor ) +{ + //! nRotMax speichern + SCCOL nRotMax = nX2; + for (SCSIZE nRotY=0; nRotY<nArrCount; nRotY++) + if (pRowInfo[nRotY].nRotMaxCol != SC_ROTMAX_NONE && pRowInfo[nRotY].nRotMaxCol > nRotMax) + nRotMax = pRowInfo[nRotY].nRotMaxCol; + + const ScPatternAttr* pPattern; + const SfxItemSet* pCondSet; + + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + // #105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed sal_True) + sal_Bool bCellContrast = bUseStyleColor && rStyleSettings.GetHighContrastMode(); + + // color (pForceColor) is determined externally, including DrawMode changes + + long nInitPosX = nScrX; + if ( bLayoutRTL ) + { + Size aOnePixel = pDev->PixelToLogic(Size(1,1)); + long nOneX = aOnePixel.Width(); + nInitPosX += nMirrorW - nOneX; + } + long nLayoutSign = bLayoutRTL ? -1 : 1; + + Rectangle aClipRect( Point(nScrX, nScrY), Size(nScrW, nScrH) ); + if (bMetaFile) + { + pDev->Push(); + pDev->IntersectClipRegion( aClipRect ); + } + else + pDev->SetClipRegion( Region( aClipRect ) ); + + svx::frame::Array& rArray = mrTabInfo.maArray; + + long nPosY = nScrY; + for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++) + { + // Rotated wird auch 1 Zeile ueber/unter Changed gezeichnet, falls Teile + // in die Zeile hineinragen... + + RowInfo& rPrevRowInfo = pRowInfo[nArrY-1]; + RowInfo& rThisRowInfo = pRowInfo[nArrY]; + RowInfo& rNextRowInfo = pRowInfo[nArrY+1]; + + size_t nRow = static_cast< size_t >( nArrY ); + + long nRowHeight = rThisRowInfo.nHeight; + if ( rThisRowInfo.nRotMaxCol != SC_ROTMAX_NONE && + ( rThisRowInfo.bChanged || rPrevRowInfo.bChanged || + ( nArrY+1<nArrCount && rNextRowInfo.bChanged ) ) ) + { + SCROW nY = rThisRowInfo.nRowNo; + long nPosX = 0; + SCCOL nX; + for (nX=0; nX<=nRotMax; nX++) + { + if (nX==nX1) nPosX = nInitPosX; // calculated individually for preceding positions + + sal_uInt16 nArrX = nX + 1; + + CellInfo* pInfo = &rThisRowInfo.pCellInfo[nArrX]; + long nColWidth = pRowInfo[0].pCellInfo[nArrX].nWidth; + if ( pInfo->nRotateDir > SC_ROTDIR_STANDARD && + !pInfo->bHOverlapped && !pInfo->bVOverlapped ) + { + pPattern = pInfo->pPatternAttr; + pCondSet = pInfo->pConditionSet; + if (!pPattern) + { + pPattern = pDoc->GetPattern( nX, nY, nTab ); + pInfo->pPatternAttr = pPattern; + pCondSet = pDoc->GetCondResult( nX, nY, nTab ); + pInfo->pConditionSet = pCondSet; + } + + //! LastPattern etc. + + long nAttrRotate = pPattern->GetRotateVal( pCondSet ); + SvxRotateMode eRotMode = (SvxRotateMode)((const SvxRotateModeItem&) + pPattern->GetItem(ATTR_ROTATE_MODE, pCondSet)).GetValue(); + + if ( nAttrRotate ) + { + if (nX<nX1) // negative Position berechnen + { + nPosX = nInitPosX; + SCCOL nCol = nX1; + while (nCol > nX) + { + --nCol; + nPosX -= nLayoutSign * (long) pRowInfo[0].pCellInfo[nCol+1].nWidth; + } + } + + // Startposition minus 1, damit auch schraege Hintergruende + // zur Umrandung passen (Umrandung ist auf dem Gitter) + + long nTop = nPosY - 1; + long nBottom = nPosY + nRowHeight - 1; + long nTopLeft = nPosX - nLayoutSign; + long nTopRight = nPosX + ( nColWidth - 1 ) * nLayoutSign; + long nBotLeft = nTopLeft; + long nBotRight = nTopRight; + + // inclusion of the sign here hasn't been decided yet + // (if not, the extension of the non-rotated background must also be changed) + double nRealOrient = nLayoutSign * nAttrRotate * F_PI18000; // 1/100th degrees + double nCos = cos( nRealOrient ); + double nSin = sin( nRealOrient ); + //! begrenzen !!! + long nSkew = (long) ( nRowHeight * nCos / nSin ); + + switch (eRotMode) + { + case SVX_ROTATE_MODE_BOTTOM: + nTopLeft += nSkew; + nTopRight += nSkew; + break; + case SVX_ROTATE_MODE_CENTER: + nSkew /= 2; + nTopLeft += nSkew; + nTopRight += nSkew; + nBotLeft -= nSkew; + nBotRight -= nSkew; + break; + case SVX_ROTATE_MODE_TOP: + nBotLeft -= nSkew; + nBotRight -= nSkew; + break; + default: + { + // added to avoid warnings + } + } + + Point aPoints[4]; + aPoints[0] = Point( nTopLeft, nTop ); + aPoints[1] = Point( nTopRight, nTop ); + aPoints[2] = Point( nBotRight, nBottom ); + aPoints[3] = Point( nBotLeft, nBottom ); + + const SvxBrushItem* pBackground = pInfo->pBackground; + if (!pBackground) + pBackground = (const SvxBrushItem*) &pPattern->GetItem( + ATTR_BACKGROUND, pCondSet ); + if (bCellContrast) + { + // high contrast for cell borders and backgrounds -> empty background + pBackground = ScGlobal::GetEmptyBrushItem(); + } + const Color& rColor = pBackground->GetColor(); + if ( rColor.GetTransparency() != 255 ) + { + // #95879# draw background only for the changed row itself + // (background doesn't extend into other cells). + // For the borders (rotated and normal), clipping should be + // set if the row isn't changed, but at least the borders + // don't cover the cell contents. + if ( rThisRowInfo.bChanged ) + { + Polygon aPoly( 4, aPoints ); + + // ohne Pen wird bei DrawPolygon rechts und unten + // ein Pixel weggelassen... + if ( rColor.GetTransparency() == 0 ) + pDev->SetLineColor(rColor); + else + pDev->SetLineColor(); + pDev->SetFillColor(rColor); + pDev->DrawPolygon( aPoly ); + } + } + + svx::frame::Style aTopLine, aBottomLine, aLeftLine, aRightLine; + + if ( nX < nX1 || nX > nX2 ) // Attribute in FillInfo nicht gesetzt + { + //! Seitengrenzen fuer Druck beruecksichtigen !!!!! + const SvxBorderLine* pLeftLine; + const SvxBorderLine* pTopLine; + const SvxBorderLine* pRightLine; + const SvxBorderLine* pBottomLine; + pDoc->GetBorderLines( nX, nY, nTab, + &pLeftLine, &pTopLine, &pRightLine, &pBottomLine ); + aTopLine.Set( pTopLine, nPPTY ); + aBottomLine.Set( pBottomLine, nPPTY ); + aLeftLine.Set( pLeftLine, nPPTX ); + aRightLine.Set( pRightLine, nPPTX ); + } + else + { + size_t nCol = lclGetArrayColFromCellInfoX( nArrX, nX1, nX2, bLayoutRTL ); + aTopLine = rArray.GetCellStyleTop( nCol, nRow ); + aBottomLine = rArray.GetCellStyleBottom( nCol, nRow ); + aLeftLine = rArray.GetCellStyleLeft( nCol, nRow ); + aRightLine = rArray.GetCellStyleRight( nCol, nRow ); + // in RTL mode the array is already mirrored -> swap back left/right borders + if( bLayoutRTL ) + std::swap( aLeftLine, aRightLine ); + } + + lcl_HorizLine( *pDev, aPoints[bLayoutRTL?1:0], aPoints[bLayoutRTL?0:1], aTopLine, pForceColor ); + lcl_HorizLine( *pDev, aPoints[bLayoutRTL?2:3], aPoints[bLayoutRTL?3:2], aBottomLine, pForceColor ); + + lcl_VertLine( *pDev, aPoints[0], aPoints[3], aLeftLine, aTopLine, aBottomLine, pForceColor ); + lcl_VertLine( *pDev, aPoints[1], aPoints[2], aRightLine, aTopLine, aBottomLine, pForceColor ); + } + } + nPosX += nColWidth * nLayoutSign; + } + + // erst hinterher im zweiten Schritt die Linien fuer normale Ausgabe loeschen + + nX = nX1 > 0 ? (nX1-1) : static_cast<SCCOL>(0); + for (; nX<=nX2+1; nX++) // sichtbarer Teil +- 1 + { + sal_uInt16 nArrX = nX + 1; + CellInfo& rInfo = rThisRowInfo.pCellInfo[nArrX]; + if ( rInfo.nRotateDir > SC_ROTDIR_STANDARD && + !rInfo.bHOverlapped && !rInfo.bVOverlapped ) + { + pPattern = rInfo.pPatternAttr; + pCondSet = rInfo.pConditionSet; + SvxRotateMode eRotMode = (SvxRotateMode)((const SvxRotateModeItem&) + pPattern->GetItem(ATTR_ROTATE_MODE, pCondSet)).GetValue(); + + size_t nCol = lclGetArrayColFromCellInfoX( nArrX, nX1, nX2, bLayoutRTL ); + + // horizontal: angrenzende Linie verlaengern + // (nur, wenn die gedrehte Zelle eine Umrandung hat) + sal_uInt16 nDir = rInfo.nRotateDir; + if ( rArray.GetCellStyleTop( nCol, nRow ).Prim() && eRotMode != SVX_ROTATE_MODE_TOP ) + { + svx::frame::Style aStyle( lcl_FindHorLine( pDoc, nX, nY, nTab, nDir, sal_True ), nPPTY ); + rArray.SetCellStyleTop( nCol, nRow, aStyle ); + if( nRow > 0 ) + rArray.SetCellStyleBottom( nCol, nRow - 1, aStyle ); + } + if ( rArray.GetCellStyleBottom( nCol, nRow ).Prim() && eRotMode != SVX_ROTATE_MODE_BOTTOM ) + { + svx::frame::Style aStyle( lcl_FindHorLine( pDoc, nX, nY, nTab, nDir, sal_False ), nPPTY ); + rArray.SetCellStyleBottom( nCol, nRow, aStyle ); + if( nRow + 1 < rArray.GetRowCount() ) + rArray.SetCellStyleTop( nCol, nRow + 1, aStyle ); + } + + // always remove vertical borders + if( !rArray.IsMergedOverlappedLeft( nCol, nRow ) ) + { + rArray.SetCellStyleLeft( nCol, nRow, svx::frame::Style() ); + if( nCol > 0 ) + rArray.SetCellStyleRight( nCol - 1, nRow, svx::frame::Style() ); + } + if( !rArray.IsMergedOverlappedRight( nCol, nRow ) ) + { + rArray.SetCellStyleRight( nCol, nRow, svx::frame::Style() ); + if( nCol + 1 < rArray.GetColCount() ) + rArray.SetCellStyleLeft( nCol + 1, nRow, svx::frame::Style() ); + } + + // remove diagonal borders + rArray.SetCellStyleTLBR( nCol, nRow, svx::frame::Style() ); + rArray.SetCellStyleBLTR( nCol, nRow, svx::frame::Style() ); + } + } + } + nPosY += nRowHeight; + } + + if (bMetaFile) + pDev->Pop(); + else + pDev->SetClipRegion(); +} + +// Drucker + +PolyPolygon ScOutputData::GetChangedArea() +{ + PolyPolygon aPoly; + + Rectangle aDrawingRect; + aDrawingRect.Left() = nScrX; + aDrawingRect.Right() = nScrX+nScrW-1; + + sal_Bool bHad = sal_False; + long nPosY = nScrY; + SCSIZE nArrY; + for (nArrY=1; nArrY+1<nArrCount; nArrY++) + { + RowInfo* pThisRowInfo = &pRowInfo[nArrY]; + + if ( pThisRowInfo->bChanged ) + { + if (!bHad) + { + aDrawingRect.Top() = nPosY; + bHad = sal_True; + } + aDrawingRect.Bottom() = nPosY + pRowInfo[nArrY].nHeight - 1; + } + else if (bHad) + { + aPoly.Insert( Polygon( pDev->PixelToLogic(aDrawingRect) ) ); + bHad = sal_False; + } + nPosY += pRowInfo[nArrY].nHeight; + } + + if (bHad) + aPoly.Insert( Polygon( pDev->PixelToLogic(aDrawingRect) ) ); + + return aPoly; +} + +sal_Bool ScOutputData::SetChangedClip() +{ + PolyPolygon aPoly; + + Rectangle aDrawingRect; + aDrawingRect.Left() = nScrX; + aDrawingRect.Right() = nScrX+nScrW-1; + + sal_Bool bHad = sal_False; + long nPosY = nScrY; + SCSIZE nArrY; + for (nArrY=1; nArrY+1<nArrCount; nArrY++) + { + RowInfo* pThisRowInfo = &pRowInfo[nArrY]; + + if ( pThisRowInfo->bChanged ) + { + if (!bHad) + { + aDrawingRect.Top() = nPosY; + bHad = sal_True; + } + aDrawingRect.Bottom() = nPosY + pRowInfo[nArrY].nHeight - 1; + } + else if (bHad) + { + aPoly.Insert( Polygon( pDev->PixelToLogic(aDrawingRect) ) ); + bHad = sal_False; + } + nPosY += pRowInfo[nArrY].nHeight; + } + + if (bHad) + aPoly.Insert( Polygon( pDev->PixelToLogic(aDrawingRect) ) ); + + sal_Bool bRet = (aPoly.Count() != 0); + if (bRet) + pDev->SetClipRegion(Region(aPoly)); + return bRet; +} + +void ScOutputData::FindChanged() +{ + SCCOL nX; + SCSIZE nArrY; + + sal_Bool bWasIdleDisabled = pDoc->IsIdleDisabled(); + pDoc->DisableIdle( sal_True ); + for (nArrY=0; nArrY<nArrCount; nArrY++) + pRowInfo[nArrY].bChanged = sal_False; + + sal_Bool bProgress = sal_False; + for (nArrY=0; nArrY<nArrCount; nArrY++) + { + RowInfo* pThisRowInfo = &pRowInfo[nArrY]; + for (nX=nX1; nX<=nX2; nX++) + { + ScBaseCell* pCell = pThisRowInfo->pCellInfo[nX+1].pCell; + if (pCell) + if (pCell->GetCellType() == CELLTYPE_FORMULA) + { + ScFormulaCell* pFCell = (ScFormulaCell*)pCell; + if ( !bProgress && pFCell->GetDirty() ) + { + ScProgress::CreateInterpretProgress( pDoc, sal_True ); + bProgress = sal_True; + } + if (!pFCell->IsRunning()) + { + (void)pFCell->GetValue(); + if (pFCell->IsChanged()) + { + pThisRowInfo->bChanged = sal_True; + if ( pThisRowInfo->pCellInfo[nX+1].bMerged ) + { + SCSIZE nOverY = nArrY + 1; + while ( nOverY<nArrCount && + pRowInfo[nOverY].pCellInfo[nX+1].bVOverlapped ) + { + pRowInfo[nOverY].bChanged = sal_True; + ++nOverY; + } + } + } + } + } + } + } + if ( bProgress ) + ScProgress::DeleteInterpretProgress(); + pDoc->DisableIdle( bWasIdleDisabled ); +} + +#ifdef OLD_SELECTION_PAINT +void ScOutputData::DrawMark( Window* pWin ) +{ + Rectangle aRect; + ScInvertMerger aInvert( pWin ); + //! additional method AddLineRect for ScInvertMerger? + + long nPosY = nScrY; + for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++) + { + RowInfo* pThisRowInfo = &pRowInfo[nArrY]; + if (pThisRowInfo->bChanged) + { + long nPosX = nScrX; + if (bLayoutRTL) + nPosX += nMirrorW - 1; // always in pixels + + aRect = Rectangle( Point( nPosX,nPosY ), Size(1, pThisRowInfo->nHeight) ); + if (bLayoutRTL) + aRect.Left() = aRect.Right() + 1; + else + aRect.Right() = aRect.Left() - 1; + + sal_Bool bOldMarked = sal_False; + for (SCCOL nX=nX1; nX<=nX2; nX++) + { + if (pThisRowInfo->pCellInfo[nX+1].bMarked != bOldMarked) + { + if (bOldMarked && aRect.Right() >= aRect.Left()) + aInvert.AddRect( aRect ); + + if (bLayoutRTL) + aRect.Right() = nPosX; + else + aRect.Left() = nPosX; + + bOldMarked = pThisRowInfo->pCellInfo[nX+1].bMarked; + } + + if (bLayoutRTL) + { + nPosX -= pRowInfo[0].pCellInfo[nX+1].nWidth; + aRect.Left() = nPosX+1; + } + else + { + nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth; + aRect.Right() = nPosX-1; + } + } + if (bOldMarked && aRect.Right() >= aRect.Left()) + aInvert.AddRect( aRect ); + } + nPosY += pThisRowInfo->nHeight; + } +} +#endif + +void ScOutputData::DrawRefMark( SCCOL nRefStartX, SCROW nRefStartY, + SCCOL nRefEndX, SCROW nRefEndY, + const Color& rColor, sal_Bool bHandle ) +{ + PutInOrder( nRefStartX, nRefEndX ); + PutInOrder( nRefStartY, nRefEndY ); + + if ( nRefStartX == nRefEndX && nRefStartY == nRefEndY ) + pDoc->ExtendMerge( nRefStartX, nRefStartY, nRefEndX, nRefEndY, nTab ); + + if ( nRefStartX <= nVisX2 && nRefEndX >= nVisX1 && + nRefStartY <= nVisY2 && nRefEndY >= nVisY1 ) + { + long nMinX = nScrX; + long nMinY = nScrY; + long nMaxX = nScrX+nScrW-1; + long nMaxY = nScrY+nScrH-1; + if ( bLayoutRTL ) + { + long nTemp = nMinX; + nMinX = nMaxX; + nMaxX = nTemp; + } + long nLayoutSign = bLayoutRTL ? -1 : 1; + + sal_Bool bTop = sal_False; + sal_Bool bBottom = sal_False; + sal_Bool bLeft = sal_False; + sal_Bool bRight = sal_False; + + long nPosY = nScrY; + sal_Bool bNoStartY = ( nY1 < nRefStartY ); + sal_Bool bNoEndY = sal_False; + for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++) // loop to end for bNoEndY check + { + SCROW nY = pRowInfo[nArrY].nRowNo; + + if ( nY==nRefStartY || (nY>nRefStartY && bNoStartY) ) + { + nMinY = nPosY; + bTop = sal_True; + } + if ( nY==nRefEndY ) + { + nMaxY = nPosY + pRowInfo[nArrY].nHeight - 2; + bBottom = sal_True; + } + if ( nY>nRefEndY && bNoEndY ) + { + nMaxY = nPosY-2; + bBottom = sal_True; + } + bNoStartY = ( nY < nRefStartY ); + bNoEndY = ( nY < nRefEndY ); + nPosY += pRowInfo[nArrY].nHeight; + } + + long nPosX = nScrX; + if ( bLayoutRTL ) + nPosX += nMirrorW - 1; // always in pixels + + for (SCCOL nX=nX1; nX<=nX2; nX++) + { + if ( nX==nRefStartX ) + { + nMinX = nPosX; + bLeft = sal_True; + } + if ( nX==nRefEndX ) + { + nMaxX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - 2 ) * nLayoutSign; + bRight = sal_True; + } + nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign; + } + + if ( nMaxX * nLayoutSign >= nMinX * nLayoutSign && + nMaxY >= nMinY ) + { + pDev->SetLineColor( rColor ); + if (bTop && bBottom && bLeft && bRight) + { + pDev->SetFillColor(); + pDev->DrawRect( Rectangle( nMinX, nMinY, nMaxX, nMaxY ) ); + } + else + { + if (bTop) + pDev->DrawLine( Point( nMinX,nMinY ), Point( nMaxX,nMinY ) ); + if (bBottom) + pDev->DrawLine( Point( nMinX,nMaxY ), Point( nMaxX,nMaxY ) ); + if (bLeft) + pDev->DrawLine( Point( nMinX,nMinY ), Point( nMinX,nMaxY ) ); + if (bRight) + pDev->DrawLine( Point( nMaxX,nMinY ), Point( nMaxX,nMaxY ) ); + } + if ( bHandle && bRight && bBottom ) + { + pDev->SetLineColor(); + pDev->SetFillColor( rColor ); + pDev->DrawRect( Rectangle( nMaxX-3*nLayoutSign, nMaxY-3, nMaxX+nLayoutSign, nMaxY+1 ) ); + } + } + } +} + +void ScOutputData::DrawOneChange( SCCOL nRefStartX, SCROW nRefStartY, + SCCOL nRefEndX, SCROW nRefEndY, + const Color& rColor, sal_uInt16 nType ) +{ + PutInOrder( nRefStartX, nRefEndX ); + PutInOrder( nRefStartY, nRefEndY ); + + if ( nRefStartX == nRefEndX && nRefStartY == nRefEndY ) + pDoc->ExtendMerge( nRefStartX, nRefStartY, nRefEndX, nRefEndY, nTab ); + + if ( nRefStartX <= nVisX2 + 1 && nRefEndX >= nVisX1 && + nRefStartY <= nVisY2 + 1 && nRefEndY >= nVisY1 ) // +1 because it touches next cells left/top + { + long nMinX = nScrX; + long nMinY = nScrY; + long nMaxX = nScrX+nScrW-1; + long nMaxY = nScrY+nScrH-1; + if ( bLayoutRTL ) + { + long nTemp = nMinX; + nMinX = nMaxX; + nMaxX = nTemp; + } + long nLayoutSign = bLayoutRTL ? -1 : 1; + + sal_Bool bTop = sal_False; + sal_Bool bBottom = sal_False; + sal_Bool bLeft = sal_False; + sal_Bool bRight = sal_False; + + long nPosY = nScrY; + sal_Bool bNoStartY = ( nY1 < nRefStartY ); + sal_Bool bNoEndY = sal_False; + for (SCSIZE nArrY=1; nArrY<nArrCount; nArrY++) // loop to end for bNoEndY check + { + SCROW nY = pRowInfo[nArrY].nRowNo; + + if ( nY==nRefStartY || (nY>nRefStartY && bNoStartY) ) + { + nMinY = nPosY - 1; + bTop = sal_True; + } + if ( nY==nRefEndY ) + { + nMaxY = nPosY + pRowInfo[nArrY].nHeight - 1; + bBottom = sal_True; + } + if ( nY>nRefEndY && bNoEndY ) + { + nMaxY = nPosY - 1; + bBottom = sal_True; + } + bNoStartY = ( nY < nRefStartY ); + bNoEndY = ( nY < nRefEndY ); + nPosY += pRowInfo[nArrY].nHeight; + } + + long nPosX = nScrX; + if ( bLayoutRTL ) + nPosX += nMirrorW - 1; // always in pixels + + for (SCCOL nX=nX1; nX<=nX2+1; nX++) + { + if ( nX==nRefStartX ) + { + nMinX = nPosX - nLayoutSign; + bLeft = sal_True; + } + if ( nX==nRefEndX ) + { + nMaxX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - 1 ) * nLayoutSign; + bRight = sal_True; + } + nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign; + } + + if ( nMaxX * nLayoutSign >= nMinX * nLayoutSign && + nMaxY >= nMinY ) + { + if ( nType == SC_CAT_DELETE_ROWS ) + bLeft = bRight = bBottom = sal_False; //! dicke Linie ??? + else if ( nType == SC_CAT_DELETE_COLS ) + bTop = bBottom = bRight = sal_False; //! dicke Linie ??? + + pDev->SetLineColor( rColor ); + if (bTop && bBottom && bLeft && bRight) + { + pDev->SetFillColor(); + pDev->DrawRect( Rectangle( nMinX, nMinY, nMaxX, nMaxY ) ); + } + else + { + if (bTop) + { + pDev->DrawLine( Point( nMinX,nMinY ), Point( nMaxX,nMinY ) ); + if ( nType == SC_CAT_DELETE_ROWS ) + pDev->DrawLine( Point( nMinX,nMinY+1 ), Point( nMaxX,nMinY+1 ) ); + } + if (bBottom) + pDev->DrawLine( Point( nMinX,nMaxY ), Point( nMaxX,nMaxY ) ); + if (bLeft) + { + pDev->DrawLine( Point( nMinX,nMinY ), Point( nMinX,nMaxY ) ); + if ( nType == SC_CAT_DELETE_COLS ) + pDev->DrawLine( Point( nMinX+nLayoutSign,nMinY ), Point( nMinX+nLayoutSign,nMaxY ) ); + } + if (bRight) + pDev->DrawLine( Point( nMaxX,nMinY ), Point( nMaxX,nMaxY ) ); + } + if ( bLeft && bTop ) + { + pDev->SetLineColor(); + pDev->SetFillColor( rColor ); + pDev->DrawRect( Rectangle( nMinX+nLayoutSign, nMinY+1, nMinX+3*nLayoutSign, nMinY+3 ) ); + } + } + } +} + +void ScOutputData::DrawChangeTrack() +{ + ScChangeTrack* pTrack = pDoc->GetChangeTrack(); + ScChangeViewSettings* pSettings = pDoc->GetChangeViewSettings(); + if ( !pTrack || !pTrack->GetFirst() || !pSettings || !pSettings->ShowChanges() ) + return; // nix da oder abgeschaltet + + ScActionColorChanger aColorChanger(*pTrack); + + // Clipping passiert von aussen + //! ohne Clipping, nur betroffene Zeilen painten ??!??!? + + SCCOL nEndX = nX2; + SCROW nEndY = nY2; + if ( nEndX < MAXCOL ) ++nEndX; // auch noch von der naechsten Zelle, weil die Markierung + if ( nEndY < MAXROW ) ++nEndY; // in die jeweils vorhergehende Zelle hineinragt + ScRange aViewRange( nX1, nY1, nTab, nEndX, nEndY, nTab ); + const ScChangeAction* pAction = pTrack->GetFirst(); + while (pAction) + { + ScChangeActionType eActionType; + if ( pAction->IsVisible() ) + { + eActionType = pAction->GetType(); + const ScBigRange& rBig = pAction->GetBigRange(); + if ( rBig.aStart.Tab() == nTab ) + { + ScRange aRange = rBig.MakeRange(); + + if ( eActionType == SC_CAT_DELETE_ROWS ) + aRange.aEnd.SetRow( aRange.aStart.Row() ); + else if ( eActionType == SC_CAT_DELETE_COLS ) + aRange.aEnd.SetCol( aRange.aStart.Col() ); + + if ( aRange.Intersects( aViewRange ) && + ScViewUtil::IsActionShown( *pAction, *pSettings, *pDoc ) ) + { + aColorChanger.Update( *pAction ); + Color aColor( aColorChanger.GetColor() ); + DrawOneChange( aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Col(), aRange.aEnd.Row(), aColor, sal::static_int_cast<sal_uInt16>(eActionType) ); + + } + } + if ( eActionType == SC_CAT_MOVE && + ((const ScChangeActionMove*)pAction)-> + GetFromRange().aStart.Tab() == nTab ) + { + ScRange aRange = ((const ScChangeActionMove*)pAction)-> + GetFromRange().MakeRange(); + if ( aRange.Intersects( aViewRange ) && + ScViewUtil::IsActionShown( *pAction, *pSettings, *pDoc ) ) + { + aColorChanger.Update( *pAction ); + Color aColor( aColorChanger.GetColor() ); + DrawOneChange( aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Col(), aRange.aEnd.Row(), aColor, sal::static_int_cast<sal_uInt16>(eActionType) ); + } + } + } + + pAction = pAction->GetNext(); + } +} + +void ScOutputData::DrawNoteMarks() +{ + sal_Bool bFirst = sal_True; + + long nInitPosX = nScrX; + if ( bLayoutRTL ) + nInitPosX += nMirrorW - 1; // always in pixels + long nLayoutSign = bLayoutRTL ? -1 : 1; + + long nPosY = nScrY; + for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++) + { + RowInfo* pThisRowInfo = &pRowInfo[nArrY]; + if ( pThisRowInfo->bChanged ) + { + long nPosX = nInitPosX; + for (SCCOL nX=nX1; nX<=nX2; nX++) + { + CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1]; + ScBaseCell* pCell = pInfo->pCell; + sal_Bool bIsMerged = sal_False; + + if ( nX==nX1 && pInfo->bHOverlapped && !pInfo->bVOverlapped ) + { + // find start of merged cell + bIsMerged = sal_True; + SCROW nY = pRowInfo[nArrY].nRowNo; + SCCOL nMergeX = nX; + SCROW nMergeY = nY; + pDoc->ExtendOverlapped( nMergeX, nMergeY, nX, nY, nTab ); + pCell = pDoc->GetCell( ScAddress(nMergeX,nMergeY,nTab) ); + // use origin's pCell for NotePtr test below + } + + if ( pCell && pCell->HasNote() && ( bIsMerged || + ( !pInfo->bHOverlapped && !pInfo->bVOverlapped ) ) ) + { + if (bFirst) + { + pDev->SetLineColor(); + + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + if ( bUseStyleColor && rStyleSettings.GetHighContrastMode() ) + pDev->SetFillColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor ); + else + pDev->SetFillColor(COL_LIGHTRED); + + bFirst = sal_False; + } + + long nMarkX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - 4 ) * nLayoutSign; + if ( bIsMerged || pInfo->bMerged ) + { + // if merged, add widths of all cells + SCCOL nNextX = nX + 1; + while ( nNextX <= nX2 + 1 && pThisRowInfo->pCellInfo[nNextX+1].bHOverlapped ) + { + nMarkX += pRowInfo[0].pCellInfo[nNextX+1].nWidth * nLayoutSign; + ++nNextX; + } + } + if ( bLayoutRTL ? ( nMarkX >= 0 ) : ( nMarkX < nScrX+nScrW ) ) + pDev->DrawRect( Rectangle( nMarkX,nPosY,nMarkX+2*nLayoutSign,nPosY+2 ) ); + } + + nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign; + } + } + nPosY += pThisRowInfo->nHeight; + } +} + +void ScOutputData::AddPDFNotes() +{ + vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, pDev->GetExtOutDevData() ); + if ( !pPDFData || !pPDFData->GetIsExportNotes() ) + return; + + long nInitPosX = nScrX; + if ( bLayoutRTL ) + { + Size aOnePixel = pDev->PixelToLogic(Size(1,1)); + long nOneX = aOnePixel.Width(); + nInitPosX += nMirrorW - nOneX; + } + long nLayoutSign = bLayoutRTL ? -1 : 1; + + long nPosY = nScrY; + for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++) + { + RowInfo* pThisRowInfo = &pRowInfo[nArrY]; + if ( pThisRowInfo->bChanged ) + { + long nPosX = nInitPosX; + for (SCCOL nX=nX1; nX<=nX2; nX++) + { + CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1]; + ScBaseCell* pCell = pInfo->pCell; + sal_Bool bIsMerged = sal_False; + SCROW nY = pRowInfo[nArrY].nRowNo; + SCCOL nMergeX = nX; + SCROW nMergeY = nY; + + if ( nX==nX1 && pInfo->bHOverlapped && !pInfo->bVOverlapped ) + { + // find start of merged cell + bIsMerged = sal_True; + pDoc->ExtendOverlapped( nMergeX, nMergeY, nX, nY, nTab ); + pCell = pDoc->GetCell( ScAddress(nMergeX,nMergeY,nTab) ); + // use origin's pCell for NotePtr test below + } + + if ( pCell && pCell->HasNote() && ( bIsMerged || + ( !pInfo->bHOverlapped && !pInfo->bVOverlapped ) ) ) + { + long nNoteWidth = (long)( SC_CLIPMARK_SIZE * nPPTX ); + long nNoteHeight = (long)( SC_CLIPMARK_SIZE * nPPTY ); + + long nMarkX = nPosX + ( pRowInfo[0].pCellInfo[nX+1].nWidth - nNoteWidth ) * nLayoutSign; + if ( bIsMerged || pInfo->bMerged ) + { + // if merged, add widths of all cells + SCCOL nNextX = nX + 1; + while ( nNextX <= nX2 + 1 && pThisRowInfo->pCellInfo[nNextX+1].bHOverlapped ) + { + nMarkX += pRowInfo[0].pCellInfo[nNextX+1].nWidth * nLayoutSign; + ++nNextX; + } + } + if ( bLayoutRTL ? ( nMarkX >= 0 ) : ( nMarkX < nScrX+nScrW ) ) + { + Rectangle aNoteRect( nMarkX, nPosY, nMarkX+nNoteWidth*nLayoutSign, nPosY+nNoteHeight ); + const ScPostIt* pNote = pCell->GetNote(); + + // Note title is the cell address (as on printed note pages) + String aTitle; + ScAddress aAddress( nMergeX, nMergeY, nTab ); + aAddress.Format( aTitle, SCA_VALID, pDoc, pDoc->GetAddressConvention() ); + + // Content has to be a simple string without line breaks + String aContent = pNote->GetText(); + xub_StrLen nPos; + while ( (nPos=aContent.Search('\n')) != STRING_NOTFOUND ) + aContent.SetChar( nPos, ' ' ); + + vcl::PDFNote aNote; + aNote.Title = aTitle; + aNote.Contents = aContent; + pPDFData->CreateNote( aNoteRect, aNote ); + } + } + + nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign; + } + } + nPosY += pThisRowInfo->nHeight; + } +} + +void ScOutputData::DrawClipMarks() +{ + if (!bAnyClipped) + return; + + Color aArrowFillCol( COL_LIGHTRED ); + + sal_uLong nOldDrawMode = pDev->GetDrawMode(); + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + if ( bUseStyleColor && rStyleSettings.GetHighContrastMode() ) + { + // use DrawMode to change the arrow's outline color + pDev->SetDrawMode( nOldDrawMode | DRAWMODE_SETTINGSLINE ); + // use text color also for the fill color + aArrowFillCol.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor ); + } + + long nInitPosX = nScrX; + if ( bLayoutRTL ) + nInitPosX += nMirrorW - 1; // always in pixels + long nLayoutSign = bLayoutRTL ? -1 : 1; + + Rectangle aCellRect; + long nPosY = nScrY; + for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++) + { + RowInfo* pThisRowInfo = &pRowInfo[nArrY]; + if ( pThisRowInfo->bChanged ) + { + SCROW nY = pThisRowInfo->nRowNo; + long nPosX = nInitPosX; + for (SCCOL nX=nX1; nX<=nX2; nX++) + { + CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1]; + if (pInfo->nClipMark) + { + if (pInfo->bHOverlapped || pInfo->bVOverlapped) + { + // merge origin may be outside of visible area - use document functions + + SCCOL nOverX = nX; + SCROW nOverY = nY; + long nStartPosX = nPosX; + long nStartPosY = nPosY; + + while ( nOverX > 0 && ( ((const ScMergeFlagAttr*)pDoc->GetAttr( + nOverX, nOverY, nTab, ATTR_MERGE_FLAG ))->GetValue() & SC_MF_HOR ) ) + { + --nOverX; + nStartPosX -= nLayoutSign * (long) ( pDoc->GetColWidth(nOverX,nTab) * nPPTX ); + } + + while ( nOverY > 0 && ( ((const ScMergeFlagAttr*)pDoc->GetAttr( + nOverX, nOverY, nTab, ATTR_MERGE_FLAG ))->GetValue() & SC_MF_VER ) ) + { + --nOverY; + nStartPosY -= nLayoutSign * (long) ( pDoc->GetRowHeight(nOverY,nTab) * nPPTY ); + } + + long nOutWidth = (long) ( pDoc->GetColWidth(nOverX,nTab) * nPPTX ); + long nOutHeight = (long) ( pDoc->GetRowHeight(nOverY,nTab) * nPPTY ); + + const ScMergeAttr* pMerge = (const ScMergeAttr*) + pDoc->GetAttr( nOverX, nOverY, nTab, ATTR_MERGE ); + SCCOL nCountX = pMerge->GetColMerge(); + for (SCCOL i=1; i<nCountX; i++) + nOutWidth += (long) ( pDoc->GetColWidth(nOverX+i,nTab) * nPPTX ); + SCROW nCountY = pMerge->GetRowMerge(); + nOutHeight += (long) pDoc->GetScaledRowHeight( nOverY+1, nOverY+nCountY-1, nTab, nPPTY); + + if ( bLayoutRTL ) + nStartPosX -= nOutWidth - 1; + aCellRect = Rectangle( Point( nStartPosX, nStartPosY ), Size( nOutWidth, nOutHeight ) ); + } + else + { + long nOutWidth = pRowInfo[0].pCellInfo[nX+1].nWidth; + long nOutHeight = pThisRowInfo->nHeight; + + if ( pInfo->bMerged && pInfo->pPatternAttr ) + { + SCCOL nOverX = nX; + SCROW nOverY = nY; + const ScMergeAttr* pMerge = + (ScMergeAttr*)&pInfo->pPatternAttr->GetItem(ATTR_MERGE); + SCCOL nCountX = pMerge->GetColMerge(); + for (SCCOL i=1; i<nCountX; i++) + nOutWidth += (long) ( pDoc->GetColWidth(nOverX+i,nTab) * nPPTX ); + SCROW nCountY = pMerge->GetRowMerge(); + nOutHeight += (long) pDoc->GetScaledRowHeight( nOverY+1, nOverY+nCountY-1, nTab, nPPTY); + } + + long nStartPosX = nPosX; + if ( bLayoutRTL ) + nStartPosX -= nOutWidth - 1; + // #i80447# create aCellRect from two points in case nOutWidth is 0 + aCellRect = Rectangle( Point( nStartPosX, nPosY ), + Point( nStartPosX+nOutWidth-1, nPosY+nOutHeight-1 ) ); + } + + aCellRect.Bottom() -= 1; // don't paint over the cell grid + if ( bLayoutRTL ) + aCellRect.Left() += 1; + else + aCellRect.Right() -= 1; + + long nMarkPixel = (long)( SC_CLIPMARK_SIZE * nPPTX ); + Size aMarkSize( nMarkPixel, (nMarkPixel-1)*2 ); + + if ( pInfo->nClipMark & ( bLayoutRTL ? SC_CLIPMARK_RIGHT : SC_CLIPMARK_LEFT ) ) + { + // visually left + Rectangle aMarkRect = aCellRect; + aMarkRect.Right() = aCellRect.Left()+nMarkPixel-1; +#if 0 + //! Test + pDev->SetLineColor(); pDev->SetFillColor(COL_YELLOW); + pDev->DrawRect(aMarkRect); + //! Test +#endif + SvxFont::DrawArrow( *pDev, aMarkRect, aMarkSize, aArrowFillCol, sal_True ); + } + if ( pInfo->nClipMark & ( bLayoutRTL ? SC_CLIPMARK_LEFT : SC_CLIPMARK_RIGHT ) ) + { + // visually right + Rectangle aMarkRect = aCellRect; + aMarkRect.Left() = aCellRect.Right()-nMarkPixel+1; +#if 0 + //! Test + pDev->SetLineColor(); pDev->SetFillColor(COL_LIGHTGREEN); + pDev->DrawRect(aMarkRect); + //! Test +#endif + SvxFont::DrawArrow( *pDev, aMarkRect, aMarkSize, aArrowFillCol, sal_False ); + } + } + nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign; + } + } + nPosY += pThisRowInfo->nHeight; + } + + pDev->SetDrawMode(nOldDrawMode); +} + + + diff --git a/sc/source/ui/view/output2.cxx b/sc/source/ui/view/output2.cxx new file mode 100644 index 000000000000..b1d6787d3ce6 --- /dev/null +++ b/sc/source/ui/view/output2.cxx @@ -0,0 +1,3705 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + + +// INCLUDE --------------------------------------------------------------- + +#include "scitems.hxx" +#include <editeng/eeitem.hxx> + + +#include <editeng/adjitem.hxx> +#include <svx/algitem.hxx> +#include <editeng/brshitem.hxx> +#include <svtools/colorcfg.hxx> +#include <editeng/colritem.hxx> +#include <editeng/editobj.hxx> +#include <editeng/editstat.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/forbiddencharacterstable.hxx> +#include <editeng/frmdiritem.hxx> +#include <editeng/langitem.hxx> +#include <svx/rotmodit.hxx> +#include <editeng/scripttypeitem.hxx> +#include <editeng/udlnitem.hxx> +#include <editeng/unolingu.hxx> +#include <svl/zforlist.hxx> +#include <svl/zformat.hxx> +#include <vcl/svapp.hxx> +#include <vcl/metric.hxx> +#include <vcl/outdev.hxx> +#include <vcl/pdfextoutdevdata.hxx> + +#ifndef _SVSTDARR_USHORTS +#define _SVSTDARR_USHORTS +#include <svl/svstdarr.hxx> +#endif + +#include "output.hxx" +#include "document.hxx" +#include "cell.hxx" +#include "attrib.hxx" +#include "patattr.hxx" +#include "cellform.hxx" +#include "editutil.hxx" +#include "progress.hxx" +#include "scmod.hxx" +#include "fillinfo.hxx" + +#include <boost/ptr_container/ptr_vector.hpp> + +#include <math.h> + +//! Autofilter-Breite mit column.cxx zusammenfassen +#define DROPDOWN_BITMAP_SIZE 18 + +#define DRAWTEXT_MAX 32767 + +const sal_uInt16 SC_SHRINKAGAIN_MAX = 7; + +// STATIC DATA ----------------------------------------------------------- + + +// ----------------------------------------------------------------------- + +class ScDrawStringsVars +{ + ScOutputData* pOutput; // Verbindung + + const ScPatternAttr* pPattern; // Attribute + const SfxItemSet* pCondSet; // aus bedingter Formatierung + + Font aFont; // aus Attributen erzeugt + FontMetric aMetric; + long nAscentPixel; // always pixels + SvxCellOrientation eAttrOrient; + SvxCellHorJustify eAttrHorJust; + SvxCellVerJustify eAttrVerJust; + const SvxMarginItem* pMargin; + sal_uInt16 nIndent; + sal_Bool bRotated; + + String aString; // Inhalte + Size aTextSize; + long nOriginalWidth; + long nMaxDigitWidth; + long nSignWidth; + long nDotWidth; + long nExpWidth; + + ScBaseCell* pLastCell; + sal_uLong nValueFormat; + sal_Bool bLineBreak; + sal_Bool bRepeat; + sal_Bool bShrink; + + sal_Bool bPixelToLogic; + sal_Bool bCellContrast; + + Color aBackConfigColor; // used for ScPatternAttr::GetFont calls + Color aTextConfigColor; + +public: + ScDrawStringsVars(ScOutputData* pData, sal_Bool bPTL); + ~ScDrawStringsVars(); + + // SetPattern = ex-SetVars + // SetPatternSimple: ohne Font + + void SetPattern( const ScPatternAttr* pNew, const SfxItemSet* pSet, ScBaseCell* pCell, sal_uInt8 nScript ); + void SetPatternSimple( const ScPatternAttr* pNew, const SfxItemSet* pSet ); + + sal_Bool SetText( ScBaseCell* pCell ); // sal_True -> pOldPattern vergessen + void SetTextToWidthOrHash( ScBaseCell* pCell, long nWidth ); + void SetAutoText( const String& rAutoText ); + + const ScPatternAttr* GetPattern() const { return pPattern; } + SvxCellOrientation GetOrient() const { return eAttrOrient; } + SvxCellHorJustify GetHorJust() const { return eAttrHorJust; } + SvxCellVerJustify GetVerJust() const { return eAttrVerJust; } + const SvxMarginItem* GetMargin() const { return pMargin; } + + sal_uInt16 GetLeftTotal() const { return pMargin->GetLeftMargin() + nIndent; } + + const String& GetString() const { return aString; } + const Size& GetTextSize() const { return aTextSize; } + long GetOriginalWidth() const { return nOriginalWidth; } + + sal_uLong GetValueFormat() const { return nValueFormat; } + sal_Bool GetLineBreak() const { return bLineBreak; } + sal_Bool IsRepeat() const { return bRepeat; } + sal_Bool IsShrink() const { return bShrink; } + + long GetAscent() const { return nAscentPixel; } + sal_Bool IsRotated() const { return bRotated; } + + void SetShrinkScale( long nScale, sal_uInt8 nScript ); + + sal_Bool HasCondHeight() const { return pCondSet && SFX_ITEM_SET == + pCondSet->GetItemState( ATTR_FONT_HEIGHT, sal_True ); } + + sal_Bool HasEditCharacters() const; + +private: + void SetHashText(); + long GetMaxDigitWidth(); // in logic units + long GetSignWidth(); + long GetDotWidth(); + long GetExpWidth(); + void TextChanged(); +}; + +//================================================================== + +ScDrawStringsVars::ScDrawStringsVars(ScOutputData* pData, sal_Bool bPTL) : + pOutput ( pData ), + pPattern ( NULL ), + pCondSet ( NULL ), + eAttrOrient ( SVX_ORIENTATION_STANDARD ), + eAttrHorJust( SVX_HOR_JUSTIFY_STANDARD ), + eAttrVerJust( SVX_VER_JUSTIFY_BOTTOM ), + pMargin ( NULL ), + nIndent ( 0 ), + bRotated ( sal_False ), + nOriginalWidth( 0 ), + nMaxDigitWidth( 0 ), + nSignWidth( 0 ), + nDotWidth( 0 ), + nExpWidth( 0 ), + pLastCell ( NULL ), + nValueFormat( 0 ), + bLineBreak ( sal_False ), + bRepeat ( sal_False ), + bShrink ( sal_False ), + bPixelToLogic( bPTL ) +{ + ScModule* pScMod = SC_MOD(); + // #105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed sal_True) + bCellContrast = pOutput->bUseStyleColor && + Application::GetSettings().GetStyleSettings().GetHighContrastMode(); + + const svtools::ColorConfig& rColorConfig = pScMod->GetColorConfig(); + aBackConfigColor.SetColor( rColorConfig.GetColorValue(svtools::DOCCOLOR).nColor ); + aTextConfigColor.SetColor( rColorConfig.GetColorValue(svtools::FONTCOLOR).nColor ); +} + +ScDrawStringsVars::~ScDrawStringsVars() +{ +} + +void ScDrawStringsVars::SetShrinkScale( long nScale, sal_uInt8 nScript ) +{ + // text remains valid, size is updated + + OutputDevice* pDev = pOutput->pDev; + OutputDevice* pRefDevice = pOutput->pRefDevice; + OutputDevice* pFmtDevice = pOutput->pFmtDevice; + + // call GetFont with a modified fraction, use only the height + + Fraction aFraction( nScale, 100 ); + if ( !bPixelToLogic ) + aFraction *= pOutput->aZoomY; + Font aTmpFont; + pPattern->GetFont( aTmpFont, SC_AUTOCOL_RAW, pFmtDevice, &aFraction, pCondSet, nScript ); + long nNewHeight = aTmpFont.GetHeight(); + if ( nNewHeight > 0 ) + aFont.SetHeight( nNewHeight ); + + // set font and dependent variables as in SetPattern + + pDev->SetFont( aFont ); + if ( pFmtDevice != pDev ) + pFmtDevice->SetFont( aFont ); + + aMetric = pFmtDevice->GetFontMetric(); + if ( pFmtDevice->GetOutDevType() == OUTDEV_PRINTER && aMetric.GetIntLeading() == 0 ) + { + OutputDevice* pDefaultDev = Application::GetDefaultDevice(); + MapMode aOld = pDefaultDev->GetMapMode(); + pDefaultDev->SetMapMode( pFmtDevice->GetMapMode() ); + aMetric = pDefaultDev->GetFontMetric( aFont ); + pDefaultDev->SetMapMode( aOld ); + } + + nAscentPixel = aMetric.GetAscent(); + if ( bPixelToLogic ) + nAscentPixel = pRefDevice->LogicToPixel( Size( 0, nAscentPixel ) ).Height(); + + SetAutoText( aString ); // same text again, to get text size +} + +void ScDrawStringsVars::SetPattern( const ScPatternAttr* pNew, const SfxItemSet* pSet, + ScBaseCell* pCell, sal_uInt8 nScript ) +{ + nMaxDigitWidth = 0; + nSignWidth = 0; + nDotWidth = 0; + nExpWidth = 0; + + pPattern = pNew; + pCondSet = pSet; + + // pPattern auswerten + + OutputDevice* pDev = pOutput->pDev; + OutputDevice* pRefDevice = pOutput->pRefDevice; + OutputDevice* pFmtDevice = pOutput->pFmtDevice; + + // Font + + ScAutoFontColorMode eColorMode; + if ( pOutput->bUseStyleColor ) + { + if ( pOutput->bForceAutoColor ) + eColorMode = bCellContrast ? SC_AUTOCOL_IGNOREALL : SC_AUTOCOL_IGNOREFONT; + else + eColorMode = bCellContrast ? SC_AUTOCOL_IGNOREBACK : SC_AUTOCOL_DISPLAY; + } + else + eColorMode = SC_AUTOCOL_PRINT; + + if ( bPixelToLogic ) + pPattern->GetFont( aFont, eColorMode, pFmtDevice, NULL, pCondSet, nScript, + &aBackConfigColor, &aTextConfigColor ); + else + pPattern->GetFont( aFont, eColorMode, pFmtDevice, &pOutput->aZoomY, pCondSet, nScript, + &aBackConfigColor, &aTextConfigColor ); + aFont.SetAlign(ALIGN_BASELINE); + + // Orientierung + + eAttrOrient = pPattern->GetCellOrientation( pCondSet ); + + // alignment + + eAttrHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem&)pPattern->GetItem( ATTR_HOR_JUSTIFY, pCondSet )).GetValue(); + + eAttrVerJust = (SvxCellVerJustify)((const SvxVerJustifyItem&)pPattern->GetItem( ATTR_VER_JUSTIFY, pCondSet )).GetValue(); + if ( eAttrVerJust == SVX_VER_JUSTIFY_STANDARD ) + eAttrVerJust = SVX_VER_JUSTIFY_BOTTOM; + + // line break + + bLineBreak = ((const SfxBoolItem&)pPattern->GetItem( ATTR_LINEBREAK, pCondSet )).GetValue(); + + // handle "repeat" alignment + + bRepeat = ( eAttrHorJust == SVX_HOR_JUSTIFY_REPEAT ); + if ( bRepeat ) + { + // "repeat" disables rotation (before constructing the font) + eAttrOrient = SVX_ORIENTATION_STANDARD; + + // #i31843# "repeat" with "line breaks" is treated as default alignment (but rotation is still disabled) + if ( bLineBreak ) + eAttrHorJust = SVX_HOR_JUSTIFY_STANDARD; + } + + short nRot; + switch (eAttrOrient) + { + case SVX_ORIENTATION_STANDARD: + nRot = 0; + bRotated = (((const SfxInt32Item&)pPattern->GetItem( ATTR_ROTATE_VALUE, pCondSet )).GetValue() != 0) && + !bRepeat; + break; + case SVX_ORIENTATION_STACKED: + nRot = 0; + bRotated = sal_False; + break; + case SVX_ORIENTATION_TOPBOTTOM: + nRot = 2700; + bRotated = sal_False; + break; + case SVX_ORIENTATION_BOTTOMTOP: + nRot = 900; + bRotated = sal_False; + break; + default: + DBG_ERROR("Falscher SvxCellOrientation Wert"); + nRot = 0; + bRotated = sal_False; + break; + } + aFont.SetOrientation( nRot ); + + // Syntax-Modus + + if (pOutput->bSyntaxMode) + pOutput->SetSyntaxColor( &aFont, pCell ); + + pDev->SetFont( aFont ); + if ( pFmtDevice != pDev ) + pFmtDevice->SetFont( aFont ); + + aMetric = pFmtDevice->GetFontMetric(); + + // + // Wenn auf dem Drucker das Leading 0 ist, gibt es Probleme + // -> Metric vom Bildschirm nehmen (wie EditEngine!) + // + + if ( pFmtDevice->GetOutDevType() == OUTDEV_PRINTER && aMetric.GetIntLeading() == 0 ) + { + OutputDevice* pDefaultDev = Application::GetDefaultDevice(); + MapMode aOld = pDefaultDev->GetMapMode(); + pDefaultDev->SetMapMode( pFmtDevice->GetMapMode() ); + aMetric = pDefaultDev->GetFontMetric( aFont ); + pDefaultDev->SetMapMode( aOld ); + } + + nAscentPixel = aMetric.GetAscent(); + if ( bPixelToLogic ) + nAscentPixel = pRefDevice->LogicToPixel( Size( 0, nAscentPixel ) ).Height(); + + Color aULineColor( ((const SvxUnderlineItem&)pPattern->GetItem( ATTR_FONT_UNDERLINE, pCondSet )).GetColor() ); + pDev->SetTextLineColor( aULineColor ); + + Color aOLineColor( ((const SvxOverlineItem&)pPattern->GetItem( ATTR_FONT_OVERLINE, pCondSet )).GetColor() ); + pDev->SetOverlineColor( aOLineColor ); + + // Zahlenformat + +// sal_uLong nOld = nValueFormat; + nValueFormat = pPattern->GetNumberFormat( pOutput->pDoc->GetFormatTable(), pCondSet ); + +/* s.u. + if (nValueFormat != nOld) + pLastCell = NULL; // immer neu formatieren +*/ + // Raender + + pMargin = (const SvxMarginItem*)&pPattern->GetItem( ATTR_MARGIN, pCondSet ); + if ( eAttrHorJust == SVX_HOR_JUSTIFY_LEFT ) + nIndent = ((const SfxUInt16Item&)pPattern->GetItem( ATTR_INDENT, pCondSet )).GetValue(); + else + nIndent = 0; + + // "Shrink to fit" + + bShrink = static_cast<const SfxBoolItem&>(pPattern->GetItem( ATTR_SHRINKTOFIT, pCondSet )).GetValue(); + + // zumindest die Text-Groesse muss neu geholt werden + //! unterscheiden, und den Text nicht neu vom Numberformatter holen? + + pLastCell = NULL; +} + +void ScDrawStringsVars::SetPatternSimple( const ScPatternAttr* pNew, const SfxItemSet* pSet ) +{ + nMaxDigitWidth = 0; + nSignWidth = 0; + nDotWidth = 0; + nExpWidth = 0; + // wird gerufen, wenn sich die Font-Variablen nicht aendern (!StringDiffer) + + pPattern = pNew; + pCondSet = pSet; //! noetig ??? + + // Zahlenformat + + sal_uLong nOld = nValueFormat; +// nValueFormat = pPattern->GetNumberFormat( pFormatter ); + const SfxPoolItem* pFormItem; + if ( !pCondSet || pCondSet->GetItemState(ATTR_VALUE_FORMAT,sal_True,&pFormItem) != SFX_ITEM_SET ) + pFormItem = &pPattern->GetItem(ATTR_VALUE_FORMAT); + const SfxPoolItem* pLangItem; + if ( !pCondSet || pCondSet->GetItemState(ATTR_LANGUAGE_FORMAT,sal_True,&pLangItem) != SFX_ITEM_SET ) + pLangItem = &pPattern->GetItem(ATTR_LANGUAGE_FORMAT); + nValueFormat = pOutput->pDoc->GetFormatTable()->GetFormatForLanguageIfBuiltIn( + ((SfxUInt32Item*)pFormItem)->GetValue(), + ((SvxLanguageItem*)pLangItem)->GetLanguage() ); + + if (nValueFormat != nOld) + pLastCell = NULL; // immer neu formatieren + + // Raender + + pMargin = (const SvxMarginItem*)&pPattern->GetItem( ATTR_MARGIN, pCondSet ); + + if ( eAttrHorJust == SVX_HOR_JUSTIFY_LEFT ) + nIndent = ((const SfxUInt16Item&)pPattern->GetItem( ATTR_INDENT, pCondSet )).GetValue(); + else + nIndent = 0; + + // "Shrink to fit" + + bShrink = static_cast<const SfxBoolItem&>(pPattern->GetItem( ATTR_SHRINKTOFIT, pCondSet )).GetValue(); +} + +inline sal_Bool SameValue( ScBaseCell* pCell, ScBaseCell* pOldCell ) // pCell ist != 0 +{ + return pOldCell && pOldCell->GetCellType() == CELLTYPE_VALUE && + pCell->GetCellType() == CELLTYPE_VALUE && + ((ScValueCell*)pCell)->GetValue() == ((ScValueCell*)pOldCell)->GetValue(); +} + +sal_Bool ScDrawStringsVars::SetText( ScBaseCell* pCell ) +{ + sal_Bool bChanged = sal_False; + + if (pCell) + { + if ( !SameValue( pCell, pLastCell ) ) + { + pLastCell = pCell; // Zelle merken + + Color* pColor; + sal_uLong nFormat = GetValueFormat(); + ScCellFormat::GetString( pCell, + nFormat, aString, &pColor, + *pOutput->pDoc->GetFormatTable(), + pOutput->bShowNullValues, + pOutput->bShowFormulas, + ftCheck ); + + if (aString.Len() > DRAWTEXT_MAX) + aString.Erase(DRAWTEXT_MAX); + + if ( pColor && !pOutput->bSyntaxMode && !( pOutput->bUseStyleColor && pOutput->bForceAutoColor ) ) + { + OutputDevice* pDev = pOutput->pDev; + aFont.SetColor(*pColor); + pDev->SetFont( aFont ); // nur fuer Ausgabe + bChanged = sal_True; + pLastCell = NULL; // naechstes Mal wieder hierherkommen + } + + TextChanged(); + } + // sonst String/Groesse behalten + } + else + { + aString.Erase(); + pLastCell = NULL; + aTextSize = Size(0,0); + nOriginalWidth = 0; + } + + return bChanged; +} + +void ScDrawStringsVars::SetHashText() +{ + SetAutoText( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("###")) ); +} + +void ScDrawStringsVars::SetTextToWidthOrHash( ScBaseCell* pCell, long nWidth ) +{ + // #i113045# do the single-character width calculations in logic units + if (bPixelToLogic) + nWidth = pOutput->pRefDevice->PixelToLogic(Size(nWidth,0)).Width(); + + if (!pCell) + return; + + CellType eType = pCell->GetCellType(); + if (eType != CELLTYPE_VALUE && eType != CELLTYPE_FORMULA) + // must be a value or formula cell. + return; + + if (eType == CELLTYPE_FORMULA) + { + ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell); + if (pFCell->GetErrCode() != 0) + { + SetHashText(); // If the error string doesn't fit, always use "###" + return; + } + // If it's formula, the result must be a value. + if (!pFCell->IsValue()) + return; + } + + sal_uLong nFormat = GetValueFormat(); + if ((nFormat % SV_COUNTRY_LANGUAGE_OFFSET) != 0) + { + // Not 'General' number format. Set hash text and bail out. + SetHashText(); + return; + } + + double fVal = (eType == CELLTYPE_VALUE) ? + static_cast<ScValueCell*>(pCell)->GetValue() : static_cast<ScFormulaCell*>(pCell)->GetValue(); + + const SvNumberformat* pNumFormat = pOutput->pDoc->GetFormatTable()->GetEntry(nFormat); + if (!pNumFormat) + return; + + long nMaxDigit = GetMaxDigitWidth(); + sal_uInt16 nNumDigits = static_cast<sal_uInt16>(nWidth / nMaxDigit); + + if (!pNumFormat->GetOutputString(fVal, nNumDigits, aString)) + // Failed to get output string. Bail out. + return; + + sal_uInt8 nSignCount = 0, nDecimalCount = 0, nExpCount = 0; + xub_StrLen nLen = aString.Len(); + sal_Unicode cDecSep = ScGlobal::GetpLocaleData()->getLocaleItem().decimalSeparator.getStr()[0]; + for (xub_StrLen i = 0; i < nLen; ++i) + { + sal_Unicode c = aString.GetChar(i); + if (c == sal_Unicode('-')) + ++nSignCount; + else if (c == cDecSep) + ++nDecimalCount; + else if (c == sal_Unicode('E')) + ++nExpCount; + } + + // #i112250# A small value might be formatted as "0" when only counting the digits, + // but fit into the column when considering the smaller width of the decimal separator. + if (aString.EqualsAscii("0") && fVal != 0.0) + nDecimalCount = 1; + + if (nDecimalCount) + nWidth += (nMaxDigit - GetDotWidth()) * nDecimalCount; + if (nSignCount) + nWidth += (nMaxDigit - GetSignWidth()) * nSignCount; + if (nExpCount) + nWidth += (nMaxDigit - GetExpWidth()) * nExpCount; + + if (nDecimalCount || nSignCount || nExpCount) + { + // Re-calculate. + nNumDigits = static_cast<sal_uInt16>(nWidth / nMaxDigit); + if (!pNumFormat->GetOutputString(fVal, nNumDigits, aString)) + // Failed to get output string. Bail out. + return; + } + + long nActualTextWidth = pOutput->pFmtDevice->GetTextWidth(aString); + if (nActualTextWidth > nWidth) + { + // Even after the decimal adjustment the text doesn't fit. Give up. + SetHashText(); + return; + } + + TextChanged(); + pLastCell = NULL; // #i113022# equal cell and format in another column may give different string +} + +void ScDrawStringsVars::SetAutoText( const String& rAutoText ) +{ + aString = rAutoText; + + OutputDevice* pRefDevice = pOutput->pRefDevice; + OutputDevice* pFmtDevice = pOutput->pFmtDevice; + aTextSize.Width() = pFmtDevice->GetTextWidth( aString ); + aTextSize.Height() = pFmtDevice->GetTextHeight(); + + if ( !pRefDevice->GetConnectMetaFile() || pRefDevice->GetOutDevType() == OUTDEV_PRINTER ) + { + double fMul = pOutput->GetStretch(); + aTextSize.Width() = (long)(aTextSize.Width() / fMul + 0.5); + } + + aTextSize.Height() = aMetric.GetAscent() + aMetric.GetDescent(); + if ( GetOrient() != SVX_ORIENTATION_STANDARD ) + { + long nTemp = aTextSize.Height(); + aTextSize.Height() = aTextSize.Width(); + aTextSize.Width() = nTemp; + } + + nOriginalWidth = aTextSize.Width(); + if ( bPixelToLogic ) + aTextSize = pRefDevice->LogicToPixel( aTextSize ); + + pLastCell = NULL; // derselbe Text kann in der naechsten Zelle wieder passen +} + +long ScDrawStringsVars::GetMaxDigitWidth() +{ + if (nMaxDigitWidth > 0) + return nMaxDigitWidth; + + sal_Char cZero = '0'; + for (sal_Char i = 0; i < 10; ++i) + { + sal_Char cDigit = cZero + i; + long n = pOutput->pFmtDevice->GetTextWidth(String(cDigit)); + nMaxDigitWidth = ::std::max(nMaxDigitWidth, n); + } + return nMaxDigitWidth; +} + +long ScDrawStringsVars::GetSignWidth() +{ + if (nSignWidth > 0) + return nSignWidth; + + nSignWidth = pOutput->pFmtDevice->GetTextWidth(String('-')); + return nSignWidth; +} + +long ScDrawStringsVars::GetDotWidth() +{ + if (nDotWidth > 0) + return nDotWidth; + + const ::rtl::OUString& sep = ScGlobal::GetpLocaleData()->getLocaleItem().decimalSeparator; + nDotWidth = pOutput->pFmtDevice->GetTextWidth(sep); + return nDotWidth; +} + +long ScDrawStringsVars::GetExpWidth() +{ + if (nExpWidth > 0) + return nExpWidth; + + nExpWidth = pOutput->pFmtDevice->GetTextWidth(String('E')); + return nExpWidth; +} + +void ScDrawStringsVars::TextChanged() +{ + OutputDevice* pRefDevice = pOutput->pRefDevice; + OutputDevice* pFmtDevice = pOutput->pFmtDevice; + aTextSize.Width() = pFmtDevice->GetTextWidth( aString ); + aTextSize.Height() = pFmtDevice->GetTextHeight(); + + if ( !pRefDevice->GetConnectMetaFile() || pRefDevice->GetOutDevType() == OUTDEV_PRINTER ) + { + double fMul = pOutput->GetStretch(); + aTextSize.Width() = (long)(aTextSize.Width() / fMul + 0.5); + } + + aTextSize.Height() = aMetric.GetAscent() + aMetric.GetDescent(); + if ( GetOrient() != SVX_ORIENTATION_STANDARD ) + { + long nTemp = aTextSize.Height(); + aTextSize.Height() = aTextSize.Width(); + aTextSize.Width() = nTemp; + } + + nOriginalWidth = aTextSize.Width(); + if ( bPixelToLogic ) + aTextSize = pRefDevice->LogicToPixel( aTextSize ); +} + +sal_Bool ScDrawStringsVars::HasEditCharacters() const +{ + static const sal_Unicode pChars[] = + { + CHAR_NBSP, CHAR_SHY, CHAR_ZWSP, CHAR_LRM, CHAR_RLM, CHAR_NBHY, CHAR_ZWNBSP, 0 + }; + return aString.SearchChar( pChars ) != STRING_NOTFOUND; +} + +//================================================================== + +double ScOutputData::GetStretch() +{ + if ( pRefDevice->IsMapMode() ) + { + // #95920# If a non-trivial MapMode is set, its scale is now already + // taken into account in the OutputDevice's font handling + // (OutputDevice::ImplNewFont, see #95414#). + // The old handling below is only needed for pixel output. + return 1.0; + } + + // calculation in double is faster than Fraction multiplication + // and doesn't overflow + + if ( pRefDevice == pFmtDevice ) + { + MapMode aOld = pRefDevice->GetMapMode(); + return ((double)aOld.GetScaleY()) / ((double)aOld.GetScaleX()) * ((double)aZoomY) / ((double)aZoomX); + } + else + { + // when formatting for printer, device map mode has already been taken care of + return ((double)aZoomY) / ((double)aZoomX); + } +} + +//================================================================== + +// +// output strings +// + +void lcl_DoHyperlinkResult( OutputDevice* pDev, const Rectangle& rRect, ScBaseCell* pCell ) +{ + vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, pDev->GetExtOutDevData() ); + + String aCellText; + String aURL; + if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA ) + { + ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell); + if ( pFCell->IsHyperLinkCell() ) + pFCell->GetURLResult( aURL, aCellText ); + } + + if ( aURL.Len() && pPDFData ) + { + vcl::PDFExtOutDevBookmarkEntry aBookmark; + aBookmark.nLinkId = pPDFData->CreateLink( rRect ); + aBookmark.aBookmark = aURL; + std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = pPDFData->GetBookmarks(); + rBookmarks.push_back( aBookmark ); + } +} + +void ScOutputData::SetSyntaxColor( Font* pFont, ScBaseCell* pCell ) +{ + if (pCell) + { + switch (pCell->GetCellType()) + { + case CELLTYPE_VALUE: + pFont->SetColor( *pValueColor ); + break; + case CELLTYPE_STRING: + pFont->SetColor( *pTextColor ); + break; + case CELLTYPE_FORMULA: + pFont->SetColor( *pFormulaColor ); + break; + default: + { + // added to avoid warnings + } + } + } +} + +void lcl_SetEditColor( EditEngine& rEngine, const Color& rColor ) +{ + ESelection aSel( 0, 0, rEngine.GetParagraphCount(), 0 ); + SfxItemSet aSet( rEngine.GetEmptyItemSet() ); + aSet.Put( SvxColorItem( rColor, EE_CHAR_COLOR ) ); + rEngine.QuickSetAttribs( aSet, aSel ); + // function is called with update mode set to FALSE +} + +void ScOutputData::SetEditSyntaxColor( EditEngine& rEngine, ScBaseCell* pCell ) +{ + if (pCell) + { + Color aColor; + switch (pCell->GetCellType()) + { + case CELLTYPE_VALUE: + aColor = *pValueColor; + break; + case CELLTYPE_STRING: + aColor = *pTextColor; + break; + case CELLTYPE_FORMULA: + aColor = *pFormulaColor; + break; + default: + { + // added to avoid warnings + } + } + lcl_SetEditColor( rEngine, aColor ); + } +} + +sal_Bool ScOutputData::GetMergeOrigin( SCCOL nX, SCROW nY, SCSIZE nArrY, + SCCOL& rOverX, SCROW& rOverY, + sal_Bool bVisRowChanged ) +{ + sal_Bool bDoMerge = sal_False; + sal_Bool bIsLeft = ( nX == nVisX1 ); + sal_Bool bIsTop = ( nY == nVisY1 ) || bVisRowChanged; + + CellInfo* pInfo = &pRowInfo[nArrY].pCellInfo[nX+1]; + if ( pInfo->bHOverlapped && pInfo->bVOverlapped ) + bDoMerge = bIsLeft && bIsTop; + else if ( pInfo->bHOverlapped ) + bDoMerge = bIsLeft; + else if ( pInfo->bVOverlapped ) + bDoMerge = bIsTop; + + // weiter solange versteckt +/* if (!bDoMerge) + return sal_False; +*/ + + rOverX = nX; + rOverY = nY; + sal_Bool bHOver = pInfo->bHOverlapped; + sal_Bool bVOver = pInfo->bVOverlapped; + sal_Bool bHidden; + + while (bHOver) // nY konstant + { + --rOverX; + bHidden = pDoc->ColHidden(rOverX, nTab); + if ( !bDoMerge && !bHidden ) + return sal_False; + + if (rOverX >= nX1 && !bHidden) + { +// rVirtPosX -= pRowInfo[0].pCellInfo[rOverX+1].nWidth; + bHOver = pRowInfo[nArrY].pCellInfo[rOverX+1].bHOverlapped; + bVOver = pRowInfo[nArrY].pCellInfo[rOverX+1].bVOverlapped; + } + else + { +// if (!bClipVirt) +// rVirtPosX -= (long) (pDoc->GetColWidth( rOverX, nTab ) * nPPTX); + sal_uInt16 nOverlap = ((ScMergeFlagAttr*)pDoc->GetAttr( + rOverX, rOverY, nTab, ATTR_MERGE_FLAG ))->GetValue(); + bHOver = ((nOverlap & SC_MF_HOR) != 0); + bVOver = ((nOverlap & SC_MF_VER) != 0); + } + } + + while (bVOver) + { + --rOverY; + bHidden = pDoc->RowHidden(rOverY, nTab); + if ( !bDoMerge && !bHidden ) + return sal_False; + + if (nArrY>0) + --nArrY; // lokale Kopie ! + + if (rOverX >= nX1 && rOverY >= nY1 && + !pDoc->ColHidden(rOverX, nTab) && + !pDoc->RowHidden(rOverY, nTab) && + pRowInfo[nArrY].nRowNo == rOverY) + { +// rVirtPosY -= pRowInfo[nArrY].nHeight; + bHOver = pRowInfo[nArrY].pCellInfo[rOverX+1].bHOverlapped; + bVOver = pRowInfo[nArrY].pCellInfo[rOverX+1].bVOverlapped; + } + else + { +// if (!bClipVirt) +// rVirtPosY -= (long) (pDoc->GetRowHeight( rOverY, nTab ) * nPPTY); + sal_uInt16 nOverlap = ((ScMergeFlagAttr*)pDoc->GetAttr( + rOverX, rOverY, nTab, ATTR_MERGE_FLAG ))->GetValue(); + bHOver = ((nOverlap & SC_MF_HOR) != 0); + bVOver = ((nOverlap & SC_MF_VER) != 0); + } + } + + return sal_True; +} + +inline sal_Bool StringDiffer( const ScPatternAttr*& rpOldPattern, const ScPatternAttr*& rpNewPattern ) +{ + DBG_ASSERT( rpNewPattern, "pNewPattern" ); + + if ( rpNewPattern == rpOldPattern ) + return sal_False; + else if ( !rpOldPattern ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_FONT ) != &rpOldPattern->GetItem( ATTR_FONT ) ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_CJK_FONT ) != &rpOldPattern->GetItem( ATTR_CJK_FONT ) ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_CTL_FONT ) != &rpOldPattern->GetItem( ATTR_CTL_FONT ) ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_FONT_HEIGHT ) != &rpOldPattern->GetItem( ATTR_FONT_HEIGHT ) ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_CJK_FONT_HEIGHT ) != &rpOldPattern->GetItem( ATTR_CJK_FONT_HEIGHT ) ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_CTL_FONT_HEIGHT ) != &rpOldPattern->GetItem( ATTR_CTL_FONT_HEIGHT ) ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_FONT_WEIGHT ) != &rpOldPattern->GetItem( ATTR_FONT_WEIGHT ) ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_CJK_FONT_WEIGHT ) != &rpOldPattern->GetItem( ATTR_CJK_FONT_WEIGHT ) ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_CTL_FONT_WEIGHT ) != &rpOldPattern->GetItem( ATTR_CTL_FONT_WEIGHT ) ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_FONT_POSTURE ) != &rpOldPattern->GetItem( ATTR_FONT_POSTURE ) ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_CJK_FONT_POSTURE ) != &rpOldPattern->GetItem( ATTR_CJK_FONT_POSTURE ) ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_CTL_FONT_POSTURE ) != &rpOldPattern->GetItem( ATTR_CTL_FONT_POSTURE ) ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_FONT_UNDERLINE ) != &rpOldPattern->GetItem( ATTR_FONT_UNDERLINE ) ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_FONT_OVERLINE ) != &rpOldPattern->GetItem( ATTR_FONT_OVERLINE ) ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_FONT_WORDLINE ) != &rpOldPattern->GetItem( ATTR_FONT_WORDLINE ) ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_FONT_CROSSEDOUT ) != &rpOldPattern->GetItem( ATTR_FONT_CROSSEDOUT ) ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_FONT_CONTOUR ) != &rpOldPattern->GetItem( ATTR_FONT_CONTOUR ) ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_FONT_SHADOWED ) != &rpOldPattern->GetItem( ATTR_FONT_SHADOWED ) ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_FONT_COLOR ) != &rpOldPattern->GetItem( ATTR_FONT_COLOR ) ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_HOR_JUSTIFY ) != &rpOldPattern->GetItem( ATTR_HOR_JUSTIFY ) ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_VER_JUSTIFY ) != &rpOldPattern->GetItem( ATTR_VER_JUSTIFY ) ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_STACKED ) != &rpOldPattern->GetItem( ATTR_STACKED ) ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_LINEBREAK ) != &rpOldPattern->GetItem( ATTR_LINEBREAK ) ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_MARGIN ) != &rpOldPattern->GetItem( ATTR_MARGIN ) ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_ROTATE_VALUE ) != &rpOldPattern->GetItem( ATTR_ROTATE_VALUE ) ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_FORBIDDEN_RULES ) != &rpOldPattern->GetItem( ATTR_FORBIDDEN_RULES ) ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_FONT_EMPHASISMARK ) != &rpOldPattern->GetItem( ATTR_FONT_EMPHASISMARK ) ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_FONT_RELIEF ) != &rpOldPattern->GetItem( ATTR_FONT_RELIEF ) ) + return sal_True; + else if ( &rpNewPattern->GetItem( ATTR_BACKGROUND ) != &rpOldPattern->GetItem( ATTR_BACKGROUND ) ) + return sal_True; // needed with automatic text color + else + { + rpOldPattern = rpNewPattern; + return sal_False; + } +} + +inline void lcl_CreateInterpretProgress( sal_Bool& bProgress, ScDocument* pDoc, + ScFormulaCell* pFCell ) +{ + if ( !bProgress && pFCell->GetDirty() ) + { + ScProgress::CreateInterpretProgress( pDoc, sal_True ); + bProgress = sal_True; + } +} + +inline sal_uInt8 GetScriptType( ScDocument* pDoc, ScBaseCell* pCell, + const ScPatternAttr* pPattern, + const SfxItemSet* pCondSet ) +{ + return pDoc->GetCellScriptType( pCell, pPattern->GetNumberFormat( pDoc->GetFormatTable(), pCondSet ) ); +} + +inline sal_Bool IsAmbiguousScript( sal_uInt8 nScript ) +{ + return ( nScript != SCRIPTTYPE_LATIN && + nScript != SCRIPTTYPE_ASIAN && + nScript != SCRIPTTYPE_COMPLEX ); +} + +sal_Bool ScOutputData::IsEmptyCellText( RowInfo* pThisRowInfo, SCCOL nX, SCROW nY ) +{ + // pThisRowInfo may be NULL + + sal_Bool bEmpty; + if ( pThisRowInfo && nX <= nX2 ) + bEmpty = pThisRowInfo->pCellInfo[nX+1].bEmptyCellText; + else + bEmpty = ( pDoc->GetCell( ScAddress( nX, nY, nTab ) ) == NULL ); + + if ( !bEmpty && ( nX < nX1 || nX > nX2 || !pThisRowInfo ) ) + { + // for the range nX1..nX2 in RowInfo, cell protection attribute is already evaluated + // into bEmptyCellText in ScDocument::FillInfo / lcl_HidePrint (printfun) + + sal_Bool bIsPrint = ( eType == OUTTYPE_PRINTER ); + + if ( bIsPrint || bTabProtected ) + { + const ScProtectionAttr* pAttr = (const ScProtectionAttr*) + pDoc->GetEffItem( nX, nY, nTab, ATTR_PROTECTION ); + if ( bIsPrint && pAttr->GetHidePrint() ) + bEmpty = sal_True; + else if ( bTabProtected ) + { + if ( pAttr->GetHideCell() ) + bEmpty = sal_True; + else if ( bShowFormulas && pAttr->GetHideFormula() ) + { + ScBaseCell* pCell = pDoc->GetCell( ScAddress( nX, nY, nTab ) ); + if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA ) + bEmpty = sal_True; + } + } + } + } + return bEmpty; +} + +void ScOutputData::GetVisibleCell( SCCOL nCol, SCROW nRow, SCTAB nTabP, ScBaseCell*& rpCell ) +{ + pDoc->GetCell( nCol, nRow, nTabP, rpCell ); + if ( rpCell && IsEmptyCellText( NULL, nCol, nRow ) ) + rpCell = NULL; +} + +sal_Bool ScOutputData::IsAvailable( SCCOL nX, SCROW nY ) +{ + // apply the same logic here as in DrawStrings/DrawEdit: + // Stop at non-empty or merged or overlapped cell, + // where a note is empty as well as a cell that's hidden by protection settings + + const ScBaseCell* pCell = pDoc->GetCell( ScAddress( nX, nY, nTab ) ); + if ( pCell && pCell->GetCellType() != CELLTYPE_NOTE && !IsEmptyCellText( NULL, nX, nY ) ) + { + return sal_False; + } + + const ScPatternAttr* pPattern = pDoc->GetPattern( nX, nY, nTab ); + if ( ((const ScMergeAttr&)pPattern->GetItem(ATTR_MERGE)).IsMerged() || + ((const ScMergeFlagAttr&)pPattern->GetItem(ATTR_MERGE_FLAG)).IsOverlapped() ) + { + return sal_False; + } + + return sal_True; +} + +// nX, nArrY: loop variables from DrawStrings / DrawEdit +// nPosX, nPosY: corresponding positions for nX, nArrY +// nCellX, nCellY: position of the cell that contains the text +// nNeeded: Text width, including margin +// rPattern: cell format at nCellX, nCellY +// nHorJustify: horizontal alignment (visual) to determine which cells to use for long strings +// bCellIsValue: if set, don't extend into empty cells +// bBreak: if set, don't extend, and don't set clip marks (but rLeftClip/rRightClip is set) +// bOverwrite: if set, also extend into non-empty cells (for rotated text) +// rParam output: various area parameters. + +void ScOutputData::GetOutputArea( SCCOL nX, SCSIZE nArrY, long nPosX, long nPosY, + SCCOL nCellX, SCROW nCellY, long nNeeded, + const ScPatternAttr& rPattern, + sal_uInt16 nHorJustify, bool bCellIsValue, + bool bBreak, bool bOverwrite, + OutputAreaParam& rParam ) +{ + // rThisRowInfo may be for a different row than nCellY, is still used for clip marks + RowInfo& rThisRowInfo = pRowInfo[nArrY]; + + long nLayoutSign = bLayoutRTL ? -1 : 1; + + long nCellPosX = nPosX; // find nCellX position, starting at nX/nPosX + SCCOL nCompCol = nX; + while ( nCellX > nCompCol ) + { + //! extra member function for width? + long nColWidth = ( nCompCol <= nX2 ) ? + pRowInfo[0].pCellInfo[nCompCol+1].nWidth : + (long) ( pDoc->GetColWidth( nCompCol, nTab ) * nPPTX ); + nCellPosX += nColWidth * nLayoutSign; + ++nCompCol; + } + while ( nCellX < nCompCol ) + { + --nCompCol; + long nColWidth = ( nCompCol <= nX2 ) ? + pRowInfo[0].pCellInfo[nCompCol+1].nWidth : + (long) ( pDoc->GetColWidth( nCompCol, nTab ) * nPPTX ); + nCellPosX -= nColWidth * nLayoutSign; + } + + long nCellPosY = nPosY; // find nCellY position, starting at nArrY/nPosY + SCSIZE nCompArr = nArrY; + SCROW nCompRow = pRowInfo[nCompArr].nRowNo; + while ( nCellY > nCompRow ) + { + if ( nCompArr + 1 < nArrCount ) + { + nCellPosY += pRowInfo[nCompArr].nHeight; + ++nCompArr; + nCompRow = pRowInfo[nCompArr].nRowNo; + } + else + { + sal_uInt16 nDocHeight = pDoc->GetRowHeight( nCompRow, nTab ); + if ( nDocHeight ) + nCellPosY += (long) ( nDocHeight * nPPTY ); + ++nCompRow; + } + } + nCellPosY -= (long) pDoc->GetScaledRowHeight( nCellY, nCompRow-1, nTab, nPPTY ); + + const ScMergeAttr* pMerge = (const ScMergeAttr*)&rPattern.GetItem( ATTR_MERGE ); + sal_Bool bMerged = pMerge->IsMerged(); + long nMergeCols = pMerge->GetColMerge(); + if ( nMergeCols == 0 ) + nMergeCols = 1; + long nMergeRows = pMerge->GetRowMerge(); + if ( nMergeRows == 0 ) + nMergeRows = 1; + + long i; + long nMergeSizeX = 0; + for ( i=0; i<nMergeCols; i++ ) + { + long nColWidth = ( nCellX+i <= nX2 ) ? + pRowInfo[0].pCellInfo[nCellX+i+1].nWidth : + (long) ( pDoc->GetColWidth( sal::static_int_cast<SCCOL>(nCellX+i), nTab ) * nPPTX ); + nMergeSizeX += nColWidth; + } + long nMergeSizeY = 0; + short nDirect = 0; + if ( rThisRowInfo.nRowNo == nCellY ) + { + // take first row's height from row info + nMergeSizeY += rThisRowInfo.nHeight; + nDirect = 1; // skip in loop + } + // following rows always from document + nMergeSizeY += (long) pDoc->GetScaledRowHeight( nCellY+nDirect, nCellY+nMergeRows-1, nTab, nPPTY); + + --nMergeSizeX; // leave out the grid horizontally, also for alignment (align between grid lines) + + rParam.mnColWidth = nMergeSizeX; // store the actual column width. + + // + // construct the rectangles using logical left/right values (justify is called at the end) + // + + // rAlignRect is the single cell or merged area, used for alignment. + + rParam.maAlignRect.Left() = nCellPosX; + rParam.maAlignRect.Right() = nCellPosX + ( nMergeSizeX - 1 ) * nLayoutSign; + rParam.maAlignRect.Top() = nCellPosY; + rParam.maAlignRect.Bottom() = nCellPosY + nMergeSizeY - 1; + + // rClipRect is all cells that are used for output. + // For merged cells this is the same as rAlignRect, otherwise neighboring cells can also be used. + + rParam.maClipRect = rParam.maAlignRect; + if ( nNeeded > nMergeSizeX ) + { + SvxCellHorJustify eHorJust = (SvxCellHorJustify)nHorJustify; + + long nMissing = nNeeded - nMergeSizeX; + long nLeftMissing = 0; + long nRightMissing = 0; + switch ( eHorJust ) + { + case SVX_HOR_JUSTIFY_LEFT: + nRightMissing = nMissing; + break; + case SVX_HOR_JUSTIFY_RIGHT: + nLeftMissing = nMissing; + break; + case SVX_HOR_JUSTIFY_CENTER: + nLeftMissing = nMissing / 2; + nRightMissing = nMissing - nLeftMissing; + break; + default: + { + // added to avoid warnings + } + } + + // nLeftMissing, nRightMissing are logical, eHorJust values are visual + if ( bLayoutRTL ) + ::std::swap( nLeftMissing, nRightMissing ); + + SCCOL nRightX = nCellX; + SCCOL nLeftX = nCellX; + if ( !bMerged && !bCellIsValue && !bBreak ) + { + // look for empty cells into which the text can be extended + + while ( nRightMissing > 0 && nRightX < MAXCOL && ( bOverwrite || IsAvailable( nRightX+1, nCellY ) ) ) + { + ++nRightX; + long nAdd = (long) ( pDoc->GetColWidth( nRightX, nTab ) * nPPTX ); + nRightMissing -= nAdd; + rParam.maClipRect.Right() += nAdd * nLayoutSign; + + if ( rThisRowInfo.nRowNo == nCellY && nRightX >= nX1 && nRightX <= nX2 ) + rThisRowInfo.pCellInfo[nRightX].bHideGrid = sal_True; + } + + while ( nLeftMissing > 0 && nLeftX > 0 && ( bOverwrite || IsAvailable( nLeftX-1, nCellY ) ) ) + { + if ( rThisRowInfo.nRowNo == nCellY && nLeftX >= nX1 && nLeftX <= nX2 ) + rThisRowInfo.pCellInfo[nLeftX].bHideGrid = sal_True; + + --nLeftX; + long nAdd = (long) ( pDoc->GetColWidth( nLeftX, nTab ) * nPPTX ); + nLeftMissing -= nAdd; + rParam.maClipRect.Left() -= nAdd * nLayoutSign; + } + } + + // Set flag and reserve space for clipping mark triangle, + // even if rThisRowInfo isn't for nCellY (merged cells). + if ( nRightMissing > 0 && bMarkClipped && nRightX >= nX1 && nRightX <= nX2 && !bBreak && !bCellIsValue ) + { + rThisRowInfo.pCellInfo[nRightX+1].nClipMark |= SC_CLIPMARK_RIGHT; + bAnyClipped = sal_True; + long nMarkPixel = (long)( SC_CLIPMARK_SIZE * nPPTX ); + rParam.maClipRect.Right() -= nMarkPixel * nLayoutSign; + } + if ( nLeftMissing > 0 && bMarkClipped && nLeftX >= nX1 && nLeftX <= nX2 && !bBreak && !bCellIsValue ) + { + rThisRowInfo.pCellInfo[nLeftX+1].nClipMark |= SC_CLIPMARK_LEFT; + bAnyClipped = sal_True; + long nMarkPixel = (long)( SC_CLIPMARK_SIZE * nPPTX ); + rParam.maClipRect.Left() += nMarkPixel * nLayoutSign; + } + + rParam.mbLeftClip = ( nLeftMissing > 0 ); + rParam.mbRightClip = ( nRightMissing > 0 ); + } + else + { + rParam.mbLeftClip = rParam.mbRightClip = sal_False; + + // leave space for AutoFilter on screen + // (for automatic line break: only if not formatting for printer, as in ScColumn::GetNeededSize) + + if ( eType==OUTTYPE_WINDOW && + ( static_cast<const ScMergeFlagAttr&>(rPattern.GetItem(ATTR_MERGE_FLAG)).GetValue() & SC_MF_AUTO ) && + ( !bBreak || pRefDevice == pFmtDevice ) ) + { + // filter drop-down width is now independent from row height + const long nFilter = DROPDOWN_BITMAP_SIZE; + sal_Bool bFit = ( nNeeded + nFilter <= nMergeSizeX ); + if ( bFit || bCellIsValue ) + { + // content fits even in the remaining area without the filter button + // -> align within that remaining area + + rParam.maAlignRect.Right() -= nFilter * nLayoutSign; + rParam.maClipRect.Right() -= nFilter * nLayoutSign; + + // if a number doesn't fit, don't hide part of the number behind the button + // -> set clip flags, so "###" replacement is used (but also within the smaller area) + + if ( !bFit ) + rParam.mbLeftClip = rParam.mbRightClip = sal_True; + } + } + } + + // justify both rectangles for alignment calculation, use with DrawText etc. + + rParam.maAlignRect.Justify(); + rParam.maClipRect.Justify(); + +#if 0 + //! Test !!! + pDev->Push(); + pDev->SetLineColor(); + pDev->SetFillColor( COL_LIGHTGREEN ); + pDev->DrawRect( pDev->PixelToLogic(rParam.maClipRect) ); + pDev->DrawRect( rParam.maClipRect ); // print preview + pDev->Pop(); + //! Test !!! +#endif +} + +void ScOutputData::DrawStrings( sal_Bool bPixelToLogic ) +{ + DBG_ASSERT( pDev == pRefDevice || + pDev->GetMapMode().GetMapUnit() == pRefDevice->GetMapMode().GetMapUnit(), + "DrawStrings: unterschiedliche MapUnits ?!?!" ); + + vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, pDev->GetExtOutDevData() ); + + sal_Bool bWasIdleDisabled = pDoc->IsIdleDisabled(); + pDoc->DisableIdle( sal_True ); + Size aMinSize = pRefDevice->PixelToLogic(Size(0,100)); // erst darueber wird ausgegeben +// sal_uInt32 nMinHeight = aMinSize.Height() / 200; // 1/2 Pixel + + ScDrawStringsVars aVars( this, bPixelToLogic ); + + sal_Bool bProgress = sal_False; + + long nInitPosX = nScrX; + if ( bLayoutRTL ) + nInitPosX += nMirrorW - 1; // pixels + long nLayoutSign = bLayoutRTL ? -1 : 1; + + SCCOL nLastContentCol = MAXCOL; + if ( nX2 < MAXCOL ) + nLastContentCol = sal::static_int_cast<SCCOL>( + nLastContentCol - pDoc->GetEmptyLinesInBlock( nX2+1, nY1, nTab, MAXCOL, nY2, nTab, DIR_RIGHT ) ); + SCCOL nLoopStartX = nX1; + if ( nX1 > 0 ) + --nLoopStartX; // start before nX1 for rest of long text to the left + + // variables for GetOutputArea + OutputAreaParam aAreaParam; + sal_Bool bCellIsValue = sal_False; + long nNeededWidth = 0; + SvxCellHorJustify eOutHorJust = SVX_HOR_JUSTIFY_STANDARD; + const ScPatternAttr* pPattern = NULL; + const SfxItemSet* pCondSet = NULL; + const ScPatternAttr* pOldPattern = NULL; + const SfxItemSet* pOldCondSet = NULL; + sal_uInt8 nOldScript = 0; + + // alternative pattern instances in case we need to modify the pattern + // before processing the cell value. + ::boost::ptr_vector<ScPatternAttr> aAltPatterns; + + long nPosY = nScrY; + for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++) + { + RowInfo* pThisRowInfo = &pRowInfo[nArrY]; + if ( pThisRowInfo->bChanged ) + { + SCROW nY = pThisRowInfo->nRowNo; +// long nCellHeight = (long) pThisRowInfo->nHeight; + long nPosX = nInitPosX; + if ( nLoopStartX < nX1 ) + nPosX -= pRowInfo[0].pCellInfo[nLoopStartX+1].nWidth * nLayoutSign; + for (SCCOL nX=nLoopStartX; nX<=nX2; nX++) + { + sal_Bool bMergeEmpty = sal_False; + CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1]; + sal_Bool bEmpty = nX < nX1 || pInfo->bEmptyCellText; + + SCCOL nCellX = nX; // position where the cell really starts + SCROW nCellY = nY; + sal_Bool bDoCell = sal_False; + sal_Bool bNeedEdit = sal_False; + + // + // Part of a merged cell? + // + + sal_Bool bOverlapped = ( pInfo->bHOverlapped || pInfo->bVOverlapped ); + if ( bOverlapped ) + { + bEmpty = sal_True; + + SCCOL nOverX; // start of the merged cells + SCROW nOverY; + sal_Bool bVisChanged = !pRowInfo[nArrY-1].bChanged; + if (GetMergeOrigin( nX,nY, nArrY, nOverX,nOverY, bVisChanged )) + { + nCellX = nOverX; + nCellY = nOverY; + bDoCell = sal_True; + } + else + bMergeEmpty = sal_True; + } + + // + // Rest of a long text further to the left? + // + + if ( bEmpty && !bMergeEmpty && nX < nX1 && !bOverlapped ) + { + SCCOL nTempX=nX1; + while (nTempX > 0 && IsEmptyCellText( pThisRowInfo, nTempX, nY )) + --nTempX; + + if ( nTempX < nX1 && + !IsEmptyCellText( pThisRowInfo, nTempX, nY ) && + !pDoc->HasAttrib( nTempX,nY,nTab, nX1,nY,nTab, HASATTR_MERGED | HASATTR_OVERLAPPED ) ) + { + nCellX = nTempX; + bDoCell = sal_True; + } + } + + // + // Rest of a long text further to the right? + // + + if ( bEmpty && !bMergeEmpty && nX == nX2 && !bOverlapped ) + { + // don't have to look further than nLastContentCol + + SCCOL nTempX=nX; + while (nTempX < nLastContentCol && IsEmptyCellText( pThisRowInfo, nTempX, nY )) + ++nTempX; + + if ( nTempX > nX && + !IsEmptyCellText( pThisRowInfo, nTempX, nY ) && + !pDoc->HasAttrib( nTempX,nY,nTab, nX,nY,nTab, HASATTR_MERGED | HASATTR_OVERLAPPED ) ) + { + nCellX = nTempX; + bDoCell = sal_True; + } + } + + // + // normal visible cell + // + + if (!bEmpty) + bDoCell = sal_True; + + // + // don't output the cell that's being edited + // + + if ( bDoCell && bEditMode && nCellX == nEditCol && nCellY == nEditRow ) + bDoCell = sal_False; + + // + // output the cell text + // + + ScBaseCell* pCell = NULL; + if (bDoCell) + { + if ( nCellY == nY && nCellX == nX && nCellX >= nX1 && nCellX <= nX2 ) + pCell = pThisRowInfo->pCellInfo[nCellX+1].pCell; + else + GetVisibleCell( nCellX, nCellY, nTab, pCell ); // get from document + if ( !pCell ) + bDoCell = sal_False; + else if ( pCell->GetCellType() == CELLTYPE_EDIT ) + bNeedEdit = sal_True; + } + if (bDoCell && !bNeedEdit) + { + if ( nCellY == nY && nCellX >= nX1 && nCellX <= nX2 ) + { + CellInfo& rCellInfo = pThisRowInfo->pCellInfo[nCellX+1]; + pPattern = rCellInfo.pPatternAttr; + pCondSet = rCellInfo.pConditionSet; + + if ( !pPattern ) + { + // #i68085# pattern from cell info for hidden columns is null, + // test for null is quicker than using column flags + pPattern = pDoc->GetPattern( nCellX, nCellY, nTab ); + pCondSet = pDoc->GetCondResult( nCellX, nCellY, nTab ); + } + } + else // get from document + { + pPattern = pDoc->GetPattern( nCellX, nCellY, nTab ); + pCondSet = pDoc->GetCondResult( nCellX, nCellY, nTab ); + } + + if (pCell->HasValueData() && + static_cast<const SfxBoolItem&>( + pPattern->GetItem(ATTR_LINEBREAK, pCondSet)).GetValue()) + { + // Disable line break when the cell content is numeric. + aAltPatterns.push_back(new ScPatternAttr(*pPattern)); + ScPatternAttr* pAltPattern = &aAltPatterns.back(); + SfxBoolItem aLineBreak(ATTR_LINEBREAK, false); + pAltPattern->GetItemSet().Put(aLineBreak); + pPattern = pAltPattern; + } + + sal_uInt8 nScript = GetScriptType( pDoc, pCell, pPattern, pCondSet ); + if (nScript == 0) nScript = ScGlobal::GetDefaultScriptType(); + if ( pPattern != pOldPattern || pCondSet != pOldCondSet || + nScript != nOldScript || bSyntaxMode ) + { + if ( StringDiffer(pOldPattern,pPattern) || + pCondSet != pOldCondSet || nScript != nOldScript || bSyntaxMode ) + aVars.SetPattern( pPattern, pCondSet, pCell, nScript ); + else + aVars.SetPatternSimple( pPattern, pCondSet ); + pOldPattern = pPattern; + pOldCondSet = pCondSet; + nOldScript = nScript; + } + + // use edit engine for rotated, stacked or mixed-script text + if ( aVars.GetOrient() == SVX_ORIENTATION_STACKED || + aVars.IsRotated() || IsAmbiguousScript(nScript) ) + bNeedEdit = sal_True; + } + if (bDoCell && !bNeedEdit) + { + sal_Bool bFormulaCell = (pCell->GetCellType() == CELLTYPE_FORMULA ); + if ( bFormulaCell ) + lcl_CreateInterpretProgress( bProgress, pDoc, (ScFormulaCell*)pCell ); + if ( aVars.SetText(pCell) ) + pOldPattern = NULL; + bNeedEdit = aVars.HasEditCharacters() || + (bFormulaCell && ((ScFormulaCell*)pCell)->IsMultilineResult()); + } + long nTotalMargin = 0; + if (bDoCell && !bNeedEdit) + { + CellType eCellType = pCell->GetCellType(); + bCellIsValue = ( eCellType == CELLTYPE_VALUE ); + if ( eCellType == CELLTYPE_FORMULA ) + { + ScFormulaCell* pFCell = (ScFormulaCell*)pCell; + bCellIsValue = pFCell->IsRunning() || pFCell->IsValue(); + } + + eOutHorJust = ( aVars.GetHorJust() != SVX_HOR_JUSTIFY_STANDARD ) ? + aVars.GetHorJust() : + ( bCellIsValue ? SVX_HOR_JUSTIFY_RIGHT : SVX_HOR_JUSTIFY_LEFT ); + + if ( eOutHorJust == SVX_HOR_JUSTIFY_BLOCK || eOutHorJust == SVX_HOR_JUSTIFY_REPEAT ) + eOutHorJust = SVX_HOR_JUSTIFY_LEFT; // repeat is not yet implemented + + sal_Bool bBreak = ( aVars.GetLineBreak() || aVars.GetHorJust() == SVX_HOR_JUSTIFY_BLOCK ); + sal_Bool bRepeat = aVars.IsRepeat() && !bBreak; + sal_Bool bShrink = aVars.IsShrink() && !bBreak && !bRepeat; + + nTotalMargin = + static_cast<long>(aVars.GetLeftTotal() * nPPTX) + + static_cast<long>(aVars.GetMargin()->GetRightMargin() * nPPTX); + + nNeededWidth = aVars.GetTextSize().Width() + nTotalMargin; + + // GetOutputArea gives justfied rectangles + GetOutputArea( nX, nArrY, nPosX, nPosY, nCellX, nCellY, nNeededWidth, + *pPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust), + bCellIsValue || bRepeat || bShrink, bBreak, sal_False, + aAreaParam ); + + if ( bShrink ) + { + if ( aVars.GetOrient() != SVX_ORIENTATION_STANDARD ) + { + // Only horizontal scaling is handled here. + // DrawEdit is used to vertically scale 90 deg rotated text. + bNeedEdit = sal_True; + } + else if ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip ) // horizontal + { + long nAvailable = aAreaParam.maAlignRect.GetWidth() - nTotalMargin; + long nScaleSize = aVars.GetTextSize().Width(); // without margin + + if ( nScaleSize > 0 ) // 0 if the text is empty (formulas, number formats) + { + long nScale = ( nAvailable * 100 ) / nScaleSize; + + aVars.SetShrinkScale( nScale, nOldScript ); + long nNewSize = aVars.GetTextSize().Width(); + + sal_uInt16 nShrinkAgain = 0; + while ( nNewSize > nAvailable && nShrinkAgain < SC_SHRINKAGAIN_MAX ) + { + // If the text is still too large, reduce the scale again by 10%, until it fits, + // at most 7 times (it's less than 50% of the calculated scale then). + + nScale = ( nScale * 9 ) / 10; + aVars.SetShrinkScale( nScale, nOldScript ); + nNewSize = aVars.GetTextSize().Width(); + ++nShrinkAgain; + } + // If even at half the size the font still isn't rendered smaller, + // fall back to normal clipping (showing ### for numbers). + if ( nNewSize <= nAvailable ) + aAreaParam.mbLeftClip = aAreaParam.mbRightClip = sal_False; + + pOldPattern = NULL; + } + } + } + + if ( bRepeat && !aAreaParam.mbLeftClip && !aAreaParam.mbRightClip ) + { + long nAvailable = aAreaParam.maAlignRect.GetWidth() - nTotalMargin; + long nRepeatSize = aVars.GetTextSize().Width(); // without margin + // When formatting for the printer, the text sizes don't always add up. + // Round down (too few repetitions) rather than exceeding the cell size then: + if ( pFmtDevice != pRefDevice ) + ++nRepeatSize; + if ( nRepeatSize > 0 ) + { + long nRepeatCount = nAvailable / nRepeatSize; + if ( nRepeatCount > 1 ) + { + String aCellStr = aVars.GetString(); + String aRepeated = aCellStr; + for ( long nRepeat = 1; nRepeat < nRepeatCount; nRepeat++ ) + aRepeated.Append( aCellStr ); + aVars.SetAutoText( aRepeated ); + } + } + } + + // use edit engine if automatic line breaks are needed + if ( bBreak ) + { + if ( aVars.GetOrient() == SVX_ORIENTATION_STANDARD ) + bNeedEdit = ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip ); + else + { + long nHeight = aVars.GetTextSize().Height() + + (long)(aVars.GetMargin()->GetTopMargin()*nPPTY) + + (long)(aVars.GetMargin()->GetBottomMargin()*nPPTY); + bNeedEdit = ( nHeight > aAreaParam.maClipRect.GetHeight() ); + } + } + } + if (bNeedEdit) + { + // mark the cell in CellInfo to be drawn in DrawEdit: + // Cells to the left are marked directly, cells to the + // right are handled by the flag for nX2 + SCCOL nMarkX = ( nCellX <= nX2 ) ? nCellX : nX2; + RowInfo* pMarkRowInfo = ( nCellY == nY ) ? pThisRowInfo : &pRowInfo[0]; + pMarkRowInfo->pCellInfo[nMarkX+1].bEditEngine = sal_True; + bDoCell = sal_False; // don't draw here + } + if ( bDoCell ) + { + if ( bCellIsValue && ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip ) ) + { + // Adjust the decimals to fit the available column width. + aVars.SetTextToWidthOrHash(pCell, aAreaParam.mnColWidth - nTotalMargin); + nNeededWidth = aVars.GetTextSize().Width() + + (long) ( aVars.GetLeftTotal() * nPPTX ) + + (long) ( aVars.GetMargin()->GetRightMargin() * nPPTX ); + if ( nNeededWidth <= aAreaParam.maClipRect.GetWidth() ) + aAreaParam.mbLeftClip = aAreaParam.mbRightClip = sal_False; + + // If the "###" replacement doesn't fit into the cells, no clip marks + // are shown, as the "###" already denotes too little space. + // The rectangles from the first GetOutputArea call remain valid. + } + + long nJustPosX = aAreaParam.maAlignRect.Left(); // "justified" - effect of alignment will be added + long nJustPosY = aAreaParam.maAlignRect.Top(); + long nAvailWidth = aAreaParam.maAlignRect.GetWidth(); + long nOutHeight = aAreaParam.maAlignRect.GetHeight(); + + sal_Bool bOutside = ( aAreaParam.maClipRect.Right() < nScrX || aAreaParam.maClipRect.Left() >= nScrX + nScrW ); + if ( aAreaParam.maClipRect.Left() < nScrX ) + { + aAreaParam.maClipRect.Left() = nScrX; + aAreaParam.mbLeftClip = sal_True; + } + if ( aAreaParam.maClipRect.Right() > nScrX + nScrW ) + { + aAreaParam.maClipRect.Right() = nScrX + nScrW; //! minus one? + aAreaParam.mbRightClip = sal_True; + } + + sal_Bool bHClip = aAreaParam.mbLeftClip || aAreaParam.mbRightClip; + sal_Bool bVClip = sal_False; + + if ( aAreaParam.maClipRect.Top() < nScrY ) + { + aAreaParam.maClipRect.Top() = nScrY; + bVClip = sal_True; + } + if ( aAreaParam.maClipRect.Bottom() > nScrY + nScrH ) + { + aAreaParam.maClipRect.Bottom() = nScrY + nScrH; //! minus one? + bVClip = sal_True; + } + + // + // horizontalen Platz testen + // + + sal_Bool bRightAdjusted = sal_False; // to correct text width calculation later + sal_Bool bNeedEditEngine = sal_False; + if ( !bNeedEditEngine && !bOutside ) + { + switch (eOutHorJust) + { + case SVX_HOR_JUSTIFY_LEFT: + nJustPosX += (long) ( aVars.GetLeftTotal() * nPPTX ); + break; + case SVX_HOR_JUSTIFY_RIGHT: + nJustPosX += nAvailWidth - aVars.GetTextSize().Width() - + (long) ( aVars.GetMargin()->GetRightMargin() * nPPTX ); + bRightAdjusted = sal_True; + break; + case SVX_HOR_JUSTIFY_CENTER: + nJustPosX += ( nAvailWidth - aVars.GetTextSize().Width() + + (long) ( aVars.GetLeftTotal() * nPPTX ) - + (long) ( aVars.GetMargin()->GetRightMargin() * nPPTX ) ) / 2; + break; + default: + { + // added to avoid warnings + } + } + + long nTestClipHeight = aVars.GetTextSize().Height(); + switch (aVars.GetVerJust()) + { + case SVX_VER_JUSTIFY_TOP: + { + long nTop = (long)( aVars.GetMargin()->GetTopMargin() * nPPTY ); + nJustPosY += nTop; + nTestClipHeight += nTop; + } + break; + case SVX_VER_JUSTIFY_BOTTOM: + { + long nBot = (long)( aVars.GetMargin()->GetBottomMargin() * nPPTY ); + nJustPosY += nOutHeight - aVars.GetTextSize().Height() - nBot; + nTestClipHeight += nBot; + } + break; + case SVX_VER_JUSTIFY_CENTER: + { + long nTop = (long)( aVars.GetMargin()->GetTopMargin() * nPPTY ); + long nBot = (long)( aVars.GetMargin()->GetBottomMargin() * nPPTY ); + nJustPosY += ( nOutHeight + nTop - + aVars.GetTextSize().Height() - nBot ) / 2; + nTestClipHeight += Abs( nTop - nBot ); + } + break; + default: + { + // added to avoid warnings + } + } + + if ( nTestClipHeight > nOutHeight ) + { + // kein vertikales Clipping beim Drucken von Zellen mit + // optimaler Hoehe, ausser bei Groesse in bedingter Formatierung + if ( eType != OUTTYPE_PRINTER || + ( pDoc->GetRowFlags( nCellY, nTab ) & CR_MANUALSIZE ) || + ( aVars.HasCondHeight() ) ) + bVClip = sal_True; + } + + if ( bHClip || bVClip ) + { + // nur die betroffene Dimension clippen, + // damit bei nicht-proportionalem Resize nicht alle + // rechtsbuendigen Zahlen abgeschnitten werden: + + if (!bHClip) + { + aAreaParam.maClipRect.Left() = nScrX; + aAreaParam.maClipRect.Right() = nScrX+nScrW; + } + if (!bVClip) + { + aAreaParam.maClipRect.Top() = nScrY; + aAreaParam.maClipRect.Bottom() = nScrY+nScrH; + } + + // aClipRect is not used after SetClipRegion/IntersectClipRegion, + // so it can be modified here + if (bPixelToLogic) + aAreaParam.maClipRect = pRefDevice->PixelToLogic( aAreaParam.maClipRect ); + + if (bMetaFile) + { + pDev->Push(); + pDev->IntersectClipRegion( aAreaParam.maClipRect ); + } + else + pDev->SetClipRegion( Region( aAreaParam.maClipRect ) ); + } + + Point aURLStart( nJustPosX, nJustPosY ); // copy before modifying for orientation + + switch (aVars.GetOrient()) + { + case SVX_ORIENTATION_STANDARD: + nJustPosY += aVars.GetAscent(); + break; + case SVX_ORIENTATION_TOPBOTTOM: + nJustPosX += aVars.GetTextSize().Width() - aVars.GetAscent(); + break; + case SVX_ORIENTATION_BOTTOMTOP: + nJustPosY += aVars.GetTextSize().Height(); + nJustPosX += aVars.GetAscent(); + break; + default: + { + // added to avoid warnings + } + } + + // When clipping, the visible part is now completely defined by the alignment, + // there's no more special handling to show the right part of RTL text. + + Point aDrawTextPos( nJustPosX, nJustPosY ); + if ( bPixelToLogic ) + { + // undo text width adjustment in pixels + if (bRightAdjusted) + aDrawTextPos.X() += aVars.GetTextSize().Width(); + + aDrawTextPos = pRefDevice->PixelToLogic( aDrawTextPos ); + + // redo text width adjustment in logic units + if (bRightAdjusted) + aDrawTextPos.X() -= aVars.GetOriginalWidth(); + } + + // in Metafiles immer DrawTextArray, damit die Positionen mit + // aufgezeichnet werden (fuer nicht-proportionales Resize): + + String aString = aVars.GetString(); + if (bMetaFile || pFmtDevice != pDev || aZoomX != aZoomY) + { + sal_Int32* pDX = new sal_Int32[aString.Len()]; + pFmtDevice->GetTextArray( aString, pDX ); + + if ( !pRefDevice->GetConnectMetaFile() || + pRefDevice->GetOutDevType() == OUTDEV_PRINTER ) + { + double fMul = GetStretch(); + xub_StrLen nLen = aString.Len(); + for (xub_StrLen i=0; i<nLen; i++) + pDX[i] = (long)(pDX[i] / fMul + 0.5); + } + + pDev->DrawTextArray( aDrawTextPos, aString, pDX ); + delete[] pDX; + } + else + pDev->DrawText( aDrawTextPos, aString ); + + if ( bHClip || bVClip ) + { + if (bMetaFile) + pDev->Pop(); + else + pDev->SetClipRegion(); + } + + // PDF: whole-cell hyperlink from formula? + sal_Bool bHasURL = pPDFData && pCell && pCell->GetCellType() == CELLTYPE_FORMULA && + static_cast<ScFormulaCell*>(pCell)->IsHyperLinkCell(); + if ( bHasURL ) + { + Rectangle aURLRect( aURLStart, aVars.GetTextSize() ); + lcl_DoHyperlinkResult( pDev, aURLRect, pCell ); + } + } + } + nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign; + } + } + nPosY += pRowInfo[nArrY].nHeight; + } + if ( bProgress ) + ScProgress::DeleteInterpretProgress(); + pDoc->DisableIdle( bWasIdleDisabled ); +} + +// ------------------------------------------------------------------------------- + +void lcl_ClearEdit( EditEngine& rEngine ) // Text und Attribute +{ + rEngine.SetUpdateMode( sal_False ); + + rEngine.SetText(EMPTY_STRING); + // keine Para-Attribute uebrigbehalten... + const SfxItemSet& rPara = rEngine.GetParaAttribs(0); + if (rPara.Count()) + rEngine.SetParaAttribs( 0, + SfxItemSet( *rPara.GetPool(), rPara.GetRanges() ) ); +} + +sal_Bool lcl_SafeIsValue( ScBaseCell* pCell ) +{ + if (!pCell) + return sal_False; + + sal_Bool bRet = sal_False; + switch ( pCell->GetCellType() ) + { + case CELLTYPE_VALUE: + bRet = sal_True; + break; + case CELLTYPE_FORMULA: + { + ScFormulaCell* pFCell = (ScFormulaCell*)pCell; + if ( pFCell->IsRunning() || pFCell->IsValue() ) + bRet = sal_True; + } + break; + default: + { + // added to avoid warnings + } + } + return bRet; +} + +void lcl_ScaleFonts( EditEngine& rEngine, long nPercent ) +{ + sal_Bool bUpdateMode = rEngine.GetUpdateMode(); + if ( bUpdateMode ) + rEngine.SetUpdateMode( sal_False ); + + sal_uInt16 nParCount = rEngine.GetParagraphCount(); + for (sal_uInt16 nPar=0; nPar<nParCount; nPar++) + { + SvUShorts aPortions; + rEngine.GetPortions( nPar, aPortions ); + + sal_uInt16 nPCount = aPortions.Count(); + sal_uInt16 nStart = 0; + for ( sal_uInt16 nPos=0; nPos<nPCount; nPos++ ) + { + sal_uInt16 nEnd = aPortions.GetObject( nPos ); + ESelection aSel( nPar, nStart, nPar, nEnd ); + SfxItemSet aAttribs = rEngine.GetAttribs( aSel ); + + long nWestern = static_cast<const SvxFontHeightItem&>(aAttribs.Get(EE_CHAR_FONTHEIGHT)).GetHeight(); + long nCJK = static_cast<const SvxFontHeightItem&>(aAttribs.Get(EE_CHAR_FONTHEIGHT_CJK)).GetHeight(); + long nCTL = static_cast<const SvxFontHeightItem&>(aAttribs.Get(EE_CHAR_FONTHEIGHT_CTL)).GetHeight(); + + nWestern = ( nWestern * nPercent ) / 100; + nCJK = ( nCJK * nPercent ) / 100; + nCTL = ( nCTL * nPercent ) / 100; + + aAttribs.Put( SvxFontHeightItem( nWestern, 100, EE_CHAR_FONTHEIGHT ) ); + aAttribs.Put( SvxFontHeightItem( nCJK, 100, EE_CHAR_FONTHEIGHT_CJK ) ); + aAttribs.Put( SvxFontHeightItem( nCTL, 100, EE_CHAR_FONTHEIGHT_CTL ) ); + + rEngine.QuickSetAttribs( aAttribs, aSel ); //! remove paragraph attributes from aAttribs? + + nStart = nEnd; + } + } + + if ( bUpdateMode ) + rEngine.SetUpdateMode( sal_True ); +} + +long lcl_GetEditSize( EditEngine& rEngine, sal_Bool bWidth, sal_Bool bSwap, long nAttrRotate ) +{ + if ( bSwap ) + bWidth = !bWidth; + + if ( nAttrRotate ) + { + long nRealWidth = (long) rEngine.CalcTextWidth(); + long nRealHeight = rEngine.GetTextHeight(); + + // assuming standard mode, otherwise width isn't used + + double nRealOrient = nAttrRotate * F_PI18000; // 1/100th degrees + double nAbsCos = fabs( cos( nRealOrient ) ); + double nAbsSin = fabs( sin( nRealOrient ) ); + if ( bWidth ) + return (long) ( nRealWidth * nAbsCos + nRealHeight * nAbsSin ); + else + return (long) ( nRealHeight * nAbsCos + nRealWidth * nAbsSin ); + } + else if ( bWidth ) + return (long) rEngine.CalcTextWidth(); + else + return rEngine.GetTextHeight(); +} + + +void ScOutputData::ShrinkEditEngine( EditEngine& rEngine, const Rectangle& rAlignRect, + long nLeftM, long nTopM, long nRightM, long nBottomM, + sal_Bool bWidth, sal_uInt16 nOrient, long nAttrRotate, sal_Bool bPixelToLogic, + long& rEngineWidth, long& rEngineHeight, long& rNeededPixel, bool& rLeftClip, bool& rRightClip ) +{ + if ( !bWidth ) + { + // vertical + + long nScaleSize = bPixelToLogic ? + pRefDevice->LogicToPixel(Size(0,rEngineHeight)).Height() : rEngineHeight; + + // Don't scale if it fits already. + // Allowing to extend into the margin, to avoid scaling at optimal height. + if ( nScaleSize <= rAlignRect.GetHeight() ) + return; + + sal_Bool bSwap = ( nOrient == SVX_ORIENTATION_TOPBOTTOM || nOrient == SVX_ORIENTATION_BOTTOMTOP ); + long nAvailable = rAlignRect.GetHeight() - nTopM - nBottomM; + long nScale = ( nAvailable * 100 ) / nScaleSize; + + lcl_ScaleFonts( rEngine, nScale ); + rEngineHeight = lcl_GetEditSize( rEngine, sal_False, bSwap, nAttrRotate ); + long nNewSize = bPixelToLogic ? + pRefDevice->LogicToPixel(Size(0,rEngineHeight)).Height() : rEngineHeight; + + sal_uInt16 nShrinkAgain = 0; + while ( nNewSize > nAvailable && nShrinkAgain < SC_SHRINKAGAIN_MAX ) + { + // further reduce, like in DrawStrings + lcl_ScaleFonts( rEngine, 90 ); // reduce by 10% + rEngineHeight = lcl_GetEditSize( rEngine, sal_False, bSwap, nAttrRotate ); + nNewSize = bPixelToLogic ? + pRefDevice->LogicToPixel(Size(0,rEngineHeight)).Height() : rEngineHeight; + ++nShrinkAgain; + } + + // sizes for further processing (alignment etc): + rEngineWidth = lcl_GetEditSize( rEngine, sal_True, bSwap, nAttrRotate ); + long nPixelWidth = bPixelToLogic ? + pRefDevice->LogicToPixel(Size(rEngineWidth,0)).Width() : rEngineWidth; + rNeededPixel = nPixelWidth + nLeftM + nRightM; + } + else if ( rLeftClip || rRightClip ) + { + // horizontal + + long nAvailable = rAlignRect.GetWidth() - nLeftM - nRightM; + long nScaleSize = rNeededPixel - nLeftM - nRightM; // without margin + + if ( nScaleSize <= nAvailable ) + return; + + long nScale = ( nAvailable * 100 ) / nScaleSize; + + lcl_ScaleFonts( rEngine, nScale ); + rEngineWidth = lcl_GetEditSize( rEngine, sal_True, sal_False, nAttrRotate ); + long nNewSize = bPixelToLogic ? + pRefDevice->LogicToPixel(Size(rEngineWidth,0)).Width() : rEngineWidth; + + sal_uInt16 nShrinkAgain = 0; + while ( nNewSize > nAvailable && nShrinkAgain < SC_SHRINKAGAIN_MAX ) + { + // further reduce, like in DrawStrings + lcl_ScaleFonts( rEngine, 90 ); // reduce by 10% + rEngineWidth = lcl_GetEditSize( rEngine, sal_True, sal_False, nAttrRotate ); + nNewSize = bPixelToLogic ? + pRefDevice->LogicToPixel(Size(rEngineWidth,0)).Width() : rEngineWidth; + ++nShrinkAgain; + } + if ( nNewSize <= nAvailable ) + rLeftClip = rRightClip = sal_False; + + // sizes for further processing (alignment etc): + rNeededPixel = nNewSize + nLeftM + nRightM; + rEngineHeight = lcl_GetEditSize( rEngine, sal_False, sal_False, nAttrRotate ); + } +} + +void ScOutputData::DrawEdit(sal_Bool bPixelToLogic) +{ + vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, pDev->GetExtOutDevData() ); + + Size aMinSize = pRefDevice->PixelToLogic(Size(0,100)); // erst darueber wird ausgegeben +// sal_uInt32 nMinHeight = aMinSize.Height() / 200; // 1/2 Pixel + + ScModule* pScMod = SC_MOD(); + sal_Int32 nConfBackColor = pScMod->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor; + // #105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed sal_True) + sal_Bool bCellContrast = bUseStyleColor && + Application::GetSettings().GetStyleSettings().GetHighContrastMode(); + + ScFieldEditEngine* pEngine = NULL; + sal_Bool bHyphenatorSet = sal_False; + const ScPatternAttr* pOldPattern = NULL; + const SfxItemSet* pOldCondSet = NULL; + ScBaseCell* pCell = NULL; + + Size aRefOne = pRefDevice->PixelToLogic(Size(1,1)); + + long nInitPosX = nScrX; + if ( bLayoutRTL ) + { +#if 0 + Size aOnePixel = pDev->PixelToLogic(Size(1,1)); + long nOneX = aOnePixel.Width(); + nInitPosX += nMirrorW - nOneX; +#endif + nInitPosX += nMirrorW - 1; + } + long nLayoutSign = bLayoutRTL ? -1 : 1; + + //! store nLastContentCol as member! + SCCOL nLastContentCol = MAXCOL; + if ( nX2 < MAXCOL ) + nLastContentCol = sal::static_int_cast<SCCOL>( + nLastContentCol - pDoc->GetEmptyLinesInBlock( nX2+1, nY1, nTab, MAXCOL, nY2, nTab, DIR_RIGHT ) ); + + long nRowPosY = nScrY; + for (SCSIZE nArrY=0; nArrY+1<nArrCount; nArrY++) // 0 fuer Reste von zusammengefassten + { + RowInfo* pThisRowInfo = &pRowInfo[nArrY]; +// long nCellHeight = (long) pThisRowInfo->nHeight; + if (nArrY==1) nRowPosY = nScrY; // vorher wird einzeln berechnet + + if ( pThisRowInfo->bChanged || nArrY==0 ) + { + long nPosX = 0; + for (SCCOL nX=0; nX<=nX2; nX++) // wegen Ueberhaengen + { + if (nX==nX1) nPosX = nInitPosX; // positions before nX1 are calculated individually + + CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1]; + if (pInfo->bEditEngine) + { + SCROW nY = pThisRowInfo->nRowNo; + + SCCOL nCellX = nX; // position where the cell really starts + SCROW nCellY = nY; + sal_Bool bDoCell = sal_False; + + long nPosY = nRowPosY; + if ( nArrY == 0 ) + { + nPosY = nScrY; + nY = pRowInfo[1].nRowNo; + SCCOL nOverX; // start of the merged cells + SCROW nOverY; + if (GetMergeOrigin( nX,nY, 1, nOverX,nOverY, sal_True )) + { + nCellX = nOverX; + nCellY = nOverY; + bDoCell = sal_True; + } + } + else if ( nX == nX2 && !pThisRowInfo->pCellInfo[nX+1].pCell ) + { + // Rest of a long text further to the right? + + SCCOL nTempX=nX; + while (nTempX < nLastContentCol && IsEmptyCellText( pThisRowInfo, nTempX, nY )) + ++nTempX; + + if ( nTempX > nX && + !IsEmptyCellText( pThisRowInfo, nTempX, nY ) && + !pDoc->HasAttrib( nTempX,nY,nTab, nX,nY,nTab, HASATTR_MERGED | HASATTR_OVERLAPPED ) ) + { + nCellX = nTempX; + bDoCell = sal_True; + } + } + else + { + bDoCell = sal_True; + } + + if ( bDoCell && bEditMode && nCellX == nEditCol && nCellY == nEditRow ) + bDoCell = sal_False; + + const ScPatternAttr* pPattern = NULL; + const SfxItemSet* pCondSet = NULL; + if (bDoCell) + { + if ( nCellY == nY && nCellX >= nX1 && nCellX <= nX2 && + !pDoc->ColHidden(nCellX, nTab) ) + { + CellInfo& rCellInfo = pThisRowInfo->pCellInfo[nCellX+1]; + pPattern = rCellInfo.pPatternAttr; + pCondSet = rCellInfo.pConditionSet; + pCell = rCellInfo.pCell; + } + else // get from document + { + pPattern = pDoc->GetPattern( nCellX, nCellY, nTab ); + pCondSet = pDoc->GetCondResult( nCellX, nCellY, nTab ); + GetVisibleCell( nCellX, nCellY, nTab, pCell ); + } + if ( !pCell ) + bDoCell = sal_False; + } + if (bDoCell) + { + sal_Bool bHidden = sal_False; + + // + // Create EditEngine + // + + if (!pEngine) + { + // Ein RefDevice muss auf jeden Fall gesetzt werden, + // sonst legt sich die EditEngine ein VirtualDevice an! + pEngine = new ScFieldEditEngine( pDoc->GetEnginePool() ); + pEngine->SetUpdateMode( sal_False ); + pEngine->SetRefDevice( pFmtDevice ); // always set + sal_uLong nCtrl = pEngine->GetControlWord(); + if ( bShowSpellErrors ) + nCtrl |= EE_CNTRL_ONLINESPELLING; + if ( eType == OUTTYPE_PRINTER ) + nCtrl &= ~EE_CNTRL_MARKFIELDS; + pEngine->SetControlWord( nCtrl ); + pEngine->SetForbiddenCharsTable( pDoc->GetForbiddenCharacters() ); + pEngine->SetAsianCompressionMode( pDoc->GetAsianCompression() ); + pEngine->SetKernAsianPunctuation( pDoc->GetAsianKerning() ); + pEngine->EnableAutoColor( bUseStyleColor ); + pEngine->SetDefaultHorizontalTextDirection( + (EEHorizontalTextDirection)pDoc->GetEditTextDirection( nTab ) ); + } + else + lcl_ClearEdit( *pEngine ); // also calls SetUpdateMode(sal_False) + + + sal_Bool bCellIsValue = lcl_SafeIsValue(pCell); + + SvxCellHorJustify eHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem&) + pPattern->GetItem(ATTR_HOR_JUSTIFY, pCondSet)).GetValue(); + sal_Bool bBreak = ( eHorJust == SVX_HOR_JUSTIFY_BLOCK ) || + ((const SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK, pCondSet)).GetValue(); + sal_Bool bRepeat = ( eHorJust == SVX_HOR_JUSTIFY_REPEAT && !bBreak ); + sal_Bool bShrink = !bBreak && !bRepeat && static_cast<const SfxBoolItem&> + (pPattern->GetItem( ATTR_SHRINKTOFIT, pCondSet )).GetValue(); + SvxCellOrientation eOrient = pPattern->GetCellOrientation( pCondSet ); + long nAttrRotate = ((const SfxInt32Item&)pPattern-> + GetItem(ATTR_ROTATE_VALUE, pCondSet)).GetValue(); + if ( eHorJust == SVX_HOR_JUSTIFY_REPEAT ) + { + // ignore orientation/rotation if "repeat" is active + eOrient = SVX_ORIENTATION_STANDARD; + nAttrRotate = 0; + + // #i31843# "repeat" with "line breaks" is treated as default alignment + // (but rotation is still disabled) + if ( bBreak ) + eHorJust = SVX_HOR_JUSTIFY_STANDARD; + } + if ( eOrient==SVX_ORIENTATION_STANDARD && nAttrRotate ) + { + //! Flag setzen, um die Zelle in DrawRotated wiederzufinden ? + //! (oder Flag schon bei DrawBackground, dann hier keine Abfrage) + bHidden = sal_True; // gedreht wird getrennt ausgegeben + } + + sal_Bool bAsianVertical = ( eOrient == SVX_ORIENTATION_STACKED && + ((const SfxBoolItem&)pPattern->GetItem( ATTR_VERTICAL_ASIAN, pCondSet )).GetValue() ); + if ( bAsianVertical ) + { + // in asian mode, use EditEngine::SetVertical instead of EE_CNTRL_ONECHARPERLINE + eOrient = SVX_ORIENTATION_STANDARD; + // default alignment for asian vertical mode is top-right + if ( eHorJust == SVX_HOR_JUSTIFY_STANDARD ) + eHorJust = SVX_HOR_JUSTIFY_RIGHT; + } + + + + SvxCellHorJustify eOutHorJust = + ( eHorJust != SVX_HOR_JUSTIFY_STANDARD ) ? eHorJust : + ( bCellIsValue ? SVX_HOR_JUSTIFY_RIGHT : SVX_HOR_JUSTIFY_LEFT ); + + if ( eOutHorJust == SVX_HOR_JUSTIFY_BLOCK || eOutHorJust == SVX_HOR_JUSTIFY_REPEAT ) + eOutHorJust = SVX_HOR_JUSTIFY_LEFT; // repeat is not yet implemented + + +//! if ( !bHidden && eType == OUTTYPE_PRINTER && +//! pDev->GetOutDevType() == OUTDEV_WINDOW && +//! ((const SvxFontHeightItem&)pPattern-> +//! GetItem(ATTR_FONT_HEIGHT)).GetHeight() <= nMinHeight ) +//! { +//! Point aPos( nStartX, nStartY ); +//! pDev->DrawPixel( aPos, +//! ((const SvxColorItem&)pPattern-> +//! GetItem( ATTR_FONT_COLOR )).GetValue() ); +//! bHidden = sal_True; +//! } + + if (!bHidden) + { + //! mirror margin values for RTL? + //! move margin down to after final GetOutputArea call + + const SvxMarginItem* pMargin = (const SvxMarginItem*) + &pPattern->GetItem(ATTR_MARGIN, pCondSet); + sal_uInt16 nIndent = 0; + if ( eHorJust == SVX_HOR_JUSTIFY_LEFT ) + nIndent = ((const SfxUInt16Item&)pPattern-> + GetItem(ATTR_INDENT, pCondSet)).GetValue(); + + long nLeftM = (long) ( (pMargin->GetLeftMargin() + nIndent) * nPPTX ); + long nTopM = (long) ( pMargin->GetTopMargin() * nPPTY ); + long nRightM = (long) ( pMargin->GetRightMargin() * nPPTX ); + long nBottomM = (long) ( pMargin->GetBottomMargin() * nPPTY ); + + SCCOL nXForPos = nX; + if ( nXForPos < nX1 ) + { + nXForPos = nX1; + nPosX = nInitPosX; + } + SCSIZE nArrYForPos = nArrY; + if ( nArrYForPos < 1 ) + { + nArrYForPos = 1; + nPosY = nScrY; + } + + OutputAreaParam aAreaParam; + + // + // Initial page size - large for normal text, cell size for automatic line breaks + // + + Size aPaperSize = Size( 1000000, 1000000 ); + if ( bBreak || eOrient == SVX_ORIENTATION_STACKED || bAsianVertical ) + { + //! also stacked, AsianVertical + + // call GetOutputArea with nNeeded=0, to get only the cell width + + //! handle nArrY == 0 + GetOutputArea( nXForPos, nArrYForPos, nPosX, nPosY, nCellX, nCellY, 0, + *pPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust), + bCellIsValue, true, false, aAreaParam ); + + //! special ScEditUtil handling if formatting for printer + + if ( eOrient == SVX_ORIENTATION_TOPBOTTOM || eOrient == SVX_ORIENTATION_BOTTOMTOP ) + aPaperSize.Width() = aAreaParam.maAlignRect.GetHeight() - nTopM - nBottomM; + else + aPaperSize.Width() = aAreaParam.maAlignRect.GetWidth() - nLeftM - nRightM; + + if (bAsianVertical && bBreak) + { + // add some extra height (default margin value) for safety + // as long as GetEditArea isn't used below + long nExtraHeight = (long)( 20 * nPPTY ); + aPaperSize.Height() = aAreaParam.maAlignRect.GetHeight() - nTopM - nBottomM + nExtraHeight; + } + } + if (bPixelToLogic) + { + Size aLogicSize = pRefDevice->PixelToLogic(aPaperSize); + if ( bBreak && !bAsianVertical && pRefDevice != pFmtDevice ) + { + // #i85342# screen display and formatting for printer, + // use same GetEditArea call as in ScViewData::SetEditEngine + + Fraction aFract(1,1); + Rectangle aUtilRect = ScEditUtil( pDoc, nCellX, nCellY, nTab, Point(0,0), pFmtDevice, + HMM_PER_TWIPS, HMM_PER_TWIPS, aFract, aFract ).GetEditArea( pPattern, sal_False ); + aLogicSize.Width() = aUtilRect.GetWidth(); + } + pEngine->SetPaperSize(aLogicSize); + } + else + pEngine->SetPaperSize(aPaperSize); + + // + // Fill the EditEngine (cell attributes and text) + // + + SvxCellVerJustify eVerJust = (SvxCellVerJustify)((const SvxVerJustifyItem&) + pPattern->GetItem(ATTR_VER_JUSTIFY, pCondSet)).GetValue(); + + // default alignment for asian vertical mode is top-right + if ( bAsianVertical && eVerJust == SVX_VER_JUSTIFY_STANDARD ) + eVerJust = SVX_VER_JUSTIFY_TOP; + + // syntax highlighting mode is ignored here + // StringDiffer doesn't look at hyphenate, language items + if ( pPattern != pOldPattern || pCondSet != pOldCondSet ) + { + SfxItemSet* pSet = new SfxItemSet( pEngine->GetEmptyItemSet() ); + pPattern->FillEditItemSet( pSet, pCondSet ); + + pEngine->SetDefaults( pSet ); + pOldPattern = pPattern; + pOldCondSet = pCondSet; + + sal_uLong nControl = pEngine->GetControlWord(); + if (eOrient==SVX_ORIENTATION_STACKED) + nControl |= EE_CNTRL_ONECHARPERLINE; + else + nControl &= ~EE_CNTRL_ONECHARPERLINE; + pEngine->SetControlWord( nControl ); + + if ( !bHyphenatorSet && ((const SfxBoolItem&)pSet->Get(EE_PARA_HYPHENATE)).GetValue() ) + { + // set hyphenator the first time it is needed + com::sun::star::uno::Reference<com::sun::star::linguistic2::XHyphenator> xXHyphenator( LinguMgr::GetHyphenator() ); + pEngine->SetHyphenator( xXHyphenator ); + bHyphenatorSet = sal_True; + } + + Color aBackCol = ((const SvxBrushItem&) + pPattern->GetItem( ATTR_BACKGROUND, pCondSet )).GetColor(); + if ( bUseStyleColor && ( aBackCol.GetTransparency() > 0 || bCellContrast ) ) + aBackCol.SetColor( nConfBackColor ); + pEngine->SetBackgroundColor( aBackCol ); + } + + // horizontal alignment now may depend on cell content + // (for values with number formats with mixed script types) + // -> always set adjustment + + SvxAdjust eSvxAdjust = SVX_ADJUST_LEFT; + if (eOrient==SVX_ORIENTATION_STACKED) + eSvxAdjust = SVX_ADJUST_CENTER; + else if (bBreak) + { + if (eOrient==SVX_ORIENTATION_STANDARD && !bAsianVertical) + switch (eHorJust) + { + case SVX_HOR_JUSTIFY_STANDARD: + eSvxAdjust = bCellIsValue ? SVX_ADJUST_RIGHT : SVX_ADJUST_LEFT; + break; + case SVX_HOR_JUSTIFY_LEFT: + case SVX_HOR_JUSTIFY_REPEAT: // nicht implementiert + eSvxAdjust = SVX_ADJUST_LEFT; + break; + case SVX_HOR_JUSTIFY_RIGHT: + eSvxAdjust = SVX_ADJUST_RIGHT; + break; + case SVX_HOR_JUSTIFY_CENTER: + eSvxAdjust = SVX_ADJUST_CENTER; + break; + case SVX_HOR_JUSTIFY_BLOCK: + eSvxAdjust = SVX_ADJUST_BLOCK; + break; + } + else + switch (eVerJust) + { + case SVX_VER_JUSTIFY_TOP: + eSvxAdjust = (eOrient==SVX_ORIENTATION_TOPBOTTOM || bAsianVertical) ? + SVX_ADJUST_LEFT : SVX_ADJUST_RIGHT; + break; + case SVX_VER_JUSTIFY_CENTER: + eSvxAdjust = SVX_ADJUST_CENTER; + break; + case SVX_VER_JUSTIFY_BOTTOM: + case SVX_HOR_JUSTIFY_STANDARD: + eSvxAdjust = (eOrient==SVX_ORIENTATION_TOPBOTTOM || bAsianVertical) ? + SVX_ADJUST_RIGHT : SVX_ADJUST_LEFT; + break; + } + } + pEngine->SetDefaultItem( SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) ); + + // Read content from cell + + sal_Bool bWrapFields = sal_False; + if (pCell) + { + if (pCell->GetCellType() == CELLTYPE_EDIT) + { + const EditTextObject* pData; + ((ScEditCell*)pCell)->GetData(pData); + + if (pData) + { + pEngine->SetText(*pData); + + if ( bBreak && !bAsianVertical && pData->HasField() ) + { + // Fields aren't wrapped, so clipping is enabled to prevent + // a field from being drawn beyond the cell size + + bWrapFields = sal_True; + } + } + else + { + DBG_ERROR("pData == 0"); + } + } + else + { + sal_uLong nFormat = pPattern->GetNumberFormat( + pDoc->GetFormatTable(), pCondSet ); + String aString; + Color* pColor; + ScCellFormat::GetString( pCell, + nFormat,aString, &pColor, + *pDoc->GetFormatTable(), + bShowNullValues, + bShowFormulas, + ftCheck ); + + pEngine->SetText(aString); + if ( pColor && !bSyntaxMode && !( bUseStyleColor && bForceAutoColor ) ) + lcl_SetEditColor( *pEngine, *pColor ); + } + + if ( bSyntaxMode ) + SetEditSyntaxColor( *pEngine, pCell ); + else if ( bUseStyleColor && bForceAutoColor ) + lcl_SetEditColor( *pEngine, COL_AUTO ); //! or have a flag at EditEngine + } + else + { + DBG_ERROR("pCell == NULL"); + } + + pEngine->SetVertical( bAsianVertical ); + pEngine->SetUpdateMode( sal_True ); // after SetText, before CalcTextWidth/GetTextHeight + + // + // Get final output area using the calculated width + // + + long nEngineWidth; + if ( bBreak && eOrient != SVX_ORIENTATION_STACKED && !bAsianVertical ) + nEngineWidth = 0; + else + nEngineWidth = (long) pEngine->CalcTextWidth(); + long nEngineHeight = pEngine->GetTextHeight(); + + if (eOrient != SVX_ORIENTATION_STANDARD && + eOrient != SVX_ORIENTATION_STACKED) + { + long nTemp = nEngineWidth; + nEngineWidth = nEngineHeight; + nEngineHeight = nTemp; + } + + if (eOrient == SVX_ORIENTATION_STACKED) + nEngineWidth = nEngineWidth * 11 / 10; + + long nNeededPixel = nEngineWidth; + if (bPixelToLogic) + nNeededPixel = pRefDevice->LogicToPixel(Size(nNeededPixel,0)).Width(); + nNeededPixel += nLeftM + nRightM; + + if ( ( !bBreak && eOrient != SVX_ORIENTATION_STACKED ) || bAsianVertical || bShrink ) + { + // for break, the first GetOutputArea call is sufficient + GetOutputArea( nXForPos, nArrYForPos, nPosX, nPosY, nCellX, nCellY, nNeededPixel, + *pPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust), + bCellIsValue || bRepeat || bShrink, false, false, aAreaParam ); + + if ( bShrink ) + { + sal_Bool bWidth = ( eOrient == SVX_ORIENTATION_STANDARD && !bAsianVertical ); + ShrinkEditEngine( *pEngine, aAreaParam.maAlignRect, + nLeftM, nTopM, nRightM, nBottomM, bWidth, + sal::static_int_cast<sal_uInt16>(eOrient), 0, bPixelToLogic, + nEngineWidth, nEngineHeight, nNeededPixel, + aAreaParam.mbLeftClip, aAreaParam.mbRightClip ); + } + + if ( bRepeat && !aAreaParam.mbLeftClip && !aAreaParam.mbRightClip && pEngine->GetParagraphCount() == 1 ) + { + // First check if twice the space for the formatted text is available + // (otherwise just keep it unchanged). + + long nFormatted = nNeededPixel - nLeftM - nRightM; // without margin + long nAvailable = aAreaParam.maAlignRect.GetWidth() - nLeftM - nRightM; + if ( nAvailable >= 2 * nFormatted ) + { + // "repeat" is handled with unformatted text (for performance reasons) + String aCellStr = pEngine->GetText(); + pEngine->SetText( aCellStr ); + + long nRepeatSize = (long) pEngine->CalcTextWidth(); + if (bPixelToLogic) + nRepeatSize = pRefDevice->LogicToPixel(Size(nRepeatSize,0)).Width(); + if ( pFmtDevice != pRefDevice ) + ++nRepeatSize; + if ( nRepeatSize > 0 ) + { + long nRepeatCount = nAvailable / nRepeatSize; + if ( nRepeatCount > 1 ) + { + String aRepeated = aCellStr; + for ( long nRepeat = 1; nRepeat < nRepeatCount; nRepeat++ ) + aRepeated.Append( aCellStr ); + pEngine->SetText( aRepeated ); + + nEngineHeight = pEngine->GetTextHeight(); + nEngineWidth = (long) pEngine->CalcTextWidth(); + if (bPixelToLogic) + nNeededPixel = pRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width(); + else + nNeededPixel = nEngineWidth; + nNeededPixel += nLeftM + nRightM; + } + } + } + } + + if ( bCellIsValue && ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip ) ) + { + pEngine->SetText( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("###")) ); + nEngineWidth = (long) pEngine->CalcTextWidth(); + if (bPixelToLogic) + nNeededPixel = pRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width(); + else + nNeededPixel = nEngineWidth; + nNeededPixel += nLeftM + nRightM; + + // No clip marks if "###" doesn't fit (same as in DrawStrings) + } + + if ( eOutHorJust != SVX_HOR_JUSTIFY_LEFT && eOrient == SVX_ORIENTATION_STANDARD ) + { + aPaperSize.Width() = nNeededPixel + 1; + if (bPixelToLogic) + pEngine->SetPaperSize(pRefDevice->PixelToLogic(aPaperSize)); + else + pEngine->SetPaperSize(aPaperSize); + } + } + + long nStartX = aAreaParam.maAlignRect.Left(); + long nStartY = aAreaParam.maAlignRect.Top(); + long nCellWidth = aAreaParam.maAlignRect.GetWidth(); + long nOutWidth = nCellWidth - 1 - nLeftM - nRightM; + long nOutHeight = aAreaParam.maAlignRect.GetHeight() - nTopM - nBottomM; + + if ( bBreak || eOrient != SVX_ORIENTATION_STANDARD || bAsianVertical ) + { + // text with automatic breaks is aligned only within the + // edit engine's paper size, the output of the whole area + // is always left-aligned + + nStartX += nLeftM; + } + else + { + if ( eOutHorJust == SVX_HOR_JUSTIFY_RIGHT ) + nStartX -= nNeededPixel - nCellWidth + nRightM + 1; + else if ( eOutHorJust == SVX_HOR_JUSTIFY_CENTER ) + nStartX -= ( nNeededPixel - nCellWidth + nRightM + 1 - nLeftM ) / 2; + else + nStartX += nLeftM; + } + + sal_Bool bOutside = ( aAreaParam.maClipRect.Right() < nScrX || aAreaParam.maClipRect.Left() >= nScrX + nScrW ); + if ( aAreaParam.maClipRect.Left() < nScrX ) + { + aAreaParam.maClipRect.Left() = nScrX; + aAreaParam.mbLeftClip = true; + } + if ( aAreaParam.maClipRect.Right() > nScrX + nScrW ) + { + aAreaParam.maClipRect.Right() = nScrX + nScrW; //! minus one? + aAreaParam.mbRightClip = true; + } + + if ( !bHidden && !bOutside ) + { + bool bClip = aAreaParam.mbLeftClip || aAreaParam.mbRightClip; + sal_Bool bSimClip = sal_False; + + if ( bWrapFields ) + { + // Fields in a cell with automatic breaks: clip to cell width + bClip = sal_True; + } + + if ( aAreaParam.maClipRect.Top() < nScrY ) + { + aAreaParam.maClipRect.Top() = nScrY; + bClip = sal_True; + } + if ( aAreaParam.maClipRect.Bottom() > nScrY + nScrH ) + { + aAreaParam.maClipRect.Bottom() = nScrY + nScrH; //! minus one? + bClip = sal_True; + } + + Size aCellSize; // output area, excluding margins, in logical units + if (bPixelToLogic) + aCellSize = pRefDevice->PixelToLogic( Size( nOutWidth, nOutHeight ) ); + else + aCellSize = Size( nOutWidth, nOutHeight ); + + if ( nEngineHeight >= aCellSize.Height() + aRefOne.Height() ) + { + const ScMergeAttr* pMerge = + (ScMergeAttr*)&pPattern->GetItem(ATTR_MERGE); + sal_Bool bMerged = pMerge->GetColMerge() > 1 || pMerge->GetRowMerge() > 1; + + // Don't clip for text height when printing rows with optimal height, + // except when font size is from conditional formatting. + //! Allow clipping when vertically merged? + if ( eType != OUTTYPE_PRINTER || + ( pDoc->GetRowFlags( nCellY, nTab ) & CR_MANUALSIZE ) || + ( pCondSet && SFX_ITEM_SET == + pCondSet->GetItemState(ATTR_FONT_HEIGHT, sal_True) ) ) + bClip = sal_True; + else + bSimClip = sal_True; + + // Show clip marks if height is at least 5pt too small and + // there are several lines of text. + // Not for asian vertical text, because that would interfere + // with the default right position of the text. + // Only with automatic line breaks, to avoid having to find + // the cells with the horizontal end of the text again. + if ( nEngineHeight - aCellSize.Height() > 100 && + ( bBreak || eOrient == SVX_ORIENTATION_STACKED ) && + !bAsianVertical && bMarkClipped && + ( pEngine->GetParagraphCount() > 1 || pEngine->GetLineCount(0) > 1 ) ) + { + CellInfo* pClipMarkCell = NULL; + if ( bMerged ) + { + // anywhere in the merged area... + SCCOL nClipX = ( nX < nX1 ) ? nX1 : nX; + pClipMarkCell = &pRowInfo[(nArrY != 0) ? nArrY : 1].pCellInfo[nClipX+1]; + } + else + pClipMarkCell = &pThisRowInfo->pCellInfo[nX+1]; + + pClipMarkCell->nClipMark |= SC_CLIPMARK_RIGHT; //! also allow left? + bAnyClipped = sal_True; + + long nMarkPixel = (long)( SC_CLIPMARK_SIZE * nPPTX ); + if ( aAreaParam.maClipRect.Right() - nMarkPixel > aAreaParam.maClipRect.Left() ) + aAreaParam.maClipRect.Right() -= nMarkPixel; + } + } + +#if 0 + long nClipStartY = nStartY; + if (nArrY==0 || bVisChanged) + { + if ( nClipStartY < nRowPosY ) + { + long nDif = nRowPosY - nClipStartY; + bClip = sal_True; + nClipStartY = nRowPosY; + aClipSize.Height() -= nDif; + } + } +#endif + + Rectangle aLogicClip; + if (bClip || bSimClip) + { + // Clip marks are already handled in GetOutputArea + + if (bPixelToLogic) + aLogicClip = pRefDevice->PixelToLogic( aAreaParam.maClipRect ); + else + aLogicClip = aAreaParam.maClipRect; + + if (bClip) // bei bSimClip nur aClipRect initialisieren + { + if (bMetaFile) + { + pDev->Push(); + pDev->IntersectClipRegion( aLogicClip ); + } + else + pDev->SetClipRegion( Region( aLogicClip ) ); + } + } + + Point aLogicStart; + if (bPixelToLogic) + aLogicStart = pRefDevice->PixelToLogic( Point(nStartX,nStartY) ); + else + aLogicStart = Point(nStartX, nStartY); + if ( eOrient!=SVX_ORIENTATION_STANDARD || bAsianVertical || !bBreak ) + { + long nAvailWidth = aCellSize.Width(); + // space for AutoFilter is already handled in GetOutputArea + + // horizontal alignment + + if (eOrient==SVX_ORIENTATION_STANDARD && !bAsianVertical) + { + if (eHorJust==SVX_HOR_JUSTIFY_RIGHT || + eHorJust==SVX_HOR_JUSTIFY_CENTER || + (eHorJust==SVX_HOR_JUSTIFY_STANDARD && bCellIsValue) ) + { + pEngine->SetUpdateMode( sal_False ); + + SvxAdjust eEditAdjust = + (eHorJust==SVX_HOR_JUSTIFY_CENTER) ? + SVX_ADJUST_CENTER : SVX_ADJUST_RIGHT; + pEngine->SetDefaultItem( + SvxAdjustItem( eEditAdjust, EE_PARA_JUST ) ); + + // #55142# reset adjustment for the next cell + pOldPattern = NULL; + + pEngine->SetUpdateMode( sal_True ); + } + } + else + { + if (eHorJust==SVX_HOR_JUSTIFY_RIGHT) + aLogicStart.X() += nAvailWidth - nEngineWidth; + else if (eHorJust==SVX_HOR_JUSTIFY_CENTER) + aLogicStart.X() += (nAvailWidth - nEngineWidth) / 2; + } + } + + if ( bAsianVertical ) + { + // paper size is subtracted below + aLogicStart.X() += nEngineWidth; + } + + if ( ( bAsianVertical || eOrient == SVX_ORIENTATION_TOPBOTTOM || + eOrient == SVX_ORIENTATION_BOTTOMTOP ) && bBreak ) + { + // vertical adjustment is within the EditEngine + if (bPixelToLogic) + aLogicStart.Y() += pRefDevice->PixelToLogic(Size(0,nTopM)).Height(); + else + aLogicStart.Y() += nTopM; + } + + if ( ( eOrient==SVX_ORIENTATION_STANDARD && !bAsianVertical ) || + eOrient==SVX_ORIENTATION_STACKED || !bBreak ) + { + if (eVerJust==SVX_VER_JUSTIFY_BOTTOM || + eVerJust==SVX_VER_JUSTIFY_STANDARD) + { + //! if pRefDevice != pFmtDevice, keep heights in logic units, + //! only converting margin? + + if (bPixelToLogic) + aLogicStart.Y() += pRefDevice->PixelToLogic( Size(0, nTopM + + pRefDevice->LogicToPixel(aCellSize).Height() - + pRefDevice->LogicToPixel(Size(0,nEngineHeight)).Height() + )).Height(); + else + aLogicStart.Y() += nTopM + aCellSize.Height() - nEngineHeight; + } + else if (eVerJust==SVX_VER_JUSTIFY_CENTER) + { + if (bPixelToLogic) + aLogicStart.Y() += pRefDevice->PixelToLogic( Size(0, nTopM + ( + pRefDevice->LogicToPixel(aCellSize).Height() - + pRefDevice->LogicToPixel(Size(0,nEngineHeight)).Height() ) + / 2)).Height(); + else + aLogicStart.Y() += nTopM + (aCellSize.Height() - nEngineHeight) / 2; + } + else // top + { + if (bPixelToLogic) + aLogicStart.Y() += pRefDevice->PixelToLogic(Size(0,nTopM)).Height(); + else + aLogicStart.Y() += nTopM; + } + } + + Point aURLStart = aLogicStart; // copy before modifying for orientation + + short nOriVal = 0; + if (eOrient==SVX_ORIENTATION_TOPBOTTOM) + { + // nOriVal = -900; + nOriVal = 2700; + aLogicStart.X() += nEngineWidth; + } + else if (eOrient==SVX_ORIENTATION_BOTTOMTOP) + { + nOriVal = 900; + aLogicStart.Y() += bBreak ? pEngine->GetPaperSize().Width() : + nEngineHeight; + } + else if (eOrient==SVX_ORIENTATION_STACKED) + { + Size aPaperLogic = pEngine->GetPaperSize(); + aPaperLogic.Width() = nEngineWidth; + pEngine->SetPaperSize(aPaperLogic); + } + + if ( pEngine->IsRightToLeft( 0 ) ) + { + // For right-to-left, EditEngine always calculates its lines + // beginning from the right edge, but EditLine::nStartPosX is + // of sal_uInt16 type, so the PaperSize must be limited to USHRT_MAX. + Size aLogicPaper = pEngine->GetPaperSize(); + if ( aLogicPaper.Width() > USHRT_MAX ) + { + aLogicPaper.Width() = USHRT_MAX; + pEngine->SetPaperSize(aLogicPaper); + } + } + + // bMoveClipped handling has been replaced by complete alignment + // handling (also extending to the left). + + if ( bSimClip && !nOriVal && !bAsianVertical ) + { + // kein hartes Clipping, aber nur die betroffenen + // Zeilen ausgeben + + Point aDocStart = aLogicClip.TopLeft(); + aDocStart -= aLogicStart; + pEngine->Draw( pDev, aLogicClip, aDocStart, sal_False ); + } + else + { + if (bAsianVertical) + { + // with SetVertical, the start position is top left of + // the whole output area, not the text itself + aLogicStart.X() -= pEngine->GetPaperSize().Width(); + } + pEngine->Draw( pDev, aLogicStart, nOriVal ); + } + + if (bClip) + { + if (bMetaFile) + pDev->Pop(); + else + pDev->SetClipRegion(); + } + + // PDF: whole-cell hyperlink from formula? + sal_Bool bHasURL = pPDFData && pCell && pCell->GetCellType() == CELLTYPE_FORMULA && + static_cast<ScFormulaCell*>(pCell)->IsHyperLinkCell(); + if ( bHasURL ) + { + long nURLWidth = (long) pEngine->CalcTextWidth(); + long nURLHeight = pEngine->GetTextHeight(); + if ( bBreak ) + { + Size aPaper = pEngine->GetPaperSize(); + if ( bAsianVertical ) + nURLHeight = aPaper.Height(); + else + nURLWidth = aPaper.Width(); + } + if ( eOrient == SVX_ORIENTATION_TOPBOTTOM || eOrient == SVX_ORIENTATION_BOTTOMTOP ) + std::swap( nURLWidth, nURLHeight ); + else if ( bAsianVertical ) + aURLStart.X() -= nURLWidth; + + Rectangle aURLRect( aURLStart, Size( nURLWidth, nURLHeight ) ); + lcl_DoHyperlinkResult( pDev, aURLRect, pCell ); + } + } + } + } + } + nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign; + } + } + nRowPosY += pRowInfo[nArrY].nHeight; + } + + delete pEngine; + + if (bAnyRotated) + DrawRotated(bPixelToLogic); //! von aussen rufen ? +} + +// ------------------------------------------------------------------------------- + +void ScOutputData::DrawRotated(sal_Bool bPixelToLogic) +{ + //! nRotMax speichern + SCCOL nRotMax = nX2; + for (SCSIZE nRotY=0; nRotY<nArrCount; nRotY++) + if (pRowInfo[nRotY].nRotMaxCol != SC_ROTMAX_NONE && pRowInfo[nRotY].nRotMaxCol > nRotMax) + nRotMax = pRowInfo[nRotY].nRotMaxCol; + + + ScModule* pScMod = SC_MOD(); + sal_Int32 nConfBackColor = pScMod->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor; + // #105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed sal_True) + sal_Bool bCellContrast = bUseStyleColor && + Application::GetSettings().GetStyleSettings().GetHighContrastMode(); + + ScFieldEditEngine* pEngine = NULL; + sal_Bool bHyphenatorSet = sal_False; + const ScPatternAttr* pPattern; + const SfxItemSet* pCondSet; + const ScPatternAttr* pOldPattern = NULL; + const SfxItemSet* pOldCondSet = NULL; + ScBaseCell* pCell = NULL; + + long nInitPosX = nScrX; + if ( bLayoutRTL ) + { +#if 0 + Size aOnePixel = pDev->PixelToLogic(Size(1,1)); + long nOneX = aOnePixel.Width(); + nInitPosX += nMirrorW - nOneX; +#endif + nInitPosX += nMirrorW - 1; + } + long nLayoutSign = bLayoutRTL ? -1 : 1; + + long nRowPosY = nScrY; + for (SCSIZE nArrY=0; nArrY+1<nArrCount; nArrY++) // 0 fuer Reste von zusammengefassten + { + RowInfo* pThisRowInfo = &pRowInfo[nArrY]; + long nCellHeight = (long) pThisRowInfo->nHeight; + if (nArrY==1) nRowPosY = nScrY; // vorher wird einzeln berechnet + + if ( ( pThisRowInfo->bChanged || nArrY==0 ) && pThisRowInfo->nRotMaxCol != SC_ROTMAX_NONE ) + { + long nPosX = 0; + for (SCCOL nX=0; nX<=nRotMax; nX++) + { + if (nX==nX1) nPosX = nInitPosX; // positions before nX1 are calculated individually + + CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1]; + if ( pInfo->nRotateDir != SC_ROTDIR_NONE ) + { + SCROW nY = pThisRowInfo->nRowNo; + + sal_Bool bHidden = sal_False; + if (bEditMode) + if ( nX == nEditCol && nY == nEditRow ) + bHidden = sal_True; + + if (!bHidden) + { + if (!pEngine) + { + // Ein RefDevice muss auf jeden Fall gesetzt werden, + // sonst legt sich die EditEngine ein VirtualDevice an! + pEngine = new ScFieldEditEngine( pDoc->GetEnginePool() ); + pEngine->SetUpdateMode( sal_False ); + pEngine->SetRefDevice( pFmtDevice ); // always set + sal_uLong nCtrl = pEngine->GetControlWord(); + if ( bShowSpellErrors ) + nCtrl |= EE_CNTRL_ONLINESPELLING; + if ( eType == OUTTYPE_PRINTER ) + nCtrl &= ~EE_CNTRL_MARKFIELDS; + pEngine->SetControlWord( nCtrl ); + pEngine->SetForbiddenCharsTable( pDoc->GetForbiddenCharacters() ); + pEngine->SetAsianCompressionMode( pDoc->GetAsianCompression() ); + pEngine->SetKernAsianPunctuation( pDoc->GetAsianKerning() ); + pEngine->EnableAutoColor( bUseStyleColor ); + pEngine->SetDefaultHorizontalTextDirection( + (EEHorizontalTextDirection)pDoc->GetEditTextDirection( nTab ) ); + } + else + lcl_ClearEdit( *pEngine ); // also calls SetUpdateMode(sal_False) + + long nPosY = nRowPosY; + sal_Bool bVisChanged = sal_False; + + //! Rest von zusammengefasster Zelle weiter oben funktioniert nicht! + + sal_Bool bFromDoc = sal_False; + pPattern = pInfo->pPatternAttr; + pCondSet = pInfo->pConditionSet; + if (!pPattern) + { + pPattern = pDoc->GetPattern( nX, nY, nTab ); + bFromDoc = sal_True; + } + pCell = pInfo->pCell; + if (bFromDoc) + pCondSet = pDoc->GetCondResult( nX, nY, nTab ); + + if (!pCell && nX>nX2) + GetVisibleCell( nX, nY, nTab, pCell ); + + if ( !pCell || IsEmptyCellText( pThisRowInfo, nX, nY ) ) + bHidden = sal_True; // nRotateDir is also set without a cell + + long nCellWidth = (long) pRowInfo[0].pCellInfo[nX+1].nWidth; + + SvxCellHorJustify eHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem&) + pPattern->GetItem(ATTR_HOR_JUSTIFY, pCondSet)).GetValue(); + sal_Bool bBreak = ( eHorJust == SVX_HOR_JUSTIFY_BLOCK ) || + ((const SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK, pCondSet)).GetValue(); + sal_Bool bRepeat = ( eHorJust == SVX_HOR_JUSTIFY_REPEAT && !bBreak ); + sal_Bool bShrink = !bBreak && !bRepeat && static_cast<const SfxBoolItem&> + (pPattern->GetItem( ATTR_SHRINKTOFIT, pCondSet )).GetValue(); + SvxCellOrientation eOrient = pPattern->GetCellOrientation( pCondSet ); + + const ScMergeAttr* pMerge = + (ScMergeAttr*)&pPattern->GetItem(ATTR_MERGE); + sal_Bool bMerged = pMerge->GetColMerge() > 1 || pMerge->GetRowMerge() > 1; + + long nStartX = nPosX; + long nStartY = nPosY; + if (nX<nX1) + { + if ((bBreak || eOrient!=SVX_ORIENTATION_STANDARD) && !bMerged) + bHidden = sal_True; + else + { + nStartX = nInitPosX; + SCCOL nCol = nX1; + while (nCol > nX) + { + --nCol; + nStartX -= nLayoutSign * (long) pRowInfo[0].pCellInfo[nCol+1].nWidth; + } + } + } + long nCellStartX = nStartX; + + // Ersatzdarstellung fuer zu kleinen Text weggelassen + + if (!bHidden) + { + long nOutWidth = nCellWidth - 1; + long nOutHeight; + if (pInfo) + nOutHeight = nCellHeight; + else + nOutHeight = (long) ( pDoc->GetRowHeight(nY,nTab) * nPPTY ); + + if ( bMerged ) // Zusammengefasst + { + SCCOL nCountX = pMerge->GetColMerge(); + for (SCCOL i=1; i<nCountX; i++) + nOutWidth += (long) ( pDoc->GetColWidth(nX+i,nTab) * nPPTX ); + SCROW nCountY = pMerge->GetRowMerge(); + nOutHeight += (long) pDoc->GetScaledRowHeight( nY+1, nY+nCountY-1, nTab, nPPTY); + } + + SvxCellVerJustify eVerJust = (SvxCellVerJustify)((const SvxVerJustifyItem&) + pPattern->GetItem(ATTR_VER_JUSTIFY, pCondSet)).GetValue(); + + // Syntax-Modus wird hier ignoriert... + + // StringDiffer doesn't look at hyphenate, language items + if ( pPattern != pOldPattern || pCondSet != pOldCondSet ) + { + SfxItemSet* pSet = new SfxItemSet( pEngine->GetEmptyItemSet() ); + pPattern->FillEditItemSet( pSet, pCondSet ); + + // Ausrichtung fuer EditEngine + SvxAdjust eSvxAdjust = SVX_ADJUST_LEFT; + if (eOrient==SVX_ORIENTATION_STACKED) + eSvxAdjust = SVX_ADJUST_CENTER; + // Adjustment fuer bBreak ist hier weggelassen + pSet->Put( SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) ); + + pEngine->SetDefaults( pSet ); + pOldPattern = pPattern; + pOldCondSet = pCondSet; + + sal_uLong nControl = pEngine->GetControlWord(); + if (eOrient==SVX_ORIENTATION_STACKED) + nControl |= EE_CNTRL_ONECHARPERLINE; + else + nControl &= ~EE_CNTRL_ONECHARPERLINE; + pEngine->SetControlWord( nControl ); + + if ( !bHyphenatorSet && ((const SfxBoolItem&)pSet->Get(EE_PARA_HYPHENATE)).GetValue() ) + { + // set hyphenator the first time it is needed + com::sun::star::uno::Reference<com::sun::star::linguistic2::XHyphenator> xXHyphenator( LinguMgr::GetHyphenator() ); + pEngine->SetHyphenator( xXHyphenator ); + bHyphenatorSet = sal_True; + } + + Color aBackCol = ((const SvxBrushItem&) + pPattern->GetItem( ATTR_BACKGROUND, pCondSet )).GetColor(); + if ( bUseStyleColor && ( aBackCol.GetTransparency() > 0 || bCellContrast ) ) + aBackCol.SetColor( nConfBackColor ); + pEngine->SetBackgroundColor( aBackCol ); + } + + // Raender + + //! Position und Papersize auf EditUtil umstellen !!! + + const SvxMarginItem* pMargin = (const SvxMarginItem*) + &pPattern->GetItem(ATTR_MARGIN, pCondSet); + sal_uInt16 nIndent = 0; + if ( eHorJust == SVX_HOR_JUSTIFY_LEFT ) + nIndent = ((const SfxUInt16Item&)pPattern-> + GetItem(ATTR_INDENT, pCondSet)).GetValue(); + + long nTotalHeight = nOutHeight; // ohne Rand abzuziehen + if ( bPixelToLogic ) + nTotalHeight = pRefDevice->PixelToLogic(Size(0,nTotalHeight)).Height(); + + long nLeftM = (long) ( (pMargin->GetLeftMargin() + nIndent) * nPPTX ); + long nTopM = (long) ( pMargin->GetTopMargin() * nPPTY ); + long nRightM = (long) ( pMargin->GetRightMargin() * nPPTX ); + long nBottomM = (long) ( pMargin->GetBottomMargin() * nPPTY ); + nStartX += nLeftM; + nStartY += nTopM; + nOutWidth -= nLeftM + nRightM; + nOutHeight -= nTopM + nBottomM; + + // Rotation schon hier, um bei Umbruch auch PaperSize anzupassen + long nAttrRotate = 0; + double nSin = 0.0; + double nCos = 1.0; + SvxRotateMode eRotMode = SVX_ROTATE_MODE_STANDARD; + if ( eOrient == SVX_ORIENTATION_STANDARD ) + { + nAttrRotate = ((const SfxInt32Item&)pPattern-> + GetItem(ATTR_ROTATE_VALUE, pCondSet)).GetValue(); + if ( nAttrRotate ) + { + eRotMode = (SvxRotateMode)((const SvxRotateModeItem&) + pPattern->GetItem(ATTR_ROTATE_MODE, pCondSet)).GetValue(); + + if ( nAttrRotate == 18000 ) + eRotMode = SVX_ROTATE_MODE_STANDARD; // keinen Ueberlauf + + if ( bLayoutRTL ) + nAttrRotate = -nAttrRotate; + + double nRealOrient = nAttrRotate * F_PI18000; // 1/100 Grad + nCos = cos( nRealOrient ); + nSin = sin( nRealOrient ); + } + } + + Size aPaperSize = Size( 1000000, 1000000 ); + if (eOrient==SVX_ORIENTATION_STACKED) + aPaperSize.Width() = nOutWidth; // zum Zentrieren + else if (bBreak) + { + if (nAttrRotate) + { + //! richtige PaperSize fuer Umbruch haengt von der Zeilenzahl + //! ab, solange die Zeilen nicht einzeln versetzt ausgegeben + //! werden koennen -> darum unbegrenzt, also kein Umbruch. + //! Mit versetzten Zeilen waere das folgende richtig: + aPaperSize.Width() = (long)(nOutHeight / fabs(nSin)); + } + else if (eOrient == SVX_ORIENTATION_STANDARD) + aPaperSize.Width() = nOutWidth; + else + aPaperSize.Width() = nOutHeight - 1; + } + if (bPixelToLogic) + pEngine->SetPaperSize(pRefDevice->PixelToLogic(aPaperSize)); + else + pEngine->SetPaperSize(aPaperSize); // Scale ist immer 1 + + // Daten aus Zelle lesen + + if (pCell) + { + if (pCell->GetCellType() == CELLTYPE_EDIT) + { + const EditTextObject* pData; + ((ScEditCell*)pCell)->GetData(pData); + + if (pData) + pEngine->SetText(*pData); + else + { + DBG_ERROR("pData == 0"); + } + } + else + { + sal_uLong nFormat = pPattern->GetNumberFormat( + pDoc->GetFormatTable(), pCondSet ); + String aString; + Color* pColor; + ScCellFormat::GetString( pCell, + nFormat,aString, &pColor, + *pDoc->GetFormatTable(), + bShowNullValues, + bShowFormulas, + ftCheck ); + + pEngine->SetText(aString); + if ( pColor && !bSyntaxMode && !( bUseStyleColor && bForceAutoColor ) ) + lcl_SetEditColor( *pEngine, *pColor ); + } + + if ( bSyntaxMode ) + SetEditSyntaxColor( *pEngine, pCell ); + else if ( bUseStyleColor && bForceAutoColor ) + lcl_SetEditColor( *pEngine, COL_AUTO ); //! or have a flag at EditEngine + } + else + { + DBG_ERROR("pCell == NULL"); + } + + pEngine->SetUpdateMode( sal_True ); // after SetText, before CalcTextWidth/GetTextHeight + + long nEngineWidth = (long) pEngine->CalcTextWidth(); + long nEngineHeight = pEngine->GetTextHeight(); + + if (nAttrRotate && bBreak) + { + double nAbsCos = fabs( nCos ); + double nAbsSin = fabs( nSin ); + + // #47740# adjust witdh of papersize for height of text + int nSteps = 5; + while (nSteps > 0) + { + // everything is in pixels + long nEnginePixel = pRefDevice->LogicToPixel( + Size(0,nEngineHeight)).Height(); + long nEffHeight = nOutHeight - (long)(nEnginePixel * nAbsCos) + 2; + long nNewWidth = (long)(nEffHeight / nAbsSin) + 2; + sal_Bool bFits = ( nNewWidth >= aPaperSize.Width() ); + if ( bFits ) + nSteps = 0; + else + { + if ( nNewWidth < 4 ) + { + // can't fit -> fall back to using half height + nEffHeight = nOutHeight / 2; + nNewWidth = (long)(nEffHeight / nAbsSin) + 2; + nSteps = 0; + } + else + --nSteps; + + // set paper width and get new text height + aPaperSize.Width() = nNewWidth; + if (bPixelToLogic) + pEngine->SetPaperSize(pRefDevice->PixelToLogic(aPaperSize)); + else + pEngine->SetPaperSize(aPaperSize); // Scale ist immer 1 + //pEngine->QuickFormatDoc( sal_True ); + nEngineWidth = (long) pEngine->CalcTextWidth(); + nEngineHeight = pEngine->GetTextHeight(); + } + } + } + + long nRealWidth = nEngineWidth; + long nRealHeight = nEngineHeight; + + // wenn gedreht, Groesse anpassen + if (nAttrRotate) + { + double nAbsCos = fabs( nCos ); + double nAbsSin = fabs( nSin ); + + if ( eRotMode == SVX_ROTATE_MODE_STANDARD ) + nEngineWidth = (long) ( nRealWidth * nAbsCos + + nRealHeight * nAbsSin ); + else + nEngineWidth = (long) ( nRealHeight / nAbsSin ); + //! begrenzen !!! + + nEngineHeight = (long) ( nRealHeight * nAbsCos + + nRealWidth * nAbsSin ); + } + + if (!nAttrRotate) // hier nur gedrehter Text + bHidden = sal_True; //! vorher abfragen !!! + + //! weglassen, was nicht hereinragt + + if (!bHidden) + { + sal_Bool bClip = sal_False; + Size aClipSize = Size( nScrX+nScrW-nStartX, nScrY+nScrH-nStartY ); + + // weiterschreiben + + Size aCellSize; + if (bPixelToLogic) + aCellSize = pRefDevice->PixelToLogic( Size( nOutWidth, nOutHeight ) ); + else + aCellSize = Size( nOutWidth, nOutHeight ); // Scale ist 1 + + long nGridWidth = nEngineWidth; + sal_Bool bNegative = sal_False; + if ( eRotMode != SVX_ROTATE_MODE_STANDARD ) + { + nGridWidth = aCellSize.Width() + + Abs((long) ( aCellSize.Height() * nCos / nSin )); + bNegative = ( pInfo->nRotateDir == SC_ROTDIR_LEFT ); + if ( bLayoutRTL ) + bNegative = !bNegative; + } + + // use GetOutputArea to hide the grid + // (clip region is done manually below) + OutputAreaParam aAreaParam; + + SCCOL nCellX = nX; + SCROW nCellY = nY; + SvxCellHorJustify eOutHorJust = eHorJust; + if ( eRotMode != SVX_ROTATE_MODE_STANDARD ) + eOutHorJust = bNegative ? SVX_HOR_JUSTIFY_RIGHT : SVX_HOR_JUSTIFY_LEFT; + long nNeededWidth = nGridWidth; // in pixel for GetOutputArea + if ( bPixelToLogic ) + nNeededWidth = pRefDevice->LogicToPixel(Size(nNeededWidth,0)).Width(); + + GetOutputArea( nX, nArrY, nCellStartX, nPosY, nCellX, nCellY, nNeededWidth, + *pPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust), + sal_False, sal_False, sal_True, aAreaParam ); + + if ( bShrink ) + { + long nPixelWidth = bPixelToLogic ? + pRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width() : nEngineWidth; + long nNeededPixel = nPixelWidth + nLeftM + nRightM; + + aAreaParam.mbLeftClip = aAreaParam.mbRightClip = sal_True; + + // always do height + ShrinkEditEngine( *pEngine, aAreaParam.maAlignRect, nLeftM, nTopM, nRightM, nBottomM, + sal_False, sal::static_int_cast<sal_uInt16>(eOrient), nAttrRotate, bPixelToLogic, + nEngineWidth, nEngineHeight, nNeededPixel, aAreaParam.mbLeftClip, aAreaParam.mbRightClip ); + + if ( eRotMode == SVX_ROTATE_MODE_STANDARD ) + { + // do width only if rotating within the cell (standard mode) + ShrinkEditEngine( *pEngine, aAreaParam.maAlignRect, nLeftM, nTopM, nRightM, nBottomM, + sal_True, sal::static_int_cast<sal_uInt16>(eOrient), nAttrRotate, bPixelToLogic, + nEngineWidth, nEngineHeight, nNeededPixel, aAreaParam.mbLeftClip, aAreaParam.mbRightClip ); + } + + // nEngineWidth/nEngineHeight is updated in ShrinkEditEngine + // (but width is only valid for standard mode) + nRealWidth = (long) pEngine->CalcTextWidth(); + nRealHeight = pEngine->GetTextHeight(); + + if ( eRotMode != SVX_ROTATE_MODE_STANDARD ) + nEngineWidth = (long) ( nRealHeight / fabs( nSin ) ); + } + + // sal_Bool bVClip = ( nEngineHeight > aCellSize.Height() ); + + long nClipStartX = nStartX; + if (nX<nX1) + { + //! Clipping unnoetig, wenn links am Fenster + + bClip = sal_True; // nur Rest ausgeben! + if (nStartX<nScrX) + { + long nDif = nScrX - nStartX; + nClipStartX = nScrX; + aClipSize.Width() -= nDif; + } + } + + long nClipStartY = nStartY; + if (nArrY==0 || bVisChanged) + { + if ( nClipStartY < nRowPosY ) + { + long nDif = nRowPosY - nClipStartY; + bClip = sal_True; + nClipStartY = nRowPosY; + aClipSize.Height() -= nDif; + } + } + + bClip = sal_True; // always clip at the window/page border + + //Rectangle aClipRect; + if (bClip) + { + if ( nAttrRotate /* && eRotMode != SVX_ROTATE_MODE_STANDARD */ ) + { + // gedrehten, ausgerichteten Text nur an den + // Seitengrenzen clippen + nClipStartX = nScrX; + aClipSize.Width() = nScrW; + } + + if (bPixelToLogic) + aAreaParam.maClipRect = pRefDevice->PixelToLogic( Rectangle( + Point(nClipStartX,nClipStartY), aClipSize ) ); + else + aAreaParam.maClipRect = Rectangle(Point(nClipStartX, nClipStartY), + aClipSize ); // Scale = 1 + + if (bMetaFile) + { + pDev->Push(); + pDev->IntersectClipRegion( aAreaParam.maClipRect ); + } + else + pDev->SetClipRegion( Region( aAreaParam.maClipRect ) ); + } + + Point aLogicStart; + if (bPixelToLogic) + aLogicStart = pRefDevice->PixelToLogic( Point(nStartX,nStartY) ); + else + aLogicStart = Point(nStartX, nStartY); + if ( eOrient!=SVX_ORIENTATION_STANDARD || !bBreak ) + { + long nAvailWidth = aCellSize.Width(); + if (eType==OUTTYPE_WINDOW && + eOrient!=SVX_ORIENTATION_STACKED && + pInfo && pInfo->bAutoFilter) + { + // filter drop-down width is now independent from row height + if (bPixelToLogic) + nAvailWidth -= pRefDevice->PixelToLogic(Size(0,DROPDOWN_BITMAP_SIZE)).Height(); + else + nAvailWidth -= DROPDOWN_BITMAP_SIZE; + long nComp = nEngineWidth; + if (nAvailWidth<nComp) nAvailWidth=nComp; + } + + // horizontale Ausrichtung + + if (eOrient==SVX_ORIENTATION_STANDARD && !nAttrRotate) + { + if (eHorJust==SVX_HOR_JUSTIFY_RIGHT || + eHorJust==SVX_HOR_JUSTIFY_CENTER) + { + pEngine->SetUpdateMode( sal_False ); + + SvxAdjust eSvxAdjust = + (eHorJust==SVX_HOR_JUSTIFY_RIGHT) ? + SVX_ADJUST_RIGHT : SVX_ADJUST_CENTER; + pEngine->SetDefaultItem( + SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) ); + + aPaperSize.Width() = nOutWidth; + if (bPixelToLogic) + pEngine->SetPaperSize(pRefDevice->PixelToLogic(aPaperSize)); + else + pEngine->SetPaperSize(aPaperSize); + + pEngine->SetUpdateMode( sal_True ); + } + } + else + { + // bei gedrehtem Text ist Standard zentriert + if (eHorJust==SVX_HOR_JUSTIFY_RIGHT) + aLogicStart.X() += nAvailWidth - nEngineWidth; + else if (eHorJust==SVX_HOR_JUSTIFY_CENTER || + eHorJust==SVX_HOR_JUSTIFY_STANDARD) + aLogicStart.X() += (nAvailWidth - nEngineWidth) / 2; + } + } + + if ( bLayoutRTL ) + { + if (bPixelToLogic) + aLogicStart.X() -= pRefDevice->PixelToLogic( + Size( nCellWidth, 0 ) ).Width(); + else + aLogicStart.X() -= nCellWidth; + } + + if ( eOrient==SVX_ORIENTATION_STANDARD || + eOrient==SVX_ORIENTATION_STACKED || !bBreak ) + { + if (eVerJust==SVX_VER_JUSTIFY_BOTTOM || + eVerJust==SVX_VER_JUSTIFY_STANDARD) + { + if (bPixelToLogic) + aLogicStart.Y() += pRefDevice->PixelToLogic( Size(0, + pRefDevice->LogicToPixel(aCellSize).Height() - + pRefDevice->LogicToPixel(Size(0,nEngineHeight)).Height() + )).Height(); + else + aLogicStart.Y() += aCellSize.Height() - nEngineHeight; + } + + else if (eVerJust==SVX_VER_JUSTIFY_CENTER) + { + if (bPixelToLogic) + aLogicStart.Y() += pRefDevice->PixelToLogic( Size(0,( + pRefDevice->LogicToPixel(aCellSize).Height() - + pRefDevice->LogicToPixel(Size(0,nEngineHeight)).Height()) + / 2)).Height(); + else + aLogicStart.Y() += (aCellSize.Height() - nEngineHeight) / 2; + } + } + + // TOPBOTTON and BOTTOMTOP are handled in DrawStrings/DrawEdit + DBG_ASSERT( eOrient == SVX_ORIENTATION_STANDARD && nAttrRotate, + "DrawRotated: no rotation" ); + + long nOriVal = 0; + if ( nAttrRotate ) + { + // Attribut ist 1/100, Font 1/10 Grad + nOriVal = nAttrRotate / 10; + + double nAddX = 0.0; + double nAddY = 0.0; + if ( nCos > 0.0 && eRotMode != SVX_ROTATE_MODE_STANDARD ) + { + //! begrenzen !!! + double nH = nRealHeight * nCos; + nAddX += nH * ( nCos / fabs(nSin) ); + } + if ( nCos < 0.0 && eRotMode == SVX_ROTATE_MODE_STANDARD ) + nAddX -= nRealWidth * nCos; + if ( nSin < 0.0 ) + nAddX -= nRealHeight * nSin; + if ( nSin > 0.0 ) + nAddY += nRealWidth * nSin; + if ( nCos < 0.0 ) + nAddY -= nRealHeight * nCos; + + if ( eRotMode != SVX_ROTATE_MODE_STANDARD ) + { + //! begrenzen !!! + double nSkew = nTotalHeight * nCos / fabs(nSin); + if ( eRotMode == SVX_ROTATE_MODE_CENTER ) + nAddX -= nSkew * 0.5; + if ( ( eRotMode == SVX_ROTATE_MODE_TOP && nSin > 0.0 ) || + ( eRotMode == SVX_ROTATE_MODE_BOTTOM && nSin < 0.0 ) ) + nAddX -= nSkew; + + long nUp = 0; + if ( eVerJust == SVX_VER_JUSTIFY_CENTER ) + nUp = ( aCellSize.Height() - nEngineHeight ) / 2; + else if ( eVerJust == SVX_VER_JUSTIFY_TOP ) + { + if ( nSin > 0.0 ) + nUp = aCellSize.Height() - nEngineHeight; + } + else // BOTTOM / STANDARD + { + if ( nSin < 0.0 ) + nUp = aCellSize.Height() - nEngineHeight; + } + if ( nUp ) + nAddX += ( nUp * nCos / fabs(nSin) ); + } + + aLogicStart.X() += (long) nAddX; + aLogicStart.Y() += (long) nAddY; + } + + // bSimClip is not used here (because nOriVal is set) + + if ( pEngine->IsRightToLeft( 0 ) ) + { + // For right-to-left, EditEngine always calculates its lines + // beginning from the right edge, but EditLine::nStartPosX is + // of sal_uInt16 type, so the PaperSize must be limited to USHRT_MAX. + Size aLogicPaper = pEngine->GetPaperSize(); + if ( aLogicPaper.Width() > USHRT_MAX ) + { + aLogicPaper.Width() = USHRT_MAX; + pEngine->SetPaperSize(aLogicPaper); + } + } + + pEngine->Draw( pDev, aLogicStart, (short)nOriVal ); + + if (bClip) + { + if (bMetaFile) + pDev->Pop(); + else + pDev->SetClipRegion(); + } + } + } + } + } + nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign; + } + } + nRowPosY += pRowInfo[nArrY].nHeight; + } + + delete pEngine; +} + + + diff --git a/sc/source/ui/view/output3.cxx b/sc/source/ui/view/output3.cxx new file mode 100644 index 000000000000..9265f6192b3c --- /dev/null +++ b/sc/source/ui/view/output3.cxx @@ -0,0 +1,276 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include <editeng/eeitem.hxx> +#include <svx/svdograf.hxx> +#include <svx/svdoole2.hxx> +#include <svx/svdoutl.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svdview.hxx> +#include <vcl/svapp.hxx> + +#include "output.hxx" +#include "drwlayer.hxx" +#include "document.hxx" +#include "tabvwsh.hxx" +#include "fillinfo.hxx" + +#include <svx/fmview.hxx> + +// STATIC DATA ----------------------------------------------------------- + +SdrObject* pSkipPaintObj = NULL; + +//================================================================== + +// #i72502# +Point ScOutputData::PrePrintDrawingLayer(long nLogStX, long nLogStY ) +{ + Rectangle aRect; + SCCOL nCol; + Point aOffset; + long nLayoutSign(bLayoutRTL ? -1 : 1); + + for (nCol=0; nCol<nX1; nCol++) + aOffset.X() -= pDoc->GetColWidth( nCol, nTab ) * nLayoutSign; + aOffset.Y() -= pDoc->GetRowHeight( 0, nY1-1, nTab ); + + long nDataWidth = 0; + long nDataHeight = 0; + for (nCol=nX1; nCol<=nX2; nCol++) + nDataWidth += pDoc->GetColWidth( nCol, nTab ); + nDataHeight += pDoc->GetRowHeight( nY1, nY2, nTab ); + + if ( bLayoutRTL ) + aOffset.X() += nDataWidth; + + aRect.Left() = aRect.Right() = -aOffset.X(); + aRect.Top() = aRect.Bottom() = -aOffset.Y(); + + Point aMMOffset( aOffset ); + aMMOffset.X() = (long)(aMMOffset.X() * HMM_PER_TWIPS); + aMMOffset.Y() = (long)(aMMOffset.Y() * HMM_PER_TWIPS); + + if (!bMetaFile) + aMMOffset += Point( nLogStX, nLogStY ); + + for (nCol=nX1; nCol<=nX2; nCol++) + aRect.Right() += pDoc->GetColWidth( nCol, nTab ); + aRect.Bottom() += pDoc->GetRowHeight( nY1, nY2, nTab ); + + aRect.Left() = (long) (aRect.Left() * HMM_PER_TWIPS); + aRect.Top() = (long) (aRect.Top() * HMM_PER_TWIPS); + aRect.Right() = (long) (aRect.Right() * HMM_PER_TWIPS); + aRect.Bottom() = (long) (aRect.Bottom() * HMM_PER_TWIPS); + + if(pViewShell || pDrawView) + { + SdrView* pLocalDrawView = (pDrawView) ? pDrawView : pViewShell->GetSdrView(); + + if(pLocalDrawView) + { + // #i76114# MapMode has to be set because BeginDrawLayers uses GetPaintRegion + MapMode aOldMode = pDev->GetMapMode(); + if (!bMetaFile) + pDev->SetMapMode( MapMode( MAP_100TH_MM, aMMOffset, aOldMode.GetScaleX(), aOldMode.GetScaleY() ) ); + + // #i74769# work with SdrPaintWindow directly + // #i76114# pass bDisableIntersect = true, because the intersection of the table area + // with the Window's paint region can be empty + Region aRectRegion(aRect); + mpTargetPaintWindow = pLocalDrawView->BeginDrawLayers(pDev, aRectRegion, true); + OSL_ENSURE(mpTargetPaintWindow, "BeginDrawLayers: Got no SdrPaintWindow (!)"); + + if (!bMetaFile) + pDev->SetMapMode( aOldMode ); + } + } + + return aMMOffset; +} + +// #i72502# +void ScOutputData::PostPrintDrawingLayer(const Point& rMMOffset) // #i74768# +{ + // #i74768# just use offset as in PrintDrawingLayer() to also get the form controls + // painted with offset + MapMode aOldMode = pDev->GetMapMode(); + + if (!bMetaFile) + { + pDev->SetMapMode( MapMode( MAP_100TH_MM, rMMOffset, aOldMode.GetScaleX(), aOldMode.GetScaleY() ) ); + } + + if(pViewShell || pDrawView) + { + SdrView* pLocalDrawView = (pDrawView) ? pDrawView : pViewShell->GetSdrView(); + + if(pLocalDrawView) + { + // #i74769# work with SdrPaintWindow directly + pLocalDrawView->EndDrawLayers(*mpTargetPaintWindow, true); + mpTargetPaintWindow = 0; + } + } + + // #i74768# + if (!bMetaFile) + { + pDev->SetMapMode( aOldMode ); + } +} + +// #i72502# +void ScOutputData::PrintDrawingLayer(const sal_uInt16 nLayer, const Point& rMMOffset) +{ + bool bHideAllDrawingLayer(false); + + if(pViewShell || pDrawView) + { + SdrView* pLocalDrawView = (pDrawView) ? pDrawView : pViewShell->GetSdrView(); + + if(pLocalDrawView) + { + bHideAllDrawingLayer = pLocalDrawView->getHideOle() && pLocalDrawView->getHideChart() + && pLocalDrawView->getHideDraw() && pLocalDrawView->getHideFormControl(); + } + } + + // #109985# + if(bHideAllDrawingLayer || (!pDoc->GetDrawLayer())) + { + return; + } + + MapMode aOldMode = pDev->GetMapMode(); + + if (!bMetaFile) + { + pDev->SetMapMode( MapMode( MAP_100TH_MM, rMMOffset, aOldMode.GetScaleX(), aOldMode.GetScaleY() ) ); + } + + // #109985# + DrawSelectiveObjects( nLayer ); + + if (!bMetaFile) + { + pDev->SetMapMode( aOldMode ); + } +} + +// #109985# +void ScOutputData::DrawSelectiveObjects(const sal_uInt16 nLayer) +{ + ScDrawLayer* pModel = pDoc->GetDrawLayer(); + if (!pModel) + return; + + // #i46362# high contrast mode (and default text direction) must be handled + // by the application, so it's still needed when using DrawLayer(). + + SdrOutliner& rOutl = pModel->GetDrawOutliner(); + rOutl.EnableAutoColor( bUseStyleColor ); + rOutl.SetDefaultHorizontalTextDirection( + (EEHorizontalTextDirection)pDoc->GetEditTextDirection( nTab ) ); + + // #i69767# The hyphenator must be set (used to be before drawing a text shape with hyphenation). + // LinguMgr::GetHyphenator (EditEngine) uses a wrapper now that creates the real hyphenator on demand, + // so it's not a performance problem to call UseHyphenator even when it's not needed. + + pModel->UseHyphenator(); + + sal_uLong nOldDrawMode = pDev->GetDrawMode(); + if ( bUseStyleColor && Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) + { + pDev->SetDrawMode( nOldDrawMode | DRAWMODE_SETTINGSLINE | DRAWMODE_SETTINGSFILL | + DRAWMODE_SETTINGSTEXT | DRAWMODE_SETTINGSGRADIENT ); + } + + // #109985# + if(pViewShell || pDrawView) + { + SdrView* pLocalDrawView = (pDrawView) ? pDrawView : pViewShell->GetSdrView(); + + if(pLocalDrawView) + { + SdrPageView* pPageView = pLocalDrawView->GetSdrPageView(); + + if(pPageView) + { + pPageView->DrawLayer(sal::static_int_cast<SdrLayerID>(nLayer), pDev); + } + } + } + + pDev->SetDrawMode(nOldDrawMode); + + // #109985# + return; +} + +// Teile nur fuer Bildschirm + +// #109985# +void ScOutputData::DrawingSingle(const sal_uInt16 nLayer) +{ + sal_Bool bHad = sal_False; + long nPosY = nScrY; + SCSIZE nArrY; + for (nArrY=1; nArrY+1<nArrCount; nArrY++) + { + RowInfo* pThisRowInfo = &pRowInfo[nArrY]; + + if ( pThisRowInfo->bChanged ) + { + if (!bHad) + { + bHad = sal_True; + } + } + else if (bHad) + { + DrawSelectiveObjects( nLayer ); + bHad = sal_False; + } + nPosY += pRowInfo[nArrY].nHeight; + } + + if (bHad) + DrawSelectiveObjects( nLayer ); +} + + + + diff --git a/sc/source/ui/view/pfuncache.cxx b/sc/source/ui/view/pfuncache.cxx new file mode 100644 index 000000000000..6bb14163b227 --- /dev/null +++ b/sc/source/ui/view/pfuncache.cxx @@ -0,0 +1,198 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include <tools/multisel.hxx> + +#include "pfuncache.hxx" +#include "printfun.hxx" +#include "docsh.hxx" +#include "markdata.hxx" +#include "prevloc.hxx" + +//------------------------------------------------------------------------ + +ScPrintFuncCache::ScPrintFuncCache( ScDocShell* pD, const ScMarkData& rMark, + const ScPrintSelectionStatus& rStatus ) : + aSelection( rStatus ), + pDocSh( pD ), + nTotalPages( 0 ), + bLocInitialized( false ) +{ + // page count uses the stored cell widths for the printer anyway, + // so ScPrintFunc with the document's printer can be used to count + + SfxPrinter* pPrinter = pDocSh->GetPrinter(); + + ScRange aRange; + const ScRange* pSelRange = NULL; + if ( rMark.IsMarked() ) + { + rMark.GetMarkArea( aRange ); + pSelRange = &aRange; + } + + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTabCount = pDoc->GetTableCount(); + SCTAB nTab; + for ( nTab=0; nTab<nTabCount; nTab++ ) + { + long nAttrPage = nTab > 0 ? nFirstAttr[nTab-1] : 1; + + long nThisTab = 0; + if ( rMark.GetTableSelect( nTab ) ) + { + pDoc->InvalidatePageBreaks( nTab ); // user print area (selection) may be different + + ScPrintFunc aFunc( pDocSh, pPrinter, nTab, nAttrPage, 0, pSelRange, &aSelection.GetOptions() ); + nThisTab = aFunc.GetTotalPages(); + nFirstAttr[nTab] = aFunc.GetFirstPageNo(); // from page style or previous sheet + } + else + nFirstAttr[nTab] = nAttrPage; + + nPages[nTab] = nThisTab; + nTotalPages += nThisTab; + } +} + +ScPrintFuncCache::~ScPrintFuncCache() +{ +} + +void ScPrintFuncCache::InitLocations( const ScMarkData& rMark, OutputDevice* pDev ) +{ + if ( bLocInitialized ) + return; // initialize only once + + ScRange aRange; + const ScRange* pSelRange = NULL; + if ( rMark.IsMarked() ) + { + rMark.GetMarkArea( aRange ); + pSelRange = &aRange; + } + + long nRenderer = 0; // 0-based physical page number across sheets + long nTabStart = 0; + + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTabCount = pDoc->GetTableCount(); + for ( SCTAB nTab=0; nTab<nTabCount; nTab++ ) + { + if ( rMark.GetTableSelect( nTab ) ) + { + ScPrintFunc aFunc( pDev, pDocSh, nTab, nFirstAttr[nTab], nTotalPages, pSelRange, &aSelection.GetOptions() ); + aFunc.SetRenderFlag( sal_True ); + + long nDisplayStart = GetDisplayStart( nTab ); + + for ( long nPage=0; nPage<nPages[nTab]; nPage++ ) + { + Range aPageRange( nRenderer+1, nRenderer+1 ); + MultiSelection aPage( aPageRange ); + aPage.SetTotalRange( Range(0,RANGE_MAX) ); + aPage.Select( aPageRange ); + + ScPreviewLocationData aLocData( pDoc, pDev ); + aFunc.DoPrint( aPage, nTabStart, nDisplayStart, sal_False, NULL, &aLocData ); + + ScRange aCellRange; + Rectangle aPixRect; + if ( aLocData.GetMainCellRange( aCellRange, aPixRect ) ) + aLocations.push_back( ScPrintPageLocation( nRenderer, aCellRange, aPixRect ) ); + + ++nRenderer; + } + + nTabStart += nPages[nTab]; + } + } + + bLocInitialized = true; +} + +bool ScPrintFuncCache::FindLocation( const ScAddress& rCell, ScPrintPageLocation& rLocation ) const +{ + for ( std::vector<ScPrintPageLocation>::const_iterator aIter(aLocations.begin()); + aIter != aLocations.end(); aIter++ ) + { + if ( aIter->aCellRange.In( rCell ) ) + { + rLocation = *aIter; + return true; + } + } + return false; // not found +} + +sal_Bool ScPrintFuncCache::IsSameSelection( const ScPrintSelectionStatus& rStatus ) const +{ + return aSelection == rStatus; +} + +SCTAB ScPrintFuncCache::GetTabForPage( long nPage ) const +{ + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTabCount = pDoc->GetTableCount(); + SCTAB nTab = 0; + while ( nTab < nTabCount && nPage >= nPages[nTab] ) + nPage -= nPages[nTab++]; + return nTab; +} + +long ScPrintFuncCache::GetTabStart( SCTAB nTab ) const +{ + long nRet = 0; + for ( SCTAB i=0; i<nTab; i++ ) + nRet += nPages[i]; + return nRet; +} + +long ScPrintFuncCache::GetDisplayStart( SCTAB nTab ) const +{ + //! merge with lcl_GetDisplayStart in preview? + + long nDisplayStart = 0; + ScDocument* pDoc = pDocSh->GetDocument(); + for (SCTAB i=0; i<nTab; i++) + { + if ( pDoc->NeedPageResetAfterTab(i) ) + nDisplayStart = 0; + else + nDisplayStart += nPages[i]; + } + return nDisplayStart; +} + + diff --git a/sc/source/ui/view/pgbrksh.cxx b/sc/source/ui/view/pgbrksh.cxx new file mode 100644 index 000000000000..d5e3450f3e5a --- /dev/null +++ b/sc/source/ui/view/pgbrksh.cxx @@ -0,0 +1,85 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +//------------------------------------------------------------------ + +#include "scitems.hxx" +#include <svl/srchitem.hxx> +#include <sfx2/app.hxx> +#include <sfx2/objface.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/request.hxx> +#include <svl/whiter.hxx> + +#include "pgbrksh.hxx" +#include "tabvwsh.hxx" +#include "scresid.hxx" +#include "document.hxx" +#include "sc.hrc" + +//------------------------------------------------------------------------ + +#define ScPageBreakShell +#include "scslots.hxx" + +//------------------------------------------------------------------------ + +TYPEINIT1( ScPageBreakShell, SfxShell ); + +SFX_IMPL_INTERFACE(ScPageBreakShell, SfxShell, ScResId(SCSTR_PAGEBREAKSHELL)) +{ + SFX_POPUPMENU_REGISTRATION( ScResId(RID_POPUP_PAGEBREAK) ); +} + + +//------------------------------------------------------------------------ +ScPageBreakShell::ScPageBreakShell( ScTabViewShell* pViewSh ) : + SfxShell(pViewSh) +{ + SetPool( &pViewSh->GetPool() ); + ScViewData* pViewData = pViewSh->GetViewData(); + ::svl::IUndoManager* pMgr = pViewData->GetSfxDocShell()->GetUndoManager(); + SetUndoManager( pMgr ); + if ( !pViewData->GetDocument()->IsUndoEnabled() ) + { + pMgr->SetMaxUndoActionCount( 0 ); + } + SetHelpId( HID_SCSHELL_PAGEBREAK ); + SetName(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("PageBreak"))); +} + +//------------------------------------------------------------------------ +ScPageBreakShell::~ScPageBreakShell() +{ +} + + diff --git a/sc/source/ui/view/pivotsh.cxx b/sc/source/ui/view/pivotsh.cxx new file mode 100644 index 000000000000..028307400a2c --- /dev/null +++ b/sc/source/ui/view/pivotsh.cxx @@ -0,0 +1,204 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +//------------------------------------------------------------------ + +#include "scitems.hxx" +#include <svl/srchitem.hxx> +#include <sfx2/app.hxx> +#include <sfx2/objface.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/request.hxx> +#include <svl/whiter.hxx> +#include <vcl/msgbox.hxx> + +#include "sc.hrc" +#include "pivotsh.hxx" +#include "tabvwsh.hxx" +#include "docsh.hxx" +#include "scresid.hxx" +#include "document.hxx" +#include "dpobject.hxx" +#include "dpshttab.hxx" +#include "dbdocfun.hxx" +#include "uiitems.hxx" +//CHINA001 #include "pfiltdlg.hxx" +#include "scabstdlg.hxx" //CHINA001 +//------------------------------------------------------------------------ + +#define ScPivotShell +#include "scslots.hxx" + +//------------------------------------------------------------------------ + +TYPEINIT1( ScPivotShell, SfxShell ); + +SFX_IMPL_INTERFACE(ScPivotShell, SfxShell, ScResId(SCSTR_PIVOTSHELL)) +{ + SFX_POPUPMENU_REGISTRATION( ScResId(RID_POPUP_PIVOT) ); +} + + +//------------------------------------------------------------------------ + +ScPivotShell::ScPivotShell( ScTabViewShell* pViewSh ) : + SfxShell(pViewSh), + pViewShell( pViewSh ) +{ + SetPool( &pViewSh->GetPool() ); + ScViewData* pViewData = pViewSh->GetViewData(); + ::svl::IUndoManager* pMgr = pViewData->GetSfxDocShell()->GetUndoManager(); + SetUndoManager( pMgr ); + if ( !pViewData->GetDocument()->IsUndoEnabled() ) + { + pMgr->SetMaxUndoActionCount( 0 ); + } + SetHelpId( HID_SCSHELL_PIVOTSH ); + SetName(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Pivot"))); +} + +//------------------------------------------------------------------------ +ScPivotShell::~ScPivotShell() +{ +} + +//------------------------------------------------------------------------ +void ScPivotShell::Execute( SfxRequest& rReq ) +{ + switch ( rReq.GetSlot() ) + { + case SID_PIVOT_RECALC: + pViewShell->RecalcPivotTable(); + break; + + case SID_PIVOT_KILL: + pViewShell->DeletePivotTable(); + break; + + case SID_DP_FILTER: + { + ScDPObject* pDPObj = GetCurrDPObject(); + if( pDPObj ) + { + ScQueryParam aQueryParam; + SCTAB nSrcTab = 0; + const ScSheetSourceDesc* pDesc = pDPObj->GetSheetDesc(); + DBG_ASSERT( pDesc, "no sheet source for DP filter dialog" ); + if( pDesc ) + { + aQueryParam = pDesc->aQueryParam; + nSrcTab = pDesc->aSourceRange.aStart.Tab(); + } + + ScViewData* pViewData = pViewShell->GetViewData(); + SfxItemSet aArgSet( pViewShell->GetPool(), + SCITEM_QUERYDATA, SCITEM_QUERYDATA ); + aArgSet.Put( ScQueryItem( SCITEM_QUERYDATA, pViewData, &aQueryParam ) ); + + //CHINA001 ScPivotFilterDlg* pDlg = new ScPivotFilterDlg( + //CHINA001 pViewShell->GetDialogParent(), aArgSet, nSrcTab ); + + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + AbstractScPivotFilterDlg* pDlg = pFact->CreateScPivotFilterDlg( pViewShell->GetDialogParent(), + aArgSet, nSrcTab, + RID_SCDLG_PIVOTFILTER); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + + if( pDlg->Execute() == RET_OK ) + { + ScSheetSourceDesc aNewDesc; + if( pDesc ) + aNewDesc = *pDesc; + + const ScQueryItem& rQueryItem = pDlg->GetOutputItem(); + aNewDesc.aQueryParam = rQueryItem.GetQueryData(); + + ScDPObject aNewObj( *pDPObj ); + aNewObj.SetSheetDesc( aNewDesc ); + ScDBDocFunc aFunc( *pViewData->GetDocShell() ); + aFunc.DataPilotUpdate( pDPObj, &aNewObj, sal_True, sal_False ); + pViewData->GetView()->CursorPosChanged(); // shells may be switched + } + delete pDlg; + } + } + break; + } +} + +//------------------------------------------------------------------------ +void __EXPORT ScPivotShell::GetState( SfxItemSet& rSet ) +{ + ScDocShell* pDocSh = pViewShell->GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + sal_Bool bDisable = pDocSh->IsReadOnly() || pDoc->GetChangeTrack(); + + SfxWhichIter aIter(rSet); + sal_uInt16 nWhich = aIter.FirstWhich(); + while (nWhich) + { + switch (nWhich) + { + case SID_PIVOT_RECALC: + case SID_PIVOT_KILL: + { + //! move ReadOnly check to idl flags + if ( bDisable ) + { + rSet.DisableItem( nWhich ); + } + } + break; + case SID_DP_FILTER: + { + ScDPObject* pDPObj = GetCurrDPObject(); + if( bDisable || !pDPObj || !pDPObj->IsSheetData() ) + rSet.DisableItem( nWhich ); + } + break; + } + nWhich = aIter.NextWhich(); + } +} + + +//------------------------------------------------------------------------ + +ScDPObject* ScPivotShell::GetCurrDPObject() +{ + const ScViewData& rViewData = *pViewShell->GetViewData(); + return rViewData.GetDocument()->GetDPAtCursor( + rViewData.GetCurX(), rViewData.GetCurY(), rViewData.GetTabNo() ); +} + diff --git a/sc/source/ui/view/preview.cxx b/sc/source/ui/view/preview.cxx new file mode 100644 index 000000000000..4f3f1d753f32 --- /dev/null +++ b/sc/source/ui/view/preview.cxx @@ -0,0 +1,1603 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- +#include <tools/pstm.hxx> +#include "scitems.hxx" +#include <editeng/eeitem.hxx> + + +#include <svtools/colorcfg.hxx> +#include <svx/fmview.hxx> +#include <editeng/sizeitem.hxx> +#include <svx/svdpagv.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/dispatch.hxx> +#include <svtools/accessibilityoptions.hxx> +#include <svl/itemset.hxx> +#include <tools/multisel.hxx> +#include <vcl/waitobj.hxx> +#include <vcl/sound.hxx> + +#include "preview.hxx" +#include "prevwsh.hxx" +#include "prevloc.hxx" +#include "docsh.hxx" +#include "docfunc.hxx" +#include "printfun.hxx" +#include "printopt.hxx" +#include "stlpool.hxx" +#include "undostyl.hxx" +#include "drwlayer.hxx" +#include "scmod.hxx" +#include "globstr.hrc" +#include "sc.hrc" // fuer ShellInvalidate +#include "AccessibleDocumentPagePreview.hxx" +#include <vcl/lineinfo.hxx> +#include <svx/algitem.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/ulspitem.hxx> +#include <editeng/sizeitem.hxx> +#include "attrib.hxx" +#include "pagepar.hxx" +#include <com/sun/star/accessibility/XAccessible.hpp> +#include "AccessibilityHints.hxx" +#include <vcl/svapp.hxx> +#include "viewutil.hxx" + +// STATIC DATA ----------------------------------------------------------- + +//================================================================== + +#define SC_PREVIEW_SHADOWSIZE 2 + +long lcl_GetDisplayStart( SCTAB nTab, ScDocument* pDoc, long* pPages ) +{ + long nDisplayStart = 0; + for (SCTAB i=0; i<nTab; i++) + { + if ( pDoc->NeedPageResetAfterTab(i) ) + nDisplayStart = 0; + else + nDisplayStart += pPages[i]; + } + return nDisplayStart; +} + + +ScPreview::ScPreview( Window* pParent, ScDocShell* pDocSh, ScPreviewShell* pViewSh ) : + Window( pParent ), + nPageNo( 0 ), + nZoom( 100 ), + bValid( sal_False ), + nTabsTested( 0 ), + nTab( 0 ), + nTabStart( 0 ), + nDisplayStart( 0 ), + nTotalPages( 0 ), + bStateValid( sal_False ), + bLocationValid( sal_False ), + pLocationData( NULL ), + pDrawView( NULL ), + bInPaint( sal_False ), + bInGetState( sal_False ), + pDocShell( pDocSh ), + pViewShell( pViewSh ), + bLeftRulerMove( sal_False ), + bRightRulerMove( sal_False ), + bTopRulerMove( sal_False ), + bBottomRulerMove( sal_False ), + bHeaderRulerMove( sal_False ), + bFooterRulerMove( sal_False ), + bLeftRulerChange( sal_False ), + bRightRulerChange( sal_False ), + bTopRulerChange( sal_False ), + bBottomRulerChange( sal_False ), + bHeaderRulerChange( sal_False ), + bFooterRulerChange( sal_False ), + bPageMargin ( sal_False ), + bColRulerMove( sal_False ), + mnScale( 0 ), + nColNumberButttonDown( 0 ), + nHeaderHeight ( 0 ), + nFooterHeight ( 0 ) +{ + SetOutDevViewType( OUTDEV_VIEWTYPE_PRINTPREVIEW ); //#106611# + SetBackground(); + + SetHelpId( HID_SC_WIN_PREVIEW ); + SetUniqueId( HID_SC_WIN_PREVIEW ); + + SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() ); +} + + +__EXPORT ScPreview::~ScPreview() +{ + delete pDrawView; + delete pLocationData; +} + +void ScPreview::UpdateDrawView() // nTab muss richtig sein +{ + ScDocument* pDoc = pDocShell->GetDocument(); + ScDrawLayer* pModel = pDoc->GetDrawLayer(); // ist nicht 0 + + // #114135# + if ( pModel ) + { + SdrPage* pPage = pModel->GetPage(nTab); + if ( pDrawView && ( !pDrawView->GetSdrPageView() || pDrawView->GetSdrPageView()->GetPage() != pPage ) ) + { + // die angezeigte Page der DrawView umzustellen (s.u.) funktioniert nicht ?!? + delete pDrawView; + pDrawView = NULL; + } + + if ( !pDrawView ) // neu anlegen? + { + pDrawView = new FmFormView( pModel, this ); + // #55259# die DrawView uebernimmt den Design-Modus vom Model + // (Einstellung "Im Entwurfsmodus oeffnen"), darum hier zuruecksetzen + pDrawView->SetDesignMode( sal_True ); + pDrawView->SetPrintPreview( sal_True ); + pDrawView->ShowSdrPage(pPage); + } +#if 0 + else if ( !pDrawView->GetSdrPageView()) // angezeigte Page umstellen + { + pDrawView->HideSdrPage(); + pDrawView->ShowSdrPage(pDrawView->GetModel()->GetPage(nTab)); + } +#endif + } + else if ( pDrawView ) + { + delete pDrawView; // fuer diese Tabelle nicht gebraucht + pDrawView = NULL; + } +} + + +void ScPreview::TestLastPage() +{ + if (nPageNo >= nTotalPages) + { + if (nTotalPages) + { + nPageNo = nTotalPages - 1; + nTab = nTabCount - 1; + while (nTab > 0 && !nPages[nTab]) // letzte nicht leere Tabelle + --nTab; + DBG_ASSERT(nPages[nTab],"alle Tabellen leer?"); + nTabPage = nPages[nTab] - 1; + nTabStart = 0; + for (sal_uInt16 i=0; i<nTab; i++) + nTabStart += nPages[i]; + + ScDocument* pDoc = pDocShell->GetDocument(); + nDisplayStart = lcl_GetDisplayStart( nTab, pDoc, nPages ); + } + else // leeres Dokument + { + nTab = 0; + nPageNo = nTabPage = nTabStart = nDisplayStart = 0; + aState.nPrintTab = 0; + aState.nStartCol = aState.nEndCol = 0; + aState.nStartRow = aState.nEndRow = 0; + aState.nZoom = 0; + aState.nPagesX = aState.nPagesY = 0; + aState.nTabPages = aState.nTotalPages = + aState.nPageStart = aState.nDocPages = 0; + } + } +} + + +void ScPreview::CalcPages( SCTAB /*nToWhichTab*/ ) +{ + WaitObject( this ); + + ScDocument* pDoc = pDocShell->GetDocument(); + nTabCount = pDoc->GetTableCount(); + + //SCTAB nAnz = Min( nTabCount, SCTAB(nToWhichTab+1) ); + SCTAB nAnz = nTabCount; + SCTAB nStart = nTabsTested; + if (!bValid) + { + nStart = 0; + nTotalPages = 0; + nTabsTested = 0; + } + + // update all pending row heights with a single progress bar, + // instead of a separate progress for each sheet from ScPrintFunc + pDocShell->UpdatePendingRowHeights( nAnz-1, true ); + + // PrintOptions is passed to PrintFunc for SkipEmpty flag, + // but always all sheets are used (there is no selected sheet) + ScPrintOptions aOptions = SC_MOD()->GetPrintOptions(); + + for (SCTAB i=nStart; i<nAnz; i++) + { + long nAttrPage = i > 0 ? nFirstAttr[i-1] : 1; + + long nThisStart = nTotalPages; + ScPrintFunc aPrintFunc( this, pDocShell, i, nAttrPage, 0, NULL, &aOptions ); + long nThisTab = aPrintFunc.GetTotalPages(); + nPages[i] = nThisTab; + nTotalPages += nThisTab; + nFirstAttr[i] = aPrintFunc.GetFirstPageNo(); // behalten oder aus Vorlage + + if (nPageNo>=nThisStart && nPageNo<nTotalPages) + { + nTab = i; + nTabPage = nPageNo - nThisStart; + nTabStart = nThisStart; + + aPrintFunc.GetPrintState( aState ); + aPageSize = aPrintFunc.GetPageSize(); + } + } + + nDisplayStart = lcl_GetDisplayStart( nTab, pDoc, nPages ); + + if (nAnz > nTabsTested) + nTabsTested = nAnz; + + // testen, ob hinter letzter Seite + + if ( nTabsTested >= nTabCount ) + TestLastPage(); + + aState.nDocPages = nTotalPages; + + bValid = sal_True; + bStateValid = sal_True; + DoInvalidate(); +} + + +void ScPreview::RecalcPages() // nur nPageNo geaendert +{ + if (!bValid) + return; // dann wird CalcPages aufgerufen + + SCTAB nOldTab = nTab; + + sal_Bool bDone = sal_False; + while (nPageNo >= nTotalPages && nTabsTested < nTabCount) + { + CalcPages( nTabsTested ); + bDone = sal_True; + } + + if (!bDone) + { + long nPartPages = 0; + for (SCTAB i=0; i<nTabsTested; i++) + { + long nThisStart = nPartPages; + nPartPages += nPages[i]; + + if (nPageNo>=nThisStart && nPageNo<nPartPages) + { + nTab = i; + nTabPage = nPageNo - nThisStart; + nTabStart = nThisStart; + +// aPageSize = aPrintFunc.GetPageSize(); + } + } + + ScDocument* pDoc = pDocShell->GetDocument(); + nDisplayStart = lcl_GetDisplayStart( nTab, pDoc, nPages ); + } + + TestLastPage(); // testen, ob hinter letzter Seite + + if ( nTab != nOldTab ) + bStateValid = sal_False; + + DoInvalidate(); +} + + +void ScPreview::DoPrint( ScPreviewLocationData* pFillLocation ) +{ + if (!bValid) + { + CalcPages(0); + RecalcPages(); + UpdateDrawView(); // Tabelle evtl. geaendert + } + + Fraction aPreviewZoom( nZoom, 100 ); + Fraction aHorPrevZoom( (long)( 100 * nZoom / pDocShell->GetOutputFactor() ), 10000 ); + MapMode aMMMode( MAP_100TH_MM, Point(), aHorPrevZoom, aPreviewZoom ); + + sal_Bool bDoPrint = ( pFillLocation == NULL ); + sal_Bool bValidPage = ( nPageNo < nTotalPages ); + + ScModule* pScMod = SC_MOD(); + const svtools::ColorConfig& rColorCfg = pScMod->GetColorConfig(); + Color aBackColor( rColorCfg.GetColorValue(svtools::APPBACKGROUND).nColor ); + + if ( bDoPrint && ( aOffset.X() < 0 || aOffset.Y() < 0 ) && bValidPage ) + { + SetMapMode( aMMMode ); + SetLineColor(); + SetFillColor(aBackColor); + + Size aWinSize = GetOutputSize(); + if ( aOffset.X() < 0 ) + DrawRect(Rectangle( 0, 0, -aOffset.X(), aWinSize.Height() )); + if ( aOffset.Y() < 0 ) + DrawRect(Rectangle( 0, 0, aWinSize.Width(), -aOffset.Y() )); + } + + Size aLocalPageSize; + if ( bValidPage ) + { + ScPrintOptions aOptions = pScMod->GetPrintOptions(); + + ScPrintFunc* pPrintFunc; + if (bStateValid) + pPrintFunc = new ScPrintFunc( this, pDocShell, aState, &aOptions ); + else + pPrintFunc = new ScPrintFunc( this, pDocShell, nTab, nFirstAttr[nTab], nTotalPages, NULL, &aOptions ); + + pPrintFunc->SetOffset(aOffset); + pPrintFunc->SetManualZoom(nZoom); + pPrintFunc->SetDateTime(aDate,aTime); + pPrintFunc->SetClearFlag(sal_True); + pPrintFunc->SetUseStyleColor( pScMod->GetAccessOptions().GetIsForPagePreviews() ); + + pPrintFunc->SetDrawView( pDrawView ); + + // MultiSelection fuer die eine Seite muss etwas umstaendlich erzeugt werden... + Range aPageRange( nPageNo+1, nPageNo+1 ); + MultiSelection aPage( aPageRange ); + aPage.SetTotalRange( Range(0,RANGE_MAX) ); + aPage.Select( aPageRange ); + + long nPrinted = pPrintFunc->DoPrint( aPage, nTabStart, nDisplayStart, bDoPrint, NULL, pFillLocation ); + DBG_ASSERT(nPrinted<=1, "was'n nu los?"); + + SetMapMode(aMMMode); +// sal_uInt16 nPrintZoom = pPrintFunc->GetZoom(); + + if (nPrinted) // wenn nichts, alles grau zeichnen + { + aLocalPageSize = pPrintFunc->GetPageSize(); + aLocalPageSize.Width() = (long) (aLocalPageSize.Width() * HMM_PER_TWIPS ); + aLocalPageSize.Height() = (long) (aLocalPageSize.Height() * HMM_PER_TWIPS ); + } + + if (!bStateValid) + { + pPrintFunc->GetPrintState( aState ); + aState.nDocPages = nTotalPages; + bStateValid = sal_True; + } + delete pPrintFunc; + } + + if ( bDoPrint ) + { + long nPageEndX = aLocalPageSize.Width() - aOffset.X(); + long nPageEndY = aLocalPageSize.Height() - aOffset.Y(); + if ( !bValidPage ) + nPageEndX = nPageEndY = 0; + + Size aWinSize = GetOutputSize(); + Point aWinEnd( aWinSize.Width(), aWinSize.Height() ); + sal_Bool bRight = nPageEndX <= aWinEnd.X(); + sal_Bool bBottom = nPageEndY <= aWinEnd.Y(); + if (bRight || bBottom) + { + SetLineColor(); + SetFillColor(aBackColor); + if (bRight) + DrawRect(Rectangle(nPageEndX,0, aWinEnd.X(),aWinEnd.Y())); + if (bBottom) + { + if (bRight) + DrawRect(Rectangle(0,nPageEndY, nPageEndX,aWinEnd.Y())); // Ecke nicht doppelt + else + DrawRect(Rectangle(0,nPageEndY, aWinEnd.X(),aWinEnd.Y())); + } + } + + if ( bValidPage ) + { + Color aBorderColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor ); + + // draw border + + if ( aOffset.X() <= 0 || aOffset.Y() <= 0 || bRight || bBottom ) + { + SetLineColor( aBorderColor ); + SetFillColor(); + + Rectangle aPixel( LogicToPixel( Rectangle( -aOffset.X(), -aOffset.Y(), nPageEndX, nPageEndY ) ) ); + --aPixel.Right(); + --aPixel.Bottom(); + DrawRect( PixelToLogic( aPixel ) ); + } + + // draw shadow + + SetLineColor(); + SetFillColor( aBorderColor ); + + Rectangle aPixel; + + aPixel = LogicToPixel( Rectangle( nPageEndX, -aOffset.Y(), nPageEndX, nPageEndY ) ); + aPixel.Top() += SC_PREVIEW_SHADOWSIZE; + aPixel.Right() += SC_PREVIEW_SHADOWSIZE - 1; + aPixel.Bottom() += SC_PREVIEW_SHADOWSIZE - 1; + DrawRect( PixelToLogic( aPixel ) ); + + aPixel = LogicToPixel( Rectangle( -aOffset.X(), nPageEndY, nPageEndX, nPageEndY ) ); + aPixel.Left() += SC_PREVIEW_SHADOWSIZE; + aPixel.Right() += SC_PREVIEW_SHADOWSIZE - 1; + aPixel.Bottom() += SC_PREVIEW_SHADOWSIZE - 1; + DrawRect( PixelToLogic( aPixel ) ); + } + } +} + +//Issue51656 Add resizeable margin on page preview from maoyg +void __EXPORT ScPreview::Paint( const Rectangle& /* rRect */ ) +{ + if (!bValid) + { + CalcPages(0); + RecalcPages(); + UpdateDrawView(); // Table possibly amended + } + + Fraction aPreviewZoom( nZoom, 100 ); + Fraction aHorPrevZoom( (long)( 100 * nZoom / pDocShell->GetOutputFactor() ), 10000 ); + MapMode aMMMode( MAP_100TH_MM, Point(), aHorPrevZoom, aPreviewZoom ); + + ScModule* pScMod = SC_MOD(); + const svtools::ColorConfig& rColorCfg = pScMod->GetColorConfig(); + Color aBackColor( rColorCfg.GetColorValue(svtools::APPBACKGROUND).nColor ); + + if ( aOffset.X() < 0 || aOffset.Y() < 0 ) + { + SetMapMode( aMMMode ); + SetLineColor(); + SetFillColor(aBackColor); + + Size aWinSize = GetOutputSize(); + if ( aOffset.X() < 0 ) + DrawRect(Rectangle( 0, 0, -aOffset.X(), aWinSize.Height() )); + if ( aOffset.Y() < 0 ) + DrawRect(Rectangle( 0, 0, aWinSize.Width(), -aOffset.Y() )); + } + + long nLeftMargin = 0; + long nRightMargin = 0; + long nTopMargin = 0; + long nBottomMargin = 0; + sal_Bool bHeaderOn = sal_False; + sal_Bool bFooterOn = sal_False; + + ScDocument* pDoc = pDocShell->GetDocument(); + sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); + + Size aPaintPageSize; + if ( nPageNo < nTotalPages ) + { + ScPrintOptions aOptions = SC_MOD()->GetPrintOptions(); + + ScPrintFunc* pPrintFunc; + if ( bStateValid ) + pPrintFunc = new ScPrintFunc( pDocShell, this, aState, &aOptions ); + else + pPrintFunc = new ScPrintFunc( pDocShell, this, nTab, nFirstAttr[nTab], nTotalPages, NULL, &aOptions ); + + pPrintFunc->SetOffset(aOffset); + pPrintFunc->SetManualZoom(nZoom); + pPrintFunc->SetDateTime(aDate,aTime); + pPrintFunc->SetClearFlag(sal_True); + pPrintFunc->SetUseStyleColor( pScMod->GetAccessOptions().GetIsForPagePreviews() ); + pPrintFunc->SetDrawView( pDrawView ); + + // Multi Selection for one side must be something umstaendlich generated ... + Range aPageRange( nPageNo+1, nPageNo+1 ); + MultiSelection aPage( aPageRange ); + aPage.SetTotalRange( Range(0,RANGE_MAX) ); + aPage.Select( aPageRange ); + + long nPrinted = pPrintFunc->DoPrint( aPage, nTabStart, nDisplayStart ); + DBG_ASSERT(nPrinted<=1, "was'n nu los?"); + + SetMapMode(aMMMode); + + //init nLeftMargin ... in the ScPrintFunc::InitParam!!! + nLeftMargin = pPrintFunc->GetLeftMargin(); + nRightMargin = pPrintFunc->GetRightMargin(); + nTopMargin = pPrintFunc->GetTopMargin(); + nBottomMargin = pPrintFunc->GetBottomMargin(); + nHeaderHeight = pPrintFunc->GetHeader().nHeight; + nFooterHeight = pPrintFunc->GetFooter().nHeight; + bHeaderOn = pPrintFunc->GetHeader().bEnable; + bFooterOn = pPrintFunc->GetFooter().bEnable; + mnScale = pPrintFunc->GetZoom(); + + Rectangle aPixRect; + Rectangle aRectCellPosition; + Rectangle aRectPosition; + GetLocationData().GetMainCellRange( aPageArea, aPixRect ); + if( !bLayoutRTL ) + { + GetLocationData().GetCellPosition( aPageArea.aStart, aRectPosition ); + nLeftPosition = aRectPosition.Left(); + for( SCCOL i = aPageArea.aStart.Col(); i <= aPageArea.aEnd.Col(); i++ ) + { + GetLocationData().GetCellPosition( ScAddress( i,aPageArea.aStart.Row(),aPageArea.aStart.Tab()),aRectCellPosition ); + nRight[i] = aRectCellPosition.Right(); + } + } + else + { + GetLocationData().GetCellPosition( aPageArea.aEnd, aRectPosition ); + nLeftPosition = aRectPosition.Right()+1; + + GetLocationData().GetCellPosition( aPageArea.aStart,aRectCellPosition ); + nRight[ aPageArea.aEnd.Col() ] = aRectCellPosition.Left(); + for( SCCOL i = aPageArea.aEnd.Col(); i > aPageArea.aStart.Col(); i-- ) + { + GetLocationData().GetCellPosition( ScAddress( i,aPageArea.aEnd.Row(),aPageArea.aEnd.Tab()),aRectCellPosition ); + nRight[ i-1 ] = nRight[ i ] + aRectCellPosition.Right() - aRectCellPosition.Left() + 1; + } + } + + if ( nPrinted ) // If nothing, all gray draw + { + aPaintPageSize = pPrintFunc->GetPageSize(); + aPaintPageSize.Width() = (long) (aPaintPageSize.Width() * HMM_PER_TWIPS ); + aPaintPageSize.Height() = (long) (aPaintPageSize.Height() * HMM_PER_TWIPS ); + + nLeftMargin = (long) ( nLeftMargin * HMM_PER_TWIPS ); + nRightMargin = (long) ( nRightMargin * HMM_PER_TWIPS ); + nTopMargin = (long) ( nTopMargin * HMM_PER_TWIPS ); + nBottomMargin = (long) ( nBottomMargin * HMM_PER_TWIPS ); + nHeaderHeight = (long) ( nHeaderHeight * HMM_PER_TWIPS * mnScale / 100 + nTopMargin ); + nFooterHeight = (long) ( nFooterHeight * HMM_PER_TWIPS * mnScale / 100 + nBottomMargin ); + } + + if ( !bStateValid ) + { + pPrintFunc->GetPrintState( aState ); + aState.nDocPages = nTotalPages; + bStateValid = sal_True; + } + + delete pPrintFunc; + } + + + long nPageEndX = aPaintPageSize.Width() - aOffset.X(); + long nPageEndY = aPaintPageSize.Height() - aOffset.Y(); + Size aWinSize = GetOutputSize(); + Point aWinEnd( aWinSize.Width(), aWinSize.Height() ); + sal_Bool bRight = nPageEndX <= aWinEnd.X(); + sal_Bool bBottom = nPageEndY <= aWinEnd.Y(); + + if( bPageMargin ) + { + SetMapMode(aMMMode); + SetLineColor( COL_BLACK ); + DrawInvert( (long)( nTopMargin - aOffset.Y() ), POINTER_VSIZEBAR ); + DrawInvert( (long)(nPageEndY - nBottomMargin ), POINTER_VSIZEBAR ); + DrawInvert( (long)( nLeftMargin - aOffset.X() ), POINTER_HSIZEBAR ); + DrawInvert( (long)( nPageEndX - nRightMargin ) , POINTER_HSIZEBAR ); + if( bHeaderOn ) + { + DrawInvert( nHeaderHeight - aOffset.Y(), POINTER_VSIZEBAR ); + } + if( bFooterOn ) + { + DrawInvert( nPageEndY - nFooterHeight, POINTER_VSIZEBAR ); + } + + SetMapMode( MapMode( MAP_PIXEL ) ); + for( int i= aPageArea.aStart.Col(); i<= aPageArea.aEnd.Col(); i++ ) + { + Point aColumnTop = LogicToPixel( Point( 0, -aOffset.Y() ) ,aMMMode ); + SetLineColor( COL_BLACK ); + SetFillColor( COL_BLACK ); + DrawRect( Rectangle( Point( nRight[i] - 2, aColumnTop.Y() ),Point( nRight[i] + 2 , 4 + aColumnTop.Y()) )); + DrawLine( Point( nRight[i], aColumnTop.Y() ), Point( nRight[i], 10 + aColumnTop.Y()) ); + } + SetMapMode( aMMMode ); + } + + if (bRight || bBottom) + { + SetMapMode(aMMMode); + SetLineColor(); + SetFillColor(aBackColor); + if (bRight) + DrawRect(Rectangle(nPageEndX,0, aWinEnd.X(),aWinEnd.Y())); + if (bBottom) + { + if (bRight) + DrawRect(Rectangle(0,nPageEndY, nPageEndX,aWinEnd.Y())); // Ecke nicht doppelt + else + DrawRect(Rectangle(0,nPageEndY, aWinEnd.X(),aWinEnd.Y())); + } + } + pViewShell->UpdateScrollBars(); +} +//Issue51656 Add resizeable margin on page preview from maoyg + +void __EXPORT ScPreview::Command( const CommandEvent& rCEvt ) +{ + sal_uInt16 nCmd = rCEvt.GetCommand(); + if ( nCmd == COMMAND_WHEEL || nCmd == COMMAND_STARTAUTOSCROLL || nCmd == COMMAND_AUTOSCROLL ) + { + sal_Bool bDone = pViewShell->ScrollCommand( rCEvt ); + if (!bDone) + Window::Command(rCEvt); + } + else if ( nCmd == COMMAND_CONTEXTMENU ) + SfxDispatcher::ExecutePopup(); + else + Window::Command( rCEvt ); +} + + +void __EXPORT ScPreview::KeyInput( const KeyEvent& rKEvt ) +{ + // The + and - keys can't be configured as accelerator entries, so they must be handled directly + // (in ScPreview, not ScPreviewShell -> only if the preview window has the focus) + + const KeyCode& rKeyCode = rKEvt.GetKeyCode(); + sal_uInt16 nKey = rKeyCode.GetCode(); + sal_Bool bHandled = sal_False; + if(!rKeyCode.GetModifier()) + { + sal_uInt16 nSlot = 0; + switch(nKey) + { + case KEY_ADD: nSlot = SID_PREVIEW_ZOOMIN; break; + case KEY_ESCAPE: nSlot = ScViewUtil::IsFullScreen( *pViewShell ) ? SID_CANCEL : SID_PREVIEW_CLOSE; break; + case KEY_SUBTRACT: nSlot = SID_PREVIEW_ZOOMOUT; break; + } + if(nSlot) + { + bHandled = sal_True; + pViewShell->GetViewFrame()->GetDispatcher()->Execute( nSlot, SFX_CALLMODE_ASYNCHRON ); + } + } + + if ( !bHandled && !pViewShell->KeyInput(rKEvt) ) + Window::KeyInput(rKEvt); +} + + +const ScPreviewLocationData& ScPreview::GetLocationData() +{ + if ( !pLocationData ) + { + pLocationData = new ScPreviewLocationData( pDocShell->GetDocument(), this ); + bLocationValid = sal_False; + } + if ( !bLocationValid ) + { + pLocationData->Clear(); + DoPrint( pLocationData ); + bLocationValid = sal_True; + } + return *pLocationData; +} + + +void ScPreview::DataChanged(sal_Bool bNewTime) +{ + if (bNewTime) + { + aDate = Date(); + aTime = Time(); + } + + bValid = sal_False; + InvalidateLocationData( SC_HINT_DATACHANGED ); + Invalidate(); +} + + +String ScPreview::GetPosString() +{ + if (!bValid) + { + CalcPages(nTab); + UpdateDrawView(); // Tabelle evtl. geaendert + } + + String aString( ScGlobal::GetRscString( STR_PAGE ) ); + aString += ' '; + aString += String::CreateFromInt32(nPageNo+1); + + if (nTabsTested >= nTabCount) + { + aString.AppendAscii(RTL_CONSTASCII_STRINGPARAM( " / " )); + aString += String::CreateFromInt32(nTotalPages); + } + + return aString; +} + + +void ScPreview::SetZoom(sal_uInt16 nNewZoom) +{ + if (nNewZoom < 20) + nNewZoom = 20; + if (nNewZoom > 400) + nNewZoom = 400; + if (nNewZoom != nZoom) + { + nZoom = nNewZoom; + + // apply new MapMode and call UpdateScrollBars to update aOffset + + Fraction aPreviewZoom( nZoom, 100 ); + Fraction aHorPrevZoom( (long)( 100 * nZoom / pDocShell->GetOutputFactor() ), 10000 ); + MapMode aMMMode( MAP_100TH_MM, Point(), aHorPrevZoom, aPreviewZoom ); + SetMapMode( aMMMode ); + + bInPaint = sal_True; // don't scroll during SetYOffset in UpdateScrollBars + pViewShell->UpdateScrollBars(); + bInPaint = sal_False; + + bStateValid = sal_False; + InvalidateLocationData( SC_HINT_ACC_VISAREACHANGED ); + DoInvalidate(); + Invalidate(); + } +} + + +void ScPreview::SetPageNo( long nPage ) +{ + nPageNo = nPage; + RecalcPages(); + UpdateDrawView(); // Tabelle evtl. geaendert + InvalidateLocationData( SC_HINT_DATACHANGED ); + Invalidate(); +} + + +long ScPreview::GetFirstPage(SCTAB nTabP) +{ + SCTAB nDocTabCount = pDocShell->GetDocument()->GetTableCount(); + if (nTabP >= nDocTabCount) + nTabP = nDocTabCount-1; + + long nPage = 0; + if (nTabP>0) + { + CalcPages( nTabP ); + UpdateDrawView(); // Tabelle evtl. geaendert + + for (SCTAB i=0; i<nTabP; i++) + nPage += nPages[i]; + + // bei leerer Tabelle vorhergehende Seite + + if ( nPages[nTabP]==0 && nPage > 0 ) + --nPage; + } + + return nPage; +} + + +Size lcl_GetDocPageSize( ScDocument* pDoc, SCTAB nTab ) +{ + String aName = pDoc->GetPageStyle( nTab ); + ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool(); + SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aName, SFX_STYLE_FAMILY_PAGE ); + if ( pStyleSheet ) + { + SfxItemSet& rStyleSet = pStyleSheet->GetItemSet(); + return ((const SvxSizeItem&) rStyleSet.Get(ATTR_PAGE_SIZE)).GetSize(); + } + else + { + DBG_ERROR( "PageStyle not found" ); + return Size(); + } +} + + +sal_uInt16 ScPreview::GetOptimalZoom(sal_Bool bWidthOnly) +{ + double nWinScaleX = ScGlobal::nScreenPPTX / pDocShell->GetOutputFactor(); + double nWinScaleY = ScGlobal::nScreenPPTY; + Size aWinSize = GetOutputSizePixel(); + + // desired margin is 0.25cm in default MapMode (like Writer), + // but some additional margin is introduced by integer scale values + // -> add only 0.10cm, so there is some margin in all cases. + Size aMarginSize( LogicToPixel( Size( 100, 100 ), MAP_100TH_MM ) ); + aWinSize.Width() -= 2 * aMarginSize.Width(); + aWinSize.Height() -= 2 * aMarginSize.Height(); + + Size aLocalPageSize = lcl_GetDocPageSize( pDocShell->GetDocument(), nTab ); + if ( aLocalPageSize.Width() && aLocalPageSize.Height() ) + { + long nZoomX = (long) ( aWinSize.Width() * 100 / ( aLocalPageSize.Width() * nWinScaleX )); + long nZoomY = (long) ( aWinSize.Height() * 100 / ( aLocalPageSize.Height() * nWinScaleY )); + + long nOptimal = nZoomX; + if (!bWidthOnly && nZoomY<nOptimal) + nOptimal = nZoomY; + + if (nOptimal<20) + nOptimal = 20; + if (nOptimal>400) + nOptimal = 400; + + return (sal_uInt16) nOptimal; + } + else + return nZoom; +} + + +void ScPreview::SetXOffset( long nX ) +{ + if ( aOffset.X() == nX ) + return; + + if (bValid) + { + long nDif = LogicToPixel(aOffset).X() - LogicToPixel(Point(nX,0)).X(); + aOffset.X() = nX; + if (nDif && !bInPaint) + { + MapMode aOldMode = GetMapMode(); SetMapMode(MAP_PIXEL); + Scroll( nDif, 0 ); + SetMapMode(aOldMode); + } + } + else + { + aOffset.X() = nX; + if (!bInPaint) + Invalidate(); + } + InvalidateLocationData( SC_HINT_ACC_VISAREACHANGED ); + Paint(Rectangle()); +} + + +void ScPreview::SetYOffset( long nY ) +{ + if ( aOffset.Y() == nY ) + return; + + if (bValid) + { + long nDif = LogicToPixel(aOffset).Y() - LogicToPixel(Point(0,nY)).Y(); + aOffset.Y() = nY; + if (nDif && !bInPaint) + { + MapMode aOldMode = GetMapMode(); SetMapMode(MAP_PIXEL); + Scroll( 0, nDif ); + SetMapMode(aOldMode); + } + } + else + { + aOffset.Y() = nY; + if (!bInPaint) + Invalidate(); + } + InvalidateLocationData( SC_HINT_ACC_VISAREACHANGED ); + Paint(Rectangle()); +} + + +void ScPreview::DoInvalidate() +{ + // Wenn das ganze aus dem GetState der Shell gerufen wird, + // muss das Invalidate hinterher asynchron kommen... + + if (bInGetState) + Application::PostUserEvent( STATIC_LINK( this, ScPreview, InvalidateHdl ) ); + else + StaticInvalidate(); // sofort +} + +void ScPreview::StaticInvalidate() +{ + // static method, because it's called asynchronously + // -> must use current viewframe + + SfxViewFrame* pViewFrm = SfxViewFrame::Current(); + if (!pViewFrm) + return; + + SfxBindings& rBindings = pViewFrm->GetBindings(); + rBindings.Invalidate(SID_STATUS_DOCPOS); + rBindings.Invalidate(SID_STATUS_PAGESTYLE); + rBindings.Invalidate(SID_PREVIEW_PREVIOUS); + rBindings.Invalidate(SID_PREVIEW_NEXT); + rBindings.Invalidate(SID_PREVIEW_FIRST); + rBindings.Invalidate(SID_PREVIEW_LAST); + rBindings.Invalidate(SID_ATTR_ZOOM); + rBindings.Invalidate(SID_PREVIEW_ZOOMIN); + rBindings.Invalidate(SID_PREVIEW_ZOOMOUT); + rBindings.Invalidate(SID_PREVIEW_SCALINGFACTOR); + rBindings.Invalidate(SID_ATTR_ZOOMSLIDER); +} + +IMPL_STATIC_LINK( ScPreview, InvalidateHdl, void*, EMPTYARG ) +{ + (void)pThis; // avoid warning + + StaticInvalidate(); + return 0; +} + +void ScPreview::DataChanged( const DataChangedEvent& rDCEvt ) +{ + Window::DataChanged(rDCEvt); + + if ( (rDCEvt.GetType() == DATACHANGED_PRINTER) || + (rDCEvt.GetType() == DATACHANGED_DISPLAY) || + (rDCEvt.GetType() == DATACHANGED_FONTS) || + (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) || + ((rDCEvt.GetType() == DATACHANGED_SETTINGS) && + (rDCEvt.GetFlags() & SETTINGS_STYLE)) ) + { + if ( rDCEvt.GetType() == DATACHANGED_FONTS ) + pDocShell->UpdateFontList(); + + if ( rDCEvt.GetType() == DATACHANGED_SETTINGS && + (rDCEvt.GetFlags() & SETTINGS_STYLE) ) + { + // scroll bar size may have changed + pViewShell->InvalidateBorder(); // calls OuterResizePixel + } + + Invalidate(); + InvalidateLocationData( SC_HINT_DATACHANGED ); + } +} + +//Issue51656 Add resizeable margin on page preview from maoyg +void __EXPORT ScPreview::MouseButtonDown( const MouseEvent& rMEvt ) +{ + Fraction aPreviewZoom( nZoom, 100 ); + Fraction aHorPrevZoom( (long)( 100 * nZoom / pDocShell->GetOutputFactor() ), 10000 ); + MapMode aMMMode( MAP_100TH_MM, Point(), aHorPrevZoom, aPreviewZoom ); + + aButtonDownChangePoint = PixelToLogic( rMEvt.GetPosPixel(),aMMMode ); + aButtonDownPt = PixelToLogic( rMEvt.GetPosPixel(),aMMMode ); + + CaptureMouse(); + + if( rMEvt.IsLeft() && GetPointer() == POINTER_HSIZEBAR ) + { + SetMapMode( aMMMode ); + if( bLeftRulerChange ) + { + DrawInvert( aButtonDownChangePoint.X(), POINTER_HSIZEBAR ); + bLeftRulerMove = sal_True; + bRightRulerMove = sal_False; + } + else if( bRightRulerChange ) + { + DrawInvert( aButtonDownChangePoint.X(), POINTER_HSIZEBAR ); + bLeftRulerMove = sal_False; + bRightRulerMove = sal_True; + } + } + + if( rMEvt.IsLeft() && GetPointer() == POINTER_VSIZEBAR ) + { + SetMapMode( aMMMode ); + if( bTopRulerChange ) + { + DrawInvert( aButtonDownChangePoint.Y(), POINTER_VSIZEBAR ); + bTopRulerMove = sal_True; + bBottomRulerMove = sal_False; + } + else if( bBottomRulerChange ) + { + DrawInvert( aButtonDownChangePoint.Y(), POINTER_VSIZEBAR ); + bTopRulerMove = sal_False; + bBottomRulerMove = sal_True; + } + else if( bHeaderRulerChange ) + { + DrawInvert( aButtonDownChangePoint.Y(), POINTER_VSIZEBAR ); + bHeaderRulerMove = sal_True; + bFooterRulerMove = sal_False; + } + else if( bFooterRulerChange ) + { + DrawInvert( aButtonDownChangePoint.Y(), POINTER_VSIZEBAR ); + bHeaderRulerMove = sal_False; + bFooterRulerMove = sal_True; + } + } + + if( rMEvt.IsLeft() && GetPointer() == POINTER_HSPLIT ) + { + Point aNowPt = rMEvt.GetPosPixel(); + SCCOL i = 0; + for( i = aPageArea.aStart.Col(); i<= aPageArea.aEnd.Col(); i++ ) + { + if( aNowPt.X() < nRight[i] + 2 && aNowPt.X() > nRight[i] - 2 ) + { + nColNumberButttonDown = i; + break; + } + } + if( i == aPageArea.aEnd.Col()+1 ) + return; + + SetMapMode( aMMMode ); + if( nColNumberButttonDown == aPageArea.aStart.Col() ) + DrawInvert( PixelToLogic( Point( nLeftPosition, 0 ),aMMMode ).X() ,POINTER_HSPLIT ); + else + DrawInvert( PixelToLogic( Point( nRight[ nColNumberButttonDown-1 ], 0 ),aMMMode ).X() ,POINTER_HSPLIT ); + + DrawInvert( aButtonDownChangePoint.X(), POINTER_HSPLIT ); + bColRulerMove = sal_True; + } +} + +void __EXPORT ScPreview::MouseButtonUp( const MouseEvent& rMEvt ) +{ + Fraction aPreviewZoom( nZoom, 100 ); + Fraction aHorPrevZoom( (long)( 100 * nZoom / pDocShell->GetOutputFactor() ), 10000 ); + MapMode aMMMode( MAP_100TH_MM, Point(), aHorPrevZoom, aPreviewZoom ); + + aButtonUpPt = PixelToLogic( rMEvt.GetPosPixel(),aMMMode ); + + long nWidth = (long) lcl_GetDocPageSize(pDocShell->GetDocument(), nTab).Width(); + long nHeight = (long) lcl_GetDocPageSize(pDocShell->GetDocument(), nTab).Height(); + + if( rMEvt.IsLeft() && GetPointer() == POINTER_HSIZEBAR ) + { + SetPointer( Pointer( POINTER_ARROW ) ); + + sal_Bool bMoveRulerAction= sal_True; + + ScDocument * pDoc = pDocShell->GetDocument(); + String aOldName = pDoc->GetPageStyle( nTab ); + sal_Bool bUndo( pDoc->IsUndoEnabled() ); + ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool(); + SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aOldName, SFX_STYLE_FAMILY_PAGE ); + + if ( pStyleSheet ) + { + ScStyleSaveData aOldData; + if( bUndo ) + aOldData.InitFromStyle( pStyleSheet ); + + SfxItemSet& rStyleSet = pStyleSheet->GetItemSet(); + + SvxLRSpaceItem aLRItem = ( const SvxLRSpaceItem& ) rStyleSet.Get( ATTR_LRSPACE ); + + if(( bLeftRulerChange || bRightRulerChange ) && ( aButtonUpPt.X() <= ( 0 - aOffset.X() ) || aButtonUpPt.X() > nWidth * HMM_PER_TWIPS - aOffset.X() ) ) + { + bMoveRulerAction = sal_False; + Paint(Rectangle(0,0,10000,10000)); + } + else if( bLeftRulerChange && ( aButtonUpPt.X() / HMM_PER_TWIPS > nWidth - aLRItem.GetRight() - aOffset.X() / HMM_PER_TWIPS ) ) + { + bMoveRulerAction = sal_False; + Paint(Rectangle(0,0,10000,10000)); + } + else if( bRightRulerChange && ( aButtonUpPt.X() / HMM_PER_TWIPS < aLRItem.GetLeft() - aOffset.X() / HMM_PER_TWIPS ) ) + { + bMoveRulerAction = sal_False; + Paint(Rectangle(0,0,10000,10000)); + } + else if( aButtonDownPt.X() == aButtonUpPt.X() ) + { + bMoveRulerAction = sal_False; + DrawInvert( aButtonUpPt.X(), POINTER_HSIZEBAR ); + } + if( bMoveRulerAction ) + { + if( bLeftRulerChange && bLeftRulerMove ) + { + aLRItem.SetLeft( (long)( aButtonUpPt.X() / HMM_PER_TWIPS + aOffset.X() / HMM_PER_TWIPS )); + rStyleSet.Put( aLRItem ); + } + else if( bRightRulerChange && bRightRulerMove ) + { + aLRItem.SetRight( (long)( nWidth - aButtonUpPt.X() / HMM_PER_TWIPS - aOffset.X() / HMM_PER_TWIPS )); + rStyleSet.Put( aLRItem ); + } + + ScStyleSaveData aNewData; + aNewData.InitFromStyle( pStyleSheet ); + if( bUndo ) + { + pDocShell->GetUndoManager()->AddUndoAction( + new ScUndoModifyStyle( pDocShell, SFX_STYLE_FAMILY_PAGE, + aOldData, aNewData ) ); + } + + if ( ValidTab( nTab ) ) + { + ScPrintFunc aPrintFunc( pDocShell, this, nTab ); + aPrintFunc.UpdatePages(); + } + + Rectangle aRect(0,0,10000,10000); + Paint( aRect ); + bLeftRulerChange = sal_False; + bRightRulerChange = sal_False; + } + } + bLeftRulerMove = sal_False; + bRightRulerMove = sal_False; + } + + if( rMEvt.IsLeft() && GetPointer() == POINTER_VSIZEBAR ) + { + SetPointer( POINTER_ARROW ); + + sal_Bool bMoveRulerAction = sal_True; + if( ( bTopRulerChange || bBottomRulerChange || bHeaderRulerChange || bFooterRulerChange ) && ( aButtonUpPt.Y() <= ( 0 - aOffset.Y() ) || aButtonUpPt.Y() > nHeight * HMM_PER_TWIPS -aOffset.Y() ) ) + { + bMoveRulerAction = sal_False; + Paint( Rectangle(0,0,10000,10000) ); + } + else if( aButtonDownPt.Y() == aButtonUpPt.Y() ) + { + bMoveRulerAction = sal_False; + DrawInvert( aButtonUpPt.Y(), POINTER_VSIZEBAR ); + } + if( bMoveRulerAction ) + { + ScDocument * pDoc = pDocShell->GetDocument(); + sal_Bool bUndo( pDoc->IsUndoEnabled() ); + ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool(); + SfxStyleSheetBase* pStyleSheet = pStylePool->Find( pDoc->GetPageStyle( nTab ), SFX_STYLE_FAMILY_PAGE ); + DBG_ASSERT( pStyleSheet, "PageStyle not found" ); + if ( pStyleSheet ) + { + ScStyleSaveData aOldData; + if( bUndo ) + aOldData.InitFromStyle( pStyleSheet ); + + SfxItemSet& rStyleSet = pStyleSheet->GetItemSet(); + + SvxULSpaceItem aULItem = ( const SvxULSpaceItem&)rStyleSet.Get( ATTR_ULSPACE ); + + if( bTopRulerMove && bTopRulerChange ) + { + aULItem.SetUpperValue( (sal_uInt16)( aButtonUpPt.Y() / HMM_PER_TWIPS + aOffset.Y() / HMM_PER_TWIPS ) ); + rStyleSet.Put( aULItem ); + } + else if( bBottomRulerMove && bBottomRulerChange ) + { + aULItem.SetLowerValue( (sal_uInt16)( nHeight - aButtonUpPt.Y() / HMM_PER_TWIPS - aOffset.Y() / HMM_PER_TWIPS ) ); + rStyleSet.Put( aULItem ); + } + else if( bHeaderRulerMove && bHeaderRulerChange ) + { + const SfxPoolItem* pItem = NULL; + if ( rStyleSet.GetItemState( ATTR_PAGE_HEADERSET, sal_False, &pItem ) == SFX_ITEM_SET ) + { + SfxItemSet& pHeaderSet = ((SvxSetItem*)pItem)->GetItemSet(); + Size aHeaderSize = ((const SvxSizeItem&)pHeaderSet.Get(ATTR_PAGE_SIZE)).GetSize(); + aHeaderSize.Height() = (long)( aButtonUpPt.Y() / HMM_PER_TWIPS + aOffset.Y() / HMM_PER_TWIPS - aULItem.GetUpper()); + aHeaderSize.Height() = aHeaderSize.Height() * 100 / mnScale; + SvxSetItem aNewHeader( (const SvxSetItem&)rStyleSet.Get(ATTR_PAGE_HEADERSET) ); + aNewHeader.GetItemSet().Put( SvxSizeItem( ATTR_PAGE_SIZE, aHeaderSize ) ); + rStyleSet.Put( aNewHeader ); + } + } + else if( bFooterRulerMove && bFooterRulerChange ) + { + const SfxPoolItem* pItem = NULL; + if( rStyleSet.GetItemState( ATTR_PAGE_FOOTERSET, sal_False, &pItem ) == SFX_ITEM_SET ) + { + SfxItemSet& pFooterSet = ((SvxSetItem*)pItem)->GetItemSet(); + Size aFooterSize = ((const SvxSizeItem&)pFooterSet.Get(ATTR_PAGE_SIZE)).GetSize(); + aFooterSize.Height() = (long)( nHeight - aButtonUpPt.Y() / HMM_PER_TWIPS - aOffset.Y() / HMM_PER_TWIPS - aULItem.GetLower() ); + aFooterSize.Height() = aFooterSize.Height() * 100 / mnScale; + SvxSetItem aNewFooter( (const SvxSetItem&)rStyleSet.Get(ATTR_PAGE_FOOTERSET) ); + aNewFooter.GetItemSet().Put( SvxSizeItem( ATTR_PAGE_SIZE, aFooterSize ) ); + rStyleSet.Put( aNewFooter ); + } + } + + ScStyleSaveData aNewData; + aNewData.InitFromStyle( pStyleSheet ); + if( bUndo ) + { + pDocShell->GetUndoManager()->AddUndoAction( + new ScUndoModifyStyle( pDocShell, SFX_STYLE_FAMILY_PAGE, + aOldData, aNewData ) ); + } + + if ( ValidTab( nTab ) ) + { + ScPrintFunc aPrintFunc( pDocShell, this, nTab ); + aPrintFunc.UpdatePages(); + } + + Rectangle aRect(0,0,10000,10000); + Paint( aRect ); + bTopRulerChange = sal_False; + bBottomRulerChange = sal_False; + bHeaderRulerChange = sal_False; + bFooterRulerChange = sal_False; + } + } + bTopRulerMove = sal_False; + bBottomRulerMove = sal_False; + bHeaderRulerMove = sal_False; + bFooterRulerMove = sal_False; + } + if( rMEvt.IsLeft() && GetPointer() == POINTER_HSPLIT ) + { + SetPointer(POINTER_ARROW); + ScDocument* pDoc = pDocShell->GetDocument(); + sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); + sal_Bool bMoveRulerAction = sal_True; + if( aButtonDownPt.X() == aButtonUpPt.X() ) + { + bMoveRulerAction = sal_False; + if( nColNumberButttonDown == aPageArea.aStart.Col() ) + DrawInvert( PixelToLogic( Point( nLeftPosition, 0 ),aMMMode ).X() ,POINTER_HSPLIT ); + else + DrawInvert( PixelToLogic( Point( nRight[ nColNumberButttonDown-1 ], 0 ),aMMMode ).X() ,POINTER_HSPLIT ); + DrawInvert( aButtonUpPt.X(), POINTER_HSPLIT ); + } + if( bMoveRulerAction ) + { + long nNewColWidth = 0; + ScDocFunc aFunc(*pDocShell); + SCCOLROW nCols[2] = { nColNumberButttonDown, nColNumberButttonDown }; + + if( !bLayoutRTL ) + { + nNewColWidth = (long) ( PixelToLogic( Point( rMEvt.GetPosPixel().X() - nRight[ nColNumberButttonDown ], 0), aMMMode ).X() / HMM_PER_TWIPS ) * 100 / mnScale; + nNewColWidth += pDocShell->GetDocument()->GetColWidth( nColNumberButttonDown, nTab ); + } + else + { + + nNewColWidth = (long) ( PixelToLogic( Point( nRight[ nColNumberButttonDown ] - rMEvt.GetPosPixel().X(), 0), aMMMode ).X() / HMM_PER_TWIPS ) * 100 / mnScale; + nNewColWidth += pDocShell->GetDocument()->GetColWidth( nColNumberButttonDown, nTab ); + } + + if( nNewColWidth >= 0 ) + { + aFunc.SetWidthOrHeight( sal_True, 1,nCols, nTab, SC_SIZE_DIRECT, (sal_uInt16)nNewColWidth, sal_True, sal_True); + } + if ( ValidTab( nTab ) ) + { + ScPrintFunc aPrintFunc( pDocShell, this, nTab ); + aPrintFunc.UpdatePages(); + } + Rectangle nRect(0,0,10000,10000); + Paint( nRect ); + } + bColRulerMove = sal_False; + } + ReleaseMouse(); +} + +void __EXPORT ScPreview::MouseMove( const MouseEvent& rMEvt ) +{ + Fraction aPreviewZoom( nZoom, 100 ); + Fraction aHorPrevZoom( (long)( 100 * nZoom / pDocShell->GetOutputFactor() ), 10000 ); + MapMode aMMMode( MAP_100TH_MM, Point(), aHorPrevZoom, aPreviewZoom ); + Point aMouseMovePoint = PixelToLogic( rMEvt.GetPosPixel(), aMMMode ); + + long nLeftMargin = 0; + long nRightMargin = 0; + long nTopMargin = 0; + long nBottomMargin = 0; + Size PageSize; + + long nWidth = (long) lcl_GetDocPageSize(pDocShell->GetDocument(), nTab).Width(); + long nHeight = (long) lcl_GetDocPageSize(pDocShell->GetDocument(), nTab).Height(); + + if ( nPageNo < nTotalPages ) + { + ScPrintOptions aOptions = SC_MOD()->GetPrintOptions(); + + ScPrintFunc* pPrintFunc; + + if (bStateValid) + pPrintFunc = new ScPrintFunc( pDocShell, this, aState, &aOptions ); + else + pPrintFunc = new ScPrintFunc( pDocShell, this, nTab, nFirstAttr[nTab], nTotalPages, NULL, &aOptions ); + + nLeftMargin = (long)( pPrintFunc->GetLeftMargin() * HMM_PER_TWIPS - aOffset.X() ); + nRightMargin = (long)( pPrintFunc->GetRightMargin() * HMM_PER_TWIPS ); + nRightMargin = (long)( nWidth * HMM_PER_TWIPS - nRightMargin - aOffset.X() ); + nTopMargin = (long)( pPrintFunc->GetTopMargin() * HMM_PER_TWIPS - aOffset.Y() ); + nBottomMargin = (long)( pPrintFunc->GetBottomMargin() * HMM_PER_TWIPS ); + nBottomMargin = (long)( nHeight * HMM_PER_TWIPS - nBottomMargin - aOffset.Y() ); + if( mnScale > 0 ) + { + nHeaderHeight = (long)( nTopMargin + pPrintFunc->GetHeader().nHeight * HMM_PER_TWIPS * mnScale / 100 ); + nFooterHeight = (long)( nBottomMargin - pPrintFunc->GetFooter().nHeight * HMM_PER_TWIPS * mnScale / 100 ); + } + else + { + nHeaderHeight = (long)( nTopMargin + pPrintFunc->GetHeader().nHeight * HMM_PER_TWIPS ); + nFooterHeight = (long)( nBottomMargin - pPrintFunc->GetFooter().nHeight * HMM_PER_TWIPS ); + } + delete pPrintFunc; + } + + Point aPixPt( rMEvt.GetPosPixel() ); + Point aLeftTop = LogicToPixel( Point( nLeftMargin, -aOffset.Y() ) , aMMMode ); + Point aLeftBottom = LogicToPixel( Point( nLeftMargin ,(long)(nHeight * HMM_PER_TWIPS - aOffset.Y()) ), aMMMode ); + Point aRightTop = LogicToPixel( Point( nRightMargin, -aOffset.Y() ), aMMMode ); + Point aTopLeft = LogicToPixel( Point( -aOffset.X(), nTopMargin ), aMMMode ); + Point aTopRight = LogicToPixel( Point( (long)(nWidth * HMM_PER_TWIPS - aOffset.X()), nTopMargin ), aMMMode ); + Point aBottomLeft = LogicToPixel( Point( -aOffset.X(), nBottomMargin ), aMMMode ); + Point aHeaderLeft = LogicToPixel( Point( -aOffset.X(), nHeaderHeight ), aMMMode ); + Point aFooderLeft = LogicToPixel( Point( -aOffset.X(), nFooterHeight ), aMMMode ); + + sal_Bool bOnColRulerChange = sal_False; + + for( SCCOL i=aPageArea.aStart.Col(); i<= aPageArea.aEnd.Col(); i++ ) + { + Point aColumnTop = LogicToPixel( Point( 0, -aOffset.Y() ) ,aMMMode ); + Point aColumnBottom = LogicToPixel( Point( 0, (long)( nHeight * HMM_PER_TWIPS - aOffset.Y()) ), aMMMode ); + if( aPixPt.X() < ( nRight[i] + 2 ) && ( aPixPt.X() > ( nRight[i] - 2 ) ) && ( aPixPt.X() < aRightTop.X() ) && ( aPixPt.X() > aLeftTop.X() ) + && ( aPixPt.Y() > aColumnTop.Y() ) && ( aPixPt.Y() < aColumnBottom.Y() ) && !bLeftRulerMove && !bRightRulerMove + && !bTopRulerMove && !bBottomRulerMove && !bHeaderRulerMove && !bFooterRulerMove ) + { + bOnColRulerChange = sal_True; + if( !rMEvt.GetButtons() && GetPointer() == POINTER_HSPLIT ) + nColNumberButttonDown = i; + break; + } + } + + if( aPixPt.X() < ( aLeftTop.X() + 2 ) && aPixPt.X() > ( aLeftTop.X() - 2 ) && !bRightRulerMove ) + { + bLeftRulerChange = sal_True; + bRightRulerChange = sal_False; + } + else if( aPixPt.X() < ( aRightTop.X() + 2 ) && aPixPt.X() > ( aRightTop.X() - 2 ) && !bLeftRulerMove ) + { + bLeftRulerChange = sal_False; + bRightRulerChange = sal_True; + } + else if( aPixPt.Y() < ( aTopLeft.Y() + 2 ) && aPixPt.Y() > ( aTopLeft.Y() - 2 ) && !bBottomRulerMove && !bHeaderRulerMove && !bFooterRulerMove ) + { + bTopRulerChange = sal_True; + bBottomRulerChange = sal_False; + bHeaderRulerChange = sal_False; + bFooterRulerChange = sal_False; + } + else if( aPixPt.Y() < ( aBottomLeft.Y() + 2 ) && aPixPt.Y() > ( aBottomLeft.Y() - 2 ) && !bTopRulerMove && !bHeaderRulerMove && !bFooterRulerMove ) + { + bTopRulerChange = sal_False; + bBottomRulerChange = sal_True; + bHeaderRulerChange = sal_False; + bFooterRulerChange = sal_False; + } + else if( aPixPt.Y() < ( aHeaderLeft.Y() + 2 ) && aPixPt.Y() > ( aHeaderLeft.Y() - 2 ) && !bTopRulerMove && !bBottomRulerMove && !bFooterRulerMove ) + { + bTopRulerChange = sal_False; + bBottomRulerChange = sal_False; + bHeaderRulerChange = sal_True; + bFooterRulerChange = sal_False; + } + else if( aPixPt.Y() < ( aFooderLeft.Y() + 2 ) && aPixPt.Y() > ( aFooderLeft.Y() - 2 ) && !bTopRulerMove && !bBottomRulerMove && !bHeaderRulerMove ) + { + bTopRulerChange = sal_False; + bBottomRulerChange = sal_False; + bHeaderRulerChange = sal_False; + bFooterRulerChange = sal_True; + } + + if( bPageMargin ) + { + if(( (aPixPt.X() < ( aLeftTop.X() + 2 ) && aPixPt.X() > ( aLeftTop.X() - 2 )) || bLeftRulerMove || + ( aPixPt.X() < ( aRightTop.X() + 2 ) && aPixPt.X() > ( aRightTop.X() - 2 ) ) || bRightRulerMove || bOnColRulerChange || bColRulerMove ) + && aPixPt.Y() > aLeftTop.Y() && aPixPt.Y() < aLeftBottom.Y() ) + { + if( bOnColRulerChange || bColRulerMove ) + { + SetPointer( Pointer( POINTER_HSPLIT ) ); + if( bColRulerMove ) + { + if( aMouseMovePoint.X() > -aOffset.X() && aMouseMovePoint.X() < nWidth * HMM_PER_TWIPS - aOffset.X() ) + DragMove( aMouseMovePoint.X(), POINTER_HSPLIT ); + } + } + else + { + if( bLeftRulerChange && !bTopRulerMove && !bBottomRulerMove && !bHeaderRulerMove && !bFooterRulerMove ) + { + SetPointer( Pointer( POINTER_HSIZEBAR ) ); + if( bLeftRulerMove ) + { + if( aMouseMovePoint.X() > -aOffset.X() && aMouseMovePoint.X() < nWidth * HMM_PER_TWIPS - aOffset.X() ) + DragMove( aMouseMovePoint.X(), POINTER_HSIZEBAR ); + } + } + else if( bRightRulerChange && !bTopRulerMove && !bBottomRulerMove && !bHeaderRulerMove && !bFooterRulerMove ) + { + SetPointer( Pointer( POINTER_HSIZEBAR ) ); + if( bRightRulerMove ) + { + if( aMouseMovePoint.X() > -aOffset.X() && aMouseMovePoint.X() < nWidth * HMM_PER_TWIPS - aOffset.X() ) + DragMove( aMouseMovePoint.X(), POINTER_HSIZEBAR ); + } + } + } + } + else + { + if( ( ( aPixPt.Y() < ( aTopLeft.Y() + 2 ) && aPixPt.Y() > ( aTopLeft.Y() - 2 ) ) || bTopRulerMove || + ( aPixPt.Y() < ( aBottomLeft.Y() + 2 ) && aPixPt.Y() > ( aBottomLeft.Y() - 2 ) ) || bBottomRulerMove || + ( aPixPt.Y() < ( aHeaderLeft.Y() + 2 ) && aPixPt.Y() > ( aHeaderLeft.Y() - 2 ) ) || bHeaderRulerMove || + ( aPixPt.Y() < ( aFooderLeft.Y() + 2 ) && aPixPt.Y() > ( aFooderLeft.Y() - 2 ) ) || bFooterRulerMove ) + && aPixPt.X() > aTopLeft.X() && aPixPt.X() < aTopRight.X() ) + { + if( bTopRulerChange ) + { + SetPointer( Pointer( POINTER_VSIZEBAR ) ); + if( bTopRulerMove ) + { + if( aMouseMovePoint.Y() > -aOffset.Y() && aMouseMovePoint.Y() < nHeight * HMM_PER_TWIPS - aOffset.Y() ) + DragMove( aMouseMovePoint.Y(), POINTER_VSIZEBAR ); + } + } + else if( bBottomRulerChange ) + { + SetPointer( Pointer( POINTER_VSIZEBAR ) ); + if( bBottomRulerMove ) + { + if( aMouseMovePoint.Y() > -aOffset.Y() && aMouseMovePoint.Y() < nHeight * HMM_PER_TWIPS - aOffset.Y() ) + DragMove( aMouseMovePoint.Y(), POINTER_VSIZEBAR ); + } + } + else if( bHeaderRulerChange ) + { + SetPointer( Pointer( POINTER_VSIZEBAR ) ); + if( bHeaderRulerMove ) + { + if( aMouseMovePoint.Y() > -aOffset.Y() && aMouseMovePoint.Y() < nHeight * HMM_PER_TWIPS - aOffset.Y() ) + DragMove( aMouseMovePoint.Y(), POINTER_VSIZEBAR ); + } + } + else if( bFooterRulerChange ) + { + SetPointer( Pointer( POINTER_VSIZEBAR ) ); + if( bFooterRulerMove ) + { + if( aMouseMovePoint.Y() > -aOffset.Y() && aMouseMovePoint.Y() < nHeight * HMM_PER_TWIPS - aOffset.Y() ) + DragMove( aMouseMovePoint.Y(), POINTER_VSIZEBAR ); + } + } + } + else + SetPointer( Pointer( POINTER_ARROW ) ); + } + } +} +//Issue51656 Add resizeable margin on page preview from maoyg +void ScPreview::InvalidateLocationData(sal_uLong nId) +{ + bLocationValid = sal_False; + if (pViewShell->HasAccessibilityObjects()) + pViewShell->BroadcastAccessibility( SfxSimpleHint( nId ) ); +} + +void ScPreview::GetFocus() +{ + if (pViewShell->HasAccessibilityObjects()) + pViewShell->BroadcastAccessibility( ScAccWinFocusGotHint(GetAccessible()) ); +} + +void ScPreview::LoseFocus() +{ + if (pViewShell->HasAccessibilityObjects()) + pViewShell->BroadcastAccessibility( ScAccWinFocusLostHint(GetAccessible()) ); +} + +com::sun::star::uno::Reference<com::sun::star::accessibility::XAccessible> ScPreview::CreateAccessible() +{ + ScAccessibleDocumentPagePreview* pAccessible = + new ScAccessibleDocumentPagePreview( GetAccessibleParentWindow()->GetAccessible(), pViewShell ); + com::sun::star::uno::Reference < com::sun::star::accessibility::XAccessible > xAccessible = pAccessible; + pAccessible->Init(); + return xAccessible; +} + +//Issue51656 Add resizeable margin on page preview from maoyg +void ScPreview::DragMove( long nDragMovePos, sal_uInt16 nFlags ) +{ + Fraction aPreviewZoom( nZoom, 100 ); + Fraction aHorPrevZoom( (long)( 100 * nZoom / pDocShell->GetOutputFactor() ), 10000 ); + MapMode aMMMode( MAP_100TH_MM, Point(), aHorPrevZoom, aPreviewZoom ); + SetMapMode( aMMMode ); + long nPos = nDragMovePos; + if( nFlags == POINTER_HSIZEBAR || nFlags == POINTER_HSPLIT ) + { + if( nDragMovePos != aButtonDownChangePoint.X() ) + { + DrawInvert( aButtonDownChangePoint.X(), nFlags ); + aButtonDownChangePoint.X() = nPos; + DrawInvert( aButtonDownChangePoint.X(), nFlags ); + } + } + else if( nFlags == POINTER_VSIZEBAR ) + { + if( nDragMovePos != aButtonDownChangePoint.Y() ) + { + DrawInvert( aButtonDownChangePoint.Y(), nFlags ); + aButtonDownChangePoint.Y() = nPos; + DrawInvert( aButtonDownChangePoint.Y(), nFlags ); + } + } +} + +void ScPreview::DrawInvert( long nDragPos, sal_uInt16 nFlags ) +{ + long nHeight = (long) lcl_GetDocPageSize( pDocShell->GetDocument(), nTab ).Height(); + long nWidth = (long) lcl_GetDocPageSize( pDocShell->GetDocument(), nTab ).Width(); + if( nFlags == POINTER_HSIZEBAR || nFlags == POINTER_HSPLIT ) + { + Rectangle aRect( nDragPos, -aOffset.Y(), nDragPos + 1,(long)( ( nHeight * HMM_PER_TWIPS ) - aOffset.Y())); + Invert( aRect,INVERT_50 ); + } + else if( nFlags == POINTER_VSIZEBAR ) + { + Rectangle aRect( -aOffset.X(), nDragPos,(long)( ( nWidth * HMM_PER_TWIPS ) - aOffset.X() ), nDragPos + 1 ); + Invert( aRect,INVERT_50 ); + } +} +//Issue51656 Add resizeable margin on page preview from maoyg diff --git a/sc/source/ui/view/prevloc.cxx b/sc/source/ui/view/prevloc.cxx new file mode 100644 index 000000000000..fb72bedd0999 --- /dev/null +++ b/sc/source/ui/view/prevloc.cxx @@ -0,0 +1,792 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include <vcl/outdev.hxx> +#include <tools/debug.hxx> + +#include "prevloc.hxx" +#include "document.hxx" + +//================================================================== + +enum ScPreviewLocationType +{ + SC_PLOC_CELLRANGE, + SC_PLOC_COLHEADER, + SC_PLOC_ROWHEADER, + SC_PLOC_LEFTHEADER, + SC_PLOC_RIGHTHEADER, + SC_PLOC_LEFTFOOTER, + SC_PLOC_RIGHTFOOTER, + SC_PLOC_NOTEMARK, + SC_PLOC_NOTETEXT +}; + +struct ScPreviewLocationEntry +{ + ScPreviewLocationType eType; + Rectangle aPixelRect; + ScRange aCellRange; + sal_Bool bRepeatCol; + sal_Bool bRepeatRow; + + ScPreviewLocationEntry( ScPreviewLocationType eNewType, const Rectangle& rPixel, const ScRange& rRange, + sal_Bool bRepCol, sal_Bool bRepRow ) : + eType( eNewType ), + aPixelRect( rPixel ), + aCellRange( rRange ), + bRepeatCol( bRepCol ), + bRepeatRow( bRepRow ) + { + } +}; + +//================================================================== + +ScPreviewTableInfo::ScPreviewTableInfo() : + nTab(0), + nCols(0), + nRows(0), + pColInfo(NULL), + pRowInfo(NULL) +{ +} + +ScPreviewTableInfo::~ScPreviewTableInfo() +{ + delete[] pColInfo; + delete[] pRowInfo; +} + +void ScPreviewTableInfo::SetTab( SCTAB nNewTab ) +{ + nTab = nNewTab; +} + +void ScPreviewTableInfo::SetColInfo( SCCOL nCount, ScPreviewColRowInfo* pNewInfo ) +{ + delete[] pColInfo; + pColInfo = pNewInfo; + nCols = nCount; +} + +void ScPreviewTableInfo::SetRowInfo( SCROW nCount, ScPreviewColRowInfo* pNewInfo ) +{ + delete[] pRowInfo; + pRowInfo = pNewInfo; + nRows = nCount; +} + +void ScPreviewTableInfo::LimitToArea( const Rectangle& rPixelArea ) +{ + if ( pColInfo ) + { + // cells completely left of the visible area + SCCOL nStart = 0; + while ( nStart < nCols && pColInfo[nStart].nPixelEnd < rPixelArea.Left() ) + ++nStart; + + // cells completely right of the visible area + SCCOL nEnd = nCols; + while ( nEnd > 0 && pColInfo[nEnd-1].nPixelStart > rPixelArea.Right() ) + --nEnd; + + if ( nStart > 0 || nEnd < nCols ) + { + if ( nEnd > nStart ) + { + SCCOL nNewCount = nEnd - nStart; + ScPreviewColRowInfo* pNewInfo = new ScPreviewColRowInfo[nNewCount]; + for (SCCOL i=0; i<nNewCount; i++) + pNewInfo[i] = pColInfo[nStart + i]; + SetColInfo( nNewCount, pNewInfo ); + } + else + SetColInfo( 0, NULL ); // all invisible + } + } + + if ( pRowInfo ) + { + // cells completely above the visible area + SCROW nStart = 0; + while ( nStart < nRows && pRowInfo[nStart].nPixelEnd < rPixelArea.Top() ) + ++nStart; + + // cells completely below the visible area + SCROW nEnd = nRows; + while ( nEnd > 0 && pRowInfo[nEnd-1].nPixelStart > rPixelArea.Bottom() ) + --nEnd; + + if ( nStart > 0 || nEnd < nRows ) + { + if ( nEnd > nStart ) + { + SCROW nNewCount = nEnd - nStart; + ScPreviewColRowInfo* pNewInfo = new ScPreviewColRowInfo[nNewCount]; + for (SCROW i=0; i<nNewCount; i++) + pNewInfo[i] = pRowInfo[nStart + i]; + SetRowInfo( nNewCount, pNewInfo ); + } + else + SetRowInfo( 0, NULL ); // all invisible + } + } +} + +//------------------------------------------------------------------ + +ScPreviewLocationData::ScPreviewLocationData( ScDocument* pDocument, OutputDevice* pWin ) : + pWindow( pWin ), + pDoc( pDocument ), + nDrawRanges( 0 ), + nPrintTab( 0 ) +{ +} + +ScPreviewLocationData::~ScPreviewLocationData() +{ + Clear(); +} + +void ScPreviewLocationData::SetCellMapMode( const MapMode& rMapMode ) +{ + aCellMapMode = rMapMode; +} + +void ScPreviewLocationData::SetPrintTab( SCTAB nNew ) +{ + nPrintTab = nNew; +} + +void ScPreviewLocationData::Clear() +{ + void* pEntry = aEntries.First(); + while ( pEntry ) + { + delete (ScPreviewLocationEntry*) pEntry; + pEntry = aEntries.Next(); + } + aEntries.Clear(); + + nDrawRanges = 0; +} + +void ScPreviewLocationData::AddCellRange( const Rectangle& rRect, const ScRange& rRange, sal_Bool bRepCol, sal_Bool bRepRow, + const MapMode& rDrawMap ) +{ + Rectangle aPixelRect( pWindow->LogicToPixel( rRect ) ); + aEntries.Insert( new ScPreviewLocationEntry( SC_PLOC_CELLRANGE, aPixelRect, rRange, bRepCol, bRepRow ) ); + + DBG_ASSERT( nDrawRanges < SC_PREVIEW_MAXRANGES, "too many ranges" ); + if ( nDrawRanges < SC_PREVIEW_MAXRANGES ) + { + aDrawRectangle[nDrawRanges] = aPixelRect; + aDrawMapMode[nDrawRanges] = rDrawMap; + if (bRepCol) + if (bRepRow) + aDrawRangeId[nDrawRanges] = SC_PREVIEW_RANGE_EDGE; + else + aDrawRangeId[nDrawRanges] = SC_PREVIEW_RANGE_REPCOL; + else + if (bRepRow) + aDrawRangeId[nDrawRanges] = SC_PREVIEW_RANGE_REPROW; + else + aDrawRangeId[nDrawRanges] = SC_PREVIEW_RANGE_TAB; + ++nDrawRanges; + } +} + +void ScPreviewLocationData::AddColHeaders( const Rectangle& rRect, SCCOL nStartCol, SCCOL nEndCol, sal_Bool bRepCol ) +{ + SCTAB nTab = 0; //! ? + ScRange aRange( nStartCol, 0, nTab, nEndCol, 0, nTab ); + Rectangle aPixelRect( pWindow->LogicToPixel( rRect ) ); + aEntries.Insert( new ScPreviewLocationEntry( SC_PLOC_COLHEADER, aPixelRect, aRange, bRepCol, sal_False ) ); +} + +void ScPreviewLocationData::AddRowHeaders( const Rectangle& rRect, SCROW nStartRow, SCROW nEndRow, sal_Bool bRepRow ) +{ + SCTAB nTab = 0; //! ? + ScRange aRange( 0, nStartRow, nTab, 0, nEndRow, nTab ); + Rectangle aPixelRect( pWindow->LogicToPixel( rRect ) ); + aEntries.Insert( new ScPreviewLocationEntry( SC_PLOC_ROWHEADER, aPixelRect, aRange, sal_False, bRepRow ) ); +} + +void ScPreviewLocationData::AddHeaderFooter( const Rectangle& rRect, sal_Bool bHeader, sal_Bool bLeft ) +{ + ScRange aRange; //! ? + Rectangle aPixelRect( pWindow->LogicToPixel( rRect ) ); + + ScPreviewLocationType eType = bHeader ? + ( bLeft ? SC_PLOC_LEFTHEADER : SC_PLOC_RIGHTHEADER ) : + ( bLeft ? SC_PLOC_LEFTFOOTER : SC_PLOC_RIGHTFOOTER ); + aEntries.Insert( new ScPreviewLocationEntry( eType, aPixelRect, aRange, sal_False, sal_False ) ); +} + +void ScPreviewLocationData::AddNoteMark( const Rectangle& rRect, const ScAddress& rPos ) +{ + ScRange aRange( rPos ); + Rectangle aPixelRect( pWindow->LogicToPixel( rRect ) ); + aEntries.Insert( new ScPreviewLocationEntry( SC_PLOC_NOTEMARK, aPixelRect, aRange, sal_False, sal_False ) ); +} + +void ScPreviewLocationData::AddNoteText( const Rectangle& rRect, const ScAddress& rPos ) +{ + ScRange aRange( rPos ); + Rectangle aPixelRect( pWindow->LogicToPixel( rRect ) ); + aEntries.Insert( new ScPreviewLocationEntry( SC_PLOC_NOTETEXT, aPixelRect, aRange, sal_False, sal_False ) ); +} + +//------------------------------------------------------------------ + +void ScPreviewLocationData::GetDrawRange( sal_uInt16 nPos, Rectangle& rPixelRect, MapMode& rMapMode, sal_uInt8& rRangeId ) const +{ + DBG_ASSERT( nPos < nDrawRanges, "wrong position" ); + if ( nPos < nDrawRanges ) + { + rPixelRect = aDrawRectangle[nPos]; + rMapMode = aDrawMapMode[nPos]; + rRangeId = aDrawRangeId[nPos]; + } +} + +ScPreviewLocationEntry* lcl_GetEntryByAddress( const List& rEntries, const ScAddress& rPos, ScPreviewLocationType eType ) +{ + sal_uLong nCount = rEntries.Count(); + for (sal_uLong nListPos=0; nListPos<nCount; nListPos++) + { + ScPreviewLocationEntry* pEntry = (ScPreviewLocationEntry*)rEntries.GetObject(nListPos); + if ( pEntry->eType == eType && pEntry->aCellRange.In( rPos ) ) + return pEntry; + } + return NULL; +} + +//UNUSED2008-05 ScAddress ScPreviewLocationData::GetCellFromRange( const Size& rOffsetPixel, const ScRange& rRange ) const +//UNUSED2008-05 { +//UNUSED2008-05 const double nScaleX = HMM_PER_TWIPS; +//UNUSED2008-05 const double nScaleY = HMM_PER_TWIPS; +//UNUSED2008-05 +//UNUSED2008-05 Size aOffsetLogic = pWindow->PixelToLogic( rOffsetPixel, aCellMapMode ); +//UNUSED2008-05 SCTAB nTab = rRange.aStart.Tab(); +//UNUSED2008-05 +//UNUSED2008-05 long nPosX = 0; +//UNUSED2008-05 SCCOL nCol = rRange.aStart.Col(); +//UNUSED2008-05 SCCOL nEndCol = rRange.aEnd.Col(); +//UNUSED2008-05 while ( nCol <= nEndCol && nPosX < aOffsetLogic.Width() ) +//UNUSED2008-05 { +//UNUSED2008-05 sal_uInt16 nDocW = pDoc->GetColWidth( nCol, nTab ); +//UNUSED2008-05 if (nDocW) +//UNUSED2008-05 nPosX += (long) (nDocW * nScaleX); +//UNUSED2008-05 ++nCol; +//UNUSED2008-05 } +//UNUSED2008-05 if ( nCol > rRange.aStart.Col() ) +//UNUSED2008-05 --nCol; +//UNUSED2008-05 +//UNUSED2008-05 long nPosY = 0; +//UNUSED2008-05 ScCoupledCompressedArrayIterator< SCROW, sal_uInt8, sal_uInt16> aIter( +//UNUSED2008-05 pDoc->GetRowFlagsArray( nTab), rRange.aStart.Row(), +//UNUSED2008-05 rRange.aEnd.Row(), CR_HIDDEN, 0, pDoc->GetRowHeightArray( nTab)); +//UNUSED2008-05 while ( aIter && nPosY < aOffsetLogic.Height() ) +//UNUSED2008-05 { +//UNUSED2008-05 sal_uInt16 nDocH = *aIter; +//UNUSED2008-05 if (nDocH) +//UNUSED2008-05 nPosY += (long) (nDocH * nScaleY); +//UNUSED2008-05 ++aIter; +//UNUSED2008-05 } +//UNUSED2008-05 SCROW nRow = aIter.GetPos(); +//UNUSED2008-05 if ( nRow > rRange.aStart.Row() ) +//UNUSED2008-05 --nRow; +//UNUSED2008-05 +//UNUSED2008-05 return ScAddress( nCol, nRow, nTab ); +//UNUSED2008-05 } + +Rectangle ScPreviewLocationData::GetOffsetPixel( const ScAddress& rCellPos, const ScRange& rRange ) const +{ + const double nScaleX = HMM_PER_TWIPS; + const double nScaleY = HMM_PER_TWIPS; + SCTAB nTab = rRange.aStart.Tab(); + + long nPosX = 0; + SCCOL nEndCol = rCellPos.Col(); + for (SCCOL nCol = rRange.aStart.Col(); nCol < nEndCol; nCol++) + { + sal_uInt16 nDocW = pDoc->GetColWidth( nCol, nTab ); + if (nDocW) + nPosX += (long) (nDocW * nScaleX); + } + long nSizeX = (long) ( pDoc->GetColWidth( nEndCol, nTab ) * nScaleX ); + + SCROW nEndRow = rCellPos.Row(); + long nPosY = (long) pDoc->GetScaledRowHeight( rRange.aStart.Row(), + nEndRow, nTab, nScaleY); + long nSizeY = (long) ( pDoc->GetRowHeight( nEndRow, nTab ) * nScaleY ); + + Size aOffsetLogic( nPosX, nPosY ); + Size aSizeLogic( nSizeX, nSizeY ); + Size aOffsetPixel = pWindow->LogicToPixel( aOffsetLogic, aCellMapMode ); + Size aSizePixel = pWindow->LogicToPixel( aSizeLogic, aCellMapMode ); + + return Rectangle( Point( aOffsetPixel.Width(), aOffsetPixel.Height() ), aSizePixel ); +} + +sal_Bool ScPreviewLocationData::GetCellPosition( const ScAddress& rCellPos, Rectangle& rCellRect ) const +{ + ScPreviewLocationEntry* pEntry = lcl_GetEntryByAddress( aEntries, rCellPos, SC_PLOC_CELLRANGE ); + if ( pEntry ) + { + Rectangle aOffsetRect = GetOffsetPixel( rCellPos, pEntry->aCellRange ); + rCellRect = Rectangle( aOffsetRect.Left() + pEntry->aPixelRect.Left(), + aOffsetRect.Top() + pEntry->aPixelRect.Top(), + aOffsetRect.Right() + pEntry->aPixelRect.Left(), + aOffsetRect.Bottom() + pEntry->aPixelRect.Top() ); + return sal_True; + } + return sal_False; +} + +sal_Bool ScPreviewLocationData::HasCellsInRange( const Rectangle& rVisiblePixel ) const +{ + sal_uLong nCount = aEntries.Count(); + for (sal_uLong nListPos=0; nListPos<nCount; nListPos++) + { + ScPreviewLocationEntry* pEntry = (ScPreviewLocationEntry*)aEntries.GetObject(nListPos); + ScPreviewLocationType eType = pEntry->eType; + if ( eType == SC_PLOC_CELLRANGE || eType == SC_PLOC_COLHEADER || eType == SC_PLOC_ROWHEADER ) + if ( pEntry->aPixelRect.IsOver( rVisiblePixel ) ) + return sal_True; + } + return sal_False; +} + +sal_Bool ScPreviewLocationData::GetHeaderPosition( Rectangle& rRect ) const +{ + sal_uLong nCount = aEntries.Count(); + for (sal_uLong nListPos=0; nListPos<nCount; nListPos++) + { + ScPreviewLocationEntry* pEntry = (ScPreviewLocationEntry*)aEntries.GetObject(nListPos); + if ( pEntry->eType == SC_PLOC_LEFTHEADER || pEntry->eType == SC_PLOC_RIGHTHEADER ) + { + rRect = pEntry->aPixelRect; + return sal_True; + } + } + return sal_False; +} + +sal_Bool ScPreviewLocationData::GetFooterPosition( Rectangle& rRect ) const +{ + sal_uLong nCount = aEntries.Count(); + for (sal_uLong nListPos=0; nListPos<nCount; nListPos++) + { + ScPreviewLocationEntry* pEntry = (ScPreviewLocationEntry*)aEntries.GetObject(nListPos); + if ( pEntry->eType == SC_PLOC_LEFTFOOTER || pEntry->eType == SC_PLOC_RIGHTFOOTER ) + { + rRect = pEntry->aPixelRect; + return sal_True; + } + } + return sal_False; +} + +sal_Bool ScPreviewLocationData::IsHeaderLeft() const +{ + sal_uLong nCount = aEntries.Count(); + for (sal_uLong nListPos=0; nListPos<nCount; nListPos++) + { + ScPreviewLocationEntry* pEntry = (ScPreviewLocationEntry*)aEntries.GetObject(nListPos); + if ( pEntry->eType == SC_PLOC_LEFTHEADER ) + return sal_True; + if ( pEntry->eType == SC_PLOC_RIGHTHEADER ) + return sal_False; + } + return sal_False; +} + +sal_Bool ScPreviewLocationData::IsFooterLeft() const +{ + sal_uLong nCount = aEntries.Count(); + for (sal_uLong nListPos=0; nListPos<nCount; nListPos++) + { + ScPreviewLocationEntry* pEntry = (ScPreviewLocationEntry*)aEntries.GetObject(nListPos); + if ( pEntry->eType == SC_PLOC_LEFTFOOTER ) + return sal_True; + if ( pEntry->eType == SC_PLOC_RIGHTFOOTER ) + return sal_False; + } + return sal_False; +} + +long ScPreviewLocationData::GetNoteCountInRange( const Rectangle& rVisiblePixel, sal_Bool bNoteMarks ) const +{ + ScPreviewLocationType eType = bNoteMarks ? SC_PLOC_NOTEMARK : SC_PLOC_NOTETEXT; + + sal_uLong nRet = 0; + sal_uLong nCount = aEntries.Count(); + for (sal_uLong nListPos=0; nListPos<nCount; nListPos++) + { + ScPreviewLocationEntry* pEntry = (ScPreviewLocationEntry*)aEntries.GetObject(nListPos); + if ( pEntry->eType == eType && pEntry->aPixelRect.IsOver( rVisiblePixel ) ) + ++nRet; + } + return nRet; +} + +sal_Bool ScPreviewLocationData::GetNoteInRange( const Rectangle& rVisiblePixel, long nIndex, sal_Bool bNoteMarks, + ScAddress& rCellPos, Rectangle& rNoteRect ) const +{ + ScPreviewLocationType eType = bNoteMarks ? SC_PLOC_NOTEMARK : SC_PLOC_NOTETEXT; + + sal_uLong nPos = 0; + sal_uLong nCount = aEntries.Count(); + for (sal_uLong nListPos=0; nListPos<nCount; nListPos++) + { + ScPreviewLocationEntry* pEntry = (ScPreviewLocationEntry*)aEntries.GetObject(nListPos); + if ( pEntry->eType == eType && pEntry->aPixelRect.IsOver( rVisiblePixel ) ) + { + if ( nPos == sal::static_int_cast<sal_uLong>(nIndex) ) + { + rCellPos = pEntry->aCellRange.aStart; + rNoteRect = pEntry->aPixelRect; + return sal_True; + } + ++nPos; + } + } + return sal_False; +} + +Rectangle ScPreviewLocationData::GetNoteInRangeOutputRect(const Rectangle& rVisiblePixel, sal_Bool bNoteMarks, const ScAddress& aCellPos) const +{ + ScPreviewLocationType eType = bNoteMarks ? SC_PLOC_NOTEMARK : SC_PLOC_NOTETEXT; + + sal_uLong nPos = 0; + sal_uLong nCount = aEntries.Count(); + for (sal_uLong nListPos=0; nListPos<nCount; nListPos++) + { + ScPreviewLocationEntry* pEntry = (ScPreviewLocationEntry*)aEntries.GetObject(nListPos); + if ( pEntry->eType == eType && pEntry->aPixelRect.IsOver( rVisiblePixel ) ) + { + if ( aCellPos == pEntry->aCellRange.aStart ) + return pEntry->aPixelRect; + ++nPos; + } + } + return Rectangle(); +} + +void ScPreviewLocationData::GetTableInfo( const Rectangle& rVisiblePixel, ScPreviewTableInfo& rInfo ) const +{ + const double nScaleX = HMM_PER_TWIPS; + const double nScaleY = HMM_PER_TWIPS; + + // from left to right: + sal_Bool bHasHeaderCol = sal_False; + sal_Bool bHasRepCols = sal_False; + sal_Bool bHasMainCols = sal_False; + SCCOL nRepeatColStart = 0; + SCCOL nRepeatColEnd = 0; + SCCOL nMainColStart = 0; + SCCOL nMainColEnd = 0; + + // from top to bottom: + sal_Bool bHasHeaderRow = sal_False; + sal_Bool bHasRepRows = sal_False; + sal_Bool bHasMainRows = sal_False; + SCROW nRepeatRowStart = 0; + SCROW nRepeatRowEnd = 0; + SCROW nMainRowStart = 0; + SCROW nMainRowEnd = 0; + + Rectangle aHeaderRect, aRepeatRect, aMainRect; + SCTAB nTab = 0; + + sal_uLong nCount = aEntries.Count(); + for (sal_uLong nListPos=0; nListPos<nCount; nListPos++) + { + ScPreviewLocationEntry* pEntry = (ScPreviewLocationEntry*)aEntries.GetObject(nListPos); + if ( pEntry->eType == SC_PLOC_CELLRANGE ) + { + if ( pEntry->bRepeatCol ) + { + bHasRepCols = sal_True; + nRepeatColStart = pEntry->aCellRange.aStart.Col(); + nRepeatColEnd = pEntry->aCellRange.aEnd.Col(); + aRepeatRect.Left() = pEntry->aPixelRect.Left(); + aRepeatRect.Right() = pEntry->aPixelRect.Right(); + } + else + { + bHasMainCols = sal_True; + nMainColStart = pEntry->aCellRange.aStart.Col(); + nMainColEnd = pEntry->aCellRange.aEnd.Col(); + aMainRect.Left() = pEntry->aPixelRect.Left(); + aMainRect.Right() = pEntry->aPixelRect.Right(); + } + if ( pEntry->bRepeatRow ) + { + bHasRepRows = sal_True; + nRepeatRowStart = pEntry->aCellRange.aStart.Row(); + nRepeatRowEnd = pEntry->aCellRange.aEnd.Row(); + aRepeatRect.Top() = pEntry->aPixelRect.Top(); + aRepeatRect.Bottom() = pEntry->aPixelRect.Bottom(); + } + else + { + bHasMainRows = sal_True; + nMainRowStart = pEntry->aCellRange.aStart.Row(); + nMainRowEnd = pEntry->aCellRange.aEnd.Row(); + aMainRect.Top() = pEntry->aPixelRect.Top(); + aMainRect.Bottom() = pEntry->aPixelRect.Bottom(); + } + nTab = pEntry->aCellRange.aStart.Tab(); //! store separately? + } + else if ( pEntry->eType == SC_PLOC_ROWHEADER ) + { + // row headers result in an additional column + bHasHeaderCol = sal_True; + aHeaderRect.Left() = pEntry->aPixelRect.Left(); + aHeaderRect.Right() = pEntry->aPixelRect.Right(); + } + else if ( pEntry->eType == SC_PLOC_COLHEADER ) + { + // column headers result in an additional row + bHasHeaderRow = sal_True; + aHeaderRect.Top() = pEntry->aPixelRect.Top(); + aHeaderRect.Bottom() = pEntry->aPixelRect.Bottom(); + } + } + + // + // get column info + // + + SCCOL nColCount = 0; + SCCOL nCol; + if ( bHasHeaderCol ) + ++nColCount; + if ( bHasRepCols ) + for ( nCol=nRepeatColStart; nCol<=nRepeatColEnd; nCol++ ) + if (!pDoc->ColHidden(nCol, nTab)) + ++nColCount; + if ( bHasMainCols ) + for ( nCol=nMainColStart; nCol<=nMainColEnd; nCol++ ) + if (!pDoc->ColHidden(nCol, nTab)) + ++nColCount; + + if ( nColCount > 0 ) + { + ScPreviewColRowInfo* pColInfo = new ScPreviewColRowInfo[ nColCount ]; + SCCOL nColPos = 0; + + if ( bHasHeaderCol ) + { + pColInfo[nColPos].Set( sal_True, 0, aHeaderRect.Left(), aHeaderRect.Right() ); + ++nColPos; + } + if ( bHasRepCols ) + { + long nPosX = 0; + for ( nCol=nRepeatColStart; nCol<=nRepeatColEnd; nCol++ ) + if (!pDoc->ColHidden(nCol, nTab)) + { + sal_uInt16 nDocW = pDoc->GetColWidth( nCol, nTab ); + long nNextX = nPosX + (long) (nDocW * nScaleX); + + long nPixelStart = pWindow->LogicToPixel( Size( nPosX, 0 ), aCellMapMode ).Width(); + long nPixelEnd = pWindow->LogicToPixel( Size( nNextX, 0 ), aCellMapMode ).Width() - 1; + pColInfo[nColPos].Set( sal_False, nCol, + aRepeatRect.Left() + nPixelStart, + aRepeatRect.Left() + nPixelEnd ); + + nPosX = nNextX; + ++nColPos; + } + } + if ( bHasMainCols ) + { + long nPosX = 0; + for ( nCol=nMainColStart; nCol<=nMainColEnd; nCol++ ) + if (!pDoc->ColHidden(nCol, nTab)) + { + sal_uInt16 nDocW = pDoc->GetColWidth( nCol, nTab ); + long nNextX = nPosX + (long) (nDocW * nScaleX); + + long nPixelStart = pWindow->LogicToPixel( Size( nPosX, 0 ), aCellMapMode ).Width(); + long nPixelEnd = pWindow->LogicToPixel( Size( nNextX, 0 ), aCellMapMode ).Width() - 1; + pColInfo[nColPos].Set( sal_False, nCol, + aMainRect.Left() + nPixelStart, + aMainRect.Left() + nPixelEnd ); + + nPosX = nNextX; + ++nColPos; + } + } + rInfo.SetColInfo( nColCount, pColInfo ); + } + else + rInfo.SetColInfo( 0, NULL ); + + // + // get row info + // + + SCROW nRowCount = 0; + if ( bHasHeaderRow ) + ++nRowCount; + if ( bHasRepRows ) + nRowCount += pDoc->CountVisibleRows(nRepeatRowStart, nRepeatRowEnd, nTab); + if ( bHasMainRows ) + nRowCount += pDoc->CountVisibleRows(nMainRowStart, nMainRowEnd, nTab); + + if ( nRowCount > 0 ) + { + ScPreviewColRowInfo* pRowInfo = new ScPreviewColRowInfo[ nRowCount ]; + SCROW nRowPos = 0; + + if ( bHasHeaderRow ) + { + pRowInfo[nRowPos].Set( sal_True, 0, aHeaderRect.Top(), aHeaderRect.Bottom() ); + ++nRowPos; + } + if ( bHasRepRows ) + { + long nPosY = 0; + for (SCROW nRow = nRepeatRowStart; nRow <= nRepeatRowEnd; ++nRow) + { + if (pDoc->RowHidden(nRow, nTab)) + continue; + + sal_uInt16 nDocH = pDoc->GetOriginalHeight( nRow, nTab ); + long nNextY = nPosY + (long) (nDocH * nScaleY); + + long nPixelStart = pWindow->LogicToPixel( Size( 0, nPosY ), aCellMapMode ).Height(); + long nPixelEnd = pWindow->LogicToPixel( Size( 0, nNextY ), aCellMapMode ).Height() - 1; + pRowInfo[nRowPos].Set( sal_False, nRow, + aRepeatRect.Top() + nPixelStart, + aRepeatRect.Top() + nPixelEnd ); + + nPosY = nNextY; + ++nRowPos; + } + } + if ( bHasMainRows ) + { + long nPosY = 0; + for (SCROW nRow = nMainRowStart; nRow <= nMainRowEnd; ++nRow) + { + if (pDoc->RowHidden(nRow, nTab)) + continue; + + sal_uInt16 nDocH = pDoc->GetOriginalHeight( nRow, nTab ); + long nNextY = nPosY + (long) (nDocH * nScaleY); + + long nPixelStart = pWindow->LogicToPixel( Size( 0, nPosY ), aCellMapMode ).Height(); + long nPixelEnd = pWindow->LogicToPixel( Size( 0, nNextY ), aCellMapMode ).Height() - 1; + pRowInfo[nRowPos].Set( sal_False, nRow, + aMainRect.Top() + nPixelStart, + aMainRect.Top() + nPixelEnd ); + + nPosY = nNextY; + ++nRowPos; + } + } + rInfo.SetRowInfo( nRowCount, pRowInfo ); + } + else + rInfo.SetRowInfo( 0, NULL ); + + // + // limit to visible area + // + + rInfo.SetTab( nTab ); + rInfo.LimitToArea( rVisiblePixel ); +} + +Rectangle ScPreviewLocationData::GetHeaderCellOutputRect(const Rectangle& rVisRect, const ScAddress& rCellPos, sal_Bool bColHeader) const +{ + // first a stupid implementation + // NN says here should be done more + Rectangle aClipRect; + ScPreviewTableInfo aTableInfo; + GetTableInfo( rVisRect, aTableInfo ); + + if ( (rCellPos.Col() >= 0) && + (rCellPos.Row() >= 0) && (rCellPos.Col() < aTableInfo.GetCols()) && + (rCellPos.Row() < aTableInfo.GetRows()) ) + { + SCCOL nCol(0); + SCROW nRow(0); + if (bColHeader) + nCol = rCellPos.Col(); + else + nRow = rCellPos.Row(); + const ScPreviewColRowInfo& rColInfo = aTableInfo.GetColInfo()[nCol]; + const ScPreviewColRowInfo& rRowInfo = aTableInfo.GetRowInfo()[nRow]; + + if ( rColInfo.bIsHeader || rRowInfo.bIsHeader ) + aClipRect = Rectangle( rColInfo.nPixelStart, rRowInfo.nPixelStart, rColInfo.nPixelEnd, rRowInfo.nPixelEnd ); + } + return aClipRect; +} + +Rectangle ScPreviewLocationData::GetCellOutputRect(const ScAddress& rCellPos) const +{ + // first a stupid implementation + // NN says here should be done more + Rectangle aRect; + GetCellPosition(rCellPos, aRect); + return aRect; +} + +// GetMainCellRange is used for links in PDF export + +sal_Bool ScPreviewLocationData::GetMainCellRange( ScRange& rRange, Rectangle& rPixRect ) const +{ + sal_uLong nCount = aEntries.Count(); + for (sal_uLong nListPos=0; nListPos<nCount; nListPos++) + { + ScPreviewLocationEntry* pEntry = (ScPreviewLocationEntry*)aEntries.GetObject(nListPos); + if ( pEntry->eType == SC_PLOC_CELLRANGE && !pEntry->bRepeatCol && !pEntry->bRepeatRow ) + { + rRange = pEntry->aCellRange; + rPixRect = pEntry->aPixelRect; + return sal_True; + } + } + return sal_False; // not found +} + diff --git a/sc/source/ui/view/prevwsh.cxx b/sc/source/ui/view/prevwsh.cxx new file mode 100644 index 000000000000..da4d4dfa28d7 --- /dev/null +++ b/sc/source/ui/view/prevwsh.cxx @@ -0,0 +1,1145 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include "scitems.hxx" +#include <editeng/eeitem.hxx> + +#include <sfx2/app.hxx> +#include <editeng/sizeitem.hxx> +#include <svl/srchitem.hxx> +#include <svx/zoomslideritem.hxx> +#include <svx/svdview.hxx> +//CHINA001 #include <svx/zoom.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/objface.hxx> +#include <sfx2/request.hxx> +#include <svl/stritem.hxx> +#include <svl/whiter.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/help.hxx> +#include <tools/urlobj.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/printer.hxx> + +#ifndef _SVX_ZOOMSLIDERITEM_HXX +#include <svx/zoomslideritem.hxx> +#endif +#include "prevwsh.hxx" +#include "preview.hxx" +#include "printfun.hxx" +#include "attrib.hxx" +#include "scmod.hxx" +#include "inputhdl.hxx" +#include "docsh.hxx" +#include "tabvwsh.hxx" +#include "stlpool.hxx" +#include "editutil.hxx" +#include "scresid.hxx" +#include "globstr.hrc" +#include "sc.hrc" +#include "ViewSettingsSequenceDefines.hxx" +#include "tpprint.hxx" +#include "printopt.hxx" +#include <xmloff/xmluconv.hxx> +#include <rtl/ustrbuf.hxx> + +#include <svx/svxdlg.hxx> //CHINA001 +#include <svx/dialogs.hrc> //CHINA001 + +#ifndef _SVX_ZOOM_HXX +#include <svx/zoom_def.hxx> +#endif + +#include "sc.hrc" //CHINA001 +#include "scabstdlg.hxx" //CHINA001 +// fuer Rad-Maus +#define SC_DELTA_ZOOM 10 +#define MINZOOM_SLIDER 10 +#define MAXZOOM_SLIDER 400 + +#define SC_USERDATA_SEP ';' + +using namespace com::sun::star; + +// ----------------------------------------------------------------------- + +#define ScPreviewShell +#include "scslots.hxx" + +TYPEINIT1( ScPreviewShell, SfxViewShell ); + +SFX_IMPL_INTERFACE( ScPreviewShell, SfxViewShell, ScResId(SCSTR_PREVIEWSHELL) ) +{ + SFX_OBJECTBAR_REGISTRATION(SFX_OBJECTBAR_OBJECT|SFX_VISIBILITY_STANDARD| + SFX_VISIBILITY_SERVER|SFX_VISIBILITY_READONLYDOC, + ScResId(RID_OBJECTBAR_PREVIEW)); + SFX_POPUPMENU_REGISTRATION(ScResId(RID_POPUP_PREVIEW)); +} + +SFX_IMPL_NAMED_VIEWFACTORY( ScPreviewShell, "PrintPreview" ) +{ + SFX_VIEW_REGISTRATION(ScDocShell); +} + +//------------------------------------------------------------------ + +void ScPreviewShell::Construct( Window* pParent ) +{ + eZoom = SVX_ZOOM_WHOLEPAGE; + + pCorner = new ScrollBarBox( pParent, WB_SIZEABLE ); + + pHorScroll = new ScrollBar(pParent, WB_HSCROLL ); + pVerScroll = new ScrollBar(pParent, WB_VSCROLL); + + // SSA: --- RTL --- no mirroring for horizontal scrollbars + pHorScroll->EnableRTL( sal_False ); + + pHorScroll->SetEndScrollHdl( LINK( this, ScPreviewShell, ScrollHandler ) ); + pVerScroll->SetEndScrollHdl( LINK( this, ScPreviewShell, ScrollHandler ) ); + + pPreview = new ScPreview( pParent, pDocShell, this ); + + SetPool( &SC_MOD()->GetPool() ); + SetWindow( pPreview ); + StartListening(*pDocShell,sal_True); + StartListening(*SFX_APP(),sal_True); // #i62045# #i62046# application is needed for Calc's own hints + SfxBroadcaster* pDrawBC = pDocShell->GetDocument()->GetDrawBroadcaster(); + if (pDrawBC) + StartListening(*pDrawBC); + + pHorScroll->Show(); + pVerScroll->Show(); + pCorner->Show(); + SetHelpId( HID_SCSHELL_PREVWSH ); + SetName(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Preview"))); +} + +ScPreviewShell::ScPreviewShell( SfxViewFrame* pViewFrame, + SfxViewShell* pOldSh ) : + SfxViewShell( pViewFrame, SFX_VIEW_CAN_PRINT | SFX_VIEW_HAS_PRINTOPTIONS ), + pDocShell( (ScDocShell*)pViewFrame->GetObjectShell() ), + nSourceDesignMode( SC_FORCEMODE_NONE ), + pAccessibilityBroadcaster( NULL ) +{ + Construct( &pViewFrame->GetWindow() ); + + if ( pOldSh && pOldSh->ISA( ScTabViewShell ) ) + { + // store view settings, show table from TabView + //! store live ScViewData instead, and update on ScTablesHint? + //! or completely forget aSourceData on ScTablesHint? + + ScTabViewShell* pTabViewShell = ((ScTabViewShell*)pOldSh); + ScViewData* pData = pTabViewShell->GetViewData(); + pData->WriteUserDataSequence( aSourceData ); + InitStartTable( pData->GetTabNo() ); + + // #106334# also have to store the TabView's DesignMode state + // (only if draw view exists) + SdrView* pDrawView = pTabViewShell->GetSdrView(); + if ( pDrawView ) + nSourceDesignMode = pDrawView->IsDesignMode(); + } +} + +__EXPORT ScPreviewShell::~ScPreviewShell() +{ + // #108333#; notify Accessibility that Shell is dying and before destroy all + BroadcastAccessibility( SfxSimpleHint( SFX_HINT_DYING ) ); + DELETEZ(pAccessibilityBroadcaster); + + SfxBroadcaster* pDrawBC = pDocShell->GetDocument()->GetDrawBroadcaster(); + if (pDrawBC) + EndListening(*pDrawBC); + EndListening(*SFX_APP()); + EndListening(*pDocShell); + + SetWindow(0); + delete pPreview; + delete pHorScroll; + delete pVerScroll; + delete pCorner; + + // #97612# normal mode of operation is switching back to default view in the same frame, + // so there's no need to activate any other window here anymore +} + +void ScPreviewShell::InitStartTable(SCTAB nTab) +{ + pPreview->SetPageNo( pPreview->GetFirstPage(nTab) ); +} + +//------------------------------------------------------------------ + +String __EXPORT ScPreviewShell::GetDescription() const +{ + return String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(" ** Test ** ")); +} + +Size __EXPORT ScPreviewShell::GetOptimalSizePixel() const +{ + Size aOptSize(100,100); + + ScTabViewShell* pViewSh = pDocShell->GetBestViewShell(); + + if ( pViewSh ) + { + ScViewData* pViewData = pViewSh->GetViewData(); + SCTAB nCurTab = pViewData->GetTabNo(); + ScDocument* pDoc = pDocShell->GetDocument(); + ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool(); + SfxStyleSheetBase* pStyleSheet = pStylePool->Find( + pDoc->GetPageStyle( nCurTab ), + SFX_STYLE_FAMILY_PAGE ); + + DBG_ASSERT( pStyleSheet, "PageStyle not found :-/" ); + + if ( pStyleSheet ) + { + const SfxItemSet& rSet = pStyleSheet->GetItemSet(); + const SvxSizeItem& rItem = (const SvxSizeItem&)rSet.Get( ATTR_PAGE_SIZE ); + const Size& rPageSize = rItem.GetSize(); + + aOptSize.Width() = (long) (rPageSize.Width() * pViewData->GetPPTX()); + aOptSize.Height() = (long) (rPageSize.Height() * pViewData->GetPPTY()); + } + } + else + { + DBG_ERROR( "TabViewShell not found :-/" ); + } + + return aOptSize; +} + +void __EXPORT ScPreviewShell::AdjustPosSizePixel( const Point &rPos, const Size &rSize ) +{ + long nBarW = GetViewFrame()->GetWindow().GetSettings().GetStyleSettings().GetScrollBarSize(); + long nBarH = nBarW; +// long nBarW = pVerScroll->GetSizePixel().Width(); +// long nBarH = pHorScroll->GetSizePixel().Height(); + + Size aOutSize( rSize.Width()-nBarW, rSize.Height()-nBarH ); + pPreview->SetPosSizePixel( rPos, aOutSize ); + pHorScroll->SetPosSizePixel( Point( rPos.X(), rPos.Y() + aOutSize.Height() ), + Size( aOutSize.Width(), nBarH ) ); + pVerScroll->SetPosSizePixel( Point( rPos.X() + aOutSize.Width(), rPos.Y() ), + Size( nBarW, aOutSize.Height() ) ); + pCorner->SetPosSizePixel( Point( rPos.X() + aOutSize.Width(), rPos.Y() + aOutSize.Height() ), + Size( nBarW, nBarH ) ); + + if ( SVX_ZOOM_WHOLEPAGE == eZoom ) + pPreview->SetZoom( pPreview->GetOptimalZoom(sal_False) ); + else if ( SVX_ZOOM_PAGEWIDTH == eZoom ) + pPreview->SetZoom( pPreview->GetOptimalZoom(sal_True) ); + + UpdateScrollBars(); +} + +void __EXPORT ScPreviewShell::InnerResizePixel( const Point &rOfs, const Size &rSize ) +{ + AdjustPosSizePixel( rOfs,rSize ); +} + +void __EXPORT ScPreviewShell::OuterResizePixel( const Point &rOfs, const Size &rSize ) +{ + AdjustPosSizePixel( rOfs,rSize ); +} + +void ScPreviewShell::UpdateScrollBars() +{ + ScDocument* pDoc = pDocShell->GetDocument(); + SCTAB nTab = pPreview->GetTab(); + + ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool(); + SfxStyleSheetBase* pStyleSheet = pStylePool->Find( pDoc->GetPageStyle( nTab ), + SFX_STYLE_FAMILY_PAGE ); + DBG_ASSERT(pStyleSheet,"StyleSheet nicht gefunden"); + if (!pStyleSheet) return; + const SfxItemSet* pParamSet = &pStyleSheet->GetItemSet(); + + Size aPageSize = ((const SvxSizeItem&) pParamSet->Get(ATTR_PAGE_SIZE)).GetSize(); + aPageSize.Width() = (long) (aPageSize.Width() * HMM_PER_TWIPS ); + aPageSize.Height() = (long) (aPageSize.Height() * HMM_PER_TWIPS ); + + // for centering, page size without the shadow is used + + Size aWindowSize = pPreview->GetOutputSize(); + + Point aOfs = pPreview->GetOffset(); + long nMaxPos; + + if( pHorScroll ) + { + pHorScroll->SetRange( Range( 0, aPageSize.Width() ) ); + pHorScroll->SetLineSize( aWindowSize.Width() / 16 ); + pHorScroll->SetPageSize( aWindowSize.Width() ); + pHorScroll->SetVisibleSize( aWindowSize.Width() ); + nMaxPos = aPageSize.Width() - aWindowSize.Width(); + if ( nMaxPos<0 ) + { + // page smaller than window -> center (but put scrollbar to 0) + aOfs.X() = 0; + pPreview->SetXOffset( nMaxPos / 2 ); + } + else if (aOfs.X() < 0) + { + // page larger than window -> never use negative offset + aOfs.X() = 0; + pPreview->SetXOffset( 0 ); + } + else if (aOfs.X() > nMaxPos) + { + // limit offset to align with right edge of window + aOfs.X() = nMaxPos; + pPreview->SetXOffset(nMaxPos); + } + pHorScroll->SetThumbPos( aOfs.X() ); + } + + if( pVerScroll ) + { + long nPageNo = pPreview->GetPageNo(); + long nTotalPages = pPreview->GetTotalPages(); + + nMaxVertPos = aPageSize.Height() - aWindowSize.Height(); + pVerScroll->SetLineSize( aWindowSize.Height() / 16 ); + pVerScroll->SetPageSize( aWindowSize.Height() ); + pVerScroll->SetVisibleSize( aWindowSize.Height() ); + if ( nMaxVertPos < 0 ) + { + // page smaller than window -> center (but put scrollbar to 0) + aOfs.Y() = 0; + pPreview->SetYOffset( nMaxVertPos / 2 ); + pVerScroll->SetThumbPos( nPageNo * aWindowSize.Height() ); + pVerScroll->SetRange( Range( 0, aWindowSize.Height() * nTotalPages )); + } + else if (aOfs.Y() < 0) + { + // page larger than window -> never use negative offset + pVerScroll->SetRange( Range( 0, aPageSize.Height() ) ); + aOfs.Y() = 0; + pPreview->SetYOffset( 0 ); + pVerScroll->SetThumbPos( aOfs.Y() ); + } + else if (aOfs.Y() > nMaxVertPos ) + { + // limit offset to align with window bottom + pVerScroll->SetRange( Range( 0, aPageSize.Height() ) ); + aOfs.Y() = nMaxVertPos; + pPreview->SetYOffset( nMaxVertPos ); + pVerScroll->SetThumbPos( aOfs.Y() ); + } + } +} + +IMPL_LINK (ScPreviewShell,ScrollHandler, ScrollBar* ,pScroll ) +{ + long nPos = pScroll->GetThumbPos(); + long nDelta = pScroll->GetDelta(); + long nMaxRange = pScroll->GetRangeMax(); + long nTotalPages = pPreview->GetTotalPages(); + long nPageNo = 0; + long nPerPageLength = 0; + sal_Bool bIsDivide = sal_True; + + if( nTotalPages ) + nPerPageLength = nMaxRange / nTotalPages; + + if( nPerPageLength ) + { + nPageNo = nPos / nPerPageLength; + if( nPos % nPerPageLength ) + { + bIsDivide = sal_False; + nPageNo ++; + } + } + + sal_Bool bHoriz = ( pScroll == pHorScroll ); + + if( bHoriz ) + pPreview->SetXOffset( nPos ); + else + { + if( nMaxVertPos > 0 ) + pPreview->SetYOffset( nPos ); + else + { + Point aMousePos = pScroll->OutputToNormalizedScreenPixel( pScroll->GetPointerPosPixel() ); + Point aPos = pScroll->GetParent()->OutputToNormalizedScreenPixel( pScroll->GetPosPixel() ); + String aHelpStr; + Rectangle aRect; + sal_uInt16 nAlign; + + if( nDelta < 0 ) + { + if ( nTotalPages && nPageNo > 0 && !bIsDivide ) + pPreview->SetPageNo( nPageNo-1 ); + if( bIsDivide ) + pPreview->SetPageNo( nPageNo ); + + aHelpStr = ScGlobal::GetRscString( STR_PAGE ); + aHelpStr += ' '; + aHelpStr += String::CreateFromInt32( nPageNo ); + + aHelpStr.AppendAscii(RTL_CONSTASCII_STRINGPARAM( " / " )); + aHelpStr += String::CreateFromInt32( nTotalPages ); + } + else if( nDelta > 0 ) + { + sal_Bool bAllTested = pPreview->AllTested(); + if ( nTotalPages && ( nPageNo < nTotalPages || !bAllTested ) ) + pPreview->SetPageNo( nPageNo ); + + aHelpStr = ScGlobal::GetRscString( STR_PAGE ); + aHelpStr += ' '; + aHelpStr += String::CreateFromInt32( nPageNo+1 ); + + aHelpStr.AppendAscii(RTL_CONSTASCII_STRINGPARAM( " / " )); + aHelpStr += String::CreateFromInt32( nTotalPages ); + } + + aRect.Left() = aPos.X() - 8; + aRect.Top() = aMousePos.Y(); + aRect.Right() = aRect.Left(); + aRect.Top() = aRect.Top(); + nAlign = QUICKHELP_BOTTOM|QUICKHELP_CENTER; + Help::ShowQuickHelp( pScroll->GetParent(), aRect, aHelpStr, nAlign ); + } + } + + return 0; +} + +sal_Bool ScPreviewShell::ScrollCommand( const CommandEvent& rCEvt ) +{ + sal_Bool bDone = sal_False; + const CommandWheelData* pData = rCEvt.GetWheelData(); + if ( pData && pData->GetMode() == COMMAND_WHEEL_ZOOM ) + { + long nOld = pPreview->GetZoom(); + long nNew = nOld; + if ( pData->GetDelta() < 0 ) + nNew = Max( (long) MINZOOM, (long)( nOld - SC_DELTA_ZOOM ) ); + else + nNew = Min( (long) MAXZOOM, (long)( nOld + SC_DELTA_ZOOM ) ); + + if ( nNew != nOld ) + { + eZoom = SVX_ZOOM_PERCENT; + pPreview->SetZoom( (sal_uInt16)nNew ); + } + + bDone = sal_True; + } + else + { + bDone = pPreview->HandleScrollCommand( rCEvt, pHorScroll, pVerScroll ); + } + + return bDone; +} + +SfxPrinter* __EXPORT ScPreviewShell::GetPrinter( sal_Bool bCreate ) +{ + return pDocShell->GetPrinter(bCreate); +} + +sal_uInt16 __EXPORT ScPreviewShell::SetPrinter( SfxPrinter *pNewPrinter, sal_uInt16 nDiffFlags, bool ) +{ + return pDocShell->SetPrinter( pNewPrinter, nDiffFlags ); +} + +SfxTabPage* ScPreviewShell::CreatePrintOptionsPage( Window *pParent, const SfxItemSet &rOptions ) +{ + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + //CHINA001 return ScTpPrintOptions::Create( pParent, rOptions ); + ::CreateTabPage ScTpPrintOptionsCreate = pFact->GetTabPageCreatorFunc( RID_SCPAGE_PRINT ); + if ( ScTpPrintOptionsCreate ) + return (*ScTpPrintOptionsCreate)( pParent, rOptions); + return 0; +} + +//------------------------------------------------------------------------ + +void __EXPORT ScPreviewShell::Activate(sal_Bool bMDI) +{ + SfxViewShell::Activate(bMDI); + + //! Basic etc. -> auslagern in eigene Datei (s. tabvwsh4) + + if (bMDI) + { + // InputHdl ist jetzt meistens Null, keine Assertion mehr! + ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl(); + if ( pInputHdl ) + pInputHdl->NotifyChange( NULL ); + } +} + +void __EXPORT ScPreviewShell::Deactivate(sal_Bool bMDI) +{ + SfxViewShell::Deactivate(bMDI); + + if (bMDI) + { + } +} + +//------------------------------------------------------------------------ + +void __EXPORT ScPreviewShell::Execute( SfxRequest& rReq ) +{ + sal_uInt16 nSlot = rReq.GetSlot(); + const SfxItemSet* pReqArgs = rReq.GetArgs(); + + switch ( nSlot ) + { + case SID_FORMATPAGE: + case SID_STATUS_PAGESTYLE: + case SID_HFEDIT: + pDocShell->ExecutePageStyle( *this, rReq, pPreview->GetTab() ); + break; + case SID_REPAINT: + pPreview->Invalidate(); + rReq.Done(); + break; + case SID_PREV_TABLE: // Accelerator + case SID_PREVIEW_PREVIOUS: + { + long nPage = pPreview->GetPageNo(); + long nTotal = pPreview->GetTotalPages(); + if (nTotal && nPage > 0) + pPreview->SetPageNo( nPage-1 ); + } + break; + case SID_NEXT_TABLE: // Accelerator + case SID_PREVIEW_NEXT: + { + sal_Bool bAllTested = pPreview->AllTested(); + long nPage = pPreview->GetPageNo(); + long nTotal = pPreview->GetTotalPages(); + if (nTotal && (nPage+1 < nTotal || !bAllTested)) + pPreview->SetPageNo( nPage+1 ); + } + break; + case SID_CURSORTOPOFFILE: // Accelerator + case SID_PREVIEW_FIRST: + { + long nPage = pPreview->GetPageNo(); + long nTotal = pPreview->GetTotalPages(); + if (nTotal && nPage != 0) + pPreview->SetPageNo( 0 ); + } + break; + case SID_CURSORENDOFFILE: // Accelerator + case SID_PREVIEW_LAST: + { + if (!pPreview->AllTested()) + pPreview->CalcAll(); + + long nPage = pPreview->GetPageNo(); + long nTotal = pPreview->GetTotalPages(); + if (nTotal && nPage+1 != nTotal) + pPreview->SetPageNo( nTotal-1 ); + } + break; + case SID_ATTR_ZOOM: + case FID_SCALE: + { + sal_uInt16 nZoom = 100; + sal_Bool bCancel = sal_False; + + eZoom = SVX_ZOOM_PERCENT; + + if ( pReqArgs ) + { + + const SvxZoomItem& rZoomItem = (const SvxZoomItem&) + pReqArgs->Get(SID_ATTR_ZOOM); + + eZoom = rZoomItem.GetType(); + nZoom = rZoomItem.GetValue(); + } + else + { + SfxItemSet aSet ( GetPool(), SID_ATTR_ZOOM, SID_ATTR_ZOOM ); + SvxZoomItem aZoomItem( SVX_ZOOM_PERCENT, pPreview->GetZoom(), SID_ATTR_ZOOM ); + + aSet.Put( aZoomItem ); + //CHINA001 SvxZoomDialog* pDlg = pDlg = new SvxZoomDialog( NULL, aSet ); + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + if(pFact) + { + AbstractSvxZoomDialog* pDlg = pFact->CreateSvxZoomDialog(NULL, aSet); + DBG_ASSERT(pDlg, "Dialogdiet fail!");//CHINA001 + pDlg->SetLimits( 20, 400 ); + pDlg->HideButton( ZOOMBTN_OPTIMAL ); + bCancel = ( RET_CANCEL == pDlg->Execute() ); + + if ( !bCancel ) + { + const SvxZoomItem& rZoomItem = (const SvxZoomItem&) + pDlg->GetOutputItemSet()-> + Get( SID_ATTR_ZOOM ); + + eZoom = rZoomItem.GetType(); + nZoom = rZoomItem.GetValue(); + } + + delete pDlg; + } + } + + if ( !bCancel ) + { + switch ( eZoom ) + { + case SVX_ZOOM_OPTIMAL: + case SVX_ZOOM_WHOLEPAGE: + nZoom = pPreview->GetOptimalZoom(sal_False); + break; + case SVX_ZOOM_PAGEWIDTH: + nZoom = pPreview->GetOptimalZoom(sal_True); + break; + default: + { + // added to avoid warnings + } + } + + pPreview->SetZoom( nZoom ); + rReq.Done(); + } + } + break; + case SID_PREVIEW_ZOOMIN: + { + sal_uInt16 nNew = pPreview->GetZoom() + 20 ; + nNew -= nNew % 20; + pPreview->SetZoom( nNew ); + eZoom = SVX_ZOOM_PERCENT; + rReq.Done(); + } + break; + case SID_PREVIEW_ZOOMOUT: + { + sal_uInt16 nNew = pPreview->GetZoom() - 1; + nNew -= nNew % 20; + pPreview->SetZoom( nNew ); + eZoom = SVX_ZOOM_PERCENT; + rReq.Done(); + } + break; + case SID_PREVIEW_MARGIN: + { + sal_Bool bMargin = pPreview->GetPageMargins(); + pPreview->SetPageMargins( !bMargin ); + pPreview->Invalidate(); + rReq.Done(); + } + break; + case SID_ATTR_ZOOMSLIDER: + { + const SfxPoolItem* pItem; + eZoom = SVX_ZOOM_PERCENT; + if( pReqArgs && SFX_ITEM_SET == pReqArgs->GetItemState( SID_ATTR_ZOOMSLIDER, sal_True, &pItem ) ) + { + const sal_uInt16 nCurrentZoom = ((const SvxZoomSliderItem*)pItem)->GetValue(); + if( nCurrentZoom ) + { + pPreview->SetZoom( nCurrentZoom ); + rReq.Done(); + } + } + } + break; + case SID_PREVIEW_SCALINGFACTOR: + { + const SfxPoolItem* pItem; + SCTAB nTab = pPreview->GetTab(); + String aOldName = pDocShell->GetDocument()->GetPageStyle( pPreview->GetTab() ); + ScStyleSheetPool* pStylePool = pDocShell->GetDocument()->GetStyleSheetPool(); + SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aOldName, SFX_STYLE_FAMILY_PAGE ); + DBG_ASSERT( pStyleSheet, "PageStyle not found! :-/" ); + + if ( pReqArgs && pStyleSheet && SFX_ITEM_SET == pReqArgs->GetItemState( SID_PREVIEW_SCALINGFACTOR, sal_True, &pItem ) ) + { + const sal_uInt16 nCurrentZoom = ((const SvxZoomSliderItem *)pItem)->GetValue(); + SfxItemSet& rSet = pStyleSheet->GetItemSet(); + rSet.Put( SfxUInt16Item( ATTR_PAGE_SCALE, nCurrentZoom ) ); + ScPrintFunc aPrintFunc( pDocShell, pDocShell->GetPrinter(), nTab ); + aPrintFunc.UpdatePages(); + rReq.Done(); + } + GetViewFrame()->GetBindings().Invalidate( nSlot ); + } + break; + case SID_PRINTPREVIEW: + case SID_PREVIEW_CLOSE: + // print preview is now always in the same frame as the tab view + // -> always switch this frame back to normal view + // (ScTabViewShell ctor reads stored view data) + + GetViewFrame()->GetDispatcher()->Execute( SID_VIEWSHELL0, SFX_CALLMODE_ASYNCHRON ); + break; + case SID_CURSORPAGEUP: + case SID_CURSORPAGEDOWN: + case SID_CURSORHOME: + case SID_CURSOREND: + case SID_CURSORUP: + case SID_CURSORDOWN: + case SID_CURSORLEFT: + case SID_CURSORRIGHT: + DoScroll( nSlot ); + break; + case SID_CANCEL: + if( ScViewUtil::IsFullScreen( *this ) ) + ScViewUtil::SetFullScreen( *this, false ); + break; + + default: + break; + } +} + +void __EXPORT ScPreviewShell::GetState( SfxItemSet& rSet ) +{ + pPreview->SetInGetState(sal_True); + + SCTAB nTab = pPreview->GetTab(); + long nPage = pPreview->GetPageNo(); + long nTotal = pPreview->GetTotalPages(); + sal_uInt16 nZoom = pPreview->GetZoom(); + sal_Bool bAllTested = pPreview->AllTested(); + + SfxWhichIter aIter(rSet); + sal_uInt16 nWhich = aIter.FirstWhich(); + while ( nWhich ) + { + switch (nWhich) + { + case SID_STATUS_PAGESTYLE: + case SID_HFEDIT: + pDocShell->GetStatePageStyle( *this, rSet, nTab ); + break; + case SID_UNDO: + case SID_REDO: + case SID_REPEAT: + rSet.DisableItem(nWhich); + break; + case SID_PREVIEW_PREVIOUS: + case SID_PREVIEW_FIRST: + if (!nTotal || nPage==0) + rSet.DisableItem(nWhich); + break; + case SID_PREVIEW_NEXT: + case SID_PREVIEW_LAST: + if (bAllTested) + if (!nTotal || nPage==nTotal-1) + rSet.DisableItem(nWhich); + break; + case SID_PREVIEW_ZOOMIN: + if (nZoom >= 400) + rSet.DisableItem(nWhich); + break; + case SID_PREVIEW_ZOOMOUT: + if (nZoom <= 20) + rSet.DisableItem(nWhich); + break; + case SID_ATTR_ZOOM: + { + SvxZoomItem aZoom( eZoom, nZoom, nWhich ); + aZoom.SetValueSet( SVX_ZOOM_ENABLE_ALL & ~SVX_ZOOM_ENABLE_OPTIMAL ); + rSet.Put( aZoom ); + } + break; + case SID_ATTR_ZOOMSLIDER: + { + SvxZoomSliderItem aZoomSliderItem( nZoom, MINZOOM, MAXZOOM, SID_ATTR_ZOOMSLIDER ); + aZoomSliderItem.AddSnappingPoint( 100 ); + rSet.Put( aZoomSliderItem ); + } + break; + case SID_PREVIEW_SCALINGFACTOR: + { + if( pDocShell->IsReadOnly() ) + rSet.DisableItem( nWhich ); + else + { + String aOldName = pDocShell->GetDocument()->GetPageStyle( pPreview->GetTab() ); + ScStyleSheetPool* pStylePool = pDocShell->GetDocument()->GetStyleSheetPool(); + SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aOldName, SFX_STYLE_FAMILY_PAGE ); + DBG_ASSERT( pStyleSheet, "PageStyle not found! :-/" ); + + if ( pStyleSheet ) + { + SfxItemSet& rStyleSet = pStyleSheet->GetItemSet(); + sal_uInt16 nCurrentZoom = ((const SfxUInt16Item&)rStyleSet.Get(ATTR_PAGE_SCALE)).GetValue(); + if( nCurrentZoom ) + { + SvxZoomSliderItem aZoomSliderItem( nCurrentZoom, MINZOOM_SLIDER, MAXZOOM_SLIDER, SID_PREVIEW_SCALINGFACTOR ); + aZoomSliderItem.AddSnappingPoint( 100 ); + rSet.Put( aZoomSliderItem ); + } + else + rSet.DisableItem( nWhich ); + } + } + } + break; + case SID_STATUS_DOCPOS: + rSet.Put( SfxStringItem( nWhich, pPreview->GetPosString() ) ); + break; + case SID_PRINTPREVIEW: + rSet.Put( SfxBoolItem( nWhich, sal_True ) ); + break; + case SID_FORMATPAGE: + case SID_PREVIEW_MARGIN: + if( pDocShell->IsReadOnly() ) + rSet.DisableItem( nWhich ); + break; + } + + nWhich = aIter.NextWhich(); + } + + pPreview->SetInGetState(sal_False); +} + +void ScPreviewShell::FillFieldData( ScHeaderFieldData& rData ) +{ + ScDocument* pDoc = pDocShell->GetDocument(); + SCTAB nTab = pPreview->GetTab(); + pDoc->GetName( nTab, rData.aTabName ); + + rData.aTitle = pDocShell->GetTitle(); + const INetURLObject& rURLObj = pDocShell->GetMedium()->GetURLObject(); + rData.aLongDocName = rURLObj.GetMainURL( INetURLObject::DECODE_UNAMBIGUOUS ); + if ( rData.aLongDocName.Len() ) + rData.aShortDocName = rURLObj.GetName( INetURLObject::DECODE_UNAMBIGUOUS ); + else + rData.aShortDocName = rData.aLongDocName = rData.aTitle; + rData.nPageNo = pPreview->GetPageNo() + 1; + + sal_Bool bAllTested = pPreview->AllTested(); + if (bAllTested) + rData.nTotalPages = pPreview->GetTotalPages(); + else + rData.nTotalPages = 99; + + // eNumType kennt der Dialog selber +} + +void __EXPORT ScPreviewShell::WriteUserData(String& rData, sal_Bool /* bBrowse */) +{ + // nZoom + // nPageNo + + rData = String::CreateFromInt32(pPreview->GetZoom()); + rData += (sal_Unicode) SC_USERDATA_SEP; + rData += String::CreateFromInt32(pPreview->GetPageNo()); +} + +void __EXPORT ScPreviewShell::ReadUserData(const String& rData, sal_Bool /* bBrowse */) +{ + xub_StrLen nCount = rData.GetTokenCount(); + if (nCount) + { + xub_StrLen nIndex = 0; + pPreview->SetZoom((sal_uInt16)rData.GetToken( 0, SC_USERDATA_SEP, nIndex ).ToInt32()); + pPreview->SetPageNo(rData.GetToken( 0, SC_USERDATA_SEP, nIndex ).ToInt32()); + eZoom = SVX_ZOOM_PERCENT; + } +} + +void __EXPORT ScPreviewShell::WriteUserDataSequence(uno::Sequence < beans::PropertyValue >& rSeq, sal_Bool /* bBrowse */) +{ + rSeq.realloc(3); + beans::PropertyValue* pSeq = rSeq.getArray(); + if(pSeq) + { + sal_uInt16 nViewID(GetViewFrame()->GetCurViewId()); + pSeq[0].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_VIEWID)); + rtl::OUStringBuffer sBuffer(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_VIEW))); + SvXMLUnitConverter::convertNumber(sBuffer, static_cast<sal_Int32>(nViewID)); + pSeq[0].Value <<= sBuffer.makeStringAndClear(); + pSeq[1].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_ZOOMVALUE)); + pSeq[1].Value <<= sal_Int32 (pPreview->GetZoom()); + pSeq[2].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("PageNumber")); + pSeq[2].Value <<= pPreview->GetPageNo(); + } +} + +void __EXPORT ScPreviewShell::ReadUserDataSequence(const uno::Sequence < beans::PropertyValue >& rSeq, sal_Bool /* bBrowse */) +{ + sal_Int32 nCount(rSeq.getLength()); + if (nCount) + { + sal_Int32 nTemp = 0; + const beans::PropertyValue* pSeq = rSeq.getConstArray(); + if(pSeq) + { + for(sal_Int32 i = 0; i < nCount; i++, pSeq++) + { + rtl::OUString sName(pSeq->Name); + if(sName.compareToAscii(SC_ZOOMVALUE) == 0) + { + if (pSeq->Value >>= nTemp) + pPreview->SetZoom(sal_uInt16(nTemp)); + } + else if (sName.compareToAscii("PageNumber") == 0) + { + if (pSeq->Value >>= nTemp) + pPreview->SetPageNo(nTemp); + } + } + } + } +} + +void ScPreviewShell::DoScroll( sal_uInt16 nMode ) +{ + Point aCurPos, aPrevPos; + + long nHRange = pHorScroll->GetRange().Max(); + long nHLine = pHorScroll->GetLineSize(); + long nHPage = pHorScroll->GetPageSize(); + long nVRange = pVerScroll->GetRange().Max(); + long nVLine = pVerScroll->GetLineSize(); + long nVPage = pVerScroll->GetPageSize(); + + aCurPos.X() = pHorScroll->GetThumbPos(); + aCurPos.Y() = pVerScroll->GetThumbPos(); + aPrevPos = aCurPos; + + long nThumbPos = pVerScroll->GetThumbPos(); + long nRangeMax = pVerScroll->GetRangeMax(); + + switch( nMode ) + { + case SID_CURSORUP: + if( nMaxVertPos<0 ) + { + long nPage = pPreview->GetPageNo(); + + if( nPage>0 ) + { + SfxViewFrame* pSfxViewFrame = GetViewFrame(); + SfxRequest aSfxRequest( pSfxViewFrame, SID_PREVIEW_PREVIOUS ); + Execute( aSfxRequest ); + } + } + else + aCurPos.Y() -= nVLine; + break; + case SID_CURSORDOWN: + if( nMaxVertPos<0 ) + { + long nPage = pPreview->GetPageNo(); + long nTotal = pPreview->GetTotalPages(); + + // before testing for last page, make sure all page counts are calculated + if ( nPage+1 == nTotal && !pPreview->AllTested() ) + { + pPreview->CalcAll(); + nTotal = pPreview->GetTotalPages(); + } + + if( nPage<nTotal-1 ) + { + SfxViewFrame* pSfxViewFrame = GetViewFrame(); + SfxRequest aSfxRequest( pSfxViewFrame, SID_PREVIEW_NEXT ); + Execute( aSfxRequest ); + } + } + else + aCurPos.Y() += nVLine; + break; + case SID_CURSORLEFT: + aCurPos.X() -= nHLine; + break; + case SID_CURSORRIGHT: + aCurPos.X() += nHLine; + break; + case SID_CURSORPAGEUP: + if( nThumbPos==0 || nMaxVertPos<0 ) + { + long nPage = pPreview->GetPageNo(); + + if( nPage>0 ) + { + SfxViewFrame* pSfxViewFrame = GetViewFrame(); + SfxRequest aSfxRequest( pSfxViewFrame, SID_PREVIEW_PREVIOUS ); + Execute( aSfxRequest ); + aCurPos.Y() = nVRange; + } + } + else + aCurPos.Y() -= nVPage; + break; + case SID_CURSORPAGEDOWN: + if( (abs(nVPage+nThumbPos-nRangeMax)<10) || nMaxVertPos<0 ) + { + long nPage = pPreview->GetPageNo(); + long nTotal = pPreview->GetTotalPages(); + + // before testing for last page, make sure all page counts are calculated + if ( nPage+1 == nTotal && !pPreview->AllTested() ) + { + pPreview->CalcAll(); + nTotal = pPreview->GetTotalPages(); + } + if( nPage<nTotal-1 ) + { + SfxViewFrame* pSfxViewFrame = GetViewFrame(); + SfxRequest aSfxRequest( pSfxViewFrame, SID_PREVIEW_NEXT ); + Execute( aSfxRequest ); + aCurPos.Y() = 0; + } + } + else + aCurPos.Y() += nVPage; + break; + case SID_CURSORHOME: + if( nMaxVertPos<0 ) + { + long nPage = pPreview->GetPageNo(); + long nTotal = pPreview->GetTotalPages(); + if( nTotal && nPage != 0 ) + { + SfxViewFrame* pSfxViewFrame = GetViewFrame(); + SfxRequest aSfxRequest( pSfxViewFrame, SID_PREVIEW_FIRST ); + Execute( aSfxRequest ); + } + } + else + { + aCurPos.Y() = 0; + aCurPos.X() = 0; + } + break; + case SID_CURSOREND: + if( nMaxVertPos<0 ) + { + if( !pPreview->AllTested() ) + pPreview->CalcAll(); + long nPage = pPreview->GetPageNo(); + long nTotal = pPreview->GetTotalPages(); + if( nTotal && nPage+1 != nTotal ) + { + SfxViewFrame* pSfxViewFrame = GetViewFrame(); + SfxRequest aSfxRequest( pSfxViewFrame, SID_PREVIEW_LAST ); + Execute( aSfxRequest ); + } + } + else + { + aCurPos.Y() = nVRange; + aCurPos.X() = nHRange; + } + break; + } + + // nHRange-nHPage kann negativ sein, deshalb Abfrage auf < 0 hinterher + + if( aCurPos.Y() > (nVRange-nVPage) ) + aCurPos.Y() = (nVRange-nVPage); + if( aCurPos.Y() < 0 ) + aCurPos.Y() = 0; + if( aCurPos.X() > (nHRange-nHPage) ) + aCurPos.X() = (nHRange-nHPage); + if( aCurPos.X() < 0 ) + aCurPos.X() = 0; + + if( nMaxVertPos>=0 ) + { + if( aCurPos.Y() != aPrevPos.Y() ) + { + pVerScroll->SetThumbPos( aCurPos.Y() ); + pPreview->SetYOffset( aCurPos.Y() ); + } + } + + if( aCurPos.X() != aPrevPos.X() ) + { + pHorScroll->SetThumbPos( aCurPos.X() ); + pPreview->SetXOffset( aCurPos.X() ); + } + +} + +void ScPreviewShell::AddAccessibilityObject( SfxListener& rObject ) +{ + if (!pAccessibilityBroadcaster) + pAccessibilityBroadcaster = new SfxBroadcaster; + + rObject.StartListening( *pAccessibilityBroadcaster ); +} + +void ScPreviewShell::RemoveAccessibilityObject( SfxListener& rObject ) +{ + if (pAccessibilityBroadcaster) + rObject.EndListening( *pAccessibilityBroadcaster ); + else + { + DBG_ERROR("kein Accessibility-Broadcaster?"); + } +} + +void ScPreviewShell::BroadcastAccessibility( const SfxHint &rHint ) +{ + if (pAccessibilityBroadcaster) + pAccessibilityBroadcaster->Broadcast( rHint ); +} + +sal_Bool ScPreviewShell::HasAccessibilityObjects() +{ + return pAccessibilityBroadcaster && pAccessibilityBroadcaster->HasListeners(); +} + +const ScPreviewLocationData& ScPreviewShell::GetLocationData() +{ + return pPreview->GetLocationData(); +} + +ScDocument* ScPreviewShell::GetDocument() +{ + return pDocShell->GetDocument(); +} + + diff --git a/sc/source/ui/view/prevwsh2.cxx b/sc/source/ui/view/prevwsh2.cxx new file mode 100644 index 000000000000..22d511e762f9 --- /dev/null +++ b/sc/source/ui/view/prevwsh2.cxx @@ -0,0 +1,353 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +//------------------------------------------------------------------ + +// TOOLS +#define _BIGINT_HXX +#define _SFXMULTISEL_HXX +#define _STACK_HXX +#define _QUEUE_HXX +#define _DYNARR_HXX +#define _TREELIST_HXX +#define _CACHESTR_HXX +#define _NEW_HXX +//#define _SHL_HXX +//#define _LINK_HXX +//#define _ERRCODE_HXX +//#define _GEN_HXX +//#define _FRACT_HXX +//#define _STRING_HXX +//#define _MTF_HXX +//#define _CONTNR_HXX +//#define _LIST_HXX +//#define _TABLE_HXX +#define _DYNARY_HXX +//#define _UNQIDX_HXX +#define _SVMEMPOOL_HXX +//#define _UNQID_HXX +//#define _DEBUG_HXX +//#define _DATE_HXX +//#define _TIME_HXX +//#define _DATETIME_HXX +//#define _INTN_HXX +//#define _WLDCRD_HXX +//#define _FSYS_HXX +//#define _STREAM_HXX +#define _CACHESTR_HXX +//#define _SV_MULTISEL_HXX + +//SV +//#define _CLIP_HXX *** +#define _CONFIG_HXX +#define _CURSOR_HXX +#define _FONTDLG_HXX +#define _PRVWIN_HXX +//#define _COLOR_HXX +//#define _PAL_HXX +//#define _BITMAP_HXX +//#define _GDIOBJ_HXX +//#define _POINTR_HXX +//#define _ICON_HXX +//#define _IMAGE_HXX +//#define _KEYCOD_HXX +//#define _EVENT_HXX +#define _HELP_HXX +//#define _APP_HXX +//#define _MDIAPP_HXX +//#define _TIMER_HXX +//#define _METRIC_HXX +//#define _REGION_HXX +//#define _OUTDEV_HXX +//#define _SYSTEM_HXX +//#define _VIRDEV_HXX +//#define _JOBSET_HXX +//#define _PRINT_HXX +//#define _WINDOW_HXX +//#define _SYSWIN_HXX +//#define _WRKWIN_HXX +#define _MDIWIN_HXX +//#define _FLOATWIN_HXX +//#define _DOCKWIN_HXX +//#define _CTRL_HXX +//#define _SCRBAR_HXX +//#define _BUTTON_HXX +//#define _IMAGEBTN_HXX +//#define _FIXED_HXX +//#define _GROUP_HXX +//#define _EDIT_HXX +//#define _COMBOBOX_HXX +//#define _LSTBOX_HXX +//#define _SELENG_HXX *** +//#define _SPLIT_HXX +#define _SPIN_HXX +//#define _FIELD_HXX +//#define _MOREBTN_HXX *** +//#define _TOOLBOX_HXX +//#define _STATUS_HXX *** +//#define _DIALOG_HXX +//#define _MSGBOX_HXX +//#define _SYSDLG_HXX +//#define _PRNDLG_HXX +#define _COLDLG_HXX +//#define _TABDLG_HXX +//#define _GDIMTF_HXX +//#define _POLY_HXX +//#define _ACCEL_HXX +//#define _GRAPH_HXX +#define _SOUND_HXX + +//svtools +#define _SCRWIN_HXX +#define _RULER_HXX +//#define _TABBAR_HXX +//#define _VALUESET_HXX +#define _STDMENU_HXX +//#define _STDCTRL_HXX +//#define _CTRLBOX_HXX +#define _CTRLTOOL_HXX +#define _EXTATTR_HXX +#define _FRM3D_HXX +#define _EXTATTR_HXX + +//SVTOOLS +//#define _SVTREELIST_HXX *** +#define _FILTER_HXX +//#define _SVLBOXITM_HXX *** +//#define _SVTREEBOX_HXX *** +#define _SVICNVW_HXX +#define _SVTABBX_HXX + +//sfxcore.hxx +//#define _SFXINIMGR_HXX *** +//#define _SFXCFGITEM_HXX +//#define _SFX_PRINTER_HXX +#define _SFXGENLINK_HXX +#define _SFXHINTPOST_HXX +#define _SFXDOCINF_HXX +#define _SFXLINKHDL_HXX +//#define _SFX_PROGRESS_HXX + +//sfxsh.hxx +//#define _SFX_SHELL_HXX +//#define _SFXAPP_HXX +//#define _SFXDISPATCH_HXX +//#define _SFXMSG_HXX *** +//#define _SFXOBJFACE_HXX *** +//#define _SFXREQUEST_HXX +#define _SFXMACRO_HXX + +// SFX +//#define _SFXAPPWIN_HXX *** +#define _SFX_SAVEOPT_HXX +//#define _SFX_CHILDWIN_HXX +//#define _SFXCTRLITEM_HXX +#define _SFXPRNMON_HXX +#define _INTRO_HXX +#define _SFXMSGDESCR_HXX +#define _SFXMSGPOOL_HXX +#define _SFXFILEDLG_HXX +#define _PASSWD_HXX +#define _SFXTBXCTRL_HXX +#define _SFXSTBITEM_HXX +#define _SFXMNUITEM_HXX +#define _SFXIMGMGR_HXX +#define _SFXTBXMGR_HXX +#define _SFXSTBMGR_HXX +#define _SFX_MINFITEM_HXX +#define _SFXEVENT_HXX + +//sfxdoc.hxx +//#define _SFX_OBJSH_HXX +//#define _SFX_CLIENTSH_HXX +//#define _SFXDOCINF_HXX +//#define _SFX_OBJFAC_HXX +#define _SFX_DOCFILT_HXX +//#define _SFXDOCFILE_HXX *** +//define _VIEWFAC_HXX +//#define _SFXVIEWFRM_HXX +//#define _SFXVIEWSH_HXX +//#define _MDIFRM_HXX *** +#define _SFX_IPFRM_HXX +//#define _SFX_INTERNO_HXX + +//sfxdlg.hxx +//#define _SFXTABDLG_HXX +//#define _BASEDLGS_HXX *** +#define _SFX_DINFDLG_HXX +#define _SFXDINFEDT_HXX +#define _SFX_MGETEMPL_HXX +#define _SFX_TPLPITEM_HXX +//#define _SFX_STYLEDLG_HXX +#define _NEWSTYLE_HXX +//#define _SFXDOCTEMPL_HXX *** +//#define _SFXDOCTDLG_HXX *** +//#define _SFX_TEMPLDLG_HXX *** +//#define _SFXNEW_HXX *** +#define _SFXDOCMAN_HXX +#define _SFXDOCKWIN_HXX + +//sfxitems.hxx +#define _SFX_WHMAP_HXX +//#define _ARGS_HXX *** +//#define _SFXPOOLITEM_HXX +//#define _SFXINTITEM_HXX +//#define _SFXENUMITEM_HXX +#define _SFXFLAGITEM_HXX +//#define _SFXSTRITEM_HXX +#define _SFXPTITEM_HXX +#define _SFXRECTITEM_HXX +//#define _SFXITEMPOOL_HXX +//#define _SFXITEMSET_HXX +#define _SFXITEMITER_HXX +#define _SFX_WHITER_HXX +#define _SFXPOOLCACH_HXX +//#define _AEITEM_HXX +#define _SFXRNGITEM_HXX +//#define _SFXSLSTITM_HXX +//#define _SFXSTYLE_HXX + +//xout.hxx +//#define _XENUM_HXX +//#define _XPOLY_HXX +//#define _XATTR_HXX +//#define _XOUTX_HXX +//#define _XPOOL_HXX +//#define _XTABLE_HXX + +//svdraw.hxx +#define _SDR_NOITEMS +#define _SDR_NOTOUCH +#define _SDR_NOTRANSFORM +//#define _SDR_NOOBJECTS +//#define _SDR_NOVIEWS +#define _SDR_NOTRANSFORM +#define _SDR_NOVIEWMARKER +#define _SDR_NODRAGMETHODS +#define _SDR_NOUNDO +#define _SDR_NOXOUTDEV + + +//#define SI_NOITEMS +//#define SI_NODRW +#define _SI_NOSBXCONTROLS +//#define _VCATTR_HXX +#define _VCONT_HXX +//#define _VCSBX_HXX +#define _SI_NOOTHERFORMS +#define _VCTRLS_HXX +//#define _VCDRWOBJ_HXX +#define _SI_NOCONTROL +#define _SETBRW_HXX +#define _VCBRW_HXX +#define _SI_NOSBXCONTROLS +//#define _SIDLL_HXX *** + +#define _SVX_DAILDLL_HXX +#define _SVX_HYPHEN_HXX +#define _SVX_IMPGRF_HXX +#define _SVX_OPTITEMS_HXX +#define _SVX_OPTGERL_HXX +#define _SVX_OPTSAVE_HXX +#define _SVX_OPTSPELL_HXX +#define _SVX_OPTPATH_HXX +#define _SVX_OPTLINGU_HXX +#define _SVX_RULER_HXX +#define _SVX_RULRITEM_HXX +#define _SVX_SPLWRAP_HXX +#define _SVX_SPLDLG_HXX +#define _SVX_THESDLG_HXX + + + + +// INCLUDE --------------------------------------------------------------- + +#include <svx/svdmodel.hxx> +#include <svl/smplhint.hxx> + +#include "prevwsh.hxx" +#include "docsh.hxx" +#include "preview.hxx" +#include "hints.hxx" +#include "sc.hrc" + +// STATIC DATA ----------------------------------------------------------- + +// ----------------------------------------------------------------------- + +void __EXPORT ScPreviewShell::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + sal_Bool bDataChanged = sal_False; + + if (rHint.ISA(SfxSimpleHint)) + { + sal_uLong nSlot = ((const SfxSimpleHint&)rHint).GetId(); + switch ( nSlot ) + { + case FID_DATACHANGED: + case SID_SCPRINTOPTIONS: + bDataChanged = sal_True; + break; + case SC_HINT_DRWLAYER_NEW: + { + SfxBroadcaster* pDrawBC = pDocShell->GetDocument()->GetDrawBroadcaster(); + if (pDrawBC) + StartListening(*pDrawBC); + } + break; + } + } + else if (rHint.ISA(ScPaintHint)) + { + if ( ((const ScPaintHint&)rHint).GetPrintFlag() ) + { + sal_uInt16 nParts = ((const ScPaintHint&)rHint).GetParts(); + if (nParts & ( PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE )) + bDataChanged = sal_True; + } + } + else if (rHint.ISA(SdrHint)) + { + // SdrHints are no longer used for invalidating, thus react on objectchange instead + if(HINT_OBJCHG == ((const SdrHint&)rHint).GetKind()) + bDataChanged = sal_True; + } + + if (bDataChanged) + pPreview->DataChanged(sal_True); +} + + + + + diff --git a/sc/source/ui/view/printfun.cxx b/sc/source/ui/view/printfun.cxx new file mode 100644 index 000000000000..c7cc92246536 --- /dev/null +++ b/sc/source/ui/view/printfun.cxx @@ -0,0 +1,3202 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +// INCLUDE --------------------------------------------------------------- + +#include "scitems.hxx" +#include <editeng/eeitem.hxx> + +#include "printfun.hxx" + +#include <svx/svxids.hrc> +#include <editeng/adjitem.hxx> +#include <editeng/boxitem.hxx> +#include <editeng/brshitem.hxx> +#include <svtools/colorcfg.hxx> +#include <editeng/editstat.hxx> // EE_CNTRL_RTFSTYLESHEETS +#include <svx/fmview.hxx> +#include <editeng/frmdiritem.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/paperinf.hxx> +#include <editeng/pbinitem.hxx> +#include <editeng/shaditem.hxx> +#include <editeng/sizeitem.hxx> +#include <svx/svdpagv.hxx> +#include <editeng/ulspitem.hxx> +#include <sfx2/app.hxx> +#include <sfx2/printer.hxx> +#include <sfx2/progress.hxx> +#include <tools/multisel.hxx> +#include <sfx2/docfile.hxx> +#include <tools/urlobj.hxx> +#include <svx/xoutbmp.hxx> + +#include "editutil.hxx" +#include "docsh.hxx" +#include "output.hxx" +#include "viewdata.hxx" +#include "viewopti.hxx" +#include "stlpool.hxx" +#include "pagepar.hxx" +#include "attrib.hxx" +#include "patattr.hxx" +#include "docpool.hxx" +#include "dociter.hxx" +#include "cell.hxx" +#include "drawutil.hxx" +#include "globstr.hrc" +#include "scresid.hxx" +#include "sc.hrc" +#include "pagedata.hxx" +#include "printopt.hxx" +#include "prevloc.hxx" +#include "scmod.hxx" +#include "drwlayer.hxx" +#include "fillinfo.hxx" +#include "postit.hxx" + +#include <vcl/lineinfo.hxx> +#include <tools/pstm.hxx> + +#include <boost/scoped_ptr.hpp> + +#define ZOOM_MIN 10 + +#define GET_BOOL(set,which) ((const SfxBoolItem&)(set)->Get((which))).GetValue() +#define GET_USHORT(set,which) ((const SfxUInt16Item&)(set)->Get((which))).GetValue() +#define GET_SHOW(set,which) ( VOBJ_MODE_SHOW == ScVObjMode( ((const ScViewObjectModeItem&)(set)->Get((which))).GetValue()) ) + +//------------------------------------------------------------------------ + +ScPageRowEntry::ScPageRowEntry(const ScPageRowEntry& r) +{ + nStartRow = r.nStartRow; + nEndRow = r.nEndRow; + nPagesX = r.nPagesX; + if (r.pHidden && nPagesX) + { + pHidden = new sal_Bool[nPagesX]; + memcpy( pHidden, r.pHidden, nPagesX * sizeof(sal_Bool) ); + } + else + pHidden = NULL; +} + +const ScPageRowEntry& ScPageRowEntry::operator=(const ScPageRowEntry& r) +{ + delete[] pHidden; + + nStartRow = r.nStartRow; + nEndRow = r.nEndRow; + nPagesX = r.nPagesX; + if (r.pHidden && nPagesX) + { + pHidden = new sal_Bool[nPagesX]; + memcpy( pHidden, r.pHidden, nPagesX * sizeof(sal_Bool) ); + } + else + pHidden = NULL; + + return *this; +} + +void ScPageRowEntry::SetPagesX(size_t nNew) +{ + if (pHidden) + { + DBG_ERROR("SetPagesX nicht nach SetHidden"); + delete[] pHidden; + pHidden = NULL; + } + nPagesX = nNew; +} + +void ScPageRowEntry::SetHidden(size_t nX) +{ + if ( nX < nPagesX ) + { + if ( nX+1 == nPagesX ) // letzte Seite? + --nPagesX; + else + { + if (!pHidden) + { + pHidden = new sal_Bool[nPagesX]; + memset( pHidden, sal_False, nPagesX * sizeof(sal_Bool) ); + } + pHidden[nX] = sal_True; + } + } +} + +sal_Bool ScPageRowEntry::IsHidden(size_t nX) const +{ + return nX>=nPagesX || ( pHidden && pHidden[nX] ); //! inline? +} + +size_t ScPageRowEntry::CountVisible() const +{ + if ( pHidden ) + { + size_t nVis = 0; + for (size_t i=0; i<nPagesX; i++) + if (!pHidden[i]) + ++nVis; + return nVis; + } + else + return nPagesX; +} + +//------------------------------------------------------------------------ + +long lcl_LineTotal(const SvxBorderLine* pLine) +{ + return pLine ? ( pLine->GetOutWidth() + pLine->GetInWidth() + pLine->GetDistance() ) : 0; +} + +void ScPrintFunc::Construct( const ScPrintOptions* pOptions ) +{ + pDocShell->UpdatePendingRowHeights( nPrintTab ); + pDoc = pDocShell->GetDocument(); + + SfxPrinter* pDocPrinter = pDoc->GetPrinter(); // auch fuer Preview den Drucker nehmen + if (pDocPrinter) + aOldPrinterMode = pDocPrinter->GetMapMode(); + + // einheitlicher MapMode ueber alle Aufrufe (z.B. Repaint !!!), + // weil die EditEngine sonst unterschiedliche Texthoehen liefert + pDev->SetMapMode(MAP_PIXEL); + + pPageEndX = NULL; + pPageEndY = NULL; + pPageRows = NULL; + pBorderItem = NULL; + pBackgroundItem = NULL; + pShadowItem = NULL; + + pEditEngine = NULL; + pEditDefaults = NULL; + + ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool(); + SfxStyleSheetBase* pStyleSheet = pStylePool->Find( + pDoc->GetPageStyle( nPrintTab ), + SFX_STYLE_FAMILY_PAGE ); + if (pStyleSheet) + pParamSet = &pStyleSheet->GetItemSet(); + else + { + DBG_ERROR("Seitenvorlage nicht gefunden" ); + pParamSet = NULL; + } + + if (!bState) + nZoom = 100; + nManualZoom = 100; + bClearWin = sal_False; + bUseStyleColor = sal_False; + bIsRender = sal_False; + + InitParam(pOptions); + + pPageData = NULL; // wird nur zur Initialisierung gebraucht +} + +ScPrintFunc::ScPrintFunc( ScDocShell* pShell, SfxPrinter* pNewPrinter, SCTAB nTab, + long nPage, long nDocP, const ScRange* pArea, + const ScPrintOptions* pOptions, + ScPageBreakData* pData ) + : pDocShell ( pShell ), + pPrinter ( pNewPrinter ), + pDrawView ( NULL ), + nPrintTab ( nTab ), + nPageStart ( nPage ), + nDocPages ( nDocP ), + pUserArea ( pArea ), + bState ( sal_False ), + bSourceRangeValid ( sal_False ), + bPrintCurrentTable ( sal_False ), + bMultiArea ( sal_False ), + nTabPages ( 0 ), + nTotalPages ( 0 ), + pPageData ( pData ) +{ + pDev = pPrinter; + aSrcOffset = pPrinter->PixelToLogic( pPrinter->GetPageOffsetPixel(), MAP_100TH_MM ); + Construct( pOptions ); +} + +ScPrintFunc::ScPrintFunc( OutputDevice* pOutDev, ScDocShell* pShell, SCTAB nTab, + long nPage, long nDocP, const ScRange* pArea, + const ScPrintOptions* pOptions ) + : pDocShell ( pShell ), + pPrinter ( NULL ), + pDrawView ( NULL ), + nPrintTab ( nTab ), + nPageStart ( nPage ), + nDocPages ( nDocP ), + pUserArea ( pArea ), + bState ( sal_False ), + bSourceRangeValid ( sal_False ), + bPrintCurrentTable ( sal_False ), + bMultiArea ( sal_False ), + nTabPages ( 0 ), + nTotalPages ( 0 ), + pPageData ( NULL ) +{ + pDev = pOutDev; + Construct( pOptions ); +} + +ScPrintFunc::ScPrintFunc( OutputDevice* pOutDev, ScDocShell* pShell, + const ScPrintState& rState, const ScPrintOptions* pOptions ) + : pDocShell ( pShell ), + pPrinter ( NULL ), + pDrawView ( NULL ), + pUserArea ( NULL ), + bSourceRangeValid ( sal_False ), + bPrintCurrentTable ( sal_False ), + bMultiArea ( sal_False ), + pPageData ( NULL ) +{ + pDev = pOutDev; + + nPrintTab = rState.nPrintTab; + nStartCol = rState.nStartCol; + nStartRow = rState.nStartRow; + nEndCol = rState.nEndCol; + nEndRow = rState.nEndRow; + nZoom = rState.nZoom; + nPagesX = rState.nPagesX; + nPagesY = rState.nPagesY; + nTabPages = rState.nTabPages; + nTotalPages = rState.nTotalPages; + nPageStart = rState.nPageStart; + nDocPages = rState.nDocPages; + bState = sal_True; + + Construct( pOptions ); +} +ScPrintFunc::ScPrintFunc( ScDocShell* pShell, Window* pWindow, SCTAB nTab, + long nPage, long nDocP, const ScRange* pArea, + const ScPrintOptions* pOptions ) + : pDocShell ( pShell ), + pPrinter ( NULL ), + pDrawView ( NULL ), + nPrintTab ( nTab ), + nPageStart ( nPage ), + nDocPages ( nDocP ), + pUserArea ( pArea ), + bState ( sal_False ), + bPrintCurrentTable ( sal_False ), + bMultiArea ( sal_False ), + nTabPages ( 0 ), + nTotalPages ( 0 ), + pPageData ( NULL ) +{ + pDev = pWindow; + Construct( pOptions ); +} +ScPrintFunc::ScPrintFunc( ScDocShell* pShell, Window* pWindow, + const ScPrintState& rState, const ScPrintOptions* pOptions ) + : pDocShell ( pShell ), + pPrinter ( NULL ), + pDrawView ( NULL ), + pUserArea ( NULL ), + bPrintCurrentTable ( sal_False ), + bMultiArea ( sal_False ), + pPageData ( NULL ) +{ + pDev = pWindow; + + nPrintTab = rState.nPrintTab; + nStartCol = rState.nStartCol; + nStartRow = rState.nStartRow; + nEndCol = rState.nEndCol; + nEndRow = rState.nEndRow; + nZoom = rState.nZoom; + nPagesX = rState.nPagesX; + nPagesY = rState.nPagesY; + nTabPages = rState.nTabPages; + nTotalPages = rState.nTotalPages; + nPageStart = rState.nPageStart; + nDocPages = rState.nDocPages; + bState = sal_True; + + Construct( pOptions ); +} + +void ScPrintFunc::GetPrintState( ScPrintState& rState ) +{ + rState.nPrintTab = nPrintTab; + rState.nStartCol = nStartCol; + rState.nStartRow = nStartRow; + rState.nEndCol = nEndCol; + rState.nEndRow = nEndRow; + rState.nZoom = nZoom; + rState.nPagesX = nPagesX; + rState.nPagesY = nPagesY; + rState.nTabPages = nTabPages; + rState.nTotalPages = nTotalPages; + rState.nPageStart = nPageStart; + rState.nDocPages = nDocPages; +} + +sal_Bool ScPrintFunc::GetLastSourceRange( ScRange& rRange ) const +{ + rRange = aLastSourceRange; + return bSourceRangeValid; +} + +void ScPrintFunc::FillPageData() +{ + if (pPageData) + { + sal_uInt16 nCount = sal::static_int_cast<sal_uInt16>( pPageData->GetCount() ); + ScPrintRangeData& rData = pPageData->GetData(nCount); // hochzaehlen + + rData.SetPrintRange( ScRange( nStartCol, nStartRow, nPrintTab, + nEndCol, nEndRow, nPrintTab ) ); + rData.SetPagesX( nPagesX, pPageEndX ); + rData.SetPagesY( nTotalY, pPageEndY ); + + // Einstellungen + rData.SetTopDown( aTableParam.bTopDown ); + rData.SetAutomatic( !aAreaParam.bPrintArea ); + } +} + +ScPrintFunc::~ScPrintFunc() +{ + ScAddress* pTripel = (ScAddress*) aNotePosList.First(); + while (pTripel) + { + delete pTripel; + pTripel = (ScAddress*) aNotePosList.Next(); + } + aNotePosList.Clear(); + + delete[] pPageEndX; + delete[] pPageEndY; + delete[] pPageRows; + delete pEditDefaults; + delete pEditEngine; + + // Druckereinstellungen werden jetzt von aussen wiederhergestellt + + // #64294# Fuer DrawingLayer/Charts muss der MapMode am Drucker (RefDevice) immer stimmen + SfxPrinter* pDocPrinter = pDoc->GetPrinter(); // auch fuer Preview den Drucker nehmen + if (pDocPrinter) + pDocPrinter->SetMapMode(aOldPrinterMode); +} + +void ScPrintFunc::SetDrawView( FmFormView* pNew ) +{ + pDrawView = pNew; +} + +void lcl_HidePrint( ScTableInfo& rTabInfo, SCCOL nX1, SCCOL nX2 ) +{ + for (SCSIZE nArrY=1; nArrY+1<rTabInfo.mnArrCount; nArrY++) + { + RowInfo* pThisRowInfo = &rTabInfo.mpRowInfo[nArrY]; + for (SCCOL nX=nX1; nX<=nX2; nX++) + { + const CellInfo& rCellInfo = pThisRowInfo->pCellInfo[nX+1]; + if (!rCellInfo.bEmptyCellText) + if (((const ScProtectionAttr&)rCellInfo.pPatternAttr-> + GetItem(ATTR_PROTECTION, rCellInfo.pConditionSet)).GetHidePrint()) + { + pThisRowInfo->pCellInfo[nX+1].pCell = NULL; + pThisRowInfo->pCellInfo[nX+1].bEmptyCellText = sal_True; + } + } + } +} + +// +// Ausgabe auf Device (static) +// +// wird benutzt fuer: +// - Clipboard/Bitmap +// - Ole-Object (DocShell::Draw) +// - Vorschau bei Vorlagen + +void ScPrintFunc::DrawToDev( ScDocument* pDoc, OutputDevice* pDev, double /* nPrintFactor */, + const Rectangle& rBound, ScViewData* pViewData, sal_Bool bMetaFile ) +{ + //! nPrintFactor auswerten !!! + + SCTAB nTab = 0; + if (pViewData) + nTab = pViewData->GetTabNo(); + + sal_Bool bDoGrid, bNullVal, bFormula; + ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool(); + SfxStyleSheetBase* pStyleSheet = pStylePool->Find( pDoc->GetPageStyle( nTab ), SFX_STYLE_FAMILY_PAGE ); + if (pStyleSheet) + { + SfxItemSet& rSet = pStyleSheet->GetItemSet(); + bDoGrid = ((const SfxBoolItem&)rSet.Get(ATTR_PAGE_GRID)).GetValue(); + bNullVal = ((const SfxBoolItem&)rSet.Get(ATTR_PAGE_NULLVALS)).GetValue(); + bFormula = ((const SfxBoolItem&)rSet.Get(ATTR_PAGE_FORMULAS)).GetValue(); + } + else + { + const ScViewOptions& rOpt = pDoc->GetViewOptions(); + bDoGrid = rOpt.GetOption(VOPT_GRID); + bNullVal = rOpt.GetOption(VOPT_NULLVALS); + bFormula = rOpt.GetOption(VOPT_FORMULAS); + } + + MapMode aMode = pDev->GetMapMode(); + + Rectangle aRect = rBound; + + if (aRect.Right() < aRect.Left() || aRect.Bottom() < aRect.Top()) + aRect = Rectangle( Point(), pDev->GetOutputSize() ); + + SCCOL nX1 = 0; + SCROW nY1 = 0; + SCCOL nX2 = OLE_STD_CELLS_X - 1; + SCROW nY2 = OLE_STD_CELLS_Y - 1; + if (bMetaFile) + { + ScRange aRange = pDoc->GetRange( nTab, rBound ); + nX1 = aRange.aStart.Col(); + nY1 = aRange.aStart.Row(); + nX2 = aRange.aEnd.Col(); + nY2 = aRange.aEnd.Row(); + } + else if (pViewData) + { + ScSplitPos eWhich = pViewData->GetActivePart(); + ScHSplitPos eHWhich = WhichH(eWhich); + ScVSplitPos eVWhich = WhichV(eWhich); + nX1 = pViewData->GetPosX(eHWhich); + nY1 = pViewData->GetPosY(eVWhich); + nX2 = nX1 + pViewData->VisibleCellsX(eHWhich); + if (nX2>nX1) --nX2; + nY2 = nY1 + pViewData->VisibleCellsY(eVWhich); + if (nY2>nY1) --nY2; + } + + if (nX1 > MAXCOL) nX1 = MAXCOL; + if (nX2 > MAXCOL) nX2 = MAXCOL; + if (nY1 > MAXROW) nY1 = MAXROW; + if (nY2 > MAXROW) nY2 = MAXROW; + + long nDevSizeX = aRect.Right()-aRect.Left()+1; + long nDevSizeY = aRect.Bottom()-aRect.Top()+1; + + Rectangle aLines; + ScRange aRange( nX1,nY1,nTab, nX2,nY2,nTab ); +// sal_Bool bAddLines = pDoc->HasLines( aRange, aLines ); + + long nTwipsSizeX = 0; + for (SCCOL i=nX1; i<=nX2; i++) + nTwipsSizeX += pDoc->GetColWidth( i, nTab ); + long nTwipsSizeY = (long) pDoc->GetRowHeight( nY1, nY2, nTab ); + + // wenn keine Linien, dann trotzdem Platz fuer den Aussenrahmen (20 Twips = 1pt) + // (HasLines initalisiert aLines auf 0,0,0,0) + nTwipsSizeX += aLines.Left() + Max( aLines.Right(), 20L ); + nTwipsSizeY += aLines.Top() + Max( aLines.Bottom(), 20L ); + + double nScaleX = (double) nDevSizeX / nTwipsSizeX; + double nScaleY = (double) nDevSizeY / nTwipsSizeY; + + //! Flag bei FillInfo uebergeben !!!!! + ScRange aERange; + sal_Bool bEmbed = pDoc->IsEmbedded(); + if (bEmbed) + { + pDoc->GetEmbedded(aERange); + pDoc->ResetEmbedded(); + } + + // Daten zusammenstellen + + ScTableInfo aTabInfo; + pDoc->FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nTab, + nScaleX, nScaleY, sal_False, bFormula ); + lcl_HidePrint( aTabInfo, nX1, nX2 ); + + if (bEmbed) + pDoc->SetEmbedded(aERange); + +/* if (!bMetaFile) + pDev->SetMapMode(MAP_PIXEL); +*/ + long nScrX = aRect.Left(); + long nScrY = aRect.Top(); + + // Wenn keine Linien, trotzdem Platz fuer Gitterlinien lassen + // (werden sonst abgeschnitten) + long nAddX = (long)( aLines.Left() * nScaleX ); + nScrX += ( nAddX ? nAddX : 1 ); + long nAddY = (long)( aLines.Top() * nScaleY ); + nScrY += ( nAddY ? nAddY : 1 ); + + ScOutputData aOutputData( pDev, OUTTYPE_PRINTER, aTabInfo, pDoc, nTab, + nScrX, nScrY, nX1, nY1, nX2, nY2, nScaleX, nScaleY ); + aOutputData.SetMetaFileMode(bMetaFile); + aOutputData.SetShowNullValues(bNullVal); + aOutputData.SetShowFormulas(bFormula); + + // #114135# + ScDrawLayer* pModel = pDoc->GetDrawLayer(); + FmFormView* pDrawView = NULL; + + if( pModel ) + { + pDrawView = new FmFormView( pModel, pDev ); + pDrawView->ShowSdrPage(pDrawView->GetModel()->GetPage(nTab)); + pDrawView->SetPrintPreview( sal_True ); + aOutputData.SetDrawView( pDrawView ); + } + + //! SetUseStyleColor ?? + + if ( bMetaFile && pDev->GetOutDevType() == OUTDEV_VIRDEV ) + aOutputData.SetSnapPixel(); + + Point aLogStart = pDev->PixelToLogic( Point(nScrX,nScrY), MAP_100TH_MM ); + long nLogStX = aLogStart.X(); + long nLogStY = aLogStart.Y(); + + //! nZoom fuer GetFont in OutputData ??? + + if (!bMetaFile && pViewData) + pDev->SetMapMode(pViewData->GetLogicMode(pViewData->GetActivePart())); + + // #i72502# + const Point aMMOffset(aOutputData.PrePrintDrawingLayer(nLogStX, nLogStY)); + aOutputData.PrintDrawingLayer(SC_LAYER_BACK, aMMOffset); + + if (!bMetaFile && pViewData) + pDev->SetMapMode(aMode); + + aOutputData.DrawBackground(); + +#ifdef OS2 + if (bMetaFile && !bDoGrid) + { + // unter OS2 fuer Metafiles gesamte Flaeche benutzen, + // weil sonst die Groesse nicht erkannt wird + pDev->SetLineColor(); + pDev->SetFillColor(); + pDev->DrawRect( Rectangle( nScrX,nScrY, + nScrX+aOutputData.GetScrW(), nScrY+aOutputData.GetScrH() ) ); + } +#endif + + aOutputData.DrawShadow(); + aOutputData.DrawFrame(); + aOutputData.DrawStrings(); + + if (!bMetaFile && pViewData) + pDev->SetMapMode(pViewData->GetLogicMode(pViewData->GetActivePart())); + + aOutputData.DrawEdit(!bMetaFile); + + if (bDoGrid) + { + if (!bMetaFile && pViewData) + pDev->SetMapMode(aMode); + + aOutputData.DrawGrid( sal_True, sal_False ); // keine Seitenumbrueche + + pDev->SetLineColor( COL_BLACK ); + + Size aOne = pDev->PixelToLogic( Size(1,1) ); + if (bMetaFile) + aOne = Size(1,1); // compatible with DrawGrid + long nRight = nScrX + aOutputData.GetScrW() - aOne.Width(); + long nBottom = nScrY + aOutputData.GetScrH() - aOne.Height(); + + sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); + + // extra line at the left edge for left-to-right, right for right-to-left + if ( bLayoutRTL ) + pDev->DrawLine( Point(nRight,nScrY), Point(nRight,nBottom) ); + else + pDev->DrawLine( Point(nScrX,nScrY), Point(nScrX,nBottom) ); + // extra line at the top in both cases + pDev->DrawLine( Point(nScrX,nScrY), Point(nRight,nScrY) ); + } + + // #i72502# + aOutputData.PrintDrawingLayer(SC_LAYER_FRONT, aMMOffset); + aOutputData.PrintDrawingLayer(SC_LAYER_INTERN, aMMOffset); + aOutputData.PostPrintDrawingLayer(aMMOffset); // #i74768# + + // #114135# + delete pDrawView; +} + +// +// Drucken +// + +void lcl_FillHFParam( ScPrintHFParam& rParam, const SfxItemSet* pHFSet ) +{ + // nDistance muss vorher unterschiedlich initalisiert sein + + if ( pHFSet == NULL ) + { + rParam.bEnable = sal_False; + rParam.pBorder = NULL; + rParam.pBack = NULL; + rParam.pShadow = NULL; + } + else + { + rParam.bEnable = ((const SfxBoolItem&) pHFSet->Get(ATTR_PAGE_ON)).GetValue(); + rParam.bDynamic = ((const SfxBoolItem&) pHFSet->Get(ATTR_PAGE_DYNAMIC)).GetValue(); + rParam.bShared = ((const SfxBoolItem&) pHFSet->Get(ATTR_PAGE_SHARED)).GetValue(); + rParam.nHeight = ((const SvxSizeItem&) pHFSet->Get(ATTR_PAGE_SIZE)).GetSize().Height(); + const SvxLRSpaceItem* pHFLR = &(const SvxLRSpaceItem&) pHFSet->Get(ATTR_LRSPACE); + long nTmp; + nTmp = pHFLR->GetLeft(); + rParam.nLeft = nTmp < 0 ? 0 : sal_uInt16(nTmp); + nTmp = pHFLR->GetRight(); + rParam.nRight = nTmp < 0 ? 0 : sal_uInt16(nTmp); + rParam.pBorder = (const SvxBoxItem*) &pHFSet->Get(ATTR_BORDER); + rParam.pBack = (const SvxBrushItem*) &pHFSet->Get(ATTR_BACKGROUND); + rParam.pShadow = (const SvxShadowItem*)&pHFSet->Get(ATTR_SHADOW);; + +// jetzt doch wieder schon im Dialog: +// rParam.nHeight += rParam.nDistance; // nicht mehr im Dialog ??? + + if (rParam.pBorder) + rParam.nHeight += lcl_LineTotal( rParam.pBorder->GetTop() ) + + lcl_LineTotal( rParam.pBorder->GetBottom() ); + + rParam.nManHeight = rParam.nHeight; + } + + if (!rParam.bEnable) + rParam.nHeight = 0; +} + +// bNew = TRUE: benutzten Bereich aus dem Dokument suchen +// bNew = FALSE: nur ganze Zeilen/Spalten begrenzen + +sal_Bool ScPrintFunc::AdjustPrintArea( sal_Bool bNew ) +{ + SCCOL nOldEndCol = nEndCol; // nur wichtig bei !bNew + SCROW nOldEndRow = nEndRow; + sal_Bool bChangeCol = sal_True; // bei bNew werden beide angepasst + sal_Bool bChangeRow = sal_True; + + sal_Bool bNotes = aTableParam.bNotes; + if ( bNew ) + { + nStartCol = 0; + nStartRow = 0; + if (!pDoc->GetPrintArea( nPrintTab, nEndCol, nEndRow, bNotes )) + return sal_False; // nix + } + else + { + sal_Bool bFound = sal_True; + bChangeCol = ( nStartCol == 0 && nEndCol == MAXCOL ); + bChangeRow = ( nStartRow == 0 && nEndRow == MAXROW ); + sal_Bool bForcedChangeRow = sal_False; + + // #i53558# Crop entire column of old row limit to real print area with + // some fuzzyness. + if (!bChangeRow && nStartRow == 0) + { + SCROW nPAEndRow; + bFound = pDoc->GetPrintAreaVer( nPrintTab, nStartCol, nEndCol, nPAEndRow, bNotes ); + // Say we don't want to print more than ~1000 empty rows, which are + // about 14 pages intentionally left blank.. + const SCROW nFuzzy = 23*42; + if (nPAEndRow + nFuzzy < nEndRow) + { + bForcedChangeRow = sal_True; + nEndRow = nPAEndRow; + } + else + bFound = sal_True; // user seems to _want_ to print some empty rows + } + // TODO: in case we extend the number of columns we may have to do the + // same for horizontal cropping. + + if ( bChangeCol && bChangeRow ) + bFound = pDoc->GetPrintArea( nPrintTab, nEndCol, nEndRow, bNotes ); + else if ( bChangeCol ) + bFound = pDoc->GetPrintAreaHor( nPrintTab, nStartRow, nEndRow, nEndCol, bNotes ); + else if ( bChangeRow ) + bFound = pDoc->GetPrintAreaVer( nPrintTab, nStartCol, nEndCol, nEndRow, bNotes ); + + if (!bFound) + return sal_False; // leer + + if (bForcedChangeRow) + bChangeRow = sal_True; + } + + pDoc->ExtendMerge( nStartCol,nStartRow, nEndCol,nEndRow, nPrintTab, + sal_False, sal_True ); // kein Refresh, incl. Attrs + + if ( bChangeCol ) + { + OutputDevice* pRefDev = pDoc->GetPrinter(); // auch fuer Preview den Drucker nehmen + pRefDev->SetMapMode( MAP_PIXEL ); // wichtig fuer GetNeededSize + + pDoc->ExtendPrintArea( pRefDev, + nPrintTab, nStartCol, nStartRow, nEndCol, nEndRow ); + // nEndCol wird veraendert + } + + if ( nEndCol < MAXCOL && pDoc->HasAttrib( + nEndCol,nStartRow,nPrintTab, nEndCol,nEndRow,nPrintTab, HASATTR_SHADOW_RIGHT ) ) + ++nEndCol; + if ( nEndRow < MAXROW && pDoc->HasAttrib( + nStartCol,nEndRow,nPrintTab, nEndCol,nEndRow,nPrintTab, HASATTR_SHADOW_DOWN ) ) + ++nEndRow; + + if (!bChangeCol) nEndCol = nOldEndCol; + if (!bChangeRow) nEndRow = nOldEndRow; + + return sal_True; +} + +long ScPrintFunc::TextHeight( const EditTextObject* pObject ) +{ + if (!pObject) + return 0; + +// pEditEngine->SetPageNo( nTotalPages ); + pEditEngine->SetTextNewDefaults( *pObject, *pEditDefaults, sal_False ); + + return (long) pEditEngine->GetTextHeight(); +} + +// nZoom muss gesetzt sein !!! +// und der entsprechende Twip-MapMode eingestellt + +void ScPrintFunc::UpdateHFHeight( ScPrintHFParam& rParam ) +{ + DBG_ASSERT( aPageSize.Width(), "UpdateHFHeight ohne aPageSize"); + + if (rParam.bEnable && rParam.bDynamic) + { + // nHeight aus Inhalten berechnen + + MakeEditEngine(); + long nPaperWidth = ( aPageSize.Width() - nLeftMargin - nRightMargin - + rParam.nLeft - rParam.nRight ) * 100 / nZoom; + if (rParam.pBorder) + nPaperWidth -= ( rParam.pBorder->GetDistance(BOX_LINE_LEFT) + + rParam.pBorder->GetDistance(BOX_LINE_RIGHT) + + lcl_LineTotal(rParam.pBorder->GetLeft()) + + lcl_LineTotal(rParam.pBorder->GetRight()) ) * 100 / nZoom; + + if (rParam.pShadow && rParam.pShadow->GetLocation() != SVX_SHADOW_NONE) + nPaperWidth -= ( rParam.pShadow->CalcShadowSpace(SHADOW_LEFT) + + rParam.pShadow->CalcShadowSpace(SHADOW_RIGHT) ) * 100L / nZoom; + + pEditEngine->SetPaperSize( Size( nPaperWidth, 10000 ) ); + + long nMaxHeight = 0; + if ( rParam.pLeft ) + { + nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pLeft->GetLeftArea() ) ); + nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pLeft->GetCenterArea() ) ); + nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pLeft->GetRightArea() ) ); + } + if ( rParam.pRight ) + { + nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pRight->GetLeftArea() ) ); + nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pRight->GetCenterArea() ) ); + nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pRight->GetRightArea() ) ); + } + + rParam.nHeight = nMaxHeight + rParam.nDistance; + if (rParam.pBorder) + rParam.nHeight += rParam.pBorder->GetDistance(BOX_LINE_TOP) + + rParam.pBorder->GetDistance(BOX_LINE_BOTTOM) + + lcl_LineTotal( rParam.pBorder->GetTop() ) + + lcl_LineTotal( rParam.pBorder->GetBottom() ); + if (rParam.pShadow && rParam.pShadow->GetLocation() != SVX_SHADOW_NONE) + rParam.nHeight += rParam.pShadow->CalcShadowSpace(SHADOW_TOP) + + rParam.pShadow->CalcShadowSpace(SHADOW_BOTTOM); + + if (rParam.nHeight < rParam.nManHeight) + rParam.nHeight = rParam.nManHeight; // eingestelltes Minimum + } +} + +void ScPrintFunc::InitParam( const ScPrintOptions* pOptions ) +{ + if (!pParamSet) + return; + + // TabPage "Seite" + const SvxLRSpaceItem* pLRItem = (const SvxLRSpaceItem*) &pParamSet->Get( ATTR_LRSPACE ); + long nTmp; + nTmp = pLRItem->GetLeft(); + nLeftMargin = nTmp < 0 ? 0 : sal_uInt16(nTmp); + nTmp = pLRItem->GetRight(); + nRightMargin = nTmp < 0 ? 0 : sal_uInt16(nTmp); + const SvxULSpaceItem* pULItem = (const SvxULSpaceItem*) &pParamSet->Get( ATTR_ULSPACE ); + nTopMargin = pULItem->GetUpper(); + nBottomMargin = pULItem->GetLower(); + + const SvxPageItem* pPageItem = (const SvxPageItem*) &pParamSet->Get( ATTR_PAGE ); + nPageUsage = pPageItem->GetPageUsage(); + bLandscape = pPageItem->IsLandscape(); + aFieldData.eNumType = pPageItem->GetNumType(); + + bCenterHor = ((const SfxBoolItem&) pParamSet->Get(ATTR_PAGE_HORCENTER)).GetValue(); + bCenterVer = ((const SfxBoolItem&) pParamSet->Get(ATTR_PAGE_VERCENTER)).GetValue(); + + aPageSize = ((const SvxSizeItem&) pParamSet->Get(ATTR_PAGE_SIZE)).GetSize(); + if ( !aPageSize.Width() || !aPageSize.Height() ) + { + DBG_ERROR("PageSize Null ?!?!?"); + aPageSize = SvxPaperInfo::GetPaperSize( PAPER_A4 ); + } + + pBorderItem = (const SvxBoxItem*) &pParamSet->Get(ATTR_BORDER); + pBackgroundItem = (const SvxBrushItem*) &pParamSet->Get(ATTR_BACKGROUND); + pShadowItem = (const SvxShadowItem*) &pParamSet->Get(ATTR_SHADOW); + + // TabPage "Kopfzeile" + + aHdr.pLeft = (const ScPageHFItem*) &pParamSet->Get(ATTR_PAGE_HEADERLEFT); // Inhalt + aHdr.pRight = (const ScPageHFItem*) &pParamSet->Get(ATTR_PAGE_HEADERRIGHT); + + const SvxSetItem* pHeaderSetItem; + const SfxItemSet* pHeaderSet = NULL; + if ( pParamSet->GetItemState( ATTR_PAGE_HEADERSET, sal_False, + (const SfxPoolItem**)&pHeaderSetItem ) == SFX_ITEM_SET ) + { + pHeaderSet = &pHeaderSetItem->GetItemSet(); + // Kopfzeile hat unteren Abstand + aHdr.nDistance = ((const SvxULSpaceItem&) pHeaderSet->Get(ATTR_ULSPACE)).GetLower(); + } + lcl_FillHFParam( aHdr, pHeaderSet ); + + // TabPage "Fusszeile" + + aFtr.pLeft = (const ScPageHFItem*) &pParamSet->Get(ATTR_PAGE_FOOTERLEFT); // Inhalt + aFtr.pRight = (const ScPageHFItem*) &pParamSet->Get(ATTR_PAGE_FOOTERRIGHT); + + const SvxSetItem* pFooterSetItem; + const SfxItemSet* pFooterSet = NULL; + if ( pParamSet->GetItemState( ATTR_PAGE_FOOTERSET, sal_False, + (const SfxPoolItem**)&pFooterSetItem ) == SFX_ITEM_SET ) + { + pFooterSet = &pFooterSetItem->GetItemSet(); + // Fusszeile hat oberen Abstand + aFtr.nDistance = ((const SvxULSpaceItem&) pFooterSet->Get(ATTR_ULSPACE)).GetUpper(); + } + lcl_FillHFParam( aFtr, pFooterSet ); + + //------------------------------------------------------ + // Table-/Area-Params aus einzelnen Items zusammenbauen: + //------------------------------------------------------ + // TabPage "Tabelle" + + const SfxUInt16Item* pScaleItem = NULL; + const ScPageScaleToItem* pScaleToItem = NULL; + const SfxUInt16Item* pScaleToPagesItem = NULL; + SfxItemState eState; + + eState = pParamSet->GetItemState( ATTR_PAGE_SCALE, sal_False, + (const SfxPoolItem**)&pScaleItem ); + if ( SFX_ITEM_DEFAULT == eState ) + pScaleItem = (const SfxUInt16Item*) + &pParamSet->GetPool()->GetDefaultItem( ATTR_PAGE_SCALE ); + + eState = pParamSet->GetItemState( ATTR_PAGE_SCALETO, sal_False, + (const SfxPoolItem**)&pScaleToItem ); + if ( SFX_ITEM_DEFAULT == eState ) + pScaleToItem = (const ScPageScaleToItem*) + &pParamSet->GetPool()->GetDefaultItem( ATTR_PAGE_SCALETO ); + + eState = pParamSet->GetItemState( ATTR_PAGE_SCALETOPAGES, sal_False, + (const SfxPoolItem**)&pScaleToPagesItem ); + if ( SFX_ITEM_DEFAULT == eState ) + pScaleToPagesItem = (const SfxUInt16Item*) + &pParamSet->GetPool()->GetDefaultItem( ATTR_PAGE_SCALETOPAGES ); + + DBG_ASSERT( pScaleItem && pScaleToItem && pScaleToPagesItem, "Missing ScaleItem! :-/" ); + + aTableParam.bCellContent = sal_True; + aTableParam.bNotes = GET_BOOL(pParamSet,ATTR_PAGE_NOTES); + aTableParam.bGrid = GET_BOOL(pParamSet,ATTR_PAGE_GRID); + aTableParam.bHeaders = GET_BOOL(pParamSet,ATTR_PAGE_HEADERS); + aTableParam.bFormulas = GET_BOOL(pParamSet,ATTR_PAGE_FORMULAS); + aTableParam.bNullVals = GET_BOOL(pParamSet,ATTR_PAGE_NULLVALS); + aTableParam.bCharts = GET_SHOW(pParamSet,ATTR_PAGE_CHARTS); + aTableParam.bObjects = GET_SHOW(pParamSet,ATTR_PAGE_OBJECTS); + aTableParam.bDrawings = GET_SHOW(pParamSet,ATTR_PAGE_DRAWINGS); + aTableParam.bTopDown = GET_BOOL(pParamSet,ATTR_PAGE_TOPDOWN); + aTableParam.bLeftRight = !aTableParam.bLeftRight; + aTableParam.nFirstPageNo = GET_USHORT(pParamSet,ATTR_PAGE_FIRSTPAGENO); + if (!aTableParam.nFirstPageNo) + aTableParam.nFirstPageNo = (sal_uInt16) nPageStart; // von vorheriger Tabelle + + if ( pScaleItem && pScaleToItem && pScaleToPagesItem ) + { + sal_uInt16 nScaleAll = pScaleItem->GetValue(); + sal_uInt16 nScaleToPages = pScaleToPagesItem->GetValue(); + + aTableParam.bScaleNone = (nScaleAll == 100); + aTableParam.bScaleAll = (nScaleAll > 0 ); + aTableParam.bScaleTo = pScaleToItem->IsValid(); + aTableParam.bScalePageNum = (nScaleToPages > 0 ); + aTableParam.nScaleAll = nScaleAll; + aTableParam.nScaleWidth = pScaleToItem->GetWidth(); + aTableParam.nScaleHeight = pScaleToItem->GetHeight(); + aTableParam.nScalePageNum = nScaleToPages; + } + else + { + aTableParam.bScaleNone = sal_True; + aTableParam.bScaleAll = sal_False; + aTableParam.bScaleTo = sal_False; + aTableParam.bScalePageNum = sal_False; + aTableParam.nScaleAll = 0; + aTableParam.nScaleWidth = 0; + aTableParam.nScaleHeight = 0; + aTableParam.nScalePageNum = 0; + } + + // skip empty pages only if options with that flag are passed + aTableParam.bSkipEmpty = pOptions && pOptions->GetSkipEmpty(); + if ( pPageData ) + aTableParam.bSkipEmpty = sal_False; + // Wenn pPageData gesetzt ist, interessieren fuer die Umbruch-Vorschau + // nur die Umbrueche, leere Seiten werden nicht speziell behandelt + + //------------------------------------------------------ + // TabPage "Bereiche": + //------------------------------------------------------ + + //! alle PrintAreas der Tabelle durchgehen !!! + const ScRange* pPrintArea = pDoc->GetPrintRange( nPrintTab, 0 ); + const ScRange* pRepeatCol = pDoc->GetRepeatColRange( nPrintTab ); + const ScRange* pRepeatRow = pDoc->GetRepeatRowRange( nPrintTab ); + + // ATTR_PAGE_PRINTTABLES wird ignoriert + + if ( pUserArea ) // UserArea (Selektion) hat Vorrang + { + bPrintCurrentTable = + aAreaParam.bPrintArea = sal_True; // Selektion + aAreaParam.aPrintArea = *pUserArea; + + // Die Tabellen-Abfrage ist schon in DocShell::Print, hier immer + aAreaParam.aPrintArea.aStart.SetTab(nPrintTab); + aAreaParam.aPrintArea.aEnd.SetTab(nPrintTab); + +// lcl_LimitRange( aAreaParam.aPrintArea, nPrintTab ); // ganze Zeilen/Spalten... + } + else if ( pDoc->HasPrintRange() ) + { + if ( pPrintArea ) // mindestens eine gesetzt ? + { + bPrintCurrentTable = + aAreaParam.bPrintArea = sal_True; + aAreaParam.aPrintArea = *pPrintArea; + + bMultiArea = ( pDoc->GetPrintRangeCount(nPrintTab) > 1 ); + } + else + { + // do not print hidden sheets with "Print entire sheet" flag + bPrintCurrentTable = pDoc->IsPrintEntireSheet( nPrintTab ) && pDoc->IsVisible( nPrintTab ); + aAreaParam.bPrintArea = !bPrintCurrentTable; // otherwise the table is always counted + } + } + else + { + // #74834# don't print hidden tables if there's no print range defined there + if ( pDoc->IsVisible( nPrintTab ) ) + { + aAreaParam.bPrintArea = sal_False; + bPrintCurrentTable = sal_True; + } + else + { + aAreaParam.bPrintArea = sal_True; // otherwise the table is always counted + bPrintCurrentTable = sal_False; + } + } + + if ( pRepeatCol ) + { + aAreaParam.bRepeatCol = sal_True; + aAreaParam.aRepeatCol = *pRepeatCol; + nRepeatStartCol = pRepeatCol->aStart.Col(); + nRepeatEndCol = pRepeatCol->aEnd .Col(); + } + else + { + aAreaParam.bRepeatCol = sal_False; + nRepeatStartCol = nRepeatEndCol = SCCOL_REPEAT_NONE; + } + + if ( pRepeatRow ) + { + aAreaParam.bRepeatRow = sal_True; + aAreaParam.aRepeatRow = *pRepeatRow; + nRepeatStartRow = pRepeatRow->aStart.Row(); + nRepeatEndRow = pRepeatRow->aEnd .Row(); + } + else + { + aAreaParam.bRepeatRow = sal_False; + nRepeatStartRow = nRepeatEndRow = SCROW_REPEAT_NONE; + } + + // + // Seiten aufteilen + // + + if (!bState) + { + nTabPages = CountPages(); // berechnet auch Zoom + nTotalPages = nTabPages; + nTotalPages += CountNotePages(); + } + else + { + CalcPages(); // nur Umbrueche suchen + CountNotePages(); // Notizen zaehlen, auch wenn Seitenzahl schon bekannt + } + + if (nDocPages) + aFieldData.nTotalPages = nDocPages; + else + aFieldData.nTotalPages = nTotalPages; + + SetDateTime( Date(), Time() ); + + aFieldData.aTitle = pDocShell->GetTitle(); + const INetURLObject& rURLObj = pDocShell->GetMedium()->GetURLObject(); + aFieldData.aLongDocName = rURLObj.GetMainURL( INetURLObject::DECODE_UNAMBIGUOUS ); + if ( aFieldData.aLongDocName.Len() ) + aFieldData.aShortDocName = rURLObj.GetName( INetURLObject::DECODE_UNAMBIGUOUS ); + else + aFieldData.aShortDocName = aFieldData.aLongDocName = aFieldData.aTitle; + + // Druckereinstellungen (Orientation, Paper) jetzt erst bei DoPrint +} + +Size ScPrintFunc::GetDataSize() const +{ + Size aSize = aPageSize; + aSize.Width() -= nLeftMargin + nRightMargin; + aSize.Height() -= nTopMargin + nBottomMargin; + aSize.Height() -= aHdr.nHeight + aFtr.nHeight; + return aSize; +} + +void ScPrintFunc::GetScaleData( Size& rPhysSize, long& rDocHdr, long& rDocFtr ) +{ + rPhysSize = aPageSize; + rPhysSize.Width() -= nLeftMargin + nRightMargin; + rPhysSize.Height() -= nTopMargin + nBottomMargin; + + rDocHdr = aHdr.nHeight; + rDocFtr = aFtr.nHeight; +} + +void ScPrintFunc::SetDateTime( const Date& rDate, const Time& rTime ) +{ + aFieldData.aDate = rDate; + aFieldData.aTime = rTime; +} + +void lcl_DrawGraphic( const Graphic &rGraphic, OutputDevice *pOut, + const Rectangle &rGrf, const Rectangle &rOut ) +{ + const FASTBOOL bNotInside = !rOut.IsInside( rGrf ); + if ( bNotInside ) + { + pOut->Push(); + pOut->IntersectClipRegion( rOut ); + } + + ((Graphic&)rGraphic).Draw( pOut, rGrf.TopLeft(), rGrf.GetSize() ); + + if ( bNotInside ) + pOut->Pop(); +} + +void lcl_DrawGraphic( const SvxBrushItem &rBrush, OutputDevice *pOut, OutputDevice* pRefDev, + const Rectangle &rOrg, const Rectangle &rOut ) +{ + Size aGrfSize(0,0); + const Graphic *pGraphic = rBrush.GetGraphic(); + SvxGraphicPosition ePos; + if ( pGraphic && pGraphic->IsSupportedGraphic() ) + { + const MapMode aMapMM( MAP_100TH_MM ); + if ( pGraphic->GetPrefMapMode().GetMapUnit() == MAP_PIXEL ) + aGrfSize = pRefDev->PixelToLogic( pGraphic->GetPrefSize(), aMapMM ); + else + aGrfSize = OutputDevice::LogicToLogic( pGraphic->GetPrefSize(), + pGraphic->GetPrefMapMode(), aMapMM ); + ePos = rBrush.GetGraphicPos(); + } + else + ePos = GPOS_NONE; + + Point aPos; + Size aDrawSize = aGrfSize; + + FASTBOOL bDraw = sal_True; +// FASTBOOL bRetouche = sal_True; + switch ( ePos ) + { + case GPOS_LT: aPos = rOrg.TopLeft(); + break; + case GPOS_MT: aPos.Y() = rOrg.Top(); + aPos.X() = rOrg.Left() + rOrg.GetSize().Width()/2 - aGrfSize.Width()/2; + break; + case GPOS_RT: aPos.Y() = rOrg.Top(); + aPos.X() = rOrg.Right() - aGrfSize.Width(); + break; + + case GPOS_LM: aPos.Y() = rOrg.Top() + rOrg.GetSize().Height()/2 - aGrfSize.Height()/2; + aPos.X() = rOrg.Left(); + break; + case GPOS_MM: aPos.Y() = rOrg.Top() + rOrg.GetSize().Height()/2 - aGrfSize.Height()/2; + aPos.X() = rOrg.Left() + rOrg.GetSize().Width()/2 - aGrfSize.Width()/2; + break; + case GPOS_RM: aPos.Y() = rOrg.Top() + rOrg.GetSize().Height()/2 - aGrfSize.Height()/2; + aPos.X() = rOrg.Right() - aGrfSize.Width(); + break; + + case GPOS_LB: aPos.Y() = rOrg.Bottom() - aGrfSize.Height(); + aPos.X() = rOrg.Left(); + break; + case GPOS_MB: aPos.Y() = rOrg.Bottom() - aGrfSize.Height(); + aPos.X() = rOrg.Left() + rOrg.GetSize().Width()/2 - aGrfSize.Width()/2; + break; + case GPOS_RB: aPos.Y() = rOrg.Bottom() - aGrfSize.Height(); + aPos.X() = rOrg.Right() - aGrfSize.Width(); + break; + + case GPOS_AREA: + aPos = rOrg.TopLeft(); + aDrawSize = rOrg.GetSize(); +// bRetouche = sal_False; + break; + case GPOS_TILED: + { + // #104004# use GraphicObject::DrawTiled instead of an own loop + // (pixel rounding is handled correctly, and a very small bitmap + // is duplicated into a bigger one for better performance) + + GraphicObject aObject( *pGraphic ); + + if( pOut->GetPDFWriter() && + (aObject.GetType() == GRAPHIC_BITMAP || aObject.GetType() == GRAPHIC_DEFAULT) ) + { + // #104004# For PDF export, every draw + // operation for bitmaps takes a noticeable + // amount of place (~50 characters). Thus, + // optimize between tile bitmap size and + // number of drawing operations here. + // + // A_out + // n_chars = k1 * ---------- + k2 * A_bitmap + // A_bitmap + // + // minimum n_chars is obtained for (derive for + // A_bitmap, set to 0, take positive + // solution): + // k1 + // A_bitmap = Sqrt( ---- A_out ) + // k2 + // + // where k1 is the number of chars per draw + // operation, and k2 is the number of chars + // per bitmap pixel. This is approximately 50 + // and 7 for current PDF writer, respectively. + // + const double k1( 50 ); + const double k2( 7 ); + const Size aSize( rOrg.GetSize() ); + const double Abitmap( k1/k2 * aSize.Width()*aSize.Height() ); + + aObject.DrawTiled( pOut, rOrg, aGrfSize, Size(0,0), + NULL, GRFMGR_DRAW_STANDARD, + ::std::max( 128, static_cast<int>( sqrt(sqrt( Abitmap)) + .5 ) ) ); + } + else + { + aObject.DrawTiled( pOut, rOrg, aGrfSize, Size(0,0) ); + } + + bDraw = sal_False; +// bRetouche = sal_False; + } + break; + + case GPOS_NONE: + bDraw = sal_False; + break; + + default: DBG_ASSERT( !pOut, "new Graphic position?" ); + } + Rectangle aGrf( aPos,aDrawSize ); + if ( bDraw && aGrf.IsOver( rOut ) ) + { + lcl_DrawGraphic( *pGraphic, pOut, aGrf, rOut ); + } +} + +// Rahmen wird nach innen gezeichnet + +void ScPrintFunc::DrawBorder( long nScrX, long nScrY, long nScrW, long nScrH, + const SvxBoxItem* pBorderData, const SvxBrushItem* pBackground, + const SvxShadowItem* pShadow ) +{ + //! direkte Ausgabe aus SvxBoxItem !!! + + if (pBorderData) + if ( !pBorderData->GetTop() && !pBorderData->GetBottom() && !pBorderData->GetLeft() && + !pBorderData->GetRight() ) + pBorderData = NULL; + + if (!pBorderData && !pBackground && !pShadow) + return; // nichts zu tun + + long nLeft = 0; + long nRight = 0; + long nTop = 0; + long nBottom = 0; + + // aFrameRect - aussen um die Umrandung, ohne Schatten + if ( pShadow && pShadow->GetLocation() != SVX_SHADOW_NONE ) + { + nLeft += (long) ( pShadow->CalcShadowSpace(SHADOW_LEFT) * nScaleX ); + nRight += (long) ( pShadow->CalcShadowSpace(SHADOW_RIGHT) * nScaleX ); + nTop += (long) ( pShadow->CalcShadowSpace(SHADOW_TOP) * nScaleY ); + nBottom += (long) ( pShadow->CalcShadowSpace(SHADOW_BOTTOM) * nScaleY ); + } + Rectangle aFrameRect( Point(nScrX+nLeft, nScrY+nTop), + Size(nScrW-nLeft-nRight, nScrH-nTop-nBottom) ); + + // Mitte der Umrandung, um Linien ueber OutputData zu zeichnen: + if (pBorderData) + { + nLeft += (long) ( lcl_LineTotal(pBorderData->GetLeft()) * nScaleX / 2 ); + nRight += (long) ( lcl_LineTotal(pBorderData->GetRight()) * nScaleX / 2 ); + nTop += (long) ( lcl_LineTotal(pBorderData->GetTop()) * nScaleY / 2 ); + nBottom += (long) ( lcl_LineTotal(pBorderData->GetBottom()) * nScaleY / 2 ); + } + long nEffHeight = nScrH - nTop - nBottom; + long nEffWidth = nScrW - nLeft - nRight; + if (nEffHeight<=0 || nEffWidth<=0) + return; // leer + + // #105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed sal_True) + sal_Bool bCellContrast = bUseStyleColor && + Application::GetSettings().GetStyleSettings().GetHighContrastMode(); + + if ( pBackground && !bCellContrast ) + { +// Rectangle aBackRect( Point(nScrX+nLeft, nScrY+nTop), Size(nEffWidth,nEffHeight) ); + if (pBackground->GetGraphicPos() != GPOS_NONE) + { + OutputDevice* pRefDev; + if ( bIsRender ) + pRefDev = pDev; // don't use printer for PDF + else + pRefDev = pDoc->GetPrinter(); // use printer also for preview + + lcl_DrawGraphic( *pBackground, pDev, pRefDev, aFrameRect, aFrameRect ); + } + else + { + pDev->SetFillColor(pBackground->GetColor()); + pDev->SetLineColor(); + pDev->DrawRect(aFrameRect); + } + } + + if ( pShadow && pShadow->GetLocation() != SVX_SHADOW_NONE ) + { + if ( bCellContrast ) + pDev->SetFillColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor ); + else + pDev->SetFillColor(pShadow->GetColor()); + pDev->SetLineColor(); + long nShadowX = (long) ( pShadow->GetWidth() * nScaleX ); + long nShadowY = (long) ( pShadow->GetWidth() * nScaleY ); + switch (pShadow->GetLocation()) + { + case SVX_SHADOW_TOPLEFT: + pDev->DrawRect( Rectangle( + aFrameRect.Left()-nShadowX, aFrameRect.Top()-nShadowY, + aFrameRect.Right()-nShadowX, aFrameRect.Top() ) ); + pDev->DrawRect( Rectangle( + aFrameRect.Left()-nShadowX, aFrameRect.Top()-nShadowY, + aFrameRect.Left(), aFrameRect.Bottom()-nShadowY ) ); + break; + case SVX_SHADOW_TOPRIGHT: + pDev->DrawRect( Rectangle( + aFrameRect.Left()+nShadowX, aFrameRect.Top()-nShadowY, + aFrameRect.Right()+nShadowX, aFrameRect.Top() ) ); + pDev->DrawRect( Rectangle( + aFrameRect.Right(), aFrameRect.Top()-nShadowY, + aFrameRect.Right()+nShadowX, aFrameRect.Bottom()-nShadowY ) ); + break; + case SVX_SHADOW_BOTTOMLEFT: + pDev->DrawRect( Rectangle( + aFrameRect.Left()-nShadowX, aFrameRect.Bottom(), + aFrameRect.Right()-nShadowX, aFrameRect.Bottom()+nShadowY ) ); + pDev->DrawRect( Rectangle( + aFrameRect.Left()-nShadowX, aFrameRect.Top()+nShadowY, + aFrameRect.Left(), aFrameRect.Bottom()+nShadowY ) ); + break; + case SVX_SHADOW_BOTTOMRIGHT: + pDev->DrawRect( Rectangle( + aFrameRect.Left()+nShadowX, aFrameRect.Bottom(), + aFrameRect.Right()+nShadowX, aFrameRect.Bottom()+nShadowY ) ); + pDev->DrawRect( Rectangle( + aFrameRect.Right(), aFrameRect.Top()+nShadowY, + aFrameRect.Right()+nShadowX, aFrameRect.Bottom()+nShadowY ) ); + break; + default: + { + // added to avoid warnings + } + } + } + + if (pBorderData) + { + ScDocument* pBorderDoc = new ScDocument( SCDOCMODE_UNDO ); + pBorderDoc->InitUndo( pDoc, 0,0, sal_True,sal_True ); + if (pBorderData) + pBorderDoc->ApplyAttr( 0,0,0, *pBorderData ); + + ScTableInfo aTabInfo; + pBorderDoc->FillInfo( aTabInfo, 0,0, 0,0, 0, + nScaleX, nScaleY, sal_False, sal_False ); + DBG_ASSERT(aTabInfo.mnArrCount,"nArrCount == 0"); + + aTabInfo.mpRowInfo[1].nHeight = (sal_uInt16) nEffHeight; + aTabInfo.mpRowInfo[0].pCellInfo[1].nWidth = + aTabInfo.mpRowInfo[1].pCellInfo[1].nWidth = (sal_uInt16) nEffWidth; + + ScOutputData aOutputData( pDev, OUTTYPE_PRINTER, aTabInfo, pBorderDoc, 0, + nScrX+nLeft, nScrY+nTop, 0,0, 0,0, nScaleX, nScaleY ); + aOutputData.SetUseStyleColor( bUseStyleColor ); + +// pDev->SetMapMode(aTwipMode); + + if (pBorderData) + aOutputData.DrawFrame(); + + delete pBorderDoc; + } +} + +void ScPrintFunc::PrintColHdr( SCCOL nX1, SCCOL nX2, long nScrX, long nScrY ) +{ + sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nPrintTab ); + long nLayoutSign = bLayoutRTL ? -1 : 1; + + Size aOnePixel = pDev->PixelToLogic(Size(1,1)); + long nOneX = aOnePixel.Width(); + long nOneY = aOnePixel.Height(); + SCCOL nCol; + + long nHeight = (long) (PRINT_HEADER_HEIGHT * nScaleY); + long nEndY = nScrY + nHeight - nOneY; + + long nPosX = nScrX; + if ( bLayoutRTL ) + { + for (nCol=nX1; nCol<=nX2; nCol++) + nPosX += (long)( pDoc->GetColWidth( nCol, nPrintTab ) * nScaleX ); + } + else + nPosX -= nOneX; + long nPosY = nScrY - nOneY; + String aText; + + for (nCol=nX1; nCol<=nX2; nCol++) + { + sal_uInt16 nDocW = pDoc->GetColWidth( nCol, nPrintTab ); + if (nDocW) + { + long nWidth = (long) (nDocW * nScaleX); + long nEndX = nPosX + nWidth * nLayoutSign; + + pDev->DrawRect( Rectangle( nPosX,nPosY,nEndX,nEndY ) ); + + aText = ::ScColToAlpha( nCol); + long nTextWidth = pDev->GetTextWidth(aText); + long nTextHeight = pDev->GetTextHeight(); + long nAddX = ( nWidth - nTextWidth ) / 2; + long nAddY = ( nHeight - nTextHeight ) / 2; + long nTextPosX = nPosX+nAddX; + if ( bLayoutRTL ) + nTextPosX -= nWidth; + pDev->DrawText( Point( nTextPosX,nPosY+nAddY ), aText ); + + nPosX = nEndX; + } + } +} + +void ScPrintFunc::PrintRowHdr( SCROW nY1, SCROW nY2, long nScrX, long nScrY ) +{ + Size aOnePixel = pDev->PixelToLogic(Size(1,1)); + long nOneX = aOnePixel.Width(); + long nOneY = aOnePixel.Height(); + + sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nPrintTab ); + + long nWidth = (long) (PRINT_HEADER_WIDTH * nScaleX); + long nEndX = nScrX + nWidth; + long nPosX = nScrX; + if ( !bLayoutRTL ) + { + nEndX -= nOneX; + nPosX -= nOneX; + } + long nPosY = nScrY - nOneY; + String aText; + + for (SCROW nRow=nY1; nRow<=nY2; nRow++) + { + sal_uInt16 nDocH = pDoc->GetRowHeight( nRow, nPrintTab ); + if (nDocH) + { + long nHeight = (long) (nDocH * nScaleY); + long nEndY = nPosY + nHeight; + + pDev->DrawRect( Rectangle( nPosX,nPosY,nEndX,nEndY ) ); + + aText = String::CreateFromInt32( nRow+1 ); + long nTextWidth = pDev->GetTextWidth(aText); + long nTextHeight = pDev->GetTextHeight(); + long nAddX = ( nWidth - nTextWidth ) / 2; + long nAddY = ( nHeight - nTextHeight ) / 2; + pDev->DrawText( Point( nPosX+nAddX,nPosY+nAddY ), aText ); + + nPosY = nEndY; + } + } +} + +void ScPrintFunc::LocateColHdr( SCCOL nX1, SCCOL nX2, long nScrX, long nScrY, + sal_Bool bRepCol, ScPreviewLocationData& rLocationData ) +{ + Size aOnePixel = pDev->PixelToLogic(Size(1,1)); + long nOneX = aOnePixel.Width(); + long nOneY = aOnePixel.Height(); + + long nHeight = (long) (PRINT_HEADER_HEIGHT * nScaleY); + long nEndY = nScrY + nHeight - nOneY; + + long nPosX = nScrX - nOneX; + for (SCCOL nCol=nX1; nCol<=nX2; nCol++) + { + sal_uInt16 nDocW = pDoc->GetColWidth( nCol, nPrintTab ); + if (nDocW) + nPosX += (long) (nDocW * nScaleX); + } + Rectangle aCellRect( nScrX, nScrY, nPosX, nEndY ); + rLocationData.AddColHeaders( aCellRect, nX1, nX2, bRepCol ); +} + +void ScPrintFunc::LocateRowHdr( SCROW nY1, SCROW nY2, long nScrX, long nScrY, + sal_Bool bRepRow, ScPreviewLocationData& rLocationData ) +{ + Size aOnePixel = pDev->PixelToLogic(Size(1,1)); + long nOneX = aOnePixel.Width(); + long nOneY = aOnePixel.Height(); + + sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nPrintTab ); + + long nWidth = (long) (PRINT_HEADER_WIDTH * nScaleX); + long nEndX = nScrX + nWidth; + if ( !bLayoutRTL ) + nEndX -= nOneX; + + long nPosY = nScrY - nOneY; + nPosY += pDoc->GetScaledRowHeight( nY1, nY2, nPrintTab, nScaleY); + Rectangle aCellRect( nScrX, nScrY, nEndX, nPosY ); + rLocationData.AddRowHeaders( aCellRect, nY1, nY2, bRepRow ); +} + +void ScPrintFunc::LocateArea( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, + long nScrX, long nScrY, sal_Bool bRepCol, sal_Bool bRepRow, + ScPreviewLocationData& rLocationData ) +{ + // get MapMode for drawing objects (same MapMode as in ScOutputData::PrintDrawingLayer) + + Point aLogPos = OutputDevice::LogicToLogic(Point(nScrX,nScrY), aOffsetMode, aLogicMode); + long nLogStX = aLogPos.X(); + long nLogStY = aLogPos.Y(); + + SCCOL nCol; + Point aTwipOffset; + for (nCol=0; nCol<nX1; nCol++) + aTwipOffset.X() -= pDoc->GetColWidth( nCol, nPrintTab ); + aTwipOffset.Y() -= pDoc->GetRowHeight( 0, nY1-1, nPrintTab ); + + Point aMMOffset( aTwipOffset ); + aMMOffset.X() = (long)(aMMOffset.X() * HMM_PER_TWIPS); + aMMOffset.Y() = (long)(aMMOffset.Y() * HMM_PER_TWIPS); + aMMOffset += Point( nLogStX, nLogStY ); + MapMode aDrawMapMode( MAP_100TH_MM, aMMOffset, aLogicMode.GetScaleX(), aLogicMode.GetScaleY() ); + + // get pixel rectangle + + Size aOnePixel = pDev->PixelToLogic(Size(1,1)); + long nOneX = aOnePixel.Width(); + long nOneY = aOnePixel.Height(); + + long nPosX = nScrX - nOneX; + for (nCol=nX1; nCol<=nX2; nCol++) + { + sal_uInt16 nDocW = pDoc->GetColWidth( nCol, nPrintTab ); + if (nDocW) + nPosX += (long) (nDocW * nScaleX); + } + + long nPosY = nScrY - nOneY; + nPosY += pDoc->GetScaledRowHeight( nY1, nY2, nPrintTab, nScaleY); + Rectangle aCellRect( nScrX, nScrY, nPosX, nPosY ); + rLocationData.AddCellRange( aCellRect, ScRange( nX1,nY1,nPrintTab, nX2,nY2,nPrintTab ), + bRepCol, bRepRow, aDrawMapMode ); +} + +void ScPrintFunc::PrintArea( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, + long nScrX, long nScrY, + sal_Bool bShLeft, sal_Bool bShTop, sal_Bool bShRight, sal_Bool bShBottom ) +{ + // #i47547# nothing to do if the end of the print area is before the end of + // the repeat columns/rows (don't use negative size for ScOutputData) + if ( nX2 < nX1 || nY2 < nY1 ) + return; + + //! Flag bei FillInfo uebergeben !!!!! + ScRange aERange; + sal_Bool bEmbed = pDoc->IsEmbedded(); + if (bEmbed) + { + pDoc->GetEmbedded(aERange); + pDoc->ResetEmbedded(); + } + + Point aPos = OutputDevice::LogicToLogic(Point(nScrX,nScrY), aOffsetMode, aLogicMode); + long nLogStX = aPos.X(); + long nLogStY = aPos.Y(); + + // Daten zusammenstellen + + ScTableInfo aTabInfo; + pDoc->FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nPrintTab, + nScaleX, nScaleY, sal_True, aTableParam.bFormulas ); + lcl_HidePrint( aTabInfo, nX1, nX2 ); + + if (bEmbed) + pDoc->SetEmbedded(aERange); + + ScOutputData aOutputData( pDev, OUTTYPE_PRINTER, aTabInfo, pDoc, nPrintTab, + nScrX, nScrY, nX1, nY1, nX2, nY2, nScaleX, nScaleY ); + + // #114135# + aOutputData.SetDrawView( pDrawView ); + + // test if all paint parts are hidden, then a paint is not necessary at all + const Point aMMOffset(aOutputData.PrePrintDrawingLayer(nLogStX, nLogStY)); + const bool bHideAllDrawingLayer( pDrawView && pDrawView->getHideOle() && pDrawView->getHideChart() + && pDrawView->getHideDraw() && pDrawView->getHideFormControl() ); + + if(!bHideAllDrawingLayer) + { + pDev->SetMapMode(aLogicMode); + // hier kein Clipping setzen (Mapmode wird verschoben) + + // #i72502# + aOutputData.PrintDrawingLayer(SC_LAYER_BACK, aMMOffset); + } + + pDev->SetMapMode(aOffsetMode); + + aOutputData.SetShowFormulas( aTableParam.bFormulas ); + aOutputData.SetShowNullValues( aTableParam.bNullVals ); + aOutputData.SetUseStyleColor( bUseStyleColor ); + + Color aGridColor( COL_BLACK ); + if ( bUseStyleColor ) + aGridColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor ); + aOutputData.SetGridColor( aGridColor ); + + if ( !pPrinter ) + { + OutputDevice* pRefDev = pDoc->GetPrinter(); // auch fuer Preview den Drucker nehmen + Fraction aPrintFrac( nZoom, 100 ); // ohne nManualZoom + // MapMode, wie er beim Drucken herauskommen wuerde: + pRefDev->SetMapMode( MapMode( MAP_100TH_MM, Point(), aPrintFrac, aPrintFrac ) ); + + // when rendering (PDF), don't use printer as ref device, but printer's MapMode + // has to be set anyway, as charts still use it (#106409#) + if ( !bIsRender ) + aOutputData.SetRefDevice( pRefDev ); + } + +// aOutputData.SetMetaFileMode(sal_True); + if( aTableParam.bCellContent ) + aOutputData.DrawBackground(); + + pDev->SetClipRegion( Rectangle( aPos, Size( aOutputData.GetScrW(), aOutputData.GetScrH() ) ) ); + pDev->SetClipRegion(); + +// aOutputData.SetMetaFileMode(sal_False); + if( aTableParam.bCellContent ) + { + aOutputData.DrawExtraShadow( bShLeft, bShTop, bShRight, bShBottom ); + aOutputData.DrawFrame(); + aOutputData.DrawStrings(); + + // pDev->SetMapMode(aLogicMode); + aOutputData.DrawEdit(sal_False); + } + +// pDev->SetMapMode(aOffsetMode); + if (aTableParam.bGrid) + aOutputData.DrawGrid( sal_True, sal_False ); // keine Seitenumbrueche + +/*!!!!!!!!!!! Notizen in Tabelle markieren ?????????????????????????? + + if (aTableParam.bNotes) + { + pDev->SetMapMode(aOffsetMode); + aOutputData.PrintNoteMarks(aNotePosList); + pDev->SetMapMode(aLogicMode); + } +*/ + + aOutputData.AddPDFNotes(); // has no effect if not rendering PDF with notes enabled + +// pDev->SetMapMode(aDrawMode); + + // test if all paint parts are hidden, then a paint is not necessary at all + if(!bHideAllDrawingLayer) + { + // #i72502# + aOutputData.PrintDrawingLayer(SC_LAYER_FRONT, aMMOffset); + } + + // #i72502# + aOutputData.PrintDrawingLayer(SC_LAYER_INTERN, aMMOffset); + aOutputData.PostPrintDrawingLayer(aMMOffset); // #i74768# +} + +sal_Bool ScPrintFunc::IsMirror( long nPageNo ) // Raender spiegeln ? +{ + SvxPageUsage eUsage = (SvxPageUsage) ( nPageUsage & 0x000f ); + return ( eUsage == SVX_PAGE_MIRROR && (nPageNo & 1) ); +} + +sal_Bool ScPrintFunc::IsLeft( long nPageNo ) // linke Fussnoten ? +{ + SvxPageUsage eUsage = (SvxPageUsage) ( nPageUsage & 0x000f ); + sal_Bool bLeft; + if (eUsage == SVX_PAGE_LEFT) + bLeft = sal_True; + else if (eUsage == SVX_PAGE_RIGHT) + bLeft = sal_False; + else + bLeft = (nPageNo & 1) != 0; + return bLeft; +} + +void ScPrintFunc::MakeTableString() +{ + pDoc->GetName( nPrintTab, aFieldData.aTabName ); +} + +void ScPrintFunc::MakeEditEngine() +{ + if (!pEditEngine) + { + // can't use document's edit engine pool here, + // because pool must have twips as default metric + pEditEngine = new ScHeaderEditEngine( EditEngine::CreatePool(), sal_True ); + + pEditEngine->EnableUndo(sal_False); + pEditEngine->SetRefDevice( pDev ); + pEditEngine->SetWordDelimiters( + ScEditUtil::ModifyDelimiters( pEditEngine->GetWordDelimiters() ) ); + pEditEngine->SetControlWord( pEditEngine->GetControlWord() & ~EE_CNTRL_RTFSTYLESHEETS ); + pEditEngine->EnableAutoColor( bUseStyleColor ); + + // Default-Set fuer Ausrichtung + pEditDefaults = new SfxItemSet( pEditEngine->GetEmptyItemSet() ); + + const ScPatternAttr& rPattern = (const ScPatternAttr&)pDoc->GetPool()->GetDefaultItem(ATTR_PATTERN); + rPattern.FillEditItemSet( pEditDefaults ); + // FillEditItemSet adjusts font height to 1/100th mm, + // but for header/footer twips is needed, as in the PatternAttr: + pEditDefaults->Put( rPattern.GetItem(ATTR_FONT_HEIGHT), EE_CHAR_FONTHEIGHT ); + pEditDefaults->Put( rPattern.GetItem(ATTR_CJK_FONT_HEIGHT), EE_CHAR_FONTHEIGHT_CJK ); + pEditDefaults->Put( rPattern.GetItem(ATTR_CTL_FONT_HEIGHT), EE_CHAR_FONTHEIGHT_CTL ); + // #69193# dont use font color, because background color is not used + //! there's no way to set the background for note pages + pEditDefaults->ClearItem( EE_CHAR_COLOR ); + if (ScGlobal::IsSystemRTL()) + pEditDefaults->Put( SvxFrameDirectionItem( FRMDIR_HORI_RIGHT_TOP, EE_PARA_WRITINGDIR ) ); + } + + pEditEngine->SetData( aFieldData ); // Seitennummer etc. setzen +} + +// nStartY = logic +void ScPrintFunc::PrintHF( long nPageNo, sal_Bool bHeader, long nStartY, + sal_Bool bDoPrint, ScPreviewLocationData* pLocationData ) +{ + const ScPrintHFParam& rParam = bHeader ? aHdr : aFtr; + + pDev->SetMapMode( aTwipMode ); // Kopf-/Fusszeilen in Twips + + sal_Bool bLeft = IsLeft(nPageNo) && !rParam.bShared; + const ScPageHFItem* pHFItem = bLeft ? rParam.pLeft : rParam.pRight; + + long nLineStartX = aPageRect.Left() + rParam.nLeft; + long nLineEndX = aPageRect.Right() - rParam.nRight; + long nLineWidth = nLineEndX - nLineStartX + 1; + + // Edit-Engine + + Point aStart( nLineStartX, nStartY ); + Size aPaperSize( nLineWidth, rParam.nHeight-rParam.nDistance ); + if ( rParam.pBorder ) + { + long nLeft = lcl_LineTotal( rParam.pBorder->GetLeft() ) + rParam.pBorder->GetDistance(BOX_LINE_LEFT); + long nTop = lcl_LineTotal( rParam.pBorder->GetTop() ) + rParam.pBorder->GetDistance(BOX_LINE_TOP); + aStart.X() += nLeft; + aStart.Y() += nTop; + aPaperSize.Width() -= nLeft + lcl_LineTotal( rParam.pBorder->GetRight() ) + rParam.pBorder->GetDistance(BOX_LINE_RIGHT); + aPaperSize.Height() -= nTop + lcl_LineTotal( rParam.pBorder->GetBottom() ) + rParam.pBorder->GetDistance(BOX_LINE_BOTTOM); + } + + if ( rParam.pShadow && rParam.pShadow->GetLocation() != SVX_SHADOW_NONE ) + { + long nLeft = rParam.pShadow->CalcShadowSpace(SHADOW_LEFT); + long nTop = rParam.pShadow->CalcShadowSpace(SHADOW_TOP); + aStart.X() += nLeft; + aStart.Y() += nTop; + aPaperSize.Width() -= nLeft + rParam.pShadow->CalcShadowSpace(SHADOW_RIGHT); + aPaperSize.Height() -= nTop + rParam.pShadow->CalcShadowSpace(SHADOW_BOTTOM); + } + + aFieldData.nPageNo = nPageNo+aTableParam.nFirstPageNo; + MakeEditEngine(); + + pEditEngine->SetPaperSize(aPaperSize); + const EditTextObject* pObject; + + // Rahmen / Hintergrund + + Point aBorderStart( nLineStartX, nStartY ); + Size aBorderSize( nLineWidth, rParam.nHeight-rParam.nDistance ); + if ( rParam.bDynamic ) + { + // hier nochmal anpassen, wegen geraden/ungeraden Kopf/Fusszeilen + // und evtl. anderen Umbruechen durch Variablen (Seitennummer etc.) + + long nMaxHeight = 0; + nMaxHeight = Max( nMaxHeight, TextHeight( pHFItem->GetLeftArea() ) ); + nMaxHeight = Max( nMaxHeight, TextHeight( pHFItem->GetCenterArea() ) ); + nMaxHeight = Max( nMaxHeight, TextHeight( pHFItem->GetRightArea() ) ); + if (rParam.pBorder) + nMaxHeight += lcl_LineTotal( rParam.pBorder->GetTop() ) + + lcl_LineTotal( rParam.pBorder->GetBottom() ) + + rParam.pBorder->GetDistance(BOX_LINE_TOP) + + rParam.pBorder->GetDistance(BOX_LINE_BOTTOM); + if (rParam.pShadow && rParam.pShadow->GetLocation() != SVX_SHADOW_NONE) + nMaxHeight += rParam.pShadow->CalcShadowSpace(SHADOW_TOP) + + rParam.pShadow->CalcShadowSpace(SHADOW_BOTTOM); + + if (nMaxHeight < rParam.nManHeight-rParam.nDistance) + nMaxHeight = rParam.nManHeight-rParam.nDistance; // eingestelltes Minimum + + aBorderSize.Height() = nMaxHeight; + } + + if ( bDoPrint ) + { + double nOldScaleX = nScaleX; + double nOldScaleY = nScaleY; + nScaleX = nScaleY = 1.0; // direkt in Twips ausgeben + DrawBorder( aBorderStart.X(), aBorderStart.Y(), aBorderSize.Width(), aBorderSize.Height(), + rParam.pBorder, rParam.pBack, rParam.pShadow ); + nScaleX = nOldScaleX; + nScaleY = nOldScaleY; + + // Clipping fuer Text + + pDev->SetClipRegion( Rectangle( aStart, aPaperSize ) ); + + // links + + pObject = pHFItem->GetLeftArea(); + if (pObject) + { + pEditDefaults->Put( SvxAdjustItem( SVX_ADJUST_LEFT, EE_PARA_JUST ) ); + pEditEngine->SetTextNewDefaults( *pObject, *pEditDefaults, sal_False ); + Point aDraw = aStart; + long nDif = aPaperSize.Height() - (long) pEditEngine->GetTextHeight(); + if (nDif > 0) + aDraw.Y() += nDif / 2; + pEditEngine->Draw( pDev, aDraw, 0 ); + } + + // Mitte + + pObject = pHFItem->GetCenterArea(); + if (pObject) + { + pEditDefaults->Put( SvxAdjustItem( SVX_ADJUST_CENTER, EE_PARA_JUST ) ); + pEditEngine->SetTextNewDefaults( *pObject, *pEditDefaults, sal_False ); + Point aDraw = aStart; + long nDif = aPaperSize.Height() - (long) pEditEngine->GetTextHeight(); + if (nDif > 0) + aDraw.Y() += nDif / 2; + pEditEngine->Draw( pDev, aDraw, 0 ); + } + + // rechts + + pObject = pHFItem->GetRightArea(); + if (pObject) + { + pEditDefaults->Put( SvxAdjustItem( SVX_ADJUST_RIGHT, EE_PARA_JUST ) ); + pEditEngine->SetTextNewDefaults( *pObject, *pEditDefaults, sal_False ); + Point aDraw = aStart; + long nDif = aPaperSize.Height() - (long) pEditEngine->GetTextHeight(); + if (nDif > 0) + aDraw.Y() += nDif / 2; + pEditEngine->Draw( pDev, aDraw, 0 ); + } + + pDev->SetClipRegion(); + } + + if ( pLocationData ) + { + Rectangle aHeaderRect( aBorderStart, aBorderSize ); + pLocationData->AddHeaderFooter( aHeaderRect, bHeader, bLeft ); + } +} + +long ScPrintFunc::DoNotes( long nNoteStart, sal_Bool bDoPrint, ScPreviewLocationData* pLocationData ) +{ + if (bDoPrint) + pDev->SetMapMode(aTwipMode); + + MakeEditEngine(); + pEditDefaults->Put( SvxAdjustItem( SVX_ADJUST_LEFT, EE_PARA_JUST ) ); + pEditEngine->SetDefaults( *pEditDefaults ); + + Font aMarkFont; + ScAutoFontColorMode eColorMode = bUseStyleColor ? SC_AUTOCOL_DISPLAY : SC_AUTOCOL_PRINT; + ((const ScPatternAttr&)pDoc->GetPool()->GetDefaultItem(ATTR_PATTERN)).GetFont( aMarkFont, eColorMode ); +//? aMarkFont.SetWeight( WEIGHT_BOLD ); + pDev->SetFont( aMarkFont ); + long nMarkLen = pDev->GetTextWidth( + String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("GW99999:"))); + // ohne Space, weil's eh selten so weit kommt + + Size aDataSize = aPageRect.GetSize(); + if ( nMarkLen > aDataSize.Width() / 2 ) // alles viel zu klein? + nMarkLen = aDataSize.Width() / 2; // Seite bruederlich aufteilen + aDataSize.Width() -= nMarkLen; + + pEditEngine->SetPaperSize( aDataSize ); + long nPosX = aPageRect.Left() + nMarkLen; + long nPosY = aPageRect.Top(); + + long nCount = 0; + sal_Bool bOk; + do + { + bOk = sal_False; + ScAddress* pPos = (ScAddress*) aNotePosList.GetObject( nNoteStart+nCount ); + if (pPos) + { + ScBaseCell* pCell = pDoc->GetCell( *pPos); + if( const ScPostIt* pNote = pCell->GetNote() ) + { + if(const EditTextObject *pEditText = pNote->GetEditTextObject()) + pEditEngine->SetText(*pEditText); + long nTextHeight = pEditEngine->GetTextHeight(); + if ( nPosY + nTextHeight < aPageRect.Bottom() ) + { + if (bDoPrint) + { + pEditEngine->Draw( pDev, Point( nPosX, nPosY ), 0 ); + + String aMarkStr; + pPos->Format( aMarkStr, SCA_VALID, pDoc, pDoc->GetAddressConvention() ); + aMarkStr += ':'; + + // Zellposition auch per EditEngine, damit die Position stimmt + pEditEngine->SetText(aMarkStr); + pEditEngine->Draw( pDev, Point( aPageRect.Left(), nPosY ), 0 ); + } + + if ( pLocationData ) + { + Rectangle aTextRect( Point( nPosX, nPosY ), Size( aDataSize.Width(), nTextHeight ) ); + pLocationData->AddNoteText( aTextRect, *pPos ); + Rectangle aMarkRect( Point( aPageRect.Left(), nPosY ), Size( nMarkLen, nTextHeight ) ); + pLocationData->AddNoteMark( aMarkRect, *pPos ); + } + + nPosY += nTextHeight; + nPosY += 200; // Abstand + ++nCount; + bOk = sal_True; + } + } + } + } + while (bOk); + + return nCount; +} + +long ScPrintFunc::PrintNotes( long nPageNo, long nNoteStart, sal_Bool bDoPrint, ScPreviewLocationData* pLocationData ) +{ + if ( nNoteStart >= (long) aNotePosList.Count() || !aTableParam.bNotes ) + return 0; + + if ( bDoPrint && bClearWin ) + { + //! mit PrintPage zusammenfassen !!! + + Color aBackgroundColor( COL_WHITE ); + if ( bUseStyleColor ) + aBackgroundColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor ); + + pDev->SetMapMode(aOffsetMode); + pDev->SetLineColor(); + pDev->SetFillColor(aBackgroundColor); + pDev->DrawRect(Rectangle(Point(), + Size((long)(aPageSize.Width() * nScaleX * 100 / nZoom), + (long)(aPageSize.Height() * nScaleY * 100 / nZoom)))); + } + + + // aPageRect auf linke / rechte Seiten anpassen + + Rectangle aTempRect = Rectangle( Point(), aPageSize ); + if (IsMirror(nPageNo)) + { + aPageRect.Left() = ( aTempRect.Left() + nRightMargin ) * 100 / nZoom; + aPageRect.Right() = ( aTempRect.Right() - nLeftMargin ) * 100 / nZoom; + } + else + { + aPageRect.Left() = ( aTempRect.Left() + nLeftMargin ) * 100 / nZoom; + aPageRect.Right() = ( aTempRect.Right() - nRightMargin ) * 100 / nZoom; + } + + if ( pPrinter && bDoPrint ) + { + DBG_ERROR( "StartPage does not exist anymore" ); + // pPrinter->StartPage(); + } + + if ( bDoPrint || pLocationData ) + { + // Kopf- und Fusszeilen + + if (aHdr.bEnable) + { + long nHeaderY = aPageRect.Top()-aHdr.nHeight; + PrintHF( nPageNo, sal_True, nHeaderY, bDoPrint, pLocationData ); + } + if (aFtr.bEnable) + { + long nFooterY = aPageRect.Bottom()+aFtr.nDistance; + PrintHF( nPageNo, sal_False, nFooterY, bDoPrint, pLocationData ); + } + } + + long nCount = DoNotes( nNoteStart, bDoPrint, pLocationData ); + + if ( pPrinter && bDoPrint ) + { + DBG_ERROR( "EndPage does not exist anymore" ); + // pPrinter->EndPage(); + } + + return nCount; +} + +void ScPrintFunc::PrintPage( long nPageNo, SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, + sal_Bool bDoPrint, ScPreviewLocationData* pLocationData ) +{ + sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nPrintTab ); + long nLayoutSign = bLayoutRTL ? -1 : 1; + + // nPageNo is the page number within all sheets of one "start page" setting + + if ( bClearWin && bDoPrint ) + { + // muss genau zum Zeichnen des Rahmens in preview.cxx passen !!! + + Color aBackgroundColor( COL_WHITE ); + if ( bUseStyleColor ) + aBackgroundColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor ); + + pDev->SetMapMode(aOffsetMode); + pDev->SetLineColor(); + pDev->SetFillColor(aBackgroundColor); + pDev->DrawRect(Rectangle(Point(), + Size((long)(aPageSize.Width() * nScaleX * 100 / nZoom), + (long)(aPageSize.Height() * nScaleY * 100 / nZoom)))); + } + + + // aPageRect auf linke / rechte Seiten anpassen + + Rectangle aTempRect = Rectangle( Point(), aPageSize ); + if (IsMirror(nPageNo)) + { + aPageRect.Left() = ( aTempRect.Left() + nRightMargin ) * 100 / nZoom; + aPageRect.Right() = ( aTempRect.Right() - nLeftMargin ) * 100 / nZoom; + } + else + { + aPageRect.Left() = ( aTempRect.Left() + nLeftMargin ) * 100 / nZoom; + aPageRect.Right() = ( aTempRect.Right() - nRightMargin ) * 100 / nZoom; + } + + if ( aAreaParam.bRepeatCol ) + if ( nX1 > nRepeatStartCol && nX1 <= nRepeatEndCol ) + nX1 = nRepeatEndCol + 1; + sal_Bool bDoRepCol = (aAreaParam.bRepeatCol && nX1 > nRepeatEndCol); + if ( aAreaParam.bRepeatRow ) + if ( nY1 > nRepeatStartRow && nY1 <= nRepeatEndRow ) + nY1 = nRepeatEndRow + 1; + sal_Bool bDoRepRow = (aAreaParam.bRepeatRow && nY1 > nRepeatEndRow); + + // use new object hide flags in SdrPaintView + if(pDrawView) + { + pDrawView->setHideOle(!aTableParam.bObjects); + pDrawView->setHideChart(!aTableParam.bCharts); + pDrawView->setHideDraw(!aTableParam.bDrawings); + pDrawView->setHideFormControl(!aTableParam.bDrawings); + } + + if ( pPrinter && bDoPrint ) + { + DBG_ERROR( "StartPage does not exist anymore" ); + // pPrinter->StartPage(); + } + + // Kopf- und Fusszeilen (ohne Zentrierung) + + if (aHdr.bEnable) + { + long nHeaderY = aPageRect.Top()-aHdr.nHeight; + PrintHF( nPageNo, sal_True, nHeaderY, bDoPrint, pLocationData ); + } + if (aFtr.bEnable) + { + long nFooterY = aPageRect.Bottom()+aFtr.nDistance; + PrintHF( nPageNo, sal_False, nFooterY, bDoPrint, pLocationData ); + } + + // Position ( Raender / zentrieren ) + + long nLeftSpace = aPageRect.Left(); // Document-Twips + long nTopSpace = aPageRect.Top(); + if ( bCenterHor || bLayoutRTL ) + { + long nDataWidth = 0; + SCCOL i; + for (i=nX1; i<=nX2; i++) + nDataWidth += pDoc->GetColWidth( i,nPrintTab ); + if (bDoRepCol) + for (i=nRepeatStartCol; i<=nRepeatEndCol; i++) + nDataWidth += pDoc->GetColWidth( i,nPrintTab ); + if (aTableParam.bHeaders) + nDataWidth += (long) PRINT_HEADER_WIDTH; + if (pBorderItem) + nDataWidth += pBorderItem->GetDistance(BOX_LINE_LEFT) + + pBorderItem->GetDistance(BOX_LINE_RIGHT); //! Line width? + if (pShadowItem && pShadowItem->GetLocation() != SVX_SHADOW_NONE) + nDataWidth += pShadowItem->CalcShadowSpace(SHADOW_LEFT) + + pShadowItem->CalcShadowSpace(SHADOW_RIGHT); + if ( bCenterHor ) + { + nLeftSpace += ( aPageRect.GetWidth() - nDataWidth ) / 2; // LTR or RTL + if (pBorderItem) + nLeftSpace -= lcl_LineTotal(pBorderItem->GetLeft()); + } + else if ( bLayoutRTL ) + nLeftSpace += aPageRect.GetWidth() - nDataWidth; // align to the right edge of the page + } + if ( bCenterVer ) + { + long nDataHeight = pDoc->GetRowHeight( nY1, nY2, nPrintTab); + if (bDoRepRow) + nDataHeight += pDoc->GetRowHeight( nRepeatStartRow, + nRepeatEndRow, nPrintTab); + if (aTableParam.bHeaders) + nDataHeight += (long) PRINT_HEADER_HEIGHT; + if (pBorderItem) + nDataHeight += pBorderItem->GetDistance(BOX_LINE_TOP) + + pBorderItem->GetDistance(BOX_LINE_BOTTOM); //! Line width? + if (pShadowItem && pShadowItem->GetLocation() != SVX_SHADOW_NONE) + nDataHeight += pShadowItem->CalcShadowSpace(SHADOW_TOP) + + pShadowItem->CalcShadowSpace(SHADOW_BOTTOM); + nTopSpace += ( aPageRect.GetHeight() - nDataHeight ) / 2; + if (pBorderItem) + nTopSpace -= lcl_LineTotal(pBorderItem->GetTop()); + } + + // calculate sizes of the elements for partitioning + // (header, repeat, data) + + long nHeaderWidth = 0; + long nHeaderHeight = 0; + long nRepeatWidth = 0; + long nRepeatHeight = 0; + long nContentWidth = 0; // scaled - not the same as nDataWidth above + long nContentHeight = 0; + if (aTableParam.bHeaders) + { + nHeaderWidth = (long) (PRINT_HEADER_WIDTH * nScaleX); + nHeaderHeight = (long) (PRINT_HEADER_HEIGHT * nScaleY); + } + if (bDoRepCol) + for (SCCOL i=nRepeatStartCol; i<=nRepeatEndCol; i++) + nRepeatWidth += (long) (pDoc->GetColWidth(i,nPrintTab) * nScaleX); + if (bDoRepRow) + nRepeatHeight += pDoc->GetScaledRowHeight( nRepeatStartRow, + nRepeatEndRow, nPrintTab, nScaleY); + for (SCCOL i=nX1; i<=nX2; i++) + nContentWidth += (long) (pDoc->GetColWidth(i,nPrintTab) * nScaleX); + nContentHeight += pDoc->GetScaledRowHeight( nY1, nY2, nPrintTab, + nScaleY); + + // partition the page + + long nStartX = ((long) ( nLeftSpace * nScaleX )); + long nStartY = ((long) ( nTopSpace * nScaleY )); +// nStartX -= aOffset.X(); // schon im MapMode +// nStartY -= aOffset.Y(); + + long nInnerStartX = nStartX; + long nInnerStartY = nStartY; + if (pBorderItem) + { + nInnerStartX += (long) ( ( lcl_LineTotal(pBorderItem->GetLeft()) + + pBorderItem->GetDistance(BOX_LINE_LEFT) ) * nScaleX ); + nInnerStartY += (long) ( ( lcl_LineTotal(pBorderItem->GetTop()) + + pBorderItem->GetDistance(BOX_LINE_TOP) ) * nScaleY ); + } + if (pShadowItem && pShadowItem->GetLocation() != SVX_SHADOW_NONE) + { + nInnerStartX += (long) ( pShadowItem->CalcShadowSpace(SHADOW_LEFT) * nScaleX ); + nInnerStartY += (long) ( pShadowItem->CalcShadowSpace(SHADOW_TOP) * nScaleY ); + } + + if ( bLayoutRTL ) + { + // arrange elements starting from the right edge + nInnerStartX += nHeaderWidth + nRepeatWidth + nContentWidth; + + // make rounding easier so the elements are really next to each other in preview + Size aOffsetOnePixel = pDev->PixelToLogic( Size(1,1), aOffsetMode ); + long nOffsetOneX = aOffsetOnePixel.Width(); + nInnerStartX += nOffsetOneX / 2; + } + + long nFrameStartX = nInnerStartX; + long nFrameStartY = nInnerStartY; + + long nRepStartX = nInnerStartX + nHeaderWidth * nLayoutSign; // widths/heights are 0 if not used + long nRepStartY = nInnerStartY + nHeaderHeight; + long nDataX = nRepStartX + nRepeatWidth * nLayoutSign; + long nDataY = nRepStartY + nRepeatHeight; + long nEndX = nDataX + nContentWidth * nLayoutSign; + long nEndY = nDataY + nContentHeight; + long nFrameEndX = nEndX; + long nFrameEndY = nEndY; + + if ( bLayoutRTL ) + { + // each element's start position is its left edge + //! subtract one pixel less? + nInnerStartX -= nHeaderWidth; // used for header + nRepStartX -= nRepeatWidth; + nDataX -= nContentWidth; + + // continue right of the main elements again + nEndX += nHeaderWidth + nRepeatWidth + nContentWidth; + } + + // Seiten-Rahmen / Hintergrund + + //! nEndX/Y anpassen + + long nBorderEndX = nEndX; + long nBorderEndY = nEndY; + if (pBorderItem) + { + nBorderEndX += (long) ( ( lcl_LineTotal(pBorderItem->GetRight()) + + pBorderItem->GetDistance(BOX_LINE_RIGHT) ) * nScaleX ); + nBorderEndY += (long) ( ( lcl_LineTotal(pBorderItem->GetBottom()) + + pBorderItem->GetDistance(BOX_LINE_BOTTOM) ) * nScaleY ); + } + if (pShadowItem && pShadowItem->GetLocation() != SVX_SHADOW_NONE) + { + nBorderEndX += (long) ( pShadowItem->CalcShadowSpace(SHADOW_RIGHT) * nScaleX ); + nBorderEndY += (long) ( pShadowItem->CalcShadowSpace(SHADOW_BOTTOM) * nScaleY ); + } + + if ( bDoPrint ) + { + pDev->SetMapMode( aOffsetMode ); + DrawBorder( nStartX, nStartY, nBorderEndX-nStartX, nBorderEndY-nStartY, + pBorderItem, pBackgroundItem, pShadowItem ); + + pDev->SetMapMode( aTwipMode ); + } + + pDev->SetMapMode( aOffsetMode ); + + // Wiederholungszeilen/Spalten ausgeben + + if (bDoRepCol && bDoRepRow) + { + if ( bDoPrint ) + PrintArea( nRepeatStartCol,nRepeatStartRow, nRepeatEndCol,nRepeatEndRow, + nRepStartX,nRepStartY, sal_True,sal_True,sal_False,sal_False ); + if ( pLocationData ) + LocateArea( nRepeatStartCol,nRepeatStartRow, nRepeatEndCol,nRepeatEndRow, + nRepStartX,nRepStartY, sal_True,sal_True, *pLocationData ); + } + if (bDoRepCol) + { + if ( bDoPrint ) + PrintArea( nRepeatStartCol,nY1, nRepeatEndCol,nY2, nRepStartX,nDataY, + sal_True,!bDoRepRow,sal_False,sal_True ); + if ( pLocationData ) + LocateArea( nRepeatStartCol,nY1, nRepeatEndCol,nY2, nRepStartX,nDataY, sal_True,sal_False, *pLocationData ); + } + if (bDoRepRow) + { + if ( bDoPrint ) + PrintArea( nX1,nRepeatStartRow, nX2,nRepeatEndRow, nDataX,nRepStartY, + !bDoRepCol,sal_True,sal_True,sal_False ); + if ( pLocationData ) + LocateArea( nX1,nRepeatStartRow, nX2,nRepeatEndRow, nDataX,nRepStartY, sal_False,sal_True, *pLocationData ); + } + + // Daten ausgeben + + if ( bDoPrint ) + PrintArea( nX1,nY1, nX2,nY2, nDataX,nDataY, !bDoRepCol,!bDoRepRow,sal_True,sal_True ); + if ( pLocationData ) + LocateArea( nX1,nY1, nX2,nY2, nDataX,nDataY, sal_False,sal_False, *pLocationData ); + + // Spalten-/Zeilenkoepfe ausgeben + // nach den Daten (ueber evtl. weitergezeichneten Schatten) + + Color aGridColor( COL_BLACK ); + if ( bUseStyleColor ) + aGridColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor ); + + if (aTableParam.bHeaders) + { + if ( bDoPrint ) + { + pDev->SetLineColor( aGridColor ); + pDev->SetFillColor(); + pDev->SetMapMode(aOffsetMode); + } + + ScPatternAttr aPattern( pDoc->GetPool() ); + Font aFont; + ScAutoFontColorMode eColorMode = bUseStyleColor ? SC_AUTOCOL_DISPLAY : SC_AUTOCOL_PRINT; + aPattern.GetFont( aFont, eColorMode, pDev ); + pDev->SetFont( aFont ); + + if (bDoRepCol) + { + if ( bDoPrint ) + PrintColHdr( nRepeatStartCol,nRepeatEndCol, nRepStartX,nInnerStartY ); + if ( pLocationData ) + LocateColHdr( nRepeatStartCol,nRepeatEndCol, nRepStartX,nInnerStartY, sal_True, *pLocationData ); + } + if ( bDoPrint ) + PrintColHdr( nX1,nX2, nDataX,nInnerStartY ); + if ( pLocationData ) + LocateColHdr( nX1,nX2, nDataX,nInnerStartY, sal_False, *pLocationData ); + if (bDoRepRow) + { + if ( bDoPrint ) + PrintRowHdr( nRepeatStartRow,nRepeatEndRow, nInnerStartX,nRepStartY ); + if ( pLocationData ) + LocateRowHdr( nRepeatStartRow,nRepeatEndRow, nInnerStartX,nRepStartY, sal_True, *pLocationData ); + } + if ( bDoPrint ) + PrintRowHdr( nY1,nY2, nInnerStartX,nDataY ); + if ( pLocationData ) + LocateRowHdr( nY1,nY2, nInnerStartX,nDataY, sal_False, *pLocationData ); + } + + // einfacher Rahmen + + if ( bDoPrint && ( aTableParam.bGrid || aTableParam.bHeaders ) ) + { + Size aOnePixel = pDev->PixelToLogic(Size(1,1)); + long nOneX = aOnePixel.Width(); + long nOneY = aOnePixel.Height(); + + long nLeftX = nFrameStartX; + long nTopY = nFrameStartY - nOneY; + long nRightX = nFrameEndX; + long nBottomY = nFrameEndY - nOneY; + if ( !bLayoutRTL ) + { + nLeftX -= nOneX; + nRightX -= nOneX; + } + pDev->SetMapMode(aOffsetMode); + pDev->SetLineColor( aGridColor ); + pDev->SetFillColor(); + pDev->DrawRect( Rectangle( nLeftX, nTopY, nRightX, nBottomY ) ); + // nEndX/Y ohne Rahmen-Anpassung + } + + if ( pPrinter && bDoPrint ) + { + DBG_ERROR( "EndPage does not exist anymore" ); + // pPrinter->EndPage(); + } + + aLastSourceRange = ScRange( nX1, nY1, nPrintTab, nX2, nY2, nPrintTab ); + bSourceRangeValid = sal_True; +} + +void ScPrintFunc::SetOffset( const Point& rOfs ) +{ + aSrcOffset = rOfs; +} + +void ScPrintFunc::SetManualZoom( sal_uInt16 nNewZoom ) +{ + nManualZoom = nNewZoom; +} + +void ScPrintFunc::SetClearFlag( sal_Bool bFlag ) +{ + bClearWin = bFlag; +} + +void ScPrintFunc::SetUseStyleColor( sal_Bool bFlag ) +{ + bUseStyleColor = bFlag; + if (pEditEngine) + pEditEngine->EnableAutoColor( bUseStyleColor ); +} + +void ScPrintFunc::SetRenderFlag( sal_Bool bFlag ) +{ + bIsRender = bFlag; // set when using XRenderable (PDF) +} + +void ScPrintFunc::SetExclusivelyDrawOleAndDrawObjects() +{ + aTableParam.bCellContent = false; + aTableParam.bNotes = false; + aTableParam.bGrid = false; + aTableParam.bHeaders = false; + aTableParam.bFormulas = false;; + aTableParam.bNullVals = false;; + aTableParam.bNullVals = false;; +} + +// +// UpdatePages wird nur von aussen gerufen, um die Umbrueche fuer die Anzeige +// richtig zu setzen - immer ohne UserArea +// + +sal_Bool ScPrintFunc::UpdatePages() +{ + if (!pParamSet) + return sal_False; + + // Zoom + + nZoom = 100; + if (aTableParam.bScalePageNum || aTableParam.bScaleTo) + nZoom = ZOOM_MIN; // stimmt fuer Umbrueche + else if (aTableParam.bScaleAll) + { + nZoom = aTableParam.nScaleAll; + if ( nZoom <= ZOOM_MIN ) + nZoom = ZOOM_MIN; + } + + String aName = pDoc->GetPageStyle( nPrintTab ); + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB nTab=0; nTab<nTabCount; nTab++) + if ( nTab==nPrintTab || pDoc->GetPageStyle(nTab)==aName ) + { + // Wiederholungszeilen / Spalten + pDoc->SetRepeatArea( nTab, nRepeatStartCol,nRepeatEndCol, nRepeatStartRow,nRepeatEndRow ); + + // Umbrueche setzen + ResetBreaks(nTab); + pDocShell->PostPaint(0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID); + } + + return sal_True; +} + +long ScPrintFunc::CountPages() // setzt auch nPagesX, nPagesY +{ + sal_Bool bAreaOk = sal_False; + + if (pDoc->HasTable( nPrintTab )) + { + if (aAreaParam.bPrintArea) // Druckbereich angegeben? + { + if ( bPrintCurrentTable ) + { + ScRange& rRange = aAreaParam.aPrintArea; + + // hier kein Vergleich der Tabellen mehr, die Area gilt immer fuer diese Tabelle + // wenn hier verglichen werden soll, muss die Tabelle der Druckbereiche beim + // Einfuegen von Tabellen etc. angepasst werden ! + + nStartCol = rRange.aStart.Col(); + nStartRow = rRange.aStart.Row(); + nEndCol = rRange.aEnd .Col(); + nEndRow = rRange.aEnd .Row(); + bAreaOk = AdjustPrintArea(sal_False); // begrenzen + } + else + bAreaOk = sal_False; + } + else // aus Dokument suchen + bAreaOk = AdjustPrintArea(sal_True); + } + + if (bAreaOk) + { + long nPages = 0; + size_t nY; + if (bMultiArea) + { + sal_uInt16 nRCount = pDoc->GetPrintRangeCount( nPrintTab ); + for (sal_uInt16 i=0; i<nRCount; i++) + { + CalcZoom(i); + if ( aTableParam.bSkipEmpty ) + for (nY=0; nY<nPagesY; nY++) + nPages += pPageRows[nY].CountVisible(); + else + nPages += ((long) nPagesX) * nPagesY; + if ( pPageData ) + FillPageData(); + } + } + else + { + CalcZoom(RANGENO_NORANGE); // Zoom berechnen + if ( aTableParam.bSkipEmpty ) + for (nY=0; nY<nPagesY; nY++) + nPages += pPageRows[nY].CountVisible(); + else + nPages += ((long) nPagesX) * nPagesY; + if ( pPageData ) + FillPageData(); + } + return nPages; + } + else + { +// nZoom = 100; // nZoom auf letztem Wert stehenlassen !!! + nPagesX = nPagesY = nTotalY = 0; + return 0; + } +} + +long ScPrintFunc::CountNotePages() +{ + if ( !aTableParam.bNotes || !bPrintCurrentTable ) + return 0; + + long nCount=0; + SCCOL nCol; + SCROW nRow; + + sal_Bool bError = sal_False; + if (!aAreaParam.bPrintArea) + bError = !AdjustPrintArea(sal_True); // komplett aus Dok suchen + + sal_uInt16 nRepeats = 1; // wie oft durchgehen ? + if (bMultiArea) + nRepeats = pDoc->GetPrintRangeCount(nPrintTab); + if (bError) + nRepeats = 0; + + for (sal_uInt16 nStep=0; nStep<nRepeats; nStep++) + { + sal_Bool bDoThis = sal_True; + if (bMultiArea) // alle Areas durchgehen + { + const ScRange* pThisRange = pDoc->GetPrintRange( nPrintTab, nStep ); + if ( pThisRange ) + { + nStartCol = pThisRange->aStart.Col(); + nStartRow = pThisRange->aStart.Row(); + nEndCol = pThisRange->aEnd .Col(); + nEndRow = pThisRange->aEnd .Row(); + bDoThis = AdjustPrintArea(sal_False); + } + } + + if (bDoThis) + { + ScHorizontalCellIterator aIter( pDoc, nPrintTab, nStartCol,nStartRow, nEndCol,nEndRow ); + ScBaseCell* pCell = aIter.GetNext( nCol, nRow ); + while (pCell) + { + if (pCell->HasNote()) + { + aNotePosList.Insert( new ScAddress( nCol,nRow,nPrintTab ), LIST_APPEND ); + ++nCount; + } + + pCell = aIter.GetNext( nCol, nRow ); + } + } + } + + long nPages = 0; + long nNoteNr = 0; + long nNoteAdd; + do + { + nNoteAdd = PrintNotes( nPages, nNoteNr, sal_False, NULL ); + if (nNoteAdd) + { + nNoteNr += nNoteAdd; + ++nPages; + } + } + while (nNoteAdd); + + return nPages; +} + +void ScPrintFunc::InitModes() // aus nZoom etc. die MapModes setzen +{ + aOffset = Point( aSrcOffset.X()*100/nZoom, aSrcOffset.Y()*100/nZoom ); + + long nEffZoom = nZoom * (long) nManualZoom; + +// nScaleX = nScaleY = 1.0; // Ausgabe in Twips + nScaleX = nScaleY = HMM_PER_TWIPS; // Ausgabe in 1/100 mm + + Fraction aZoomFract( nEffZoom,10000 ); + Fraction aHorFract = aZoomFract; + + if ( !pPrinter && !bIsRender ) // adjust scale for preview + { + double nFact = pDocShell->GetOutputFactor(); + aHorFract = Fraction( (long)( nEffZoom / nFact ), 10000 ); + } + + aLogicMode = MapMode( MAP_100TH_MM, Point(), aHorFract, aZoomFract ); + + Point aLogicOfs( -aOffset.X(), -aOffset.Y() ); + aOffsetMode = MapMode( MAP_100TH_MM, aLogicOfs, aHorFract, aZoomFract ); + + Point aTwipsOfs( (long) ( -aOffset.X() / nScaleX + 0.5 ), (long) ( -aOffset.Y() / nScaleY + 0.5 ) ); + aTwipMode = MapMode( MAP_TWIP, aTwipsOfs, aHorFract, aZoomFract ); +} + +//-------------------------------------------------------------------- + +void ScPrintFunc::ApplyPrintSettings() +{ + if ( pPrinter ) + { + // + // Printer zum Drucken umstellen + // + + Size aEnumSize = aPageSize; + + + pPrinter->SetOrientation( bLandscape ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT ); + if ( bLandscape ) + { + // landscape is always interpreted as a rotation by 90 degrees ! + // this leads to non WYSIWIG but at least it prints! + // #i21775# + long nTemp = aEnumSize.Width(); + aEnumSize.Width() = aEnumSize.Height(); + aEnumSize.Height() = nTemp; + } + Paper ePaper = SvxPaperInfo::GetSvxPaper( aEnumSize, MAP_TWIP, sal_True ); + sal_uInt16 nPaperBin = ((const SvxPaperBinItem&)pParamSet->Get(ATTR_PAGE_PAPERBIN)).GetValue(); + + pPrinter->SetPaper( ePaper ); + if ( PAPER_USER == ePaper ) + { + MapMode aPrinterMode = pPrinter->GetMapMode(); + MapMode aLocalMode( MAP_TWIP ); + pPrinter->SetMapMode( aLocalMode ); + pPrinter->SetPaperSizeUser( aEnumSize ); + pPrinter->SetMapMode( aPrinterMode ); + } + + pPrinter->SetPaperBin( nPaperBin ); + } +} + +//-------------------------------------------------------------------- +// rPageRanges = Range fuer alle Tabellen +// nStartPage = in rPageRanges beginnen bei nStartPage +// nDisplayStart = lfd. Nummer fuer Anzeige der Seitennummer + +long ScPrintFunc::DoPrint( const MultiSelection& rPageRanges, + long nStartPage, long nDisplayStart, sal_Bool bDoPrint, + SfxProgress* pProgress, ScPreviewLocationData* pLocationData ) +{ + DBG_ASSERT(pDev,"Device == NULL"); + if (!pParamSet) + return 0; + + if ( pPrinter && bDoPrint ) + ApplyPrintSettings(); + + //-------------------------------------------------------------------- + + InitModes(); + if ( pLocationData ) + { + pLocationData->SetCellMapMode( aOffsetMode ); + pLocationData->SetPrintTab( nPrintTab ); + } + + MakeTableString(); + + if ( pProgress ) + pProgress->SetText( String( ScResId( SCSTR_STAT_PRINT ) ) ); + + //-------------------------------------------------------------------- + + long nPageNo = 0; + long nPrinted = 0; + long nEndPage = rPageRanges.GetTotalRange().Max(); + + sal_uInt16 nRepeats = 1; // wie oft durchgehen ? + if (bMultiArea) + nRepeats = pDoc->GetPrintRangeCount(nPrintTab); + for (sal_uInt16 nStep=0; nStep<nRepeats; nStep++) + { + if (bMultiArea) // Bereich neu belegen ? + { + CalcZoom(nStep); // setzt auch nStartCol etc. neu + InitModes(); + } + + SCCOL nX1; + SCROW nY1; + SCCOL nX2; + SCROW nY2; + size_t nCountX; + size_t nCountY; + + if (aTableParam.bTopDown) // von oben nach unten + { + nX1 = nStartCol; + for (nCountX=0; nCountX<nPagesX; nCountX++) + { + nX2 = pPageEndX[nCountX]; + for (nCountY=0; nCountY<nPagesY; nCountY++) + { + nY1 = pPageRows[nCountY].GetStartRow(); + nY2 = pPageRows[nCountY].GetEndRow(); + if ( !aTableParam.bSkipEmpty || !pPageRows[nCountY].IsHidden(nCountX) ) + { + if ( rPageRanges.IsSelected( nPageNo+nStartPage+1 ) ) + { + PrintPage( nPageNo+nDisplayStart, nX1, nY1, nX2, nY2, + bDoPrint, pLocationData ); + + if ( pProgress ) + { + pProgress->SetState( nPageNo+nStartPage+1, nEndPage ); + pProgress->Reschedule(); //Mag der Anwender noch oder hat er genug? + } + ++nPrinted; + } + ++nPageNo; + } + } + nX1 = nX2 + 1; + } + } + else // von links nach rechts + { + for (nCountY=0; nCountY<nPagesY; nCountY++) + { + nY1 = pPageRows[nCountY].GetStartRow(); + nY2 = pPageRows[nCountY].GetEndRow(); + nX1 = nStartCol; + for (nCountX=0; nCountX<nPagesX; nCountX++) + { + nX2 = pPageEndX[nCountX]; + if ( !aTableParam.bSkipEmpty || !pPageRows[nCountY].IsHidden(nCountX) ) + { + if ( rPageRanges.IsSelected( nPageNo+nStartPage+1 ) ) + { + PrintPage( nPageNo+nDisplayStart, nX1, nY1, nX2, nY2, + bDoPrint, pLocationData ); + + if ( pProgress ) + { + pProgress->SetState( nPageNo+nStartPage+1, nEndPage ); + pProgress->Reschedule(); //Mag der Anwender noch oder hat er genug? + } + ++nPrinted; + } + ++nPageNo; + } + nX1 = nX2 + 1; + } + } + } + } + + aFieldData.aTabName = ScGlobal::GetRscString( STR_NOTES ); + + long nNoteNr = 0; + long nNoteAdd; + do + { + if ( nPageNo+nStartPage <= nEndPage ) + { + sal_Bool bPageSelected = rPageRanges.IsSelected( nPageNo+nStartPage+1 ); + nNoteAdd = PrintNotes( nPageNo+nStartPage, nNoteNr, bDoPrint && bPageSelected, + ( bPageSelected ? pLocationData : NULL ) ); + if ( nNoteAdd ) + { + nNoteNr += nNoteAdd; + if ( pProgress && bPageSelected ) + { + pProgress->SetState( nPageNo+nStartPage+1, nEndPage ); + pProgress->Reschedule(); //Mag der Anwender noch oder hat er genug? + } + if (bPageSelected) + { + ++nPrinted; + bSourceRangeValid = sal_False; // last page was no cell range + } + ++nPageNo; + } + } + else + nNoteAdd = 0; + } + while (nNoteAdd); + + if ( bMultiArea ) + ResetBreaks(nPrintTab); // Breaks fuer Anzeige richtig + + return nPrinted; +} + +void ScPrintFunc::CalcZoom( sal_uInt16 nRangeNo ) // Zoom berechnen +{ + sal_uInt16 nRCount = pDoc->GetPrintRangeCount( nPrintTab ); + const ScRange* pThisRange = NULL; + if ( nRangeNo != RANGENO_NORANGE || nRangeNo < nRCount ) + pThisRange = pDoc->GetPrintRange( nPrintTab, nRangeNo ); + if ( pThisRange ) + { + nStartCol = pThisRange->aStart.Col(); + nStartRow = pThisRange->aStart.Row(); + nEndCol = pThisRange->aEnd .Col(); + nEndRow = pThisRange->aEnd .Row(); + } + + if (!AdjustPrintArea(sal_False)) // leer + { + nZoom = 100; + nPagesX = nPagesY = nTotalY = 0; + return; + } + + pDoc->SetRepeatArea( nPrintTab, nRepeatStartCol,nRepeatEndCol, nRepeatStartRow,nRepeatEndRow ); + + if (aTableParam.bScalePageNum) + { + nZoom = 100; + sal_uInt16 nPagesToFit = aTableParam.nScalePageNum; + + sal_uInt16 nLastFitZoom = 0, nLastNonFitZoom = 0; + while (true) + { + if (nZoom <= ZOOM_MIN) + break; + + CalcPages(); + bool bFitsPage = (nPagesX * nPagesY <= nPagesToFit); + + if (bFitsPage) + { + if (nZoom == 100) + // If it fits at 100 %, it's good enough for me. + break; + + nLastFitZoom = nZoom; + nZoom = (nLastNonFitZoom + nZoom) / 2; + + if (nLastFitZoom == nZoom) + // It converged. Use this zoom level. + break; + } + else + { + if (nZoom - nLastFitZoom <= 1) + { + nZoom = nLastFitZoom; + CalcPages(); + break; + } + + nLastNonFitZoom = nZoom; + nZoom = (nLastFitZoom + nZoom) / 2; + } + } + } + else if (aTableParam.bScaleTo) + { + nZoom = 100; + sal_uInt16 nW = aTableParam.nScaleWidth; + sal_uInt16 nH = aTableParam.nScaleHeight; + + sal_uInt16 nLastFitZoom = 0, nLastNonFitZoom = 0; + while (true) + { + if (nZoom <= ZOOM_MIN) + break; + + CalcPages(); + bool bFitsPage = ((!nW || (nPagesX <= nW)) && (!nH || (nPagesY <= nH))); + + if (bFitsPage) + { + if (nZoom == 100) + // If it fits at 100 %, it's good enough for me. + break; + + nLastFitZoom = nZoom; + nZoom = (nLastNonFitZoom + nZoom) / 2; + + if (nLastFitZoom == nZoom) + // It converged. Use this zoom level. + break; + } + else + { + if (nZoom - nLastFitZoom <= 1) + { + nZoom = nLastFitZoom; + CalcPages(); + break; + } + + nLastNonFitZoom = nZoom; + nZoom = (nLastFitZoom + nZoom) / 2; + } + } + } + else if (aTableParam.bScaleAll) + { + nZoom = aTableParam.nScaleAll; + if ( nZoom <= ZOOM_MIN ) + nZoom = ZOOM_MIN; + CalcPages(); + } + else + { + DBG_ASSERT( aTableParam.bScaleNone, "kein Scale-Flag gesetzt" ); + nZoom = 100; + CalcPages(); + } +} + +Size ScPrintFunc::GetDocPageSize() +{ + // Hoehe Kopf-/Fusszeile anpassen + + InitModes(); // aTwipMode aus nZoom initialisieren + pDev->SetMapMode( aTwipMode ); // Kopf-/Fusszeilen in Twips + UpdateHFHeight( aHdr ); + UpdateHFHeight( aFtr ); + + // Seitengroesse in Document-Twips + // Berechnung Left / Right auch in PrintPage + + aPageRect = Rectangle( Point(), aPageSize ); + aPageRect.Left() = ( aPageRect.Left() + nLeftMargin ) * 100 / nZoom; + aPageRect.Right() = ( aPageRect.Right() - nRightMargin ) * 100 / nZoom; + aPageRect.Top() = ( aPageRect.Top() + nTopMargin ) * 100 / nZoom + aHdr.nHeight; + aPageRect.Bottom() = ( aPageRect.Bottom() - nBottomMargin ) * 100 / nZoom - aFtr.nHeight; + + Size aDocPageSize = aPageRect.GetSize(); + if (aTableParam.bHeaders) + { + aDocPageSize.Width() -= (long) PRINT_HEADER_WIDTH; + aDocPageSize.Height() -= (long) PRINT_HEADER_HEIGHT; + } + if (pBorderItem) + { + aDocPageSize.Width() -= lcl_LineTotal(pBorderItem->GetLeft()) + + lcl_LineTotal(pBorderItem->GetRight()) + + pBorderItem->GetDistance(BOX_LINE_LEFT) + + pBorderItem->GetDistance(BOX_LINE_RIGHT); + aDocPageSize.Height() -= lcl_LineTotal(pBorderItem->GetTop()) + + lcl_LineTotal(pBorderItem->GetBottom()) + + pBorderItem->GetDistance(BOX_LINE_TOP) + + pBorderItem->GetDistance(BOX_LINE_BOTTOM); + } + if (pShadowItem && pShadowItem->GetLocation() != SVX_SHADOW_NONE) + { + aDocPageSize.Width() -= pShadowItem->CalcShadowSpace(SHADOW_LEFT) + + pShadowItem->CalcShadowSpace(SHADOW_RIGHT); + aDocPageSize.Height() -= pShadowItem->CalcShadowSpace(SHADOW_TOP) + + pShadowItem->CalcShadowSpace(SHADOW_BOTTOM); + } + return aDocPageSize; +} + +void ScPrintFunc::ResetBreaks( SCTAB nTab ) // Breaks fuer Anzeige richtig setzen +{ + pDoc->SetPageSize( nTab, GetDocPageSize() ); + pDoc->UpdatePageBreaks( nTab, NULL ); +} + +void lcl_SetHidden( ScDocument* pDoc, SCTAB nPrintTab, ScPageRowEntry& rPageRowEntry, + SCCOL nStartCol, const SCCOL* pPageEndX ) +{ + size_t nPagesX = rPageRowEntry.GetPagesX(); + SCROW nStartRow = rPageRowEntry.GetStartRow(); + SCROW nEndRow = rPageRowEntry.GetEndRow(); + + sal_Bool bLeftIsEmpty = sal_False; + ScRange aTempRange; + Rectangle aTempRect = pDoc->GetMMRect( 0,0, 0,0, 0 ); + + for (size_t i=0; i<nPagesX; i++) + { + SCCOL nEndCol = pPageEndX[i]; + if ( pDoc->IsPrintEmpty( nPrintTab, nStartCol, nStartRow, nEndCol, nEndRow, + bLeftIsEmpty, &aTempRange, &aTempRect ) ) + { + rPageRowEntry.SetHidden(i); + bLeftIsEmpty = sal_True; + } + else + bLeftIsEmpty = sal_False; + + nStartCol = nEndCol+1; + } +} + +void ScPrintFunc::CalcPages() // berechnet aPageRect und Seiten aus nZoom +{ + if (!pPageEndX) pPageEndX = new SCCOL[MAXCOL+1]; + if (!pPageEndY) pPageEndY = new SCROW[MAXROW+1]; + if (!pPageRows) pPageRows = new ScPageRowEntry[MAXROW+1]; //! vorher zaehlen !!!! + + pDoc->SetPageSize( nPrintTab, GetDocPageSize() ); + if (aAreaParam.bPrintArea) + { + ScRange aRange( nStartCol, nStartRow, nPrintTab, nEndCol, nEndRow, nPrintTab ); + pDoc->UpdatePageBreaks( nPrintTab, &aRange ); + } + else + pDoc->UpdatePageBreaks( nPrintTab, NULL ); // sonst wird das Ende markiert + + // + // Seiteneinteilung nach Umbruechen in Col/RowFlags + // Von mehreren Umbruechen in einem ausgeblendeten Bereich zaehlt nur einer. + // + + nPagesX = 0; + nPagesY = 0; + nTotalY = 0; + + bool bVisCol = false; + SCCOL nLastCol = -1; + for (SCCOL i=nStartCol; i<=nEndCol; i++) + { + bool bHidden = pDoc->ColHidden(i, nPrintTab, nLastCol); + bool bPageBreak = (pDoc->HasColBreak(i, nPrintTab) & BREAK_PAGE); + if ( i>nStartCol && bVisCol && bPageBreak ) + { + pPageEndX[nPagesX] = i-1; + ++nPagesX; + bVisCol = false; + } + if (!bHidden) + bVisCol = true; + } + if (bVisCol) // auch am Ende keine leeren Seiten + { + pPageEndX[nPagesX] = nEndCol; + ++nPagesX; + } + + bool bVisRow = false; + SCROW nPageStartRow = nStartRow; + SCROW nLastVisibleRow = -1; + + ::boost::scoped_ptr<ScRowBreakIterator> pRowBreakIter(pDoc->GetRowBreakIterator(nPrintTab)); + SCROW nNextPageBreak = pRowBreakIter->first(); + while (nNextPageBreak != ScRowBreakIterator::NOT_FOUND && nNextPageBreak < nStartRow) + // Skip until the page break position is at the start row or greater. + nNextPageBreak = pRowBreakIter->next(); + + for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow) + { + bool bPageBreak = (nNextPageBreak == nRow); + if (bPageBreak) + nNextPageBreak = pRowBreakIter->next(); + + if (nRow > nStartRow && bVisRow && bPageBreak ) + { + pPageEndY[nTotalY] = nRow-1; + ++nTotalY; + + if ( !aTableParam.bSkipEmpty || + !pDoc->IsPrintEmpty( nPrintTab, nStartCol, nPageStartRow, nEndCol, nRow-1 ) ) + { + pPageRows[nPagesY].SetStartRow( nPageStartRow ); + pPageRows[nPagesY].SetEndRow( nRow-1 ); + pPageRows[nPagesY].SetPagesX( nPagesX ); + if (aTableParam.bSkipEmpty) + lcl_SetHidden( pDoc, nPrintTab, pPageRows[nPagesY], nStartCol, pPageEndX ); + ++nPagesY; + } + + nPageStartRow = nRow; + bVisRow = false; + } + + if (nRow <= nLastVisibleRow) + { + // This row is still visible. Don't bother calling RowHidden() to + // find out, for speed optimization. + bVisRow = true; + continue; + } + + SCROW nLastRow = -1; + if (!pDoc->RowHidden(nRow, nPrintTab, NULL, &nLastRow)) + { + bVisRow = true; + nLastVisibleRow = nLastRow; + } + else + // skip all hidden rows. + nRow = nLastRow; + } + + if (bVisRow) + { + pPageEndY[nTotalY] = nEndRow; + ++nTotalY; + + if ( !aTableParam.bSkipEmpty || + !pDoc->IsPrintEmpty( nPrintTab, nStartCol, nPageStartRow, nEndCol, nEndRow ) ) + { + pPageRows[nPagesY].SetStartRow( nPageStartRow ); + pPageRows[nPagesY].SetEndRow( nEndRow ); + pPageRows[nPagesY].SetPagesX( nPagesX ); + if (aTableParam.bSkipEmpty) + lcl_SetHidden( pDoc, nPrintTab, pPageRows[nPagesY], nStartCol, pPageEndX ); + ++nPagesY; + } + } +} + +//------------------------------------------------------------------------ +// class ScJobSetup +//------------------------------------------------------------------------ + +ScJobSetup::ScJobSetup( SfxPrinter* pPrinter ) +{ + eOrientation = pPrinter->GetOrientation(); + nPaperBin = pPrinter->GetPaperBin(); + ePaper = pPrinter->GetPaper(); + + if ( PAPER_USER == ePaper ) + { + aUserSize = pPrinter->GetPaperSize(); + aUserMapMode = pPrinter->GetMapMode(); + } +}; + + + + + diff --git a/sc/source/ui/view/reffact.cxx b/sc/source/ui/view/reffact.cxx new file mode 100644 index 000000000000..0d35aacb04bb --- /dev/null +++ b/sc/source/ui/view/reffact.cxx @@ -0,0 +1,434 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include <sfx2/app.hxx> +#include <sfx2/basedlgs.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/viewfrm.hxx> + +#include "reffact.hxx" +#include "tabvwsh.hxx" +#include "sc.hrc" +#include "acredlin.hxx" +#include "simpref.hxx" +#include "scmod.hxx" +//<!--Added by PengYunQuan for Validity Cell Range Picker +#include "validate.hxx" +//<!--Added by PengYunQuan for Validity Cell Range Picker + +// ----------------------------------------------------------------------- + +SFX_IMPL_MODELESSDIALOG(ScNameDlgWrapper, FID_DEFINE_NAME ) +SFX_IMPL_MODELESSDIALOG(ScSolverDlgWrapper, SID_OPENDLG_SOLVE ) +SFX_IMPL_MODELESSDIALOG(ScOptSolverDlgWrapper, SID_OPENDLG_OPTSOLVER ) +SFX_IMPL_MODELESSDIALOG(ScPivotLayoutWrapper, SID_OPENDLG_PIVOTTABLE ) +SFX_IMPL_MODELESSDIALOG(ScTabOpDlgWrapper, SID_OPENDLG_TABOP ) +SFX_IMPL_MODELESSDIALOG(ScFilterDlgWrapper, SID_FILTER ) +SFX_IMPL_MODELESSDIALOG(ScSpecialFilterDlgWrapper, SID_SPECIAL_FILTER ) +SFX_IMPL_MODELESSDIALOG(ScDbNameDlgWrapper, SID_DEFINE_DBNAME ) +SFX_IMPL_MODELESSDIALOG(ScConsolidateDlgWrapper, SID_OPENDLG_CONSOLIDATE ) +SFX_IMPL_MODELESSDIALOG(ScPrintAreasDlgWrapper, SID_OPENDLG_EDIT_PRINTAREA ) +SFX_IMPL_MODELESSDIALOG(ScCondFormatDlgWrapper, SID_OPENDLG_CONDFRMT ) +SFX_IMPL_MODELESSDIALOG(ScColRowNameRangesDlgWrapper, SID_DEFINE_COLROWNAMERANGES ) +SFX_IMPL_MODELESSDIALOG(ScFormulaDlgWrapper, SID_OPENDLG_FUNCTION ) +SFX_IMPL_MODELESSDIALOG(ScAcceptChgDlgWrapper, FID_CHG_ACCEPT ) +SFX_IMPL_MODELESSDIALOG(ScHighlightChgDlgWrapper, FID_CHG_SHOW ) +SFX_IMPL_MODELESSDIALOG(ScSimpleRefDlgWrapper, WID_SIMPLE_REF ) +/*!!! dafuer muss der Funktionsautopilot noch umgebaut werden +SFX_IMPL_CHILDWINDOW(ScFunctionDlgWrapper, SID_OPENDLG_FUNCTION ) +SFX_IMPL_CHILDWINDOW(ScEditFunctionDlgWrapper, SID_OPENDLG_EDITFUNCTION ) +SFX_IMPL_CHILDWINDOW(ScArgumentDlgWrapper, SID_OPENDLG_ARGUMENT ) +*/ +//<!--Added by PengYunQuan for Validity Cell Range Picker +//SFX_IMPL_MODELESSDIALOG(ScValidityRefChildWin, SID_VALIDITY_REFERENCE ) +SFX_IMPL_CHILDWINDOW(ScValidityRefChildWin, SID_VALIDITY_REFERENCE) +SfxChildWinInfo __EXPORT ScValidityRefChildWin::GetInfo() const +{ + SfxChildWinInfo anInfo = SfxChildWindow::GetInfo(); + + if( Window *pWnd = GetWindow() ) + { + anInfo.aSize = pWnd->GetSizePixel(); + + if( pWnd->IsDialog() ) + if ( static_cast<Dialog*>(pWnd)->IsRollUp() ) + anInfo.nFlags |= SFX_CHILDWIN_ZOOMIN; + } + + return anInfo; +} + +namespace { ScTabViewShell * lcl_GetTabViewShell( SfxBindings *pBindings ); } +//<!--Added by PengYunQuan for Validity Cell Range Picker + +#define IMPL_CHILD_CTOR(Class,sid) \ + Class::Class( Window* pParentP, \ + sal_uInt16 nId, \ + SfxBindings* p, \ + SfxChildWinInfo* pInfo ) \ + : SfxChildWindow(pParentP, nId) \ + { \ + /*//<!--Added by PengYunQuan for Validity Cell Range Picker*/\ + /************************************************************************************/\ + /* When a new document is creating, the SfxViewFrame may be ready, */\ + /* But the ScTabViewShell may have not been activated yet. In this */\ + /* situation, SfxViewShell::Current() does not get the correct shell, */\ + /* and we should lcl_GetTabViewShell( p ) instead of SfxViewShell::Current() */\ + /************************************************************************************/\ + ScTabViewShell* pViewShell = lcl_GetTabViewShell( p ); \ + /*//-->Added by PengYunQuan for Validity Cell Range Picker*/\ + if (!pViewShell) \ + pViewShell = PTR_CAST( ScTabViewShell, SfxViewShell::Current() ); \ + DBG_ASSERT( pViewShell, "missing view shell :-(" ); \ + pWindow = pViewShell ? \ + pViewShell->CreateRefDialog( p, this, pInfo, pParentP, sid ) : NULL; \ + if (pViewShell && !pWindow) \ + pViewShell->GetViewFrame()->SetChildWindow( nId, sal_False ); \ + } + + +//========================================================================= + +//------------------------------------------------------------------------- +// ScNameDlgWrapper +//------------------------------------------------------------------------- + +IMPL_CHILD_CTOR( ScNameDlgWrapper, FID_DEFINE_NAME ) + +//------------------------------------------------------------------------- +// ScSolverDlgWrapper +//------------------------------------------------------------------------- + +IMPL_CHILD_CTOR( ScSolverDlgWrapper, SID_OPENDLG_SOLVE ) + +//------------------------------------------------------------------------- +// ScOptSolverDlgWrapper +//------------------------------------------------------------------------- + +IMPL_CHILD_CTOR( ScOptSolverDlgWrapper, SID_OPENDLG_OPTSOLVER ) + +//------------------------------------------------------------------------- +// ScPivotLayoutWrapper +//------------------------------------------------------------------------- + +IMPL_CHILD_CTOR( ScPivotLayoutWrapper, SID_OPENDLG_PIVOTTABLE ) + +//------------------------------------------------------------------------- +// ScTabOpDlgWrapper +//------------------------------------------------------------------------- + +IMPL_CHILD_CTOR( ScTabOpDlgWrapper, SID_OPENDLG_TABOP ) + +//------------------------------------------------------------------------- +// ScFilterDlgWrapper +//------------------------------------------------------------------------- + +IMPL_CHILD_CTOR( ScFilterDlgWrapper, SID_FILTER ) + +//------------------------------------------------------------------------- +// ScSpecialFilterDlgWrapper +//------------------------------------------------------------------------- + +IMPL_CHILD_CTOR( ScSpecialFilterDlgWrapper, SID_SPECIAL_FILTER ) + +//------------------------------------------------------------------------- +// ScDbNameDlgWrapper +//------------------------------------------------------------------------- + +IMPL_CHILD_CTOR( ScDbNameDlgWrapper, SID_DEFINE_DBNAME ) + +//------------------------------------------------------------------------- +// ScColRowNameRangesDlgWrapper +//------------------------------------------------------------------------- + +IMPL_CHILD_CTOR( ScColRowNameRangesDlgWrapper, SID_DEFINE_COLROWNAMERANGES ) + +//------------------------------------------------------------------------- +// ScConsolidateDlgWrapper +//------------------------------------------------------------------------- + +IMPL_CHILD_CTOR( ScConsolidateDlgWrapper, SID_OPENDLG_CONSOLIDATE ) + +//------------------------------------------------------------------------- +// ScPrintAreasDlgWrapper +//------------------------------------------------------------------------- + +IMPL_CHILD_CTOR( ScPrintAreasDlgWrapper, SID_OPENDLG_EDIT_PRINTAREA ) + +//------------------------------------------------------------------------- +// ScCondFormatDlgWrapper +//------------------------------------------------------------------------- + +IMPL_CHILD_CTOR( ScCondFormatDlgWrapper, SID_OPENDLG_CONDFRMT ) + +//------------------------------------------------------------------------- +// ScFormulaDlgWrapper +//------------------------------------------------------------------------- + +IMPL_CHILD_CTOR( ScFormulaDlgWrapper, SID_OPENDLG_FUNCTION ) + + +//------------------------------------------------------------------------- +// ScSimpleRefDlgWrapper +//------------------------------------------------------------------------- + +static sal_Bool bScSimpleRefFlag; +static long nScSimpleRefHeight; +static long nScSimpleRefWidth; +static long nScSimpleRefX; +static long nScSimpleRefY; +static sal_Bool bAutoReOpen=sal_True; + +ScSimpleRefDlgWrapper::ScSimpleRefDlgWrapper( Window* pParentP, + sal_uInt16 nId, + SfxBindings* p, + SfxChildWinInfo* pInfo ) + : SfxChildWindow(pParentP, nId) +{ +// ScTabViewShell* pViewShell = +// PTR_CAST( ScTabViewShell, SfxViewShell::Current() ); + + ScTabViewShell* pViewShell = NULL; + SfxDispatcher* pDisp = p->GetDispatcher(); + if ( pDisp ) + { + SfxViewFrame* pViewFrm = pDisp->GetFrame(); + if ( pViewFrm ) + pViewShell = PTR_CAST( ScTabViewShell, pViewFrm->GetViewShell() ); + } + + DBG_ASSERT( pViewShell, "missing view shell :-(" ); + + if(pInfo!=NULL && bScSimpleRefFlag) + { + pInfo->aPos.X()=nScSimpleRefX; + pInfo->aPos.Y()=nScSimpleRefY; + pInfo->aSize.Height()=nScSimpleRefHeight; + pInfo->aSize.Width()=nScSimpleRefWidth; + } + pWindow = NULL; + + if(bAutoReOpen && pViewShell) + pWindow = pViewShell->CreateRefDialog( p, this, pInfo, pParentP, WID_SIMPLE_REF); + + if (!pWindow) + { + SC_MOD()->SetRefDialog( nId, sal_False ); + } +} + +void ScSimpleRefDlgWrapper::SetDefaultPosSize(Point aPos, Size aSize, sal_Bool bSet) +{ + bScSimpleRefFlag=bSet; + if(bScSimpleRefFlag) + { + nScSimpleRefX=aPos.X(); + nScSimpleRefY=aPos.Y(); + nScSimpleRefHeight=aSize.Height(); + nScSimpleRefWidth=aSize.Width(); + } +} + + +String ScSimpleRefDlgWrapper::GetRefString() +{ + String aResult; + if(pWindow!=NULL) + { + aResult=((ScSimpleRefDlg*)pWindow)->GetRefString(); + } + return aResult; +} + +void ScSimpleRefDlgWrapper::SetAutoReOpen(sal_Bool bFlag) +{ + bAutoReOpen=bFlag; +} + +void ScSimpleRefDlgWrapper::SetRefString(const String& rStr) +{ + if(pWindow!=NULL) + { + ((ScSimpleRefDlg*)pWindow)->SetRefString(rStr); + } +} + +void ScSimpleRefDlgWrapper::SetCloseHdl( const Link& rLink ) +{ + if(pWindow!=NULL) + { + ((ScSimpleRefDlg*)pWindow)->SetCloseHdl( rLink ); + } +} + +void ScSimpleRefDlgWrapper::SetUnoLinks( const Link& rDone, + const Link& rAbort, const Link& rChange ) +{ + if(pWindow!=NULL) + { + ((ScSimpleRefDlg*)pWindow)->SetUnoLinks( rDone, rAbort, rChange ); + } +} + +void ScSimpleRefDlgWrapper::SetFlags( sal_Bool bCloseOnButtonUp, sal_Bool bSingleCell, sal_Bool bMultiSelection ) +{ + if(pWindow!=NULL) + { + ((ScSimpleRefDlg*)pWindow)->SetFlags( bCloseOnButtonUp, bSingleCell, bMultiSelection ); + } +} + +void ScSimpleRefDlgWrapper::StartRefInput() +{ + if(pWindow!=NULL) + { + ((ScSimpleRefDlg*)pWindow)->StartRefInput(); + } +} + + + +//------------------------------------------------------------------------- +// ScAcceptChgDlgWrapper //Kommentar: sollte in die ViewShell +//------------------------------------------------------------------------- + +ScAcceptChgDlgWrapper::ScAcceptChgDlgWrapper( Window* pParentP, + sal_uInt16 nId, + SfxBindings* pBindings, + SfxChildWinInfo* pInfo ) : + SfxChildWindow( pParentP, nId ) +{ + ScTabViewShell* pViewShell = + PTR_CAST( ScTabViewShell, SfxViewShell::Current() ); + DBG_ASSERT( pViewShell, "missing view shell :-(" ); + pWindow = pViewShell ? + new ScAcceptChgDlg( pBindings, this, pParentP, pViewShell->GetViewData() ) : + NULL; + if(pWindow!=NULL) + { + ((ScAcceptChgDlg*)pWindow)->Initialize( pInfo ); + } + if (pViewShell && !pWindow) + pViewShell->GetViewFrame()->SetChildWindow( nId, sal_False ); +} + +void ScAcceptChgDlgWrapper::ReInitDlg() +{ + ScTabViewShell* pViewShell = + PTR_CAST( ScTabViewShell, SfxViewShell::Current() ); + DBG_ASSERT( pViewShell, "missing view shell :-(" ); + + if(pWindow!=NULL && pViewShell) + { + ((ScAcceptChgDlg*)pWindow)->ReInit(pViewShell->GetViewData()); + } +} + +//------------------------------------------------------------------------- +// ScHighlightChgDlgWrapper +//------------------------------------------------------------------------- + +IMPL_CHILD_CTOR( ScHighlightChgDlgWrapper, FID_CHG_SHOW ) + +/*------------------------------------------------------------------------*/ +/*@@@ + //------------------------------------------------------------------------- + // ScFunctionDlgWrapper + //------------------------------------------------------------------------- + + IMPL_CHILD_CTOR( ScFunctionDlgWrapper, SID_OPENDLG_FUNCTION ) + + //------------------------------------------------------------------------- + // ScEditFunctionDlgWrapper + //------------------------------------------------------------------------- + + IMPL_CHILD_CTOR( ScEditFunctionDlgWrapper, SID_OPENDLG_EDITFUNCTION ) + + //------------------------------------------------------------------------- + // ScArgumentDlgWrapper + //------------------------------------------------------------------------- + + IMPL_CHILD_CTOR( ScArgumentDlgWrapper, SID_OPENDLG_ARGUMENT ) +@@@*/ +/*------------------------------------------------------------------------*/ + + +//<!--Added by PengYunQuan for Validity Cell Range Picker +namespace +{ + ScTabViewShell * lcl_GetTabViewShell( SfxBindings *pBindings ) + { + if( pBindings ) + if( SfxDispatcher* pDisp = pBindings ->GetDispatcher() ) + if( SfxViewFrame *pFrm = pDisp->GetFrame() ) + if( SfxViewShell* pViewSh = pFrm->GetViewShell() ) + return dynamic_cast<ScTabViewShell*>( pViewSh ); + + return NULL; + } +} + +ScValidityRefChildWin::ScValidityRefChildWin( Window* pParentP, \ + sal_uInt16 nId, \ + SfxBindings* p, \ + SfxChildWinInfo* /*pInfo*/ ) \ + : SfxChildWindow(pParentP, nId), + m_bVisibleLock( false ), + m_bFreeWindowLock( false ), + m_pSavedWndParent( NULL ) +{ + SetWantsFocus( sal_False );\ + ScTabViewShell* pViewShell = \ + NULL != ( pWindow = ScValidationDlg::Find1AliveObject( pParentP ) ) ? static_cast<ScValidationDlg*>(pWindow)->GetTabViewShell() : + lcl_GetTabViewShell( p ); + if (!pViewShell) + pViewShell = PTR_CAST( ScTabViewShell, SfxViewShell::Current() ); + DBG_ASSERT( pViewShell, "missing view shell :-(" ); \ + if (pViewShell && !pWindow) \ + pViewShell->GetViewFrame()->SetChildWindow( nId, sal_False ); \ + else if( pWindow /*&& pWindow->ISA(ScValidationDlg)*/ ) + {}//pWindow = new Window( pParentP, WB_HIDE ); + + if( pWindow ) m_pSavedWndParent = pWindow->GetParent(); +} + +ScValidityRefChildWin::~ScValidityRefChildWin() +{ + if( pWindow ) pWindow->SetParent( m_pSavedWndParent ); + + if( m_bFreeWindowLock ) + pWindow = NULL; +} +//-->Added by PengYunQuan for Validity Cell Range Picker diff --git a/sc/source/ui/view/scextopt.cxx b/sc/source/ui/view/scextopt.cxx new file mode 100644 index 000000000000..d5816ecdd289 --- /dev/null +++ b/sc/source/ui/view/scextopt.cxx @@ -0,0 +1,224 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" +#include "scextopt.hxx" + +#include <vector> +#include <map> +#include <boost/shared_ptr.hpp> + +// ============================================================================ + +ScExtDocSettings::ScExtDocSettings() : + mfTabBarWidth( -1.0 ), + mnLinkCnt( 0 ), + mnDisplTab( 0 ) +{ +} + +// ============================================================================ + +ScExtTabSettings::ScExtTabSettings() : + maUsedArea( ScAddress::INITIALIZE_INVALID ), + maCursor( ScAddress::INITIALIZE_INVALID ), + maFirstVis( ScAddress::INITIALIZE_INVALID ), + maSecondVis( ScAddress::INITIALIZE_INVALID ), + maFreezePos( 0, 0, 0 ), + maSplitPos( 0, 0 ), + meActivePane( SCEXT_PANE_TOPLEFT ), + maGridColor( COL_AUTO ), + mnNormalZoom( 0 ), + mnPageZoom( 0 ), + mbSelected( false ), + mbFrozenPanes( false ), + mbPageMode( false ) +{ +} + +// ============================================================================ + +/** A container for ScExtTabSettings objects. + @descr Internally, a std::map with shared pointers to ScExtTabSettings is + used. The copy constructor and assignment operator make deep copies of the + objects. */ +class ScExtTabSettingsCont +{ +public: + explicit ScExtTabSettingsCont(); + ScExtTabSettingsCont( const ScExtTabSettingsCont& rSrc ); + ScExtTabSettingsCont& operator=( const ScExtTabSettingsCont& rSrc ); + + const ScExtTabSettings* GetTabSettings( SCTAB nTab ) const; + ScExtTabSettings& GetOrCreateTabSettings( SCTAB nTab ); + +private: + typedef ::boost::shared_ptr< ScExtTabSettings > ScExtTabSettingsRef; + typedef ::std::map< SCTAB, ScExtTabSettingsRef > ScExtTabSettingsMap; + + /** Makes a deep copy of all objects in the passed map. */ + void CopyFromMap( const ScExtTabSettingsMap& rMap ); + + ScExtTabSettingsMap maMap; +}; + +// ---------------------------------------------------------------------------- + +ScExtTabSettingsCont::ScExtTabSettingsCont() +{ +} + +ScExtTabSettingsCont::ScExtTabSettingsCont( const ScExtTabSettingsCont& rSrc ) +{ + CopyFromMap( rSrc.maMap ); +} + +ScExtTabSettingsCont& ScExtTabSettingsCont::operator=( const ScExtTabSettingsCont& rSrc ) +{ + CopyFromMap( rSrc.maMap ); + return *this; +} + +const ScExtTabSettings* ScExtTabSettingsCont::GetTabSettings( SCTAB nTab ) const +{ + ScExtTabSettingsMap::const_iterator aIt = maMap.find( nTab ); + return (aIt == maMap.end()) ? 0 : aIt->second.get(); +} + +ScExtTabSettings& ScExtTabSettingsCont::GetOrCreateTabSettings( SCTAB nTab ) +{ + ScExtTabSettingsRef& rxTabSett = maMap[ nTab ]; + if( !rxTabSett ) + rxTabSett.reset( new ScExtTabSettings ); + return *rxTabSett; +} + +void ScExtTabSettingsCont::CopyFromMap( const ScExtTabSettingsMap& rMap ) +{ + maMap.clear(); + for( ScExtTabSettingsMap::const_iterator aIt = rMap.begin(), aEnd = rMap.end(); aIt != aEnd; ++aIt ) + maMap[ aIt->first ].reset( new ScExtTabSettings( *aIt->second ) ); +} + +// ============================================================================ + +/** Implementation struct for ScExtDocOptions containing all members. */ +struct ScExtDocOptionsImpl +{ + typedef ::std::vector< String > StringVec; + + ScExtDocSettings maDocSett; /// Global document settings. + ScExtTabSettingsCont maTabSett; /// Settings for all sheets. + StringVec maCodeNames; /// Codenames for all sheets (VBA module names). + bool mbChanged; /// Use only if something has been changed. + + explicit ScExtDocOptionsImpl(); +}; + +ScExtDocOptionsImpl::ScExtDocOptionsImpl() : + mbChanged( false ) +{ +} + +// ---------------------------------------------------------------------------- + +ScExtDocOptions::ScExtDocOptions() : + mxImpl( new ScExtDocOptionsImpl ) +{ +} + +ScExtDocOptions::ScExtDocOptions( const ScExtDocOptions& rSrc ) : + mxImpl( new ScExtDocOptionsImpl( *rSrc.mxImpl ) ) +{ +} + +ScExtDocOptions::~ScExtDocOptions() +{ +} + +ScExtDocOptions& ScExtDocOptions::operator=( const ScExtDocOptions& rSrc ) +{ + *mxImpl = *rSrc.mxImpl; + return *this; +} + +bool ScExtDocOptions::IsChanged() const +{ + return mxImpl->mbChanged; +} + +void ScExtDocOptions::SetChanged( bool bChanged ) +{ + mxImpl->mbChanged = bChanged; +} + +const ScExtDocSettings& ScExtDocOptions::GetDocSettings() const +{ + return mxImpl->maDocSett; +} + +ScExtDocSettings& ScExtDocOptions::GetDocSettings() +{ + return mxImpl->maDocSett; +} + +const ScExtTabSettings* ScExtDocOptions::GetTabSettings( SCTAB nTab ) const +{ + return mxImpl->maTabSett.GetTabSettings( nTab ); +} + +ScExtTabSettings& ScExtDocOptions::GetOrCreateTabSettings( SCTAB nTab ) +{ + return mxImpl->maTabSett.GetOrCreateTabSettings( nTab ); +} + +SCTAB ScExtDocOptions::GetCodeNameCount() const +{ + return static_cast< SCTAB >( mxImpl->maCodeNames.size() ); +} + +const String& ScExtDocOptions::GetCodeName( SCTAB nTab ) const +{ + DBG_ASSERT( (0 <= nTab) && (nTab < GetCodeNameCount()), "ScExtDocOptions::GetCodeName - invalid sheet index" ); + return ((0 <= nTab) && (nTab < GetCodeNameCount())) ? mxImpl->maCodeNames[ static_cast< size_t >( nTab ) ] : EMPTY_STRING; +} + +void ScExtDocOptions::SetCodeName( SCTAB nTab, const String& rCodeName ) +{ + DBG_ASSERT( nTab >= 0, "ScExtDocOptions::SetCodeName - invalid sheet index" ); + if( nTab >= 0 ) + { + size_t nIndex = static_cast< size_t >( nTab ); + if( nIndex >= mxImpl->maCodeNames.size() ) + mxImpl->maCodeNames.resize( nIndex + 1 ); + mxImpl->maCodeNames[ nIndex ] = rCodeName; + } +} + +// ============================================================================ + diff --git a/sc/source/ui/view/select.cxx b/sc/source/ui/view/select.cxx new file mode 100644 index 000000000000..ab0cb8248813 --- /dev/null +++ b/sc/source/ui/view/select.cxx @@ -0,0 +1,891 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include <tools/urlobj.hxx> +#include <vcl/sound.hxx> +#include <sfx2/docfile.hxx> + +#include "select.hxx" +#include "sc.hrc" +#include "tabvwsh.hxx" +#include "scmod.hxx" +#include "document.hxx" +//#include "dataobj.hxx" +#include "transobj.hxx" +#include "docsh.hxx" +#include "tabprotection.hxx" + +extern sal_uInt16 nScFillModeMouseModifier; // global.cxx + +using namespace com::sun::star; + +// STATIC DATA ----------------------------------------------------------- + +static Point aSwitchPos; //! Member +static sal_Bool bDidSwitch = sal_False; + +// ----------------------------------------------------------------------- + +// +// View (Gridwin / Tastatur) +// + +ScViewFunctionSet::ScViewFunctionSet( ScViewData* pNewViewData ) : + pViewData( pNewViewData ), + pEngine( NULL ), + bAnchor( sal_False ), + bStarted( sal_False ) +{ + DBG_ASSERT(pViewData, "ViewData==0 bei FunctionSet"); +} + +ScSplitPos ScViewFunctionSet::GetWhich() +{ + if (pEngine) + return pEngine->GetWhich(); + else + return pViewData->GetActivePart(); +} + +void ScViewFunctionSet::SetSelectionEngine( ScViewSelectionEngine* pSelEngine ) +{ + pEngine = pSelEngine; +} + +// Drag & Drop + +void __EXPORT ScViewFunctionSet::BeginDrag() +{ + SCTAB nTab = pViewData->GetTabNo(); + + SCsCOL nPosX; + SCsROW nPosY; + if (pEngine) + { + Point aMPos = pEngine->GetMousePosPixel(); + pViewData->GetPosFromPixel( aMPos.X(), aMPos.Y(), GetWhich(), nPosX, nPosY ); + } + else + { + nPosX = pViewData->GetCurX(); + nPosY = pViewData->GetCurY(); + } + + ScModule* pScMod = SC_MOD(); + sal_Bool bRefMode = pScMod->IsFormulaMode(); + if (!bRefMode) + { + pViewData->GetView()->FakeButtonUp( GetWhich() ); // ButtonUp wird verschluckt + + ScMarkData& rMark = pViewData->GetMarkData(); +// rMark.SetMarking(sal_False); // es fehlt ein ButtonUp + rMark.MarkToSimple(); + if ( rMark.IsMarked() && !rMark.IsMultiMarked() ) + { + ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP ); + // bApi = sal_True -> no error mesages + sal_Bool bCopied = pViewData->GetView()->CopyToClip( pClipDoc, sal_False, sal_True ); + if ( bCopied ) + { + sal_Int8 nDragActions = pViewData->GetView()->SelectionEditable() ? + ( DND_ACTION_COPYMOVE | DND_ACTION_LINK ) : + ( DND_ACTION_COPY | DND_ACTION_LINK ); + + ScDocShell* pDocSh = pViewData->GetDocShell(); + TransferableObjectDescriptor aObjDesc; + pDocSh->FillTransferableObjectDescriptor( aObjDesc ); + aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass(); + // maSize is set in ScTransferObj ctor + + ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc ); + uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj ); + + // set position of dragged cell within range + ScRange aMarkRange = pTransferObj->GetRange(); + SCCOL nStartX = aMarkRange.aStart.Col(); + SCROW nStartY = aMarkRange.aStart.Row(); + SCCOL nHandleX = (nPosX >= (SCsCOL) nStartX) ? nPosX - nStartX : 0; + SCROW nHandleY = (nPosY >= (SCsROW) nStartY) ? nPosY - nStartY : 0; + pTransferObj->SetDragHandlePos( nHandleX, nHandleY ); + pTransferObj->SetVisibleTab( nTab ); + + pTransferObj->SetDragSource( pDocSh, rMark ); + + Window* pWindow = pViewData->GetActiveWin(); + if ( pWindow->IsTracking() ) + pWindow->EndTracking( ENDTRACK_CANCEL ); // abort selecting + + SC_MOD()->SetDragObject( pTransferObj, NULL ); // for internal D&D + pTransferObj->StartDrag( pWindow, nDragActions ); + + return; // dragging started + } + else + delete pClipDoc; + } + } + + Sound::Beep(); // can't drag +} + +// Selektion + +void __EXPORT ScViewFunctionSet::CreateAnchor() +{ + if (bAnchor) return; + + sal_Bool bRefMode = SC_MOD()->IsFormulaMode(); + if (bRefMode) + SetAnchor( pViewData->GetRefStartX(), pViewData->GetRefStartY() ); + else + SetAnchor( pViewData->GetCurX(), pViewData->GetCurY() ); +} + +void ScViewFunctionSet::SetAnchor( SCCOL nPosX, SCROW nPosY ) +{ + sal_Bool bRefMode = SC_MOD()->IsFormulaMode(); + ScTabView* pView = pViewData->GetView(); + SCTAB nTab = pViewData->GetTabNo(); + + if (bRefMode) + { + pView->DoneRefMode( sal_False ); + aAnchorPos.Set( nPosX, nPosY, nTab ); + pView->InitRefMode( aAnchorPos.Col(), aAnchorPos.Row(), aAnchorPos.Tab(), + SC_REFTYPE_REF ); + bStarted = sal_True; + } + else if (pViewData->IsAnyFillMode()) + { + aAnchorPos.Set( nPosX, nPosY, nTab ); + bStarted = sal_True; + } + else + { + // nicht weg und gleich wieder hin + if ( bStarted && pView->IsMarking( nPosX, nPosY, nTab ) ) + { + // nix + } + else + { + pView->DoneBlockMode( sal_True ); + aAnchorPos.Set( nPosX, nPosY, nTab ); + ScMarkData& rMark = pViewData->GetMarkData(); + if ( rMark.IsMarked() || rMark.IsMultiMarked() ) + { + pView->InitBlockMode( aAnchorPos.Col(), aAnchorPos.Row(), + aAnchorPos.Tab(), sal_True ); + bStarted = sal_True; + } + else + bStarted = sal_False; + } + } + bAnchor = sal_True; +} + +void __EXPORT ScViewFunctionSet::DestroyAnchor() +{ + sal_Bool bRefMode = SC_MOD()->IsFormulaMode(); + if (bRefMode) + pViewData->GetView()->DoneRefMode( sal_True ); + else + pViewData->GetView()->DoneBlockMode( sal_True ); + + bAnchor = sal_False; +} + +void ScViewFunctionSet::SetAnchorFlag( sal_Bool bSet ) +{ + bAnchor = bSet; +} + +sal_Bool __EXPORT ScViewFunctionSet::SetCursorAtPoint( const Point& rPointPixel, sal_Bool /* bDontSelectAtCursor */ ) +{ + if ( bDidSwitch ) + { + if ( rPointPixel == aSwitchPos ) + return sal_False; // nicht auf falschem Fenster scrollen + else + bDidSwitch = sal_False; + } + aSwitchPos = rPointPixel; // nur wichtig, wenn bDidSwitch + + // treat position 0 as -1, so scrolling is always possible + // (with full screen and hidden headers, the top left border may be at 0) + // (moved from ScViewData::GetPosFromPixel) + + Point aEffPos = rPointPixel; + if ( aEffPos.X() == 0 ) + aEffPos.X() = -1; + if ( aEffPos.Y() == 0 ) + aEffPos.Y() = -1; + + // Scrolling + + Size aWinSize = pEngine->GetWindow()->GetOutputSizePixel(); + sal_Bool bRightScroll = ( aEffPos.X() >= aWinSize.Width() ); + sal_Bool bBottomScroll = ( aEffPos.Y() >= aWinSize.Height() ); + sal_Bool bNegScroll = ( aEffPos.X() < 0 || aEffPos.Y() < 0 ); + sal_Bool bScroll = bRightScroll || bBottomScroll || bNegScroll; + + SCsCOL nPosX; + SCsROW nPosY; + pViewData->GetPosFromPixel( aEffPos.X(), aEffPos.Y(), GetWhich(), + nPosX, nPosY, sal_True, sal_True ); // mit Repair + + // fuer AutoFill in der Mitte der Zelle umschalten + // dabei aber nicht das Scrolling nach rechts/unten verhindern + if ( pViewData->IsFillMode() || pViewData->GetFillMode() == SC_FILL_MATRIX ) + { + sal_Bool bLeft, bTop; + pViewData->GetMouseQuadrant( aEffPos, GetWhich(), nPosX, nPosY, bLeft, bTop ); + ScDocument* pDoc = pViewData->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + if ( bLeft && !bRightScroll ) + do --nPosX; while ( nPosX>=0 && pDoc->ColHidden( nPosX, nTab ) ); + if ( bTop && !bBottomScroll ) + { + if (--nPosY >= 0) + { + nPosY = pDoc->LastVisibleRow(0, nPosY, nTab); + if (!ValidRow(nPosY)) + nPosY = -1; + } + } + // negativ ist erlaubt + } + + // ueber Fixier-Grenze bewegt? + + ScSplitPos eWhich = GetWhich(); + if ( eWhich == pViewData->GetActivePart() ) + { + if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX ) + if ( aEffPos.X() >= aWinSize.Width() ) + { + if ( eWhich == SC_SPLIT_TOPLEFT ) + pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT ), bScroll = sal_False, bDidSwitch = sal_True; + else if ( eWhich == SC_SPLIT_BOTTOMLEFT ) + pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ), bScroll = sal_False, bDidSwitch = sal_True; + } + + if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX ) + if ( aEffPos.Y() >= aWinSize.Height() ) + { + if ( eWhich == SC_SPLIT_TOPLEFT ) + pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT ), bScroll = sal_False, bDidSwitch = sal_True; + else if ( eWhich == SC_SPLIT_TOPRIGHT ) + pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ), bScroll = sal_False, bDidSwitch = sal_True; + } + } + + pViewData->ResetOldCursor(); + return SetCursorAtCell( nPosX, nPosY, bScroll ); +} + +sal_Bool ScViewFunctionSet::SetCursorAtCell( SCsCOL nPosX, SCsROW nPosY, sal_Bool bScroll ) +{ + ScTabView* pView = pViewData->GetView(); + SCTAB nTab = pViewData->GetTabNo(); + ScDocument* pDoc = pViewData->GetDocument(); + + if ( pDoc->IsTabProtected(nTab) ) + { + if (nPosX < 0 || nPosY < 0) + return false; + + ScTableProtection* pProtect = pDoc->GetTabProtection(nTab); + bool bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS); + bool bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS); + + if ( bSkipProtected && bSkipUnprotected ) + return sal_False; + + bool bCellProtected = pDoc->HasAttrib(nPosX, nPosY, nTab, nPosX, nPosY, nTab, HASATTR_PROTECTED); + if ( (bCellProtected && bSkipProtected) || (!bCellProtected && bSkipUnprotected) ) + // Don't select this cell! + return sal_False; + } + + ScModule* pScMod = SC_MOD(); + ScTabViewShell* pViewShell = pViewData->GetViewShell(); + bool bRefMode = ( pViewShell ? pViewShell->IsRefInputMode() : false ); + + sal_Bool bHide = !bRefMode && !pViewData->IsAnyFillMode() && + ( nPosX != (SCsCOL) pViewData->GetCurX() || nPosY != (SCsROW) pViewData->GetCurY() ); + + if (bHide) + pView->HideAllCursors(); + + if (bScroll) + { + if (bRefMode) + { + ScSplitPos eWhich = GetWhich(); + pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE, &eWhich ); + } + else + pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE ); + } + + if (bRefMode) + { + // #90910# if no input is possible from this doc, don't move the reference cursor around + if ( !pScMod->IsModalMode(pViewData->GetSfxDocShell()) ) + { + if (!bAnchor) + { + pView->DoneRefMode( sal_True ); + pView->InitRefMode( nPosX, nPosY, pViewData->GetTabNo(), SC_REFTYPE_REF ); + } + + pView->UpdateRef( nPosX, nPosY, pViewData->GetTabNo() ); + } + } + else if (pViewData->IsFillMode() || + (pViewData->GetFillMode() == SC_FILL_MATRIX && (nScFillModeMouseModifier & KEY_MOD1) )) + { + // Wenn eine Matrix angefasst wurde, kann mit Ctrl auf AutoFill zurueckgeschaltet werden + + SCCOL nStartX, nEndX; + SCROW nStartY, nEndY; // Block + SCTAB nDummy; + pViewData->GetSimpleArea( nStartX, nStartY, nDummy, nEndX, nEndY, nDummy ); + + if (pViewData->GetRefType() != SC_REFTYPE_FILL) + { + pView->InitRefMode( nStartX, nStartY, nTab, SC_REFTYPE_FILL ); + CreateAnchor(); + } + + ScRange aDelRange; + sal_Bool bOldDelMark = pViewData->GetDelMark( aDelRange ); + + if ( nPosX+1 >= (SCsCOL) nStartX && nPosX <= (SCsCOL) nEndX && + nPosY+1 >= (SCsROW) nStartY && nPosY <= (SCsROW) nEndY && + ( nPosX != nEndX || nPosY != nEndY ) ) // verkleinern ? + { + // Richtung (links oder oben) + + long nSizeX = 0; + for (SCCOL i=nPosX+1; i<=nEndX; i++) + nSizeX += pDoc->GetColWidth( i, nTab ); + long nSizeY = (long) pDoc->GetRowHeight( nPosY+1, nEndY, nTab ); + + SCCOL nDelStartX = nStartX; + SCROW nDelStartY = nStartY; + if ( nSizeX > nSizeY ) + nDelStartX = nPosX + 1; + else + nDelStartY = nPosY + 1; + // 0 braucht nicht mehr getrennt abgefragt zu werden, weil nPosX/Y auch negativ wird + + if ( nDelStartX < nStartX ) + nDelStartX = nStartX; + if ( nDelStartY < nStartY ) + nDelStartY = nStartY; + + // Bereich setzen + + pViewData->SetDelMark( ScRange( nDelStartX,nDelStartY,nTab, + nEndX,nEndY,nTab ) ); + pViewData->GetView()->UpdateShrinkOverlay(); + +#if 0 + if ( bOldDelMark ) + { + ScUpdateRect aRect( aDelRange.aStart.Col(), aDelRange.aStart.Row(), + aDelRange.aEnd.Col(), aDelRange.aEnd.Row() ); + aRect.SetNew( nDelStartX,nDelStartY, nEndX,nEndY ); + SCCOL nPaintStartX; + SCROW nPaintStartY; + SCCOL nPaintEndX; + SCROW nPaintEndY; + if (aRect.GetDiff( nPaintStartX, nPaintStartY, nPaintEndX, nPaintEndY )) + pViewData->GetView()-> + PaintArea( nPaintStartX, nPaintStartY, + nPaintEndX, nPaintEndY, SC_UPDATE_MARKS ); + } + else +#endif + pViewData->GetView()-> + PaintArea( nStartX,nDelStartY, nEndX,nEndY, SC_UPDATE_MARKS ); + + nPosX = nEndX; // roten Rahmen um ganzen Bereich lassen + nPosY = nEndY; + + // Referenz wieder richtigherum, falls unten umgedreht + if ( nStartX != pViewData->GetRefStartX() || nStartY != pViewData->GetRefStartY() ) + { + pViewData->GetView()->DoneRefMode(); + pViewData->GetView()->InitRefMode( nStartX, nStartY, nTab, SC_REFTYPE_FILL ); + } + } + else + { + if ( bOldDelMark ) + { + pViewData->ResetDelMark(); + pViewData->GetView()->UpdateShrinkOverlay(); + +#if 0 + pViewData->GetView()-> + PaintArea( aDelRange.aStart.Col(), aDelRange.aStart.Row(), + aDelRange.aEnd.Col(), aDelRange.aEnd.Row(), SC_UPDATE_MARKS ); +#endif + } + + sal_Bool bNegX = ( nPosX < (SCsCOL) nStartX ); + sal_Bool bNegY = ( nPosY < (SCsROW) nStartY ); + + long nSizeX = 0; + if ( bNegX ) + { + // #94321# in SetCursorAtPoint hidden columns are skipped. + // They must be skipped here too, or the result will always be the first hidden column. + do ++nPosX; while ( nPosX<nStartX && pDoc->ColHidden(nPosX, nTab) ); + for (SCCOL i=nPosX; i<nStartX; i++) + nSizeX += pDoc->GetColWidth( i, nTab ); + } + else + for (SCCOL i=nEndX+1; i<=nPosX; i++) + nSizeX += pDoc->GetColWidth( i, nTab ); + + long nSizeY = 0; + if ( bNegY ) + { + // #94321# in SetCursorAtPoint hidden rows are skipped. + // They must be skipped here too, or the result will always be the first hidden row. + if (++nPosY < nStartY) + { + nPosY = pDoc->FirstVisibleRow(nPosY, nStartY-1, nTab); + if (!ValidRow(nPosY)) + nPosY = nStartY; + } + nSizeY += pDoc->GetRowHeight( nPosY, nStartY-1, nTab ); + } + else + nSizeY += pDoc->GetRowHeight( nEndY+1, nPosY, nTab ); + + if ( nSizeX > nSizeY ) // Fill immer nur in einer Richtung + { + nPosY = nEndY; + bNegY = sal_False; + } + else + { + nPosX = nEndX; + bNegX = sal_False; + } + + SCCOL nRefStX = bNegX ? nEndX : nStartX; + SCROW nRefStY = bNegY ? nEndY : nStartY; + if ( nRefStX != pViewData->GetRefStartX() || nRefStY != pViewData->GetRefStartY() ) + { + pViewData->GetView()->DoneRefMode(); + pViewData->GetView()->InitRefMode( nRefStX, nRefStY, nTab, SC_REFTYPE_FILL ); + } + } + + pView->UpdateRef( nPosX, nPosY, nTab ); + } + else if (pViewData->IsAnyFillMode()) + { + sal_uInt8 nMode = pViewData->GetFillMode(); + if ( nMode == SC_FILL_EMBED_LT || nMode == SC_FILL_EMBED_RB ) + { + DBG_ASSERT( pDoc->IsEmbedded(), "!pDoc->IsEmbedded()" ); + ScRange aRange; + pDoc->GetEmbedded( aRange); + ScRefType eRefMode = (nMode == SC_FILL_EMBED_LT) ? SC_REFTYPE_EMBED_LT : SC_REFTYPE_EMBED_RB; + if (pViewData->GetRefType() != eRefMode) + { + if ( nMode == SC_FILL_EMBED_LT ) + pView->InitRefMode( aRange.aEnd.Col(), aRange.aEnd.Row(), nTab, eRefMode ); + else + pView->InitRefMode( aRange.aStart.Col(), aRange.aStart.Row(), nTab, eRefMode ); + CreateAnchor(); + } + + pView->UpdateRef( nPosX, nPosY, nTab ); + } + else if ( nMode == SC_FILL_MATRIX ) + { + SCCOL nStartX, nEndX; + SCROW nStartY, nEndY; // Block + SCTAB nDummy; + pViewData->GetSimpleArea( nStartX, nStartY, nDummy, nEndX, nEndY, nDummy ); + + if (pViewData->GetRefType() != SC_REFTYPE_FILL) + { + pView->InitRefMode( nStartX, nStartY, nTab, SC_REFTYPE_FILL ); + CreateAnchor(); + } + + if ( nPosX < nStartX ) nPosX = nStartX; + if ( nPosY < nStartY ) nPosY = nStartY; + + pView->UpdateRef( nPosX, nPosY, nTab ); + } + // else neue Modi + } + else // normales Markieren + { + sal_Bool bHideCur = bAnchor && ( (SCCOL)nPosX != pViewData->GetCurX() || + (SCROW)nPosY != pViewData->GetCurY() ); + if (bHideCur) + pView->HideAllCursors(); // sonst zweimal: Block und SetCursor + + if (bAnchor) + { + if (!bStarted) + { + sal_Bool bMove = ( nPosX != (SCsCOL) aAnchorPos.Col() || + nPosY != (SCsROW) aAnchorPos.Row() ); + if ( bMove || ( pEngine && pEngine->GetMouseEvent().IsShift() ) ) + { + pView->InitBlockMode( aAnchorPos.Col(), aAnchorPos.Row(), + aAnchorPos.Tab(), sal_True ); + bStarted = sal_True; + } + } + if (bStarted) + pView->MarkCursor( (SCCOL) nPosX, (SCROW) nPosY, nTab, sal_False, sal_False, sal_True ); + } + else + { + ScMarkData& rMark = pViewData->GetMarkData(); + if (rMark.IsMarked() || rMark.IsMultiMarked()) + { + pView->DoneBlockMode(sal_True); + pView->InitBlockMode( nPosX, nPosY, nTab, sal_True ); + pView->MarkCursor( (SCCOL) nPosX, (SCROW) nPosY, nTab ); + + aAnchorPos.Set( nPosX, nPosY, nTab ); + bStarted = sal_True; + } + // #i3875# *Hack* When a new cell is Ctrl-clicked with no pre-selected cells, + // it highlights that new cell as well as the old cell where the cursor is + // positioned prior to the click. A selection mode via Shift-F8 should also + // follow the same behavior. + else if ( pViewData->IsSelCtrlMouseClick() ) + { + SCCOL nOldX = pViewData->GetCurX(); + SCROW nOldY = pViewData->GetCurY(); + + pView->InitBlockMode( nOldX, nOldY, nTab, sal_True ); + pView->MarkCursor( (SCCOL) nOldX, (SCROW) nOldY, nTab ); + + if ( nOldX != nPosX || nOldY != nPosY ) + { + pView->DoneBlockMode( sal_True ); + pView->InitBlockMode( nPosX, nPosY, nTab, sal_True ); + pView->MarkCursor( (SCCOL) nPosX, (SCROW) nPosY, nTab ); + aAnchorPos.Set( nPosX, nPosY, nTab ); + } + + bStarted = sal_True; + } + } + + pView->SetCursor( (SCCOL) nPosX, (SCROW) nPosY ); + pViewData->SetRefStart( nPosX, nPosY, nTab ); + if (bHideCur) + pView->ShowAllCursors(); + } + + if (bHide) + pView->ShowAllCursors(); + + return sal_True; +} + +sal_Bool __EXPORT ScViewFunctionSet::IsSelectionAtPoint( const Point& rPointPixel ) +{ + sal_Bool bRefMode = SC_MOD()->IsFormulaMode(); + if (bRefMode) + return sal_False; + + if (pViewData->IsAnyFillMode()) + return sal_False; + + ScMarkData& rMark = pViewData->GetMarkData(); + if (bAnchor || !rMark.IsMultiMarked()) + { + SCsCOL nPosX; + SCsROW nPosY; + pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), GetWhich(), nPosX, nPosY ); + return pViewData->GetMarkData().IsCellMarked( (SCCOL) nPosX, (SCROW) nPosY ); + } + + return sal_False; +} + +void __EXPORT ScViewFunctionSet::DeselectAtPoint( const Point& /* rPointPixel */ ) +{ + // gibt's nicht +} + +void __EXPORT ScViewFunctionSet::DeselectAll() +{ + if (pViewData->IsAnyFillMode()) + return; + + sal_Bool bRefMode = SC_MOD()->IsFormulaMode(); + if (bRefMode) + { + pViewData->GetView()->DoneRefMode( sal_False ); + } + else + { + pViewData->GetView()->DoneBlockMode( sal_False ); + pViewData->GetViewShell()->UpdateInputHandler(); + } + + bAnchor = sal_False; +} + +//------------------------------------------------------------------------ + +ScViewSelectionEngine::ScViewSelectionEngine( Window* pWindow, ScTabView* pView, + ScSplitPos eSplitPos ) : + SelectionEngine( pWindow, pView->GetFunctionSet() ), + eWhich( eSplitPos ) +{ + // Parameter einstellen + SetSelectionMode( MULTIPLE_SELECTION ); + EnableDrag( sal_True ); +} + + +//------------------------------------------------------------------------ + +// +// Spalten- / Zeilenheader +// + +ScHeaderFunctionSet::ScHeaderFunctionSet( ScViewData* pNewViewData ) : + pViewData( pNewViewData ), + bColumn( sal_False ), + eWhich( SC_SPLIT_TOPLEFT ), + bAnchor( sal_False ), + nCursorPos( 0 ) +{ + DBG_ASSERT(pViewData, "ViewData==0 bei FunctionSet"); +} + +void ScHeaderFunctionSet::SetColumn( sal_Bool bSet ) +{ + bColumn = bSet; +} + +void ScHeaderFunctionSet::SetWhich( ScSplitPos eNew ) +{ + eWhich = eNew; +} + +void __EXPORT ScHeaderFunctionSet::BeginDrag() +{ + // gippsnich +} + +void __EXPORT ScHeaderFunctionSet::CreateAnchor() +{ + if (bAnchor) + return; + + ScTabView* pView = pViewData->GetView(); + pView->DoneBlockMode( sal_True ); + if (bColumn) + { + pView->InitBlockMode( static_cast<SCCOL>(nCursorPos), 0, pViewData->GetTabNo(), sal_True, sal_True, sal_False ); + pView->MarkCursor( static_cast<SCCOL>(nCursorPos), MAXROW, pViewData->GetTabNo() ); + } + else + { + pView->InitBlockMode( 0, nCursorPos, pViewData->GetTabNo(), sal_True, sal_False, sal_True ); + pView->MarkCursor( MAXCOL, nCursorPos, pViewData->GetTabNo() ); + } + bAnchor = sal_True; +} + +void __EXPORT ScHeaderFunctionSet::DestroyAnchor() +{ + pViewData->GetView()->DoneBlockMode( sal_True ); + bAnchor = sal_False; +} + +sal_Bool __EXPORT ScHeaderFunctionSet::SetCursorAtPoint( const Point& rPointPixel, sal_Bool /* bDontSelectAtCursor */ ) +{ + if ( bDidSwitch ) + { + // die naechste gueltige Position muss vom anderen Fenster kommen + if ( rPointPixel == aSwitchPos ) + return sal_False; // nicht auf falschem Fenster scrollen + else + bDidSwitch = sal_False; + } + + // Scrolling + + Size aWinSize = pViewData->GetActiveWin()->GetOutputSizePixel(); + sal_Bool bScroll; + if (bColumn) + bScroll = ( rPointPixel.X() < 0 || rPointPixel.X() >= aWinSize.Width() ); + else + bScroll = ( rPointPixel.Y() < 0 || rPointPixel.Y() >= aWinSize.Height() ); + + // ueber Fixier-Grenze bewegt? + + sal_Bool bSwitched = sal_False; + if ( bColumn ) + { + if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX ) + { + if ( rPointPixel.X() > aWinSize.Width() ) + { + if ( eWhich == SC_SPLIT_TOPLEFT ) + pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT ), bSwitched = sal_True; + else if ( eWhich == SC_SPLIT_BOTTOMLEFT ) + pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ), bSwitched = sal_True; + } + } + } + else // Zeilenkoepfe + { + if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX ) + { + if ( rPointPixel.Y() > aWinSize.Height() ) + { + if ( eWhich == SC_SPLIT_TOPLEFT ) + pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT ), bSwitched = sal_True; + else if ( eWhich == SC_SPLIT_TOPRIGHT ) + pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ), bSwitched = sal_True; + } + } + } + if (bSwitched) + { + aSwitchPos = rPointPixel; + bDidSwitch = sal_True; + return sal_False; // nicht mit falschen Positionen rechnen + } + + // + + SCsCOL nPosX; + SCsROW nPosY; + pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), pViewData->GetActivePart(), + nPosX, nPosY, sal_False ); + if (bColumn) + { + nCursorPos = static_cast<SCCOLROW>(nPosX); + nPosY = pViewData->GetPosY(WhichV(pViewData->GetActivePart())); + } + else + { + nCursorPos = static_cast<SCCOLROW>(nPosY); + nPosX = pViewData->GetPosX(WhichH(pViewData->GetActivePart())); + } + + ScTabView* pView = pViewData->GetView(); + sal_Bool bHide = pViewData->GetCurX() != nPosX || + pViewData->GetCurY() != nPosY; + if (bHide) + pView->HideAllCursors(); + + if (bScroll) + pView->AlignToCursor( nPosX, nPosY, SC_FOLLOW_LINE ); + pView->SetCursor( nPosX, nPosY ); + + if ( !bAnchor || !pView->IsBlockMode() ) + { + pView->DoneBlockMode( sal_True ); + pViewData->GetMarkData().MarkToMulti(); //! wer verstellt das ??? + pView->InitBlockMode( nPosX, nPosY, pViewData->GetTabNo(), sal_True, bColumn, !bColumn ); + + bAnchor = sal_True; + } + + pView->MarkCursor( nPosX, nPosY, pViewData->GetTabNo(), bColumn, !bColumn ); + + // SelectionChanged innerhalb von HideCursor wegen UpdateAutoFillMark + pView->SelectionChanged(); + + if (bHide) + pView->ShowAllCursors(); + + return sal_True; +} + +sal_Bool __EXPORT ScHeaderFunctionSet::IsSelectionAtPoint( const Point& rPointPixel ) +{ + SCsCOL nPosX; + SCsROW nPosY; + pViewData->GetPosFromPixel( rPointPixel.X(), rPointPixel.Y(), pViewData->GetActivePart(), + nPosX, nPosY, sal_False ); + + ScMarkData& rMark = pViewData->GetMarkData(); + if (bColumn) + return rMark.IsColumnMarked( nPosX ); + else + return rMark.IsRowMarked( nPosY ); +} + +void __EXPORT ScHeaderFunctionSet::DeselectAtPoint( const Point& /* rPointPixel */ ) +{ +} + +void __EXPORT ScHeaderFunctionSet::DeselectAll() +{ + pViewData->GetView()->DoneBlockMode( sal_False ); + bAnchor = sal_False; +} + +//------------------------------------------------------------------------ + +ScHeaderSelectionEngine::ScHeaderSelectionEngine( Window* pWindow, ScHeaderFunctionSet* pFuncSet ) : + SelectionEngine( pWindow, pFuncSet ) +{ + // Parameter einstellen + SetSelectionMode( MULTIPLE_SELECTION ); + EnableDrag( sal_False ); +} + + + + + diff --git a/sc/source/ui/view/selectionstate.cxx b/sc/source/ui/view/selectionstate.cxx new file mode 100644 index 000000000000..d5101e68a2b7 --- /dev/null +++ b/sc/source/ui/view/selectionstate.cxx @@ -0,0 +1,89 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" +#include "selectionstate.hxx" + +#include <editeng/editview.hxx> +#include "viewdata.hxx" + +// ============================================================================ + +ScSelectionState::ScSelectionState( ScViewData& rViewData ) : + meType( SC_SELECTTYPE_NONE ) +{ + maCursor.SetTab( rViewData.GetTabNo() ); + ScSplitPos eWhich = rViewData.GetActivePart(); + + if( rViewData.HasEditView( eWhich ) ) + { + meType = SC_SELECTTYPE_EDITCELL; + maCursor.SetCol( rViewData.GetEditViewCol() ); + maCursor.SetRow( rViewData.GetEditViewRow() ); + maEditSel = rViewData.GetEditView( eWhich )->GetSelection(); + } + else + { + maCursor.SetCol( rViewData.GetCurX() ); + maCursor.SetRow( rViewData.GetCurY() ); + + ScMarkData& rMarkData = rViewData.GetMarkData(); + rMarkData.MarkToMulti(); + if( rMarkData.IsMultiMarked() ) + { + meType = SC_SELECTTYPE_SHEET; + rMarkData.FillRangeListWithMarks( &maSheetSel, sal_False ); + } + // else type is SC_SELECTTYPE_NONE - already initialized + } +} + +bool operator==( const ScSelectionState& rL, const ScSelectionState& rR ) +{ + bool bEqual = rL.GetSelectionType() == rR.GetSelectionType(); + if( bEqual ) switch( rL.GetSelectionType() ) + { + case SC_SELECTTYPE_EDITCELL: + bEqual &= ( rL.GetEditSelection().IsEqual( rR.GetEditSelection() ) != sal_False ); + // run through! + case SC_SELECTTYPE_SHEET: + bEqual &= (rL.GetSheetSelection() == rR.GetSheetSelection()) == sal_True; + // run through! + case SC_SELECTTYPE_NONE: + bEqual &= rL.GetCellCursor() == rR.GetCellCursor(); + break; + default: + { + // added to avoid warnings + } + } + return bEqual; +} + +// ============================================================================ + diff --git a/sc/source/ui/view/spelldialog.cxx b/sc/source/ui/view/spelldialog.cxx new file mode 100644 index 000000000000..bdce01457094 --- /dev/null +++ b/sc/source/ui/view/spelldialog.cxx @@ -0,0 +1,279 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" +#include "spelldialog.hxx" + +#include <sfx2/app.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <svx/svxids.hrc> +#include <editeng/editstat.hxx> +#include <editeng/editview.hxx> +#include <editeng/unolingu.hxx> +#include "selectionstate.hxx" + +#include "spelleng.hxx" +#include "tabvwsh.hxx" +#include "docsh.hxx" +#include "scmod.hxx" +#include "editable.hxx" +#include "undoblk.hxx" + +// ============================================================================ + +SFX_IMPL_CHILDWINDOW( ScSpellDialogChildWindow, SID_SPELL_DIALOG ) + +ScSpellDialogChildWindow::ScSpellDialogChildWindow( Window* pParentP, sal_uInt16 nId, + SfxBindings* pBindings, SfxChildWinInfo* pInfo ) : + ::svx::SpellDialogChildWindow( pParentP, nId, pBindings, pInfo ), + mpViewShell( 0 ), + mpViewData( 0 ), + mpDocShell( 0 ), + mpDoc( 0 ), + mbNeedNextObj( false ), + mbOldIdleDisabled( false ) +{ + Init(); +} + +ScSpellDialogChildWindow::~ScSpellDialogChildWindow() +{ + Reset(); +} + +SfxChildWinInfo ScSpellDialogChildWindow::GetInfo() const +{ + return ::svx::SpellDialogChildWindow::GetInfo(); +} + +void ScSpellDialogChildWindow::InvalidateSpellDialog() +{ + ::svx::SpellDialogChildWindow::InvalidateSpellDialog(); +} + +// protected ------------------------------------------------------------------ + +::svx::SpellPortions ScSpellDialogChildWindow::GetNextWrongSentence( bool /*bRecheck*/ ) +{ + ::svx::SpellPortions aPortions; + if( mxEngine.get() && mpViewData ) + { + if( EditView* pEditView = mpViewData->GetSpellingView() ) + { + // edit engine handles cell iteration internally + do + { + if( mbNeedNextObj ) + mxEngine->SpellNextDocument(); + mbNeedNextObj = !mxEngine->IsFinished() && !mxEngine->SpellSentence( *pEditView, aPortions, false ); + } + while( mbNeedNextObj ); + } + + // finished? - close the spelling dialog + if( mxEngine->IsFinished() ) + GetBindings().GetDispatcher()->Execute( SID_SPELL_DIALOG, SFX_CALLMODE_ASYNCHRON ); + } + return aPortions; +} + +void ScSpellDialogChildWindow::ApplyChangedSentence( const ::svx::SpellPortions& rChanged, bool bRecheck ) +{ + if( mxEngine.get() && mpViewData ) + if( EditView* pEditView = mpViewData->GetSpellingView() ) + mxEngine->ApplyChangedSentence( *pEditView, rChanged, bRecheck ); +} + +void ScSpellDialogChildWindow::GetFocus() +{ + if( IsSelectionChanged() ) + { + Reset(); + InvalidateSpellDialog(); + Init(); + } +} + +void ScSpellDialogChildWindow::LoseFocus() +{ +} + +// private -------------------------------------------------------------------- + +void ScSpellDialogChildWindow::Reset() +{ + if( mpViewShell && (mpViewShell == PTR_CAST( ScTabViewShell, SfxViewShell::Current() )) ) + { + if( mxEngine.get() && mxEngine->IsAnyModified() ) + { + const ScAddress& rCursor = mxOldSel->GetCellCursor(); + SCTAB nTab = rCursor.Tab(); + SCCOL nOldCol = rCursor.Col(); + SCROW nOldRow = rCursor.Row(); + SCCOL nNewCol = mpViewData->GetCurX(); + SCROW nNewRow = mpViewData->GetCurY(); + mpDocShell->GetUndoManager()->AddUndoAction( new ScUndoConversion( + mpDocShell, mpViewData->GetMarkData(), + nOldCol, nOldRow, nTab, mxUndoDoc.release(), + nNewCol, nNewRow, nTab, mxRedoDoc.release(), + ScConversionParam( SC_CONVERSION_SPELLCHECK ) ) ); + mpDoc->SetDirty(); + mpDocShell->SetDocumentModified(); + } + + mpViewData->SetSpellingView( 0 ); + mpViewShell->KillEditView( sal_True ); + mpDocShell->PostPaintGridAll(); + mpViewShell->UpdateInputHandler(); + mpDoc->DisableIdle( mbOldIdleDisabled ); + } + mxEngine.reset(); + mxUndoDoc.reset(); + mxRedoDoc.reset(); + mxOldSel.reset(); + mpViewShell = 0; + mpViewData = 0; + mpDocShell = 0; + mpDoc = 0; + mbNeedNextObj = false; + mbOldIdleDisabled = false; +} + +void ScSpellDialogChildWindow::Init() +{ + if( mpViewShell ) + return; + if( (mpViewShell = PTR_CAST( ScTabViewShell, SfxViewShell::Current() )) == 0 ) + return; + + mpViewData = mpViewShell->GetViewData(); + + // exit edit mode - TODO support spelling in edit mode + if( mpViewData->HasEditView( mpViewData->GetActivePart() ) ) + SC_MOD()->InputEnterHandler(); + + mxOldSel.reset( new ScSelectionState( *mpViewData ) ); + + mpDocShell = mpViewData->GetDocShell(); + mpDoc = mpDocShell->GetDocument(); + + const ScAddress& rCursor = mxOldSel->GetCellCursor(); + SCCOL nCol = rCursor.Col(); + SCROW nRow = rCursor.Row(); + SCTAB nTab = rCursor.Tab(); + + ScMarkData& rMarkData = mpViewData->GetMarkData(); + rMarkData.MarkToMulti(); + + switch( mxOldSel->GetSelectionType() ) + { + case SC_SELECTTYPE_NONE: + case SC_SELECTTYPE_SHEET: + { + // test if there is something editable + ScEditableTester aTester( mpDoc, rMarkData ); + if( !aTester.IsEditable() ) + { + // #i85751# Don't show a ErrorMessage here, because the vcl + // parent of the InfoBox is not fully initialized yet. + // This leads to problems in the modality behaviour of the + // ScSpellDialogChildWindow. + + //mpViewShell->ErrorMessage( aTester.GetMessageId() ); + return; + } + } + break; + + // edit mode exited, see TODO above +// case SC_SELECTTYPE_EDITCELL: +// break; + + default: + DBG_ERRORFILE( "ScSpellDialogChildWindow::Init - unknown selection type" ); + } + + mbOldIdleDisabled = mpDoc->IsIdleDisabled(); + mpDoc->DisableIdle( sal_True ); // #42726# stop online spelling + + // *** create Undo/Redo documents *** ------------------------------------- + + mxUndoDoc.reset( new ScDocument( SCDOCMODE_UNDO ) ); + mxUndoDoc->InitUndo( mpDoc, nTab, nTab ); + mxRedoDoc.reset( new ScDocument( SCDOCMODE_UNDO ) ); + mxRedoDoc->InitUndo( mpDoc, nTab, nTab ); + + if ( rMarkData.GetSelectCount() > 1 ) + { + SCTAB nTabCount = mpDoc->GetTableCount(); + for( SCTAB nOtherTab = 0; nOtherTab < nTabCount; ++nOtherTab ) + { + if( rMarkData.GetTableSelect( nOtherTab ) && (nOtherTab != nTab) ) + { + mxUndoDoc->AddUndoTab( nOtherTab, nOtherTab ); + mxRedoDoc->AddUndoTab( nOtherTab, nOtherTab ); + } + } + } + + // *** create and init the edit engine *** -------------------------------- + + mxEngine.reset( new ScSpellingEngine( + mpDoc->GetEnginePool(), *mpViewData, mxUndoDoc.get(), mxRedoDoc.get(), LinguMgr::GetSpellChecker() ) ); + mxEngine->SetRefDevice( mpViewData->GetActiveWin() ); + + mpViewShell->MakeEditView( mxEngine.get(), nCol, nRow ); + EditView* pEditView = mpViewData->GetEditView( mpViewData->GetActivePart() ); + mpViewData->SetSpellingView( pEditView ); + Rectangle aRect( Point( 0, 0 ), Point( 0, 0 ) ); + pEditView->SetOutputArea( aRect ); + mxEngine->SetControlWord( EE_CNTRL_USECHARATTRIBS ); + mxEngine->EnableUndo( sal_False ); + mxEngine->SetPaperSize( aRect.GetSize() ); + mxEngine->SetText( EMPTY_STRING ); + mxEngine->ClearModifyFlag(); + + mbNeedNextObj = true; +} + +bool ScSpellDialogChildWindow::IsSelectionChanged() +{ + if( !mxOldSel.get() || !mpViewShell || (mpViewShell != PTR_CAST( ScTabViewShell, SfxViewShell::Current() )) ) + return true; + + if( EditView* pEditView = mpViewData->GetSpellingView() ) + if( pEditView->GetEditEngine() != mxEngine.get() ) + return true; + + ScSelectionState aNewSel( *mpViewData ); + return mxOldSel->GetSheetSelection() != aNewSel.GetSheetSelection(); +} + +// ============================================================================ + diff --git a/sc/source/ui/view/spelleng.cxx b/sc/source/ui/view/spelleng.cxx new file mode 100644 index 000000000000..ab7b876d6417 --- /dev/null +++ b/sc/source/ui/view/spelleng.cxx @@ -0,0 +1,458 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" +#include "spelleng.hxx" +#include <com/sun/star/i18n/TextConversionOption.hpp> + +#include <memory> + +#include "scitems.hxx" +#include <editeng/eeitem.hxx> + + +#include <editeng/langitem.hxx> +#include <editeng/editobj.hxx> +#include <editeng/editview.hxx> +#include <sfx2/viewfrm.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/svapp.hxx> + +#include "spelldialog.hxx" +#include "tabvwsh.hxx" +#include "docsh.hxx" +#include "cell.hxx" +#include "patattr.hxx" +#include "waitoff.hxx" +#include "globstr.hrc" + + +using namespace ::com::sun::star; + +// ============================================================================ + +namespace { + +bool lclHasString( ScDocument& rDoc, SCCOL nCol, SCROW nRow, SCTAB nTab, const String& rString ) +{ + String aCompStr; + rDoc.GetString( nCol, nRow, nTab, aCompStr ); + return aCompStr == rString; //! case-insensitive? +} + +} // namespace + +// ---------------------------------------------------------------------------- + +ScConversionEngineBase::ScConversionEngineBase( + SfxItemPool* pEnginePoolP, ScViewData& rViewData, + ScDocument* pUndoDoc, ScDocument* pRedoDoc ) : + ScEditEngineDefaulter( pEnginePoolP ), + mrViewData( rViewData ), + mrDocShell( *rViewData.GetDocShell() ), + mrDoc( *rViewData.GetDocShell()->GetDocument() ), + maSelState( rViewData ), + mpUndoDoc( pUndoDoc ), + mpRedoDoc( pRedoDoc ), + meCurrLang( LANGUAGE_ENGLISH_US ), + mbIsAnyModified( false ), + mbInitialState( true ), + mbWrappedInTable( false ), + mbFinished( false ) +{ + maSelState.GetCellCursor().GetVars( mnStartCol, mnStartRow, mnStartTab ); + // start with cell A1 in cell/range/multi-selection, will seek to first selected + if( maSelState.GetSelectionType() == SC_SELECTTYPE_SHEET ) + { + mnStartCol = 0; + mnStartRow = 0; + } + mnCurrCol = mnStartCol; + mnCurrRow = mnStartRow; +} + +ScConversionEngineBase::~ScConversionEngineBase() +{ +} + +bool ScConversionEngineBase::FindNextConversionCell() +{ + ScMarkData& rMark = mrViewData.GetMarkData(); + ScTabViewShell* pViewShell = mrViewData.GetViewShell(); + ScBaseCell* pCell = NULL; + const ScPatternAttr* pPattern = NULL; + const ScPatternAttr* pLastPattern = NULL; + ::std::auto_ptr< SfxItemSet > pEditDefaults( new SfxItemSet( GetEmptyItemSet() ) ); + + if( IsModified() ) + { + mbIsAnyModified = true; + + String aNewStr = GetText(); + + sal_Bool bMultiTab = (rMark.GetSelectCount() > 1); + String aVisibleStr; + if( bMultiTab ) + mrDoc.GetString( mnCurrCol, mnCurrRow, mnStartTab, aVisibleStr ); + + for( SCTAB nTab = 0, nTabCount = mrDoc.GetTableCount(); nTab < nTabCount; ++nTab ) + { + // #69965# always change the cell on the visible tab, + // on the other selected tabs only if they contain the same text + + if( (nTab == mnStartTab) || + (bMultiTab && rMark.GetTableSelect( nTab ) && + lclHasString( mrDoc, mnCurrCol, mnCurrRow, nTab, aVisibleStr )) ) + { + ScAddress aPos( mnCurrCol, mnCurrRow, nTab ); + CellType eCellType = mrDoc.GetCellType( aPos ); + pCell = mrDoc.GetCell( aPos ); + + if( mpUndoDoc && pCell ) + { + ScBaseCell* pUndoCell = pCell->CloneWithoutNote( *mpUndoDoc ); + mpUndoDoc->PutCell( aPos, pUndoCell ); + } + + if( eCellType == CELLTYPE_EDIT ) + { + if( pCell ) + { + ScEditCell* pEditCell = static_cast< ScEditCell* >( pCell ); + ::std::auto_ptr< EditTextObject > pEditObj( CreateTextObject() ); + pEditCell->SetData( pEditObj.get(), GetEditTextObjectPool() ); + } + } + else + { + mrDoc.SetString( mnCurrCol, mnCurrRow, nTab, aNewStr ); + pCell = mrDoc.GetCell( aPos ); + } + + if( mpRedoDoc && pCell ) + { + ScBaseCell* pRedoCell = pCell->CloneWithoutNote( *mpRedoDoc ); + mpRedoDoc->PutCell( aPos, pRedoCell ); + } + + mrDocShell.PostPaintCell( mnCurrCol, mnCurrRow, nTab ); + } + } + } + pCell = NULL; + SCCOL nNewCol = mnCurrCol; + SCROW nNewRow = mnCurrRow; + + if( mbInitialState ) + { + /* On very first call, decrement row to let GetNextSpellingCell() find + the first cell of current range. */ + mbInitialState = false; + --nNewRow; + } + + bool bSheetSel = maSelState.GetSelectionType() == SC_SELECTTYPE_SHEET; + bool bLoop = true; + bool bFound = false; + while( bLoop && !bFound ) + { + bLoop = mrDoc.GetNextSpellingCell( nNewCol, nNewRow, mnStartTab, bSheetSel, rMark ); + if( bLoop ) + { + FillFromCell( mnCurrCol, mnCurrRow, mnStartTab ); + + if( mbWrappedInTable && ((nNewCol > mnStartCol) || ((nNewCol == mnStartCol) && (nNewRow >= mnStartRow))) ) + { + ShowFinishDialog(); + bLoop = false; + mbFinished = true; + } + else if( nNewCol > MAXCOL ) + { + // no more cells in the sheet - try to restart at top of sheet + + if( bSheetSel || ((mnStartCol == 0) && (mnStartRow == 0)) ) + { + // conversion started at cell A1 or in selection, do not query to restart at top + ShowFinishDialog(); + bLoop = false; + mbFinished = true; + } + else if( ShowTableWrapDialog() ) + { + // conversion started anywhere but in cell A1, user wants to restart + nNewRow = MAXROW + 2; + mbWrappedInTable = true; + } + else + { + bLoop = false; + mbFinished = true; + } + } + else + { + pPattern = mrDoc.GetPattern( nNewCol, nNewRow, mnStartTab ); + if( pPattern && (pPattern != pLastPattern) ) + { + pPattern->FillEditItemSet( pEditDefaults.get() ); + SetDefaults( *pEditDefaults ); + pLastPattern = pPattern; + } + + // language changed? + const SfxPoolItem* pItem = mrDoc.GetAttr( nNewCol, nNewRow, mnStartTab, ATTR_FONT_LANGUAGE ); + if( const SvxLanguageItem* pLangItem = PTR_CAST( SvxLanguageItem, pItem ) ) + { + LanguageType eLang = static_cast< LanguageType >( pLangItem->GetValue() ); + if( eLang == LANGUAGE_SYSTEM ) + eLang = Application::GetSettings().GetLanguage(); // never use SYSTEM for spelling + if( eLang != meCurrLang ) + { + meCurrLang = eLang; + SetDefaultLanguage( eLang ); + } + } + + FillFromCell( nNewCol, nNewRow, mnStartTab ); + + bFound = bLoop && NeedsConversion(); + } + } + } + + if( bFound ) + { + pViewShell->AlignToCursor( nNewCol, nNewRow, SC_FOLLOW_JUMP ); + pViewShell->SetCursor( nNewCol, nNewRow, sal_True ); + mrViewData.GetView()->MakeEditView( this, nNewCol, nNewRow ); + EditView* pEditView = mrViewData.GetSpellingView(); + // maSelState.GetEditSelection() returns (0,0) if not in edit mode -> ok + pEditView->SetSelection( maSelState.GetEditSelection() ); + + ClearModifyFlag(); + mnCurrCol = nNewCol; + mnCurrRow = nNewRow; + } + + return bFound; +} + +void ScConversionEngineBase::RestoreCursorPos() +{ + const ScAddress& rPos = maSelState.GetCellCursor(); + mrViewData.GetViewShell()->SetCursor( rPos.Col(), rPos.Row() ); +} + +bool ScConversionEngineBase::ShowTableWrapDialog() +{ + // default: no dialog, always restart at top + return true; +} + +void ScConversionEngineBase::ShowFinishDialog() +{ + // default: no dialog +} + +// private -------------------------------------------------------------------- + +void ScConversionEngineBase::FillFromCell( SCCOL nCol, SCROW nRow, SCTAB nTab ) +{ + CellType eCellType; + mrDoc.GetCellType( nCol, nRow, nTab, eCellType ); + + switch( eCellType ) + { + case CELLTYPE_STRING: + { + String aText; + mrDoc.GetString( nCol, nRow, nTab, aText ); + SetText( aText ); + } + break; + case CELLTYPE_EDIT: + { + ScBaseCell* pCell = NULL; + mrDoc.GetCell( nCol, nRow, nTab, pCell ); + if( pCell ) + { + const EditTextObject* pNewEditObj = NULL; + static_cast< ScEditCell* >( pCell )->GetData( pNewEditObj ); + if( pNewEditObj ) + SetText( *pNewEditObj ); + } + } + break; + default: + SetText( EMPTY_STRING ); + } +} + +// ============================================================================ + +ScSpellingEngine::ScSpellingEngine( + SfxItemPool* pEnginePoolP, ScViewData& rViewData, + ScDocument* pUndoDoc, ScDocument* pRedoDoc, + XSpellCheckerRef xSpeller ) : + ScConversionEngineBase( pEnginePoolP, rViewData, pUndoDoc, pRedoDoc ) +{ + SetSpeller( xSpeller ); +} + +void ScSpellingEngine::ConvertAll( EditView& rEditView ) +{ + EESpellState eState = EE_SPELL_OK; + if( FindNextConversionCell() ) + eState = rEditView.StartSpeller( static_cast< sal_Bool >( sal_True ) ); + + DBG_ASSERT( eState != EE_SPELL_NOSPELLER, "ScSpellingEngine::Convert - no spell checker" ); + if( eState == EE_SPELL_NOLANGUAGE ) + { + Window* pParent = GetDialogParent(); + ScWaitCursorOff aWaitOff( pParent ); + InfoBox( pParent, ScGlobal::GetRscString( STR_NOLANGERR ) ).Execute(); + } +} + +sal_Bool ScSpellingEngine::SpellNextDocument() +{ + return FindNextConversionCell(); +} + +bool ScSpellingEngine::NeedsConversion() +{ + return HasSpellErrors() != EE_SPELL_OK; +} + +bool ScSpellingEngine::ShowTableWrapDialog() +{ + Window* pParent = GetDialogParent(); + ScWaitCursorOff aWaitOff( pParent ); + MessBox aMsgBox( pParent, WinBits( WB_YES_NO | WB_DEF_YES ), + ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_0 ), + ScGlobal::GetRscString( STR_SPELLING_BEGIN_TAB) ); + return aMsgBox.Execute() == RET_YES; +} + +void ScSpellingEngine::ShowFinishDialog() +{ + Window* pParent = GetDialogParent(); + ScWaitCursorOff aWaitOff( pParent ); + InfoBox( pParent, ScGlobal::GetRscString( STR_SPELLING_STOP_OK ) ).Execute(); +} + +Window* ScSpellingEngine::GetDialogParent() +{ + sal_uInt16 nWinId = ScSpellDialogChildWindow::GetChildWindowId(); + SfxViewFrame* pViewFrm = mrViewData.GetViewShell()->GetViewFrame(); + if( pViewFrm->HasChildWindow( nWinId ) ) + if( SfxChildWindow* pChild = pViewFrm->GetChildWindow( nWinId ) ) + if( Window* pWin = pChild->GetWindow() ) + if( pWin->IsVisible() ) + return pWin; + + // fall back to standard dialog parent + return mrDocShell.GetActiveDialogParent(); +} + +// ============================================================================ + +ScConversionParam::ScConversionParam( ScConversionType eConvType ) : + meConvType( eConvType ), + meSourceLang( LANGUAGE_NONE ), + meTargetLang( LANGUAGE_NONE ), + mnOptions( 0 ), + mbUseTargetFont( false ), + mbIsInteractive( false ) +{ +} + +ScConversionParam::ScConversionParam( ScConversionType eConvType, + LanguageType eLang, sal_Int32 nOptions, bool bIsInteractive ) : + meConvType( eConvType ), + meSourceLang( eLang ), + meTargetLang( eLang ), + mnOptions( nOptions ), + mbUseTargetFont( false ), + mbIsInteractive( bIsInteractive ) +{ + if (LANGUAGE_KOREAN == eLang) + mnOptions = i18n::TextConversionOption::CHARACTER_BY_CHARACTER; +} + +ScConversionParam::ScConversionParam( ScConversionType eConvType, + LanguageType eSourceLang, LanguageType eTargetLang, const Font& rTargetFont, + sal_Int32 nOptions, bool bIsInteractive ) : + meConvType( eConvType ), + meSourceLang( eSourceLang ), + meTargetLang( eTargetLang ), + maTargetFont( rTargetFont ), + mnOptions( nOptions ), + mbUseTargetFont( true ), + mbIsInteractive( bIsInteractive ) +{ + if (LANGUAGE_KOREAN == meSourceLang && LANGUAGE_KOREAN == meTargetLang) + mnOptions = i18n::TextConversionOption::CHARACTER_BY_CHARACTER; +} + +// ---------------------------------------------------------------------------- + +ScTextConversionEngine::ScTextConversionEngine( + SfxItemPool* pEnginePoolP, ScViewData& rViewData, + const ScConversionParam& rConvParam, + ScDocument* pUndoDoc, ScDocument* pRedoDoc ) : + ScConversionEngineBase( pEnginePoolP, rViewData, pUndoDoc, pRedoDoc ), + maConvParam( rConvParam ) +{ +} + +void ScTextConversionEngine::ConvertAll( EditView& rEditView ) +{ + if( FindNextConversionCell() ) + { + rEditView.StartTextConversion( + maConvParam.GetSourceLang(), maConvParam.GetTargetLang(), maConvParam.GetTargetFont(), + maConvParam.GetOptions(), maConvParam.IsInteractive(), sal_True ); + // #i34769# restore initial cursor position + RestoreCursorPos(); + } +} + +sal_Bool ScTextConversionEngine::ConvertNextDocument() +{ + return FindNextConversionCell(); +} + +bool ScTextConversionEngine::NeedsConversion() +{ + return HasConvertibleTextPortion( maConvParam.GetSourceLang() ); +} + +// ============================================================================ + diff --git a/sc/source/ui/view/tabcont.cxx b/sc/source/ui/view/tabcont.cxx new file mode 100644 index 000000000000..6e41548dc31f --- /dev/null +++ b/sc/source/ui/view/tabcont.cxx @@ -0,0 +1,638 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include <sfx2/viewfrm.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/docfile.hxx> +#include <vcl/sound.hxx> +#include <tools/urlobj.hxx> +#include <vcl/svapp.hxx> +#include "tabcont.hxx" +#include "tabvwsh.hxx" +#include "docsh.hxx" +#include "scmod.hxx" +#include "scresid.hxx" +#include "sc.hrc" +#include "globstr.hrc" +#include "transobj.hxx" +#include "clipparam.hxx" + + +// STATIC DATA ----------------------------------------------------------- + +//================================================================== + +ScTabControl::ScTabControl( Window* pParent, ScViewData* pData ) : + TabBar( pParent, WinBits( WB_BORDER | WB_3DLOOK | WB_SCROLL | + WB_RANGESELECT | WB_MULTISELECT | WB_DRAG | WB_SIZEABLE ) ), + DropTargetHelper( this ), + DragSourceHelper( this ), + pViewData( pData ), + nMouseClickPageId( TabBar::PAGE_NOT_FOUND ), + nSelPageIdByMouse( TabBar::PAGE_NOT_FOUND ), + bErrorShown( sal_False ) +{ + ScDocument* pDoc = pViewData->GetDocument(); + + String aString; + Color aTabBgColor; + SCTAB nCount = pDoc->GetTableCount(); + for (SCTAB i=0; i<nCount; i++) + { + if (pDoc->IsVisible(i)) + { + if (pDoc->GetName(i,aString)) + { + if ( pDoc->IsScenario(i) ) + InsertPage( static_cast<sal_uInt16>(i)+1, aString, TPB_SPECIAL ); + else + InsertPage( static_cast<sal_uInt16>(i)+1, aString ); + if ( !pDoc->IsDefaultTabBgColor(i) ) + { + aTabBgColor = pDoc->GetTabBgColor(i); + SetTabBgColor( static_cast<sal_uInt16>(i)+1, aTabBgColor ); + } + } + } + } + + SetCurPageId( static_cast<sal_uInt16>(pViewData->GetTabNo()) + 1 ); + + SetSizePixel( Size(SC_TABBAR_DEFWIDTH, 0) ); + + SetSplitHdl( LINK( pViewData->GetView(), ScTabView, TabBarResize ) ); + + EnableEditMode(); +} + +ScTabControl::~ScTabControl() +{ +} + +sal_uInt16 ScTabControl::GetMaxId() const +{ + sal_uInt16 nVisCnt = GetPageCount(); + if (nVisCnt) + return GetPageId(nVisCnt-1); + + return 0; +} + +SCTAB ScTabControl::GetPrivatDropPos(const Point& rPos ) +{ + sal_uInt16 nPos = ShowDropPos(rPos); + + SCTAB nRealPos = static_cast<SCTAB>(nPos); + + if(nPos !=0 ) + { + ScDocument* pDoc = pViewData->GetDocument(); + + SCTAB nCount = pDoc->GetTableCount(); + + sal_uInt16 nViewPos=0; + nRealPos = nCount; + for (SCTAB i=0; i<nCount; i++) + { + if (pDoc->IsVisible(i)) + { + nViewPos++; + if(nViewPos==nPos) + { + SCTAB j; + for (j=i+1; j<nCount; j++) + { + if (pDoc->IsVisible(j)) + { + break; + } + } + nRealPos =j; + break; + } + } + } + } + return nRealPos ; +} + +void ScTabControl::MouseButtonDown( const MouseEvent& rMEvt ) +{ + ScModule* pScMod = SC_MOD(); + if ( !pScMod->IsModalMode() && !pScMod->IsFormulaMode() && !IsInEditMode() ) + { + // View aktivieren + pViewData->GetViewShell()->SetActive(); // Appear und SetViewFrame + pViewData->GetView()->ActiveGrabFocus(); + } + + /* #47745# Click into free area -> insert new sheet (like in Draw). + Needing clean left click without modifiers (may be context menu). + #106948# Remember clicks to all pages, to be able to move mouse pointer later. */ + if( rMEvt.IsLeft() && (rMEvt.GetModifier() == 0) ) + nMouseClickPageId = GetPageId( rMEvt.GetPosPixel() ); + else + nMouseClickPageId = TabBar::PAGE_NOT_FOUND; + + TabBar::MouseButtonDown( rMEvt ); +} + +void ScTabControl::MouseButtonUp( const MouseEvent& rMEvt ) +{ + Point aPos = PixelToLogic( rMEvt.GetPosPixel() ); + + // mouse button down and up on same page? + if( nMouseClickPageId != GetPageId( aPos ) ) + nMouseClickPageId = TabBar::PAGE_NOT_FOUND; + + if ( rMEvt.GetClicks() == 2 && rMEvt.IsLeft() && nMouseClickPageId != 0 && nMouseClickPageId != TAB_PAGE_NOTFOUND ) + { + SfxDispatcher* pDispatcher = pViewData->GetViewShell()->GetViewFrame()->GetDispatcher(); + pDispatcher->Execute( FID_TAB_MENU_RENAME, SFX_CALLMODE_SYNCHRON | SFX_CALLMODE_RECORD ); + } + + if( nMouseClickPageId == 0 ) + { + // Click in the area next to the existing tabs: + // #i70320# if several sheets are selected, deselect all ecxept the current sheet, + // otherwise add new sheet + sal_uInt16 nSlot = ( GetSelectPageCount() > 1 ) ? FID_TAB_DESELECTALL : FID_INS_TABLE; + SfxDispatcher* pDispatcher = pViewData->GetViewShell()->GetViewFrame()->GetDispatcher(); + pDispatcher->Execute( nSlot, SFX_CALLMODE_SYNCHRON | SFX_CALLMODE_RECORD ); + // forget page ID, to be really sure that the dialog is not called twice + nMouseClickPageId = TabBar::PAGE_NOT_FOUND; + } + + TabBar::MouseButtonUp( rMEvt ); +} + +void ScTabControl::Select() +{ + /* Remember last clicked page ID. */ + nSelPageIdByMouse = nMouseClickPageId; + /* Reset nMouseClickPageId, so that next Select() call may invalidate + nSelPageIdByMouse (i.e. if called from keyboard). */ + nMouseClickPageId = TabBar::PAGE_NOT_FOUND; + + ScModule* pScMod = SC_MOD(); + ScDocument* pDoc = pViewData->GetDocument(); + ScMarkData& rMark = pViewData->GetMarkData(); + SCTAB nCount = pDoc->GetTableCount(); + SCTAB i; + + if ( pScMod->IsTableLocked() ) // darf jetzt nicht umgeschaltet werden ? + { + // den alten Zustand des TabControls wiederherstellen: + + for (i=0; i<nCount; i++) + SelectPage( static_cast<sal_uInt16>(i)+1, rMark.GetTableSelect(i) ); + SetCurPageId( static_cast<sal_uInt16>(pViewData->GetTabNo()) + 1 ); + + Sound::Beep(); + return; + } + + sal_uInt16 nCurId = GetCurPageId(); + if (!nCurId) return; // kann vorkommen, wenn bei Excel-Import alles versteckt ist + sal_uInt16 nPage = nCurId - 1; + + // OLE-inplace deaktivieren + if ( nPage != static_cast<sal_uInt16>(pViewData->GetTabNo()) ) + pViewData->GetView()->DrawMarkListHasChanged(); + + // InputEnterHandler nur wenn nicht Referenzeingabe + + sal_Bool bRefMode = pScMod->IsFormulaMode(); + if (!bRefMode) + pScMod->InputEnterHandler(); + + for (i=0; i<nCount; i++) + rMark.SelectTable( i, IsPageSelected(static_cast<sal_uInt16>(i)+1) ); + +/* Markierungen werden per Default nicht pro Tabelle gehalten + sal_uInt16 nSelCnt = GetSelectPageCount(); + if (nSelCnt>1) + pDoc->ExtendMarksFromTable( nPage ); +*/ + + SfxDispatcher& rDisp = pViewData->GetDispatcher(); + if (rDisp.IsLocked()) + pViewData->GetView()->SetTabNo( static_cast<SCTAB>(nPage) ); + else + { + // Tabelle fuer Basic ist 1-basiert + SfxUInt16Item aItem( SID_CURRENTTAB, nPage + 1 ); + rDisp.Execute( SID_CURRENTTAB, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD, + &aItem, (void*) NULL ); + } + + SfxBindings& rBind = pViewData->GetBindings(); + rBind.Invalidate( FID_FILL_TAB ); + rBind.Invalidate( FID_TAB_DESELECTALL ); + + rBind.Invalidate( FID_INS_TABLE ); + rBind.Invalidate( FID_TAB_APPEND ); + rBind.Invalidate( FID_TAB_MOVE ); + rBind.Invalidate( FID_TAB_RENAME ); + rBind.Invalidate( FID_DELETE_TABLE ); + rBind.Invalidate( FID_TABLE_SHOW ); + rBind.Invalidate( FID_TABLE_HIDE ); + rBind.Invalidate( FID_TAB_SET_TAB_BG_COLOR ); + + // SetReference nur wenn der Konsolidieren-Dialog offen ist + // (fuer Referenzen ueber mehrere Tabellen) + // bei anderen gibt das nur unnoetiges Gezappel + + if ( bRefMode && pViewData->GetRefType() == SC_REFTYPE_REF ) + if ( pViewData->GetViewShell()->GetViewFrame()->HasChildWindow(SID_OPENDLG_CONSOLIDATE) ) + { + ScRange aRange( + pViewData->GetRefStartX(), pViewData->GetRefStartY(), pViewData->GetRefStartZ(), + pViewData->GetRefEndX(), pViewData->GetRefEndY(), pViewData->GetRefEndZ() ); + pScMod->SetReference( aRange, pDoc, &rMark ); + pScMod->EndReference(); // wegen Auto-Hide + } +} + +void ScTabControl::UpdateStatus() +{ + ScDocument* pDoc = pViewData->GetDocument(); + ScMarkData& rMark = pViewData->GetMarkData(); + sal_Bool bActive = pViewData->IsActive(); + + SCTAB nCount = pDoc->GetTableCount(); + SCTAB i; + String aString; + SCTAB nMaxCnt = Max( nCount, static_cast<SCTAB>(GetMaxId()) ); + Color aTabBgColor; + + sal_Bool bModified = sal_False; // Tabellen-Namen + for (i=0; i<nMaxCnt && !bModified; i++) + { + if (pDoc->IsVisible(i)) + { + pDoc->GetName(i,aString); + aTabBgColor = pDoc->GetTabBgColor(i); + } + else + { + aString.Erase(); + } + + if ( (GetPageText(static_cast<sal_uInt16>(i)+1) != aString) || (GetTabBgColor(static_cast<sal_uInt16>(i)+1) != aTabBgColor) ) + bModified = sal_True; + } + + if (bModified) + { + Clear(); + for (i=0; i<nCount; i++) + { + if (pDoc->IsVisible(i)) + { + if (pDoc->GetName(i,aString)) + { + if ( pDoc->IsScenario(i) ) + InsertPage( static_cast<sal_uInt16>(i)+1, aString, TPB_SPECIAL ); + else + InsertPage( static_cast<sal_uInt16>(i)+1, aString ); + if ( !pDoc->IsDefaultTabBgColor(i) ) + { + aTabBgColor = pDoc->GetTabBgColor(i); + SetTabBgColor( static_cast<sal_uInt16>(i)+1, aTabBgColor ); + } + } + } + } + } + SetCurPageId( static_cast<sal_uInt16>(pViewData->GetTabNo()) + 1 ); + + if (bActive) + { + bModified = sal_False; // Selektion + for (i=0; i<nMaxCnt && !bModified; i++) + if ( rMark.GetTableSelect(i) != IsPageSelected(static_cast<sal_uInt16>(i)+1) ) + bModified = sal_True; + + // #i99576# the following loop is mis-optimized on unxsoli4 and the reason + // why this file is in NOOPTFILES. + if ( bModified ) + for (i=0; i<nCount; i++) + SelectPage( static_cast<sal_uInt16>(i)+1, rMark.GetTableSelect(i) ); + } + else + { + } +} + +void ScTabControl::ActivateView(sal_Bool bActivate) +{ +// ScDocument* pDoc = pViewData->GetDocument(); + ScMarkData& rMark = pViewData->GetMarkData(); + +// ResetMark direkt in TabView +// pDoc->ResetMark(); + + sal_uInt16 nCurId = GetCurPageId(); + if (!nCurId) return; // kann vorkommen, wenn bei Excel-Import alles versteckt ist + sal_uInt16 nPage = nCurId - 1; +// sal_uInt16 nCount = GetMaxId(); + + /* + sal_uInt16 i; + for (i=0; i<nCount; i++) + { + SelectPage( i+1, sal_False ); + if (bActivate) + rMark.SelectTable( i, sal_False ); + } + */ + if (bActivate) + { + SelectPage( nPage+1, sal_True ); + rMark.SelectTable( static_cast<SCTAB>(nPage), sal_True ); + } + Invalidate(); +} + +void ScTabControl::SetSheetLayoutRTL( sal_Bool bSheetRTL ) +{ + SetEffectiveRTL( bSheetRTL ); + nSelPageIdByMouse = TabBar::PAGE_NOT_FOUND; +} + + +void ScTabControl::Command( const CommandEvent& rCEvt ) +{ + ScModule* pScMod = SC_MOD(); + ScTabViewShell* pViewSh = pViewData->GetViewShell(); + sal_Bool bDisable = pScMod->IsFormulaMode() || pScMod->IsModalMode(); + + // ViewFrame erstmal aktivieren (Bug 19493): + pViewSh->SetActive(); + + sal_uInt16 nCmd = rCEvt.GetCommand(); + if ( nCmd == COMMAND_CONTEXTMENU ) + { + if (!bDisable) + { + // #i18735# select the page that is under the mouse cursor + // if multiple tables are selected and the one under the cursor + // is not part of them then unselect them + sal_uInt16 nId = GetPageId( rCEvt.GetMousePosPixel() ); + if (nId) + { + sal_Bool bAlreadySelected = IsPageSelected( nId ); + //make the clicked page the current one + SetCurPageId( nId ); + //change the selection when the current one is not already + //selected or part of a multi selection + if(!bAlreadySelected) + { + sal_uInt16 nCount = GetMaxId(); + + for (sal_uInt16 i=1; i<=nCount; i++) + SelectPage( i, i==nId ); + Select(); + } + } + + // #i52073# OLE inplace editing has to be stopped before showing the sheet tab context menu + pViewSh->DeactivateOle(); + + // Popup-Menu: + // get Dispatcher from ViewData (ViewFrame) instead of Shell (Frame), so it can't be null + pViewData->GetDispatcher().ExecutePopup( ScResId(RID_POPUP_TAB) ); + } + } +} + +void ScTabControl::StartDrag( sal_Int8 /* nAction */, const Point& rPosPixel ) +{ + ScModule* pScMod = SC_MOD(); + sal_Bool bDisable = pScMod->IsFormulaMode() || pScMod->IsModalMode(); + + if (!bDisable) + { + Region aRegion( Rectangle(0,0,0,0) ); + CommandEvent aCEvt( rPosPixel, COMMAND_STARTDRAG, sal_True ); // needed for StartDrag + if (TabBar::StartDrag( aCEvt, aRegion )) + DoDrag( aRegion ); + } +} + +void ScTabControl::DoDrag( const Region& /* rRegion */ ) +{ + ScDocShell* pDocSh = pViewData->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + + SCTAB nTab = pViewData->GetTabNo(); + ScMarkData aTabMark = pViewData->GetMarkData(); + aTabMark.ResetMark(); // doesn't change marked table information + aTabMark.SetMarkArea( ScRange(0,0,nTab,MAXCOL,MAXROW,nTab) ); + + ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP ); + ScClipParam aClipParam(ScRange(0, 0, 0, MAXCOL, MAXROW, 0), false); + pDoc->CopyToClip(aClipParam, pClipDoc, &aTabMark, false); + + TransferableObjectDescriptor aObjDesc; + pDocSh->FillTransferableObjectDescriptor( aObjDesc ); + aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass(); + // maSize is set in ScTransferObj ctor + + ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc ); + com::sun::star::uno::Reference<com::sun::star::datatransfer::XTransferable> xTransferable( pTransferObj ); + + pTransferObj->SetDragSourceFlags( SC_DROP_TABLE ); + + pTransferObj->SetDragSource( pDocSh, aTabMark ); + + Window* pWindow = pViewData->GetActiveWin(); + SC_MOD()->SetDragObject( pTransferObj, NULL ); // for internal D&D + pTransferObj->StartDrag( pWindow, DND_ACTION_COPYMOVE | DND_ACTION_LINK ); +} + +sal_uInt16 lcl_DocShellNr( ScDocument* pDoc ) +{ + sal_uInt16 nShellCnt = 0; + SfxObjectShell* pShell = SfxObjectShell::GetFirst(); + while ( pShell ) + { + if ( pShell->Type() == TYPE(ScDocShell) ) + { + if ( ((ScDocShell*)pShell)->GetDocument() == pDoc ) + return nShellCnt; + + ++nShellCnt; + } + pShell = SfxObjectShell::GetNext( *pShell ); + } + + DBG_ERROR("Dokument nicht gefunden"); + return 0; +} + +sal_Int8 ScTabControl::ExecuteDrop( const ExecuteDropEvent& rEvt ) +{ + EndSwitchPage(); + + ScDocument* pDoc = pViewData->GetDocument(); + const ScDragData& rData = SC_MOD()->GetDragData(); + if ( rData.pCellTransfer && ( rData.pCellTransfer->GetDragSourceFlags() & SC_DROP_TABLE ) && + rData.pCellTransfer->GetSourceDocument() == pDoc ) + { + // moving of tables within the document + SCTAB nPos = GetPrivatDropPos( rEvt.maPosPixel ); + HideDropPos(); + + if ( nPos == rData.pCellTransfer->GetVisibleTab() && rEvt.mnAction == DND_ACTION_MOVE ) + { + // #i83005# do nothing - don't move to the same position + // (too easily triggered unintentionally, and might take a long time in large documents) + } + else + { + if ( !pDoc->GetChangeTrack() && pDoc->IsDocEditable() ) + { + //! use table selection from the tab control where dragging was started? + pViewData->GetView()->MoveTable( lcl_DocShellNr(pDoc), nPos, rEvt.mnAction != DND_ACTION_MOVE ); + + rData.pCellTransfer->SetDragWasInternal(); // don't delete + return sal_True; + } + else + Sound::Beep(); + } + } + + return 0; +} + +sal_Int8 ScTabControl::AcceptDrop( const AcceptDropEvent& rEvt ) +{ + if ( rEvt.mbLeaving ) + { + EndSwitchPage(); + HideDropPos(); + return rEvt.mnAction; + } + + const ScDocument* pDoc = pViewData->GetDocument(); + const ScDragData& rData = SC_MOD()->GetDragData(); + if ( rData.pCellTransfer && ( rData.pCellTransfer->GetDragSourceFlags() & SC_DROP_TABLE ) && + rData.pCellTransfer->GetSourceDocument() == pDoc ) + { + // moving of tables within the document + if ( !pDoc->GetChangeTrack() && pDoc->IsDocEditable() ) + { + ShowDropPos( rEvt.maPosPixel ); + return rEvt.mnAction; + } + } + else // switch sheets for all formats + { + SwitchPage( rEvt.maPosPixel ); // switch sheet after timeout + return 0; // nothing can be dropped here + } + + return 0; +} + +long ScTabControl::StartRenaming() +{ + if ( pViewData->GetDocument()->IsDocEditable() ) + return TABBAR_RENAMING_YES; + else + return TABBAR_RENAMING_NO; +} + +long ScTabControl::AllowRenaming() +{ + ScTabViewShell* pViewSh = pViewData->GetViewShell(); + DBG_ASSERT( pViewSh, "pViewData->GetViewShell()" ); + + long nRet = TABBAR_RENAMING_CANCEL; + sal_uInt16 nId = GetEditPageId(); + if ( nId ) + { + SCTAB nTab = nId - 1; + String aNewName = GetEditText(); + sal_Bool bDone = pViewSh->RenameTable( aNewName, nTab ); + if ( bDone ) + nRet = TABBAR_RENAMING_YES; + else if ( bErrorShown ) + { + // if the error message from this TabControl is currently visible, + // don't end edit mode now, to avoid problems when returning to + // the other call (showing the error) - this should not happen + DBG_ERROR("ScTabControl::AllowRenaming: nested calls"); + nRet = TABBAR_RENAMING_NO; + } + else if ( Application::IsInModalMode() ) + { + // #73472# don't show error message above any modal dialog + // instead cancel renaming without error message + nRet = TABBAR_RENAMING_CANCEL; + } + else + { + bErrorShown = sal_True; + pViewSh->ErrorMessage( STR_INVALIDTABNAME ); + bErrorShown = sal_False; + nRet = TABBAR_RENAMING_NO; + } + } + return nRet; +} + +void ScTabControl::EndRenaming() +{ + if ( HasFocus() ) + pViewData->GetView()->ActiveGrabFocus(); +} + +void ScTabControl::Mirror() +{ + TabBar::Mirror(); + if( nSelPageIdByMouse != TabBar::PAGE_NOT_FOUND ) + { + Rectangle aRect( GetPageRect( GetCurPageId() ) ); + if( !aRect.IsEmpty() ) + SetPointerPosPixel( aRect.Center() ); + nSelPageIdByMouse = TabBar::PAGE_NOT_FOUND; // only once after a Select() + } +} + + + diff --git a/sc/source/ui/view/tabpopsh.cxx b/sc/source/ui/view/tabpopsh.cxx new file mode 100644 index 000000000000..f5033d5d0df5 --- /dev/null +++ b/sc/source/ui/view/tabpopsh.cxx @@ -0,0 +1,72 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + +#include "tabpopsh.hxx" +#include "sc.hrc" + +#undef ShellClass +#define ShellClass ScTabPopShell +SFX_SLOTMAP(ScTabPopShell) +{ + SFX_SLOT( 0,0, DummyExec, DummyState, 0, SfxVoidItem ) +}; + + +TYPEINIT1(ScTabPopShell,SfxShell); + +//SFX_IMPL_IDL_INTERFACE(ScTabPopShell, SfxShell, 0) +SFX_IMPL_INTERFACE(ScTabPopShell, SfxShell, ResId( 0, NULL)) +{ + SFX_POPUPMENU_REGISTRATION( RID_POPUP_TAB ); +} + + + + +ScTabPopShell::ScTabPopShell(SfxItemPool& rItemPool) +{ + SetPool( &rItemPool ); +} + + +ScTabPopShell::~ScTabPopShell() +{ +} + + +void ScTabPopShell::DummyExec( SfxRequest& rReq ) +{ +} + + +void ScTabPopShell::DummyState( SfxItemSet& rSet ) +{ +} diff --git a/sc/source/ui/view/tabsplit.cxx b/sc/source/ui/view/tabsplit.cxx new file mode 100644 index 000000000000..9007d627cda5 --- /dev/null +++ b/sc/source/ui/view/tabsplit.cxx @@ -0,0 +1,105 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +// System - Includes ----------------------------------------------------- + + + +// INCLUDE --------------------------------------------------------------- + +#include "tabsplit.hxx" +#include "viewdata.hxx" +#include "dbfunc.hxx" + +//================================================================== + +ScTabSplitter::ScTabSplitter( Window* pParent, WinBits nWinStyle, ScViewData* pData ) : + Splitter( pParent, nWinStyle ), + pViewData(pData) +{ + SetFixed(sal_False); + EnableRTL( sal_False ); +} + + +ScTabSplitter::~ScTabSplitter() +{ +} + +void __EXPORT ScTabSplitter::MouseMove( const MouseEvent& rMEvt ) +{ + if (bFixed) + Window::MouseMove( rMEvt ); + else + Splitter::MouseMove( rMEvt ); +} + +void __EXPORT ScTabSplitter::MouseButtonUp( const MouseEvent& rMEvt ) +{ + if (bFixed) + Window::MouseButtonUp( rMEvt ); + else + Splitter::MouseButtonUp( rMEvt ); +} + +void __EXPORT ScTabSplitter::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if (bFixed) + Window::MouseButtonDown( rMEvt ); + else + Splitter::MouseButtonDown( rMEvt ); +} + +void __EXPORT ScTabSplitter::Splitting( Point& rSplitPos ) +{ + Window* pParent = GetParent(); + Point aScreenPos = pParent->OutputToNormalizedScreenPixel( rSplitPos ); + pViewData->GetView()->SnapSplitPos( aScreenPos ); + Point aNew = pParent->NormalizedScreenToOutputPixel( aScreenPos ); + if ( IsHorizontal() ) + rSplitPos.X() = aNew.X(); + else + rSplitPos.Y() = aNew.Y(); +} + + +void ScTabSplitter::SetFixed(sal_Bool bSet) +{ + bFixed = bSet; + if (bSet) + SetPointer(POINTER_ARROW); + else if (IsHorizontal()) + SetPointer(POINTER_HSPLIT); + else + SetPointer(POINTER_VSPLIT); +} + + + diff --git a/sc/source/ui/view/tabview.cxx b/sc/source/ui/view/tabview.cxx new file mode 100644 index 000000000000..83bf1a4c9c12 --- /dev/null +++ b/sc/source/ui/view/tabview.cxx @@ -0,0 +1,2535 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + +//------------------------------------------------------------------ + +#if 0 +#define _MACRODLG_HXX +#define _BIGINT_HXX +#define _SVCONTNR_HXX +#define BASIC_NODIALOGS +#define _SFXMNUITEM_HXX +#define _SVDXOUT_HXX +#define _SVDATTR_HXX +#define _SFXMNUITEM_HXX +#define _DLGCFG_HXX +#define _SFXMNUMGR_HXX +#define _SFXBASIC_HXX +#define _MODALDLG_HXX +#define _SFX_TEMPLDLG_HXX +#define _SFXSTBMGR_HXX +#define _SFXTBXMGR_HXX +#define _BASE_DLGS_HXX +#define _SFXIMGMGR_HXX +#define _SFXMNUMGR_HXX +#define _SFXSTBITEM_HXX +#define _SFXTBXCTRL_HXX +#define _PASSWD_HXX +//#define _SFXFILEDLG_HXX +//#define _SFXREQUEST_HXX +#define _SFXOBJFACE_HXX + +#define _SDR_NOTRANSFORM +#define _SVDXOUT_HXX +#endif +#include <vcl/svapp.hxx> + +/////////////////////////////////////////////////////////////////////////// +// NODRAW.HXX +// Erweiterte Konstanten, um CLOKs mit SVDRAW.HXX zu vermeiden +// Die u.a. Aenderungen nehmen vorgeschlagene Konstante vorweg +/////////////////////////////////////////////////////////////////////////// + +#if 0 +#define _SDR_NOTRANSFORM // Transformationen, selten verwendet +#define _SDR_NOTOUCH // Hit-Tests, selten verwendet + +#define _SDR_NOUNDO // Undo-Objekte +#define _SDR_NOPAGEOBJ // SdrPageObj +#define _SDR_NOVIRTOBJ // SdrVirtObj +#define _SDR_NOGROUPOBJ // SdrGroupObj +#define _SDR_NOTEXTOBJ // SdrTextObj +#define _SDR_NOPATHOBJ // SdrPathObj +#define _SDR_NOEDGEOBJ // SdrEdgeObj +#define _SDR_NORECTOBJ // SdrRectObj +#define _SDR_NOCAPTIONOBJ // SdrCaptionObj +#define _SDR_NOCIRCLEOBJ // SdrCircleObj +#define _SDR_NOGRAFOBJ // SdrGrafObj +#define _SDR_NOOLE2OBJ // SdrOle2Obj +#endif + +// Dieses define entfernt die VCControls aus SI.HXX + +#define _SI_HXX // VCControls + +////////////////////// Umsetzen der Standard-Defines ////////////////////// + +//#define _SVDDRAG_HXX // SdrDragStat +#define _SVDPAGE_HXX // SdrPage + +#ifdef _SDR_NOSURROGATEOBJ + #undef _SDR_NOSURROGATEOBJ + #define _SVDSURO_HXX +#endif + +#ifdef _SDR_NOPAGEOBJ + #undef _SDR_NOPAGEOBJ + #define _SVDOPAGE_HXX +#endif + +#ifdef _SDR_NOVIRTOBJ + #undef _SDR_NOVIRTOBJ + #define _SVDOVIRT_HXX +#endif + +#ifdef _SDR_NOGROUPOBJ + #undef _SDR_NOGROUPOBJ + #define _SVDOGRP_HXX +#endif + +#ifdef _SDR_NOTEXTOBJ + #undef _SDR_NOTEXTOBJ + #define _SVDOTEXT_HXX +#endif + +#ifdef _SDR_NOPATHOBJ + #undef _SDR_NOPATHOBJ + #define _SVDOPATH_HXX +#endif + +#ifdef _SDR_NOEDGEOBJ + #undef _SDR_NOEDGEOBJ + #define _SVDOEDGE_HXX +#endif + +#ifdef _SDR_NORECTOBJ + #undef _SDR_NORECTOBJ + #define _SVDORECT_HXX +#else + #undef _SDVOTEXT_OBJ +#endif + +#ifdef _SDR_NOCAPTIONOBJ + #undef _SDR_NOCAPTIONOBJ + #define _SVDCAPT_HXX +#endif + +#ifdef _SDR_NOCIRCLEOBJ + #undef _SDR_NOCIRCLEOBJ + #define _SVDOCIRC_HXX +#endif + +#ifdef _SDR_NOGRAFOBJ + #undef _SDR_NOGRAFOBJ + #define _SVDOGRAF_HXX +#else + #undef _SVDOTEXT_HXX + #undef _SVDORECT_HXX +#endif + +#ifdef _SDR_NOOLE2OBJ + #undef _SDR_NOOLE2OBJ + #define _SVDOOLE2_HXX +#else + #undef _SVDOTEXT_HXX + #undef _SVDORECT_HXX +#endif + +//#ifdef _SDR_NOVIEWS +// #define _SVDDRAG_HXX +//#endif + +////////////////////// Ende der SVDRAW-Modifikationen ///////////////////// + + +// INCLUDE --------------------------------------------------------------- + +#include "scitems.hxx" +#include <sfx2/viewfrm.hxx> +#include <sfx2/bindings.hxx> +#include <vcl/help.hxx> +#include <rtl/logfile.hxx> + +#include "tabview.hxx" +#include "tabvwsh.hxx" +#include "document.hxx" +#include "gridwin.hxx" +#include "olinewin.hxx" +#include "olinetab.hxx" +#include "tabsplit.hxx" +#include "colrowba.hxx" +#include "tabcont.hxx" +#include "scmod.hxx" +#include "sc.hrc" +#include "viewutil.hxx" +#include "globstr.hrc" +#include "drawview.hxx" +#include "docsh.hxx" +#include "viewuno.hxx" +#include "AccessibilityHints.hxx" +#include "appoptio.hxx" + +#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp> + +#include <string> +#include <algorithm> + +#define SPLIT_MARGIN 30 +#define SC_ICONSIZE 36 + +#define SC_SCROLLBAR_MIN 30 +#define SC_TABBAR_MIN 6 + +// fuer Rad-Maus +#define SC_DELTA_ZOOM 10 + +using namespace ::com::sun::star; + +// STATIC DATA ----------------------------------------------------------- + + +//================================================================== + +// Corner-Button + +ScCornerButton::ScCornerButton( Window* pParent, ScViewData* pData, sal_Bool bAdditional ) : + Window( pParent, WinBits( 0 ) ), + pViewData( pData ), + bAdd( bAdditional ) +{ + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + SetBackground( rStyleSettings.GetFaceColor() ); + EnableRTL( sal_False ); +} + +__EXPORT ScCornerButton::~ScCornerButton() +{ +} + +void __EXPORT ScCornerButton::Paint( const Rectangle& rRect ) +{ + Size aSize = GetOutputSizePixel(); + long nPosX = aSize.Width()-1; + long nPosY = aSize.Height()-1; + + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + + Window::Paint(rRect); + + sal_Bool bLayoutRTL = pViewData->GetDocument()->IsLayoutRTL( pViewData->GetTabNo() ); + long nDarkX = bLayoutRTL ? 0 : nPosX; + + if ( !bAdd && !rStyleSettings.GetHighContrastMode() ) + { + // match the shaded look of column/row headers + + Color aFace( rStyleSettings.GetFaceColor() ); + Color aWhite( COL_WHITE ); + Color aCenter( aFace ); + aCenter.Merge( aWhite, 0xd0 ); // lighten up a bit + Color aOuter( aFace ); + aOuter.Merge( aWhite, 0xa0 ); // lighten up more + + long nCenterX = (aSize.Width() / 2) - 1; + long nCenterY = (aSize.Height() / 2) - 1; + + SetLineColor(); + SetFillColor(aCenter); + DrawRect( Rectangle( nCenterX, nCenterY, nCenterX, nPosY ) ); + DrawRect( Rectangle( nCenterX, nCenterY, nDarkX, nCenterY ) ); + SetFillColor(aOuter); + DrawRect( Rectangle( 0, 0, nPosX, nCenterY-1 ) ); + if ( bLayoutRTL ) + DrawRect( Rectangle( nCenterX+1, nCenterY, nPosX, nPosY ) ); + else + DrawRect( Rectangle( 0, nCenterY, nCenterX-1, nPosY ) ); + } + + // both buttons have the same look now - only dark right/bottom lines + SetLineColor( rStyleSettings.GetDarkShadowColor() ); + DrawLine( Point(0,nPosY), Point(nPosX,nPosY) ); + DrawLine( Point(nDarkX,0), Point(nDarkX,nPosY) ); +} + +void ScCornerButton::StateChanged( StateChangedType nType ) +{ + Window::StateChanged( nType ); + + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + SetBackground( rStyleSettings.GetFaceColor() ); + Invalidate(); +} + +// ----------------------------------------------------------------------- + +void ScCornerButton::DataChanged( const DataChangedEvent& rDCEvt ) +{ + Window::DataChanged( rDCEvt ); + + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + SetBackground( rStyleSettings.GetFaceColor() ); + Invalidate(); +} + + +void __EXPORT ScCornerButton::Resize() +{ + Invalidate(); +} + +void __EXPORT ScCornerButton::MouseButtonDown( const MouseEvent& rMEvt ) +{ + ScModule* pScMod = SC_MOD(); + sal_Bool bDisable = pScMod->IsFormulaMode() || pScMod->IsModalMode(); + if (!bDisable) + { + ScTabViewShell* pViewSh = pViewData->GetViewShell(); + pViewSh->SetActive(); // Appear und SetViewFrame + pViewSh->ActiveGrabFocus(); + + sal_Bool bControl = rMEvt.IsMod1(); + pViewSh->SelectAll( bControl ); + } +} + +//================================================================== + +sal_Bool lcl_HasColOutline( const ScViewData& rViewData ) +{ + const ScOutlineTable* pTable = rViewData.GetDocument()->GetOutlineTable(rViewData.GetTabNo()); + if (pTable) + { + const ScOutlineArray* pArray = pTable->GetColArray(); + if ( pArray->GetDepth() > 0 ) + return sal_True; + } + return sal_False; +} + +sal_Bool lcl_HasRowOutline( const ScViewData& rViewData ) +{ + const ScOutlineTable* pTable = rViewData.GetDocument()->GetOutlineTable(rViewData.GetTabNo()); + if (pTable) + { + const ScOutlineArray* pArray = pTable->GetRowArray(); + if ( pArray->GetDepth() > 0 ) + return sal_True; + } + return sal_False; +} + +//================================================================== + +// Init und Konstruktoren +// ScTabView::Init() in tabview5.cxx wegen out of keys + + +#define TABVIEW_INIT \ + pSelEngine( NULL ), \ + aFunctionSet( &aViewData ), \ + pHdrSelEng( NULL ), \ + aHdrFunc( &aViewData ), \ + pDrawView( NULL ), \ + bDrawSelMode( sal_False ), \ + aVScrollTop( pFrameWin, WinBits( WB_VSCROLL | WB_DRAG ) ), \ + aVScrollBottom( pFrameWin, WinBits( WB_VSCROLL | WB_DRAG ) ), \ + aHScrollLeft( pFrameWin, WinBits( WB_HSCROLL | WB_DRAG ) ), \ + aHScrollRight( pFrameWin, WinBits( WB_HSCROLL | WB_DRAG ) ), \ + aCornerButton( pFrameWin, &aViewData, sal_False ), \ + aTopButton( pFrameWin, &aViewData, sal_True ), \ + aScrollBarBox( pFrameWin, WB_SIZEABLE ), \ + pInputHintWindow( NULL ), \ + pPageBreakData( NULL ), \ + pHighlightRanges( NULL ), \ + pBrushDocument( NULL ), \ + pDrawBrushSet( NULL ), \ + bLockPaintBrush( sal_False ), \ + pTimerWindow( NULL ), \ + nTipVisible( 0 ), \ + bDragging( sal_False ), \ + bIsBlockMode( sal_False ), \ + bBlockNeg( sal_False ), \ + bBlockCols( sal_False ), \ + bBlockRows( sal_False ), \ + mfPendingTabBarWidth( -1.0 ), \ + bMinimized( sal_False ), \ + bInUpdateHeader( sal_False ), \ + bInActivatePart( sal_False ), \ + bInZoomUpdate( sal_False ), \ + bMoveIsShift( sal_False ), \ + bNewStartIfMarking( sal_False ) + + +ScTabView::ScTabView( Window* pParent, ScDocShell& rDocSh, ScTabViewShell* pViewShell ) : + pFrameWin( pParent ), + aViewData( &rDocSh, pViewShell ), + TABVIEW_INIT +{ + RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScTabView::ScTabView" ); + + Init(); +} + +//UNUSED2009-05 ScTabView::ScTabView( Window* pParent, const ScTabView& rScTabView, ScTabViewShell* pViewShell ) : +//UNUSED2009-05 pFrameWin( pParent ), +//UNUSED2009-05 aViewData( rScTabView.aViewData ), +//UNUSED2009-05 TABVIEW_INIT +//UNUSED2009-05 { +//UNUSED2009-05 RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScTabView::ScTabView" ); +//UNUSED2009-05 +//UNUSED2009-05 aViewData.SetViewShell( pViewShell ); +//UNUSED2009-05 Init(); +//UNUSED2009-05 +//UNUSED2009-05 UpdateShow(); +//UNUSED2009-05 if ( aViewData.GetActivePart() != SC_SPLIT_BOTTOMLEFT ) +//UNUSED2009-05 pGridWin[SC_SPLIT_BOTTOMLEFT]->Show(); +//UNUSED2009-05 +//UNUSED2009-05 InvalidateSplit(); +//UNUSED2009-05 } + +void ScTabView::InitScrollBar( ScrollBar& rScrollBar, long nMaxVal ) +{ + rScrollBar.SetRange( Range( 0, nMaxVal ) ); + rScrollBar.SetLineSize( 1 ); + rScrollBar.SetPageSize( 1 ); // wird getrennt abgefragt + rScrollBar.SetVisibleSize( 10 ); // wird bei Resize neu gesetzt + + rScrollBar.SetScrollHdl( LINK(this, ScTabView, ScrollHdl) ); + rScrollBar.SetEndScrollHdl( LINK(this, ScTabView, EndScrollHdl) ); +} + +// Scroll-Timer + +void ScTabView::SetTimer( ScGridWindow* pWin, const MouseEvent& rMEvt ) +{ + pTimerWindow = pWin; + aTimerMEvt = rMEvt; + aScrollTimer.Start(); +} + +void ScTabView::ResetTimer() +{ + aScrollTimer.Stop(); + pTimerWindow = NULL; +} + +IMPL_LINK( ScTabView, TimerHdl, Timer*, EMPTYARG ) +{ +// aScrollTimer.Stop(); + if (pTimerWindow) + pTimerWindow->MouseMove( aTimerMEvt ); + + return 0; +} + +// --- Resize --------------------------------------------------------------------- + +void lcl_SetPosSize( Window& rWindow, const Point& rPos, const Size& rSize, + long nTotalWidth, sal_Bool bLayoutRTL ) +{ + Point aNewPos = rPos; + if ( bLayoutRTL ) + { + aNewPos.X() = nTotalWidth - rPos.X() - rSize.Width(); + if ( aNewPos == rWindow.GetPosPixel() && rSize.Width() != rWindow.GetSizePixel().Width() ) + { + // Document windows are manually painted right-to-left, so they need to + // be repainted if the size changes. + rWindow.Invalidate(); + } + } + rWindow.SetPosSizePixel( aNewPos, rSize ); +} + +void ScTabView::DoResize( const Point& rOffset, const Size& rSize, sal_Bool bInner ) +{ + HideListBox(); + + sal_Bool bHasHint = ( pInputHintWindow != NULL ); + if (bHasHint) + RemoveHintWindow(); + + sal_Bool bLayoutRTL = aViewData.GetDocument()->IsLayoutRTL( aViewData.GetTabNo() ); + long nTotalWidth = rSize.Width(); + if ( bLayoutRTL ) + nTotalWidth += 2*rOffset.X(); + + sal_Bool bVScroll = aViewData.IsVScrollMode(); + sal_Bool bHScroll = aViewData.IsHScrollMode(); + sal_Bool bTabControl = aViewData.IsTabMode(); + sal_Bool bHeaders = aViewData.IsHeaderMode(); + sal_Bool bOutlMode = aViewData.IsOutlineMode(); + sal_Bool bHOutline = bOutlMode && lcl_HasColOutline(aViewData); + sal_Bool bVOutline = bOutlMode && lcl_HasRowOutline(aViewData); + + // Scrollbar-Einstellungen koennen vom Sfx ueberschrieben werden: + SfxScrollingMode eMode = aViewData.GetViewShell()->GetScrollingMode(); + if ( eMode == SCROLLING_NO ) + bHScroll = bVScroll = sal_False; + else if ( eMode == SCROLLING_YES || eMode == SCROLLING_AUTO ) //! Auto ??? + bHScroll = bVScroll = sal_True; + + if ( aViewData.GetDocShell()->IsPreview() ) + bHScroll = bVScroll = bTabControl = bHeaders = bOutlMode = bHOutline = bVOutline = sal_False; + + long nBarX = 0; + long nBarY = 0; + long nOutlineX = 0; + long nOutlineY = 0; + long nOutPosX; + long nOutPosY; + + long nPosX = rOffset.X(); + long nPosY = rOffset.Y(); + long nSizeX = rSize.Width(); + long nSizeY = rSize.Height(); + long nSize1; + + bMinimized = ( nSizeX<=SC_ICONSIZE || nSizeY<=SC_ICONSIZE ); + if ( bMinimized ) + return; + + long nSplitSizeX = SPLIT_HANDLE_SIZE; + if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX ) + nSplitSizeX = 1; + long nSplitSizeY = SPLIT_HANDLE_SIZE; + if ( aViewData.GetVSplitMode() == SC_SPLIT_FIX ) + nSplitSizeY = 1; + + const long nOverlap = 0; // ScrollBar::GetWindowOverlapPixel(); + + aBorderPos = rOffset; + aFrameSize = rSize; + + if ( aViewData.GetHSplitMode() != SC_SPLIT_NONE ) + if ( aViewData.GetHSplitPos() > nSizeX - SPLIT_MARGIN ) + { + aViewData.SetHSplitMode( SC_SPLIT_NONE ); + if ( WhichH( aViewData.GetActivePart() ) == SC_SPLIT_RIGHT ) + ActivatePart( SC_SPLIT_BOTTOMLEFT ); + InvalidateSplit(); +// UpdateShow(); + } + if ( aViewData.GetVSplitMode() != SC_SPLIT_NONE ) + if ( aViewData.GetVSplitPos() > nSizeY - SPLIT_MARGIN ) + { + aViewData.SetVSplitMode( SC_SPLIT_NONE ); + if ( WhichV( aViewData.GetActivePart() ) == SC_SPLIT_TOP ) + ActivatePart( SC_SPLIT_BOTTOMLEFT ); + InvalidateSplit(); +// UpdateShow(); + } + + UpdateShow(); + + if (bHScroll || bVScroll) // Scrollbars horizontal oder vertikal + { + long nScrollBarSize = pFrameWin->GetSettings().GetStyleSettings().GetScrollBarSize(); + if (bVScroll) + { +// nBarX = aVScrollBottom.GetSizePixel().Width(); + nBarX = nScrollBarSize; + nSizeX -= nBarX - nOverlap; + } + if (bHScroll) + { +// nBarY = aHScrollLeft.GetSizePixel().Height(); + nBarY = nScrollBarSize; + nSizeY -= nBarY - nOverlap; + } + + // window at the bottom right + lcl_SetPosSize( aScrollBarBox, Point( nPosX+nSizeX, nPosY+nSizeY ), Size( nBarX, nBarY ), + nTotalWidth, bLayoutRTL ); + + if (bHScroll) // Scrollbars horizontal + { + long nSizeLt = 0; // left scroll bar + long nSizeRt = 0; // right scroll bar + long nSizeSp = 0; // splitter + + switch (aViewData.GetHSplitMode()) + { + case SC_SPLIT_NONE: + nSizeSp = nSplitSizeX; + nSizeLt = nSizeX - nSizeSp + nOverlap; // Ecke ueberdecken + break; + case SC_SPLIT_NORMAL: + nSizeSp = nSplitSizeX; + nSizeLt = aViewData.GetHSplitPos(); + break; + case SC_SPLIT_FIX: + nSizeSp = 0; + nSizeLt = 0; + break; + } + nSizeRt = nSizeX - nSizeLt - nSizeSp; + + long nTabSize = 0; + if (bTabControl) + { + // pending relative tab bar width from extended document options + if( mfPendingTabBarWidth >= 0.0 ) + { + SetRelTabBarWidth( mfPendingTabBarWidth ); + mfPendingTabBarWidth = -1.0; + } + + nTabSize = pTabControl->GetSizePixel().Width()-nOverlap; + + if ( aViewData.GetHSplitMode() != SC_SPLIT_FIX ) // bei linkem Scrollbar + { + if (nTabSize > nSizeLt-SC_SCROLLBAR_MIN) nTabSize = nSizeLt-SC_SCROLLBAR_MIN; + if (nTabSize < SC_TABBAR_MIN) nTabSize = SC_TABBAR_MIN; + nSizeLt -= nTabSize; + } + else // bei rechtem Scrollbar + { + if (nTabSize > nSizeRt-SC_SCROLLBAR_MIN) nTabSize = nSizeRt-SC_SCROLLBAR_MIN; + if (nTabSize < SC_TABBAR_MIN) nTabSize = SC_TABBAR_MIN; + nSizeRt -= nTabSize; + } + } + + lcl_SetPosSize( *pTabControl, Point(nPosX-nOverlap, nPosY+nSizeY), + Size(nTabSize+nOverlap, nBarY), nTotalWidth, bLayoutRTL ); + pTabControl->SetSheetLayoutRTL( bLayoutRTL ); + + lcl_SetPosSize( aHScrollLeft, Point(nPosX+nTabSize-nOverlap, nPosY+nSizeY), + Size(nSizeLt+2*nOverlap, nBarY), nTotalWidth, bLayoutRTL ); + lcl_SetPosSize( *pHSplitter, Point( nPosX+nTabSize+nSizeLt, nPosY+nSizeY ), + Size( nSizeSp, nBarY ), nTotalWidth, bLayoutRTL ); + lcl_SetPosSize( aHScrollRight, Point(nPosX+nTabSize+nSizeLt+nSizeSp-nOverlap, + nPosY+nSizeY), + Size(nSizeRt+2*nOverlap, nBarY), nTotalWidth, bLayoutRTL ); + + // SetDragRectPixel is done below + } + + if (bVScroll) // Scrollbars vertikal + { + long nSizeUp = 0; // upper scroll bar + long nSizeSp = 0; // splitter + long nSizeDn; // unterer Scrollbar + + switch (aViewData.GetVSplitMode()) + { + case SC_SPLIT_NONE: + nSizeUp = 0; + nSizeSp = nSplitSizeY; + break; + case SC_SPLIT_NORMAL: + nSizeUp = aViewData.GetVSplitPos(); + nSizeSp = nSplitSizeY; + break; + case SC_SPLIT_FIX: + nSizeUp = 0; + nSizeSp = 0; + break; + } + nSizeDn = nSizeY - nSizeUp - nSizeSp; + + lcl_SetPosSize( aVScrollTop, Point(nPosX+nSizeX, nPosY-nOverlap), + Size(nBarX,nSizeUp+2*nOverlap), nTotalWidth, bLayoutRTL ); + lcl_SetPosSize( *pVSplitter, Point( nPosX+nSizeX, nPosY+nSizeUp ), + Size( nBarX, nSizeSp ), nTotalWidth, bLayoutRTL ); + lcl_SetPosSize( aVScrollBottom, Point(nPosX+nSizeX, + nPosY+nSizeUp+nSizeSp-nOverlap), + Size(nBarX, nSizeDn+2*nOverlap), nTotalWidth, bLayoutRTL ); + + // SetDragRectPixel is done below + } + } + + // SetDragRectPixel auch ohne Scrollbars etc., wenn schon gesplittet ist + if ( bHScroll || aViewData.GetHSplitMode() != SC_SPLIT_NONE ) + pHSplitter->SetDragRectPixel( + Rectangle( nPosX, nPosY, nPosX+nSizeX, nPosY+nSizeY ), pFrameWin ); + if ( bVScroll || aViewData.GetVSplitMode() != SC_SPLIT_NONE ) + pVSplitter->SetDragRectPixel( + Rectangle( nPosX, nPosY, nPosX+nSizeX, nPosY+nSizeY ), pFrameWin ); + + if (bTabControl && ! bHScroll ) + { + nBarY = aHScrollLeft.GetSizePixel().Height(); + nBarX = aVScrollBottom.GetSizePixel().Width(); + + nSize1 = nSizeX + nOverlap; + + long nTabSize = nSize1; + if (nTabSize < 0) nTabSize = 0; + + lcl_SetPosSize( *pTabControl, Point(nPosX-nOverlap, nPosY+nSizeY-nBarY), + Size(nTabSize+nOverlap, nBarY), nTotalWidth, bLayoutRTL ); + nSizeY -= nBarY - nOverlap; + lcl_SetPosSize( aScrollBarBox, Point( nPosX+nSizeX, nPosY+nSizeY ), Size( nBarX, nBarY ), + nTotalWidth, bLayoutRTL ); + + if( bVScroll ) + { + Size aVScrSize = aVScrollBottom.GetSizePixel(); + aVScrSize.Height() -= nBarY; + aVScrollBottom.SetSizePixel( aVScrSize ); + } + } + + nOutPosX = nPosX; + nOutPosY = nPosY; + + // Outline-Controls + if (bVOutline && pRowOutline[SC_SPLIT_BOTTOM]) + { + nOutlineX = pRowOutline[SC_SPLIT_BOTTOM]->GetDepthSize(); + nSizeX -= nOutlineX; + nPosX += nOutlineX; + } + if (bHOutline && pColOutline[SC_SPLIT_LEFT]) + { + nOutlineY = pColOutline[SC_SPLIT_LEFT]->GetDepthSize(); + nSizeY -= nOutlineY; + nPosY += nOutlineY; + } + + if (bHeaders) // Spalten/Zeilen-Header + { + nBarX = pRowBar[SC_SPLIT_BOTTOM]->GetSizePixel().Width(); + nBarY = pColBar[SC_SPLIT_LEFT]->GetSizePixel().Height(); + nSizeX -= nBarX; + nSizeY -= nBarY; + nPosX += nBarX; + nPosY += nBarY; + } + else + nBarX = nBarY = 0; + + // + // Splitter auswerten + // + + long nLeftSize = nSizeX; + long nRightSize = 0; + long nTopSize = 0; + long nBottomSize = nSizeY; + long nSplitPosX = nPosX; + long nSplitPosY = nPosY; + + if ( aViewData.GetHSplitMode() != SC_SPLIT_NONE ) + { + long nSplitHeight = rSize.Height(); + if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX ) + { + // Fixier-Splitter nicht mit Scrollbar/TabBar ueberlappen lassen + if ( bHScroll ) + nSplitHeight -= aHScrollLeft.GetSizePixel().Height(); + else if ( bTabControl && pTabControl ) + nSplitHeight -= pTabControl->GetSizePixel().Height(); + } + nSplitPosX = aViewData.GetHSplitPos(); + lcl_SetPosSize( *pHSplitter, + Point( nSplitPosX, nOutPosY ), Size( nSplitSizeX, nSplitHeight ), nTotalWidth, bLayoutRTL ); + nLeftSize = nSplitPosX - nPosX; + nSplitPosX += nSplitSizeX; + nRightSize = nSizeX - nLeftSize - nSplitSizeX; + } + if ( aViewData.GetVSplitMode() != SC_SPLIT_NONE ) + { + long nSplitWidth = rSize.Width(); + if ( aViewData.GetVSplitMode() == SC_SPLIT_FIX && bVScroll ) + nSplitWidth -= aVScrollBottom.GetSizePixel().Width(); + nSplitPosY = aViewData.GetVSplitPos(); + lcl_SetPosSize( *pVSplitter, + Point( nOutPosX, nSplitPosY ), Size( nSplitWidth, nSplitSizeY ), nTotalWidth, bLayoutRTL ); + nTopSize = nSplitPosY - nPosY; + nSplitPosY += nSplitSizeY; + nBottomSize = nSizeY - nTopSize - nSplitSizeY; + } + + // ShowHide fuer pColOutline / pRowOutline passiert in UpdateShow + + if (bHOutline) // Outline-Controls + { + if (pColOutline[SC_SPLIT_LEFT]) + { + pColOutline[SC_SPLIT_LEFT]->SetHeaderSize( nBarX ); + lcl_SetPosSize( *pColOutline[SC_SPLIT_LEFT], + Point(nPosX-nBarX,nOutPosY), Size(nLeftSize+nBarX,nOutlineY), nTotalWidth, bLayoutRTL ); + } + if (pColOutline[SC_SPLIT_RIGHT]) + { + pColOutline[SC_SPLIT_RIGHT]->SetHeaderSize( 0 ); // always call to update RTL flag + lcl_SetPosSize( *pColOutline[SC_SPLIT_RIGHT], + Point(nSplitPosX,nOutPosY), Size(nRightSize,nOutlineY), nTotalWidth, bLayoutRTL ); + } + } + if (bVOutline) + { + if (nTopSize) + { + if (pRowOutline[SC_SPLIT_TOP] && pRowOutline[SC_SPLIT_BOTTOM]) + { + pRowOutline[SC_SPLIT_TOP]->SetHeaderSize( nBarY ); + lcl_SetPosSize( *pRowOutline[SC_SPLIT_TOP], + Point(nOutPosX,nPosY-nBarY), Size(nOutlineX,nTopSize+nBarY), nTotalWidth, bLayoutRTL ); + pRowOutline[SC_SPLIT_BOTTOM]->SetHeaderSize( 0 ); + lcl_SetPosSize( *pRowOutline[SC_SPLIT_BOTTOM], + Point(nOutPosX,nSplitPosY), Size(nOutlineX,nBottomSize), nTotalWidth, bLayoutRTL ); + } + } + else if (pRowOutline[SC_SPLIT_BOTTOM]) + { + pRowOutline[SC_SPLIT_BOTTOM]->SetHeaderSize( nBarY ); + lcl_SetPosSize( *pRowOutline[SC_SPLIT_BOTTOM], + Point(nOutPosX,nSplitPosY-nBarY), Size(nOutlineX,nBottomSize+nBarY), nTotalWidth, bLayoutRTL ); + } + } + if (bHOutline && bVOutline) + { + lcl_SetPosSize( aTopButton, Point(nOutPosX,nOutPosY), Size(nOutlineX,nOutlineY), nTotalWidth, bLayoutRTL ); + aTopButton.Show(); + } + else + aTopButton.Hide(); + + if (bHeaders) // Spalten/Zeilen-Header + { + lcl_SetPosSize( *pColBar[SC_SPLIT_LEFT], + Point(nPosX,nPosY-nBarY), Size(nLeftSize,nBarY), nTotalWidth, bLayoutRTL ); + if (pColBar[SC_SPLIT_RIGHT]) + lcl_SetPosSize( *pColBar[SC_SPLIT_RIGHT], + Point(nSplitPosX,nPosY-nBarY), Size(nRightSize,nBarY), nTotalWidth, bLayoutRTL ); + + if (pRowBar[SC_SPLIT_TOP]) + lcl_SetPosSize( *pRowBar[SC_SPLIT_TOP], + Point(nPosX-nBarX,nPosY), Size(nBarX,nTopSize), nTotalWidth, bLayoutRTL ); + lcl_SetPosSize( *pRowBar[SC_SPLIT_BOTTOM], + Point(nPosX-nBarX,nSplitPosY), Size(nBarX,nBottomSize), nTotalWidth, bLayoutRTL ); + + lcl_SetPosSize( aCornerButton, Point(nPosX-nBarX,nPosY-nBarY), Size(nBarX,nBarY), nTotalWidth, bLayoutRTL ); + aCornerButton.Show(); + pColBar[SC_SPLIT_LEFT]->Show(); + pRowBar[SC_SPLIT_BOTTOM]->Show(); + } + else + { + aCornerButton.Hide(); + pColBar[SC_SPLIT_LEFT]->Hide(); // immer da + pRowBar[SC_SPLIT_BOTTOM]->Hide(); + } + + + // Grid-Windows + + if (bInner) + { + long nInnerPosX = bLayoutRTL ? ( nTotalWidth - nPosX - nLeftSize ) : nPosX; + pGridWin[SC_SPLIT_BOTTOMLEFT]->SetPosPixel( Point(nInnerPosX,nSplitPosY) ); + } + else + { + lcl_SetPosSize( *pGridWin[SC_SPLIT_BOTTOMLEFT], + Point(nPosX,nSplitPosY), Size(nLeftSize,nBottomSize), nTotalWidth, bLayoutRTL ); + if ( aViewData.GetHSplitMode() != SC_SPLIT_NONE ) + lcl_SetPosSize( *pGridWin[SC_SPLIT_BOTTOMRIGHT], + Point(nSplitPosX,nSplitPosY), Size(nRightSize,nBottomSize), nTotalWidth, bLayoutRTL ); + if ( aViewData.GetVSplitMode() != SC_SPLIT_NONE ) + lcl_SetPosSize( *pGridWin[SC_SPLIT_TOPLEFT], + Point(nPosX,nPosY), Size(nLeftSize,nTopSize), nTotalWidth, bLayoutRTL ); + if ( aViewData.GetHSplitMode() != SC_SPLIT_NONE && aViewData.GetVSplitMode() != SC_SPLIT_NONE ) + lcl_SetPosSize( *pGridWin[SC_SPLIT_TOPRIGHT], + Point(nSplitPosX,nPosY), Size(nRightSize,nTopSize), nTotalWidth, bLayoutRTL ); + } + + // + // Scrollbars updaten + // + + if (!bInUpdateHeader) + { + UpdateScrollBars(); // Scrollbars nicht beim Scrollen neu setzen + UpdateHeaderWidth(); + + InterpretVisible(); // #69343# have everything calculated before painting + } + + if (bHasHint) + TestHintWindow(); // neu positionieren + + UpdateVarZoom(); // update variable zoom types (after resizing GridWindows) + + if (aViewData.GetViewShell()->HasAccessibilityObjects()) + aViewData.GetViewShell()->BroadcastAccessibility(SfxSimpleHint(SC_HINT_ACC_WINDOWRESIZED)); +} + +void ScTabView::UpdateVarZoom() +{ + // update variable zoom types + + SvxZoomType eZoomType = GetZoomType(); + if ( eZoomType != SVX_ZOOM_PERCENT && !bInZoomUpdate ) + { + bInZoomUpdate = sal_True; + const Fraction& rOldX = GetViewData()->GetZoomX(); + const Fraction& rOldY = GetViewData()->GetZoomY(); + long nOldPercent = ( rOldY.GetNumerator() * 100 ) / rOldY.GetDenominator(); + sal_uInt16 nNewZoom = CalcZoom( eZoomType, (sal_uInt16)nOldPercent ); + Fraction aNew( nNewZoom, 100 ); + + if ( aNew != rOldX || aNew != rOldY ) + { + SetZoom( aNew, aNew, sal_False ); // always separately per sheet + PaintGrid(); + PaintTop(); + PaintLeft(); + aViewData.GetViewShell()->GetViewFrame()->GetBindings().Invalidate( SID_ATTR_ZOOM ); + aViewData.GetViewShell()->GetViewFrame()->GetBindings().Invalidate( SID_ATTR_ZOOMSLIDER ); + } + bInZoomUpdate = sal_False; + } +} + +void ScTabView::UpdateFixPos() +{ + sal_Bool bResize = sal_False; + if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX ) + if (aViewData.UpdateFixX()) + bResize = sal_True; + if ( aViewData.GetVSplitMode() == SC_SPLIT_FIX ) + if (aViewData.UpdateFixY()) + bResize = sal_True; + if (bResize) + RepeatResize(sal_False); +} + +void ScTabView::RepeatResize( sal_Bool bUpdateFix ) +{ + if ( bUpdateFix ) + { + ScSplitMode eHSplit = aViewData.GetHSplitMode(); + ScSplitMode eVSplit = aViewData.GetVSplitMode(); + + // #i46796# UpdateFixX / UpdateFixY uses GetGridOffset, which requires the + // outline windows to be available. So UpdateShow has to be called before + // (also called from DoResize). + if ( eHSplit == SC_SPLIT_FIX || eVSplit == SC_SPLIT_FIX ) + UpdateShow(); + + if ( eHSplit == SC_SPLIT_FIX ) + aViewData.UpdateFixX(); + if ( eVSplit == SC_SPLIT_FIX ) + aViewData.UpdateFixY(); + } + + DoResize( aBorderPos, aFrameSize ); + + //! Border muss neu gesetzt werden ??? +} + +void ScTabView::GetBorderSize( SvBorder& rBorder, const Size& /* rSize */ ) +{ + sal_Bool bScrollBars = aViewData.IsVScrollMode(); + sal_Bool bHeaders = aViewData.IsHeaderMode(); + sal_Bool bOutlMode = aViewData.IsOutlineMode(); + sal_Bool bHOutline = bOutlMode && lcl_HasColOutline(aViewData); + sal_Bool bVOutline = bOutlMode && lcl_HasRowOutline(aViewData); + sal_Bool bLayoutRTL = aViewData.GetDocument()->IsLayoutRTL( aViewData.GetTabNo() ); + + rBorder = SvBorder(); + + if (bScrollBars) // Scrollbars horizontal oder vertikal + { + rBorder.Right() += aVScrollBottom.GetSizePixel().Width(); + rBorder.Bottom() += aHScrollLeft.GetSizePixel().Height(); + } + + // Outline-Controls + if (bVOutline && pRowOutline[SC_SPLIT_BOTTOM]) + rBorder.Left() += pRowOutline[SC_SPLIT_BOTTOM]->GetDepthSize(); + if (bHOutline && pColOutline[SC_SPLIT_LEFT]) + rBorder.Top() += pColOutline[SC_SPLIT_LEFT]->GetDepthSize(); + + if (bHeaders) // Spalten/Zeilen-Header + { + rBorder.Left() += pRowBar[SC_SPLIT_BOTTOM]->GetSizePixel().Width(); + rBorder.Top() += pColBar[SC_SPLIT_LEFT]->GetSizePixel().Height(); + } + + if ( bLayoutRTL ) + ::std::swap( rBorder.Left(), rBorder.Right() ); +} + +IMPL_LINK( ScTabView, TabBarResize, void*, EMPTYARG ) +{ + sal_Bool bHScrollMode = aViewData.IsHScrollMode(); + + // Scrollbar-Einstellungen koennen vom Sfx ueberschrieben werden: + SfxScrollingMode eMode = aViewData.GetViewShell()->GetScrollingMode(); + if ( eMode == SCROLLING_NO ) + bHScrollMode = sal_False; + else if ( eMode == SCROLLING_YES || eMode == SCROLLING_AUTO ) //! Auto ??? + bHScrollMode = sal_True; + + if( bHScrollMode ) + { + const long nOverlap = 0; // ScrollBar::GetWindowOverlapPixel(); + long nSize = pTabControl->GetSplitSize(); + + if (aViewData.GetHSplitMode() != SC_SPLIT_FIX) + { + long nMax = pHSplitter->GetPosPixel().X(); + if( pTabControl->IsEffectiveRTL() ) + nMax = pFrameWin->GetSizePixel().Width() - nMax; + --nMax; + if (nSize>nMax) nSize = nMax; + } + + if ( nSize != pTabControl->GetSizePixel().Width() ) + { + pTabControl->SetSizePixel( Size( nSize+nOverlap, + pTabControl->GetSizePixel().Height() ) ); + RepeatResize(); + } + } + + return 0; +} + +void ScTabView::SetTabBarWidth( long nNewWidth ) +{ + Size aSize = pTabControl->GetSizePixel(); + + if ( aSize.Width() != nNewWidth ) + { + aSize.Width() = nNewWidth; + pTabControl->SetSizePixel( aSize ); + } +} + +void ScTabView::SetRelTabBarWidth( double fRelTabBarWidth ) +{ + if( (0.0 <= fRelTabBarWidth) && (fRelTabBarWidth <= 1.0) ) + if( long nFrameWidth = pFrameWin->GetSizePixel().Width() ) + SetTabBarWidth( static_cast< long >( fRelTabBarWidth * nFrameWidth + 0.5 ) ); +} + +void ScTabView::SetPendingRelTabBarWidth( double fRelTabBarWidth ) +{ + mfPendingTabBarWidth = fRelTabBarWidth; + SetRelTabBarWidth( fRelTabBarWidth ); +} + +long ScTabView::GetTabBarWidth() const +{ + return pTabControl->GetSizePixel().Width(); +} + +double ScTabView::GetRelTabBarWidth() const +{ + if( long nFrameWidth = pFrameWin->GetSizePixel().Width() ) + return static_cast< double >( GetTabBarWidth() ) / nFrameWidth; + return 0.0; +} + +double ScTabView::GetPendingRelTabBarWidth() const +{ + return mfPendingTabBarWidth; +} + +Window* ScTabView::GetActiveWin() +{ + ScSplitPos ePos = aViewData.GetActivePart(); + DBG_ASSERT(pGridWin[ePos],"kein aktives Fenster"); + return pGridWin[ePos]; +} + +Window* ScTabView::GetWindowByPos( ScSplitPos ePos ) +{ + return pGridWin[ePos]; +} + +void ScTabView::SetActivePointer( const Pointer& rPointer ) +{ + for (sal_uInt16 i=0; i<4; i++) + if (pGridWin[i]) + pGridWin[i]->SetPointer( rPointer ); + +/* ScSplitPos ePos = aViewData.GetActivePart(); + if (pGridWin[ePos]) + pGridWin[ePos]->SetPointer( rPointer ); +*/ +} + +//UNUSED2008-05 void ScTabView::SetActivePointer( const ResId& ) +//UNUSED2008-05 { +//UNUSED2008-05 DBG_ERRORFILE( "keine Pointer mit ResId!" ); +//UNUSED2008-05 } + +void ScTabView::ActiveGrabFocus() +{ + ScSplitPos ePos = aViewData.GetActivePart(); + if (pGridWin[ePos]) + pGridWin[ePos]->GrabFocus(); +} + +//UNUSED2008-05 void ScTabView::ActiveCaptureMouse() +//UNUSED2008-05 { +//UNUSED2008-05 ScSplitPos ePos = aViewData.GetActivePart(); +//UNUSED2008-05 if (pGridWin[ePos]) +//UNUSED2008-05 pGridWin[ePos]->CaptureMouse(); +//UNUSED2008-05 } +//UNUSED2008-05 +//UNUSED2008-05 void ScTabView::ActiveReleaseMouse() +//UNUSED2008-05 { +//UNUSED2008-05 ScSplitPos ePos = aViewData.GetActivePart(); +//UNUSED2008-05 if (pGridWin[ePos]) +//UNUSED2008-05 pGridWin[ePos]->ReleaseMouse(); +//UNUSED2008-05 } +//UNUSED2008-05 +//UNUSED2008-05 Point ScTabView::ActivePixelToLogic( const Point& rDevicePoint ) +//UNUSED2008-05 { +//UNUSED2008-05 ScSplitPos ePos = aViewData.GetActivePart(); +//UNUSED2008-05 if (pGridWin[ePos]) +//UNUSED2008-05 return pGridWin[ePos]->PixelToLogic(rDevicePoint); +//UNUSED2008-05 else +//UNUSED2008-05 return Point(); +//UNUSED2008-05 } + +ScSplitPos ScTabView::FindWindow( Window* pWindow ) const +{ + ScSplitPos eVal = SC_SPLIT_BOTTOMLEFT; // Default + for (sal_uInt16 i=0; i<4; i++) + if ( pGridWin[i] == pWindow ) + eVal = (ScSplitPos) i; + + return eVal; +} + +Point ScTabView::GetGridOffset() const +{ + Point aPos; + + // Groessen hier wie in DoResize + + sal_Bool bHeaders = aViewData.IsHeaderMode(); + sal_Bool bOutlMode = aViewData.IsOutlineMode(); + sal_Bool bHOutline = bOutlMode && lcl_HasColOutline(aViewData); + sal_Bool bVOutline = bOutlMode && lcl_HasRowOutline(aViewData); + + // Outline-Controls + if (bVOutline && pRowOutline[SC_SPLIT_BOTTOM]) + aPos.X() += pRowOutline[SC_SPLIT_BOTTOM]->GetDepthSize(); + if (bHOutline && pColOutline[SC_SPLIT_LEFT]) + aPos.Y() += pColOutline[SC_SPLIT_LEFT]->GetDepthSize(); + + if (bHeaders) // Spalten/Zeilen-Header + { + if (pRowBar[SC_SPLIT_BOTTOM]) + aPos.X() += pRowBar[SC_SPLIT_BOTTOM]->GetSizePixel().Width(); + if (pColBar[SC_SPLIT_LEFT]) + aPos.Y() += pColBar[SC_SPLIT_LEFT]->GetSizePixel().Height(); + } + + return aPos; +} + +// --- Scroll-Bars -------------------------------------------------------- + +sal_Bool ScTabView::ScrollCommand( const CommandEvent& rCEvt, ScSplitPos ePos ) +{ + HideNoteMarker(); + + sal_Bool bDone = sal_False; + const CommandWheelData* pData = rCEvt.GetWheelData(); + if ( pData && pData->GetMode() == COMMAND_WHEEL_ZOOM ) + { + if ( !aViewData.GetViewShell()->GetViewFrame()->GetFrame().IsInPlace() ) + { + // for ole inplace editing, the scale is defined by the visarea and client size + // and can't be changed directly + + const Fraction& rOldY = aViewData.GetZoomY(); + long nOld = (long)(( rOldY.GetNumerator() * 100 ) / rOldY.GetDenominator()); + long nNew = nOld; + if ( pData->GetDelta() < 0 ) + nNew = Max( (long) MINZOOM, (long)( nOld - SC_DELTA_ZOOM ) ); + else + nNew = Min( (long) MAXZOOM, (long)( nOld + SC_DELTA_ZOOM ) ); + + if ( nNew != nOld ) + { + // scroll wheel doesn't set the AppOptions default + + sal_Bool bSyncZoom = SC_MOD()->GetAppOptions().GetSynchronizeZoom(); + SetZoomType( SVX_ZOOM_PERCENT, bSyncZoom ); + Fraction aFract( nNew, 100 ); + SetZoom( aFract, aFract, bSyncZoom ); + PaintGrid(); + PaintTop(); + PaintLeft(); + aViewData.GetBindings().Invalidate( SID_ATTR_ZOOM ); + aViewData.GetBindings().Invalidate( SID_ATTR_ZOOMSLIDER ); + } + + bDone = sal_True; + } + } + else + { + ScHSplitPos eHPos = WhichH(ePos); + ScVSplitPos eVPos = WhichV(ePos); + ScrollBar* pHScroll = ( eHPos == SC_SPLIT_LEFT ) ? &aHScrollLeft : &aHScrollRight; + ScrollBar* pVScroll = ( eVPos == SC_SPLIT_TOP ) ? &aVScrollTop : &aVScrollBottom; + if ( pGridWin[ePos] ) + bDone = pGridWin[ePos]->HandleScrollCommand( rCEvt, pHScroll, pVScroll ); + } + return bDone; +} + +IMPL_LINK( ScTabView, EndScrollHdl, ScrollBar*, pScroll ) +{ + sal_Bool bOnlineScroll = sal_True; //! Optionen + + if ( bDragging ) + { + if ( bOnlineScroll ) // nur Ranges aktualisieren + UpdateScrollBars(); + else + { + long nScrollMin = 0; // RangeMin simulieren + if ( aViewData.GetHSplitMode()==SC_SPLIT_FIX && pScroll == &aHScrollRight ) + nScrollMin = aViewData.GetFixPosX(); + if ( aViewData.GetVSplitMode()==SC_SPLIT_FIX && pScroll == &aVScrollBottom ) + nScrollMin = aViewData.GetFixPosY(); + + if ( pScroll == &aHScrollLeft || pScroll == &aHScrollRight ) + { + sal_Bool bMirror = aViewData.GetDocument()->IsLayoutRTL( aViewData.GetTabNo() ) != Application::GetSettings().GetLayoutRTL(); + ScHSplitPos eWhich = (pScroll == &aHScrollLeft) ? SC_SPLIT_LEFT : SC_SPLIT_RIGHT; + long nDelta = GetScrollBarPos( *pScroll, bMirror ) + nScrollMin - aViewData.GetPosX(eWhich); + if (nDelta) ScrollX( nDelta, eWhich ); + } + else // VScroll... + { + ScVSplitPos eWhich = (pScroll == &aVScrollTop) ? SC_SPLIT_TOP : SC_SPLIT_BOTTOM; + long nDelta = GetScrollBarPos( *pScroll, sal_False ) + nScrollMin - aViewData.GetPosY(eWhich); + if (nDelta) ScrollY( nDelta, eWhich ); + } + } + bDragging = sal_False; + } + return 0; +} + +IMPL_LINK( ScTabView, ScrollHdl, ScrollBar*, pScroll ) +{ + sal_Bool bOnlineScroll = sal_True; //! Optionen + + sal_Bool bHoriz = ( pScroll == &aHScrollLeft || pScroll == &aHScrollRight ); + long nViewPos; + if ( bHoriz ) + nViewPos = aViewData.GetPosX( (pScroll == &aHScrollLeft) ? + SC_SPLIT_LEFT : SC_SPLIT_RIGHT ); + else + nViewPos = aViewData.GetPosY( (pScroll == &aVScrollTop) ? + SC_SPLIT_TOP : SC_SPLIT_BOTTOM ); + + sal_Bool bLayoutRTL = aViewData.GetDocument()->IsLayoutRTL( aViewData.GetTabNo() ); + sal_Bool bMirror = bHoriz && (bLayoutRTL != Application::GetSettings().GetLayoutRTL()); + + ScrollType eType = pScroll->GetType(); + if ( eType == SCROLL_DRAG ) + { + if (!bDragging) + { + bDragging = sal_True; + nPrevDragPos = nViewPos; + } + + // Scroll-Position anzeigen + // (nur QuickHelp, in der Statuszeile gibt es keinen Eintrag dafuer) + + if (Help::IsQuickHelpEnabled()) + { + Size aSize = pScroll->GetSizePixel(); + + /* Convert scrollbar mouse position to screen position. If RTL + mode of scrollbar differs from RTL mode of its parent, then the + direct call to Window::OutputToNormalizedScreenPixel() will + give unusable results, because calcualtion of screen position + is based on parent orientation and expects equal orientation of + the child position. Need to mirror mouse position before. */ + Point aMousePos = pScroll->GetPointerPosPixel(); + if( pScroll->IsRTLEnabled() != pScroll->GetParent()->IsRTLEnabled() ) + aMousePos.X() = aSize.Width() - aMousePos.X() - 1; + aMousePos = pScroll->OutputToNormalizedScreenPixel( aMousePos ); + + // convert top-left position of scrollbar to screen position + Point aPos = pScroll->OutputToNormalizedScreenPixel( Point() ); + + // get scrollbar scroll position for help text (row number/column name) + long nScrollMin = 0; // RangeMin simulieren + if ( aViewData.GetHSplitMode()==SC_SPLIT_FIX && pScroll == &aHScrollRight ) + nScrollMin = aViewData.GetFixPosX(); + if ( aViewData.GetVSplitMode()==SC_SPLIT_FIX && pScroll == &aVScrollBottom ) + nScrollMin = aViewData.GetFixPosY(); + long nScrollPos = GetScrollBarPos( *pScroll, bMirror ) + nScrollMin; + + String aHelpStr; + Rectangle aRect; + sal_uInt16 nAlign; + if (bHoriz) + { + aHelpStr = ScGlobal::GetRscString(STR_COLUMN); + aHelpStr += ' '; + aHelpStr += ScColToAlpha((SCCOL) nScrollPos); + + aRect.Left() = aMousePos.X(); + aRect.Top() = aPos.Y() - 4; + nAlign = QUICKHELP_BOTTOM|QUICKHELP_CENTER; + } + else + { + aHelpStr = ScGlobal::GetRscString(STR_ROW); + aHelpStr += ' '; + aHelpStr += String::CreateFromInt32(nScrollPos + 1); + + // show quicktext always inside sheet area + aRect.Left() = bLayoutRTL ? (aPos.X() + aSize.Width() + 8) : (aPos.X() - 8); + aRect.Top() = aMousePos.Y(); + nAlign = (bLayoutRTL ? QUICKHELP_LEFT : QUICKHELP_RIGHT) | QUICKHELP_VCENTER; + } + aRect.Right() = aRect.Left(); + aRect.Bottom() = aRect.Top(); + + Help::ShowQuickHelp(pScroll->GetParent(), aRect, aHelpStr, nAlign); + } + } + + if ( bOnlineScroll || eType != SCROLL_DRAG ) + { + if ( bMirror ) + { + // change scroll type so visible/previous cells calculation below remains the same + switch ( eType ) + { + case SCROLL_LINEUP: eType = SCROLL_LINEDOWN; break; + case SCROLL_LINEDOWN: eType = SCROLL_LINEUP; break; + case SCROLL_PAGEUP: eType = SCROLL_PAGEDOWN; break; + case SCROLL_PAGEDOWN: eType = SCROLL_PAGEUP; break; + default: + { + // added to avoid warnings + } + } + } + long nDelta = pScroll->GetDelta(); + switch ( eType ) + { + case SCROLL_LINEUP: + nDelta = -1; + break; + case SCROLL_LINEDOWN: + nDelta = 1; + break; + case SCROLL_PAGEUP: + if ( pScroll == &aHScrollLeft ) nDelta = -(long) aViewData.PrevCellsX( SC_SPLIT_LEFT ); + if ( pScroll == &aHScrollRight ) nDelta = -(long) aViewData.PrevCellsX( SC_SPLIT_RIGHT ); + if ( pScroll == &aVScrollTop ) nDelta = -(long) aViewData.PrevCellsY( SC_SPLIT_TOP ); + if ( pScroll == &aVScrollBottom ) nDelta = -(long) aViewData.PrevCellsY( SC_SPLIT_BOTTOM ); + if (nDelta==0) nDelta=-1; + break; + case SCROLL_PAGEDOWN: + if ( pScroll == &aHScrollLeft ) nDelta = aViewData.VisibleCellsX( SC_SPLIT_LEFT ); + if ( pScroll == &aHScrollRight ) nDelta = aViewData.VisibleCellsX( SC_SPLIT_RIGHT ); + if ( pScroll == &aVScrollTop ) nDelta = aViewData.VisibleCellsY( SC_SPLIT_TOP ); + if ( pScroll == &aVScrollBottom ) nDelta = aViewData.VisibleCellsY( SC_SPLIT_BOTTOM ); + if (nDelta==0) nDelta=1; + break; + case SCROLL_DRAG: + { + // nur in die richtige Richtung scrollen, nicht um ausgeblendete + // Bereiche herumzittern + + long nScrollMin = 0; // RangeMin simulieren + if ( aViewData.GetHSplitMode()==SC_SPLIT_FIX && pScroll == &aHScrollRight ) + nScrollMin = aViewData.GetFixPosX(); + if ( aViewData.GetVSplitMode()==SC_SPLIT_FIX && pScroll == &aVScrollBottom ) + nScrollMin = aViewData.GetFixPosY(); + + long nScrollPos = GetScrollBarPos( *pScroll, bMirror ) + nScrollMin; + nDelta = nScrollPos - nViewPos; + if ( nScrollPos > nPrevDragPos ) + { + if (nDelta<0) nDelta=0; + } + else if ( nScrollPos < nPrevDragPos ) + { + if (nDelta>0) nDelta=0; + } + else + nDelta = 0; + nPrevDragPos = nScrollPos; + } + break; + default: + { + // added to avoid warnings + } + } + + if (nDelta) + { + sal_Bool bUpdate = ( eType != SCROLL_DRAG ); // bei Drag die Ranges nicht aendern + if ( bHoriz ) + ScrollX( nDelta, (pScroll == &aHScrollLeft) ? SC_SPLIT_LEFT : SC_SPLIT_RIGHT, bUpdate ); + else + ScrollY( nDelta, (pScroll == &aVScrollTop) ? SC_SPLIT_TOP : SC_SPLIT_BOTTOM, bUpdate ); + } + } + + return 0; +} + +void ScTabView::ScrollX( long nDeltaX, ScHSplitPos eWhich, sal_Bool bUpdBars ) +{ + sal_Bool bHasHint = ( pInputHintWindow != NULL ); + if (bHasHint) + RemoveHintWindow(); + + SCCOL nOldX = aViewData.GetPosX(eWhich); + SCsCOL nNewX = static_cast<SCsCOL>(nOldX) + static_cast<SCsCOL>(nDeltaX); + if ( nNewX < 0 ) + { + nDeltaX -= nNewX; + nNewX = 0; + } + if ( nNewX > MAXCOL ) + { + nDeltaX -= nNewX - MAXCOL; + nNewX = MAXCOL; + } + + SCsCOL nDir = ( nDeltaX > 0 ) ? 1 : -1; + ScDocument* pDoc = aViewData.GetDocument(); + SCTAB nTab = aViewData.GetTabNo(); + while ( pDoc->ColHidden(nNewX, nTab) && + nNewX+nDir >= 0 && nNewX+nDir <= MAXCOL ) + nNewX = sal::static_int_cast<SCsCOL>( nNewX + nDir ); + + // Fixierung + + if (aViewData.GetHSplitMode() == SC_SPLIT_FIX) + { + if (eWhich == SC_SPLIT_LEFT) + nNewX = static_cast<SCsCOL>(nOldX); // links immer stehenlassen + else + { + SCsCOL nFixX = static_cast<SCsCOL>(aViewData.GetFixPosX()); + if (nNewX < nFixX) + nNewX = nFixX; + } + } + if (nNewX == static_cast<SCsCOL>(nOldX)) + return; + + HideAllCursors(); + + if ( nNewX >= 0 && nNewX <= MAXCOL && nDeltaX ) + { + SCCOL nTrackX = std::max( nOldX, static_cast<SCCOL>(nNewX) ); + + // Mit VCL wirkt Update() im Moment immer auf alle Fenster, beim Update + // nach dem Scrollen des GridWindow's wuerde darum der Col-/RowBar evtl. + // mit schon geaenderter Pos. gepainted werden - + // darum vorher einmal Update am Col-/RowBar + + if (pColBar[eWhich]) + pColBar[eWhich]->Update(); + + long nOldPos = aViewData.GetScrPos( nTrackX, 0, eWhich ).X(); + aViewData.SetPosX( eWhich, static_cast<SCCOL>(nNewX) ); + long nDiff = aViewData.GetScrPos( nTrackX, 0, eWhich ).X() - nOldPos; + + if ( eWhich==SC_SPLIT_LEFT ) + { + pGridWin[SC_SPLIT_BOTTOMLEFT]->ScrollPixel( nDiff, 0 ); + if ( aViewData.GetVSplitMode() != SC_SPLIT_NONE ) + pGridWin[SC_SPLIT_TOPLEFT]->ScrollPixel( nDiff, 0 ); + } + else + { + pGridWin[SC_SPLIT_BOTTOMRIGHT]->ScrollPixel( nDiff, 0 ); + if ( aViewData.GetVSplitMode() != SC_SPLIT_NONE ) + pGridWin[SC_SPLIT_TOPRIGHT]->ScrollPixel( nDiff, 0 ); + } + if (pColBar[eWhich]) { pColBar[eWhich]->Scroll( nDiff,0 ); pColBar[eWhich]->Update(); } + if (pColOutline[eWhich]) pColOutline[eWhich]->ScrollPixel( nDiff ); + if (bUpdBars) + UpdateScrollBars(); + } + + if (nDeltaX==1 || nDeltaX==-1) + pGridWin[aViewData.GetActivePart()]->Update(); + + ShowAllCursors(); + + SetNewVisArea(); // MapMode muss schon gesetzt sein + + if (bHasHint) + TestHintWindow(); // neu positionieren +} + +void ScTabView::ScrollY( long nDeltaY, ScVSplitPos eWhich, sal_Bool bUpdBars ) +{ + sal_Bool bHasHint = ( pInputHintWindow != NULL ); + if (bHasHint) + RemoveHintWindow(); + + SCROW nOldY = aViewData.GetPosY(eWhich); + SCsROW nNewY = static_cast<SCsROW>(nOldY) + static_cast<SCsROW>(nDeltaY); + if ( nNewY < 0 ) + { + nDeltaY -= nNewY; + nNewY = 0; + } + if ( nNewY > MAXROW ) + { + nDeltaY -= nNewY - MAXROW; + nNewY = MAXROW; + } + + SCsROW nDir = ( nDeltaY > 0 ) ? 1 : -1; + ScDocument* pDoc = aViewData.GetDocument(); + SCTAB nTab = aViewData.GetTabNo(); + while ( pDoc->RowHidden(nNewY, nTab) && + nNewY+nDir >= 0 && nNewY+nDir <= MAXROW ) + nNewY += nDir; + + // Fixierung + + if (aViewData.GetVSplitMode() == SC_SPLIT_FIX) + { + if (eWhich == SC_SPLIT_TOP) + nNewY = static_cast<SCsROW>(nOldY); // oben immer stehenlassen + else + { + SCsROW nFixY = static_cast<SCsROW>(aViewData.GetFixPosY()); + if (nNewY < nFixY) + nNewY = nFixY; + } + } + if (nNewY == static_cast<SCsROW>(nOldY)) + return; + + HideAllCursors(); + + if ( nNewY >= 0 && nNewY <= MAXROW && nDeltaY ) + { + SCROW nTrackY = std::max( nOldY, static_cast<SCROW>(nNewY) ); + + // Zeilenkoepfe anpassen vor dem eigentlichen Scrolling, damit nicht + // doppelt gepainted werden muss + // PosY darf dann auch noch nicht umgesetzt sein, neuen Wert uebergeben + SCROW nUNew = static_cast<SCROW>(nNewY); + UpdateHeaderWidth( &eWhich, &nUNew ); // Zeilenkoepfe anpassen + + if (pRowBar[eWhich]) + pRowBar[eWhich]->Update(); + + long nOldPos = aViewData.GetScrPos( 0, nTrackY, eWhich ).Y(); + aViewData.SetPosY( eWhich, static_cast<SCROW>(nNewY) ); + long nDiff = aViewData.GetScrPos( 0, nTrackY, eWhich ).Y() - nOldPos; + + if ( eWhich==SC_SPLIT_TOP ) + { + pGridWin[SC_SPLIT_TOPLEFT]->ScrollPixel( 0, nDiff ); + if ( aViewData.GetHSplitMode() != SC_SPLIT_NONE ) + pGridWin[SC_SPLIT_TOPRIGHT]->ScrollPixel( 0, nDiff ); + } + else + { + pGridWin[SC_SPLIT_BOTTOMLEFT]->ScrollPixel( 0, nDiff ); + if ( aViewData.GetHSplitMode() != SC_SPLIT_NONE ) + pGridWin[SC_SPLIT_BOTTOMRIGHT]->ScrollPixel( 0, nDiff ); + } + if (pRowBar[eWhich]) { pRowBar[eWhich]->Scroll( 0,nDiff ); pRowBar[eWhich]->Update(); } + if (pRowOutline[eWhich]) pRowOutline[eWhich]->ScrollPixel( nDiff ); + if (bUpdBars) + UpdateScrollBars(); + } + + if (nDeltaY==1 || nDeltaY==-1) + pGridWin[aViewData.GetActivePart()]->Update(); + + ShowAllCursors(); + + SetNewVisArea(); // MapMode muss schon gesetzt sein + + if (bHasHint) + TestHintWindow(); // neu positionieren +} + +void ScTabView::ScrollLines( long nDeltaX, long nDeltaY ) +{ + ScSplitPos eWhich = aViewData.GetActivePart(); + if (nDeltaX) + ScrollX(nDeltaX,WhichH(eWhich)); + if (nDeltaY) + ScrollY(nDeltaY,WhichV(eWhich)); +} + +SCROW lcl_LastVisible( ScViewData& rViewData ) +{ + // wenn am Dokumentende viele Zeilen ausgeblendet sind (welcher Trottel macht sowas?), + // soll dadurch nicht auf breite Zeilenkoepfe geschaltet werden + //! als Member ans Dokument ??? + + ScDocument* pDoc = rViewData.GetDocument(); + SCTAB nTab = rViewData.GetTabNo(); + + SCROW nVis = MAXROW; + while ( nVis > 0 && pDoc->GetRowHeight( nVis, nTab ) == 0 ) + --nVis; + return nVis; +} + +void ScTabView::UpdateHeaderWidth( const ScVSplitPos* pWhich, const SCROW* pPosY ) +{ + if ( !pRowBar[SC_SPLIT_BOTTOM] || MAXROW < 10000 ) + return; + + SCROW nEndPos = MAXROW; + if ( !aViewData.GetViewShell()->GetViewFrame()->GetFrame().IsInPlace() ) + { + // fuer OLE Inplace immer MAXROW + + if ( pWhich && *pWhich == SC_SPLIT_BOTTOM && pPosY ) + nEndPos = *pPosY; + else + nEndPos = aViewData.GetPosY( SC_SPLIT_BOTTOM ); + nEndPos += aViewData.CellsAtY( nEndPos, 1, SC_SPLIT_BOTTOM, SC_SIZE_NONE ); // VisibleCellsY + if (nEndPos > MAXROW) + nEndPos = lcl_LastVisible( aViewData ); + + if ( aViewData.GetVSplitMode() != SC_SPLIT_NONE ) + { + SCROW nTopEnd; + if ( pWhich && *pWhich == SC_SPLIT_TOP && pPosY ) + nTopEnd = *pPosY; + else + nTopEnd = aViewData.GetPosY( SC_SPLIT_TOP ); + nTopEnd += aViewData.CellsAtY( nTopEnd, 1, SC_SPLIT_TOP, SC_SIZE_NONE );// VisibleCellsY + if (nTopEnd > MAXROW) + nTopEnd = lcl_LastVisible( aViewData ); + + if ( nTopEnd > nEndPos ) + nEndPos = nTopEnd; + } + } + + long nSmall = pRowBar[SC_SPLIT_BOTTOM]->GetSmallWidth(); + long nBig = pRowBar[SC_SPLIT_BOTTOM]->GetBigWidth(); + long nDiff = nBig - nSmall; + + if (nEndPos>10000) + nEndPos = 10000; + else if (nEndPos<1) // avoid extra step at 0 (when only one row is visible) + nEndPos = 1; + long nWidth = nBig - ( 10000 - nEndPos ) * nDiff / 10000; + + if ( nWidth != pRowBar[SC_SPLIT_BOTTOM]->GetWidth() && !bInUpdateHeader ) + { + bInUpdateHeader = sal_True; + + pRowBar[SC_SPLIT_BOTTOM]->SetWidth( nWidth ); + if (pRowBar[SC_SPLIT_TOP]) + pRowBar[SC_SPLIT_TOP]->SetWidth( nWidth ); + + RepeatResize(); + + // auf VCL gibt's Update ohne Ende (jedes Update gilt fuer alle Fenster) + //aCornerButton.Update(); // der bekommt sonst nie ein Update + + bInUpdateHeader = sal_False; + } +} + +inline void ShowHide( Window* pWin, sal_Bool bShow ) +{ + DBG_ASSERT(pWin || !bShow, "Fenster ist nicht da"); + if (pWin) + pWin->Show(bShow); +} + +void ScTabView::UpdateShow() +{ + sal_Bool bHScrollMode = aViewData.IsHScrollMode(); + sal_Bool bVScrollMode = aViewData.IsVScrollMode(); + sal_Bool bTabMode = aViewData.IsTabMode(); + sal_Bool bOutlMode = aViewData.IsOutlineMode(); + sal_Bool bHOutline = bOutlMode && lcl_HasColOutline(aViewData); + sal_Bool bVOutline = bOutlMode && lcl_HasRowOutline(aViewData); + sal_Bool bHeader = aViewData.IsHeaderMode(); + + sal_Bool bShowH = ( aViewData.GetHSplitMode() != SC_SPLIT_NONE ); + sal_Bool bShowV = ( aViewData.GetVSplitMode() != SC_SPLIT_NONE ); + + // Scrollbar-Einstellungen koennen vom Sfx ueberschrieben werden: + SfxScrollingMode eMode = aViewData.GetViewShell()->GetScrollingMode(); + if ( eMode == SCROLLING_NO ) + bHScrollMode = bVScrollMode = sal_False; + else if ( eMode == SCROLLING_YES || eMode == SCROLLING_AUTO ) //! Auto ??? + bHScrollMode = bVScrollMode = sal_True; + + if ( aViewData.GetDocShell()->IsPreview() ) + bHScrollMode = bVScrollMode = bTabMode = bHeader = bOutlMode = bHOutline = bVOutline = sal_False; + + // + // Windows anlegen + // + + if (bShowH && !pGridWin[SC_SPLIT_BOTTOMRIGHT]) + { + pGridWin[SC_SPLIT_BOTTOMRIGHT] = new ScGridWindow( pFrameWin, &aViewData, SC_SPLIT_BOTTOMRIGHT ); + DoAddWin( pGridWin[SC_SPLIT_BOTTOMRIGHT] ); + } + if (bShowV && !pGridWin[SC_SPLIT_TOPLEFT]) + { + pGridWin[SC_SPLIT_TOPLEFT] = new ScGridWindow( pFrameWin, &aViewData, SC_SPLIT_TOPLEFT ); + DoAddWin( pGridWin[SC_SPLIT_TOPLEFT] ); + } + if (bShowH && bShowV && !pGridWin[SC_SPLIT_TOPRIGHT]) + { + pGridWin[SC_SPLIT_TOPRIGHT] = new ScGridWindow( pFrameWin, &aViewData, SC_SPLIT_TOPRIGHT ); + DoAddWin( pGridWin[SC_SPLIT_TOPRIGHT] ); + } + + if (bHOutline && !pColOutline[SC_SPLIT_LEFT]) + pColOutline[SC_SPLIT_LEFT] = new ScOutlineWindow( pFrameWin, SC_OUTLINE_HOR, &aViewData, SC_SPLIT_BOTTOMLEFT ); + if (bShowH && bHOutline && !pColOutline[SC_SPLIT_RIGHT]) + pColOutline[SC_SPLIT_RIGHT] = new ScOutlineWindow( pFrameWin, SC_OUTLINE_HOR, &aViewData, SC_SPLIT_BOTTOMRIGHT ); + + if (bVOutline && !pRowOutline[SC_SPLIT_BOTTOM]) + pRowOutline[SC_SPLIT_BOTTOM] = new ScOutlineWindow( pFrameWin, SC_OUTLINE_VER, &aViewData, SC_SPLIT_BOTTOMLEFT ); + if (bShowV && bVOutline && !pRowOutline[SC_SPLIT_TOP]) + pRowOutline[SC_SPLIT_TOP] = new ScOutlineWindow( pFrameWin, SC_OUTLINE_VER, &aViewData, SC_SPLIT_TOPLEFT ); + + if (bShowH && bHeader && !pColBar[SC_SPLIT_RIGHT]) + pColBar[SC_SPLIT_RIGHT] = new ScColBar( pFrameWin, &aViewData, SC_SPLIT_RIGHT, + &aHdrFunc, pHdrSelEng ); + if (bShowV && bHeader && !pRowBar[SC_SPLIT_TOP]) + pRowBar[SC_SPLIT_TOP] = new ScRowBar( pFrameWin, &aViewData, SC_SPLIT_TOP, + &aHdrFunc, pHdrSelEng ); + + // + // Windows anzeigen + // + + ShowHide( &aHScrollLeft, bHScrollMode ); + ShowHide( &aHScrollRight, bShowH && bHScrollMode ); + ShowHide( &aVScrollBottom, bVScrollMode ); + ShowHide( &aVScrollTop, bShowV && bVScrollMode ); + ShowHide( &aScrollBarBox, bVScrollMode || bHScrollMode ); + + ShowHide( pHSplitter, bHScrollMode || bShowH ); // immer angelegt + ShowHide( pVSplitter, bVScrollMode || bShowV ); + ShowHide( pTabControl, bTabMode ); + + // ab hier dynamisch angelegte + + ShowHide( pGridWin[SC_SPLIT_BOTTOMRIGHT], bShowH ); + ShowHide( pGridWin[SC_SPLIT_TOPLEFT], bShowV ); + ShowHide( pGridWin[SC_SPLIT_TOPRIGHT], bShowH && bShowV ); + + ShowHide( pColOutline[SC_SPLIT_LEFT], bHOutline ); + ShowHide( pColOutline[SC_SPLIT_RIGHT], bShowH && bHOutline ); + + ShowHide( pRowOutline[SC_SPLIT_BOTTOM], bVOutline ); + ShowHide( pRowOutline[SC_SPLIT_TOP], bShowV && bVOutline ); + + ShowHide( pColBar[SC_SPLIT_RIGHT], bShowH && bHeader ); + ShowHide( pRowBar[SC_SPLIT_TOP], bShowV && bHeader ); + + + //! neue Gridwindows eintragen +} + +// --- Splitter -------------------------------------------------------- + +IMPL_LINK( ScTabView, SplitHdl, Splitter*, pSplitter ) +{ + if ( pSplitter == pHSplitter ) + DoHSplit( pHSplitter->GetSplitPosPixel() ); + else + DoVSplit( pVSplitter->GetSplitPosPixel() ); + + if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX || aViewData.GetVSplitMode() == SC_SPLIT_FIX ) + FreezeSplitters( sal_True ); + + DoResize( aBorderPos, aFrameSize ); + + return 0; +} + +void ScTabView::DoHSplit(long nSplitPos) +{ + // nSplitPos is the real pixel position on the frame window, + // mirroring for RTL has to be done here. + + sal_Bool bLayoutRTL = aViewData.GetDocument()->IsLayoutRTL( aViewData.GetTabNo() ); + if ( bLayoutRTL ) + nSplitPos = pFrameWin->GetOutputSizePixel().Width() - nSplitPos - 1; + + long nMinPos; + long nMaxPos; + SCCOL nOldDelta; + SCCOL nNewDelta; + + nMinPos = SPLIT_MARGIN; + if ( pRowBar[SC_SPLIT_BOTTOM] && pRowBar[SC_SPLIT_BOTTOM]->GetSizePixel().Width() >= nMinPos ) + nMinPos = pRowBar[SC_SPLIT_BOTTOM]->GetSizePixel().Width() + 1; + nMaxPos = aFrameSize.Width() - SPLIT_MARGIN; + + ScSplitMode aOldMode = aViewData.GetHSplitMode(); + ScSplitMode aNewMode = SC_SPLIT_NORMAL; + + aViewData.SetHSplitPos( nSplitPos ); + if ( nSplitPos < nMinPos || nSplitPos > nMaxPos ) + aNewMode = SC_SPLIT_NONE; + + aViewData.SetHSplitMode( aNewMode ); + + if ( aNewMode != aOldMode ) + { + UpdateShow(); // vor ActivatePart !! + + if ( aNewMode == SC_SPLIT_NONE ) + { + if (aViewData.GetActivePart() == SC_SPLIT_TOPRIGHT) + ActivatePart( SC_SPLIT_TOPLEFT ); + if (aViewData.GetActivePart() == SC_SPLIT_BOTTOMRIGHT) + ActivatePart( SC_SPLIT_BOTTOMLEFT ); + } + else + { + nOldDelta = aViewData.GetPosX( SC_SPLIT_LEFT ); +// aViewData.SetPosX( SC_SPLIT_LEFT, nOldDelta ); + long nLeftWidth = nSplitPos - pRowBar[SC_SPLIT_BOTTOM]->GetSizePixel().Width(); + if ( nLeftWidth < 0 ) nLeftWidth = 0; + nNewDelta = nOldDelta + aViewData.CellsAtX( nOldDelta, 1, SC_SPLIT_LEFT, + (sal_uInt16) nLeftWidth ); + if ( nNewDelta > MAXCOL ) + nNewDelta = MAXCOL; + aViewData.SetPosX( SC_SPLIT_RIGHT, nNewDelta ); + if ( nNewDelta > aViewData.GetCurX() ) + ActivatePart( (WhichV(aViewData.GetActivePart()) == SC_SPLIT_BOTTOM) ? + SC_SPLIT_BOTTOMLEFT : SC_SPLIT_TOPLEFT ); + else + ActivatePart( (WhichV(aViewData.GetActivePart()) == SC_SPLIT_BOTTOM) ? + SC_SPLIT_BOTTOMRIGHT : SC_SPLIT_TOPRIGHT ); + } + + // #61410# Form-Layer muss den sichtbaren Ausschnitt aller Fenster kennen + // dafuer muss hier schon der MapMode stimmen + for (sal_uInt16 i=0; i<4; i++) + if (pGridWin[i]) + pGridWin[i]->SetMapMode( pGridWin[i]->GetDrawMapMode() ); + SetNewVisArea(); + + PaintGrid(); + PaintTop(); + + InvalidateSplit(); + } +} + +void ScTabView::DoVSplit(long nSplitPos) +{ + long nMinPos; + long nMaxPos; + SCROW nOldDelta; + SCROW nNewDelta; + + nMinPos = SPLIT_MARGIN; + if ( pColBar[SC_SPLIT_LEFT] && pColBar[SC_SPLIT_LEFT]->GetSizePixel().Height() >= nMinPos ) + nMinPos = pColBar[SC_SPLIT_LEFT]->GetSizePixel().Height() + 1; + nMaxPos = aFrameSize.Height() - SPLIT_MARGIN; + + ScSplitMode aOldMode = aViewData.GetVSplitMode(); + ScSplitMode aNewMode = SC_SPLIT_NORMAL; + + aViewData.SetVSplitPos( nSplitPos ); + if ( nSplitPos < nMinPos || nSplitPos > nMaxPos ) + aNewMode = SC_SPLIT_NONE; + + aViewData.SetVSplitMode( aNewMode ); + + if ( aNewMode != aOldMode ) + { + UpdateShow(); // vor ActivatePart !! + + if ( aNewMode == SC_SPLIT_NONE ) + { + nOldDelta = aViewData.GetPosY( SC_SPLIT_TOP ); + aViewData.SetPosY( SC_SPLIT_BOTTOM, nOldDelta ); + + if (aViewData.GetActivePart() == SC_SPLIT_TOPLEFT) + ActivatePart( SC_SPLIT_BOTTOMLEFT ); + if (aViewData.GetActivePart() == SC_SPLIT_TOPRIGHT) + ActivatePart( SC_SPLIT_BOTTOMRIGHT ); + } + else + { + if ( aOldMode == SC_SPLIT_NONE ) + nOldDelta = aViewData.GetPosY( SC_SPLIT_BOTTOM ); + else + nOldDelta = aViewData.GetPosY( SC_SPLIT_TOP ); + + aViewData.SetPosY( SC_SPLIT_TOP, nOldDelta ); + long nTopHeight = nSplitPos - pColBar[SC_SPLIT_LEFT]->GetSizePixel().Height(); + if ( nTopHeight < 0 ) nTopHeight = 0; + nNewDelta = nOldDelta + aViewData.CellsAtY( nOldDelta, 1, SC_SPLIT_TOP, + (sal_uInt16) nTopHeight ); + if ( nNewDelta > MAXROW ) + nNewDelta = MAXROW; + aViewData.SetPosY( SC_SPLIT_BOTTOM, nNewDelta ); + if ( nNewDelta > aViewData.GetCurY() ) + ActivatePart( (WhichH(aViewData.GetActivePart()) == SC_SPLIT_LEFT) ? + SC_SPLIT_TOPLEFT : SC_SPLIT_TOPRIGHT ); + else + ActivatePart( (WhichH(aViewData.GetActivePart()) == SC_SPLIT_LEFT) ? + SC_SPLIT_BOTTOMLEFT : SC_SPLIT_BOTTOMRIGHT ); + } + + // #61410# Form-Layer muss den sichtbaren Ausschnitt aller Fenster kennen + // dafuer muss hier schon der MapMode stimmen + for (sal_uInt16 i=0; i<4; i++) + if (pGridWin[i]) + pGridWin[i]->SetMapMode( pGridWin[i]->GetDrawMapMode() ); + SetNewVisArea(); + + PaintGrid(); + PaintLeft(); + + InvalidateSplit(); + } +} + +Point ScTabView::GetInsertPos() +{ + ScDocument* pDoc = aViewData.GetDocument(); + SCCOL nCol = aViewData.GetCurX(); + SCROW nRow = aViewData.GetCurY(); + SCTAB nTab = aViewData.GetTabNo(); + long nPosX = 0; + for (SCCOL i=0; i<nCol; i++) + nPosX += pDoc->GetColWidth(i,nTab); + nPosX = (long)(nPosX * HMM_PER_TWIPS); + if ( pDoc->IsNegativePage( nTab ) ) + nPosX = -nPosX; + long nPosY = (long) pDoc->GetRowHeight( 0, nRow-1, nTab); + nPosY = (long)(nPosY * HMM_PER_TWIPS); + return Point(nPosX,nPosY); +} + +Point ScTabView::GetChartInsertPos( const Size& rSize, const ScRange& rCellRange ) +{ + Point aInsertPos; + const long nBorder = 100; // leave 1mm for border + long nNeededWidth = rSize.Width() + 2 * nBorder; + long nNeededHeight = rSize.Height() + 2 * nBorder; + + // use the active window, or lower/right if frozen (as in CalcZoom) + ScSplitPos eUsedPart = aViewData.GetActivePart(); + if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX ) + eUsedPart = (WhichV(eUsedPart)==SC_SPLIT_TOP) ? SC_SPLIT_TOPRIGHT : SC_SPLIT_BOTTOMRIGHT; + if ( aViewData.GetVSplitMode() == SC_SPLIT_FIX ) + eUsedPart = (WhichH(eUsedPart)==SC_SPLIT_LEFT) ? SC_SPLIT_BOTTOMLEFT : SC_SPLIT_BOTTOMRIGHT; + + ScGridWindow* pWin = pGridWin[eUsedPart]; + DBG_ASSERT( pWin, "Window not found" ); + if (pWin) + { + ActivatePart( eUsedPart ); + + // get the visible rectangle in logic units + + MapMode aDrawMode = pWin->GetDrawMapMode(); + Rectangle aVisible( pWin->PixelToLogic( Rectangle( Point(0,0), pWin->GetOutputSizePixel() ), aDrawMode ) ); + + ScDocument* pDoc = aViewData.GetDocument(); + SCTAB nTab = aViewData.GetTabNo(); + sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); + long nLayoutSign = bLayoutRTL ? -1 : 1; + + long nDocX = (long)( (double) pDoc->GetColOffset( MAXCOL + 1, nTab ) * HMM_PER_TWIPS ) * nLayoutSign; + long nDocY = (long)( (double) pDoc->GetRowOffset( MAXROW + 1, nTab ) * HMM_PER_TWIPS ); + + if ( aVisible.Left() * nLayoutSign > nDocX * nLayoutSign ) + aVisible.Left() = nDocX; + if ( aVisible.Right() * nLayoutSign > nDocX * nLayoutSign ) + aVisible.Right() = nDocX; + if ( aVisible.Top() > nDocY ) + aVisible.Top() = nDocY; + if ( aVisible.Bottom() > nDocY ) + aVisible.Bottom() = nDocY; + + // get the logic position of the selection + + Rectangle aSelection = pDoc->GetMMRect( rCellRange.aStart.Col(), rCellRange.aStart.Row(), + rCellRange.aEnd.Col(), rCellRange.aEnd.Row(), nTab ); + + long nLeftSpace = aSelection.Left() - aVisible.Left(); + long nRightSpace = aVisible.Right() - aSelection.Right(); + long nTopSpace = aSelection.Top() - aVisible.Top(); + long nBottomSpace = aVisible.Bottom() - aSelection.Bottom(); + + bool bFitLeft = ( nLeftSpace >= nNeededWidth ); + bool bFitRight = ( nRightSpace >= nNeededWidth ); + + if ( bFitLeft || bFitRight ) + { + // first preference: completely left or right of the selection + + // if both fit, prefer left in RTL mode, right otherwise + bool bPutLeft = bFitLeft && ( bLayoutRTL || !bFitRight ); + + if ( bPutLeft ) + aInsertPos.X() = aSelection.Left() - nNeededWidth; + else + aInsertPos.X() = aSelection.Right() + 1; + + // align with top of selection (is moved again if it doesn't fit) + aInsertPos.Y() = std::max( aSelection.Top(), aVisible.Top() ); + } + else if ( nTopSpace >= nNeededHeight || nBottomSpace >= nNeededHeight ) + { + // second preference: completely above or below the selection + + if ( nBottomSpace > nNeededHeight ) // bottom is preferred + aInsertPos.Y() = aSelection.Bottom() + 1; + else + aInsertPos.Y() = aSelection.Top() - nNeededHeight; + + // align with (logic) left edge of selection (moved again if it doesn't fit) + if ( bLayoutRTL ) + aInsertPos.X() = std::min( aSelection.Right(), aVisible.Right() ) - nNeededWidth + 1; + else + aInsertPos.X() = std::max( aSelection.Left(), aVisible.Left() ); + } + else + { + // place to the (logic) right of the selection and move so it fits + + if ( bLayoutRTL ) + aInsertPos.X() = aSelection.Left() - nNeededWidth; + else + aInsertPos.X() = aSelection.Right() + 1; + aInsertPos.Y() = std::max( aSelection.Top(), aVisible.Top() ); + } + + // move the position if the object doesn't fit in the screen + + Rectangle aCompareRect( aInsertPos, Size( nNeededWidth, nNeededHeight ) ); + if ( aCompareRect.Right() > aVisible.Right() ) + aInsertPos.X() -= aCompareRect.Right() - aVisible.Right(); + if ( aCompareRect.Bottom() > aVisible.Bottom() ) + aInsertPos.Y() -= aCompareRect.Bottom() - aVisible.Bottom(); + + if ( aInsertPos.X() < aVisible.Left() ) + aInsertPos.X() = aVisible.Left(); + if ( aInsertPos.Y() < aVisible.Top() ) + aInsertPos.Y() = aVisible.Top(); + + // nNeededWidth / nNeededHeight includes all borders - move aInsertPos to the + // object position, inside the border + + aInsertPos.X() += nBorder; + aInsertPos.Y() += nBorder; + } + return aInsertPos; +} + +Point ScTabView::GetChartDialogPos( const Size& rDialogSize, const Rectangle& rLogicChart ) +{ + // rDialogSize must be in pixels, rLogicChart in 1/100 mm. Return value is in pixels. + + Point aRet; + + // use the active window, or lower/right if frozen (as in CalcZoom) + ScSplitPos eUsedPart = aViewData.GetActivePart(); + if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX ) + eUsedPart = (WhichV(eUsedPart)==SC_SPLIT_TOP) ? SC_SPLIT_TOPRIGHT : SC_SPLIT_BOTTOMRIGHT; + if ( aViewData.GetVSplitMode() == SC_SPLIT_FIX ) + eUsedPart = (WhichH(eUsedPart)==SC_SPLIT_LEFT) ? SC_SPLIT_BOTTOMLEFT : SC_SPLIT_BOTTOMRIGHT; + + ScGridWindow* pWin = pGridWin[eUsedPart]; + DBG_ASSERT( pWin, "Window not found" ); + if (pWin) + { + MapMode aDrawMode = pWin->GetDrawMapMode(); + Rectangle aObjPixel = pWin->LogicToPixel( rLogicChart, aDrawMode ); + Rectangle aObjAbs( pWin->OutputToAbsoluteScreenPixel( aObjPixel.TopLeft() ), + pWin->OutputToAbsoluteScreenPixel( aObjPixel.BottomRight() ) ); + + Rectangle aDesktop = pWin->GetDesktopRectPixel(); + Size aSpace = pWin->LogicToPixel( Size( 8, 12 ), MAP_APPFONT ); + + ScDocument* pDoc = aViewData.GetDocument(); + SCTAB nTab = aViewData.GetTabNo(); + sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); + + bool bCenterHor = false; + + if ( aDesktop.Bottom() - aObjAbs.Bottom() >= rDialogSize.Height() + aSpace.Height() ) + { + // first preference: below the chart + + aRet.Y() = aObjAbs.Bottom() + aSpace.Height(); + bCenterHor = true; + } + else if ( aObjAbs.Top() - aDesktop.Top() >= rDialogSize.Height() + aSpace.Height() ) + { + // second preference: above the chart + + aRet.Y() = aObjAbs.Top() - rDialogSize.Height() - aSpace.Height(); + bCenterHor = true; + } + else + { + bool bFitLeft = ( aObjAbs.Left() - aDesktop.Left() >= rDialogSize.Width() + aSpace.Width() ); + bool bFitRight = ( aDesktop.Right() - aObjAbs.Right() >= rDialogSize.Width() + aSpace.Width() ); + + if ( bFitLeft || bFitRight ) + { + // if both fit, prefer right in RTL mode, left otherwise + bool bPutRight = bFitRight && ( bLayoutRTL || !bFitLeft ); + if ( bPutRight ) + aRet.X() = aObjAbs.Right() + aSpace.Width(); + else + aRet.X() = aObjAbs.Left() - rDialogSize.Width() - aSpace.Width(); + + // center vertically + aRet.Y() = aObjAbs.Top() + ( aObjAbs.GetHeight() - rDialogSize.Height() ) / 2; + } + else + { + // doesn't fit on any edge - put at the bottom of the screen + aRet.Y() = aDesktop.Bottom() - rDialogSize.Height(); + bCenterHor = true; + } + } + if ( bCenterHor ) + aRet.X() = aObjAbs.Left() + ( aObjAbs.GetWidth() - rDialogSize.Width() ) / 2; + + // limit to screen (centering might lead to invalid positions) + if ( aRet.X() + rDialogSize.Width() - 1 > aDesktop.Right() ) + aRet.X() = aDesktop.Right() - rDialogSize.Width() + 1; + if ( aRet.X() < aDesktop.Left() ) + aRet.X() = aDesktop.Left(); + if ( aRet.Y() + rDialogSize.Height() - 1 > aDesktop.Bottom() ) + aRet.Y() = aDesktop.Bottom() - rDialogSize.Height() + 1; + if ( aRet.Y() < aDesktop.Top() ) + aRet.Y() = aDesktop.Top(); + } + + return aRet; +} + +void ScTabView::LockModifiers( sal_uInt16 nModifiers ) +{ + pSelEngine->LockModifiers( nModifiers ); + pHdrSelEng->LockModifiers( nModifiers ); +} + +sal_uInt16 ScTabView::GetLockedModifiers() const +{ + return pSelEngine->GetLockedModifiers(); +} + +Point ScTabView::GetMousePosPixel() +{ + Point aPos; + ScGridWindow* pWin = (ScGridWindow*)GetActiveWin(); + + if ( pWin ) + aPos = pWin->GetMousePosPixel(); + + return aPos; +} + +sal_Bool lcl_MouseIsOverWin( const Point& rScreenPosPixel, Window* pWin ) +{ + if (pWin) + { + // SPLIT_HANDLE_SIZE draufaddieren, damit das Einrasten genau + // auf dem Splitter nicht aussetzt + + Point aRel = pWin->NormalizedScreenToOutputPixel( rScreenPosPixel ); + Size aWinSize = pWin->GetOutputSizePixel(); + if ( aRel.X() >= 0 && aRel.X() < aWinSize.Width() + SPLIT_HANDLE_SIZE && + aRel.Y() >= 0 && aRel.Y() < aWinSize.Height() + SPLIT_HANDLE_SIZE ) + return sal_True; + } + return sal_False; +} + +void ScTabView::SnapSplitPos( Point& rScreenPosPixel ) +{ + sal_Bool bOverWin = sal_False; + sal_uInt16 i; + for (i=0; i<4; i++) + if (lcl_MouseIsOverWin(rScreenPosPixel,pGridWin[i])) + bOverWin = sal_True; + + if (!bOverWin) + return; + + // #74761# don't snap to cells if the scale will be modified afterwards + if ( GetZoomType() != SVX_ZOOM_PERCENT ) + return; + + ScSplitPos ePos = SC_SPLIT_BOTTOMLEFT; + if ( aViewData.GetVSplitMode() != SC_SPLIT_NONE ) + ePos = SC_SPLIT_TOPLEFT; + + Window* pWin = pGridWin[ePos]; + if (!pWin) + { + DBG_ERROR("Window NULL"); + return; + } + + Point aMouse = pWin->NormalizedScreenToOutputPixel( rScreenPosPixel ); + SCsCOL nPosX; + SCsROW nPosY; + // #52949# bNextIfLarge=FALSE: nicht auf naechste Zelle, wenn ausserhalb des Fensters + aViewData.GetPosFromPixel( aMouse.X(), aMouse.Y(), ePos, nPosX, nPosY, sal_True, sal_False, sal_False ); + sal_Bool bLeft; + sal_Bool bTop; + aViewData.GetMouseQuadrant( aMouse, ePos, nPosX, nPosY, bLeft, bTop ); + if (!bLeft) + ++nPosX; + if (!bTop) + ++nPosY; + aMouse = aViewData.GetScrPos( static_cast<SCCOL>(nPosX), static_cast<SCROW>(nPosY), ePos, sal_True ); + rScreenPosPixel = pWin->OutputToNormalizedScreenPixel( aMouse ); +} + +void ScTabView::FreezeSplitters( sal_Bool bFreeze ) +{ + ScSplitMode eOldH = aViewData.GetHSplitMode(); + ScSplitMode eOldV = aViewData.GetVSplitMode(); + + ScSplitPos ePos = SC_SPLIT_BOTTOMLEFT; + if ( eOldV != SC_SPLIT_NONE ) + ePos = SC_SPLIT_TOPLEFT; + Window* pWin = pGridWin[ePos]; + + sal_Bool bLayoutRTL = aViewData.GetDocument()->IsLayoutRTL( aViewData.GetTabNo() ); + + if ( bFreeze ) + { + Point aWinStart = pWin->GetPosPixel(); + + Point aSplit; + SCsCOL nPosX; + SCsROW nPosY; + if (eOldH != SC_SPLIT_NONE || eOldV != SC_SPLIT_NONE) + { + if (eOldH != SC_SPLIT_NONE) + { + long nSplitPos = aViewData.GetHSplitPos(); + if ( bLayoutRTL ) + nSplitPos = pFrameWin->GetOutputSizePixel().Width() - nSplitPos - 1; + aSplit.X() = nSplitPos - aWinStart.X(); + } + if (eOldV != SC_SPLIT_NONE) + aSplit.Y() = aViewData.GetVSplitPos() - aWinStart.Y(); + + aViewData.GetPosFromPixel( aSplit.X(), aSplit.Y(), ePos, nPosX, nPosY ); + sal_Bool bLeft; + sal_Bool bTop; + aViewData.GetMouseQuadrant( aSplit, ePos, nPosX, nPosY, bLeft, bTop ); + if (!bLeft) + ++nPosX; + if (!bTop) + ++nPosY; + } + else + { + nPosX = static_cast<SCsCOL>( aViewData.GetCurX()); + nPosY = static_cast<SCsROW>( aViewData.GetCurY()); + } + + SCCOL nLeftPos = aViewData.GetPosX(SC_SPLIT_LEFT); + SCROW nTopPos = aViewData.GetPosY(SC_SPLIT_BOTTOM); + SCCOL nRightPos = static_cast<SCCOL>(nPosX); + SCROW nBottomPos = static_cast<SCROW>(nPosY); + if (eOldH != SC_SPLIT_NONE) + if (aViewData.GetPosX(SC_SPLIT_RIGHT) > nRightPos) + nRightPos = aViewData.GetPosX(SC_SPLIT_RIGHT); + if (eOldV != SC_SPLIT_NONE) + { + nTopPos = aViewData.GetPosY(SC_SPLIT_TOP); + if (aViewData.GetPosY(SC_SPLIT_BOTTOM) > nBottomPos) + nBottomPos = aViewData.GetPosY(SC_SPLIT_BOTTOM); + } + + aSplit = aViewData.GetScrPos( static_cast<SCCOL>(nPosX), static_cast<SCROW>(nPosY), ePos, sal_True ); + if (nPosX > aViewData.GetPosX(SC_SPLIT_LEFT)) // (aSplit.X() > 0) doesn't work for RTL + { + long nSplitPos = aSplit.X() + aWinStart.X(); + if ( bLayoutRTL ) + nSplitPos = pFrameWin->GetOutputSizePixel().Width() - nSplitPos - 1; + + aViewData.SetHSplitMode( SC_SPLIT_FIX ); + aViewData.SetHSplitPos( nSplitPos ); + aViewData.SetFixPosX( nPosX ); + + aViewData.SetPosX(SC_SPLIT_LEFT, nLeftPos); + aViewData.SetPosX(SC_SPLIT_RIGHT, nRightPos); + } + else + aViewData.SetHSplitMode( SC_SPLIT_NONE ); + if (aSplit.Y() > 0) + { + aViewData.SetVSplitMode( SC_SPLIT_FIX ); + aViewData.SetVSplitPos( aSplit.Y() + aWinStart.Y() ); + aViewData.SetFixPosY( nPosY ); + + aViewData.SetPosY(SC_SPLIT_TOP, nTopPos); + aViewData.SetPosY(SC_SPLIT_BOTTOM, nBottomPos); + } + else + aViewData.SetVSplitMode( SC_SPLIT_NONE ); + } + else // Fixierung aufheben + { + if ( eOldH == SC_SPLIT_FIX ) + aViewData.SetHSplitMode( SC_SPLIT_NORMAL ); + if ( eOldV == SC_SPLIT_FIX ) + aViewData.SetVSplitMode( SC_SPLIT_NORMAL ); + } + + // #61410# Form-Layer muss den sichtbaren Ausschnitt aller Fenster kennen + // dafuer muss hier schon der MapMode stimmen + for (sal_uInt16 i=0; i<4; i++) + if (pGridWin[i]) + pGridWin[i]->SetMapMode( pGridWin[i]->GetDrawMapMode() ); + SetNewVisArea(); + + RepeatResize(sal_False); + + UpdateShow(); + PaintLeft(); + PaintTop(); + PaintGrid(); + + // SC_FOLLOW_NONE: only update active part + AlignToCursor( aViewData.GetCurX(), aViewData.GetCurY(), SC_FOLLOW_NONE ); + UpdateAutoFillMark(); + + InvalidateSplit(); +} + +void ScTabView::RemoveSplit() +{ + DoHSplit( 0 ); + DoVSplit( 0 ); + RepeatResize(); +} + +void ScTabView::SplitAtCursor() +{ + ScSplitPos ePos = SC_SPLIT_BOTTOMLEFT; + if ( aViewData.GetVSplitMode() != SC_SPLIT_NONE ) + ePos = SC_SPLIT_TOPLEFT; + Window* pWin = pGridWin[ePos]; + Point aWinStart = pWin->GetPosPixel(); + + SCCOL nPosX = aViewData.GetCurX(); + SCROW nPosY = aViewData.GetCurY(); + Point aSplit = aViewData.GetScrPos( nPosX, nPosY, ePos, sal_True ); + if ( nPosX > 0 ) + DoHSplit( aSplit.X() + aWinStart.X() ); + else + DoHSplit( 0 ); + if ( nPosY > 0 ) + DoVSplit( aSplit.Y() + aWinStart.Y() ); + else + DoVSplit( 0 ); + RepeatResize(); +} + +void ScTabView::SplitAtPixel( const Point& rPixel, sal_Bool bHor, sal_Bool bVer ) // fuer API +{ + // Pixel ist auf die ganze View bezogen, nicht auf das erste GridWin + + if (bHor) + { + if ( rPixel.X() > 0 ) + DoHSplit( rPixel.X() ); + else + DoHSplit( 0 ); + } + if (bVer) + { + if ( rPixel.Y() > 0 ) + DoVSplit( rPixel.Y() ); + else + DoVSplit( 0 ); + } + RepeatResize(); +} + +void ScTabView::InvalidateSplit() +{ + SfxBindings& rBindings = aViewData.GetBindings(); + rBindings.Invalidate( SID_WINDOW_SPLIT ); + rBindings.Invalidate( SID_WINDOW_FIX ); + + pHSplitter->SetFixed( aViewData.GetHSplitMode() == SC_SPLIT_FIX ); + pVSplitter->SetFixed( aViewData.GetVSplitMode() == SC_SPLIT_FIX ); +} + +void ScTabView::SetNewVisArea() +{ + // #63854# fuer die Controls muss bei VisAreaChanged der Draw-MapMode eingestellt sein + // (auch wenn ansonsten der Edit-MapMode gesetzt ist) + MapMode aOldMode[4]; + MapMode aDrawMode[4]; + sal_uInt16 i; + for (i=0; i<4; i++) + if (pGridWin[i]) + { + aOldMode[i] = pGridWin[i]->GetMapMode(); + aDrawMode[i] = pGridWin[i]->GetDrawMapMode(); + if (aDrawMode[i] != aOldMode[i]) + pGridWin[i]->SetMapMode(aDrawMode[i]); + } + + Window* pActive = pGridWin[aViewData.GetActivePart()]; + if (pActive) + aViewData.GetViewShell()->VisAreaChanged( + pActive->PixelToLogic(Rectangle(Point(),pActive->GetOutputSizePixel())) ); + if (pDrawView) + pDrawView->VisAreaChanged(); // kein Window uebergeben -> alle Fenster + + UpdateAllOverlays(); // #i79909# with drawing MapMode set + + for (i=0; i<4; i++) + if (pGridWin[i] && aDrawMode[i] != aOldMode[i]) + { + pGridWin[i]->flushOverlayManager(); // #i79909# flush overlays before switching to edit MapMode + pGridWin[i]->SetMapMode(aOldMode[i]); + } + + SfxViewFrame* pViewFrame = aViewData.GetViewShell()->GetViewFrame(); + if (pViewFrame) + { + SfxFrame& rFrame = pViewFrame->GetFrame(); + com::sun::star::uno::Reference<com::sun::star::frame::XController> xController = rFrame.GetController(); + if (xController.is()) + { + ScTabViewObj* pImp = ScTabViewObj::getImplementation( xController ); + if (pImp) + pImp->VisAreaChanged(); + } + } + if (aViewData.GetViewShell()->HasAccessibilityObjects()) + aViewData.GetViewShell()->BroadcastAccessibility(SfxSimpleHint(SC_HINT_ACC_VISAREACHANGED)); +} + +sal_Bool ScTabView::HasPageFieldDataAtCursor() const +{ + ScGridWindow* pWin = pGridWin[aViewData.GetActivePart()]; + SCCOL nCol = aViewData.GetCurX(); + SCROW nRow = aViewData.GetCurY(); + if (pWin) + return pWin->GetDPFieldOrientation( nCol, nRow ) == sheet::DataPilotFieldOrientation_PAGE; + + return sal_False; +} + +void ScTabView::StartDataSelect() +{ + ScGridWindow* pWin = pGridWin[aViewData.GetActivePart()]; + SCCOL nCol = aViewData.GetCurX(); + SCROW nRow = aViewData.GetCurY(); + + if (!pWin) + return; + + switch (pWin->GetDPFieldOrientation(nCol, nRow)) + { + case sheet::DataPilotFieldOrientation_PAGE: + // #i36598# If the cursor is on a page field's data cell, + // no meaningful input is possible anyway, so this function + // can be used to select a page field entry. + pWin->LaunchPageFieldMenu( nCol, nRow ); + break; + case sheet::DataPilotFieldOrientation_COLUMN: + case sheet::DataPilotFieldOrientation_ROW: + pWin->LaunchDPFieldMenu( nCol, nRow ); + break; + default: + pWin->DoAutoFilterMenue( nCol, nRow, sal_True ); + } +} + +void ScTabView::EnableRefInput(sal_Bool bFlag) +{ + aHScrollLeft.EnableInput(bFlag); + aHScrollRight.EnableInput(bFlag); + aVScrollBottom.EnableInput(bFlag); + aVScrollTop.EnableInput(bFlag); + aScrollBarBox.EnableInput(bFlag); + + // ab hier dynamisch angelegte + + if(pTabControl!=NULL) pTabControl->EnableInput(bFlag,sal_True); + + if(pGridWin[SC_SPLIT_BOTTOMLEFT]!=NULL) + pGridWin[SC_SPLIT_BOTTOMLEFT]->EnableInput(bFlag,sal_False); + if(pGridWin[SC_SPLIT_BOTTOMRIGHT]!=NULL) + pGridWin[SC_SPLIT_BOTTOMRIGHT]->EnableInput(bFlag,sal_False); + if(pGridWin[SC_SPLIT_TOPLEFT]!=NULL) + pGridWin[SC_SPLIT_TOPLEFT]->EnableInput(bFlag,sal_False); + if(pGridWin[SC_SPLIT_TOPRIGHT]!=NULL) + pGridWin[SC_SPLIT_TOPRIGHT]->EnableInput(bFlag,sal_False); + if(pColBar[SC_SPLIT_RIGHT]!=NULL) + pColBar[SC_SPLIT_RIGHT]->EnableInput(bFlag,sal_False); + if(pRowBar[SC_SPLIT_TOP]!=NULL) + pRowBar[SC_SPLIT_TOP]->EnableInput(bFlag,sal_False); +} + + + diff --git a/sc/source/ui/view/tabview2.cxx b/sc/source/ui/view/tabview2.cxx new file mode 100644 index 000000000000..4fc575942feb --- /dev/null +++ b/sc/source/ui/view/tabview2.cxx @@ -0,0 +1,982 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include "scitems.hxx" +#include <editeng/eeitem.hxx> + + +#include <vcl/timer.hxx> +#include <vcl/msgbox.hxx> +#include <sfx2/app.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/childwin.hxx> + +#include "attrib.hxx" +#include "pagedata.hxx" +#include "tabview.hxx" +#include "tabvwsh.hxx" +#include "printfun.hxx" +#include "stlpool.hxx" +#include "docsh.hxx" +#include "gridwin.hxx" +#include "olinewin.hxx" +#include "uiitems.hxx" +#include "sc.hrc" +#include "viewutil.hxx" +#include "colrowba.hxx" +#include "waitoff.hxx" +#include "globstr.hrc" +#include "scmod.hxx" + +#define SC_BLOCKMODE_NONE 0 +#define SC_BLOCKMODE_NORMAL 1 +#define SC_BLOCKMODE_OWN 2 + + + +// +// Markier - Funktionen +// + +void ScTabView::PaintMarks(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow ) +{ + if (!ValidCol(nStartCol)) nStartCol = MAXCOL; + if (!ValidRow(nStartRow)) nStartRow = MAXROW; + if (!ValidCol(nEndCol)) nEndCol = MAXCOL; + if (!ValidRow(nEndRow)) nEndRow = MAXROW; + + sal_Bool bLeft = (nStartCol==0 && nEndCol==MAXCOL); + sal_Bool bTop = (nStartRow==0 && nEndRow==MAXROW); + + if (bLeft) + PaintLeftArea( nStartRow, nEndRow ); + if (bTop) + PaintTopArea( nStartCol, nEndCol ); + + aViewData.GetDocument()->ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow, + aViewData.GetTabNo() ); + PaintArea( nStartCol, nStartRow, nEndCol, nEndRow, SC_UPDATE_MARKS ); +} + +sal_Bool ScTabView::IsMarking( SCCOL nCol, SCROW nRow, SCTAB nTab ) const +{ + return bIsBlockMode + && nBlockStartX == nCol + && nBlockStartY == nRow + && nBlockStartZ == nTab; +} + +void ScTabView::InitOwnBlockMode() +{ + if (!bIsBlockMode) + { + // Wenn keine (alte) Markierung mehr da ist, Anker in SelectionEngine loeschen: + + ScMarkData& rMark = aViewData.GetMarkData(); + if (!rMark.IsMarked() && !rMark.IsMultiMarked()) + GetSelEngine()->CursorPosChanging( sal_False, sal_False ); + +// bIsBlockMode = sal_True; + bIsBlockMode = SC_BLOCKMODE_OWN; //! Variable umbenennen! + nBlockStartX = 0; + nBlockStartY = 0; + nBlockStartZ = 0; + nBlockEndX = 0; + nBlockEndY = 0; + nBlockEndZ = 0; + + SelectionChanged(); // Status wird mit gesetzer Markierung abgefragt + } +} + +void ScTabView::InitBlockMode( SCCOL nCurX, SCROW nCurY, SCTAB nCurZ, + sal_Bool bTestNeg, sal_Bool bCols, sal_Bool bRows ) +{ + if (!bIsBlockMode) + { + if (!ValidCol(nCurX)) nCurX = MAXCOL; + if (!ValidRow(nCurY)) nCurY = MAXROW; + + ScMarkData& rMark = aViewData.GetMarkData(); + SCTAB nTab = aViewData.GetTabNo(); + + // Teil von Markierung aufheben? + if (bTestNeg) + { + if ( bCols ) + bBlockNeg = rMark.IsColumnMarked( nCurX ); + else if ( bRows ) + bBlockNeg = rMark.IsRowMarked( nCurY ); + else + bBlockNeg = rMark.IsCellMarked( nCurX, nCurY ); + } + else + bBlockNeg = sal_False; + rMark.SetMarkNegative(bBlockNeg); + +// bIsBlockMode = sal_True; + bIsBlockMode = SC_BLOCKMODE_NORMAL; //! Variable umbenennen! + bBlockCols = bCols; + bBlockRows = bRows; + nBlockStartX = nBlockStartXOrig = nCurX; + nBlockStartY = nBlockStartYOrig = nCurY; + nBlockStartZ = nCurZ; + nBlockEndX = nOldCurX = nBlockStartX; + nBlockEndY = nOldCurY = nBlockStartY; + nBlockEndZ = nBlockStartZ; + + if (bBlockCols) + { + nBlockStartY = nBlockStartYOrig = 0; + nBlockEndY = MAXROW; + } + + if (bBlockRows) + { + nBlockStartX = nBlockStartXOrig = 0; + nBlockEndX = MAXCOL; + } + + rMark.SetMarkArea( ScRange( nBlockStartX,nBlockStartY, nTab, nBlockEndX,nBlockEndY, nTab ) ); + +#ifdef OLD_SELECTION_PAINT + InvertBlockMark( nBlockStartX,nBlockStartY,nBlockEndX,nBlockEndY ); +#endif + UpdateSelectionOverlay(); + + bNewStartIfMarking = sal_False; // use only once + } +} + +void ScTabView::SetNewStartIfMarking() +{ + bNewStartIfMarking = sal_True; +} + +void ScTabView::DoneBlockMode( sal_Bool bContinue ) // Default FALSE +{ + // Wenn zwischen Tabellen- und Header SelectionEngine gewechselt wird, + // wird evtl. DeselectAll gerufen, weil die andere Engine keinen Anker hat. + // Mit bMoveIsShift wird verhindert, dass dann die Selektion aufgehoben wird. + + if (bIsBlockMode && !bMoveIsShift) + { + ScMarkData& rMark = aViewData.GetMarkData(); + sal_Bool bFlag = rMark.GetMarkingFlag(); + rMark.SetMarking(sal_False); + + if (bBlockNeg && !bContinue) + rMark.MarkToMulti(); + + if (bContinue) + rMark.MarkToMulti(); + else + { + // Die Tabelle kann an dieser Stelle ungueltig sein, weil DoneBlockMode + // aus SetTabNo aufgerufen wird + // (z.B. wenn die aktuelle Tabelle von einer anderen View aus geloescht wird) + + SCTAB nTab = aViewData.GetTabNo(); + ScDocument* pDoc = aViewData.GetDocument(); + if ( pDoc->HasTable(nTab) ) + PaintBlock( sal_True ); // sal_True -> Block loeschen + else + rMark.ResetMark(); + } +// bIsBlockMode = sal_False; + bIsBlockMode = SC_BLOCKMODE_NONE; //! Variable umbenennen! + + rMark.SetMarking(bFlag); + rMark.SetMarkNegative(sal_False); + } +} + +void ScTabView::MarkCursor( SCCOL nCurX, SCROW nCurY, SCTAB nCurZ, + sal_Bool bCols, sal_Bool bRows, sal_Bool bCellSelection ) +{ + if (!ValidCol(nCurX)) nCurX = MAXCOL; + if (!ValidRow(nCurY)) nCurY = MAXROW; + + if (!bIsBlockMode) + { + DBG_ERROR( "MarkCursor nicht im BlockMode" ); + InitBlockMode( nCurX, nCurY, nCurZ, sal_False, bCols, bRows ); + } + + if (bCols) + nCurY = MAXROW; + if (bRows) + nCurX = MAXCOL; + + ScMarkData& rMark = aViewData.GetMarkData(); + DBG_ASSERT(rMark.IsMarked() || rMark.IsMultiMarked(), "MarkCursor, !IsMarked()"); + ScRange aMarkRange; + rMark.GetMarkArea(aMarkRange); + if (( aMarkRange.aStart.Col() != nBlockStartX && aMarkRange.aEnd.Col() != nBlockStartX ) || + ( aMarkRange.aStart.Row() != nBlockStartY && aMarkRange.aEnd.Row() != nBlockStartY ) || + ( bIsBlockMode == SC_BLOCKMODE_OWN )) + { + // Markierung ist veraendert worden + // (z.B. MarkToSimple, wenn per negativ alles bis auf ein Rechteck geloescht wurde) + // oder nach InitOwnBlockMode wird mit Shift-Klick weitermarkiert... + + sal_Bool bOldShift = bMoveIsShift; + bMoveIsShift = sal_False; // wirklich umsetzen + DoneBlockMode(sal_False); //! direkt Variablen setzen? (-> kein Geflacker) + bMoveIsShift = bOldShift; + + InitBlockMode( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), + nBlockStartZ, rMark.IsMarkNegative(), bCols, bRows ); + } + + SCCOL nOldBlockEndX = nBlockEndX; + SCROW nOldBlockEndY = nBlockEndY; + + if ( nCurX != nOldCurX || nCurY != nOldCurY ) + { + // Current cursor has moved + + SCTAB nTab = nCurZ; + +#ifdef OLD_SELECTION_PAINT + SCCOL nDrawStartCol; + SCROW nDrawStartRow; + SCCOL nDrawEndCol; + SCROW nDrawEndRow; +#endif + + // Set old selection area + ScUpdateRect aRect( nBlockStartX, nBlockStartY, nOldBlockEndX, nOldBlockEndY ); + + if ( bCellSelection ) + { + // Expand selection area accordingly when the current selection ends + // with a merged cell. + SCsCOL nCurXOffset = 0; + SCsCOL nBlockStartXOffset = 0; + SCsROW nCurYOffset = 0; + SCsROW nBlockStartYOffset = 0; + sal_Bool bBlockStartMerged = sal_False; + const ScMergeAttr* pMergeAttr = NULL; + ScDocument* pDocument = aViewData.GetDocument(); + + // The following block checks whether or not the "BlockStart" (anchor) + // cell is merged. If it's merged, it'll then move the position of the + // anchor cell to the corner that's diagonally opposite of the + // direction of a current selection area. For instance, if a current + // selection is moving in the upperleft direction, the anchor cell will + // move to the lower-right corner of the merged anchor cell, and so on. + + pMergeAttr = static_cast<const ScMergeAttr*>( + pDocument->GetAttr( nBlockStartXOrig, nBlockStartYOrig, nTab, ATTR_MERGE ) ); + if ( pMergeAttr->IsMerged() ) + { + SCsCOL nColSpan = pMergeAttr->GetColMerge(); + SCsROW nRowSpan = pMergeAttr->GetRowMerge(); + + if ( !( nCurX >= nBlockStartXOrig + nColSpan - 1 && nCurY >= nBlockStartYOrig + nRowSpan - 1 ) ) + { + nBlockStartX = nCurX >= nBlockStartXOrig ? nBlockStartXOrig : nBlockStartXOrig + nColSpan - 1; + nBlockStartY = nCurY >= nBlockStartYOrig ? nBlockStartYOrig : nBlockStartYOrig + nRowSpan - 1; + nCurXOffset = nCurX >= nBlockStartXOrig && nCurX < nBlockStartXOrig + nColSpan - 1 ? + nBlockStartXOrig - nCurX + nColSpan - 1 : 0; + nCurYOffset = nCurY >= nBlockStartYOrig && nCurY < nBlockStartYOrig + nRowSpan - 1 ? + nBlockStartYOrig - nCurY + nRowSpan - 1 : 0; + bBlockStartMerged = sal_True; + } + } + + // The following block checks whether or not the current cell is + // merged. If it is, it'll then set the appropriate X & Y offset + // values (nCurXOffset & nCurYOffset) such that the selection area will + // grow by those specified offset amounts. Note that the values of + // nCurXOffset/nCurYOffset may also be specified in the previous code + // block, in which case whichever value is greater will take on. + + pMergeAttr = static_cast<const ScMergeAttr*>( + pDocument->GetAttr( nCurX, nCurY, nTab, ATTR_MERGE ) ); + if ( pMergeAttr->IsMerged() ) + { + SCsCOL nColSpan = pMergeAttr->GetColMerge(); + SCsROW nRowSpan = pMergeAttr->GetRowMerge(); + + if ( !( nBlockStartX >= nCurX + nColSpan - 1 && nBlockStartY >= nCurY + nRowSpan - 1 ) ) + { + if ( nBlockStartX <= nCurX + nColSpan - 1 ) + { + SCsCOL nCurXOffsetTemp = nCurX < nCurX + nColSpan - 1 ? nColSpan - 1 : 0; + nCurXOffset = nCurXOffset > nCurXOffsetTemp ? nCurXOffset : nCurXOffsetTemp; + } + if ( nBlockStartY <= nCurY + nRowSpan - 1 ) + { + SCsROW nCurYOffsetTemp = nCurY < nCurY + nRowSpan - 1 ? nRowSpan - 1 : 0; + nCurYOffset = nCurYOffset > nCurYOffsetTemp ? nCurYOffset : nCurYOffsetTemp; + } + if ( !( nBlockStartX <= nCurX && nBlockStartY <= nCurY ) && + !( nBlockStartX > nCurX + nColSpan - 1 && nBlockStartY > nCurY + nRowSpan - 1 ) ) + { + nBlockStartXOffset = nBlockStartX > nCurX && nBlockStartX <= nCurX + nColSpan - 1 ? nCurX - nBlockStartX : 0; + nBlockStartYOffset = nBlockStartY > nCurY && nBlockStartY <= nCurY + nRowSpan - 1 ? nCurY - nBlockStartY : 0; + } + } + } + else + { + // The current cell is not merged. Move the anchor cell to its + // original position. + if ( !bBlockStartMerged ) + { + nBlockStartX = nBlockStartXOrig; + nBlockStartY = nBlockStartYOrig; + } + } + + nBlockStartX = nBlockStartX + nBlockStartXOffset >= 0 ? nBlockStartX + nBlockStartXOffset : 0; + nBlockStartY = nBlockStartY + nBlockStartYOffset >= 0 ? nBlockStartY + nBlockStartYOffset : 0; + nBlockEndX = nCurX + nCurXOffset > MAXCOL ? MAXCOL : nCurX + nCurXOffset; + nBlockEndY = nCurY + nCurYOffset > MAXROW ? MAXROW : nCurY + nCurYOffset; + } + else + { + nBlockEndX = nCurX; + nBlockEndY = nCurY; + } + // end of "if ( bCellSelection )" + + // Set new selection area + aRect.SetNew( nBlockStartX, nBlockStartY, nBlockEndX, nBlockEndY ); + rMark.SetMarkArea( ScRange( nBlockStartX, nBlockStartY, nTab, nBlockEndX, nBlockEndY, nTab ) ); + +#ifdef OLD_SELECTION_PAINT + sal_Bool bCont; + sal_Bool bDraw = aRect.GetXorDiff( nDrawStartCol, nDrawStartRow, + nDrawEndCol, nDrawEndRow, bCont ); + if ( bDraw ) + { +//? PutInOrder( nDrawStartCol, nDrawEndCol ); +//? PutInOrder( nDrawStartRow, nDrawEndRow ); + + HideAllCursors(); + InvertBlockMark( nDrawStartCol, nDrawStartRow, nDrawEndCol, nDrawEndRow ); + if (bCont) + { + aRect.GetContDiff( nDrawStartCol, nDrawStartRow, nDrawEndCol, nDrawEndRow ); + InvertBlockMark( nDrawStartCol, nDrawStartRow, nDrawEndCol, nDrawEndRow ); + } + ShowAllCursors(); + } +#endif + UpdateSelectionOverlay(); + + nOldCurX = nCurX; + nOldCurY = nCurY; + + aViewData.GetViewShell()->UpdateInputHandler(); +// InvalidateAttribs(); + } + + if ( !bCols && !bRows ) + aHdrFunc.SetAnchorFlag( sal_False ); +} + +void ScTabView::UpdateSelectionOverlay() +{ + for (sal_uInt16 i=0; i<4; i++) + if ( pGridWin[i] && pGridWin[i]->IsVisible() ) + pGridWin[i]->UpdateSelectionOverlay(); +} + +void ScTabView::UpdateShrinkOverlay() +{ + for (sal_uInt16 i=0; i<4; i++) + if ( pGridWin[i] && pGridWin[i]->IsVisible() ) + pGridWin[i]->UpdateShrinkOverlay(); +} + +void ScTabView::UpdateAllOverlays() +{ + for (sal_uInt16 i=0; i<4; i++) + if ( pGridWin[i] && pGridWin[i]->IsVisible() ) + pGridWin[i]->UpdateAllOverlays(); +} + +//! +//! PaintBlock in zwei Methoden aufteilen: RepaintBlock und RemoveBlock o.ae. +//! + +void ScTabView::PaintBlock( sal_Bool bReset ) +{ + ScDocument* pDoc = aViewData.GetDocument(); + ScMarkData& rMark = aViewData.GetMarkData(); + SCTAB nTab = aViewData.GetTabNo(); + sal_Bool bMark = rMark.IsMarked(); + sal_Bool bMulti = rMark.IsMultiMarked(); + if (bMark || bMulti) + { + ScRange aMarkRange; + HideAllCursors(); + if (bMulti) + { + sal_Bool bFlag = rMark.GetMarkingFlag(); + rMark.SetMarking(sal_False); + rMark.MarkToMulti(); + rMark.GetMultiMarkArea(aMarkRange); + rMark.MarkToSimple(); + rMark.SetMarking(bFlag); + + bMark = rMark.IsMarked(); + bMulti = rMark.IsMultiMarked(); + } + else + rMark.GetMarkArea(aMarkRange); + + nBlockStartX = aMarkRange.aStart.Col(); + nBlockStartY = aMarkRange.aStart.Row(); + nBlockStartZ = aMarkRange.aStart.Tab(); + nBlockEndX = aMarkRange.aEnd.Col(); + nBlockEndY = aMarkRange.aEnd.Row(); + nBlockEndZ = aMarkRange.aEnd.Tab(); + + sal_Bool bDidReset = sal_False; + + if ( nTab>=nBlockStartZ && nTab<=nBlockEndZ ) + { + if ( bReset ) + { + // Invertieren beim Loeschen nur auf aktiver View + if ( aViewData.IsActive() ) + { + sal_uInt16 i; + if ( bMulti ) + { +#ifdef OLD_SELECTION_PAINT + for (i=0; i<4; i++) + if (pGridWin[i] && pGridWin[i]->IsVisible()) + pGridWin[i]->InvertSimple( nBlockStartX, nBlockStartY, + nBlockEndX, nBlockEndY, + sal_True, sal_True ); +#endif + rMark.ResetMark(); + UpdateSelectionOverlay(); + bDidReset = sal_True; + } + else + { +#ifdef OLD_SELECTION_PAINT + // (mis)use InvertBlockMark to remove all of the selection + // -> set bBlockNeg (like when removing parts of a selection) + // and convert everything to Multi + + rMark.MarkToMulti(); + sal_Bool bOld = bBlockNeg; + bBlockNeg = sal_True; + // #73130# (negative) MarkArea must be set in case of repaint + rMark.SetMarkArea( ScRange( nBlockStartX,nBlockStartY, nTab, + nBlockEndX,nBlockEndY, nTab ) ); + + InvertBlockMark( nBlockStartX, nBlockStartY, nBlockEndX, nBlockEndY ); + + bBlockNeg = bOld; +#endif + rMark.ResetMark(); + UpdateSelectionOverlay(); + bDidReset = sal_True; + } + + // repaint if controls are touched (#69680# in both cases) + // #i74768# Forms are rendered by DrawingLayer's EndDrawLayers() + static bool bSuppressControlExtraStuff(true); + + if(!bSuppressControlExtraStuff) + { + Rectangle aMMRect = pDoc->GetMMRect(nBlockStartX,nBlockStartY,nBlockEndX,nBlockEndY, nTab); + if (pDoc->HasControl( nTab, aMMRect )) + { + for (i=0; i<4; i++) + { + if (pGridWin[i] && pGridWin[i]->IsVisible()) + { + // MapMode muss logischer (1/100mm) sein !!! + pDoc->InvalidateControls( pGridWin[i], nTab, aMMRect ); + pGridWin[i]->Update(); + } + } + } + } + } + } + else + PaintMarks( nBlockStartX, nBlockStartY, nBlockEndX, nBlockEndY ); + } + + if ( bReset && !bDidReset ) + rMark.ResetMark(); + + ShowAllCursors(); + } +} + +void ScTabView::SelectAll( sal_Bool bContinue ) +{ + ScMarkData& rMark = aViewData.GetMarkData(); + SCTAB nTab = aViewData.GetTabNo(); + + if (rMark.IsMarked()) + { + ScRange aMarkRange; + rMark.GetMarkArea( aMarkRange ); + if ( aMarkRange == ScRange( 0,0,nTab, MAXCOL,MAXROW,nTab ) ) + return; + } + + DoneBlockMode( bContinue ); + InitBlockMode( 0,0,nTab ); + MarkCursor( MAXCOL,MAXROW,nTab ); + + SelectionChanged(); +} + +void ScTabView::SelectAllTables() +{ + ScDocument* pDoc = aViewData.GetDocument(); + ScMarkData& rMark = aViewData.GetMarkData(); +// SCTAB nTab = aViewData.GetTabNo(); + SCTAB nCount = pDoc->GetTableCount(); + + if (nCount>1) + { + for (SCTAB i=0; i<nCount; i++) + rMark.SelectTable( i, sal_True ); + + // Markierungen werden per Default nicht pro Tabelle gehalten +// pDoc->ExtendMarksFromTable( nTab ); + + aViewData.GetDocShell()->PostPaintExtras(); + SfxBindings& rBind = aViewData.GetBindings(); + rBind.Invalidate( FID_FILL_TAB ); + rBind.Invalidate( FID_TAB_DESELECTALL ); + } +} + +void ScTabView::DeselectAllTables() +{ + ScDocument* pDoc = aViewData.GetDocument(); + ScMarkData& rMark = aViewData.GetMarkData(); + SCTAB nTab = aViewData.GetTabNo(); + SCTAB nCount = pDoc->GetTableCount(); + + for (SCTAB i=0; i<nCount; i++) + rMark.SelectTable( i, ( i == nTab ) ); + + aViewData.GetDocShell()->PostPaintExtras(); + SfxBindings& rBind = aViewData.GetBindings(); + rBind.Invalidate( FID_FILL_TAB ); + rBind.Invalidate( FID_TAB_DESELECTALL ); +} + +sal_Bool lcl_FitsInWindow( double fScaleX, double fScaleY, sal_uInt16 nZoom, + long nWindowX, long nWindowY, ScDocument* pDoc, SCTAB nTab, + SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, + SCCOL nFixPosX, SCROW nFixPosY ) +{ + double fZoomFactor = (double)Fraction(nZoom,100); + fScaleX *= fZoomFactor; + fScaleY *= fZoomFactor; + + long nBlockX = 0; + SCCOL nCol; + for (nCol=0; nCol<nFixPosX; nCol++) + { + // for frozen panes, add both parts + sal_uInt16 nColTwips = pDoc->GetColWidth( nCol, nTab ); + if (nColTwips) + { + nBlockX += (long)(nColTwips * fScaleX); + if (nBlockX > nWindowX) + return sal_False; + } + } + for (nCol=nStartCol; nCol<=nEndCol; nCol++) + { + sal_uInt16 nColTwips = pDoc->GetColWidth( nCol, nTab ); + if (nColTwips) + { + nBlockX += (long)(nColTwips * fScaleX); + if (nBlockX > nWindowX) + return sal_False; + } + } + + long nBlockY = 0; + for (SCROW nRow = 0; nRow <= nFixPosY-1; ++nRow) + { + if (pDoc->RowHidden(nRow, nTab)) + continue; + + // for frozen panes, add both parts + sal_uInt16 nRowTwips = pDoc->GetRowHeight(nRow, nTab); + if (nRowTwips) + { + nBlockY += (long)(nRowTwips * fScaleY); + if (nBlockY > nWindowY) + return sal_False; + } + } + for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow) + { + sal_uInt16 nRowTwips = pDoc->GetRowHeight(nRow, nTab); + if (nRowTwips) + { + nBlockY += (long)(nRowTwips * fScaleY); + if (nBlockY > nWindowY) + return sal_False; + } + } + + return sal_True; +} + +sal_uInt16 ScTabView::CalcZoom( SvxZoomType eType, sal_uInt16 nOldZoom ) +{ + sal_uInt16 nZoom = 0; // Ergebnis + + switch ( eType ) + { + case SVX_ZOOM_PERCENT: // rZoom ist kein besonderer prozentualer Wert + nZoom = nOldZoom; + break; + + case SVX_ZOOM_OPTIMAL: // nZoom entspricht der optimalen Gr"o\se + { + ScMarkData& rMark = aViewData.GetMarkData(); + ScDocument* pDoc = aViewData.GetDocument(); + + if (!rMark.IsMarked() && !rMark.IsMultiMarked()) + nZoom = 100; // nothing selected + else + { + SCTAB nTab = aViewData.GetTabNo(); + ScRange aMarkRange; + if ( aViewData.GetSimpleArea( aMarkRange ) != SC_MARK_SIMPLE ) + rMark.GetMultiMarkArea( aMarkRange ); + + SCCOL nStartCol = aMarkRange.aStart.Col(); + SCROW nStartRow = aMarkRange.aStart.Row(); + SCTAB nStartTab = aMarkRange.aStart.Tab(); + SCCOL nEndCol = aMarkRange.aEnd.Col(); + SCROW nEndRow = aMarkRange.aEnd.Row(); + SCTAB nEndTab = aMarkRange.aEnd.Tab(); + + if ( nTab < nStartTab && nTab > nEndTab ) + nTab = nStartTab; + + ScSplitPos eUsedPart = aViewData.GetActivePart(); + + SCCOL nFixPosX = 0; + SCROW nFixPosY = 0; + if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX ) + { + // use right part + eUsedPart = (WhichV(eUsedPart)==SC_SPLIT_TOP) ? SC_SPLIT_TOPRIGHT : SC_SPLIT_BOTTOMRIGHT; + nFixPosX = aViewData.GetFixPosX(); + if ( nStartCol < nFixPosX ) + nStartCol = nFixPosX; + } + if ( aViewData.GetVSplitMode() == SC_SPLIT_FIX ) + { + // use bottom part + eUsedPart = (WhichH(eUsedPart)==SC_SPLIT_LEFT) ? SC_SPLIT_BOTTOMLEFT : SC_SPLIT_BOTTOMRIGHT; + nFixPosY = aViewData.GetFixPosY(); + if ( nStartRow < nFixPosY ) + nStartRow = nFixPosY; + } + + if (pGridWin[eUsedPart]) + { + // Because scale is rounded to pixels, the only reliable way to find + // the right scale is to check if a zoom fits + + Size aWinSize = pGridWin[eUsedPart]->GetOutputSizePixel(); + + // for frozen panes, use sum of both parts for calculation + + if ( nFixPosX != 0 ) + aWinSize.Width() += GetGridWidth( SC_SPLIT_LEFT ); + if ( nFixPosY != 0 ) + aWinSize.Height() += GetGridHeight( SC_SPLIT_TOP ); + + ScDocShell* pDocSh = aViewData.GetDocShell(); + double nPPTX = ScGlobal::nScreenPPTX / pDocSh->GetOutputFactor(); + double nPPTY = ScGlobal::nScreenPPTY; + + sal_uInt16 nMin = MINZOOM; + sal_uInt16 nMax = MAXZOOM; + while ( nMax > nMin ) + { + sal_uInt16 nTest = (nMin+nMax+1)/2; + if ( lcl_FitsInWindow( + nPPTX, nPPTY, nTest, aWinSize.Width(), aWinSize.Height(), + pDoc, nTab, nStartCol, nStartRow, nEndCol, nEndRow, + nFixPosX, nFixPosY ) ) + nMin = nTest; + else + nMax = nTest-1; + } + DBG_ASSERT( nMin == nMax, "Schachtelung ist falsch" ); + nZoom = nMin; + + if ( nZoom != nOldZoom ) + { + // scroll to block only in active split part + // (the part for which the size was calculated) + + if ( nStartCol <= nEndCol ) + aViewData.SetPosX( WhichH(eUsedPart), nStartCol ); + if ( nStartRow <= nEndRow ) + aViewData.SetPosY( WhichV(eUsedPart), nStartRow ); + } + } + } + } + break; + + case SVX_ZOOM_WHOLEPAGE: // nZoom entspricht der ganzen Seite oder + case SVX_ZOOM_PAGEWIDTH: // nZoom entspricht der Seitenbreite + { + SCTAB nCurTab = aViewData.GetTabNo(); + ScDocument* pDoc = aViewData.GetDocument(); + ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool(); + SfxStyleSheetBase* pStyleSheet = + pStylePool->Find( pDoc->GetPageStyle( nCurTab ), + SFX_STYLE_FAMILY_PAGE ); + + DBG_ASSERT( pStyleSheet, "PageStyle not found :-/" ); + + if ( pStyleSheet ) + { + ScPrintFunc aPrintFunc( aViewData.GetDocShell(), + aViewData.GetViewShell()->GetPrinter(sal_True), + nCurTab ); + + Size aPageSize = aPrintFunc.GetDataSize(); + + // use the size of the largest GridWin for normal split, + // or both combined for frozen panes, with the (document) size + // of the frozen part added to the page size + // (with frozen panes, the size of the individual parts + // depends on the scale that is to be calculated) + + if ( !pGridWin[SC_SPLIT_BOTTOMLEFT] ) return 0; + Size aWinSize = pGridWin[SC_SPLIT_BOTTOMLEFT]->GetOutputSizePixel(); + ScSplitMode eHMode = aViewData.GetHSplitMode(); + if ( eHMode != SC_SPLIT_NONE && pGridWin[SC_SPLIT_BOTTOMRIGHT] ) + { + long nOtherWidth = pGridWin[SC_SPLIT_BOTTOMRIGHT]-> + GetOutputSizePixel().Width(); + if ( eHMode == SC_SPLIT_FIX ) + { + aWinSize.Width() += nOtherWidth; + for ( SCCOL nCol = aViewData.GetPosX(SC_SPLIT_LEFT); + nCol < aViewData.GetFixPosX(); nCol++ ) + aPageSize.Width() += pDoc->GetColWidth( nCol, nCurTab ); + } + else if ( nOtherWidth > aWinSize.Width() ) + aWinSize.Width() = nOtherWidth; + } + ScSplitMode eVMode = aViewData.GetVSplitMode(); + if ( eVMode != SC_SPLIT_NONE && pGridWin[SC_SPLIT_TOPLEFT] ) + { + long nOtherHeight = pGridWin[SC_SPLIT_TOPLEFT]-> + GetOutputSizePixel().Height(); + if ( eVMode == SC_SPLIT_FIX ) + { + aWinSize.Height() += nOtherHeight; + aPageSize.Height() += pDoc->GetRowHeight( + aViewData.GetPosY(SC_SPLIT_TOP), + aViewData.GetFixPosY()-1, nCurTab); + } + else if ( nOtherHeight > aWinSize.Height() ) + aWinSize.Height() = nOtherHeight; + } + + double nPPTX = ScGlobal::nScreenPPTX / aViewData.GetDocShell()->GetOutputFactor(); + double nPPTY = ScGlobal::nScreenPPTY; + + long nZoomX = (long) ( aWinSize.Width() * 100 / + ( aPageSize.Width() * nPPTX ) ); + long nZoomY = (long) ( aWinSize.Height() * 100 / + ( aPageSize.Height() * nPPTY ) ); + long nNew = nZoomX; + + if (eType == SVX_ZOOM_WHOLEPAGE && nZoomY < nNew) + nNew = nZoomY; + + nZoom = (sal_uInt16) nNew; + } + } + break; + + default: + DBG_ERROR("Unknown Zoom-Revision"); + nZoom = 0; + } + + return nZoom; +} + +// wird z.B. gerufen, wenn sich das View-Fenster verschiebt: + +void ScTabView::StopMarking() +{ + ScSplitPos eActive = aViewData.GetActivePart(); + if (pGridWin[eActive]) + pGridWin[eActive]->StopMarking(); + + ScHSplitPos eH = WhichH(eActive); + if (pColBar[eH]) + pColBar[eH]->StopMarking(); + + ScVSplitPos eV = WhichV(eActive); + if (pRowBar[eV]) + pRowBar[eV]->StopMarking(); +} + +void ScTabView::HideNoteMarker() +{ + for (sal_uInt16 i=0; i<4; i++) + if (pGridWin[i] && pGridWin[i]->IsVisible()) + pGridWin[i]->HideNoteMarker(); +} + +void ScTabView::MakeDrawLayer() +{ + if (!pDrawView) + { + aViewData.GetDocShell()->MakeDrawLayer(); + + // pDrawView wird per Notify gesetzt + DBG_ASSERT(pDrawView,"ScTabView::MakeDrawLayer funktioniert nicht"); + + // #114409# + for(sal_uInt16 a(0); a < 4; a++) + { + if(pGridWin[a]) + { + pGridWin[a]->DrawLayerCreated(); + } + } + } +} + +void ScTabView::ErrorMessage( sal_uInt16 nGlobStrId ) +{ + if ( SC_MOD()->IsInExecuteDrop() ) + { + // #i28468# don't show error message when called from Drag&Drop, silently abort instead + return; + } + + StopMarking(); // falls per Focus aus MouseButtonDown aufgerufen + + Window* pParent = aViewData.GetDialogParent(); + ScWaitCursorOff aWaitOff( pParent ); + sal_Bool bFocus = pParent && pParent->HasFocus(); + + if(nGlobStrId==STR_PROTECTIONERR) + { + if(aViewData.GetDocShell()->IsReadOnly()) + { + nGlobStrId=STR_READONLYERR; + } + } + + InfoBox aBox( pParent, ScGlobal::GetRscString( nGlobStrId ) ); + aBox.Execute(); + if (bFocus) + pParent->GrabFocus(); +} + +Window* ScTabView::GetParentOrChild( sal_uInt16 nChildId ) +{ + SfxViewFrame* pViewFrm = aViewData.GetViewShell()->GetViewFrame(); + + if ( pViewFrm->HasChildWindow(nChildId) ) + { + SfxChildWindow* pChild = pViewFrm->GetChildWindow(nChildId); + if (pChild) + { + Window* pWin = pChild->GetWindow(); + if (pWin && pWin->IsVisible()) + return pWin; + } + } + + return aViewData.GetDialogParent(); +} + +void ScTabView::UpdatePageBreakData( sal_Bool bForcePaint ) +{ + ScPageBreakData* pNewData = NULL; + + if (aViewData.IsPagebreakMode()) + { + ScDocShell* pDocSh = aViewData.GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = aViewData.GetTabNo(); + + sal_uInt16 nCount = pDoc->GetPrintRangeCount(nTab); + if (!nCount) + nCount = 1; + pNewData = new ScPageBreakData(nCount); + + ScPrintFunc aPrintFunc( pDocSh, pDocSh->GetPrinter(), nTab, 0,0,NULL, NULL, pNewData ); + // ScPrintFunc fuellt im ctor die PageBreakData + if ( nCount > 1 ) + { + aPrintFunc.ResetBreaks(nTab); + pNewData->AddPages(); + } + + // Druckbereiche veraendert? + if ( bForcePaint || ( pPageBreakData && !pPageBreakData->IsEqual( *pNewData ) ) ) + PaintGrid(); + } + + delete pPageBreakData; + pPageBreakData = pNewData; +} + + + diff --git a/sc/source/ui/view/tabview3.cxx b/sc/source/ui/view/tabview3.cxx new file mode 100644 index 000000000000..19289e4cf703 --- /dev/null +++ b/sc/source/ui/view/tabview3.cxx @@ -0,0 +1,2792 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +// System - Includes ----------------------------------------------------- + + + +// INCLUDE --------------------------------------------------------------- +#include <rangelst.hxx> +#include "scitems.hxx" +#include <editeng/eeitem.hxx> + + +#include <editeng/brshitem.hxx> +#include <editeng/editview.hxx> +#include <svx/fmshell.hxx> +#include <svx/svdoole2.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/viewfrm.hxx> +#include <vcl/cursor.hxx> + +#include "tabview.hxx" +#include "tabvwsh.hxx" +#include "docsh.hxx" +#include "gridwin.hxx" +#include "olinewin.hxx" +#include "colrowba.hxx" +#include "tabcont.hxx" +#include "scmod.hxx" +#include "uiitems.hxx" +#include "sc.hrc" +#include "viewutil.hxx" +#include "editutil.hxx" +#include "inputhdl.hxx" +#include "inputwin.hxx" +#include "validat.hxx" +#include "hintwin.hxx" +#include "inputopt.hxx" +#include "rfindlst.hxx" +#include "hiranges.hxx" +#include "viewuno.hxx" +#include "chartarr.hxx" +#include "anyrefdg.hxx" +#include "dpobject.hxx" +#include "patattr.hxx" +#include "dociter.hxx" +#include "seltrans.hxx" +#include "fillinfo.hxx" +#include "AccessibilityHints.hxx" +#include "rangeutl.hxx" +#include "client.hxx" +#include "tabprotection.hxx" + +#include <com/sun/star/chart2/data/HighlightedRange.hpp> + +namespace +{ + +ScRange lcl_getSubRangeByIndex( const ScRange& rRange, sal_Int32 nIndex ) +{ + ScAddress aResult( rRange.aStart ); + + SCCOL nWidth = rRange.aEnd.Col() - rRange.aStart.Col() + 1; + SCROW nHeight = rRange.aEnd.Row() - rRange.aStart.Row() + 1; + SCTAB nDepth = rRange.aEnd.Tab() - rRange.aStart.Tab() + 1; + if( (nWidth > 0) && (nHeight > 0) && (nDepth > 0) ) + { + // row by row from first to last sheet + sal_Int32 nArea = nWidth * nHeight; + aResult.IncCol( static_cast< SCsCOL >( nIndex % nWidth ) ); + aResult.IncRow( static_cast< SCsROW >( (nIndex % nArea) / nWidth ) ); + aResult.IncTab( static_cast< SCsTAB >( nIndex / nArea ) ); + if( !rRange.In( aResult ) ) + aResult = rRange.aStart; + } + + return ScRange( aResult ); +} + +} // anonymous namespace + +using namespace com::sun::star; + +// ----------------------------------------------------------------------- + +// +// --- Public-Funktionen +// + +void ScTabView::ClickCursor( SCCOL nPosX, SCROW nPosY, sal_Bool bControl ) +{ + ScDocument* pDoc = aViewData.GetDocument(); + SCTAB nTab = aViewData.GetTabNo(); + while (pDoc->IsHorOverlapped( nPosX, nPosY, nTab )) //! ViewData !!! + --nPosX; + while (pDoc->IsVerOverlapped( nPosX, nPosY, nTab )) + --nPosY; + + sal_Bool bRefMode = SC_MOD()->IsFormulaMode(); + + if ( bRefMode ) + { + DoneRefMode( sal_False ); + + if (bControl) + SC_MOD()->AddRefEntry(); + + InitRefMode( nPosX, nPosY, nTab, SC_REFTYPE_REF ); + } + else + { + DoneBlockMode( bControl ); + aViewData.ResetOldCursor(); + SetCursor( (SCCOL) nPosX, (SCROW) nPosY ); + } +} + +void ScTabView::UpdateAutoFillMark() +{ + // single selection or cursor + ScRange aMarkRange; + sal_Bool bMarked = (aViewData.GetSimpleArea( aMarkRange ) == SC_MARK_SIMPLE); + + sal_uInt16 i; + for (i=0; i<4; i++) + if (pGridWin[i] && pGridWin[i]->IsVisible()) + pGridWin[i]->UpdateAutoFillMark( bMarked, aMarkRange ); + + for (i=0; i<2; i++) + { + if (pColBar[i] && pColBar[i]->IsVisible()) + pColBar[i]->SetMark( bMarked, aMarkRange.aStart.Col(), aMarkRange.aEnd.Col() ); + if (pRowBar[i] && pRowBar[i]->IsVisible()) + pRowBar[i]->SetMark( bMarked, aMarkRange.aStart.Row(), aMarkRange.aEnd.Row() ); + } + + // selection transfer object is checked together with AutoFill marks, + // because it has the same requirement of a single continuous block. + CheckSelectionTransfer(); // update selection transfer object +} + +void ScTabView::FakeButtonUp( ScSplitPos eWhich ) +{ + if (pGridWin[eWhich]) + pGridWin[eWhich]->FakeButtonUp(); +} + +void ScTabView::HideAllCursors() +{ + for (sal_uInt16 i=0; i<4; i++) + if (pGridWin[i]) + if (pGridWin[i]->IsVisible()) + { + Cursor* pCur = pGridWin[i]->GetCursor(); + if (pCur) + if (pCur->IsVisible()) + pCur->Hide(); + pGridWin[i]->HideCursor(); + } +} + +void ScTabView::ShowAllCursors() +{ + for (sal_uInt16 i=0; i<4; i++) + if (pGridWin[i]) + if (pGridWin[i]->IsVisible()) + { + pGridWin[i]->ShowCursor(); + + // #114409# + pGridWin[i]->CursorChanged(); + } +} + +void ScTabView::HideCursor() +{ + pGridWin[aViewData.GetActivePart()]->HideCursor(); +} + +void ScTabView::ShowCursor() +{ + pGridWin[aViewData.GetActivePart()]->ShowCursor(); + + // #114409# + pGridWin[aViewData.GetActivePart()]->CursorChanged(); +} + +void ScTabView::InvalidateAttribs() +{ + SfxBindings& rBindings = aViewData.GetBindings(); + + rBindings.Invalidate( SID_STYLE_APPLY ); + rBindings.Invalidate( SID_STYLE_FAMILY2 ); + // StarCalc kennt nur Absatz- bzw. Zellformat-Vorlagen + + rBindings.Invalidate( SID_ATTR_CHAR_FONT ); + rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT ); + rBindings.Invalidate( SID_ATTR_CHAR_COLOR ); + + rBindings.Invalidate( SID_ATTR_CHAR_WEIGHT ); + rBindings.Invalidate( SID_ATTR_CHAR_POSTURE ); + rBindings.Invalidate( SID_ATTR_CHAR_UNDERLINE ); + rBindings.Invalidate( SID_ULINE_VAL_NONE ); + rBindings.Invalidate( SID_ULINE_VAL_SINGLE ); + rBindings.Invalidate( SID_ULINE_VAL_DOUBLE ); + rBindings.Invalidate( SID_ULINE_VAL_DOTTED ); + + rBindings.Invalidate( SID_ATTR_CHAR_OVERLINE ); + + rBindings.Invalidate( SID_ALIGNLEFT ); + rBindings.Invalidate( SID_ALIGNRIGHT ); + rBindings.Invalidate( SID_ALIGNBLOCK ); + rBindings.Invalidate( SID_ALIGNCENTERHOR ); + + rBindings.Invalidate( SID_ALIGNTOP ); + rBindings.Invalidate( SID_ALIGNBOTTOM ); + rBindings.Invalidate( SID_ALIGNCENTERVER ); + + rBindings.Invalidate( SID_BACKGROUND_COLOR ); + + rBindings.Invalidate( SID_ATTR_ALIGN_LINEBREAK ); + rBindings.Invalidate( SID_NUMBER_FORMAT ); + + rBindings.Invalidate( SID_TEXTDIRECTION_LEFT_TO_RIGHT ); + rBindings.Invalidate( SID_TEXTDIRECTION_TOP_TO_BOTTOM ); + rBindings.Invalidate( SID_ATTR_PARA_LEFT_TO_RIGHT ); + rBindings.Invalidate( SID_ATTR_PARA_RIGHT_TO_LEFT ); + + // pseudo slots for Format menu + rBindings.Invalidate( SID_ALIGN_ANY_HDEFAULT ); + rBindings.Invalidate( SID_ALIGN_ANY_LEFT ); + rBindings.Invalidate( SID_ALIGN_ANY_HCENTER ); + rBindings.Invalidate( SID_ALIGN_ANY_RIGHT ); + rBindings.Invalidate( SID_ALIGN_ANY_JUSTIFIED ); + rBindings.Invalidate( SID_ALIGN_ANY_VDEFAULT ); + rBindings.Invalidate( SID_ALIGN_ANY_TOP ); + rBindings.Invalidate( SID_ALIGN_ANY_VCENTER ); + rBindings.Invalidate( SID_ALIGN_ANY_BOTTOM ); + +// rBindings.Invalidate( SID_RANGE_VALUE ); +// rBindings.Invalidate( SID_RANGE_FORMULA ); +} + +// SetCursor - Cursor setzen, zeichnen, InputWin updaten +// oder Referenz verschicken +// ohne Optimierung wegen BugId 29307 + +#ifdef _MSC_VER +#pragma optimize ( "", off ) +#endif + +void ScTabView::SetCursor( SCCOL nPosX, SCROW nPosY, sal_Bool bNew ) +{ + SCCOL nOldX = aViewData.GetCurX(); + SCROW nOldY = aViewData.GetCurY(); + + // DeactivateIP nur noch bei MarkListHasChanged + + if ( nPosX != nOldX || nPosY != nOldY || bNew ) + { + ScTabViewShell* pViewShell = aViewData.GetViewShell(); + bool bRefMode = ( pViewShell ? pViewShell->IsRefInputMode() : false ); + if ( aViewData.HasEditView( aViewData.GetActivePart() ) && !bRefMode ) // 23259 oder so + { + UpdateInputLine(); + } + + HideAllCursors(); + + aViewData.SetCurX( nPosX ); + aViewData.SetCurY( nPosY ); + + ShowAllCursors(); + + CursorPosChanged(); + } +} + +#ifdef _MSC_VER +#pragma optimize ( "", on ) +#endif + +void ScTabView::CheckSelectionTransfer() +{ + if ( aViewData.IsActive() ) // only for active view + { + ScModule* pScMod = SC_MOD(); + ScSelectionTransferObj* pOld = pScMod->GetSelectionTransfer(); + if ( pOld && pOld->GetView() == this && pOld->StillValid() ) + { + // selection not changed - nothing to do + } + else + { + ScSelectionTransferObj* pNew = ScSelectionTransferObj::CreateFromView( this ); + if ( pNew ) + { + // create new selection + + if (pOld) + pOld->ForgetView(); + + uno::Reference<datatransfer::XTransferable> xRef( pNew ); + pScMod->SetSelectionTransfer( pNew ); + pNew->CopyToSelection( GetActiveWin() ); // may delete pOld + } + else if ( pOld && pOld->GetView() == this ) + { + // remove own selection + + pOld->ForgetView(); + pScMod->SetSelectionTransfer( NULL ); + TransferableHelper::ClearSelection( GetActiveWin() ); // may delete pOld + } + // else: selection from outside: leave unchanged + } + } +} + +// Eingabezeile / Menues updaten +// CursorPosChanged ruft SelectionChanged +// SelectionChanged ruft CellContentChanged + +void ScTabView::CellContentChanged() +{ + SfxBindings& rBindings = aViewData.GetBindings(); + + rBindings.Invalidate( SID_ATTR_SIZE ); // -> Fehlermeldungen anzeigen + rBindings.Invalidate( SID_THESAURUS ); + rBindings.Invalidate( SID_HYPERLINK_GETLINK ); + + InvalidateAttribs(); // Attribut-Updates + TestHintWindow(); // Eingabemeldung (Gueltigkeit) + + aViewData.GetViewShell()->UpdateInputHandler(); +} + +void ScTabView::SelectionChanged() +{ + SfxViewFrame* pViewFrame = aViewData.GetViewShell()->GetViewFrame(); + if (pViewFrame) + { + uno::Reference<frame::XController> xController = pViewFrame->GetFrame().GetController(); + if (xController.is()) + { + ScTabViewObj* pImp = ScTabViewObj::getImplementation( xController ); + if (pImp) + pImp->SelectionChanged(); + } + } + + UpdateAutoFillMark(); // also calls CheckSelectionTransfer + + SfxBindings& rBindings = aViewData.GetBindings(); + + rBindings.Invalidate( SID_CURRENTCELL ); // -> Navigator + rBindings.Invalidate( SID_AUTO_FILTER ); // -> Menue + rBindings.Invalidate( FID_NOTE_VISIBLE ); + rBindings.Invalidate( SID_DELETE_NOTE ); + + // Funktionen, die evtl disabled werden muessen + + rBindings.Invalidate( FID_INS_ROWBRK ); + rBindings.Invalidate( FID_INS_COLBRK ); + rBindings.Invalidate( FID_DEL_ROWBRK ); + rBindings.Invalidate( FID_DEL_COLBRK ); + rBindings.Invalidate( FID_MERGE_ON ); + rBindings.Invalidate( FID_MERGE_OFF ); + rBindings.Invalidate( FID_MERGE_TOGGLE ); + rBindings.Invalidate( SID_AUTOFILTER_HIDE ); + rBindings.Invalidate( SID_UNFILTER ); +// rBindings.Invalidate( SID_IMPORT_DATA ); // jetzt wieder immer moeglich + rBindings.Invalidate( SID_REIMPORT_DATA ); + rBindings.Invalidate( SID_REFRESH_DBAREA ); + rBindings.Invalidate( SID_OUTLINE_SHOW ); + rBindings.Invalidate( SID_OUTLINE_HIDE ); + rBindings.Invalidate( SID_OUTLINE_REMOVE ); + rBindings.Invalidate( FID_FILL_TO_BOTTOM ); + rBindings.Invalidate( FID_FILL_TO_RIGHT ); + rBindings.Invalidate( FID_FILL_TO_TOP ); + rBindings.Invalidate( FID_FILL_TO_LEFT ); + rBindings.Invalidate( FID_FILL_SERIES ); + rBindings.Invalidate( SID_SCENARIOS ); + rBindings.Invalidate( SID_AUTOFORMAT ); + rBindings.Invalidate( SID_OPENDLG_TABOP ); + rBindings.Invalidate( SID_DATA_SELECT ); + + rBindings.Invalidate( SID_CUT ); + rBindings.Invalidate( SID_COPY ); + rBindings.Invalidate( SID_PASTE ); + rBindings.Invalidate( SID_PASTE_SPECIAL ); + + rBindings.Invalidate( FID_INS_ROW ); + rBindings.Invalidate( FID_INS_COLUMN ); + rBindings.Invalidate( FID_INS_CELL ); + rBindings.Invalidate( FID_INS_CELLSDOWN ); + rBindings.Invalidate( FID_INS_CELLSRIGHT ); + + rBindings.Invalidate( FID_CHG_COMMENT ); + + // nur wegen Zellschutz: + + rBindings.Invalidate( SID_CELL_FORMAT_RESET ); + rBindings.Invalidate( SID_DELETE ); + rBindings.Invalidate( SID_DELETE_CONTENTS ); + rBindings.Invalidate( FID_DELETE_CELL ); + rBindings.Invalidate( FID_CELL_FORMAT ); + rBindings.Invalidate( SID_ENABLE_HYPHENATION ); + rBindings.Invalidate( SID_INSERT_POSTIT ); + rBindings.Invalidate( SID_CHARMAP ); + rBindings.Invalidate( SID_OPENDLG_FUNCTION ); +// rBindings.Invalidate( FID_CONDITIONAL_FORMAT ); + rBindings.Invalidate( SID_OPENDLG_CONDFRMT ); + 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)); + + CellContentChanged(); +} + +void ScTabView::CursorPosChanged() +{ + sal_Bool bRefMode = SC_MOD()->IsFormulaMode(); + if ( !bRefMode ) // Abfrage, damit RefMode bei Tabellenwechsel funktioniert + aViewData.GetDocShell()->Broadcast( SfxSimpleHint( FID_KILLEDITVIEW ) ); + + // Broadcast, damit andere Views des Dokuments auch umschalten + + ScDocument* pDoc = aViewData.GetDocument(); + bool bDP = NULL != pDoc->GetDPAtCursor( + aViewData.GetCurX(), aViewData.GetCurY(), aViewData.GetTabNo() ); + aViewData.GetViewShell()->SetPivotShell(bDP); + + // UpdateInputHandler jetzt in CellContentChanged + + SelectionChanged(); + + aViewData.SetTabStartCol( SC_TABSTART_NONE ); +} + +void ScTabView::TestHintWindow() +{ + // show input help window and list drop-down button for validity + + sal_Bool bListValButton = sal_False; + ScAddress aListValPos; + + ScDocument* pDoc = aViewData.GetDocument(); + const SfxUInt32Item* pItem = (const SfxUInt32Item*) + pDoc->GetAttr( aViewData.GetCurX(), + aViewData.GetCurY(), + aViewData.GetTabNo(), + ATTR_VALIDDATA ); + if ( pItem->GetValue() ) + { + const ScValidationData* pData = pDoc->GetValidationEntry( pItem->GetValue() ); + DBG_ASSERT(pData,"ValidationData nicht gefunden"); + String aTitle, aMessage; + if ( pData && pData->GetInput( aTitle, aMessage ) && aMessage.Len() > 0 ) + { + //! Abfrage, ob an gleicher Stelle !!!! + + DELETEZ(pInputHintWindow); + + ScSplitPos eWhich = aViewData.GetActivePart(); + Window* pWin = pGridWin[eWhich]; + SCCOL nCol = aViewData.GetCurX(); + SCROW nRow = aViewData.GetCurY(); + Point aPos = aViewData.GetScrPos( nCol, nRow, eWhich ); + Size aWinSize = pWin->GetOutputSizePixel(); + // Cursor sichtbar? + if ( nCol >= aViewData.GetPosX(WhichH(eWhich)) && + nRow >= aViewData.GetPosY(WhichV(eWhich)) && + aPos.X() < aWinSize.Width() && aPos.Y() < aWinSize.Height() ) + { + aPos += pWin->GetPosPixel(); // Position auf Frame + long nSizeXPix; + long nSizeYPix; + aViewData.GetMergeSizePixel( nCol, nRow, nSizeXPix, nSizeYPix ); + + // HintWindow anlegen, bestimmt seine Groesse selbst + pInputHintWindow = new ScHintWindow( pFrameWin, aTitle, aMessage ); + Size aHintSize = pInputHintWindow->GetSizePixel(); + Size aFrameWinSize = pFrameWin->GetOutputSizePixel(); + + // passende Position finden + // erster Versuch: unter dem Cursor + Point aHintPos( aPos.X() + nSizeXPix / 2, aPos.Y() + nSizeYPix + 3 ); + if ( aHintPos.Y() + aHintSize.Height() > aFrameWinSize.Height() ) + { + // zweiter Versuch: rechts vom Cursor + aHintPos = Point( aPos.X() + nSizeXPix + 3, aPos.Y() + nSizeYPix / 2 ); + if ( aHintPos.X() + aHintSize.Width() > aFrameWinSize.Width() ) + { + // dritter Versuch: ueber dem Cursor + aHintPos = Point( aPos.X() + nSizeXPix / 2, + aPos.Y() - aHintSize.Height() - 3 ); + if ( aHintPos.Y() < 0 ) + { + // oben und unten kein Platz - dann Default und abschneiden + aHintPos = Point( aPos.X() + nSizeXPix / 2, aPos.Y() + nSizeYPix + 3 ); + aHintSize.Height() = aFrameWinSize.Height() - aHintPos.Y(); + pInputHintWindow->SetSizePixel( aHintSize ); + } + } + } + + // X anpassen + if ( aHintPos.X() + aHintSize.Width() > aFrameWinSize.Width() ) + aHintPos.X() = aFrameWinSize.Width() - aHintSize.Width(); + // Y anpassen + if ( aHintPos.Y() + aHintSize.Height() > aFrameWinSize.Height() ) + aHintPos.Y() = aFrameWinSize.Height() - aHintSize.Height(); + + pInputHintWindow->SetPosPixel( aHintPos ); + pInputHintWindow->ToTop(); + pInputHintWindow->Show(); + } + } + else + DELETEZ(pInputHintWindow); + + // list drop-down button + if ( pData && pData->HasSelectionList() ) + { + aListValPos.Set( aViewData.GetCurX(), aViewData.GetCurY(), aViewData.GetTabNo() ); + bListValButton = sal_True; + } + } + else + DELETEZ(pInputHintWindow); + + for ( sal_uInt16 i=0; i<4; i++ ) + if ( pGridWin[i] && pGridWin[i]->IsVisible() ) + pGridWin[i]->UpdateListValPos( bListValButton, aListValPos ); +} + +void ScTabView::RemoveHintWindow() +{ + DELETEZ(pInputHintWindow); +} + + +// find window that should not be over the cursor +Window* lcl_GetCareWin(SfxViewFrame* pViewFrm) +{ + //! auch Spelling ??? (dann beim Aufruf Membervariable setzen) + + // Suchen & Ersetzen + if ( pViewFrm->HasChildWindow(SID_SEARCH_DLG) ) + { + SfxChildWindow* pChild = pViewFrm->GetChildWindow(SID_SEARCH_DLG); + if (pChild) + { + Window* pWin = pChild->GetWindow(); + if (pWin && pWin->IsVisible()) + return pWin; + } + } + + // Aenderungen uebernehmen + if ( pViewFrm->HasChildWindow(FID_CHG_ACCEPT) ) + { + SfxChildWindow* pChild = pViewFrm->GetChildWindow(FID_CHG_ACCEPT); + if (pChild) + { + Window* pWin = pChild->GetWindow(); + if (pWin && pWin->IsVisible()) + return pWin; + } + } + + return NULL; +} + + // + // Bildschirm an Cursorposition anpassen + // + +void ScTabView::AlignToCursor( SCsCOL nCurX, SCsROW nCurY, ScFollowMode eMode, + const ScSplitPos* pWhich ) +{ + // + // aktiven Teil umschalten jetzt hier + // + + ScSplitPos eActive = aViewData.GetActivePart(); + ScHSplitPos eActiveX = WhichH(eActive); + ScVSplitPos eActiveY = WhichV(eActive); + sal_Bool bHFix = (aViewData.GetHSplitMode() == SC_SPLIT_FIX); + sal_Bool bVFix = (aViewData.GetVSplitMode() == SC_SPLIT_FIX); + if (bHFix) + if (eActiveX == SC_SPLIT_LEFT && nCurX >= (SCsCOL)aViewData.GetFixPosX()) + { + ActivatePart( (eActiveY==SC_SPLIT_TOP) ? SC_SPLIT_TOPRIGHT : SC_SPLIT_BOTTOMRIGHT ); + eActiveX = SC_SPLIT_RIGHT; + } + if (bVFix) + if (eActiveY == SC_SPLIT_TOP && nCurY >= (SCsROW)aViewData.GetFixPosY()) + { + ActivatePart( (eActiveX==SC_SPLIT_LEFT) ? SC_SPLIT_BOTTOMLEFT : SC_SPLIT_BOTTOMRIGHT ); + eActiveY = SC_SPLIT_BOTTOM; + } + + // + // eigentliches Align + // + + if ( eMode != SC_FOLLOW_NONE ) + { + ScSplitPos eAlign; + if (pWhich) + eAlign = *pWhich; + else + eAlign = aViewData.GetActivePart(); + ScHSplitPos eAlignX = WhichH(eAlign); + ScVSplitPos eAlignY = WhichV(eAlign); + + SCsCOL nDeltaX = (SCsCOL) aViewData.GetPosX(eAlignX); + SCsROW nDeltaY = (SCsROW) aViewData.GetPosY(eAlignY); + SCsCOL nSizeX = (SCsCOL) aViewData.VisibleCellsX(eAlignX); + SCsROW nSizeY = (SCsROW) aViewData.VisibleCellsY(eAlignY); + + long nCellSizeX; + long nCellSizeY; + if ( nCurX >= 0 && nCurY >= 0 ) + aViewData.GetMergeSizePixel( (SCCOL)nCurX, (SCROW)nCurY, nCellSizeX, nCellSizeY ); + else + nCellSizeX = nCellSizeY = 0; + Size aScrSize = aViewData.GetScrSize(); + long nSpaceX = ( aScrSize.Width() - nCellSizeX ) / 2; + long nSpaceY = ( aScrSize.Height() - nCellSizeY ) / 2; + // nSpaceY: desired start position of cell for FOLLOW_JUMP, modified if dialog interferes + + sal_Bool bForceNew = sal_False; // force new calculation of JUMP position (vertical only) + + // VisibleCellsY == CellsAtY( GetPosY( eWhichY ), 1, eWhichY ) + + //------------------------------------------------------------------------------- + // falls z.B. Suchen-Dialog offen ist, Cursor nicht hinter den Dialog stellen + // wenn moeglich, die Zeile mit dem Cursor oberhalb oder unterhalb des Dialogs + + //! nicht, wenn schon komplett sichtbar + + if ( eMode == SC_FOLLOW_JUMP ) + { + Window* pCare = lcl_GetCareWin( aViewData.GetViewShell()->GetViewFrame() ); + if (pCare) + { + sal_Bool bLimit = sal_False; + Rectangle aDlgPixel; + Size aWinSize; + Window* pWin = GetActiveWin(); + if (pWin) + { + aDlgPixel = pCare->GetWindowExtentsRelative( pWin ); + aWinSize = pWin->GetOutputSizePixel(); + // ueberdeckt der Dialog das GridWin? + if ( aDlgPixel.Right() >= 0 && aDlgPixel.Left() < aWinSize.Width() ) + { + if ( nCurX < nDeltaX || nCurX >= nDeltaX+nSizeX || + nCurY < nDeltaY || nCurY >= nDeltaY+nSizeY ) + bLimit = sal_True; // es wird sowieso gescrollt + else + { + // Cursor ist auf dem Bildschirm + Point aStart = aViewData.GetScrPos( nCurX, nCurY, eAlign ); + long nCSX, nCSY; + aViewData.GetMergeSizePixel( nCurX, nCurY, nCSX, nCSY ); + Rectangle aCursor( aStart, Size( nCSX, nCSY ) ); + if ( aCursor.IsOver( aDlgPixel ) ) + bLimit = sal_True; // Zelle vom Dialog ueberdeckt + } + } + } + + if (bLimit) + { + sal_Bool bBottom = sal_False; + long nTopSpace = aDlgPixel.Top(); + long nBotSpace = aWinSize.Height() - aDlgPixel.Bottom(); + if ( nBotSpace > 0 && nBotSpace > nTopSpace ) + { + long nDlgBot = aDlgPixel.Bottom(); + SCsCOL nWPosX; + SCsROW nWPosY; + aViewData.GetPosFromPixel( 0,nDlgBot, eAlign, nWPosX, nWPosY ); + ++nWPosY; // unter der letzten betroffenen Zelle + + SCsROW nDiff = nWPosY - nDeltaY; + if ( nCurY >= nDiff ) // Pos. kann nicht negativ werden + { + nSpaceY = nDlgBot + ( nBotSpace - nCellSizeY ) / 2; + bBottom = sal_True; + bForceNew = sal_True; + } + } + if ( !bBottom && nTopSpace > 0 ) + { + nSpaceY = ( nTopSpace - nCellSizeY ) / 2; + bForceNew = sal_True; + } + } + } + } + //------------------------------------------------------------------------------- + + SCsCOL nNewDeltaX = nDeltaX; + SCsROW nNewDeltaY = nDeltaY; + sal_Bool bDoLine = sal_False; + + switch (eMode) + { + case SC_FOLLOW_JUMP: + if ( nCurX < nDeltaX || nCurX >= nDeltaX+nSizeX ) + { + nNewDeltaX = nCurX - static_cast<SCsCOL>(aViewData.CellsAtX( nCurX, -1, eAlignX, static_cast<sal_uInt16>(nSpaceX) )); + if (nNewDeltaX < 0) nNewDeltaX = 0; + nSizeX = (SCsCOL) aViewData.CellsAtX( nNewDeltaX, 1, eAlignX ); + } + if ( nCurY < nDeltaY || nCurY >= nDeltaY+nSizeY || bForceNew ) + { + nNewDeltaY = nCurY - static_cast<SCsROW>(aViewData.CellsAtY( nCurY, -1, eAlignY, static_cast<sal_uInt16>(nSpaceY) )); + if (nNewDeltaY < 0) nNewDeltaY = 0; + nSizeY = (SCsROW) aViewData.CellsAtY( nNewDeltaY, 1, eAlignY ); + } + bDoLine = sal_True; + break; + + case SC_FOLLOW_LINE: + bDoLine = sal_True; + break; + + case SC_FOLLOW_FIX: + if ( nCurX < nDeltaX || nCurX >= nDeltaX+nSizeX ) + { + nNewDeltaX = nDeltaX + nCurX - aViewData.GetCurX(); + if (nNewDeltaX < 0) nNewDeltaX = 0; + nSizeX = (SCsCOL) aViewData.CellsAtX( nNewDeltaX, 1, eAlignX ); + } + if ( nCurY < nDeltaY || nCurY >= nDeltaY+nSizeY ) + { + nNewDeltaY = nDeltaY + nCurY - aViewData.GetCurY(); + if (nNewDeltaY < 0) nNewDeltaY = 0; + nSizeY = (SCsROW) aViewData.CellsAtY( nNewDeltaY, 1, eAlignY ); + } + + // like old version of SC_FOLLOW_JUMP: + + if ( nCurX < nNewDeltaX || nCurX >= nNewDeltaX+nSizeX ) + { + nNewDeltaX = nCurX - (nSizeX / 2); + if (nNewDeltaX < 0) nNewDeltaX = 0; + nSizeX = (SCsCOL) aViewData.CellsAtX( nNewDeltaX, 1, eAlignX ); + } + if ( nCurY < nNewDeltaY || nCurY >= nNewDeltaY+nSizeY ) + { + nNewDeltaY = nCurY - (nSizeY / 2); + if (nNewDeltaY < 0) nNewDeltaY = 0; + nSizeY = (SCsROW) aViewData.CellsAtY( nNewDeltaY, 1, eAlignY ); + } + + bDoLine = sal_True; + break; + + case SC_FOLLOW_NONE: + break; + default: + DBG_ERROR("Falscher Cursormodus"); + break; + } + + if (bDoLine) + { + while ( nCurX >= nNewDeltaX+nSizeX ) + { + nNewDeltaX = nCurX-nSizeX+1; + ScDocument* pDoc = aViewData.GetDocument(); + SCTAB nTab = aViewData.GetTabNo(); + while ( nNewDeltaX < MAXCOL && !pDoc->GetColWidth( nNewDeltaX, nTab ) ) + ++nNewDeltaX; + nSizeX = (SCsCOL) aViewData.CellsAtX( nNewDeltaX, 1, eAlignX ); + } + while ( nCurY >= nNewDeltaY+nSizeY ) + { + nNewDeltaY = nCurY-nSizeY+1; + ScDocument* pDoc = aViewData.GetDocument(); + SCTAB nTab = aViewData.GetTabNo(); + while ( nNewDeltaY < MAXROW && !pDoc->GetRowHeight( nNewDeltaY, nTab ) ) + ++nNewDeltaY; + nSizeY = (SCsROW) aViewData.CellsAtY( nNewDeltaY, 1, eAlignY ); + } + if ( nCurX < nNewDeltaX ) nNewDeltaX = nCurX; + if ( nCurY < nNewDeltaY ) nNewDeltaY = nCurY; + } + + if ( nNewDeltaX != nDeltaX ) + nSizeX = (SCsCOL) aViewData.CellsAtX( nNewDeltaX, 1, eAlignX ); + if (nNewDeltaX+nSizeX-1 > MAXCOL) nNewDeltaX = MAXCOL-nSizeX+1; + if (nNewDeltaX < 0) nNewDeltaX = 0; + + if ( nNewDeltaY != nDeltaY ) + nSizeY = (SCsROW) aViewData.CellsAtY( nNewDeltaY, 1, eAlignY ); + if (nNewDeltaY+nSizeY-1 > MAXROW) nNewDeltaY = MAXROW-nSizeY+1; + if (nNewDeltaY < 0) nNewDeltaY = 0; + + if ( nNewDeltaX != nDeltaX ) ScrollX( nNewDeltaX - nDeltaX, eAlignX ); + if ( nNewDeltaY != nDeltaY ) ScrollY( nNewDeltaY - nDeltaY, eAlignY ); + } + + // + // nochmal aktiven Teil umschalten + // + + if (bHFix) + if (eActiveX == SC_SPLIT_RIGHT && nCurX < (SCsCOL)aViewData.GetFixPosX()) + { + ActivatePart( (eActiveY==SC_SPLIT_TOP) ? SC_SPLIT_TOPLEFT : SC_SPLIT_BOTTOMLEFT ); + eActiveX = SC_SPLIT_LEFT; + } + if (bVFix) + if (eActiveY == SC_SPLIT_BOTTOM && nCurY < (SCsROW)aViewData.GetFixPosY()) + { + ActivatePart( (eActiveX==SC_SPLIT_LEFT) ? SC_SPLIT_TOPLEFT : SC_SPLIT_TOPRIGHT ); + eActiveY = SC_SPLIT_TOP; + } +} + +sal_Bool ScTabView::SelMouseButtonDown( const MouseEvent& rMEvt ) +{ + sal_Bool bRet = sal_False; + + // #i3875# *Hack* + sal_Bool bMod1Locked = aViewData.GetViewShell()->GetLockedModifiers() & KEY_MOD1 ? sal_True : sal_False; + aViewData.SetSelCtrlMouseClick( rMEvt.IsMod1() || bMod1Locked ); + + if ( pSelEngine ) + { + bMoveIsShift = rMEvt.IsShift(); + bRet = pSelEngine->SelMouseButtonDown( rMEvt ); + bMoveIsShift = sal_False; + } + + aViewData.SetSelCtrlMouseClick( sal_False ); // #i3875# *Hack* + + return bRet; +} + + // + // MoveCursor - mit Anpassung des Bildausschnitts + // + +void ScTabView::MoveCursorAbs( SCsCOL nCurX, SCsROW nCurY, ScFollowMode eMode, + sal_Bool bShift, sal_Bool bControl, sal_Bool bKeepOld, sal_Bool bKeepSel ) +{ + if (!bKeepOld) + aViewData.ResetOldCursor(); + + if (nCurX < 0) nCurX = 0; + if (nCurY < 0) nCurY = 0; + if (nCurX > MAXCOL) nCurX = MAXCOL; + if (nCurY > MAXROW) nCurY = MAXROW; + + HideAllCursors(); + + if ( bShift && bNewStartIfMarking && IsBlockMode() ) + { + // used for ADD selection mode: start a new block from the cursor position + DoneBlockMode( sal_True ); + InitBlockMode( aViewData.GetCurX(), aViewData.GetCurY(), aViewData.GetTabNo(), sal_True ); + } + + // aktiven Teil umschalten jetzt in AlignToCursor + + AlignToCursor( nCurX, nCurY, eMode ); + //! auf OS/2: SC_FOLLOW_JUMP statt SC_FOLLOW_LINE, um Nachlaufen zu verhindern ??? + + if (bKeepSel) + SetCursor( nCurX, nCurY ); // Markierung stehenlassen + else + { + sal_Bool bSame = ( nCurX == aViewData.GetCurX() && nCurY == aViewData.GetCurY() ); + bMoveIsShift = bShift; + pSelEngine->CursorPosChanging( bShift, bControl ); + bMoveIsShift = sal_False; + aFunctionSet.SetCursorAtCell( nCurX, nCurY, sal_False ); + + // Wenn der Cursor nicht bewegt wurde, muss das SelectionChanged fuer das + // Aufheben der Selektion hier einzeln passieren: + if (bSame) + SelectionChanged(); + } + + ShowAllCursors(); +} + +void ScTabView::MoveCursorRel( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode, + sal_Bool bShift, sal_Bool bKeepSel ) +{ + ScDocument* pDoc = aViewData.GetDocument(); + SCTAB nTab = aViewData.GetTabNo(); + + bool bSkipProtected = false, bSkipUnprotected = false; + ScTableProtection* pProtect = pDoc->GetTabProtection(nTab); + if ( pProtect && pProtect->isProtected() ) + { + bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS); + bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS); + } + + if ( bSkipProtected && bSkipUnprotected ) + return; + + SCsCOL nOldX; + SCsROW nOldY; + SCsCOL nCurX; + SCsROW nCurY; + if ( aViewData.IsRefMode() ) + { + nOldX = (SCsCOL) aViewData.GetRefEndX(); + nOldY = (SCsROW) aViewData.GetRefEndY(); + nCurX = nOldX + nMovX; + nCurY = nOldY + nMovY; + } + else + { + nOldX = (SCsCOL) aViewData.GetCurX(); + nOldY = (SCsROW) aViewData.GetCurY(); + nCurX = (nMovX != 0) ? nOldX+nMovX : (SCsCOL) aViewData.GetOldCurX(); + nCurY = (nMovY != 0) ? nOldY+nMovY : (SCsROW) aViewData.GetOldCurY(); + } + + sal_Bool bSkipCell = sal_False; + aViewData.ResetOldCursor(); + + if (nMovX != 0 && VALIDCOLROW(nCurX,nCurY)) + { + sal_Bool bHFlip = sal_False; + do + { + SCCOL nLastCol = -1; + bSkipCell = pDoc->ColHidden(nCurX, nTab, nLastCol) || pDoc->IsHorOverlapped( nCurX, nCurY, nTab ); + if (bSkipProtected && !bSkipCell) + bSkipCell = pDoc->HasAttrib(nCurX, nCurY, nTab, nCurX, nCurY, nTab, HASATTR_PROTECTED); + if (bSkipUnprotected && !bSkipCell) + bSkipCell = !pDoc->HasAttrib(nCurX, nCurY, nTab, nCurX, nCurY, nTab, HASATTR_PROTECTED); + + if (bSkipCell) + { + if ( nCurX<=0 || nCurX>=MAXCOL ) + { + if (bHFlip) + { + nCurX = nOldX; + bSkipCell = sal_False; + } + else + { + nMovX = -nMovX; + if (nMovX > 0) ++nCurX; else --nCurX; // zuruecknehmen + bHFlip = sal_True; + } + } + else + if (nMovX > 0) ++nCurX; else --nCurX; + } + } + while (bSkipCell); + + if (pDoc->IsVerOverlapped( nCurX, nCurY, nTab )) + { + aViewData.SetOldCursor( nCurX,nCurY ); + while (pDoc->IsVerOverlapped( nCurX, nCurY, nTab )) + --nCurY; + } + } + + if (nMovY != 0 && VALIDCOLROW(nCurX,nCurY)) + { + sal_Bool bVFlip = sal_False; + do + { + SCROW nLastRow = -1; + bSkipCell = pDoc->RowHidden(nCurY, nTab, nLastRow) || pDoc->IsVerOverlapped( nCurX, nCurY, nTab ); + if (bSkipProtected && !bSkipCell) + bSkipCell = pDoc->HasAttrib(nCurX, nCurY, nTab, nCurX, nCurY, nTab, HASATTR_PROTECTED); + if (bSkipUnprotected && !bSkipCell) + bSkipCell = !pDoc->HasAttrib(nCurX, nCurY, nTab, nCurX, nCurY, nTab, HASATTR_PROTECTED); + + if (bSkipCell) + { + if ( nCurY<=0 || nCurY>=MAXROW ) + { + if (bVFlip) + { + nCurY = nOldY; + bSkipCell = sal_False; + } + else + { + nMovY = -nMovY; + if (nMovY > 0) ++nCurY; else --nCurY; // zuruecknehmen + bVFlip = sal_True; + } + } + else + if (nMovY > 0) ++nCurY; else --nCurY; + } + } + while (bSkipCell); + + if (pDoc->IsHorOverlapped( nCurX, nCurY, nTab )) + { + aViewData.SetOldCursor( nCurX,nCurY ); + while (pDoc->IsHorOverlapped( nCurX, nCurY, nTab )) + --nCurX; + } + } + + MoveCursorAbs( nCurX, nCurY, eMode, bShift, sal_False, sal_True, bKeepSel ); +} + +void ScTabView::MoveCursorPage( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode, sal_Bool bShift, sal_Bool bKeepSel ) +{ + SCCOL nCurX; + SCROW nCurY; + aViewData.GetMoveCursor( nCurX,nCurY ); + + ScSplitPos eWhich = aViewData.GetActivePart(); + ScHSplitPos eWhichX = WhichH( eWhich ); + ScVSplitPos eWhichY = WhichV( eWhich ); + + SCsCOL nPageX; + SCsROW nPageY; + if (nMovX >= 0) + nPageX = ((SCsCOL) aViewData.CellsAtX( nCurX, 1, eWhichX )) * nMovX; + else + nPageX = ((SCsCOL) aViewData.CellsAtX( nCurX, -1, eWhichX )) * nMovX; + + if (nMovY >= 0) + nPageY = ((SCsROW) aViewData.CellsAtY( nCurY, 1, eWhichY )) * nMovY; + else + nPageY = ((SCsROW) aViewData.CellsAtY( nCurY, -1, eWhichY )) * nMovY; + + if (nMovX != 0 && nPageX == 0) nPageX = (nMovX>0) ? 1 : -1; + if (nMovY != 0 && nPageY == 0) nPageY = (nMovY>0) ? 1 : -1; + + MoveCursorRel( nPageX, nPageY, eMode, bShift, bKeepSel ); +} + +void ScTabView::MoveCursorArea( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode, sal_Bool bShift, sal_Bool bKeepSel ) +{ + SCCOL nCurX; + SCROW nCurY; + aViewData.GetMoveCursor( nCurX,nCurY ); + SCCOL nNewX = nCurX; + SCROW nNewY = nCurY; + + ScDocument* pDoc = aViewData.GetDocument(); + SCTAB nTab = aViewData.GetTabNo(); + + // FindAreaPos kennt nur -1 oder 1 als Richtung + + SCsCOLROW i; + if ( nMovX > 0 ) + for ( i=0; i<nMovX; i++ ) + pDoc->FindAreaPos( nNewX, nNewY, nTab, 1, 0 ); + if ( nMovX < 0 ) + for ( i=0; i<-nMovX; i++ ) + pDoc->FindAreaPos( nNewX, nNewY, nTab, -1, 0 ); + if ( nMovY > 0 ) + for ( i=0; i<nMovY; i++ ) + pDoc->FindAreaPos( nNewX, nNewY, nTab, 0, 1 ); + if ( nMovY < 0 ) + for ( i=0; i<-nMovY; i++ ) + pDoc->FindAreaPos( nNewX, nNewY, nTab, 0, -1 ); + + if (eMode==SC_FOLLOW_JUMP) // unten/rechts nicht zuviel grau anzeigen + { + if (nMovX != 0 && nNewX == MAXCOL) + eMode = SC_FOLLOW_LINE; + if (nMovY != 0 && nNewY == MAXROW) + eMode = SC_FOLLOW_LINE; + } + + MoveCursorRel( ((SCsCOL)nNewX)-(SCsCOL)nCurX, ((SCsROW)nNewY)-(SCsROW)nCurY, eMode, bShift, bKeepSel ); +} + +void ScTabView::MoveCursorEnd( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode, sal_Bool bShift, sal_Bool bKeepSel ) +{ + ScDocument* pDoc = aViewData.GetDocument(); + SCTAB nTab = aViewData.GetTabNo(); + + SCCOL nCurX; + SCROW nCurY; + aViewData.GetMoveCursor( nCurX,nCurY ); + SCCOL nNewX = nCurX; + SCROW nNewY = nCurY; + + SCCOL nUsedX = 0; + SCROW nUsedY = 0; + if ( nMovX > 0 || nMovY > 0 ) + pDoc->GetPrintArea( nTab, nUsedX, nUsedY ); // Ende holen + + if (nMovX<0) + nNewX=0; + else if (nMovX>0) + nNewX=nUsedX; // letzter benutzter Bereich + + if (nMovY<0) + nNewY=0; + else if (nMovY>0) + nNewY=nUsedY; + + aViewData.ResetOldCursor(); + MoveCursorRel( ((SCsCOL)nNewX)-(SCsCOL)nCurX, ((SCsROW)nNewY)-(SCsROW)nCurY, eMode, bShift, bKeepSel ); +} + +void ScTabView::MoveCursorScreen( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode, sal_Bool bShift ) +{ + ScDocument* pDoc = aViewData.GetDocument(); + SCTAB nTab = aViewData.GetTabNo(); + + SCCOL nCurX; + SCROW nCurY; + aViewData.GetMoveCursor( nCurX,nCurY ); + SCCOL nNewX = nCurX; + SCROW nNewY = nCurY; + + ScSplitPos eWhich = aViewData.GetActivePart(); + SCCOL nPosX = aViewData.GetPosX( WhichH(eWhich) ); + SCROW nPosY = aViewData.GetPosY( WhichV(eWhich) ); + + SCCOL nAddX = aViewData.VisibleCellsX( WhichH(eWhich) ); + if (nAddX != 0) + --nAddX; + SCROW nAddY = aViewData.VisibleCellsY( WhichV(eWhich) ); + if (nAddY != 0) + --nAddY; + + if (nMovX<0) + nNewX=nPosX; + else if (nMovX>0) + nNewX=nPosX+nAddX; + + if (nMovY<0) + nNewY=nPosY; + else if (nMovY>0) + nNewY=nPosY+nAddY; + +// aViewData.ResetOldCursor(); + aViewData.SetOldCursor( nNewX,nNewY ); + + while (pDoc->IsHorOverlapped( nNewX, nNewY, nTab )) + --nNewX; + while (pDoc->IsVerOverlapped( nNewX, nNewY, nTab )) + --nNewY; + + MoveCursorAbs( nNewX, nNewY, eMode, bShift, sal_False, sal_True ); +} + +void ScTabView::MoveCursorEnter( sal_Bool bShift ) // bShift -> hoch/runter +{ + const ScInputOptions& rOpt = SC_MOD()->GetInputOptions(); + if (!rOpt.GetMoveSelection()) + { + aViewData.UpdateInputHandler(sal_True); + return; + } + + SCsCOL nMoveX = 0; + SCsROW nMoveY = 0; + switch ((ScDirection)rOpt.GetMoveDir()) + { + case DIR_BOTTOM: + nMoveY = bShift ? -1 : 1; + break; + case DIR_RIGHT: + nMoveX = bShift ? -1 : 1; + break; + case DIR_TOP: + nMoveY = bShift ? 1 : -1; + break; + case DIR_LEFT: + nMoveX = bShift ? 1 : -1; + break; + } + + ScMarkData& rMark = aViewData.GetMarkData(); + if (rMark.IsMarked() || rMark.IsMultiMarked()) + { + SCCOL nCurX; + SCROW nCurY; + aViewData.GetMoveCursor( nCurX,nCurY ); + SCCOL nNewX = nCurX; + SCROW nNewY = nCurY; + SCTAB nTab = aViewData.GetTabNo(); + + ScDocument* pDoc = aViewData.GetDocument(); + pDoc->GetNextPos( nNewX,nNewY, nTab, nMoveX,nMoveY, sal_True,sal_False, rMark ); + + MoveCursorRel( ((SCsCOL)nNewX)-(SCsCOL)nCurX, ((SCsROW)nNewY)-(SCsROW)nCurY, + SC_FOLLOW_LINE, sal_False, sal_True ); + + // update input line even if cursor was not moved + if ( nNewX == nCurX && nNewY == nCurY ) + aViewData.UpdateInputHandler(sal_True); + } + else + { + if ( nMoveY != 0 && !nMoveX ) + { + // nach Tab und Enter wieder zur Ausgangsspalte + SCCOL nTabCol = aViewData.GetTabStartCol(); + if (nTabCol != SC_TABSTART_NONE) + { + SCCOL nCurX; + SCROW nCurY; + aViewData.GetMoveCursor( nCurX,nCurY ); + nMoveX = ((SCsCOL)nTabCol)-(SCsCOL)nCurX; + } + } + + MoveCursorRel( nMoveX,nMoveY, SC_FOLLOW_LINE, sal_False ); + } +} + + +sal_Bool ScTabView::MoveCursorKeyInput( const KeyEvent& rKeyEvent ) +{ + const KeyCode& rKCode = rKeyEvent.GetKeyCode(); + + enum { MOD_NONE, MOD_CTRL, MOD_ALT, MOD_BOTH } eModifier = + rKCode.IsMod1() ? + (rKCode.IsMod2() ? MOD_BOTH : MOD_CTRL) : + (rKCode.IsMod2() ? MOD_ALT : MOD_NONE); + + sal_Bool bSel = rKCode.IsShift(); + sal_uInt16 nCode = rKCode.GetCode(); + + // CURSOR keys + SCsCOL nDX = 0; + SCsROW nDY = 0; + switch( nCode ) + { + case KEY_LEFT: nDX = -1; break; + case KEY_RIGHT: nDX = 1; break; + case KEY_UP: nDY = -1; break; + case KEY_DOWN: nDY = 1; break; + } + if( nDX != 0 || nDY != 0 ) + { + switch( eModifier ) + { + case MOD_NONE: MoveCursorRel( nDX, nDY, SC_FOLLOW_LINE, bSel ); break; + case MOD_CTRL: MoveCursorArea( nDX, nDY, SC_FOLLOW_JUMP, bSel ); break; + default: + { + // added to avoid warnings + } + } + // always sal_True to suppress changes of col/row size (ALT+CURSOR) + return sal_True; + } + + // PAGEUP/PAGEDOWN + if( (nCode == KEY_PAGEUP) || (nCode == KEY_PAGEDOWN) ) + { + nDX = (nCode == KEY_PAGEUP) ? -1 : 1; + switch( eModifier ) + { + case MOD_NONE: MoveCursorPage( 0, static_cast<SCsCOLROW>(nDX), SC_FOLLOW_FIX, bSel ); break; + case MOD_ALT: MoveCursorPage( nDX, 0, SC_FOLLOW_FIX, bSel ); break; + case MOD_CTRL: SelectNextTab( nDX ); break; + default: + { + // added to avoid warnings + } + } + return sal_True; + } + + // HOME/END + if( (nCode == KEY_HOME) || (nCode == KEY_END) ) + { + nDX = (nCode == KEY_HOME) ? -1 : 1; + ScFollowMode eMode = (nCode == KEY_HOME) ? SC_FOLLOW_LINE : SC_FOLLOW_JUMP; + switch( eModifier ) + { + case MOD_NONE: MoveCursorEnd( nDX, 0, eMode, bSel ); break; + case MOD_CTRL: MoveCursorEnd( nDX, static_cast<SCsCOLROW>(nDX), eMode, bSel ); break; + default: + { + // added to avoid warnings + } + } + return sal_True; + } + + return sal_False; +} + + + // naechste/vorherige nicht geschuetzte Zelle +void ScTabView::FindNextUnprot( sal_Bool bShift, sal_Bool bInSelection ) +{ + short nMove = bShift ? -1 : 1; + + ScMarkData& rMark = aViewData.GetMarkData(); + sal_Bool bMarked = bInSelection && (rMark.IsMarked() || rMark.IsMultiMarked()); + + SCCOL nCurX; + SCROW nCurY; + aViewData.GetMoveCursor( nCurX,nCurY ); + SCCOL nNewX = nCurX; + SCROW nNewY = nCurY; + SCTAB nTab = aViewData.GetTabNo(); + + ScDocument* pDoc = aViewData.GetDocument(); + pDoc->GetNextPos( nNewX,nNewY, nTab, nMove,0, bMarked,sal_True, rMark ); + + SCCOL nTabCol = aViewData.GetTabStartCol(); + if ( nTabCol == SC_TABSTART_NONE ) + nTabCol = nCurX; // auf diese Spalte zurueck bei Enter + + MoveCursorRel( ((SCsCOL)nNewX)-(SCsCOL)nCurX, ((SCsROW)nNewY)-(SCsROW)nCurY, + SC_FOLLOW_LINE, sal_False, sal_True ); + + // in MoveCursorRel wird die TabCol zurueckgesetzt... + aViewData.SetTabStartCol( nTabCol ); +} + +void ScTabView::MarkColumns() +{ + SCCOL nStartCol; + SCCOL nEndCol; + + ScMarkData& rMark = aViewData.GetMarkData(); + if (rMark.IsMarked()) + { + ScRange aMarkRange; + rMark.GetMarkArea( aMarkRange ); + nStartCol = aMarkRange.aStart.Col(); + nEndCol = aMarkRange.aEnd.Col(); + } + else + { + SCROW nDummy; + aViewData.GetMoveCursor( nStartCol, nDummy ); + nEndCol=nStartCol; + } + + SCTAB nTab = aViewData.GetTabNo(); + DoneBlockMode(); + InitBlockMode( nStartCol,0, nTab ); + MarkCursor( nEndCol,MAXROW, nTab ); + SelectionChanged(); +} + +void ScTabView::MarkRows() +{ + SCROW nStartRow; + SCROW nEndRow; + + ScMarkData& rMark = aViewData.GetMarkData(); + if (rMark.IsMarked()) + { + ScRange aMarkRange; + rMark.GetMarkArea( aMarkRange ); + nStartRow = aMarkRange.aStart.Row(); + nEndRow = aMarkRange.aEnd.Row(); + } + else + { + SCCOL nDummy; + aViewData.GetMoveCursor( nDummy, nStartRow ); + nEndRow=nStartRow; + } + + SCTAB nTab = aViewData.GetTabNo(); + DoneBlockMode(); + InitBlockMode( 0,nStartRow, nTab ); + MarkCursor( MAXCOL,nEndRow, nTab ); + SelectionChanged(); +} + +void ScTabView::MarkDataArea( sal_Bool bIncludeCursor ) +{ + ScDocument* pDoc = aViewData.GetDocument(); + SCTAB nTab = aViewData.GetTabNo(); + SCCOL nStartCol = aViewData.GetCurX(); + SCROW nStartRow = aViewData.GetCurY(); + SCCOL nEndCol = nStartCol; + SCROW nEndRow = nStartRow; + + pDoc->GetDataArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow, bIncludeCursor, false ); + + HideAllCursors(); + DoneBlockMode(); + InitBlockMode( nStartCol, nStartRow, nTab ); + MarkCursor( nEndCol, nEndRow, nTab ); + ShowAllCursors(); + + SelectionChanged(); +} + +void ScTabView::MarkMatrixFormula() +{ + ScDocument* pDoc = aViewData.GetDocument(); + ScAddress aCursor( aViewData.GetCurX(), aViewData.GetCurY(), aViewData.GetTabNo() ); + ScRange aMatrix; + if ( pDoc->GetMatrixFormulaRange( aCursor, aMatrix ) ) + { + MarkRange( aMatrix, sal_False ); // cursor is already within the range + } +} + +void ScTabView::MarkRange( const ScRange& rRange, sal_Bool bSetCursor, sal_Bool bContinue ) +{ + SCTAB nTab = rRange.aStart.Tab(); + SetTabNo( nTab ); + + HideAllCursors(); + DoneBlockMode( bContinue ); // bContinue==sal_True -> clear old mark + if (bSetCursor) // Wenn Cursor gesetzt wird, immer auch alignen + { + SCCOL nAlignX = rRange.aStart.Col(); + SCROW nAlignY = rRange.aStart.Row(); + if ( rRange.aStart.Col() == 0 && rRange.aEnd.Col() == MAXCOL ) + nAlignX = aViewData.GetPosX(WhichH(aViewData.GetActivePart())); + if ( rRange.aStart.Row() == 0 && rRange.aEnd.Row() == MAXROW ) + nAlignY = aViewData.GetPosY(WhichV(aViewData.GetActivePart())); + AlignToCursor( nAlignX, nAlignY, SC_FOLLOW_JUMP ); + } + InitBlockMode( rRange.aStart.Col(), rRange.aStart.Row(), nTab ); + MarkCursor( rRange.aEnd.Col(), rRange.aEnd.Row(), nTab ); + if (bSetCursor) + { + SCCOL nPosX = rRange.aStart.Col(); + SCROW nPosY = rRange.aStart.Row(); + ScDocument* pDoc = aViewData.GetDocument(); + + while (pDoc->IsHorOverlapped( nPosX, nPosY, nTab )) //! ViewData !!! + --nPosX; + while (pDoc->IsVerOverlapped( nPosX, nPosY, nTab )) + --nPosY; + + aViewData.ResetOldCursor(); + SetCursor( nPosX, nPosY ); + } + ShowAllCursors(); + + SelectionChanged(); +} + +void ScTabView::Unmark() +{ + ScMarkData& rMark = aViewData.GetMarkData(); + if ( rMark.IsMarked() || rMark.IsMultiMarked() ) + { + SCCOL nCurX; + SCROW nCurY; + aViewData.GetMoveCursor( nCurX,nCurY ); + MoveCursorAbs( nCurX, nCurY, SC_FOLLOW_NONE, sal_False, sal_False ); + + SelectionChanged(); + } +} + +void ScTabView::SetMarkData( const ScMarkData& rNew ) +{ + DoneBlockMode(); + InitOwnBlockMode(); + aViewData.GetMarkData() = rNew; + + MarkDataChanged(); +} + +void ScTabView::MarkDataChanged() +{ + // has to be called after making direct changes to mark data (not via MarkCursor etc) + + UpdateSelectionOverlay(); +} + +void ScTabView::SelectNextTab( short nDir, sal_Bool bExtendSelection ) +{ + if (!nDir) return; + DBG_ASSERT( nDir==-1 || nDir==1, "SelectNextTab: falscher Wert"); + + ScDocument* pDoc = aViewData.GetDocument(); + SCTAB nTab = aViewData.GetTabNo(); + if (nDir<0) + { + if (!nTab) return; + --nTab; + while (!pDoc->IsVisible(nTab)) + { + if (!nTab) return; + --nTab; + } + } + else + { + SCTAB nCount = pDoc->GetTableCount(); + ++nTab; + if (nTab >= nCount) return; + while (!pDoc->IsVisible(nTab)) + { + ++nTab; + if (nTab >= nCount) return; + } + } + + SetTabNo( nTab, sal_False, bExtendSelection ); + PaintExtras(); +} + + +// SetTabNo - angezeigte Tabelle + +void ScTabView::SetTabNo( SCTAB nTab, sal_Bool bNew, sal_Bool bExtendSelection, bool bSameTabButMoved ) +{ + if ( !ValidTab(nTab) ) + { + DBG_ERROR("SetTabNo: falsche Tabelle"); + return; + } + + if ( nTab != aViewData.GetTabNo() || bNew ) + { + // #57724# Die FormShell moechte vor dem Umschalten benachrichtigt werden + FmFormShell* pFormSh = aViewData.GetViewShell()->GetFormShell(); + if (pFormSh) + { + sal_Bool bAllowed = sal::static_int_cast<sal_Bool>( pFormSh->PrepareClose( sal_True ) ); + if (!bAllowed) + { + //! Fehlermeldung? oder macht das die FormShell selber? + //! Fehler-Flag zurueckgeben und Aktionen abbrechen + + return; // Die FormShell sagt, es kann nicht umgeschaltet werden + } + } + + // nicht InputEnterHandler wegen Referenzeingabe ! + + ScDocument* pDoc = aViewData.GetDocument(); + pDoc->MakeTable( nTab ); + + // Update pending row heights before switching the sheet, so Reschedule from the progress bar + // doesn't paint the new sheet with old heights + aViewData.GetDocShell()->UpdatePendingRowHeights( nTab ); + + SCTAB nTabCount = pDoc->GetTableCount(); + SCTAB nOldPos = nTab; + while (!pDoc->IsVisible(nTab)) // naechste sichtbare suchen + { + sal_Bool bUp = (nTab>=nOldPos); + if (bUp) + { + ++nTab; + if (nTab>=nTabCount) + { + nTab = nOldPos; + bUp = sal_False; + } + } + + if (!bUp) + { + if (nTab != 0) + --nTab; + else + { + DBG_ERROR("keine sichtbare Tabelle"); + pDoc->SetVisible( 0, sal_True ); + } + } + } + + // #i71490# Deselect drawing objects before changing the sheet number in view data, + // so the handling of notes still has the sheet selected on which the notes are. + DrawDeselectAll(); + + ScModule* pScMod = SC_MOD(); + sal_Bool bRefMode = pScMod->IsFormulaMode(); + if ( !bRefMode ) // Abfrage, damit RefMode bei Tabellenwechsel funktioniert + { + DoneBlockMode(); + pSelEngine->Reset(); // reset all flags, including locked modifiers + aViewData.SetRefTabNo( nTab ); + } + + ScSplitPos eOldActive = aViewData.GetActivePart(); // before switching + sal_Bool bFocus = pGridWin[eOldActive]->HasFocus(); + + aViewData.SetTabNo( nTab ); + // UpdateShow noch vor SetCursor, damit UpdateAutoFillMark die richtigen + // Fenster findet (wird aus SetCursor gerufen) + UpdateShow(); + aViewData.ResetOldCursor(); + SetCursor( aViewData.GetCurX(), aViewData.GetCurY(), sal_True ); + + SfxBindings& rBindings = aViewData.GetBindings(); + ScMarkData& rMark = aViewData.GetMarkData(); + + bool bAllSelected = true; + for (SCTAB nSelTab = 0; nSelTab < nTabCount; ++nSelTab) + { + if (!pDoc->IsVisible(nSelTab) || rMark.GetTableSelect(nSelTab)) + { + if (nTab == nSelTab) + // This tab is already in selection. Keep the current + // selection. + bExtendSelection = true; + } + else + { + bAllSelected = false; + if (bExtendSelection) + // We got what we need. No need to stay in the loop. + break; + } + } + if (bAllSelected && !bNew) + // #i6327# if all tables are selected, a selection event (#i6330#) will deselect all + // (not if called with bNew to update settings) + bExtendSelection = false; + + if (bExtendSelection) + rMark.SelectTable( nTab, sal_True ); + else + { + rMark.SelectOneTable( nTab ); + rBindings.Invalidate( FID_FILL_TAB ); + rBindings.Invalidate( FID_TAB_DESELECTALL ); + } + + bool bUnoRefDialog = pScMod->IsRefDialogOpen() && pScMod->GetCurRefDlgId() == WID_SIMPLE_REF; + + // recalc zoom-dependent values (before TabChanged, before UpdateEditViewPos) + RefreshZoom(); + UpdateVarZoom(); + + if ( bRefMode ) // hide EditView if necessary (after aViewData.SetTabNo !) + { + for ( sal_uInt16 i=0; i<4; i++ ) + if ( pGridWin[i] ) + if ( pGridWin[i]->IsVisible() ) + pGridWin[i]->UpdateEditViewPos(); + } + + TabChanged( bSameTabButMoved ); // DrawView + + aViewData.GetViewShell()->WindowChanged(); // falls das aktive Fenster anders ist + if ( !bUnoRefDialog ) + aViewData.GetViewShell()->DisconnectAllClients(); // important for floating frames + else + { + // hide / show inplace client + + ScClient* pClient = static_cast<ScClient*>(aViewData.GetViewShell()->GetIPClient()); + if ( pClient && pClient->IsObjectInPlaceActive() ) + { + Rectangle aObjArea = pClient->GetObjArea(); + if ( nTab == aViewData.GetRefTabNo() ) + { + // move to its original position + + SdrOle2Obj* pDrawObj = pClient->GetDrawObj(); + if ( pDrawObj ) + { + Rectangle aRect = pDrawObj->GetLogicRect(); + MapMode aMapMode( MAP_100TH_MM ); + Size aOleSize = pDrawObj->GetOrigObjSize( &aMapMode ); + aRect.SetSize( aOleSize ); + aObjArea = aRect; + } + } + else + { + // move to an invisible position + + aObjArea.SetPos( Point( 0, -2*aObjArea.GetHeight() ) ); + } + pClient->SetObjArea( aObjArea ); + } + } + + if ( bFocus && aViewData.GetActivePart() != eOldActive && !bRefMode ) + ActiveGrabFocus(); // grab focus to the pane that's active now + + // Fixierungen + + sal_Bool bResize = sal_False; + if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX ) + if (aViewData.UpdateFixX()) + bResize = sal_True; + if ( aViewData.GetVSplitMode() == SC_SPLIT_FIX ) + if (aViewData.UpdateFixY()) + bResize = sal_True; + if (bResize) + RepeatResize(); + InvalidateSplit(); + + if ( aViewData.IsPagebreakMode() ) + UpdatePageBreakData(); //! asynchron ?? + + // #53551# Form-Layer muss den sichtbaren Ausschnitt der neuen Tabelle kennen + // dafuer muss hier schon der MapMode stimmen + for (sal_uInt16 i=0; i<4; i++) + if (pGridWin[i]) + pGridWin[i]->SetMapMode( pGridWin[i]->GetDrawMapMode() ); + SetNewVisArea(); + + PaintGrid(); + PaintTop(); + PaintLeft(); + PaintExtras(); + + DoResize( aBorderPos, aFrameSize ); + rBindings.Invalidate( SID_DELETE_PRINTAREA ); // Menue + rBindings.Invalidate( FID_DEL_MANUALBREAKS ); + rBindings.Invalidate( FID_RESET_PRINTZOOM ); + rBindings.Invalidate( SID_STATUS_DOCPOS ); // Statusbar + rBindings.Invalidate( SID_STATUS_PAGESTYLE ); // Statusbar + rBindings.Invalidate( SID_CURRENTTAB ); // Navigator + rBindings.Invalidate( SID_STYLE_FAMILY2 ); // Gestalter + rBindings.Invalidate( SID_STYLE_FAMILY4 ); // Gestalter + rBindings.Invalidate( SID_TABLES_COUNT ); + + if(pScMod->IsRefDialogOpen()) + { + sal_uInt16 nCurRefDlgId=pScMod->GetCurRefDlgId(); + SfxViewFrame* pViewFrm = aViewData.GetViewShell()->GetViewFrame(); + SfxChildWindow* pChildWnd = pViewFrm->GetChildWindow( nCurRefDlgId ); + if ( pChildWnd ) + { + IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetWindow()); + pRefDlg->ViewShellChanged(NULL); + } + } + } +} + +// +// Paint-Funktionen - nur fuer diese View +// + +void ScTabView::MakeEditView( ScEditEngineDefaulter* pEngine, SCCOL nCol, SCROW nRow ) +{ + DrawDeselectAll(); + + if (pDrawView) + DrawEnableAnim( sal_False ); + + EditView* pSpellingView = aViewData.GetSpellingView(); + + for (sal_uInt16 i=0; i<4; i++) + if (pGridWin[i]) + if ( pGridWin[i]->IsVisible() && !aViewData.HasEditView((ScSplitPos)i) ) + { + ScHSplitPos eHWhich = WhichH( (ScSplitPos) i ); + ScVSplitPos eVWhich = WhichV( (ScSplitPos) i ); + SCCOL nScrX = aViewData.GetPosX( eHWhich ); + SCROW nScrY = aViewData.GetPosY( eVWhich ); + + sal_Bool bPosVisible = + ( nCol >= nScrX && nCol <= nScrX + aViewData.VisibleCellsX(eHWhich) + 1 && + nRow >= nScrY && nRow <= nScrY + aViewData.VisibleCellsY(eVWhich) + 1 ); + + // #102421# for the active part, create edit view even if outside the visible area, + // so input isn't lost (and the edit view may be scrolled into the visible area) + + // #i26433# during spelling, the spelling view must be active + if ( bPosVisible || aViewData.GetActivePart() == (ScSplitPos) i || + ( pSpellingView && aViewData.GetEditView((ScSplitPos) i) == pSpellingView ) ) + { + pGridWin[i]->HideCursor(); + + pGridWin[i]->DeleteCursorOverlay(); + pGridWin[i]->DeleteAutoFillOverlay(); + + // flush OverlayManager before changing MapMode to text edit + pGridWin[i]->flushOverlayManager(); + + // MapMode must be set after HideCursor + pGridWin[i]->SetMapMode(aViewData.GetLogicMode()); + + aViewData.SetEditEngine( (ScSplitPos) i, pEngine, pGridWin[i], nCol, nRow ); + + if ( !bPosVisible ) + { + // move the edit view area to the real (possibly negative) position, + // or hide if completely above or left of the window + pGridWin[i]->UpdateEditViewPos(); + } + } + } + + if (aViewData.GetViewShell()->HasAccessibilityObjects()) + aViewData.GetViewShell()->BroadcastAccessibility(SfxSimpleHint(SC_HINT_ACC_ENTEREDITMODE)); +} + +void ScTabView::UpdateEditView() +{ + ScSplitPos eActive = aViewData.GetActivePart(); + for (sal_uInt16 i=0; i<4; i++) + if (aViewData.HasEditView( (ScSplitPos) i )) + { + EditView* pEditView = aViewData.GetEditView( (ScSplitPos) i ); + aViewData.SetEditEngine( (ScSplitPos) i, + static_cast<ScEditEngineDefaulter*>(pEditView->GetEditEngine()), + pGridWin[i], GetViewData()->GetCurX(), GetViewData()->GetCurY() ); + if ( (ScSplitPos)i == eActive ) + pEditView->ShowCursor( sal_False ); + } +} + +void ScTabView::KillEditView( sal_Bool bNoPaint ) +{ + sal_uInt16 i; + SCCOL nCol1 = aViewData.GetEditStartCol(); + SCROW nRow1 = aViewData.GetEditStartRow(); + SCCOL nCol2 = aViewData.GetEditEndCol(); + SCROW nRow2 = aViewData.GetEditEndRow(); + sal_Bool bPaint[4]; + sal_Bool bNotifyAcc(false); + + sal_Bool bExtended = nRow1 != nRow2; // Col wird sowieso bis zum Ende gezeichnet + sal_Bool bAtCursor = nCol1 <= aViewData.GetCurX() && + nCol2 >= aViewData.GetCurX() && + nRow1 == aViewData.GetCurY(); + for (i=0; i<4; i++) + { + bPaint[i] = aViewData.HasEditView( (ScSplitPos) i ); + if (bPaint[i]) + bNotifyAcc = true; + } + + // #108931#; notify accessibility before all things happen + if ((bNotifyAcc) && (aViewData.GetViewShell()->HasAccessibilityObjects())) + aViewData.GetViewShell()->BroadcastAccessibility(SfxSimpleHint(SC_HINT_ACC_LEAVEEDITMODE)); + + aViewData.ResetEditView(); + for (i=0; i<4; i++) + if (pGridWin[i] && bPaint[i]) + if (pGridWin[i]->IsVisible()) + { + pGridWin[i]->ShowCursor(); + + pGridWin[i]->SetMapMode(pGridWin[i]->GetDrawMapMode()); + + // #i73567# the cell still has to be repainted + if (bExtended || ( bAtCursor && !bNoPaint )) + { + pGridWin[i]->Draw( nCol1, nRow1, nCol2, nRow2 ); + pGridWin[i]->UpdateSelectionOverlay(); + } + } + + if (pDrawView) + DrawEnableAnim( sal_True ); + + // GrabFocus immer dann, wenn diese View aktiv ist und + // die Eingabezeile den Focus hat + + sal_Bool bGrabFocus = sal_False; + if (aViewData.IsActive()) + { + ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl(); + if ( pInputHdl ) + { + ScInputWindow* pInputWin = pInputHdl->GetInputWindow(); + if (pInputWin && pInputWin->IsInputActive()) + bGrabFocus = sal_True; + } + } + + if (bGrabFocus) + { +// So soll es gemacht werden, damit der Sfx es mitbekommt, klappt aber nicht: +//! aViewData.GetViewShell()->GetViewFrame()->GetWindow().GrabFocus(); +// deshalb erstmal so: + GetActiveWin()->GrabFocus(); + } + + // Cursor-Abfrage erst nach GrabFocus + + for (i=0; i<4; i++) + if (pGridWin[i] && pGridWin[i]->IsVisible()) + { + Cursor* pCur = pGridWin[i]->GetCursor(); + if (pCur && pCur->IsVisible()) + pCur->Hide(); + + if(bPaint[i]) + { + pGridWin[i]->UpdateCursorOverlay(); + pGridWin[i]->UpdateAutoFillOverlay(); + // pGridWin[i]->UpdateAllOverlays(); + } + } +} + +void ScTabView::UpdateFormulas() +{ + if ( aViewData.GetDocument()->IsAutoCalcShellDisabled() ) + return ; + + sal_uInt16 i; + for (i=0; i<4; i++) + if (pGridWin[i]) + if (pGridWin[i]->IsVisible()) + pGridWin[i]->UpdateFormulas(); + + if ( aViewData.IsPagebreakMode() ) + UpdatePageBreakData(); //! asynchron + + UpdateHeaderWidth(); + + // if in edit mode, adjust edit view area because widths/heights may have changed + if ( aViewData.HasEditView( aViewData.GetActivePart() ) ) + UpdateEditView(); +} + +// PaintArea -Block neu zeichnen + +void ScTabView::PaintArea( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, + ScUpdateMode eMode ) +{ + sal_uInt16 i; + SCCOL nCol1; + SCROW nRow1; + SCCOL nCol2; + SCROW nRow2; + + PutInOrder( nStartCol, nEndCol ); + PutInOrder( nStartRow, nEndRow ); + + for (i=0; i<4; i++) + if (pGridWin[i]) + if (pGridWin[i]->IsVisible()) + { + ScHSplitPos eHWhich = WhichH( (ScSplitPos) i ); + ScVSplitPos eVWhich = WhichV( (ScSplitPos) i ); + sal_Bool bOut = sal_False; + + nCol1 = nStartCol; + nRow1 = nStartRow; + nCol2 = nEndCol; + nRow2 = nEndRow; + + SCCOL nScrX = aViewData.GetPosX( eHWhich ); + SCROW nScrY = aViewData.GetPosY( eVWhich ); + if (nCol1 < nScrX) nCol1 = nScrX; + if (nCol2 < nScrX) + { + if ( eMode == SC_UPDATE_ALL ) // #91240# for UPDATE_ALL, paint anyway + nCol2 = nScrX; // (because of extending strings to the right) + else + bOut = sal_True; // completely outside the window + } + if (nRow1 < nScrY) nRow1 = nScrY; + if (nRow2 < nScrY) bOut = sal_True; + + SCCOL nLastX = nScrX + aViewData.VisibleCellsX( eHWhich ) + 1; + SCROW nLastY = nScrY + aViewData.VisibleCellsY( eVWhich ) + 1; + if (nCol1 > nLastX) bOut = sal_True; + if (nCol2 > nLastX) nCol2 = nLastX; + if (nRow1 > nLastY) bOut = sal_True; + if (nRow2 > nLastY) nRow2 = nLastY; + + if (!bOut) + { + if ( eMode == SC_UPDATE_CHANGED ) + pGridWin[i]->Draw( nCol1, nRow1, nCol2, nRow2, eMode ); + else // ALL oder MARKS + { + sal_Bool bLayoutRTL = aViewData.GetDocument()->IsLayoutRTL( aViewData.GetTabNo() ); + long nLayoutSign = bLayoutRTL ? -1 : 1; + + Point aStart = aViewData.GetScrPos( nCol1, nRow1, (ScSplitPos) i ); + Point aEnd = aViewData.GetScrPos( nCol2+1, nRow2+1, (ScSplitPos) i ); + if ( eMode == SC_UPDATE_ALL ) + aEnd.X() = bLayoutRTL ? 0 : (pGridWin[i]->GetOutputSizePixel().Width()); + aEnd.X() -= nLayoutSign; + aEnd.Y() -= 1; + + // #i85232# include area below cells (could be done in GetScrPos?) + if ( eMode == SC_UPDATE_ALL && nRow2 >= MAXROW ) + aEnd.Y() = pGridWin[i]->GetOutputSizePixel().Height(); + + sal_Bool bShowChanges = sal_True; //! ... + if (bShowChanges) + { + aStart.X() -= nLayoutSign; // include change marks + aStart.Y() -= 1; + } + + sal_Bool bMarkClipped = aViewData.GetOptions().GetOption( VOPT_CLIPMARKS ); + if (bMarkClipped) + { + // dazu muesste ScColumn::IsEmptyBlock optimiert werden + // (auf Search() umstellen) + //!if ( nCol1 > 0 && !aViewData.GetDocument()->IsBlockEmpty( + //! aViewData.GetTabNo(), + //! 0, nRow1, nCol1-1, nRow2 ) ) + { + long nMarkPixel = (long)( SC_CLIPMARK_SIZE * aViewData.GetPPTX() ); + aStart.X() -= nMarkPixel * nLayoutSign; + if (!bShowChanges) + aStart.X() -= nLayoutSign; // cell grid + } + } + + pGridWin[i]->Invalidate( pGridWin[i]->PixelToLogic( Rectangle( aStart,aEnd ) ) ); + } + } + } + + // #i79909# Calling UpdateAllOverlays here isn't necessary and would lead to overlay calls from a timer, + // with a wrong MapMode if editing in a cell (reference input). + // #i80499# Overlays need updates in a lot of cases, e.g. changing row/column size, + // or showing/hiding outlines. TODO: selections in inactive windows are vanishing. + // #i84689# With relative conditional formats, PaintArea may be called often (for each changed cell), + // so UpdateAllOverlays was moved to ScTabViewShell::Notify and is called only if PAINT_LEFT/PAINT_TOP + // is set (width or height changed). +} + +void ScTabView::PaintRangeFinder( long nNumber ) +{ + ScInputHandler* pHdl = SC_MOD()->GetInputHdl( aViewData.GetViewShell() ); + if (pHdl) + { + ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList(); + if ( pRangeFinder && pRangeFinder->GetDocName() == aViewData.GetDocShell()->GetTitle() ) + { + SCTAB nTab = aViewData.GetTabNo(); + sal_uInt16 nCount = (sal_uInt16)pRangeFinder->Count(); + for (sal_uInt16 i=0; i<nCount; i++) + if ( nNumber < 0 || nNumber == i ) + { + ScRangeFindData* pData = pRangeFinder->GetObject(i); + if (pData) + { + ScRange aRef = pData->aRef; + aRef.Justify(); // Justify fuer die Abfragen unten + + if ( aRef.aStart == aRef.aEnd ) //! Tab ignorieren? + aViewData.GetDocument()->ExtendMerge(aRef); + + if ( aRef.aStart.Tab() >= nTab && aRef.aEnd.Tab() <= nTab ) + { + SCCOL nCol1 = aRef.aStart.Col(); + SCROW nRow1 = aRef.aStart.Row(); + SCCOL nCol2 = aRef.aEnd.Col(); + SCROW nRow2 = aRef.aEnd.Row(); + + // wegnehmen -> Repaint + // SC_UPDATE_MARKS: Invalidate, nicht bis zum Zeilenende + + sal_Bool bHiddenEdge = sal_False; + SCROW nTmp; + ScDocument* pDoc = aViewData.GetDocument(); + SCCOL nLastCol = -1; + while ( nCol1 > 0 && pDoc->ColHidden(nCol1, nTab, nLastCol) ) + { + --nCol1; + bHiddenEdge = sal_True; + } + while ( nCol2 < MAXCOL && pDoc->ColHidden(nCol2, nTab, nLastCol) ) + { + ++nCol2; + bHiddenEdge = sal_True; + } + nTmp = pDoc->LastVisibleRow(0, nRow1, nTab); + if (!ValidRow(nTmp)) + nTmp = 0; + if (nTmp < nRow1) + { + nRow1 = nTmp; + bHiddenEdge = sal_True; + } + nTmp = pDoc->FirstVisibleRow(nRow2, MAXROW, nTab); + if (!ValidRow(nTmp)) + nTmp = MAXROW; + if (nTmp > nRow2) + { + nRow2 = nTmp; + bHiddenEdge = sal_True; + } + + if ( nCol2 - nCol1 > 1 && nRow2 - nRow1 > 1 && !bHiddenEdge ) + { + // nur an den Raendern entlang + PaintArea( nCol1, nRow1, nCol2, nRow1, SC_UPDATE_MARKS ); + PaintArea( nCol1, nRow1+1, nCol1, nRow2-1, SC_UPDATE_MARKS ); + PaintArea( nCol2, nRow1+1, nCol2, nRow2-1, SC_UPDATE_MARKS ); + PaintArea( nCol1, nRow2, nCol2, nRow2, SC_UPDATE_MARKS ); + } + else // alles am Stueck + PaintArea( nCol1, nRow1, nCol2, nRow2, SC_UPDATE_MARKS ); + } + } + } + } + } +} + +// fuer Chart-Daten-Markierung + +void ScTabView::AddHighlightRange( const ScRange& rRange, const Color& rColor ) +{ + if (!pHighlightRanges) + pHighlightRanges = new ScHighlightRanges; + pHighlightRanges->Insert( new ScHighlightEntry( rRange, rColor ) ); + + SCTAB nTab = aViewData.GetTabNo(); + if ( nTab >= rRange.aStart.Tab() && nTab <= rRange.aEnd.Tab() ) + PaintArea( rRange.aStart.Col(), rRange.aStart.Row(), + rRange.aEnd.Col(), rRange.aEnd.Row(), SC_UPDATE_MARKS ); +} + +void ScTabView::ClearHighlightRanges() +{ + if (pHighlightRanges) + { + ScHighlightRanges* pTemp = pHighlightRanges; + pHighlightRanges = NULL; // Repaint ohne Highlight + + SCTAB nTab = aViewData.GetTabNo(); + sal_uLong nCount = pTemp->Count(); + for (sal_uLong i=0; i<nCount; i++) + { + ScHighlightEntry* pEntry = pTemp->GetObject( i ); + if (pEntry) + { + ScRange aRange = pEntry->aRef; + if ( nTab >= aRange.aStart.Tab() && nTab <= aRange.aEnd.Tab() ) + PaintArea( aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Col(), aRange.aEnd.Row(), SC_UPDATE_MARKS ); + } + } + delete pTemp; + } +} + +void ScTabView::DoChartSelection( + const uno::Sequence< chart2::data::HighlightedRange > & rHilightRanges ) +{ + ClearHighlightRanges(); + + for( sal_Int32 i=0; i<rHilightRanges.getLength(); ++i ) + { + Color aSelColor( rHilightRanges[i].PreferredColor ); + ScRangeList aRangeList; + ScDocument* pDoc = aViewData.GetDocShell()->GetDocument(); + if( ScRangeStringConverter::GetRangeListFromString( + aRangeList, rHilightRanges[i].RangeRepresentation, pDoc, pDoc->GetAddressConvention(), ';' )) + { + for ( ScRangePtr p = aRangeList.First(); p; p = aRangeList.Next()) + { + if( rHilightRanges[i].Index == - 1 ) + AddHighlightRange( *p, aSelColor ); + else + AddHighlightRange( lcl_getSubRangeByIndex( *p, rHilightRanges[i].Index ), aSelColor ); + } + } + } +} + +// DrawDragRect - Drag&Drop-Rechteck zeichnen (XOR) + +//UNUSED2008-05 void ScTabView::DrawDragRect( SCCOL nStartX, SCROW nStartY, SCCOL nEndX, SCROW nEndY, +//UNUSED2008-05 ScSplitPos ePos ) +//UNUSED2008-05 { +//UNUSED2008-05 if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX || aViewData.GetVSplitMode() == SC_SPLIT_FIX ) +//UNUSED2008-05 { +//UNUSED2008-05 for (sal_uInt16 i=0; i<4; i++) +//UNUSED2008-05 if (pGridWin[i]) +//UNUSED2008-05 if (pGridWin[i]->IsVisible()) +//UNUSED2008-05 pGridWin[i]->DrawDragRect( nStartX, nStartY, nEndX, nEndY ); +//UNUSED2008-05 } +//UNUSED2008-05 else +//UNUSED2008-05 pGridWin[ePos]->DrawDragRect( nStartX, nStartY, nEndX, nEndY ); +//UNUSED2008-05 } +//UNUSED2008-05 +//UNUSED2008-05 // PaintCell - einzelne Zelle neu zeichnen +//UNUSED2008-05 +//UNUSED2008-05 void ScTabView::PaintCell( SCCOL nCol, SCROW nRow, SCTAB nTab ) +//UNUSED2008-05 { +//UNUSED2008-05 if ( aViewData.GetTabNo() == nTab ) +//UNUSED2008-05 { +//UNUSED2008-05 sal_uInt16 i; +//UNUSED2008-05 for (i=0; i<4; i++) +//UNUSED2008-05 if (pGridWin[i]) +//UNUSED2008-05 if (pGridWin[i]->IsVisible()) +//UNUSED2008-05 pGridWin[i]->Draw( nCol, nRow, nCol, nRow ); +//UNUSED2008-05 } +//UNUSED2008-05 } +//UNUSED2008-05 +//UNUSED2008-05 void ScTabView::PaintLeftRow( SCROW nRow ) +//UNUSED2008-05 { +//UNUSED2008-05 PaintLeftArea( nRow, nRow ); +//UNUSED2008-05 } +//UNUSED2008-05 +//UNUSED2008-05 void ScTabView::PaintTopCol( SCCOL nCol ) +//UNUSED2008-05 { +//UNUSED2008-05 PaintTopArea( nCol, nCol ); +//UNUSED2008-05 } + +// PaintGrid - Datenbereiche neu zeichnen + +void ScTabView::PaintGrid() +{ + sal_uInt16 i; + for (i=0; i<4; i++) + if (pGridWin[i]) + if (pGridWin[i]->IsVisible()) + pGridWin[i]->Invalidate(); +} + +// PaintTop - obere Kontrollelemente neu zeichnen + +void ScTabView::PaintTop() +{ + sal_uInt16 i; + for (i=0; i<2; i++) + { + if (pColBar[i]) + pColBar[i]->Invalidate(); + if (pColOutline[i]) + pColOutline[i]->Invalidate(); + } +} + +void ScTabView::CreateAnchorHandles(SdrHdlList& rHdl, const ScAddress& rAddress) +{ + sal_uInt16 i; + + for(i=0; i<4; i++) + { + if(pGridWin[i]) + { + if(pGridWin[i]->IsVisible()) + { + pGridWin[i]->CreateAnchorHandle(rHdl, rAddress); + } + } + } +} + +void ScTabView::PaintTopArea( SCCOL nStartCol, SCCOL nEndCol ) +{ + // Pixel-Position der linken Kante + + if ( nStartCol < aViewData.GetPosX(SC_SPLIT_LEFT) || + nStartCol < aViewData.GetPosX(SC_SPLIT_RIGHT) ) + aViewData.RecalcPixPos(); + + // Fixierung anpassen (UpdateFixX setzt HSplitPos neu) + + if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX && nStartCol < aViewData.GetFixPosX() ) + if (aViewData.UpdateFixX()) + RepeatResize(); + + // zeichnen + + if (nStartCol>0) + --nStartCol; //! allgemeiner ? + + sal_Bool bLayoutRTL = aViewData.GetDocument()->IsLayoutRTL( aViewData.GetTabNo() ); + long nLayoutSign = bLayoutRTL ? -1 : 1; + + for (sal_uInt16 i=0; i<2; i++) + { + ScHSplitPos eWhich = (ScHSplitPos) i; + if (pColBar[eWhich]) + { + Size aWinSize = pColBar[eWhich]->GetSizePixel(); + long nStartX = aViewData.GetScrPos( nStartCol, 0, eWhich ).X(); + long nEndX; + if (nEndCol >= MAXCOL) + nEndX = bLayoutRTL ? 0 : ( aWinSize.Width()-1 ); + else + nEndX = aViewData.GetScrPos( nEndCol+1, 0, eWhich ).X() - nLayoutSign; + pColBar[eWhich]->Invalidate( + Rectangle( nStartX, 0, nEndX, aWinSize.Height()-1 ) ); + } + if (pColOutline[eWhich]) + pColOutline[eWhich]->Invalidate(); + } +} + + +// PaintLeft - linke Kontrollelemente neu zeichnen + +void ScTabView::PaintLeft() +{ + sal_uInt16 i; + for (i=0; i<2; i++) + { + if (pRowBar[i]) + pRowBar[i]->Invalidate(); + if (pRowOutline[i]) + pRowOutline[i]->Invalidate(); + } +} + +void ScTabView::PaintLeftArea( SCROW nStartRow, SCROW nEndRow ) +{ + // Pixel-Position der oberen Kante + + if ( nStartRow < aViewData.GetPosY(SC_SPLIT_TOP) || + nStartRow < aViewData.GetPosY(SC_SPLIT_BOTTOM) ) + aViewData.RecalcPixPos(); + + // Fixierung anpassen (UpdateFixY setzt VSplitPos neu) + + if ( aViewData.GetVSplitMode() == SC_SPLIT_FIX && nStartRow < aViewData.GetFixPosY() ) + if (aViewData.UpdateFixY()) + RepeatResize(); + + // zeichnen + + if (nStartRow>0) + --nStartRow; + + for (sal_uInt16 i=0; i<2; i++) + { + ScVSplitPos eWhich = (ScVSplitPos) i; + if (pRowBar[eWhich]) + { + Size aWinSize = pRowBar[eWhich]->GetSizePixel(); + long nStartY = aViewData.GetScrPos( 0, nStartRow, eWhich ).Y(); + long nEndY; + if (nEndRow >= MAXROW) + nEndY = aWinSize.Height()-1; + else + nEndY = aViewData.GetScrPos( 0, nEndRow+1, eWhich ).Y() - 1; + pRowBar[eWhich]->Invalidate( + Rectangle( 0, nStartY, aWinSize.Width()-1, nEndY ) ); + } + if (pRowOutline[eWhich]) + pRowOutline[eWhich]->Invalidate(); + } +} + +// InvertBlockMark - Block invertieren + +void ScTabView::InvertBlockMark(SCCOL nStartX, SCROW nStartY, + SCCOL nEndX, SCROW nEndY) +{ + if ( !aViewData.IsActive() ) + return; // invertiert wird nur auf aktiver View + + PutInOrder( nStartX, nEndX ); + PutInOrder( nStartY, nEndY ); + + ScMarkData& rMark = aViewData.GetMarkData(); + ScDocShell* pDocSh = aViewData.GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = aViewData.GetTabNo(); + + if ( pDocSh->GetLockCount() ) + { + // if paint is locked, avoid repeated inverting + // add repaint areas to paint lock data instead + pDocSh->PostPaint( nStartX,nStartY,nTab, nEndX,nEndY,nTab, PAINT_GRID ); + return; + } + + sal_Bool bSingle = rMark.IsMultiMarked(); + sal_Bool bMerge = pDoc->HasAttrib( nStartX, nStartY, nTab, nEndX, nEndY, nTab, + HASATTR_MERGED | HASATTR_OVERLAPPED ); + + sal_uInt16 i; + if ( bMerge || bSingle ) + { + for (i=0; i<4; i++) + if (pGridWin[i]) + if (pGridWin[i]->IsVisible()) + pGridWin[i]->InvertSimple( nStartX, nStartY, nEndX, nEndY, + bMerge, bBlockNeg ); + } + else + { + for (i=0; i<4; i++) + if (pGridWin[i]) + if (pGridWin[i]->IsVisible()) + { + ScSplitPos ePos = (ScSplitPos) i; + Point aStartPoint = aViewData.GetScrPos( nStartX, nStartY, ePos ); + Point aEndPoint = aViewData.GetScrPos( nEndX+1, nEndY+1, ePos ); + if ( pDoc->IsLayoutRTL( nTab ) ) + { + long nTemp = aStartPoint.X(); + aStartPoint.X() = aEndPoint.X() + 1; // +1 - excluding start of nEndX+1 + aEndPoint.X() = nTemp; + } + else + aEndPoint.X() -= 1; + aEndPoint.Y() -= 1; + if ( aEndPoint.X() >= aStartPoint.X() && aEndPoint.Y() >= aStartPoint.Y() ) + { + MapMode aOld = pGridWin[ePos]->GetMapMode(); + pGridWin[ePos]->SetMapMode(MAP_PIXEL); + pGridWin[ePos]->Invert( Rectangle(aStartPoint,aEndPoint), INVERT_HIGHLIGHT ); + pGridWin[ePos]->SetMapMode(aOld); + pGridWin[ePos]->CheckInverted(); + } + } + } + + // + // wenn Controls betroffen, neu malen + // + + sal_Bool bHide = sal_True; // wird Teil der Markierung aufgehoben ? + if (rMark.IsMarked()) + { + ScRange aMarkRange; + rMark.GetMarkArea( aMarkRange ); + if ( aMarkRange.aStart.Col() <= nStartX && aMarkRange.aEnd.Col() >= nEndX && + aMarkRange.aStart.Row() <= nStartY && aMarkRange.aEnd.Row() >= nEndY ) + { + bHide = sal_False; // der ganze Bereich ist markiert + } + } +} + +sal_Bool ScTabView::PaintExtras() +{ + sal_Bool bRet = sal_False; + ScDocument* pDoc = aViewData.GetDocument(); + SCTAB nTab = aViewData.GetTabNo(); + if (!pDoc->HasTable(nTab)) // Tabelle geloescht ? + { + SCTAB nCount = pDoc->GetTableCount(); + aViewData.SetTabNo(nCount-1); + bRet = sal_True; + } + pTabControl->UpdateStatus(); // sal_True = active + return bRet; +} + +void ScTabView::RecalcPPT() +{ + // called after changes that require the PPT values to be recalculated + // (currently from detective operations) + + double nOldX = aViewData.GetPPTX(); + double nOldY = aViewData.GetPPTY(); + + aViewData.RefreshZoom(); // pre-calculate new PPT values + + sal_Bool bChangedX = ( aViewData.GetPPTX() != nOldX ); + sal_Bool bChangedY = ( aViewData.GetPPTY() != nOldY ); + if ( bChangedX || bChangedY ) + { + // call view SetZoom (including draw scale, split update etc) + // and paint only if values changed + + Fraction aZoomX = aViewData.GetZoomX(); + Fraction aZoomY = aViewData.GetZoomY(); + SetZoom( aZoomX, aZoomY, sal_False ); + + PaintGrid(); + if (bChangedX) + PaintTop(); + if (bChangedY) + PaintLeft(); + } +} + +void ScTabView::ActivateView( sal_Bool bActivate, sal_Bool bFirst ) +{ + if ( bActivate == aViewData.IsActive() && !bFirst ) + { + // keine Assertion mehr - kommt vor, wenn vorher im Drag&Drop + // auf ein anderes Dokument umgeschaltet wurde + return; + } + + // wird nur bei MDI-(De)Activate gerufen + // aViewData.Activate hinten wegen Cursor-Show bei KillEditView + // Markierung nicht mehr loeschen - wenn an der ViewData Activate(sal_False) gesetzt ist, + // wird die Markierung nicht ausgegeben + + if (!bActivate) + { + ScModule* pScMod = SC_MOD(); + sal_Bool bRefMode = pScMod->IsFormulaMode(); + + // Referenzeingabe nicht abbrechen, um Referenzen auf + // andere Dokumente zuzulassen + + if (!bRefMode) + { + //pScMod->InputEnterHandler(); + + // #80843# pass view to GetInputHdl, this view may not be current anymore + ScInputHandler* pHdl = SC_MOD()->GetInputHdl(aViewData.GetViewShell()); + if (pHdl) + pHdl->EnterHandler(); + } + } + pTabControl->ActivateView(bActivate); + PaintExtras(); + + aViewData.Activate(bActivate); + + PaintBlock(sal_False); // Repaint, Markierung je nach Active-Status + + if (!bActivate) + HideAllCursors(); // Cursor + else if (!bFirst) + ShowAllCursors(); + + //HMHif (pDrawView) + //HMH DrawShowMarkHdl(bActivate); // Drawing-Markierung + + if (bActivate) + { + if ( bFirst ) + { + ScSplitPos eWin = aViewData.GetActivePart(); + DBG_ASSERT( pGridWin[eWin], "rottes Dokument, nicht alle SplitPos in GridWin" ); + if ( !pGridWin[eWin] ) + { + eWin = SC_SPLIT_BOTTOMLEFT; + if ( !pGridWin[eWin] ) + { + short i; + for ( i=0; i<4; i++ ) + { + if ( pGridWin[i] ) + { + eWin = (ScSplitPos) i; + break; // for + } + } + DBG_ASSERT( i<4, "und BUMM" ); + } + aViewData.SetActivePart( eWin ); + } + } + // hier nicht mehr selber GrabFocus rufen! + // Wenn das Doc bearbeitet wird, ruft der Sfx selber GrabFocus am Fenster der Shell. + // Wenn es z.B. ein Mailbody ist, darf es den Focus nicht bekommen (Bug #43638#) + + UpdateInputContext(); + } + else + pGridWin[aViewData.GetActivePart()]->ClickExtern(); +} + +void ScTabView::ActivatePart( ScSplitPos eWhich ) +{ + ScSplitPos eOld = aViewData.GetActivePart(); + if ( eOld != eWhich ) + { + bInActivatePart = sal_True; + + sal_Bool bRefMode = SC_MOD()->IsFormulaMode(); + + // #40565# the HasEditView call during SetCursor would fail otherwise + if ( aViewData.HasEditView(eOld) && !bRefMode ) + UpdateInputLine(); + + ScHSplitPos eOldH = WhichH(eOld); + ScVSplitPos eOldV = WhichV(eOld); + ScHSplitPos eNewH = WhichH(eWhich); + ScVSplitPos eNewV = WhichV(eWhich); + sal_Bool bTopCap = pColBar[eOldH] && pColBar[eOldH]->IsMouseCaptured(); + sal_Bool bLeftCap = pRowBar[eOldV] && pRowBar[eOldV]->IsMouseCaptured(); + + sal_Bool bFocus = pGridWin[eOld]->HasFocus(); + sal_Bool bCapture = pGridWin[eOld]->IsMouseCaptured(); + if (bCapture) + pGridWin[eOld]->ReleaseMouse(); + pGridWin[eOld]->ClickExtern(); + pGridWin[eOld]->HideCursor(); + pGridWin[eWhich]->HideCursor(); + aViewData.SetActivePart( eWhich ); + + ScTabViewShell* pShell = aViewData.GetViewShell(); + pShell->WindowChanged(); + + pSelEngine->SetWindow(pGridWin[eWhich]); + pSelEngine->SetWhich(eWhich); + pSelEngine->SetVisibleArea( Rectangle(Point(), pGridWin[eWhich]->GetOutputSizePixel()) ); + + pGridWin[eOld]->MoveMouseStatus(*pGridWin[eWhich]); + + if ( bCapture || pGridWin[eWhich]->IsMouseCaptured() ) + { + // Tracking statt CaptureMouse, damit sauber abgebrochen werden kann + // (SelectionEngine ruft CaptureMouse beim SetWindow) + //! Irgendwann sollte die SelectionEngine selber StartTracking rufen!?! + pGridWin[eWhich]->ReleaseMouse(); + pGridWin[eWhich]->StartTracking(); + } + + if ( bTopCap && pColBar[eNewH] ) + { + pColBar[eOldH]->SetIgnoreMove(sal_True); + pColBar[eNewH]->SetIgnoreMove(sal_False); + pHdrSelEng->SetWindow( pColBar[eNewH] ); + long nWidth = pColBar[eNewH]->GetOutputSizePixel().Width(); + pHdrSelEng->SetVisibleArea( Rectangle( 0, LONG_MIN, nWidth-1, LONG_MAX ) ); + pColBar[eNewH]->CaptureMouse(); + } + if ( bLeftCap && pRowBar[eNewV] ) + { + pRowBar[eOldV]->SetIgnoreMove(sal_True); + pRowBar[eNewV]->SetIgnoreMove(sal_False); + pHdrSelEng->SetWindow( pRowBar[eNewV] ); + long nHeight = pRowBar[eNewV]->GetOutputSizePixel().Height(); + pHdrSelEng->SetVisibleArea( Rectangle( LONG_MIN, 0, LONG_MAX, nHeight-1 ) ); + pRowBar[eNewV]->CaptureMouse(); + } + aHdrFunc.SetWhich(eWhich); + + pGridWin[eOld]->ShowCursor(); + pGridWin[eWhich]->ShowCursor(); + + SfxInPlaceClient* pClient = aViewData.GetViewShell()->GetIPClient(); + sal_Bool bOleActive = ( pClient && pClient->IsObjectInPlaceActive() ); + + // #103823# don't switch ViewShell's active window during RefInput, because the focus + // might change, and subsequent SetReference calls wouldn't find the right EditView + if ( !bRefMode && !bOleActive ) + aViewData.GetViewShell()->SetWindow( pGridWin[eWhich] ); + + if ( bFocus && !aViewData.IsAnyFillMode() && !bRefMode ) + { + // GrabFocus nur, wenn vorher das andere GridWindow den Focus hatte + // (z.B. wegen Suchen & Ersetzen) +//! aViewData.GetViewShell()->GetViewFrame()->GetWindow().GrabFocus(); + pGridWin[eWhich]->GrabFocus(); + } + + bInActivatePart = sal_False; + } +} + +void ScTabView::HideListBox() +{ + for (sal_uInt16 i=0; i<4; i++) + if (pGridWin[i]) + pGridWin[i]->ClickExtern(); +} + +void ScTabView::UpdateInputContext() +{ + ScGridWindow* pWin = pGridWin[aViewData.GetActivePart()]; + if (pWin) + pWin->UpdateInputContext(); +} + +// GetGridWidth - Breite eines Ausgabebereichs (fuer ViewData) + +long ScTabView::GetGridWidth( ScHSplitPos eWhich ) +{ + ScSplitPos eGridWhich = ( eWhich == SC_SPLIT_LEFT ) ? SC_SPLIT_BOTTOMLEFT : SC_SPLIT_BOTTOMRIGHT; + if (pGridWin[eGridWhich]) + return pGridWin[eGridWhich]->GetSizePixel().Width(); + else + return 0; +} + +// GetGridHeight - Hoehe eines Ausgabebereichs (fuer ViewData) + +long ScTabView::GetGridHeight( ScVSplitPos eWhich ) +{ + ScSplitPos eGridWhich = ( eWhich == SC_SPLIT_TOP ) ? SC_SPLIT_TOPLEFT : SC_SPLIT_BOTTOMLEFT; + if (pGridWin[eGridWhich]) + return pGridWin[eGridWhich]->GetSizePixel().Height(); + else + return 0; +} + +void ScTabView::UpdateInputLine() +{ + SC_MOD()->InputEnterHandler(); +} + +void ScTabView::ZoomChanged() +{ + ScInputHandler* pHdl = SC_MOD()->GetInputHdl(aViewData.GetViewShell()); + if (pHdl) + pHdl->SetRefScale( aViewData.GetZoomX(), aViewData.GetZoomY() ); + + UpdateFixPos(); + + UpdateScrollBars(); + + // VisArea... + // AW: Discussed with NN if there is a reason that new map mode was only set for one window, + // but is not. Setting only on one window causes the first repaint to have the old mapMode + // in three of four views, so the overlay will save the wrong content e.g. when zooming out. + // Changing to setting map mode at all windows. + sal_uInt32 a; + + for(a = 0L; a < 4L; a++) + { + if(pGridWin[a]) + { + pGridWin[a]->SetMapMode(pGridWin[a]->GetDrawMapMode()); + } + } + + SetNewVisArea(); + + /* the old code + ScGridWindow* pWin = pGridWin[aViewData.GetActivePart()]; + if (pWin) + { + pWin->SetMapMode( pWin->GetDrawMapMode() ); // mit neuem Zoom + SetNewVisArea(); // benutzt den gesetzten MapMode + } */ + + InterpretVisible(); // #69343# have everything calculated before painting + + SfxBindings& rBindings = aViewData.GetBindings(); + rBindings.Invalidate( SID_ATTR_ZOOM ); + rBindings.Invalidate( SID_ATTR_ZOOMSLIDER ); + + HideNoteMarker(); + + // AW: To not change too much, use pWin here + ScGridWindow* pWin = pGridWin[aViewData.GetActivePart()]; + + if ( pWin && aViewData.HasEditView( aViewData.GetActivePart() ) ) + { + // flush OverlayManager before changing the MapMode + pWin->flushOverlayManager(); + + // #93650# make sure the EditView's position and size are updated + // with the right (logic, not drawing) MapMode + pWin->SetMapMode( aViewData.GetLogicMode() ); + UpdateEditView(); + } +} + +void ScTabView::CheckNeedsRepaint() +{ + sal_uInt16 i; + for (i=0; i<4; i++) + if ( pGridWin[i] && pGridWin[i]->IsVisible() ) + pGridWin[i]->CheckNeedsRepaint(); +} + + + + + diff --git a/sc/source/ui/view/tabview4.cxx b/sc/source/ui/view/tabview4.cxx new file mode 100644 index 000000000000..b7fb4d717200 --- /dev/null +++ b/sc/source/ui/view/tabview4.cxx @@ -0,0 +1,573 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +//------------------------------------------------------------------ + +// INCLUDE --------------------------------------------------------------- + +#include <vcl/help.hxx> +#include <vcl/svapp.hxx> + +#include "tabview.hxx" +#include "document.hxx" +#include "docsh.hxx" +#include "scmod.hxx" +#include "gridwin.hxx" +#include "globstr.hrc" +#include "cell.hxx" +#include "dociter.hxx" + +extern sal_uInt16 nScFillModeMouseModifier; // global.cxx + +// STATIC DATA ----------------------------------------------------------- + +//================================================================== + +// +// --- Referenz-Eingabe / Fill-Cursor +// + +void ScTabView::HideTip() +{ + if ( nTipVisible ) + { + Help::HideTip( nTipVisible ); + nTipVisible = 0; + } +} + +void ScTabView::ShowRefTip() +{ + sal_Bool bDone = sal_False; + if ( aViewData.GetRefType() == SC_REFTYPE_REF && Help::IsQuickHelpEnabled() ) + { + SCCOL nStartX = aViewData.GetRefStartX(); + SCROW nStartY = aViewData.GetRefStartY(); + SCCOL nEndX = aViewData.GetRefEndX(); + SCROW nEndY = aViewData.GetRefEndY(); + if ( nEndX != nStartX || nEndY != nStartY ) // nicht fuer einzelne Zelle + { + sal_Bool bLeft = ( nEndX < nStartX ); + sal_Bool bTop = ( nEndY < nStartY ); + PutInOrder( nStartX, nEndX ); + PutInOrder( nStartY, nEndY ); + SCCOL nCols = nEndX+1-nStartX; + SCROW nRows = nEndY+1-nStartY; + + String aHelp = ScGlobal::GetRscString( STR_QUICKHELP_REF ); + aHelp.SearchAndReplace( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("%1")), + String::CreateFromInt32(nRows) ); + aHelp.SearchAndReplace( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("%2")), + String::CreateFromInt32(nCols) ); + + ScSplitPos eWhich = aViewData.GetActivePart(); + Window* pWin = pGridWin[eWhich]; + if ( pWin ) + { + Point aStart = aViewData.GetScrPos( nStartX, nStartY, eWhich ); + Point aEnd = aViewData.GetScrPos( nEndX+1, nEndY+1, eWhich ); + + Point aPos( bLeft ? aStart.X() : ( aEnd.X() + 3 ), + bTop ? aStart.Y() : ( aEnd.Y() + 3 ) ); + sal_uInt16 nFlags = ( bLeft ? QUICKHELP_RIGHT : QUICKHELP_LEFT ) | + ( bTop ? QUICKHELP_BOTTOM : QUICKHELP_TOP ); + + // nicht ueber die editierte Formel + if ( !bTop && aViewData.HasEditView( eWhich ) && + nEndY+1 == aViewData.GetEditViewRow() ) + { + // dann an der oberen Kante der editierten Zelle ausrichten + aPos.Y() -= 2; // die 3 von oben + nFlags = ( nFlags & ~QUICKHELP_TOP ) | QUICKHELP_BOTTOM; + } + + Rectangle aRect( pWin->OutputToScreenPixel( aPos ), Size(1,1) ); + + //! Test, ob geaendert ?? + + HideTip(); + nTipVisible = Help::ShowTip( pWin, aRect, aHelp, nFlags ); + bDone = sal_True; + } + } + } + + if (!bDone) + HideTip(); +} + +void ScTabView::StopRefMode() +{ + if (aViewData.IsRefMode()) + { + aViewData.SetRefMode( sal_False, SC_REFTYPE_NONE ); + + HideTip(); + UpdateShrinkOverlay(); + + if ( aViewData.GetTabNo() >= aViewData.GetRefStartZ() && + aViewData.GetTabNo() <= aViewData.GetRefEndZ() ) + { + ScDocument* pDoc = aViewData.GetDocument(); + SCCOL nStartX = aViewData.GetRefStartX(); + SCROW nStartY = aViewData.GetRefStartY(); + SCCOL nEndX = aViewData.GetRefEndX(); + SCROW nEndY = aViewData.GetRefEndY(); + if ( nStartX == nEndX && nStartY == nEndY ) + pDoc->ExtendMerge( nStartX, nStartY, nEndX, nEndY, aViewData.GetTabNo() ); + + PaintArea( nStartX,nStartY,nEndX,nEndY, SC_UPDATE_MARKS ); + } + + pSelEngine->Reset(); + pSelEngine->SetAddMode( sal_False ); //! sollte das nicht bei Reset passieren? + + ScSplitPos eOld = pSelEngine->GetWhich(); + ScSplitPos eNew = aViewData.GetActivePart(); + if ( eNew != eOld ) + { + pSelEngine->SetWindow( pGridWin[ eNew ] ); + pSelEngine->SetWhich( eNew ); + pSelEngine->SetVisibleArea( Rectangle(Point(), + pGridWin[eNew]->GetOutputSizePixel()) ); + pGridWin[eOld]->MoveMouseStatus(*pGridWin[eNew]); + } + } + + // AlignToCursor(SC_FOLLOW_NONE): Only switch active part. + // This must also be done if no RefMode was active (for RangeFinder dragging), + // but if RefMode was set, AlignToCursor must be after SelectionEngine reset, + // so the SelectionEngine SetWindow call from AlignToCursor doesn't capture + // the mouse again when called from Tracking/MouseButtonUp (#94562#). + AlignToCursor( aViewData.GetCurX(), aViewData.GetCurY(), SC_FOLLOW_NONE ); +} + +void ScTabView::DoneRefMode( sal_Bool bContinue ) +{ + ScDocument* pDoc = aViewData.GetDocument(); + if ( aViewData.GetRefType() == SC_REFTYPE_REF && bContinue ) + SC_MOD()->AddRefEntry(); + + sal_Bool bWasRef = aViewData.IsRefMode(); + aViewData.SetRefMode( sal_False, SC_REFTYPE_NONE ); + + HideTip(); + UpdateShrinkOverlay(); + + // Paint: + if ( bWasRef && aViewData.GetTabNo() >= aViewData.GetRefStartZ() && + aViewData.GetTabNo() <= aViewData.GetRefEndZ() ) + { + SCCOL nStartX = aViewData.GetRefStartX(); + SCROW nStartY = aViewData.GetRefStartY(); + SCCOL nEndX = aViewData.GetRefEndX(); + SCROW nEndY = aViewData.GetRefEndY(); + if ( nStartX == nEndX && nStartY == nEndY ) + pDoc->ExtendMerge( nStartX, nStartY, nEndX, nEndY, aViewData.GetTabNo() ); + + PaintArea( nStartX,nStartY,nEndX,nEndY, SC_UPDATE_MARKS ); + } +} + +void ScTabView::UpdateRef( SCCOL nCurX, SCROW nCurY, SCTAB nCurZ ) +{ + ScDocument* pDoc = aViewData.GetDocument(); + + if (!aViewData.IsRefMode()) + { + // Das kommt vor, wenn bei einem Referenz-Dialog als erstes mit Control in die + // die Tabelle geklickt wird. Dann die neue Referenz an den alten Inhalt anhaengen: + + ScModule* pScMod = SC_MOD(); + if (pScMod->IsFormulaMode()) + pScMod->AddRefEntry(); + + InitRefMode( nCurX, nCurY, nCurZ, SC_REFTYPE_REF ); + } + + if ( nCurX != aViewData.GetRefEndX() || nCurY != aViewData.GetRefEndY() || + nCurZ != aViewData.GetRefEndZ() ) + { + ScMarkData& rMark = aViewData.GetMarkData(); + SCTAB nTab = aViewData.GetTabNo(); + + SCCOL nStartX = aViewData.GetRefStartX(); + SCROW nStartY = aViewData.GetRefStartY(); + SCCOL nEndX = aViewData.GetRefEndX(); + SCROW nEndY = aViewData.GetRefEndY(); + if ( nStartX == nEndX && nStartY == nEndY ) + pDoc->ExtendMerge( nStartX, nStartY, nEndX, nEndY, nTab ); + ScUpdateRect aRect( nStartX, nStartY, nEndX, nEndY ); + + aViewData.SetRefEnd( nCurX, nCurY, nCurZ ); + + nStartX = aViewData.GetRefStartX(); + nStartY = aViewData.GetRefStartY(); + nEndX = aViewData.GetRefEndX(); + nEndY = aViewData.GetRefEndY(); + if ( nStartX == nEndX && nStartY == nEndY ) + pDoc->ExtendMerge( nStartX, nStartY, nEndX, nEndY, nTab ); + aRect.SetNew( nStartX, nStartY, nEndX, nEndY ); + + ScRefType eType = aViewData.GetRefType(); + if ( eType == SC_REFTYPE_REF ) + { + ScRange aRef( + aViewData.GetRefStartX(), aViewData.GetRefStartY(), aViewData.GetRefStartZ(), + aViewData.GetRefEndX(), aViewData.GetRefEndY(), aViewData.GetRefEndZ() ); + SC_MOD()->SetReference( aRef, pDoc, &rMark ); + ShowRefTip(); + } + else if ( eType == SC_REFTYPE_EMBED_LT || eType == SC_REFTYPE_EMBED_RB ) + { + PutInOrder(nStartX,nEndX); + PutInOrder(nStartY,nEndY); + pDoc->SetEmbedded( ScRange(nStartX,nStartY,nTab, nEndX,nEndY,nTab) ); + ScDocShell* pDocSh = aViewData.GetDocShell(); + pDocSh->UpdateOle( &aViewData, sal_True ); + pDocSh->SetDocumentModified(); + } + + SCCOL nPaintStartX; + SCROW nPaintStartY; + SCCOL nPaintEndX; + SCROW nPaintEndY; + if (aRect.GetDiff( nPaintStartX, nPaintStartY, nPaintEndX, nPaintEndY )) + PaintArea( nPaintStartX, nPaintStartY, nPaintEndX, nPaintEndY, SC_UPDATE_MARKS ); + } + + // Tip-Hilfe fuer Auto-Fill + + if ( aViewData.GetRefType() == SC_REFTYPE_FILL && Help::IsQuickHelpEnabled() ) + { + String aHelpStr; + ScRange aMarkRange; + aViewData.GetSimpleArea( aMarkRange ); + SCCOL nEndX = aViewData.GetRefEndX(); + SCROW nEndY = aViewData.GetRefEndY(); + ScRange aDelRange; + if ( aViewData.GetFillMode() == SC_FILL_MATRIX && !(nScFillModeMouseModifier & KEY_MOD1) ) + { + aHelpStr = ScGlobal::GetRscString( STR_TIP_RESIZEMATRIX ); + SCCOL nCols = nEndX + 1 - aViewData.GetRefStartX(); // Reihenfolge ist richtig + SCROW nRows = nEndY + 1 - aViewData.GetRefStartY(); + aHelpStr.SearchAndReplace( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("%1")), + String::CreateFromInt32(nRows) ); + aHelpStr.SearchAndReplace( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("%2")), + String::CreateFromInt32(nCols) ); + } + else if ( aViewData.GetDelMark( aDelRange ) ) + aHelpStr = ScGlobal::GetRscString( STR_QUICKHELP_DELETE ); + else if ( nEndX != aMarkRange.aEnd.Col() || nEndY != aMarkRange.aEnd.Row() ) + aHelpStr = pDoc->GetAutoFillPreview( aMarkRange, nEndX, nEndY ); + + // je nach Richtung die obere oder untere Ecke: + SCCOL nAddX = ( nEndX >= aMarkRange.aEnd.Col() ) ? 1 : 0; + SCROW nAddY = ( nEndY >= aMarkRange.aEnd.Row() ) ? 1 : 0; + Point aPos = aViewData.GetScrPos( nEndX+nAddX, nEndY+nAddY, aViewData.GetActivePart() ); + aPos.X() += 8; + aPos.Y() += 4; + Window* pWin = GetActiveWin(); + if ( pWin ) + aPos = pWin->OutputToScreenPixel( aPos ); + Rectangle aRect( aPos, aPos ); + sal_uInt16 nAlign = QUICKHELP_LEFT|QUICKHELP_TOP; + Help::ShowQuickHelp(pWin, aRect, aHelpStr, nAlign); + } +} + +void ScTabView::InitRefMode( SCCOL nCurX, SCROW nCurY, SCTAB nCurZ, ScRefType eType, sal_Bool bPaint ) +{ + ScDocument* pDoc = aViewData.GetDocument(); + ScMarkData& rMark = aViewData.GetMarkData(); + if (!aViewData.IsRefMode()) + { + aViewData.SetRefMode( sal_True, eType ); + aViewData.SetRefStart( nCurX, nCurY, nCurZ ); + aViewData.SetRefEnd( nCurX, nCurY, nCurZ ); + + if (nCurZ == aViewData.GetTabNo() && bPaint) + { + SCCOL nStartX = nCurX; + SCROW nStartY = nCurY; + SCCOL nEndX = nCurX; + SCROW nEndY = nCurY; + pDoc->ExtendMerge( nStartX, nStartY, nEndX, nEndY, aViewData.GetTabNo() ); + + //! nur Markierung ueber Inhalte zeichnen! + PaintArea( nStartX,nStartY,nEndX,nEndY, SC_UPDATE_MARKS ); + + // SetReference ohne Merge-Anpassung + ScRange aRef( nCurX,nCurY,nCurZ, nCurX,nCurY,nCurZ ); + SC_MOD()->SetReference( aRef, pDoc, &rMark ); + } + } +} + +//UNUSED2008-05 void ScTabView::EndSelection() +//UNUSED2008-05 { +//UNUSED2008-05 ScModule* pScMod = SC_MOD(); +//UNUSED2008-05 sal_Bool bRefMode = pScMod->IsFormulaMode(); +//UNUSED2008-05 if ( bRefMode ) +//UNUSED2008-05 pScMod->EndReference(); +//UNUSED2008-05 } + +// static +void ScTabView::SetScrollBar( ScrollBar& rScroll, long nRangeMax, long nVisible, long nPos, sal_Bool bLayoutRTL ) +{ + if ( nVisible == 0 ) + nVisible = 1; // #i59893# don't use visible size 0 + + // RTL layout uses a negative range to simulate a mirrored scroll bar. + // SetScrollBar/GetScrollBarPos hide this so outside of these functions normal cell + // addresses can be used. + + if ( bLayoutRTL ) + { + rScroll.SetRange( Range( -nRangeMax, 0 ) ); + rScroll.SetVisibleSize( nVisible ); + rScroll.SetThumbPos( -nPos - nVisible ); + } + else + { + rScroll.SetRange( Range( 0, nRangeMax ) ); + rScroll.SetVisibleSize( nVisible ); + rScroll.SetThumbPos( nPos ); + } +} + +// static +long ScTabView::GetScrollBarPos( ScrollBar& rScroll, sal_Bool bLayoutRTL ) +{ + if ( bLayoutRTL ) + return -rScroll.GetThumbPos() - rScroll.GetVisibleSize(); + else + return rScroll.GetThumbPos(); +} + +// UpdateScrollBars - sichtbaren Bereich und Scrollweite der Scrollbars einstellen + +long lcl_UpdateBar( ScrollBar& rScroll, SCCOLROW nSize ) // Size = (komplette) Zellen +{ + long nOldPos; + long nNewPos; + + nOldPos = rScroll.GetThumbPos(); + rScroll.SetPageSize( static_cast<long>(nSize) ); + nNewPos = rScroll.GetThumbPos(); +#ifndef UNX + rScroll.SetPageSize( 1 ); // immer moeglich ! +#endif + + return nNewPos - nOldPos; +} + +long lcl_GetScrollRange( SCCOLROW nDocEnd, SCCOLROW nPos, SCCOLROW nVis, SCCOLROW nMax, SCCOLROW nStart ) +{ + // get the end (positive) of a scroll bar range that always starts at 0 + + ++nVis; + ++nMax; // for partially visible cells + SCCOLROW nEnd = Max(nDocEnd, (SCCOLROW)(nPos+nVis)) + nVis; + if (nEnd > nMax) + nEnd = nMax; + + return ( nEnd - nStart ); // for range starting at 0 +} + +void ScTabView::UpdateScrollBars() +{ + long nDiff; + sal_Bool bTop = ( aViewData.GetVSplitMode() != SC_SPLIT_NONE ); + sal_Bool bRight = ( aViewData.GetHSplitMode() != SC_SPLIT_NONE ); + ScDocument* pDoc = aViewData.GetDocument(); + SCTAB nTab = aViewData.GetTabNo(); + sal_Bool bMirror = pDoc->IsLayoutRTL( nTab ) != Application::GetSettings().GetLayoutRTL(); + SCCOL nUsedX; + SCROW nUsedY; + pDoc->GetTableArea( nTab, nUsedX, nUsedY ); //! cachen !!!!!!!!!!!!!!! + + SCCOL nVisXL = 0; + SCCOL nVisXR = 0; + SCROW nVisYB = 0; + SCROW nVisYT = 0; + + SCCOL nStartX = 0; + SCROW nStartY = 0; + if (aViewData.GetHSplitMode()==SC_SPLIT_FIX) + nStartX = aViewData.GetFixPosX(); + if (aViewData.GetVSplitMode()==SC_SPLIT_FIX) + nStartY = aViewData.GetFixPosY(); + + nVisXL = aViewData.VisibleCellsX( SC_SPLIT_LEFT ); + long nMaxXL = lcl_GetScrollRange( nUsedX, aViewData.GetPosX(SC_SPLIT_LEFT), nVisXL, MAXCOL, 0 ); + SetScrollBar( aHScrollLeft, nMaxXL, nVisXL, aViewData.GetPosX( SC_SPLIT_LEFT ), bMirror ); + + nVisYB = aViewData.VisibleCellsY( SC_SPLIT_BOTTOM ); + long nMaxYB = lcl_GetScrollRange( nUsedY, aViewData.GetPosY(SC_SPLIT_BOTTOM), nVisYB, MAXROW, nStartY ); + SetScrollBar( aVScrollBottom, nMaxYB, nVisYB, aViewData.GetPosY( SC_SPLIT_BOTTOM ) - nStartY, sal_False ); + + if (bRight) + { + nVisXR = aViewData.VisibleCellsX( SC_SPLIT_RIGHT ); + long nMaxXR = lcl_GetScrollRange( nUsedX, aViewData.GetPosX(SC_SPLIT_RIGHT), nVisXR, MAXCOL, nStartX ); + SetScrollBar( aHScrollRight, nMaxXR, nVisXR, aViewData.GetPosX( SC_SPLIT_RIGHT ) - nStartX, bMirror ); + } + + if (bTop) + { + nVisYT = aViewData.VisibleCellsY( SC_SPLIT_TOP ); + long nMaxYT = lcl_GetScrollRange( nUsedY, aViewData.GetPosY(SC_SPLIT_TOP), nVisYT, MAXROW, 0 ); + SetScrollBar( aVScrollTop, nMaxYT, nVisYT, aViewData.GetPosY( SC_SPLIT_TOP ), sal_False ); + } + + // Bereich testen + + nDiff = lcl_UpdateBar( aHScrollLeft, nVisXL ); + if (nDiff) ScrollX( nDiff, SC_SPLIT_LEFT ); + if (bRight) + { + nDiff = lcl_UpdateBar( aHScrollRight, nVisXR ); + if (nDiff) ScrollX( nDiff, SC_SPLIT_RIGHT ); + } + + nDiff = lcl_UpdateBar( aVScrollBottom, nVisYB ); + if (nDiff) ScrollY( nDiff, SC_SPLIT_BOTTOM ); + if (bTop) + { + nDiff = lcl_UpdateBar( aVScrollTop, nVisYT ); + if (nDiff) ScrollY( nDiff, SC_SPLIT_TOP ); + } + + // set visible area for online spelling + + if ( aViewData.IsActive() ) + { + ScSplitPos eActive = aViewData.GetActivePart(); + ScHSplitPos eHWhich = WhichH( eActive ); + ScVSplitPos eVWhich = WhichV( eActive ); + SCCOL nPosX = aViewData.GetPosX(eHWhich); + SCROW nPosY = aViewData.GetPosY(eVWhich); + SCCOL nEndX = nPosX + ( ( eHWhich == SC_SPLIT_LEFT ) ? nVisXL : nVisXR ); + SCROW nEndY = nPosY + ( ( eVWhich == SC_SPLIT_TOP ) ? nVisYT : nVisYB ); + if ( nEndX > MAXCOL ) nEndX = MAXCOL; + if ( nEndY > MAXROW ) nEndY = MAXROW; + ScRange aVisible( nPosX, nPosY, nTab, nEndX, nEndY, nTab ); + if ( pDoc->SetVisibleSpellRange( aVisible ) ) + SC_MOD()->AnythingChanged(); // if visible area has changed + } +} + +#ifndef HDR_SLIDERSIZE +#define HDR_SLIDERSIZE 2 +#endif + +void ScTabView::InvertHorizontal( ScVSplitPos eWhich, long nDragPos ) +{ + for (sal_uInt16 i=0; i<4; i++) + if (WhichV((ScSplitPos)i)==eWhich) + { + ScGridWindow* pWin = pGridWin[i]; + if (pWin) + { + Rectangle aRect( 0,nDragPos, pWin->GetOutputSizePixel().Width()-1,nDragPos+HDR_SLIDERSIZE-1 ); + pWin->Update(); + pWin->DoInvertRect( aRect ); // Pixel + } + } +} + +void ScTabView::InvertVertical( ScHSplitPos eWhich, long nDragPos ) +{ + for (sal_uInt16 i=0; i<4; i++) + if (WhichH((ScSplitPos)i)==eWhich) + { + ScGridWindow* pWin = pGridWin[i]; + if (pWin) + { + Rectangle aRect( nDragPos,0, nDragPos+HDR_SLIDERSIZE-1,pWin->GetOutputSizePixel().Height()-1 ); + pWin->Update(); + pWin->DoInvertRect( aRect ); // Pixel + } + } +} + +//================================================================== + +void ScTabView::InterpretVisible() +{ + // make sure all visible cells are interpreted, + // so the next paint will not execute a macro function + + ScDocument* pDoc = aViewData.GetDocument(); + if ( !pDoc->GetAutoCalc() ) + return; + + SCTAB nTab = aViewData.GetTabNo(); + for (sal_uInt16 i=0; i<4; i++) + { + // rely on gridwin pointers to find used panes + // no IsVisible test in case the whole view is not yet shown + + if (pGridWin[i]) + { + ScHSplitPos eHWhich = WhichH( ScSplitPos(i) ); + ScVSplitPos eVWhich = WhichV( ScSplitPos(i) ); + + SCCOL nX1 = aViewData.GetPosX( eHWhich ); + SCROW nY1 = aViewData.GetPosY( eVWhich ); + SCCOL nX2 = nX1 + aViewData.VisibleCellsX( eHWhich ); + SCROW nY2 = nY1 + aViewData.VisibleCellsY( eVWhich ); + + if (nX2 > MAXCOL) nX2 = MAXCOL; + if (nY2 > MAXROW) nY2 = MAXROW; + + ScCellIterator aIter( pDoc, nX1, nY1, nTab, nX2, nY2, nTab ); + ScBaseCell* pCell = aIter.GetFirst(); + while ( pCell ) + { + if ( pCell->GetCellType() == CELLTYPE_FORMULA && ((ScFormulaCell*)pCell)->GetDirty() ) + ((ScFormulaCell*)pCell)->Interpret(); + + pCell = aIter.GetNext(); + } + } + } + + // #i65047# repaint during the above loop may have set the bNeedsRepaint flag + CheckNeedsRepaint(); +} + + + + + diff --git a/sc/source/ui/view/tabview5.cxx b/sc/source/ui/view/tabview5.cxx new file mode 100644 index 000000000000..a20c73d04adf --- /dev/null +++ b/sc/source/ui/view/tabview5.cxx @@ -0,0 +1,722 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include "scitems.hxx" +#include <editeng/eeitem.hxx> + + +#include <svx/fmshell.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdoutl.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/objsh.hxx> +#include <tools/ref.hxx> + +#include "tabview.hxx" +#include "tabvwsh.hxx" +#include "document.hxx" +#include "gridwin.hxx" +#include "olinewin.hxx" +#include "tabsplit.hxx" +#include "colrowba.hxx" +#include "tabcont.hxx" +#include "hintwin.hxx" +#include "sc.hrc" +#include "pagedata.hxx" +#include "hiranges.hxx" +#include "drawview.hxx" +#include "drwlayer.hxx" +#include "fusel.hxx" // Start-Function +#include "seltrans.hxx" +#include "scmod.hxx" +#include "AccessibilityHints.hxx" +#include "docsh.hxx" +#include "viewuno.hxx" + +#include <vcl/svapp.hxx> + +using namespace com::sun::star; + +// STATIC DATA ----------------------------------------------------------- + + +void __EXPORT ScTabView::Init() +{ + /* RTL layout of the view windows is done manually, because it depends on + the sheet orientation, not the UI setting. Note: controls that are + already constructed (e.g. scroll bars) have the RTL setting of the GUI. + Eventually this has to be disabled manually (see below). */ + pFrameWin->EnableRTL( sal_False ); + + sal_uInt16 i; + + aScrollTimer.SetTimeout(10); + aScrollTimer.SetTimeoutHdl( LINK( this, ScTabView, TimerHdl ) ); + + for (i=0; i<4; i++) + pGridWin[i] = NULL; + pGridWin[SC_SPLIT_BOTTOMLEFT] = new ScGridWindow( pFrameWin, &aViewData, SC_SPLIT_BOTTOMLEFT ); + + pSelEngine = new ScViewSelectionEngine( pGridWin[SC_SPLIT_BOTTOMLEFT], this, + SC_SPLIT_BOTTOMLEFT ); + aFunctionSet.SetSelectionEngine( pSelEngine ); + + pHdrSelEng = new ScHeaderSelectionEngine( pFrameWin, &aHdrFunc ); + + pColBar[SC_SPLIT_LEFT] = new ScColBar( pFrameWin, &aViewData, SC_SPLIT_LEFT, + &aHdrFunc, pHdrSelEng ); + pColBar[SC_SPLIT_RIGHT] = NULL; + pRowBar[SC_SPLIT_BOTTOM] = new ScRowBar( pFrameWin, &aViewData, SC_SPLIT_BOTTOM, + &aHdrFunc, pHdrSelEng ); + pRowBar[SC_SPLIT_TOP] = NULL; + for (i=0; i<2; i++) + pColOutline[i] = pRowOutline[i] = NULL; + + pHSplitter = new ScTabSplitter( pFrameWin, WinBits( WB_HSCROLL ), &aViewData ); + pVSplitter = new ScTabSplitter( pFrameWin, WinBits( WB_VSCROLL ), &aViewData ); + + // SSA: override default keyboard step size to allow snap to row/column + pHSplitter->SetKeyboardStepSize( 1 ); + pVSplitter->SetKeyboardStepSize( 1 ); + + pTabControl = new ScTabControl( pFrameWin, &aViewData ); + /* #i97900# The tab control has to remain in RTL mode if GUI is RTL, this + is needed to draw the 3D effect correctly. The base TabBar implementes + mirroring independent from the GUI direction. Have to set RTL mode + explicitly because the parent frame window is already RTL disabled. */ + pTabControl->EnableRTL( Application::GetSettings().GetLayoutRTL() ); + + InitScrollBar( aHScrollLeft, MAXCOL+1 ); + InitScrollBar( aHScrollRight, MAXCOL+1 ); + InitScrollBar( aVScrollTop, MAXROW+1 ); + InitScrollBar( aVScrollBottom, MAXROW+1 ); + /* #i97900# scrollbars remain in correct RTL mode, needed mirroring etc. + is now handled correctly at the respective places. */ + + // Hier noch nichts anzeigen (Show), weil noch falsch angeordnet ist + // Show kommt dann aus UpdateShow beim ersten Resize + // pTabControl, pGridWin, aHScrollLeft, aVScrollBottom, + // aCornerButton, aScrollBarBox, pHSplitter, pVSplitter + + // Splitter + + pHSplitter->SetSplitHdl( LINK( this, ScTabView, SplitHdl ) ); + pVSplitter->SetSplitHdl( LINK( this, ScTabView, SplitHdl ) ); + + // UpdateShow kommt beim Resize, oder bei Kopie einer bestehenden View aus dem ctor + + pDrawActual = NULL; + pDrawOld = NULL; + + // DrawView darf nicht im TabView - ctor angelegt werden, + // wenn die ViewShell noch nicht konstruiert ist... + // Das gilt auch fuer ViewOptionsHasChanged() + + TestHintWindow(); +} + +__EXPORT ScTabView::~ScTabView() +{ + sal_uInt16 i; + + // remove selection object + ScModule* pScMod = SC_MOD(); + ScSelectionTransferObj* pOld = pScMod->GetSelectionTransfer(); + if ( pOld && pOld->GetView() == this ) + { + pOld->ForgetView(); + pScMod->SetSelectionTransfer( NULL ); + TransferableHelper::ClearSelection( GetActiveWin() ); // may delete pOld + } + + DELETEZ(pBrushDocument); + DELETEZ(pDrawBrushSet); + + DELETEZ(pPageBreakData); + DELETEZ(pHighlightRanges); + + DELETEZ(pDrawOld); + DELETEZ(pDrawActual); + + aViewData.KillEditView(); // solange GridWin's noch existieren + + DELETEZ(pInputHintWindow); + + if (pDrawView) + { + for (i=0; i<4; i++) + if (pGridWin[i]) + { + pDrawView->VCRemoveWin(pGridWin[i]); + pDrawView->DeleteWindowFromPaintView(pGridWin[i]); + } + + pDrawView->HideSdrPage(); + delete pDrawView; + } + + delete pSelEngine; + + for (i=0; i<4; i++) + delete pGridWin[i]; + + delete pHdrSelEng; + + for (i=0; i<2; i++) + { + delete pColBar[i]; + delete pRowBar[i]; + delete pColOutline[i]; + delete pRowOutline[i]; + } + + delete pHSplitter; + delete pVSplitter; + + delete pTabControl; +} + +void ScTabView::MakeDrawView( sal_uInt8 nForceDesignMode ) +{ + if (!pDrawView) + { + ScDrawLayer* pLayer = aViewData.GetDocument()->GetDrawLayer(); + DBG_ASSERT(pLayer, "wo ist der Draw Layer ??"); + + sal_uInt16 i; + pDrawView = new ScDrawView( pGridWin[SC_SPLIT_BOTTOMLEFT], &aViewData ); + for (i=0; i<4; i++) + if (pGridWin[i]) + { + if ( SC_SPLIT_BOTTOMLEFT != (ScSplitPos)i ) + pDrawView->AddWindowToPaintView(pGridWin[i]); + pDrawView->VCAddWin(pGridWin[i]); + } + pDrawView->RecalcScale(); + for (i=0; i<4; i++) + if (pGridWin[i]) + { + pGridWin[i]->SetMapMode(pGridWin[i]->GetDrawMapMode()); + + pGridWin[i]->Update(); // wegen Invalidate im DrawView ctor (ShowPage), + // damit gleich gezeichnet werden kann + } + SfxRequest aSfxRequest(SID_OBJECT_SELECT, 0,aViewData.GetViewShell()->GetPool()); + SetDrawFuncPtr(new FuSelection( aViewData.GetViewShell(), GetActiveWin(), pDrawView, + pLayer,aSfxRequest)); + + // #106334# used when switching back from page preview: restore saved design mode state + // (otherwise, keep the default from the draw view ctor) + if ( nForceDesignMode != SC_FORCEMODE_NONE ) + pDrawView->SetDesignMode( (sal_Bool)nForceDesignMode ); + + // an der FormShell anmelden + FmFormShell* pFormSh = aViewData.GetViewShell()->GetFormShell(); + if (pFormSh) + pFormSh->SetView(pDrawView); + + if (aViewData.GetViewShell()->HasAccessibilityObjects()) + aViewData.GetViewShell()->BroadcastAccessibility(SfxSimpleHint(SC_HINT_ACC_MAKEDRAWLAYER)); + + } +} + +void ScTabView::DoAddWin( ScGridWindow* pWin ) +{ + if (pDrawView) + { + pDrawView->AddWindowToPaintView(pWin); + pDrawView->VCAddWin(pWin); + + // #114409# + pWin->DrawLayerCreated(); + } +} + +//================================================================== + +void ScTabView::TabChanged( bool bSameTabButMoved ) +{ + if (pDrawView) + { + DrawDeselectAll(); // beendet auch Text-Edit-Modus + + sal_uInt16 i; + for (i=0; i<4; i++) + if (pGridWin[i]) + pDrawView->VCRemoveWin(pGridWin[i]); // fuer alte Page + + SCTAB nTab = aViewData.GetTabNo(); + pDrawView->HideSdrPage(); + pDrawView->ShowSdrPage(pDrawView->GetModel()->GetPage(nTab)); + + UpdateLayerLocks(); + + pDrawView->RecalcScale(); + pDrawView->UpdateWorkArea(); // #54782# PageSize ist pro Page unterschiedlich + + for (i=0; i<4; i++) + if (pGridWin[i]) + pDrawView->VCAddWin(pGridWin[i]); // fuer neue Page + } + + SfxBindings& rBindings = aViewData.GetBindings(); + + // Es gibt keine einfache Moeglichkeit, alle Slots der FormShell zu invalidieren + // (fuer disablete Slots auf geschuetzten Tabellen), darum hier einfach alles... + rBindings.InvalidateAll(sal_False); + +#if 0 + rBindings.Invalidate( SID_SELECT_SCENARIO ); + rBindings.Invalidate( FID_PROTECT_TABLE ); + rBindings.Invalidate( FID_DELETE_TABLE ); + rBindings.Invalidate( FID_TABLE_SHOW ); + rBindings.Invalidate( FID_TABLE_HIDE ); + + // Auswirkungen von geschuetzten Tabellen. + rBindings.Invalidate( FID_TAB_RENAME ); + rBindings.Invalidate( FID_TAB_MOVE ); + rBindings.Invalidate( SID_DEL_ROWS ); + rBindings.Invalidate( SID_DEL_COLS ); + rBindings.Invalidate( FID_INS_ROW ); + rBindings.Invalidate( FID_INS_COLUMN ); + rBindings.Invalidate( FID_INS_CELL ); + rBindings.Invalidate( FID_INS_CELLSDOWN ); + rBindings.Invalidate( FID_INS_CELLSRIGHT ); + rBindings.Invalidate( FID_DELETE_CELL ); + + rBindings.Invalidate( SID_OPENDLG_CHART ); + rBindings.Invalidate( SID_INSERT_OBJECT ); + rBindings.Invalidate( SID_INSERT_DIAGRAM ); + rBindings.Invalidate( SID_INSERT_SMATH ); + rBindings.Invalidate( SID_INSERT_GRAPHIC ); +#endif + + if (aViewData.GetViewShell()->HasAccessibilityObjects()) + { + SfxSimpleHint aAccHint(SC_HINT_ACC_TABLECHANGED); + aViewData.GetViewShell()->BroadcastAccessibility(aAccHint); + } + + // notification for XActivationBroadcaster + SfxViewFrame* pViewFrame = aViewData.GetViewShell()->GetViewFrame(); + if (pViewFrame) + { + uno::Reference<frame::XController> xController = pViewFrame->GetFrame().GetController(); + if (xController.is()) + { + ScTabViewObj* pImp = ScTabViewObj::getImplementation( xController ); + if (pImp) + pImp->SheetChanged( bSameTabButMoved ); + } + } +} + +void ScTabView::UpdateLayerLocks() +{ + if (pDrawView) + { + SCTAB nTab = aViewData.GetTabNo(); + sal_Bool bEx = aViewData.GetViewShell()->IsDrawSelMode(); + sal_Bool bProt = aViewData.GetDocument()->IsTabProtected( nTab ) || + aViewData.GetSfxDocShell()->IsReadOnly(); + sal_Bool bShared = aViewData.GetDocShell()->IsDocShared(); + + SdrLayer* pLayer; + SdrLayerAdmin& rAdmin = pDrawView->GetModel()->GetLayerAdmin(); + pLayer = rAdmin.GetLayerPerID(SC_LAYER_BACK); + if (pLayer) + pDrawView->SetLayerLocked( pLayer->GetName(), bProt || !bEx || bShared ); + pLayer = rAdmin.GetLayerPerID(SC_LAYER_INTERN); + if (pLayer) + pDrawView->SetLayerLocked( pLayer->GetName(), sal_True ); + pLayer = rAdmin.GetLayerPerID(SC_LAYER_FRONT); + if (pLayer) + pDrawView->SetLayerLocked( pLayer->GetName(), bProt || bShared ); + pLayer = rAdmin.GetLayerPerID(SC_LAYER_CONTROLS); + if (pLayer) + pDrawView->SetLayerLocked( pLayer->GetName(), bProt || bShared ); + pLayer = rAdmin.GetLayerPerID(SC_LAYER_HIDDEN); + if (pLayer) + { + pDrawView->SetLayerLocked( pLayer->GetName(), bProt || bShared ); + pDrawView->SetLayerVisible( pLayer->GetName(), sal_False); + } + } +} + +void ScTabView::DrawDeselectAll() +{ + if (pDrawView) + { + ScTabViewShell* pViewSh = aViewData.GetViewShell(); + if ( pDrawActual && + ( pViewSh->IsDrawTextShell() || pDrawActual->GetSlotID() == SID_DRAW_NOTEEDIT ) ) + { + // end text edit (as if escape pressed, in FuDraw) + aViewData.GetDispatcher().Execute( pDrawActual->GetSlotID(), + SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD ); + } + + pDrawView->ScEndTextEdit(); + pDrawView->UnmarkAll(); + + if (!pViewSh->IsDrawSelMode()) + pViewSh->SetDrawShell( sal_False ); + } +} + +sal_Bool ScTabView::IsDrawTextEdit() const +{ + if (pDrawView) + return pDrawView->IsTextEdit(); + else + return sal_False; +} + +//UNUSED2008-05 String ScTabView::GetSelectedChartName() const +//UNUSED2008-05 { +//UNUSED2008-05 if (pDrawView) +//UNUSED2008-05 return pDrawView->GetSelectedChartName(); +//UNUSED2008-05 else +//UNUSED2008-05 return EMPTY_STRING; +//UNUSED2008-05 } + +SvxZoomType ScTabView::GetZoomType() const +{ + return aViewData.GetZoomType(); +} + +void ScTabView::SetZoomType( SvxZoomType eNew, sal_Bool bAll ) +{ + aViewData.SetZoomType( eNew, bAll ); +} + +void ScTabView::SetZoom( const Fraction& rNewX, const Fraction& rNewY, sal_Bool bAll ) +{ + aViewData.SetZoom( rNewX, rNewY, bAll ); + if (pDrawView) + pDrawView->RecalcScale(); + ZoomChanged(); // einzeln wegen CLOOKs +} + +void ScTabView::RefreshZoom() +{ + aViewData.RefreshZoom(); + if (pDrawView) + pDrawView->RecalcScale(); + ZoomChanged(); +} + +void ScTabView::SetPagebreakMode( sal_Bool bSet ) +{ + aViewData.SetPagebreakMode(bSet); + if (pDrawView) + pDrawView->RecalcScale(); + ZoomChanged(); // einzeln wegen CLOOKs +} + +void ScTabView::ResetDrawDragMode() +{ + if (pDrawView) + pDrawView->SetDragMode( SDRDRAG_MOVE ); +} + +void ScTabView::ViewOptionsHasChanged( sal_Bool bHScrollChanged, sal_Bool bGraphicsChanged ) +{ + // DrawView erzeugen, wenn Gitter angezeigt werden soll + if ( !pDrawView && aViewData.GetOptions().GetGridOptions().GetGridVisible() ) + MakeDrawLayer(); + + if (pDrawView) + pDrawView->UpdateUserViewOptions(); + + if (bGraphicsChanged) + DrawEnableAnim(sal_True); // DrawEnableAnim checks the options state + + // if TabBar is set to visible, make sure its size is not 0 + sal_Bool bGrow = ( aViewData.IsTabMode() && pTabControl->GetSizePixel().Width() <= 0 ); + + // if ScrollBar is set to visible, TabBar must make room + sal_Bool bShrink = ( bHScrollChanged && aViewData.IsTabMode() && aViewData.IsHScrollMode() && + pTabControl->GetSizePixel().Width() > SC_TABBAR_DEFWIDTH ); + + if ( bGrow || bShrink ) + { + Size aSize = pTabControl->GetSizePixel(); + aSize.Width() = SC_TABBAR_DEFWIDTH; // initial size + pTabControl->SetSizePixel(aSize); // DoResize is called later... + } +} + +// Helper-Funktion gegen das Include des Drawing Layers + +SdrView* ScTabView::GetSdrView() +{ + return pDrawView; +} + +void ScTabView::DrawMarkListHasChanged() +{ + if ( pDrawView ) + pDrawView->MarkListHasChanged(); +} + +void ScTabView::UpdateAnchorHandles() +{ + if ( pDrawView ) + pDrawView->AdjustMarkHdl(); +} + +void ScTabView::UpdateIMap( SdrObject* pObj ) +{ + if ( pDrawView ) + pDrawView->UpdateIMap( pObj ); +} + +void ScTabView::DrawMarkRect( const Rectangle& rRect ) +{ + //! store rectangle for repaint during drag + + for (sal_uInt16 i=0; i<4; i++) + { + if ( pGridWin[i] && pGridWin[i]->IsVisible() ) + { + RasterOp aROp = pGridWin[i]->GetRasterOp(); + sal_Bool bHasLine = pGridWin[i]->IsLineColor(); + Color aLine = pGridWin[i]->GetLineColor(); + sal_Bool bHasFill = pGridWin[i]->IsFillColor(); + Color aFill = pGridWin[i]->GetFillColor(); + + pGridWin[i]->SetRasterOp( ROP_INVERT ); + pGridWin[i]->SetLineColor( COL_BLACK ); + pGridWin[i]->SetFillColor(); + + pGridWin[i]->DrawRect(rRect); + + pGridWin[i]->SetRasterOp(aROp); + if (bHasLine) + pGridWin[i]->SetLineColor(aLine); + else + pGridWin[i]->SetLineColor(); + if (bHasFill) + pGridWin[i]->SetFillColor(aFill); + else + pGridWin[i]->SetFillColor(); + } + } +} + +void ScTabView::DrawEnableAnim(sal_Bool bSet) +{ + sal_uInt16 i; + if ( pDrawView ) + { + // #71040# dont start animations if display of graphics is disabled + // graphics are controlled by VOBJ_TYPE_OLE + if ( bSet && aViewData.GetOptions().GetObjMode(VOBJ_TYPE_OLE) == VOBJ_MODE_SHOW ) + { + if ( !pDrawView->IsAnimationEnabled() ) + { + pDrawView->SetAnimationEnabled(sal_True); + + // Animierte GIFs muessen wieder gestartet werden: + ScDocument* pDoc = aViewData.GetDocument(); + for (i=0; i<4; i++) + if ( pGridWin[i] && pGridWin[i]->IsVisible() ) + pDoc->StartAnimations( aViewData.GetTabNo(), pGridWin[i] ); + } + } + else + { + pDrawView->SetAnimationEnabled(sal_False); + } + } +} + +//HMHvoid ScTabView::DrawShowMarkHdl(sal_Bool bShow) +//HMH{ + //HMHif (!pDrawView) + //HMH return; + + //HMHif (bShow) + //HMH{ + //HMH if (!pDrawView->IsDisableHdl()) + //HMH pDrawView->ShowMarkHdl(); + //HMH} + //HMHelse + //HMH pDrawView->HideMarkHdl(); +//HMH} + +void ScTabView::UpdateDrawTextOutliner() +{ + if ( pDrawView ) + { + Outliner* pOL = pDrawView->GetTextEditOutliner(); + if (pOL) + aViewData.UpdateOutlinerFlags( *pOL ); + } +} + +void ScTabView::DigitLanguageChanged() +{ + LanguageType eNewLang = SC_MOD()->GetOptDigitLanguage(); + for (sal_uInt16 i=0; i<4; i++) + if ( pGridWin[i] ) + pGridWin[i]->SetDigitLanguage( eNewLang ); +} + +//--------------------------------------------------------------- + +void ScTabView::ScrollToObject( SdrObject* pDrawObj ) +{ + if ( pDrawObj ) + MakeVisible( pDrawObj->GetLogicRect() ); +} + +void ScTabView::MakeVisible( const Rectangle& rHMMRect ) +{ + Window* pWin = GetActiveWin(); + Size aWinSize = pWin->GetOutputSizePixel(); + SCTAB nTab = aViewData.GetTabNo(); + + Rectangle aRect = pWin->LogicToPixel( rHMMRect ); + + long nScrollX=0, nScrollY=0; // Pixel + + if ( aRect.Right() >= aWinSize.Width() ) // rechts raus + { + nScrollX = aRect.Right() - aWinSize.Width() + 1; // rechter Rand sichtbar + if ( aRect.Left() < nScrollX ) + nScrollX = aRect.Left(); // links sichtbar (falls zu gross) + } + if ( aRect.Bottom() >= aWinSize.Height() ) // unten raus + { + nScrollY = aRect.Bottom() - aWinSize.Height() + 1; // unterer Rand sichtbar + if ( aRect.Top() < nScrollY ) + nScrollY = aRect.Top(); // oben sichtbar (falls zu gross) + } + + if ( aRect.Left() < 0 ) // links raus + nScrollX = aRect.Left(); // linker Rand sichtbar + if ( aRect.Top() < 0 ) // oben raus + nScrollY = aRect.Top(); // oberer Rand sichtbar + + if (nScrollX || nScrollY) + { + ScDocument* pDoc = aViewData.GetDocument(); + if ( pDoc->IsNegativePage( nTab ) ) + nScrollX = -nScrollX; + + double nPPTX = aViewData.GetPPTX(); + double nPPTY = aViewData.GetPPTY(); + ScSplitPos eWhich = aViewData.GetActivePart(); + SCCOL nPosX = aViewData.GetPosX(WhichH(eWhich)); + SCROW nPosY = aViewData.GetPosY(WhichV(eWhich)); + + long nLinesX=0, nLinesY=0; // Spalten/Zeilen - um mindestens nScrollX/Y scrollen + + if (nScrollX > 0) + while (nScrollX > 0 && nPosX < MAXCOL) + { + nScrollX -= (long) ( pDoc->GetColWidth(nPosX, nTab) * nPPTX ); + ++nPosX; + ++nLinesX; + } + else if (nScrollX < 0) + while (nScrollX < 0 && nPosX > 0) + { + --nPosX; + nScrollX += (long) ( pDoc->GetColWidth(nPosX, nTab) * nPPTX ); + --nLinesX; + } + + if (nScrollY > 0) + while (nScrollY > 0 && nPosY < MAXROW) + { + nScrollY -= (long) ( pDoc->GetRowHeight(nPosY, nTab) * nPPTY ); + ++nPosY; + ++nLinesY; + } + else if (nScrollY < 0) + while (nScrollY < 0 && nPosY > 0) + { + --nPosY; + nScrollY += (long) ( pDoc->GetRowHeight(nPosY, nTab) * nPPTY ); + --nLinesY; + } + + ScrollLines( nLinesX, nLinesY ); // ausfuehren + } +} + +//--------------------------------------------------------------- + +void ScTabView::SetBrushDocument( ScDocument* pNew, sal_Bool bLock ) +{ + delete pBrushDocument; + delete pDrawBrushSet; + + pBrushDocument = pNew; + pDrawBrushSet = NULL; + + bLockPaintBrush = bLock; + + aViewData.GetBindings().Invalidate(SID_FORMATPAINTBRUSH); +} + +void ScTabView::SetDrawBrushSet( SfxItemSet* pNew, sal_Bool bLock ) +{ + delete pBrushDocument; + delete pDrawBrushSet; + + pBrushDocument = NULL; + pDrawBrushSet = pNew; + + bLockPaintBrush = bLock; + + aViewData.GetBindings().Invalidate(SID_FORMATPAINTBRUSH); +} + +void ScTabView::ResetBrushDocument() +{ + if ( HasPaintBrush() ) + { + SetBrushDocument( NULL, sal_False ); + SetActivePointer( Pointer( POINTER_ARROW ) ); // switch pointers also when ended with escape key + } +} + + diff --git a/sc/source/ui/view/tabvwsh.cxx b/sc/source/ui/view/tabvwsh.cxx new file mode 100644 index 000000000000..bdeb74a2d101 --- /dev/null +++ b/sc/source/ui/view/tabvwsh.cxx @@ -0,0 +1,111 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +//------------------------------------------------------------------ +// INCLUDE --------------------------------------------------------------- + +#include "scitems.hxx" +#include <svx/galbrws.hxx> +#include <svx/imapdlg.hxx> +#include <svl/srchitem.hxx> +#include <sfx2/templdlg.hxx> +#include <sfx2/objface.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/app.hxx> +#include <avmedia/mediaplayer.hxx> + +#include "tabvwsh.hxx" +#include "docsh.hxx" +#include "reffact.hxx" +#include "scresid.hxx" +#include "dwfunctr.hxx" +#include "sc.hrc" // -> SID_TOOL_xxx +#include "drawattr.hxx" // -> SvxDrawToolItem +#include "spelldialog.hxx" + + +#define ScTabViewShell +#include "scslots.hxx" + +TYPEINIT2(ScTabViewShell,SfxViewShell,SfxListener); + +SFX_IMPL_INTERFACE(ScTabViewShell,SfxViewShell,ScResId(SCSTR_TABVIEWSHELL)) +{ + SFX_OBJECTBAR_REGISTRATION( SFX_OBJECTBAR_TOOLS | SFX_VISIBILITY_STANDARD | + SFX_VISIBILITY_FULLSCREEN | SFX_VISIBILITY_SERVER, + ScResId(RID_OBJECTBAR_TOOLS) ); + + SFX_CHILDWINDOW_REGISTRATION(FID_INPUTLINE_STATUS); + SFX_CHILDWINDOW_REGISTRATION(SfxTemplateDialogWrapper::GetChildWindowId()); + SFX_CHILDWINDOW_CONTEXT_REGISTRATION(SID_NAVIGATOR); + SFX_CHILDWINDOW_REGISTRATION(SID_TASKPANE); + SFX_CHILDWINDOW_REGISTRATION(ScNameDlgWrapper::GetChildWindowId()); + SFX_CHILDWINDOW_REGISTRATION(ScSolverDlgWrapper::GetChildWindowId()); + SFX_CHILDWINDOW_REGISTRATION(ScOptSolverDlgWrapper::GetChildWindowId()); + SFX_CHILDWINDOW_REGISTRATION(ScPivotLayoutWrapper::GetChildWindowId()); + SFX_CHILDWINDOW_REGISTRATION(ScTabOpDlgWrapper::GetChildWindowId()); + SFX_CHILDWINDOW_REGISTRATION(ScFilterDlgWrapper::GetChildWindowId()); + SFX_CHILDWINDOW_REGISTRATION(ScSpecialFilterDlgWrapper::GetChildWindowId()); + SFX_CHILDWINDOW_REGISTRATION(ScDbNameDlgWrapper::GetChildWindowId()); + SFX_CHILDWINDOW_REGISTRATION(ScConsolidateDlgWrapper::GetChildWindowId()); + SFX_CHILDWINDOW_REGISTRATION(ScPrintAreasDlgWrapper::GetChildWindowId()); + SFX_CHILDWINDOW_REGISTRATION(ScCondFormatDlgWrapper::GetChildWindowId()); + SFX_CHILDWINDOW_REGISTRATION(ScColRowNameRangesDlgWrapper::GetChildWindowId()); + SFX_CHILDWINDOW_REGISTRATION(ScFormulaDlgWrapper::GetChildWindowId()); + SFX_CHILDWINDOW_REGISTRATION(SvxIMapDlgChildWindow::GetChildWindowId()); + SFX_CHILDWINDOW_REGISTRATION(ScFunctionChildWindow::GetChildWindowId()); + SFX_CHILDWINDOW_REGISTRATION(ScFormulaDlgWrapper::GetChildWindowId()); + SFX_CHILDWINDOW_REGISTRATION(ScAcceptChgDlgWrapper::GetChildWindowId()); + SFX_CHILDWINDOW_REGISTRATION(ScHighlightChgDlgWrapper::GetChildWindowId()); + SFX_CHILDWINDOW_REGISTRATION(ScSimpleRefDlgWrapper::GetChildWindowId()); + SFX_CHILDWINDOW_REGISTRATION(SID_SEARCH_DLG); + SFX_CHILDWINDOW_REGISTRATION(SID_HYPERLINK_DIALOG); + SFX_CHILDWINDOW_REGISTRATION(GalleryChildWindow::GetChildWindowId()); + SFX_CHILDWINDOW_REGISTRATION(ScSpellDialogChildWindow::GetChildWindowId()); + SFX_CHILDWINDOW_REGISTRATION( ::avmedia::MediaPlayer::GetChildWindowId() ); + SFX_CHILDWINDOW_REGISTRATION(ScValidityRefChildWin::GetChildWindowId()); +} + +SFX_IMPL_NAMED_VIEWFACTORY( ScTabViewShell, "Default" ) +{ + SFX_VIEW_REGISTRATION(ScDocShell); +} + +//------------------------------------------------------------------ + +IMPL_LINK( ScTabViewShell, HtmlOptionsHdl, void*, EMPTYARG ) +{ + // Invalidierung, falls blinkender Text erlaubt/verboten wurde + GetViewFrame()->GetBindings().Invalidate(SID_DRAW_TEXT_MARQUEE); + return 0; +} diff --git a/sc/source/ui/view/tabvwsh2.cxx b/sc/source/ui/view/tabvwsh2.cxx new file mode 100644 index 000000000000..64b60caf6f4e --- /dev/null +++ b/sc/source/ui/view/tabvwsh2.cxx @@ -0,0 +1,481 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#ifdef _MSC_VER +#pragma optimize ("", off) +#endif + +#include <sfx2/bindings.hxx> +#include <sfx2/viewfrm.hxx> +#include <svl/aeitem.hxx> +#include <svl/whiter.hxx> +#include <unotools/moduleoptions.hxx> +#include <svl/languageoptions.hxx> +#include <sfx2/dispatch.hxx> + +#include "tabvwsh.hxx" +#include "drawattr.hxx" +#include "drawsh.hxx" +#include "drawview.hxx" +#include "fupoor.hxx" +#include "fuconrec.hxx" +#include "fuconpol.hxx" +#include "fuconarc.hxx" +#include "fuconuno.hxx" +#include "fusel.hxx" +#include "futext.hxx" +#include "fumark.hxx" +#include "fuinsert.hxx" +#include "global.hxx" +#include "sc.hrc" +#include "scmod.hxx" +#include "appoptio.hxx" + +// #98185# Create default drawing objects via keyboard +#include <svx/svdpagv.hxx> +#include <svl/stritem.hxx> +#include <svx/svdpage.hxx> +#include <fuconcustomshape.hxx> + +// ----------------------------------------------------------------------- + +SdrView* __EXPORT ScTabViewShell::GetDrawView() const +{ + return ((ScTabViewShell*)this)->GetScDrawView(); // GetScDrawView ist nicht-const +} + +void ScTabViewShell::WindowChanged() +{ + Window* pWin = GetActiveWin(); + + ScDrawView* pDrView = GetScDrawView(); + if (pDrView) + pDrView->SetActualWin(pWin); + + FuPoor* pFunc = GetDrawFuncPtr(); + if (pFunc) + pFunc->SetWindow(pWin); + + // when font from InputContext is used, + // this must be moved to change of cursor position: + UpdateInputContext(); +} + +void ScTabViewShell::ExecDraw(SfxRequest& rReq) +{ + SC_MOD()->InputEnterHandler(); + UpdateInputHandler(); + + MakeDrawLayer(); + + ScTabView* pTabView = GetViewData()->GetView(); + SfxBindings& rBindings = GetViewFrame()->GetBindings(); + + Window* pWin = pTabView->GetActiveWin(); + ScDrawView* pView = pTabView->GetScDrawView(); + SdrModel* pDoc = pView->GetModel(); + + const SfxItemSet *pArgs = rReq.GetArgs(); + sal_uInt16 nNewId = rReq.GetSlot(); + + if ( nNewId == SID_DRAW_CHART ) + { + // #i71254# directly insert a chart instead of drawing its output rectangle + FuInsertChart(this, pWin, pView, pDoc, rReq); + return; + } + + // + // Pseudo-Slots von Draw-Toolbox auswerten + //! wird das ueberhaupt noch gebraucht ????? + // + + if (nNewId == SID_INSERT_DRAW && pArgs) + { + const SfxPoolItem* pItem; + if ( pArgs->GetItemState( SID_INSERT_DRAW, sal_True, &pItem ) == SFX_ITEM_SET && + pItem->ISA( SvxDrawToolItem ) ) + { + SvxDrawToolEnum eSel = (SvxDrawToolEnum)((const SvxDrawToolItem*)pItem)->GetValue(); + switch (eSel) + { + case SVX_SNAP_DRAW_SELECT: nNewId = SID_OBJECT_SELECT; break; + case SVX_SNAP_DRAW_LINE: nNewId = SID_DRAW_LINE; break; + case SVX_SNAP_DRAW_RECT: nNewId = SID_DRAW_RECT; break; + case SVX_SNAP_DRAW_ELLIPSE: nNewId = SID_DRAW_ELLIPSE; break; + case SVX_SNAP_DRAW_POLYGON_NOFILL: nNewId = SID_DRAW_POLYGON_NOFILL; break; + case SVX_SNAP_DRAW_BEZIER_NOFILL: nNewId = SID_DRAW_BEZIER_NOFILL; break; + case SVX_SNAP_DRAW_FREELINE_NOFILL: nNewId = SID_DRAW_FREELINE_NOFILL; break; + case SVX_SNAP_DRAW_ARC: nNewId = SID_DRAW_ARC; break; + case SVX_SNAP_DRAW_PIE: nNewId = SID_DRAW_PIE; break; + case SVX_SNAP_DRAW_CIRCLECUT: nNewId = SID_DRAW_CIRCLECUT; break; + case SVX_SNAP_DRAW_TEXT: nNewId = SID_DRAW_TEXT; break; + case SVX_SNAP_DRAW_TEXT_VERTICAL: nNewId = SID_DRAW_TEXT_VERTICAL; break; + case SVX_SNAP_DRAW_TEXT_MARQUEE: nNewId = SID_DRAW_TEXT_MARQUEE; break; + case SVX_SNAP_DRAW_CAPTION: nNewId = SID_DRAW_CAPTION; break; + case SVX_SNAP_DRAW_CAPTION_VERTICAL: nNewId = SID_DRAW_CAPTION_VERTICAL; break; + } + } + else // sal_uInt16-Item vom Controller + { + rReq.Done(); + return; + } + } + + if ( nNewId == SID_DRAW_SELECT ) + nNewId = SID_OBJECT_SELECT; + + sal_uInt16 nNewFormId = 0; + if ( nNewId == SID_FM_CREATE_CONTROL && pArgs ) + { + const SfxPoolItem* pItem; + if ( pArgs->GetItemState( SID_FM_CONTROL_IDENTIFIER, sal_True, &pItem ) == SFX_ITEM_SET && + pItem->ISA( SfxUInt16Item ) ) + nNewFormId = ((const SfxUInt16Item*)pItem)->GetValue(); + } + + String sStringItemValue; + if ( pArgs ) + { + const SfxPoolItem* pItem; + if ( pArgs->GetItemState( nNewId, sal_True, &pItem ) == SFX_ITEM_SET && pItem->ISA( SfxStringItem ) ) + sStringItemValue = static_cast<const SfxStringItem*>(pItem)->GetValue(); + } + bool bSwitchCustom = ( sStringItemValue.Len() && sDrawCustom.Len() && sStringItemValue != sDrawCustom ); + + if (nNewId == SID_INSERT_FRAME) // vom Tbx-Button + nNewId = SID_DRAW_TEXT; + + // #97016# CTRL-SID_OBJECT_SELECT is used to select the first object, + // but not if SID_OBJECT_SELECT is the result of clicking a create function again, + // so this must be tested before changing nNewId below. + sal_Bool bSelectFirst = ( nNewId == SID_OBJECT_SELECT && (rReq.GetModifier() & KEY_MOD1) ); + + sal_Bool bEx = IsDrawSelMode(); + if ( rReq.GetModifier() & KEY_MOD1 ) + { + // #97016# always allow keyboard selection also on background layer + // #98185# also allow creation of default objects if the same object type + // was already active + bEx = sal_True; + } + else if ( nNewId == nDrawSfxId && ( nNewId != SID_FM_CREATE_CONTROL || + nNewFormId == nFormSfxId || nNewFormId == 0 ) && !bSwitchCustom ) + { + // #i52871# if a different custom shape is selected, the slot id can be the same, + // so the custom shape type string has to be compared, too. + + // SID_FM_CREATE_CONTROL mit nNewFormId==0 (ohne Parameter) kommt beim Deaktivieren + // aus FuConstruct::SimpleMouseButtonUp + // #59280# Execute fuer die Form-Shell, um im Controller zu deselektieren + if ( nNewId == SID_FM_CREATE_CONTROL ) + { + GetViewData()->GetDispatcher().Execute(SID_FM_LEAVE_CREATE); + GetViewFrame()->GetBindings().InvalidateAll(sal_False); + //! was fuer einen Slot braucht der komische Controller wirklich, um das anzuzeigen???? + } + + bEx = !bEx; + nNewId = SID_OBJECT_SELECT; + } + else + bEx = sal_True; + + if ( nDrawSfxId == SID_FM_CREATE_CONTROL && nNewId != nDrawSfxId ) + { + // Wechsel von Control- zu Zeichenfunktion -> im Control-Controller deselektieren + GetViewData()->GetDispatcher().Execute(SID_FM_LEAVE_CREATE); + GetViewFrame()->GetBindings().InvalidateAll(sal_False); + //! was fuer einen Slot braucht der komische Controller wirklich, um das anzuzeigen???? + } + + SetDrawSelMode(bEx); + + pView->LockBackgroundLayer( !bEx ); + + if ( bSelectFirst ) + { + // #97016# select first draw object if none is selected yet + if(!pView->AreObjectsMarked()) + { + // select first object + pView->UnmarkAllObj(); + pView->MarkNextObj(sal_True); + + // ...and make it visible + if(pView->AreObjectsMarked()) + pView->MakeVisible(pView->GetAllMarkedRect(), *pWin); + } + } + + nDrawSfxId = nNewId; + sDrawCustom.Erase(); // value is set below for custom shapes + + if ( nNewId != SID_DRAW_CHART ) // Chart nicht mit DrawShell + { + if ( nNewId == SID_DRAW_TEXT || nNewId == SID_DRAW_TEXT_VERTICAL || + nNewId == SID_DRAW_TEXT_MARQUEE || nNewId == SID_DRAW_NOTEEDIT ) + SetDrawTextShell( sal_True ); + else + { + if ( bEx || pView->GetMarkedObjectList().GetMarkCount() != 0 ) + SetDrawShellOrSub(); + else + SetDrawShell( sal_False ); + } + } + + if (pTabView->GetDrawFuncPtr()) + { + if (pTabView->GetDrawFuncOldPtr() != pTabView->GetDrawFuncPtr()) + delete pTabView->GetDrawFuncOldPtr(); + + pTabView->GetDrawFuncPtr()->Deactivate(); + pTabView->SetDrawFuncOldPtr(pTabView->GetDrawFuncPtr()); + pTabView->SetDrawFuncPtr(NULL); + } + + SfxRequest aNewReq(rReq); + aNewReq.SetSlot(nDrawSfxId); + + switch (nNewId) + { + case SID_OBJECT_SELECT: + //@#70206# Nicht immer zurueckschalten + if(pView->GetMarkedObjectList().GetMarkCount() == 0) SetDrawShell(bEx); + pTabView->SetDrawFuncPtr(new FuSelection(this, pWin, pView, pDoc, aNewReq)); + break; + + case SID_DRAW_LINE: + case SID_DRAW_RECT: + case SID_DRAW_ELLIPSE: + pTabView->SetDrawFuncPtr(new FuConstRectangle(this, pWin, pView, pDoc, aNewReq)); + break; + + case SID_DRAW_CAPTION: + case SID_DRAW_CAPTION_VERTICAL: + pTabView->SetDrawFuncPtr(new FuConstRectangle(this, pWin, pView, pDoc, aNewReq)); + pView->SetFrameDragSingles( sal_False ); + rBindings.Invalidate( SID_BEZIER_EDIT ); + break; + + case SID_DRAW_POLYGON: + case SID_DRAW_POLYGON_NOFILL: + case SID_DRAW_BEZIER_NOFILL: + case SID_DRAW_FREELINE_NOFILL: + pTabView->SetDrawFuncPtr(new FuConstPolygon(this, pWin, pView, pDoc, aNewReq)); + break; + + case SID_DRAW_ARC: + case SID_DRAW_PIE: + case SID_DRAW_CIRCLECUT: + pTabView->SetDrawFuncPtr(new FuConstArc(this, pWin, pView, pDoc, aNewReq)); + break; + + case SID_DRAW_TEXT: + case SID_DRAW_TEXT_VERTICAL: + case SID_DRAW_TEXT_MARQUEE: + case SID_DRAW_NOTEEDIT: + pTabView->SetDrawFuncPtr(new FuText(this, pWin, pView, pDoc, aNewReq)); + break; + + case SID_FM_CREATE_CONTROL: + SetDrawFormShell(sal_True); + pTabView->SetDrawFuncPtr(new FuConstUnoControl(this, pWin, pView, pDoc, aNewReq)); + nFormSfxId = nNewFormId; + break; + + case SID_DRAW_CHART: +//UNUSED2008-05 bChartDlgIsEdit = sal_False; + pTabView->SetDrawFuncPtr(new FuMarkRect(this, pWin, pView, pDoc, aNewReq)); + break; + + case SID_DRAWTBX_CS_BASIC : + case SID_DRAWTBX_CS_SYMBOL : + case SID_DRAWTBX_CS_ARROW : + case SID_DRAWTBX_CS_FLOWCHART : + case SID_DRAWTBX_CS_CALLOUT : + case SID_DRAWTBX_CS_STAR : + case SID_DRAW_CS_ID : + { + pTabView->SetDrawFuncPtr( new FuConstCustomShape( this, pWin, pView, pDoc, aNewReq )); + if ( nNewId != SID_DRAW_CS_ID ) + { + SFX_REQUEST_ARG( rReq, pEnumCommand, SfxStringItem, nNewId, sal_False ); + if ( pEnumCommand ) + { + aCurrShapeEnumCommand[ nNewId - SID_DRAWTBX_CS_BASIC ] = pEnumCommand->GetValue(); + SfxBindings& rBind = GetViewFrame()->GetBindings(); + rBind.Invalidate( nNewId ); + rBind.Update( nNewId ); + + sDrawCustom = pEnumCommand->GetValue(); // to detect when a different shape type is selected + } + } + } + break; + + default: + break; + } + + if (pTabView->GetDrawFuncPtr()) + pTabView->GetDrawFuncPtr()->Activate(); + + rReq.Done(); + + rBindings.Invalidate( SID_INSERT_DRAW ); + rBindings.Update( SID_INSERT_DRAW ); + + // #98185# Create default drawing objects via keyboard + // with qualifier construct directly + FuPoor* pFuActual = GetDrawFuncPtr(); + + if(pFuActual && (rReq.GetModifier() & KEY_MOD1)) + { + // #98185# Create default drawing objects via keyboard + const ScAppOptions& rAppOpt = SC_MOD()->GetAppOptions(); + sal_uInt32 nDefaultObjectSizeWidth = rAppOpt.GetDefaultObjectSizeWidth(); + sal_uInt32 nDefaultObjectSizeHeight = rAppOpt.GetDefaultObjectSizeHeight(); + + // calc position and size + Rectangle aVisArea = pWin->PixelToLogic(Rectangle(Point(0,0), pWin->GetOutputSizePixel())); + Point aPagePos = aVisArea.Center(); + aPagePos.X() -= nDefaultObjectSizeWidth / 2; + aPagePos.Y() -= nDefaultObjectSizeHeight / 2; + Rectangle aNewObjectRectangle(aPagePos, Size(nDefaultObjectSizeWidth, nDefaultObjectSizeHeight)); + + ScDrawView* pDrView = GetScDrawView(); + + if(pDrView) + { + SdrPageView* pPageView = pDrView->GetSdrPageView(); + + if(pPageView) + { + // create the default object + SdrObject* pObj = pFuActual->CreateDefaultObject(nNewId, aNewObjectRectangle); + + if(pObj) + { + // insert into page + pView->InsertObjectAtView(pObj, *pPageView); + + if ( nNewId == SID_DRAW_CAPTION || nNewId == SID_DRAW_CAPTION_VERTICAL ) + { + // #105815# use KeyInput to start edit mode (FuText is created). + // For FuText objects, edit mode is handled within CreateDefaultObject. + // KEY_F2 is handled in FuDraw::KeyInput. + + pFuActual->KeyInput( KeyEvent( 0, KeyCode( KEY_F2 ) ) ); + } + } + } + } + } +} + +void ScTabViewShell::GetDrawState(SfxItemSet &rSet) +{ + SfxWhichIter aIter(rSet); + sal_uInt16 nWhich = aIter.FirstWhich(); + + while ( nWhich ) + { + switch ( nWhich ) + { + case SID_INSERT_DRAW: + { + // SID_OBJECT_SELECT nur, wenn "harter" Selektionsmodus + sal_uInt16 nPutId = nDrawSfxId; + if ( nPutId == SID_OBJECT_SELECT && !IsDrawSelMode() ) + nPutId = USHRT_MAX; + // nur die Images, die auch auf dem Controller liegen + if ( nPutId != SID_OBJECT_SELECT && + nPutId != SID_DRAW_LINE && + nPutId != SID_DRAW_RECT && + nPutId != SID_DRAW_ELLIPSE && + nPutId != SID_DRAW_POLYGON_NOFILL && + nPutId != SID_DRAW_BEZIER_NOFILL && + nPutId != SID_DRAW_FREELINE_NOFILL && + nPutId != SID_DRAW_ARC && + nPutId != SID_DRAW_PIE && + nPutId != SID_DRAW_CIRCLECUT && + nPutId != SID_DRAW_TEXT && + nPutId != SID_DRAW_TEXT_VERTICAL && + nPutId != SID_DRAW_TEXT_MARQUEE && + nPutId != SID_DRAW_CAPTION && + nPutId != SID_DRAW_CAPTION_VERTICAL ) + nPutId = USHRT_MAX; + SfxAllEnumItem aItem( nWhich, nPutId ); + if ( !SvtLanguageOptions().IsVerticalTextEnabled() ) + { + aItem.DisableValue( SID_DRAW_TEXT_VERTICAL ); + aItem.DisableValue( SID_DRAW_CAPTION_VERTICAL ); + } + rSet.Put( aItem ); + } + break; + + case SID_DRAW_CHART: + { + sal_Bool bOle = GetViewFrame()->GetFrame().IsInPlace(); + if ( bOle || !SvtModuleOptions().IsChart() ) + rSet.DisableItem( nWhich ); + } + break; + + case SID_OBJECT_SELECT: // wichtig fuer den ollen Control-Controller + rSet.Put( SfxBoolItem( nWhich, nDrawSfxId == SID_OBJECT_SELECT && IsDrawSelMode() ) ); + break; + } + nWhich = aIter.NextWhich(); + } +} + +sal_Bool ScTabViewShell::SelectObject( const String& rName ) +{ + ScDrawView* pView = GetViewData()->GetScDrawView(); + if (!pView) + return sal_False; + + sal_Bool bFound = pView->SelectObject( rName ); + // DrawShell etc. is handled in MarkListHasChanged + + return bFound; +} + + + diff --git a/sc/source/ui/view/tabvwsh3.cxx b/sc/source/ui/view/tabvwsh3.cxx new file mode 100644 index 000000000000..79f63f873916 --- /dev/null +++ b/sc/source/ui/view/tabvwsh3.cxx @@ -0,0 +1,1234 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include "scitems.hxx" +#include <editeng/eeitem.hxx> + +#include <sfx2/app.hxx> +//CHINA001 #include <svx/zoom.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/passwd.hxx> +#include <sfx2/request.hxx> +#include <svl/ptitem.hxx> +#include <svl/stritem.hxx> +#include <tools/urlobj.hxx> +#include <sfx2/objface.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/vclenum.hxx> + +#include "globstr.hrc" +#include "scmod.hxx" +#include "appoptio.hxx" +#include "tabvwsh.hxx" +#include "document.hxx" +#include "sc.hrc" +#include "inputwin.hxx" +#include "scresid.hxx" +#include "printfun.hxx" +#include "docsh.hxx" +#include "rangelst.hxx" +#include "prevwsh.hxx" +#include "rangeutl.hxx" +#include "reffact.hxx" +#include "uiitems.hxx" +#include "cell.hxx" +#include "inputhdl.hxx" +//CHINA001 #include "scendlg.hxx" +//CHINA001 #include "mtrindlg.hxx" +#include "autoform.hxx" +#include "autofmt.hxx" +#include "dwfunctr.hxx" +#include "shtabdlg.hxx" +#include "tabprotection.hxx" +#include "protectiondlg.hxx" + +#include <svl/ilstitem.hxx> +#define _SVSTDARR_ULONGS +#include <svl/svstdarr.hxx> + +#include <svx/zoomslideritem.hxx> +#include <svx/svxdlg.hxx> //CHINA001 +#include <svx/dialogs.hrc> //CHINA001 +#include "scabstdlg.hxx" //CHINA001 + +#include <memory> + +using ::std::auto_ptr; + +#define IS_EDITMODE() GetViewData()->HasEditView( GetViewData()->GetActivePart() ) +#define IS_AVAILABLE(WhichId,ppItem) \ + (pReqArgs->GetItemState((WhichId), sal_True, ppItem ) == SFX_ITEM_SET) +#define GET_STRING(nid) ((const SfxStringItem&)pReqArgs->Get(nid)).GetValue() +#define GET_UINT16(nid) ((const SfxUInt16Item&)pReqArgs->Get(nid)).GetValue() +#define GET_BOOL(nid) ((const SfxBoolItem&)pReqArgs->Get(nid)).GetValue() +#define RECALC_PAGE(pDocSh) ScPrintFunc( pDocSh, GetPrinter(), nCurTab ).UpdatePages() + +//------------------------------------------------------------------ + +/** Try to parse the given range using Calc-style syntax first, then + Excel-style if that fails. */ +sal_uInt16 lcl_ParseRange(ScRange& rScRange, const String& aAddress, ScDocument* pDoc, sal_uInt16 /* nSlot */) +{ + sal_uInt16 nResult = rScRange.Parse(aAddress, pDoc); + if ( (nResult & SCA_VALID) ) + return nResult; + + return rScRange.Parse(aAddress, pDoc, ScAddress::Details(formula::FormulaGrammar::CONV_XL_A1, 0, 0)); +} + +/** Try to parse the given address using Calc-style syntax first, then + Excel-style if that fails. */ +sal_uInt16 lcl_ParseAddress(ScAddress& rScAddress, const String& aAddress, ScDocument* pDoc, sal_uInt16 /* nSlot */) +{ + sal_uInt16 nResult = rScAddress.Parse(aAddress, pDoc); + if ( (nResult & SCA_VALID) ) + return nResult; + + return rScAddress.Parse(aAddress, pDoc, ScAddress::Details(formula::FormulaGrammar::CONV_XL_A1, 0, 0)); +} + +void ScTabViewShell::Execute( SfxRequest& rReq ) +{ + SfxViewFrame* pThisFrame = GetViewFrame(); + SfxBindings& rBindings = pThisFrame->GetBindings(); + ScModule* pScMod = SC_MOD(); + const SfxItemSet* pReqArgs = rReq.GetArgs(); + sal_uInt16 nSlot = rReq.GetSlot(); + + if (nSlot != SID_CURRENTCELL) // der kommt beim MouseButtonUp + HideListBox(); // Autofilter-DropDown-Listbox + + switch ( nSlot ) + { + case FID_INSERT_FILE: + { + const SfxPoolItem* pItem; + if ( pReqArgs && + pReqArgs->GetItemState(FID_INSERT_FILE,sal_True,&pItem) == SFX_ITEM_SET ) + { + String aFileName = ((const SfxStringItem*)pItem)->GetValue(); + + // Einfuege-Position + + Point aInsertPos; + if ( pReqArgs->GetItemState(FN_PARAM_1,sal_True,&pItem) == SFX_ITEM_SET ) + aInsertPos = ((const SfxPointItem*)pItem)->GetValue(); + else + aInsertPos = GetInsertPos(); + + // als Link? + + sal_Bool bAsLink = sal_False; + if ( pReqArgs->GetItemState(FN_PARAM_2,sal_True,&pItem) == SFX_ITEM_SET ) + bAsLink = ((const SfxBoolItem*)pItem)->GetValue(); + + // ausfuehren + + PasteFile( aInsertPos, aFileName, bAsLink ); + } + } + break; + + case SID_OPENDLG_EDIT_PRINTAREA: + { + sal_uInt16 nId = ScPrintAreasDlgWrapper::GetChildWindowId(); + SfxChildWindow* pWnd = pThisFrame->GetChildWindow( nId ); + + pScMod->SetRefDialog( nId, pWnd ? sal_False : sal_True ); + } + break; + + case SID_CHANGE_PRINTAREA: + { + if ( pReqArgs ) // OK aus Dialog + { + String aPrintStr; + String aRowStr; + String aColStr; + sal_Bool bEntire = sal_False; + const SfxPoolItem* pItem; + if ( pReqArgs->GetItemState( SID_CHANGE_PRINTAREA, sal_True, &pItem ) == SFX_ITEM_SET ) + aPrintStr = static_cast<const SfxStringItem*>(pItem)->GetValue(); + if ( pReqArgs->GetItemState( FN_PARAM_2, sal_True, &pItem ) == SFX_ITEM_SET ) + aRowStr = static_cast<const SfxStringItem*>(pItem)->GetValue(); + if ( pReqArgs->GetItemState( FN_PARAM_3, sal_True, &pItem ) == SFX_ITEM_SET ) + aColStr = static_cast<const SfxStringItem*>(pItem)->GetValue(); + if ( pReqArgs->GetItemState( FN_PARAM_4, sal_True, &pItem ) == SFX_ITEM_SET ) + bEntire = static_cast<const SfxBoolItem*>(pItem)->GetValue(); + + SetPrintRanges( bEntire, &aPrintStr, &aColStr, &aRowStr, sal_False ); + + rReq.Done(); + } + } + break; + + case SID_ADD_PRINTAREA: + case SID_DEFINE_PRINTAREA: // Menue oder Basic + { + sal_Bool bAdd = ( nSlot == SID_ADD_PRINTAREA ); + if ( pReqArgs ) + { + String aPrintStr; + const SfxPoolItem* pItem; + if ( pReqArgs->GetItemState( SID_DEFINE_PRINTAREA, sal_True, &pItem ) == SFX_ITEM_SET ) + aPrintStr = static_cast<const SfxStringItem*>(pItem)->GetValue(); + SetPrintRanges( sal_False, &aPrintStr, NULL, NULL, bAdd ); + } + else + { + SetPrintRanges( sal_False, NULL, NULL, NULL, bAdd ); // aus Selektion + rReq.Done(); + } + } + break; + + case SID_DELETE_PRINTAREA: + { + String aEmpty; + SetPrintRanges( sal_False, &aEmpty, NULL, NULL, sal_False ); // Druckbereich loeschen + rReq.Done(); + } + break; + + case FID_DEL_MANUALBREAKS: + RemoveManualBreaks(); + rReq.Done(); + break; + + case FID_ADJUST_PRINTZOOM: + AdjustPrintZoom(); + rReq.Done(); + break; + + case FID_RESET_PRINTZOOM: + SetPrintZoom( 100, 0 ); // 100%, nicht auf Seiten + rReq.Done(); + break; + + case SID_FORMATPAGE: + case SID_STATUS_PAGESTYLE: + case SID_HFEDIT: + GetViewData()->GetDocShell()-> + ExecutePageStyle( *this, rReq, GetViewData()->GetTabNo() ); + break; + + case SID_JUMPTOMARK: + case SID_CURRENTCELL: + if ( pReqArgs ) + { + String aAddress; + const SfxPoolItem* pItem; + if ( pReqArgs->GetItemState( nSlot, sal_True, &pItem ) == SFX_ITEM_SET ) + aAddress = ((const SfxStringItem*)pItem)->GetValue(); + else if ( nSlot == SID_JUMPTOMARK && pReqArgs->GetItemState( + SID_JUMPTOMARK, sal_True, &pItem ) == SFX_ITEM_SET ) + aAddress = ((const SfxStringItem*)pItem)->GetValue(); + + // #i14927# SID_CURRENTCELL with a single cell must unmark if FN_PARAM_1 + // isn't set (for recorded macros, because IsAPI is no longer available). + // ScGridWindow::MouseButtonUp no longer executes the slot for a single + // cell if there is a multi selection. + sal_Bool bUnmark = ( nSlot == SID_CURRENTCELL ); + if ( pReqArgs->GetItemState( FN_PARAM_1, sal_True, &pItem ) == SFX_ITEM_SET ) + bUnmark = ((const SfxBoolItem*)pItem)->GetValue(); + + if ( nSlot == SID_JUMPTOMARK ) + { + // #106586# URL has to be decoded for escaped characters (%20) + aAddress = INetURLObject::decode( aAddress, INET_HEX_ESCAPE, + INetURLObject::DECODE_WITH_CHARSET, + RTL_TEXTENCODING_UTF8 ); + } + + sal_Bool bFound = sal_False; + ScViewData* pViewData = GetViewData(); + ScDocument* pDoc = pViewData->GetDocument(); + ScMarkData& rMark = pViewData->GetMarkData(); + ScRange aScRange; + ScAddress aScAddress; + sal_uInt16 nResult = lcl_ParseRange(aScRange, aAddress, pDoc, nSlot); + SCTAB nTab = pViewData->GetTabNo(); + sal_Bool bMark = sal_True; + + // Is this a range ? + if( nResult & SCA_VALID ) + { + if ( nResult & SCA_TAB_3D ) + { + if( aScRange.aStart.Tab() != nTab ) + SetTabNo( nTab = aScRange.aStart.Tab() ); + } + else + { + aScRange.aStart.SetTab( nTab ); + aScRange.aEnd.SetTab( nTab ); + } + } + // Is this a cell ? + else if ( (nResult = lcl_ParseAddress(aScAddress, aAddress, pDoc, nSlot)) & SCA_VALID ) + { + if ( nResult & SCA_TAB_3D ) + { + if( aScAddress.Tab() != nTab ) + SetTabNo( nTab = aScAddress.Tab() ); + } + else + aScAddress.SetTab( nTab ); + + aScRange = ScRange( aScAddress, aScAddress ); + // Zellen sollen nicht markiert werden + bMark = sal_False; + } + // Ist es benahmster Bereich (erst Namen dann DBBereiche) ? + else + { + ScRangeUtil aRangeUtil; + formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention(); + if( aRangeUtil.MakeRangeFromName( aAddress, pDoc, nTab, aScRange, RUTL_NAMES, eConv ) || + aRangeUtil.MakeRangeFromName( aAddress, pDoc, nTab, aScRange, RUTL_DBASE, eConv ) ) + { + nResult |= SCA_VALID; + if( aScRange.aStart.Tab() != nTab ) + SetTabNo( nTab = aScRange.aStart.Tab() ); + } + } + + if ( !(nResult & SCA_VALID) && + ByteString(aAddress, RTL_TEXTENCODING_ASCII_US).IsNumericAscii() ) + { + sal_Int32 nNumeric = aAddress.ToInt32(); + if ( nNumeric > 0 && nNumeric <= MAXROW+1 ) + { + // 1-basierte Zeilennummer + + aScAddress.SetRow( (SCROW)(nNumeric - 1) ); + aScAddress.SetCol( pViewData->GetCurX() ); + aScAddress.SetTab( nTab ); + aScRange = ScRange( aScAddress, aScAddress ); + bMark = sal_False; + nResult = SCA_VALID; + } + } + + if ( !ValidRow(aScRange.aStart.Row()) || !ValidRow(aScRange.aEnd.Row()) ) + nResult = 0; + + // wir haben was gefunden + if( nResult & SCA_VALID ) + { + bFound = sal_True; + SCCOL nCol = aScRange.aStart.Col(); + SCROW nRow = aScRange.aStart.Row(); + sal_Bool bNothing = ( pViewData->GetCurX()==nCol && pViewData->GetCurY()==nRow ); + + // markieren + if( bMark ) + { + if (rMark.IsMarked()) // ist derselbe Bereich schon markiert? + { + ScRange aOldMark; + rMark.GetMarkArea( aOldMark ); + aOldMark.Justify(); + ScRange aCurrent = aScRange; + aCurrent.Justify(); + bNothing = ( aCurrent == aOldMark ); + } + else + bNothing = sal_False; + + if (!bNothing) + MarkRange( aScRange, sal_False ); // Cursor kommt hinterher... + } + else + { + // remove old selection, unless bUnmark argument is sal_False (from navigator) + if( bUnmark ) + { + MoveCursorAbs( nCol, nRow, + SC_FOLLOW_NONE, sal_False, sal_False ); + } + } + + // und Cursor setzen + + // zusammengefasste Zellen beruecksichtigen: + while ( pDoc->IsHorOverlapped( nCol, nRow, nTab ) ) //! ViewData !!! + --nCol; + while ( pDoc->IsVerOverlapped( nCol, nRow, nTab ) ) + --nRow; + + // Navigator-Aufrufe sind nicht API!!! + + if( bNothing ) + { + if (rReq.IsAPI()) + rReq.Ignore(); // wenn Makro, dann gar nix + else + rReq.Done(); // sonst wenigstens aufzeichnen + } + else + { + pViewData->ResetOldCursor(); + SetCursor( nCol, nRow ); + AlignToCursor( nCol, nRow, SC_FOLLOW_JUMP ); + rBindings.Invalidate( SID_CURRENTCELL ); + rBindings.Update( nSlot ); + + if (!rReq.IsAPI()) + rReq.Done(); + } + + rReq.SetReturnValue( SfxStringItem( SID_CURRENTCELL, aAddress ) ); + } + + if (!bFound) // kein gueltiger Bereich + { + // wenn es ein Tabellenname ist, umschalten (fuer Navigator/URL's) + + SCTAB nNameTab; + if ( pDoc->GetTable( aAddress, nNameTab ) ) + { + bFound = sal_True; + if ( nNameTab != nTab ) + SetTabNo( nNameTab ); + } + } + + if ( !bFound && nSlot == SID_JUMPTOMARK ) + { + // Grafik-Objekte probieren (nur bei URL's) + + bFound = SelectObject( aAddress ); + } + + if (!bFound && !rReq.IsAPI()) + ErrorMessage( STR_ERR_INVALID_AREA ); + } + break; + + case SID_CURRENTOBJECT: + if ( pReqArgs ) + { + String aName = ((const SfxStringItem&)pReqArgs->Get(nSlot)).GetValue(); + SelectObject( aName ); + } + break; + + case SID_CURRENTTAB: + if ( pReqArgs ) + { + // Tabelle fuer Basic ist 1-basiert + SCTAB nTab = ((const SfxUInt16Item&)pReqArgs->Get(nSlot)).GetValue() - 1; + ScDocument* pDoc = GetViewData()->GetDocument(); + if ( nTab < pDoc->GetTableCount() ) + { + SetTabNo( nTab ); + rBindings.Update( nSlot ); + + if( ! rReq.IsAPI() ) + rReq.Done(); + } + //! sonst Fehler ? + } + break; + + case SID_CURRENTDOC: + if ( pReqArgs ) + { + String aStrDocName( ((const SfxStringItem&)pReqArgs-> + Get(nSlot)).GetValue() ); + + SfxViewFrame* pViewFrame = NULL; + ScDocShell* pDocSh = (ScDocShell*)SfxObjectShell::GetFirst(); + sal_Bool bFound = sal_False; + + // zu aktivierenden ViewFrame suchen + + while ( pDocSh && !bFound ) + { + if ( pDocSh->GetTitle() == aStrDocName ) + { + pViewFrame = SfxViewFrame::GetFirst( pDocSh ); + bFound = ( NULL != pViewFrame ); + } + + pDocSh = (ScDocShell*)SfxObjectShell::GetNext( *pDocSh ); + } + + if ( bFound ) + pViewFrame->GetFrame().Appear(); + + rReq.Ignore();//XXX wird von SFX erledigt + } + + case SID_ATTR_SIZE://XXX ??? + break; + + + case SID_PRINTPREVIEW: + { + if ( !pThisFrame->GetFrame().IsInPlace() ) // nicht bei OLE + { + // print preview is now always in the same frame as the tab view + // -> always switch this frame back to normal view + // (ScPreviewShell ctor reads view data) + + // #102785#; finish input + pScMod->InputEnterHandler(); + + pThisFrame->GetDispatcher()->Execute( SID_VIEWSHELL1, SFX_CALLMODE_ASYNCHRON ); + } + // else Fehler (z.B. Ole) + } + break; + + case SID_DETECTIVE_DEL_ALL: + DetectiveDelAll(); + rReq.Done(); + break; + + // SID_TABLE_ACTIVATE und SID_MARKAREA werden von Basic aus an der versteckten + // View aufgerufen, um auf der sichtbaren View zu markieren/umzuschalten: + + case SID_TABLE_ACTIVATE: + DBG_ERROR("old slot SID_TABLE_ACTIVATE"); + break; + + case SID_REPAINT: + PaintGrid(); + PaintTop(); + PaintLeft(); + PaintExtras(); + rReq.Done(); + break; + + case FID_NORMALVIEWMODE: + case FID_PAGEBREAKMODE: + { + sal_Bool bWantPageBreak = nSlot == FID_PAGEBREAKMODE; + + // check whether there is an explicit argument, use it + const SfxPoolItem* pItem; + if ( pReqArgs && pReqArgs->GetItemState(nSlot, sal_True, &pItem) == SFX_ITEM_SET ) + { + sal_Bool bItemValue = ((const SfxBoolItem*)pItem)->GetValue(); + bWantPageBreak = (nSlot == FID_PAGEBREAKMODE) == bItemValue; + } + + if( GetViewData()->IsPagebreakMode() != bWantPageBreak ) + { + SetPagebreakMode( bWantPageBreak ); + UpdatePageBreakData(); + SetCurSubShell( GetCurObjectSelectionType(), sal_True ); + PaintGrid(); + PaintTop(); + PaintLeft(); + rBindings.Invalidate( nSlot ); + rReq.AppendItem( SfxBoolItem( nSlot, sal_True ) ); + rReq.Done(); + } + } + break; + + case FID_FUNCTION_BOX: + { + sal_uInt16 nChildId = ScFunctionChildWindow::GetChildWindowId(); + if ( rReq.GetArgs() ) + pThisFrame->SetChildWindow( nChildId, ((const SfxBoolItem&) (rReq.GetArgs()->Get(FID_FUNCTION_BOX))).GetValue()); + else + { + pThisFrame->ToggleChildWindow( nChildId ); + rReq.AppendItem( SfxBoolItem( FID_FUNCTION_BOX , pThisFrame->HasChildWindow( nChildId ) ) ); + } + + GetViewFrame()->GetBindings().Invalidate(FID_FUNCTION_BOX); + rReq.Done (); + } + break; + + + case FID_TOGGLESYNTAX: + { + sal_Bool bSet = !GetViewData()->IsSyntaxMode(); + const SfxPoolItem* pItem; + if ( pReqArgs && pReqArgs->GetItemState(nSlot, sal_True, &pItem) == SFX_ITEM_SET ) + bSet = ((const SfxBoolItem*)pItem)->GetValue(); + GetViewData()->SetSyntaxMode( bSet ); + PaintGrid(); + rBindings.Invalidate( FID_TOGGLESYNTAX ); + rReq.AppendItem( SfxBoolItem( nSlot, bSet ) ); + rReq.Done(); + } + break; + case FID_TOGGLEHEADERS: + { + sal_Bool bSet = !GetViewData()->IsHeaderMode(); + const SfxPoolItem* pItem; + if ( pReqArgs && pReqArgs->GetItemState(nSlot, sal_True, &pItem) == SFX_ITEM_SET ) + bSet = ((const SfxBoolItem*)pItem)->GetValue(); + GetViewData()->SetHeaderMode( bSet ); + RepeatResize(); + rBindings.Invalidate( FID_TOGGLEHEADERS ); + rReq.AppendItem( SfxBoolItem( nSlot, bSet ) ); + rReq.Done(); + } + break; + + case FID_TOGGLEFORMULA: + { + ScViewData* pViewData = GetViewData(); + const ScViewOptions& rOpts = pViewData->GetOptions(); + sal_Bool bFormulaMode = !rOpts.GetOption( VOPT_FORMULAS ); + const SfxPoolItem *pItem; + if( pReqArgs && pReqArgs->GetItemState(nSlot, sal_True, &pItem) == SFX_ITEM_SET ) + bFormulaMode = ((const SfxBoolItem *)pItem)->GetValue(); + + ScViewOptions rSetOpts = ScViewOptions( rOpts ); + rSetOpts.SetOption( VOPT_FORMULAS, bFormulaMode ); + pViewData->SetOptions( rSetOpts ); + + pViewData->GetDocShell()->PostPaintGridAll(); + + rBindings.Invalidate( FID_TOGGLEFORMULA ); + rReq.AppendItem( SfxBoolItem( nSlot, bFormulaMode ) ); + rReq.Done(); + } + break; + + case FID_TOGGLEINPUTLINE: + { + sal_uInt16 nId = ScInputWindowWrapper::GetChildWindowId(); + SfxChildWindow* pWnd = pThisFrame->GetChildWindow( nId ); + sal_Bool bSet = ( pWnd == NULL ); + const SfxPoolItem* pItem; + if ( pReqArgs && pReqArgs->GetItemState(nSlot, sal_True, &pItem) == SFX_ITEM_SET ) + bSet = ((const SfxBoolItem*)pItem)->GetValue(); + + pThisFrame->SetChildWindow( nId, bSet ); + rBindings.Invalidate( FID_TOGGLEINPUTLINE ); + rReq.AppendItem( SfxBoolItem( nSlot, bSet ) ); + rReq.Done(); + } + break; + + case SID_ATTR_ZOOM: // Statuszeile + case FID_SCALE: + { + sal_Bool bSyncZoom = SC_MOD()->GetAppOptions().GetSynchronizeZoom(); + SvxZoomType eOldZoomType = GetZoomType(); + SvxZoomType eNewZoomType = eOldZoomType; + const Fraction& rOldY = GetViewData()->GetZoomY(); // Y wird angezeigt + sal_uInt16 nOldZoom = (sal_uInt16)(( rOldY.GetNumerator() * 100 ) + / rOldY.GetDenominator()); + sal_uInt16 nZoom = nOldZoom; + sal_Bool bCancel = sal_False; + + if ( pReqArgs ) + { + const SvxZoomItem& rZoomItem = (const SvxZoomItem&) + pReqArgs->Get(SID_ATTR_ZOOM); + + eNewZoomType = rZoomItem.GetType(); + nZoom = rZoomItem.GetValue(); + } + else + { + SfxItemSet aSet ( GetPool(), SID_ATTR_ZOOM, SID_ATTR_ZOOM ); + SvxZoomItem aZoomItem( eOldZoomType, nOldZoom, SID_ATTR_ZOOM ); + //CHINA001 SvxZoomDialog* pDlg = NULL; + AbstractSvxZoomDialog* pDlg = NULL; + ScMarkData& rMark = GetViewData()->GetMarkData(); + sal_uInt16 nBtnFlags = SVX_ZOOM_ENABLE_50 + | SVX_ZOOM_ENABLE_75 + | SVX_ZOOM_ENABLE_100 + | SVX_ZOOM_ENABLE_150 + | SVX_ZOOM_ENABLE_200 + | SVX_ZOOM_ENABLE_WHOLEPAGE + | SVX_ZOOM_ENABLE_PAGEWIDTH; + + if ( rMark.IsMarked() || rMark.IsMultiMarked() ) + nBtnFlags = nBtnFlags | SVX_ZOOM_ENABLE_OPTIMAL; + + aZoomItem.SetValueSet( nBtnFlags ); + aSet.Put( aZoomItem ); + //CHINA001 pDlg = new SvxZoomDialog( GetDialogParent(), aSet ); + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + if(pFact) + { + pDlg = pFact->CreateSvxZoomDialog(GetDialogParent(), aSet ); + DBG_ASSERT(pDlg, "Dialogdiet fail!");//CHINA001 + } + pDlg->SetLimits( MINZOOM, MAXZOOM ); + + bCancel = ( RET_CANCEL == pDlg->Execute() ); + + if ( !bCancel ) + { + const SvxZoomItem& rZoomItem = (const SvxZoomItem&) + pDlg->GetOutputItemSet()-> + Get( SID_ATTR_ZOOM ); + + eNewZoomType = rZoomItem.GetType(); + nZoom = rZoomItem.GetValue(); + } + + delete pDlg; + } + + if ( !bCancel ) + { + if ( eNewZoomType == SVX_ZOOM_PERCENT ) + { + if ( nZoom < MINZOOM ) nZoom = MINZOOM; + if ( nZoom > MAXZOOM ) nZoom = MAXZOOM; + } + else + { + nZoom = CalcZoom( eNewZoomType, nOldZoom ); + bCancel = nZoom == 0; + } + + switch ( eNewZoomType ) + { + case SVX_ZOOM_WHOLEPAGE: + case SVX_ZOOM_PAGEWIDTH: + SetZoomType( eNewZoomType, bSyncZoom ); + break; + + default: + SetZoomType( SVX_ZOOM_PERCENT, bSyncZoom ); + } + } + + if ( nZoom != nOldZoom && !bCancel ) + { + if (!GetViewData()->IsPagebreakMode()) + { + ScAppOptions aNewOpt = pScMod->GetAppOptions(); + aNewOpt.SetZoom( nZoom ); + aNewOpt.SetZoomType( GetZoomType() ); + pScMod->SetAppOptions( aNewOpt ); + } + Fraction aFract( nZoom, 100 ); + SetZoom( aFract, aFract, bSyncZoom ); + PaintGrid(); + PaintTop(); + PaintLeft(); + rBindings.Invalidate( SID_ATTR_ZOOM ); + rReq.AppendItem( SvxZoomItem( GetZoomType(), nZoom, nSlot ) ); + rReq.Done(); + } + } + break; + + case SID_ATTR_ZOOMSLIDER: + { + const SfxPoolItem* pItem = NULL; + sal_Bool bSyncZoom = SC_MOD()->GetAppOptions().GetSynchronizeZoom(); + if ( pReqArgs && pReqArgs->GetItemState(SID_ATTR_ZOOMSLIDER, sal_True, &pItem) == SFX_ITEM_SET ) + { + const sal_uInt16 nCurrentZoom = ((const SvxZoomSliderItem *)pItem)->GetValue(); + if( nCurrentZoom ) + { + SetZoomType( SVX_ZOOM_PERCENT, bSyncZoom ); + if (!GetViewData()->IsPagebreakMode()) + { + ScAppOptions aNewOpt = pScMod->GetAppOptions(); + aNewOpt.SetZoom( nCurrentZoom ); + aNewOpt.SetZoomType( GetZoomType() ); + pScMod->SetAppOptions( aNewOpt ); + } + Fraction aFract( nCurrentZoom,100 ); + SetZoom( aFract, aFract, bSyncZoom ); + PaintGrid(); + PaintTop(); + PaintLeft(); + rBindings.Invalidate( SID_ATTR_ZOOMSLIDER ); + rReq.Done(); + } + } + } + break; + + //---------------------------------------------------------------- + + case FID_TAB_SELECTALL: + SelectAllTables(); + rReq.Done(); + break; + + case FID_TAB_DESELECTALL: + DeselectAllTables(); + rReq.Done(); + break; + + case SID_SELECT_TABLES: + { + ScViewData& rViewData = *GetViewData(); + ScDocument& rDoc = *rViewData.GetDocument(); + ScMarkData& rMark = rViewData.GetMarkData(); + SCTAB nTabCount = rDoc.GetTableCount(); + SCTAB nTab; + + SvULongs aIndexList( 4, 4 ); + SFX_REQUEST_ARG( rReq, pItem, SfxIntegerListItem, SID_SELECT_TABLES, sal_False ); + if ( pItem ) + pItem->GetList( aIndexList ); + else + { + //CHINA001 ScShowTabDlg* pDlg = new ScShowTabDlg( GetDialogParent() ); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + AbstractScShowTabDlg* pDlg = pFact->CreateScShowTabDlg( GetDialogParent(), RID_SCDLG_SHOW_TAB); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + pDlg->SetDescription( + String( ScResId( STR_DLG_SELECTTABLES_TITLE ) ), + String( ScResId( STR_DLG_SELECTTABLES_LBNAME ) ), + GetStaticInterface()->GetSlot(SID_SELECT_TABLES)->GetCommand(), HID_SELECTTABLES ); + + // fill all table names with selection state + String aTabName; + for( nTab = 0; nTab < nTabCount; ++nTab ) + { + rDoc.GetName( nTab, aTabName ); + pDlg->Insert( aTabName, rMark.GetTableSelect( nTab ) ); + } + + if( pDlg->Execute() == RET_OK ) + { + sal_uInt16 nSelCount = pDlg->GetSelectEntryCount(); + sal_uInt16 nSelIx; + for( nSelIx = 0; nSelIx < nSelCount; ++nSelIx ) + aIndexList.Insert( pDlg->GetSelectEntryPos( nSelIx ), nSelIx ); + delete pDlg; + rReq.AppendItem( SfxIntegerListItem( SID_SELECT_TABLES, aIndexList ) ); + } + else + rReq.Ignore(); + } + + if ( aIndexList.Count() ) + { + sal_uInt16 nSelCount = aIndexList.Count(); + sal_uInt16 nSelIx; + SCTAB nFirstVisTab = 0; + + // special case: only hidden tables selected -> do nothing + sal_Bool bVisSelected = sal_False; + for( nSelIx = 0; !bVisSelected && (nSelIx < nSelCount); ++nSelIx ) + bVisSelected = rDoc.IsVisible( nFirstVisTab = static_cast<SCTAB>(aIndexList[nSelIx]) ); + if( !bVisSelected ) + nSelCount = 0; + + // select the tables + if( nSelCount ) + { + for( nTab = 0; nTab < nTabCount; ++nTab ) + rMark.SelectTable( nTab, sal_False ); + + for( nSelIx = 0; nSelIx < nSelCount; ++nSelIx ) + rMark.SelectTable( static_cast<SCTAB>(aIndexList[nSelIx]), sal_True ); + + // activate another table, if current is deselected + if( !rMark.GetTableSelect( rViewData.GetTabNo() ) ) + { + rMark.SelectTable( nFirstVisTab, sal_True ); + SetTabNo( nFirstVisTab ); + } + + rViewData.GetDocShell()->PostPaintExtras(); + SfxBindings& rBind = rViewData.GetBindings(); + rBind.Invalidate( FID_FILL_TAB ); + rBind.Invalidate( FID_TAB_DESELECTALL ); + } + + rReq.Done(); + } + } + break; + + + case SID_OUTLINE_DELETEALL: + RemoveAllOutlines(); + rReq.Done(); + break; + + case SID_AUTO_OUTLINE: + AutoOutline(); + rReq.Done(); + break; + + + case SID_WINDOW_SPLIT: + { + ScSplitMode eHSplit = GetViewData()->GetHSplitMode(); + ScSplitMode eVSplit = GetViewData()->GetVSplitMode(); + if ( eHSplit == SC_SPLIT_NORMAL || eVSplit == SC_SPLIT_NORMAL ) // aufheben + RemoveSplit(); + else if ( eHSplit == SC_SPLIT_FIX || eVSplit == SC_SPLIT_FIX ) // normal + FreezeSplitters( sal_False ); + else // erzeugen + SplitAtCursor(); + rReq.Done(); + + InvalidateSplit(); + } + break; + + case SID_WINDOW_FIX: + { + ScSplitMode eHSplit = GetViewData()->GetHSplitMode(); + ScSplitMode eVSplit = GetViewData()->GetVSplitMode(); + if ( eHSplit == SC_SPLIT_FIX || eVSplit == SC_SPLIT_FIX ) // aufheben + RemoveSplit(); + else + FreezeSplitters( sal_True ); // erzeugen oder fixieren + rReq.Done(); + + InvalidateSplit(); + } + break; + + // ---------------------------------------------------------------- + + case FID_CHG_SHOW: + { + sal_uInt16 nId = ScHighlightChgDlgWrapper::GetChildWindowId(); + SfxChildWindow* pWnd = pThisFrame->GetChildWindow( nId ); + + pScMod->SetRefDialog( nId, pWnd ? sal_False : sal_True ); + } + break; + + case FID_CHG_ACCEPT: + { + pThisFrame->ToggleChildWindow(ScAcceptChgDlgWrapper::GetChildWindowId()); + GetViewFrame()->GetBindings().Invalidate(FID_CHG_ACCEPT); + rReq.Done (); + + /* + sal_uInt16 nId = ScAcceptChgDlgWrapper::GetChildWindowId(); + SfxChildWindow* pWnd = pThisFrame->GetChildWindow( nId ); + + pScMod->SetRefDialog( nId, pWnd ? sal_False : sal_True ); + */ + } + break; + + case FID_CHG_COMMENT: + { + ScViewData* pData = GetViewData(); + ScAddress aCursorPos( pData->GetCurX(), pData->GetCurY(), pData->GetTabNo() ); + ScDocShell* pDocSh = pData->GetDocShell(); + + ScChangeAction* pAction = pDocSh->GetChangeAction( aCursorPos ); + if ( pAction ) + { + const SfxPoolItem* pItem; + if ( pReqArgs && + pReqArgs->GetItemState( nSlot, sal_True, &pItem ) == SFX_ITEM_SET && + pItem->ISA( SfxStringItem ) ) + { + String aComment = ((const SfxStringItem*)pItem)->GetValue(); + pDocSh->SetChangeComment( pAction, aComment ); + rReq.Done(); + } + else + { + pDocSh->ExecuteChangeCommentDialog( pAction, GetDialogParent() ); + rReq.Done(); + } + } + } + break; + + case SID_CREATE_SW_DRAWVIEW: + // wird von den Forms gerufen, wenn die DrawView mit allem Zubehoer + // angelegt werden muss + if (!GetScDrawView()) + { + GetViewData()->GetDocShell()->MakeDrawLayer(); + rBindings.InvalidateAll(sal_False); + } + break; + + case FID_PROTECT_DOC: + { + ScDocument* pDoc = GetViewData()->GetDocument(); + SfxPasswordDialog* pDlg; + + if( pReqArgs ) + { + const SfxPoolItem* pItem; + if( IS_AVAILABLE( FID_PROTECT_DOC, &pItem ) && + ((const SfxBoolItem*)pItem)->GetValue() == pDoc->IsDocProtected() ) + { + rReq.Ignore(); + break; + } + } + + ScDocProtection* pProtect = pDoc->GetDocProtection(); + if (pProtect && pProtect->isProtected()) + { + sal_Bool bCancel = sal_False; + String aPassword; + + if (pProtect->isProtectedWithPass()) + { + String aText( ScResId(SCSTR_PASSWORD) ); + + pDlg = new SfxPasswordDialog( GetDialogParent(), &aText ); + pDlg->SetText( ScResId(SCSTR_UNPROTECTDOC) ); + pDlg->SetMinLen( 0 ); + pDlg->SetHelpId( GetStaticInterface()->GetSlot(FID_PROTECT_DOC)->GetCommand() ); + pDlg->SetEditHelpId( HID_PASSWD_DOC ); + + if (pDlg->Execute() == RET_OK) + aPassword = pDlg->GetPassword(); + else + bCancel = sal_True; + delete pDlg; + } + if (!bCancel) + { + Unprotect( TABLEID_DOC, aPassword ); + rReq.AppendItem( SfxBoolItem( FID_PROTECT_DOC, sal_False ) ); + rReq.Done(); + } + } + else + { + String aText( ScResId(SCSTR_PASSWORDOPT) ); + + pDlg = new SfxPasswordDialog( GetDialogParent(), &aText ); + pDlg->SetText( ScResId(SCSTR_PROTECTDOC) ); + pDlg->SetMinLen( 0 ); + pDlg->SetHelpId( GetStaticInterface()->GetSlot(FID_PROTECT_DOC)->GetCommand() ); + pDlg->SetEditHelpId( HID_PASSWD_DOC ); + pDlg->ShowExtras( SHOWEXTRAS_CONFIRM ); + + if (pDlg->Execute() == RET_OK) + { + String aPassword = pDlg->GetPassword(); + Protect( TABLEID_DOC, aPassword ); + rReq.AppendItem( SfxBoolItem( FID_PROTECT_DOC, sal_True ) ); + rReq.Done(); + } + + delete pDlg; + } + rBindings.Invalidate( FID_PROTECT_DOC ); + } + break; + + + case FID_PROTECT_TABLE: + { + ScDocument* pDoc = GetViewData()->GetDocument(); + SCTAB nTab = GetViewData()->GetTabNo(); + bool bOldProtection = pDoc->IsTabProtected(nTab); + +#if ENABLE_SHEET_PROTECTION + + if( pReqArgs ) + { + const SfxPoolItem* pItem; + bool bNewProtection = !bOldProtection; + if( IS_AVAILABLE( FID_PROTECT_TABLE, &pItem ) ) + bNewProtection = ((const SfxBoolItem*)pItem)->GetValue(); + if( bNewProtection == bOldProtection ) + { + rReq.Ignore(); + break; + } + } + + if (bOldProtection) + { + // Unprotect a protected sheet. + + ScTableProtection* pProtect = pDoc->GetTabProtection(nTab); + if (pProtect && pProtect->isProtectedWithPass()) + { + String aText( ScResId(SCSTR_PASSWORDOPT) ); + auto_ptr<SfxPasswordDialog> pDlg(new SfxPasswordDialog(GetDialogParent(), &aText)); + pDlg->SetText( ScResId(SCSTR_UNPROTECTTAB) ); + pDlg->SetMinLen( 0 ); + pDlg->SetHelpId( GetStaticInterface()->GetSlot(FID_PROTECT_TABLE)->GetCommand() ); + pDlg->SetEditHelpId( HID_PASSWD_TABLE ); + + if (pDlg->Execute() == RET_OK) + { + String aPassword = pDlg->GetPassword(); + Unprotect(nTab, aPassword); + } + } + else + // this sheet is not password-protected. + Unprotect(nTab, String()); + + if (!pReqArgs) + { + rReq.AppendItem( SfxBoolItem(FID_PROTECT_TABLE, false) ); + rReq.Done(); + } + } + else + { + // Protect a current sheet. + + auto_ptr<ScTableProtectionDlg> pDlg(new ScTableProtectionDlg(GetDialogParent())); + + ScTableProtection* pProtect = pDoc->GetTabProtection(nTab); + if (pProtect) + pDlg->SetDialogData(*pProtect); + + if (pDlg->Execute() == RET_OK) + { + pScMod->InputEnterHandler(); + + ScTableProtection aNewProtect; + pDlg->WriteData(aNewProtect); + ProtectSheet(nTab, aNewProtect); + if (!pReqArgs) + { + rReq.AppendItem( SfxBoolItem(FID_PROTECT_TABLE, true) ); + rReq.Done(); + } + } + } +#else + auto_ptr<SfxPasswordDialog> pDlg; + String aPassword; + sal_Bool bCancel = sal_False; + bool bNewProtection = ! bOldProtection; + + if( pReqArgs ) + { + const SfxPoolItem* pItem; + if( IS_AVAILABLE( FID_PROTECT_TABLE, &pItem ) ) + bNewProtection = ((const SfxBoolItem*)pItem)->GetValue(); + if( bNewProtection == bOldProtection ) + { + rReq.Ignore(); + break; + } + } + + if ( bOldProtection) + { + // Unprotect a protected sheet. + + ScTableProtection* pProtect = pDoc->GetTabProtection(nTab); + if (pProtect && pProtect->isProtectedWithPass()) + { + String aText( ScResId(SCSTR_PASSWORDOPT) ); + pDlg.reset(new SfxPasswordDialog(GetDialogParent(), &aText)); + pDlg->SetText( ScResId(SCSTR_UNPROTECTTAB) ); + pDlg->SetMinLen( 0 ); + pDlg->SetHelpId( GetStaticInterface()->GetSlot(FID_PROTECT_TABLE)->GetCommand() ); + pDlg->SetEditHelpId( HID_PASSWD_TABLE ); + + if (pDlg->Execute() == RET_OK) + aPassword = pDlg->GetPassword(); + else + bCancel = sal_True; + } + + if (!pReqArgs) + { + rReq.AppendItem( SfxBoolItem(FID_PROTECT_TABLE, false) ); + rReq.Done(); + } + } + else + { + String aText( ScResId(SCSTR_PASSWORDOPT) ); + + pDlg.reset(new SfxPasswordDialog(GetDialogParent(), &aText)); + pDlg->SetText( ScResId(SCSTR_PROTECTTAB) ); + pDlg->SetMinLen( 0 ); + pDlg->SetHelpId( GetStaticInterface()->GetSlot(FID_PROTECT_TABLE)->GetCommand() ); + pDlg->SetEditHelpId( HID_PASSWD_TABLE ); + pDlg->ShowExtras( SHOWEXTRAS_CONFIRM ); + + if (pDlg->Execute() == RET_OK) + aPassword = pDlg->GetPassword(); + else + bCancel = sal_True; + } + + if( !bCancel ) + { + if ( bOldProtection ) + Unprotect( nTab, aPassword ); + else + { + pScMod->InputEnterHandler(); + + Protect( nTab, aPassword ); + } + + if( !pReqArgs ) + { + rReq.AppendItem( SfxBoolItem( FID_PROTECT_TABLE, bNewProtection ) ); + rReq.Done(); + } + } +#endif + TabChanged(); + UpdateInputHandler(true); // damit sofort wieder eingegeben werden kann + SelectionChanged(); + } + break; + + case SID_OPT_LOCALE_CHANGED : + { // locale changed, SYSTEM number formats changed => repaint cell contents + PaintGrid(); + rReq.Done(); + } + break; + + default: + DBG_ERROR("Unbekannter Slot bei ScTabViewShell::Execute"); + break; + } +} + + + diff --git a/sc/source/ui/view/tabvwsh4.cxx b/sc/source/ui/view/tabvwsh4.cxx new file mode 100644 index 000000000000..3710fca85e33 --- /dev/null +++ b/sc/source/ui/view/tabvwsh4.cxx @@ -0,0 +1,1990 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include "scitems.hxx" +#include <editeng/eeitem.hxx> + +#include <sfx2/app.hxx> +#include <svx/extrusionbar.hxx> +#include <svx/fontworkbar.hxx> +#include <editeng/boxitem.hxx> +#include <svx/fmshell.hxx> +#include <editeng/sizeitem.hxx> +#include <editeng/boxitem.hxx> +#include <svx/prtqry.hxx> +#include <sfx2/request.hxx> +#include <sfx2/printer.hxx> +#include <sfx2/dispatch.hxx> +#include <svl/whiter.hxx> +#include <unotools/moduleoptions.hxx> +#include <rtl/logfile.hxx> +#include <tools/urlobj.hxx> +#include <sfx2/docfile.hxx> + +#include "tabvwsh.hxx" +#include "sc.hrc" +#include "globstr.hrc" +#include "stlpool.hxx" +#include "stlsheet.hxx" +#include "docsh.hxx" +#include "scmod.hxx" +#include "appoptio.hxx" +#include "rangeutl.hxx" +#include "printfun.hxx" +#include "drawsh.hxx" +#include "drformsh.hxx" +#include "editsh.hxx" +#include "pivotsh.hxx" +#include "auditsh.hxx" +#include "drtxtob.hxx" +#include "inputhdl.hxx" +#include "editutil.hxx" +#include "inputopt.hxx" +#include "inputwin.hxx" +#include "scresid.hxx" +#include "dbcolect.hxx" // fuer ReImport +#include "reffact.hxx" +#include "viewuno.hxx" +#include "dispuno.hxx" +#include "anyrefdg.hxx" +#include "chgtrack.hxx" +#include "cellsh.hxx" +#include "oleobjsh.hxx" +#include "chartsh.hxx" +#include "graphsh.hxx" +#include "mediash.hxx" +#include "pgbrksh.hxx" +#include "dpobject.hxx" +#include "prevwsh.hxx" +#include "tpprint.hxx" +#include "scextopt.hxx" +#include "printopt.hxx" +#include "drawview.hxx" +#include "fupoor.hxx" +#include "navsett.hxx" +#include "sc.hrc" //CHINA001 +#include "scabstdlg.hxx" //CHINA001 +#include "externalrefmgr.hxx" + +void ActivateOlk( ScViewData* pViewData ); +void DeActivateOlk( ScViewData* pViewData ); + +extern SfxViewShell* pScActiveViewShell; // global.cxx + +using namespace com::sun::star; + +// STATIC DATA ----------------------------------------------------------- + +sal_uInt16 ScTabViewShell::nInsertCtrlState = SID_INSERT_GRAPHIC; +sal_uInt16 ScTabViewShell::nInsCellsCtrlState = 0; +sal_uInt16 ScTabViewShell::nInsObjCtrlState = SID_INSERT_DIAGRAM; + +// ----------------------------------------------------------------------- + +void __EXPORT ScTabViewShell::Activate(sal_Bool bMDI) +{ + SfxViewShell::Activate(bMDI); + + // hier kein GrabFocus, sonst gibt's Probleme wenn etwas inplace editiert wird! + + if ( bMDI ) + { + // fuer Eingabezeile (ClearCache) + ScModule* pScMod = SC_MOD(); + pScMod->ViewShellChanged(); + + ActivateView( sal_True, bFirstActivate ); + ActivateOlk( GetViewData() ); + + // #56870# AutoCorrect umsetzen, falls der Writer seins neu angelegt hat + UpdateDrawTextOutliner(); + + // RegisterNewTargetNames gibts nicht mehr + + SfxViewFrame* pThisFrame = GetViewFrame(); + if ( pInputHandler && pThisFrame->HasChildWindow(FID_INPUTLINE_STATUS) ) + { + // eigentlich nur beim Reload (letzte Version) noetig: + // Das InputWindow bleibt stehen, aber die View mitsamt InputHandler wird + // neu angelegt, darum muss der InputHandler am InputWindow gesetzt werden. + SfxChildWindow* pChild = pThisFrame->GetChildWindow(FID_INPUTLINE_STATUS); + if (pChild) + { + ScInputWindow* pWin = (ScInputWindow*)pChild->GetWindow(); + if (pWin && pWin->IsVisible()) + { + + ScInputHandler* pOldHdl=pWin->GetInputHandler(); + + TypeId aScType = TYPE(ScTabViewShell); + + SfxViewShell* pSh = SfxViewShell::GetFirst( &aScType ); + while ( pSh!=NULL && pOldHdl!=NULL) + { + if (((ScTabViewShell*)pSh)->GetInputHandler() == pOldHdl) + { + pOldHdl->ResetDelayTimer(); + break; + } + pSh = SfxViewShell::GetNext( *pSh, &aScType ); + } + + pWin->SetInputHandler( pInputHandler ); + } + } + } + + UpdateInputHandler( sal_True ); + + if ( bFirstActivate ) + { + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_NAVIGATOR_UPDATEALL ) ); + bFirstActivate = sal_False; + + // #116278# ReadExtOptions (view settings from Excel import) must also be done + // after the ctor, because of the potential calls to Window::Show. + // Even after the fix for #104887# (Window::Show no longer notifies the access + // bridge, it's done in ImplSetReallyVisible), there are problems if Window::Show + // is called during the ViewShell ctor and reschedules asynchronous calls + // (for example from the FmFormShell ctor). + ScExtDocOptions* pExtOpt = GetViewData()->GetDocument()->GetExtDocOptions(); + if ( pExtOpt && pExtOpt->IsChanged() ) + { + GetViewData()->ReadExtOptions(*pExtOpt); // Excel view settings + SetTabNo( GetViewData()->GetTabNo(), sal_True ); + pExtOpt->SetChanged( false ); + } + } + + pScActiveViewShell = this; + + ScInputHandler* pHdl = pScMod->GetInputHdl(this); + if (pHdl) + { + pHdl->SetRefScale( GetViewData()->GetZoomX(), GetViewData()->GetZoomY() ); + } + + // Aenderungs-Dialog aktualisieren + + if ( pThisFrame->HasChildWindow(FID_CHG_ACCEPT) ) + { + SfxChildWindow* pChild = pThisFrame->GetChildWindow(FID_CHG_ACCEPT); + if (pChild) + { + ((ScAcceptChgDlgWrapper*)pChild)->ReInitDlg(); + } + } + + if(pScMod->IsRefDialogOpen()) + { + sal_uInt16 nModRefDlgId=pScMod->GetCurRefDlgId(); + SfxChildWindow* pChildWnd = pThisFrame->GetChildWindow( nModRefDlgId ); + if ( pChildWnd ) + { + IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetWindow()); + pRefDlg->ViewShellChanged(this); + } + } + } + + // don't call CheckSelectionTransfer here - activating a view should not change the + // primary selection (may be happening just because the mouse was moved over the window) + + // Wenn Referenzeingabe-Tip-Hilfe hier wieder angezeigt werden soll (ShowRefTip), + // muss sie beim Verschieben der View angepasst werden (gibt sonst Probleme unter OS/2 + // beim Umschalten zwischen Dokumenten) +} + +void __EXPORT ScTabViewShell::Deactivate(sal_Bool bMDI) +{ + HideTip(); + + ScDocument* pDoc=GetViewData()->GetDocument(); + + ScChangeTrack* pChanges=pDoc->GetChangeTrack(); + + if(pChanges!=NULL) + { + Link aLink; + pChanges->SetModifiedLink(aLink); + } + + SfxViewShell::Deactivate(bMDI); + + ScInputHandler* pHdl = SC_MOD()->GetInputHdl(this); + + if( bMDI ) + { + // #85421# during shell deactivation, shells must not be switched, or the loop + // through the shell stack (in SfxDispatcher::DoDeactivate_Impl) will not work + sal_Bool bOldDontSwitch = bDontSwitch; + bDontSwitch = sal_True; + + DeActivateOlk( GetViewData() ); + ActivateView( sal_False, sal_False ); + + if ( GetViewFrame()->GetFrame().IsInPlace() ) // inplace + GetViewData()->GetDocShell()->UpdateOle(GetViewData(),sal_True); + + if ( pHdl ) + pHdl->NotifyChange( NULL, sal_True ); // Timer-verzoegert wg. Dokumentwechsel + + if (pScActiveViewShell == this) + pScActiveViewShell = NULL; + + bDontSwitch = bOldDontSwitch; + } + else + { + HideNoteMarker(); // Notiz-Anzeige + + if ( pHdl ) + pHdl->HideTip(); // Formel-AutoEingabe-Tip abschalten + } +} + +void ScTabViewShell::SetActive() +{ + // Die Sfx-View moechte sich gerne selbst aktivieren, weil dabei noch + // magische Dinge geschehen (z.B. stuerzt sonst evtl. der Gestalter ab) + ActiveGrabFocus(); + +#if 0 + SfxViewFrame* pFrame = GetViewFrame(); + pFrame->GetFrame().Appear(); + + SFX_APP()->SetViewFrame( pFrame ); // immer erst Appear, dann SetViewFrame (#29290#) +#endif +} + +sal_uInt16 __EXPORT ScTabViewShell::PrepareClose(sal_Bool bUI, sal_Bool bForBrowsing) +{ + // Call EnterHandler even in formula mode here, + // so a formula change in an embedded object isn't lost + // (ScDocShell::PrepareClose isn't called then). + ScInputHandler* pHdl = SC_MOD()->GetInputHdl( this ); + if ( pHdl && pHdl->IsInputMode() ) + pHdl->EnterHandler(); + + // #110797# draw text edit mode must be closed + FuPoor* pPoor = GetDrawFuncPtr(); + if ( pPoor && ( IsDrawTextShell() || pPoor->GetSlotID() == SID_DRAW_NOTEEDIT ) ) + { + // "clean" end of text edit, including note handling, subshells and draw func switching, + // as in FuDraw and ScTabView::DrawDeselectAll + GetViewData()->GetDispatcher().Execute( pPoor->GetSlotID(), SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD ); + } + ScDrawView* pDrView = GetScDrawView(); + if ( pDrView ) + { + // force end of text edit, to be safe + // #128314# ScEndTextEdit must always be used, to ensure correct UndoManager + pDrView->ScEndTextEdit(); + } + + if ( pFormShell ) + { + sal_uInt16 nRet = pFormShell->PrepareClose(bUI, bForBrowsing); + if (nRet!=sal_True) + return nRet; + } + return SfxViewShell::PrepareClose(bUI,bForBrowsing); +} + +//------------------------------------------------------------------ + +Size __EXPORT ScTabViewShell::GetOptimalSizePixel() const +{ + Size aOptSize; + + SCTAB nCurTab = GetViewData()->GetTabNo(); + ScDocument* pDoc = GetViewData()->GetDocument(); + ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool(); + SfxStyleSheetBase* pStyleSheet = pStylePool->Find( + pDoc->GetPageStyle( nCurTab ), + SFX_STYLE_FAMILY_PAGE ); + + DBG_ASSERT( pStyleSheet, "PageStyle not found :-/" ); + + if ( pStyleSheet ) + { + const SfxItemSet& rSet = pStyleSheet->GetItemSet(); + const SvxSizeItem& rItem = (const SvxSizeItem&)rSet.Get( ATTR_PAGE_SIZE ); + const Size& rPageSize = rItem.GetSize(); + + aOptSize.Width() = (long) (rPageSize.Width() * GetViewData()->GetPPTX()); + aOptSize.Height() = (long) (rPageSize.Height() * GetViewData()->GetPPTY()); + } + + return aOptSize; +} + +//------------------------------------------------------------------ + +// Zoom fuer In-Place berechnen +// aus Verhaeltnis von VisArea und Fenstergroesse des GridWin + +void ScTabViewShell::UpdateOleZoom() +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + if ( pDocSh->GetCreateMode() == SFX_CREATE_MODE_EMBEDDED ) + { + //TODO/LATER: is there a difference between the two GetVisArea methods? + Size aObjSize = ((const SfxObjectShell*)pDocSh)->GetVisArea().GetSize(); + if ( aObjSize.Width() > 0 && aObjSize.Height() > 0 ) + { + Window* pWin = GetActiveWin(); + Size aWinHMM = pWin->PixelToLogic( pWin->GetOutputSizePixel(), MAP_100TH_MM ); + SetZoomFactor( Fraction( aWinHMM.Width(),aObjSize.Width() ), + Fraction( aWinHMM.Height(),aObjSize.Height() ) ); + } + } +} + +void __EXPORT ScTabViewShell::AdjustPosSizePixel( const Point &rPos, const Size &rSize ) +{ + OuterResizePixel( rPos, rSize ); +} + +void __EXPORT ScTabViewShell::InnerResizePixel( const Point &rOfs, const Size &rSize ) +{ + Size aNewSize( rSize ); + if ( GetViewFrame()->GetFrame().IsInPlace() ) + { + SvBorder aBorder; + GetBorderSize( aBorder, rSize ); + SetBorderPixel( aBorder ); + + Size aObjSize = GetObjectShell()->GetVisArea().GetSize(); + + Size aSize( rSize ); + aSize.Width() -= (aBorder.Left() + aBorder.Right()); + aSize.Height() -= (aBorder.Top() + aBorder.Bottom()); + + if ( aObjSize.Width() > 0 && aObjSize.Height() > 0 ) + { + Size aLogicSize = GetWindow()->PixelToLogic( aSize, MAP_100TH_MM ); + SfxViewShell::SetZoomFactor( Fraction( aLogicSize.Width(),aObjSize.Width() ), + Fraction( aLogicSize.Height(),aObjSize.Height() ) ); + } + + Point aPos( rOfs ); + aPos.X() += aBorder.Left(); + aPos.Y() += aBorder.Top(); + GetWindow()->SetPosSizePixel( aPos, aSize ); + } + else + { + SvBorder aBorder; + GetBorderSize( aBorder, rSize ); + SetBorderPixel( aBorder ); + aNewSize.Width() += aBorder.Left() + aBorder.Right(); + aNewSize.Height() += aBorder.Top() + aBorder.Bottom(); + } + + DoResize( rOfs, aNewSize, sal_True ); // rSize = Groesse von gridwin + + UpdateOleZoom(); // Zoom fuer In-Place berechnen + +// GetViewData()->GetDocShell()->UpdateOle( GetViewData() ); + GetViewData()->GetDocShell()->SetDocumentModified(); +} + +void __EXPORT ScTabViewShell::OuterResizePixel( const Point &rOfs, const Size &rSize ) +{ + SvBorder aBorder; + GetBorderSize( aBorder, rSize ); + SetBorderPixel( aBorder ); + + DoResize( rOfs, rSize ); // Position und Groesse von tabview wie uebergeben + + // ForceMove als Ersatz fuer den Sfx-Move-Mechanismus + // (aWinPos muss aktuell gehalten werden, damit ForceMove beim Ole-Deaktivieren klappt) + + ForceMove(); +} + +void __EXPORT ScTabViewShell::SetZoomFactor( const Fraction &rZoomX, const Fraction &rZoomY ) +{ + // fuer OLE... + + Fraction aFrac20( 1,5 ); + Fraction aFrac400( 4,1 ); + + Fraction aNewX( rZoomX ); + if ( aNewX < aFrac20 ) + aNewX = aFrac20; + if ( aNewX > aFrac400 ) + aNewX = aFrac400; + Fraction aNewY( rZoomY ); + if ( aNewY < aFrac20 ) + aNewY = aFrac20; + if ( aNewY > aFrac400 ) + aNewY = aFrac400; + + GetViewData()->UpdateScreenZoom( aNewX, aNewY ); + SetZoom( aNewX, aNewY, sal_True ); + + PaintGrid(); + PaintTop(); + PaintLeft(); + + SfxViewShell::SetZoomFactor( rZoomX, rZoomY ); +} + +void __EXPORT ScTabViewShell::QueryObjAreaPixel( Rectangle& rRect ) const +{ + // auf ganze Zellen anpassen (in 1/100 mm) + + Size aPixelSize = rRect.GetSize(); + Window* pWin = ((ScTabViewShell*)this)->GetActiveWin(); + Size aLogicSize = pWin->PixelToLogic( aPixelSize ); + + const ScViewData* pViewData = GetViewData(); + ScDocument* pDoc = pViewData->GetDocument(); + ScSplitPos ePos = pViewData->GetActivePart(); + SCCOL nCol = pViewData->GetPosX(WhichH(ePos)); + SCROW nRow = pViewData->GetPosY(WhichV(ePos)); + SCTAB nTab = pViewData->GetTabNo(); + sal_Bool bNegativePage = pDoc->IsNegativePage( nTab ); + + Rectangle aLogicRect = pDoc->GetMMRect( nCol, nRow, nCol, nRow, nTab ); + if ( bNegativePage ) + { + // use right edge of aLogicRect, and aLogicSize + aLogicRect.Left() = aLogicRect.Right() - aLogicSize.Width() + 1; // Right() is set below + } + aLogicRect.SetSize( aLogicSize ); + + pDoc->SnapVisArea( aLogicRect ); + + rRect.SetSize( pWin->LogicToPixel( aLogicRect.GetSize() ) ); + +#if 0 + // auf ganze Zellen anpassen (in Pixeln) + + ScViewData* pViewData = ((ScTabViewShell*)this)->GetViewData(); + Size aSize = rRect.GetSize(); + + ScSplitPos ePos = pViewData->GetActivePart(); + Window* pWin = ((ScTabViewShell*)this)->GetActiveWin(); + + Point aTest( aSize.Width(), aSize.Height() ); + SCsCOL nPosX; + SCsROW nPosY; + pViewData->GetPosFromPixel( aTest.X(), aTest.Y(), ePos, nPosX, nPosY ); + sal_Bool bLeft; + sal_Bool bTop; + pViewData->GetMouseQuadrant( aTest, ePos, nPosX, nPosY, bLeft, bTop ); + if (!bLeft) + ++nPosX; + if (!bTop) + ++nPosY; + aTest = pViewData->GetScrPos( (SCCOL)nPosX, (SCROW)nPosY, ePos, sal_True ); + + rRect.SetSize(Size(aTest.X(),aTest.Y())); +#endif +} + +//------------------------------------------------------------------ + +void __EXPORT ScTabViewShell::Move() +{ + Point aNewPos = GetViewFrame()->GetWindow().OutputToScreenPixel(Point()); + + if (aNewPos != aWinPos) + { + StopMarking(); + aWinPos = aNewPos; + } +} + +//------------------------------------------------------------------ + +void __EXPORT ScTabViewShell::ShowCursor(FASTBOOL /* bOn */) +{ +/*!!! ShowCursor wird nicht paarweise wie im gridwin gerufen. + Der CursorLockCount am Gridwin muss hier direkt auf 0 gesetzt werden + + if (bOn) + ShowAllCursors(); + else + HideAllCursors(); +*/ +} + +//------------------------------------------------------------------ + +void __EXPORT ScTabViewShell::WriteUserData(String& rData, sal_Bool /* bBrowse */) +{ + GetViewData()->WriteUserData(rData); +} + +void ScTabViewShell::WriteUserDataSequence (uno::Sequence < beans::PropertyValue >& rSettings, sal_Bool /* bBrowse */ ) +{ + GetViewData()->WriteUserDataSequence (rSettings); +} + +void __EXPORT ScTabViewShell::ReadUserData(const String& rData, sal_Bool /* bBrowse */) +{ + if ( !GetViewData()->GetDocShell()->IsPreview() ) + DoReadUserData( rData ); +} + +void ScTabViewShell::ReadUserDataSequence (const uno::Sequence < beans::PropertyValue >& rSettings, sal_Bool /* bBrowse */ ) +{ + if ( !GetViewData()->GetDocShell()->IsPreview() ) + DoReadUserDataSequence( rSettings ); +} + +void ScTabViewShell::DoReadUserDataSequence( const uno::Sequence < beans::PropertyValue >& rSettings ) +{ + Window* pOldWin = GetActiveWin(); + sal_Bool bFocus = pOldWin && pOldWin->HasFocus(); + + GetViewData()->ReadUserDataSequence(rSettings); + SetTabNo( GetViewData()->GetTabNo(), sal_True ); + + if ( GetViewData()->IsPagebreakMode() ) + SetCurSubShell( GetCurObjectSelectionType(), sal_True ); + + Window* pNewWin = GetActiveWin(); + if (pNewWin && pNewWin != pOldWin) + { + SetWindow( pNewWin ); //! ist diese ViewShell immer aktiv??? + if (bFocus) + pNewWin->GrabFocus(); + WindowChanged(); // Drawing-Layer (z.B. #56771#) + } + + if (GetViewData()->GetHSplitMode() == SC_SPLIT_FIX || + GetViewData()->GetVSplitMode() == SC_SPLIT_FIX) + { + InvalidateSplit(); + } + + ZoomChanged(); + + TestHintWindow(); + + //! if ViewData has more tables than document, remove tables in ViewData +} + +// DoReadUserData is also called from ctor when switching from print preview + +void ScTabViewShell::DoReadUserData( const String& rData ) +{ + Window* pOldWin = GetActiveWin(); + sal_Bool bFocus = pOldWin && pOldWin->HasFocus(); + + GetViewData()->ReadUserData(rData); + SetTabNo( GetViewData()->GetTabNo(), sal_True ); + + if ( GetViewData()->IsPagebreakMode() ) + SetCurSubShell( GetCurObjectSelectionType(), sal_True ); + + Window* pNewWin = GetActiveWin(); + if (pNewWin && pNewWin != pOldWin) + { + SetWindow( pNewWin ); //! ist diese ViewShell immer aktiv??? + if (bFocus) + pNewWin->GrabFocus(); + WindowChanged(); // Drawing-Layer (z.B. #56771#) + } + + if (GetViewData()->GetHSplitMode() == SC_SPLIT_FIX || + GetViewData()->GetVSplitMode() == SC_SPLIT_FIX) + { + InvalidateSplit(); + } + + ZoomChanged(); + + TestHintWindow(); + + //! if ViewData has more tables than document, remove tables in ViewData +} + +//------------------------------------------------------------------ + +//UNUSED2008-05 void ScTabViewShell::ExecuteShowNIY( SfxRequest& /* rReq */ ) +//UNUSED2008-05 { +//UNUSED2008-05 ErrorMessage(STR_BOX_YNI); +//UNUSED2008-05 } +//UNUSED2008-05 +//UNUSED2008-05 //------------------------------------------------------------------ +//UNUSED2008-05 +//UNUSED2008-05 void ScTabViewShell::StateDisabled( SfxItemSet& rSet ) +//UNUSED2008-05 { +//UNUSED2008-05 SfxWhichIter aIter( rSet ); +//UNUSED2008-05 sal_uInt16 nWhich = aIter.FirstWhich(); +//UNUSED2008-05 +//UNUSED2008-05 while ( nWhich ) +//UNUSED2008-05 { +//UNUSED2008-05 rSet.DisableItem( nWhich ); +//UNUSED2008-05 nWhich = aIter.NextWhich(); +//UNUSED2008-05 } +//UNUSED2008-05 } + +void ScTabViewShell::SetDrawShellOrSub() +{ + bActiveDrawSh = sal_True; + + if(bActiveDrawFormSh) + { + SetCurSubShell(OST_DrawForm); + } + else if(bActiveGraphicSh) + { + SetCurSubShell(OST_Graphic); + } + else if(bActiveMediaSh) + { + SetCurSubShell(OST_Media); + } + else if(bActiveChartSh) + { + SetCurSubShell(OST_Chart); + } + else if(bActiveOleObjectSh) + { + SetCurSubShell(OST_OleObject); + } + else + { + SetCurSubShell(OST_Drawing, true /* force: different toolbars are + visible concerning shape type + and shape state */); + } +} + +void ScTabViewShell::SetDrawShell( sal_Bool bActive ) +{ + if(bActive) + { + SetCurSubShell(OST_Drawing, true /* force: different toolbars are + visible concerning shape type + and shape state */); + } + else + { + if(bActiveDrawFormSh || bActiveDrawSh || + bActiveGraphicSh || bActiveMediaSh || bActiveOleObjectSh|| + bActiveChartSh || bActiveDrawTextSh) + { + SetCurSubShell(OST_Cell); + } + bActiveDrawFormSh=sal_False; + bActiveGraphicSh=sal_False; + bActiveMediaSh=sal_False; + bActiveOleObjectSh=sal_False; + bActiveChartSh=sal_False; + } + + sal_Bool bWasDraw = bActiveDrawSh || bActiveDrawTextSh; + + bActiveDrawSh = bActive; + bActiveDrawTextSh = sal_False; + + if ( !bActive ) + { + ResetDrawDragMode(); // Mirror / Rotate aus + + if (bWasDraw && (GetViewData()->GetHSplitMode() == SC_SPLIT_FIX || + GetViewData()->GetVSplitMode() == SC_SPLIT_FIX)) + { + // Aktiven Teil an Cursor anpassen, etc. + MoveCursorAbs( GetViewData()->GetCurX(), GetViewData()->GetCurY(), + SC_FOLLOW_NONE, sal_False, sal_False, sal_True ); + } + } +} + +void ScTabViewShell::SetDrawTextShell( sal_Bool bActive ) +{ + bActiveDrawTextSh = bActive; + if ( bActive ) + { + bActiveDrawFormSh=sal_False; + bActiveGraphicSh=sal_False; + bActiveMediaSh=sal_False; + bActiveOleObjectSh=sal_False; + bActiveChartSh=sal_False; + bActiveDrawSh = sal_False; + SetCurSubShell(OST_DrawText); + } + else + SetCurSubShell(OST_Cell); + +} + +void ScTabViewShell::SetPivotShell( sal_Bool bActive ) +{ + bActivePivotSh = bActive; + + // #68771# #76198# SetPivotShell is called from CursorPosChanged every time + // -> don't change anything except switching between cell and pivot shell + + if ( eCurOST == OST_Pivot || eCurOST == OST_Cell ) + { + if ( bActive ) + { + bActiveDrawTextSh = bActiveDrawSh = sal_False; + bActiveDrawFormSh=sal_False; + bActiveGraphicSh=sal_False; + bActiveMediaSh=sal_False; + bActiveOleObjectSh=sal_False; + bActiveChartSh=sal_False; + SetCurSubShell(OST_Pivot); + } + else + SetCurSubShell(OST_Cell); + } +} + +void ScTabViewShell::SetAuditShell( sal_Bool bActive ) +{ + bActiveAuditingSh = bActive; + if ( bActive ) + { + bActiveDrawTextSh = bActiveDrawSh = sal_False; + bActiveDrawFormSh=sal_False; + bActiveGraphicSh=sal_False; + bActiveMediaSh=sal_False; + bActiveOleObjectSh=sal_False; + bActiveChartSh=sal_False; + SetCurSubShell(OST_Auditing); + } + else + SetCurSubShell(OST_Cell); +} + +void ScTabViewShell::SetDrawFormShell( sal_Bool bActive ) +{ + bActiveDrawFormSh = bActive; + + if(bActiveDrawFormSh) + SetCurSubShell(OST_DrawForm); +} +void ScTabViewShell::SetChartShell( sal_Bool bActive ) +{ + bActiveChartSh = bActive; + + if(bActiveChartSh) + SetCurSubShell(OST_Chart); +} + +void ScTabViewShell::SetGraphicShell( sal_Bool bActive ) +{ + bActiveGraphicSh = bActive; + + if(bActiveGraphicSh) + SetCurSubShell(OST_Graphic); +} + +void ScTabViewShell::SetMediaShell( sal_Bool bActive ) +{ + bActiveMediaSh = bActive; + + if(bActiveMediaSh) + SetCurSubShell(OST_Media); +} + +void ScTabViewShell::SetOleObjectShell( sal_Bool bActive ) +{ + bActiveOleObjectSh = bActive; + + if(bActiveOleObjectSh) + SetCurSubShell(OST_OleObject); + else + SetCurSubShell(OST_Cell); +} + +void ScTabViewShell::SetEditShell(EditView* pView, sal_Bool bActive ) +{ + if(bActive) + { + if (pEditShell) + pEditShell->SetEditView( pView ); + else + pEditShell = new ScEditShell( pView, GetViewData() ); + + SetCurSubShell(OST_Editing); + } + else if(bActiveEditSh) + { + SetCurSubShell(OST_Cell); + } + bActiveEditSh = bActive; +} + +void ScTabViewShell::SetCurSubShell(ObjectSelectionType eOST, sal_Bool bForce) +{ + ScViewData* pViewData = GetViewData(); + ScDocShell* pDocSh = pViewData->GetDocShell(); + + if(bDontSwitch) return; + + if(!pCellShell) //Wird eh immer gebraucht. + { + pCellShell = new ScCellShell( GetViewData() ); + pCellShell->SetRepeatTarget( &aTarget ); + } + + sal_Bool bPgBrk=pViewData->IsPagebreakMode(); + + if(bPgBrk && !pPageBreakShell) + { + pPageBreakShell = new ScPageBreakShell( this ); + pPageBreakShell->SetRepeatTarget( &aTarget ); + } + + + if ( eOST!=eCurOST || bForce ) + { + sal_Bool bCellBrush = sal_False; // "format paint brush" allowed for cells + sal_Bool bDrawBrush = sal_False; // "format paint brush" allowed for drawing objects + + if(eCurOST!=OST_NONE) RemoveSubShell(); + + if (pFormShell && !bFormShellAtTop) + AddSubShell(*pFormShell); // add below own subshells + + switch(eOST) + { + case OST_Cell: + { + AddSubShell(*pCellShell); + if(bPgBrk) AddSubShell(*pPageBreakShell); + bCellBrush = sal_True; + } + break; + case OST_Editing: + { + AddSubShell(*pCellShell); + if(bPgBrk) AddSubShell(*pPageBreakShell); + + if(pEditShell) + { + AddSubShell(*pEditShell); + } + } + break; + case OST_DrawText: + { + if ( !pDrawTextShell ) + { + pDocSh->MakeDrawLayer(); + pDrawTextShell = new ScDrawTextObjectBar( GetViewData() ); + } + AddSubShell(*pDrawTextShell); + } + break; + case OST_Drawing: + { + if (svx::checkForSelectedCustomShapes( + GetScDrawView(), true /* bOnlyExtruded */ )) { + if (pExtrusionBarShell == 0) + pExtrusionBarShell = new svx::ExtrusionBar(this); + AddSubShell( *pExtrusionBarShell ); + } + sal_uInt32 nCheckStatus = 0; + if (svx::checkForSelectedFontWork( + GetScDrawView(), nCheckStatus )) { + if (pFontworkBarShell == 0) + pFontworkBarShell = new svx::FontworkBar(this); + AddSubShell( *pFontworkBarShell ); + } + + if ( !pDrawShell ) + { + pDocSh->MakeDrawLayer(); + pDrawShell = new ScDrawShell( GetViewData() ); + pDrawShell->SetRepeatTarget( &aTarget ); + } + AddSubShell(*pDrawShell); + bDrawBrush = sal_True; + } + break; + + case OST_DrawForm: + { + if ( !pDrawFormShell ) + { + pDocSh->MakeDrawLayer(); + pDrawFormShell = new ScDrawFormShell( GetViewData() ); + pDrawFormShell->SetRepeatTarget( &aTarget ); + } + AddSubShell(*pDrawFormShell); + bDrawBrush = sal_True; + } + break; + + case OST_Chart: + { + if ( !pChartShell ) + { + pDocSh->MakeDrawLayer(); + pChartShell = new ScChartShell( GetViewData() ); + pChartShell->SetRepeatTarget( &aTarget ); + } + AddSubShell(*pChartShell); + bDrawBrush = sal_True; + } + break; + + case OST_OleObject: + { + if ( !pOleObjectShell ) + { + pDocSh->MakeDrawLayer(); + pOleObjectShell = new ScOleObjectShell( GetViewData() ); + pOleObjectShell->SetRepeatTarget( &aTarget ); + } + AddSubShell(*pOleObjectShell); + bDrawBrush = sal_True; + } + break; + + case OST_Graphic: + { + if ( !pGraphicShell) + { + pDocSh->MakeDrawLayer(); + pGraphicShell = new ScGraphicShell( GetViewData() ); + pGraphicShell->SetRepeatTarget( &aTarget ); + } + AddSubShell(*pGraphicShell); + bDrawBrush = sal_True; + } + break; + + case OST_Media: + { + if ( !pMediaShell) + { + pDocSh->MakeDrawLayer(); + pMediaShell = new ScMediaShell( GetViewData() ); + pMediaShell->SetRepeatTarget( &aTarget ); + } + AddSubShell(*pMediaShell); + } + break; + + case OST_Pivot: + { + AddSubShell(*pCellShell); + if(bPgBrk) AddSubShell(*pPageBreakShell); + + if ( !pPivotShell ) + { + pPivotShell = new ScPivotShell( this ); + pPivotShell->SetRepeatTarget( &aTarget ); + } + AddSubShell(*pPivotShell); + bCellBrush = sal_True; + } + break; + case OST_Auditing: + { + AddSubShell(*pCellShell); + if(bPgBrk) AddSubShell(*pPageBreakShell); + + if ( !pAuditingShell ) + { + pDocSh->MakeDrawLayer(); // die Wartezeit lieber jetzt als beim Klick + + pAuditingShell = new ScAuditingShell( GetViewData() ); + pAuditingShell->SetRepeatTarget( &aTarget ); + } + AddSubShell(*pAuditingShell); + bCellBrush = sal_True; + } + break; + default: + DBG_ERROR("Falsche Shell angefordert"); + break; + } + + if (pFormShell && bFormShellAtTop) + AddSubShell(*pFormShell); // add on top of own subshells + + eCurOST=eOST; + + // abort "format paint brush" when switching to an incompatible shell + if ( ( GetBrushDocument() && !bCellBrush ) || ( GetDrawBrushSet() && !bDrawBrush ) ) + ResetBrushDocument(); + } +} + +void ScTabViewShell::SetFormShellAtTop( sal_Bool bSet ) +{ + if ( pFormShell && !bSet ) + pFormShell->ForgetActiveControl(); // let the FormShell know it no longer has the focus + + if ( bFormShellAtTop != bSet ) + { + bFormShellAtTop = bSet; + SetCurSubShell( GetCurObjectSelectionType(), sal_True ); + } +} + +IMPL_LINK( ScTabViewShell, FormControlActivated, FmFormShell*, EMPTYARG ) +{ + // a form control got the focus, so the form shell has to be on top + SetFormShellAtTop( sal_True ); + return 0; +} + +ObjectSelectionType ScTabViewShell::GetCurObjectSelectionType() +{ + return eCurOST; +} + +// GetMySubShell / SetMySubShell: altes Verhalten simulieren, +// dass es nur eine SubShell gibt (nur innerhalb der 5 eignenen SubShells) + +SfxShell* ScTabViewShell::GetMySubShell() const +{ + // GetSubShell() war frueher const, und GetSubShell(sal_uInt16) sollte es auch sein... + + sal_uInt16 nPos = 0; + SfxShell* pSub = ((ScTabViewShell*)this)->GetSubShell(nPos); + while (pSub) + { + if ( pSub == pDrawShell || pSub == pDrawTextShell || pSub == pEditShell || + pSub == pPivotShell || pSub == pAuditingShell || pSub == pDrawFormShell || + pSub == pCellShell || pSub == pOleObjectShell|| pSub == pChartShell || + pSub == pGraphicShell || pSub == pMediaShell || pSub == pPageBreakShell) + return pSub; // gefunden + + pSub = ((ScTabViewShell*)this)->GetSubShell(++nPos); + } + return NULL; // keine von meinen dabei +} + +//UNUSED2008-05 void ScTabViewShell::SetMySubShell( SfxShell* pShell ) +//UNUSED2008-05 { +//UNUSED2008-05 SfxShell* pOld = GetMySubShell(); +//UNUSED2008-05 if ( pOld != pShell ) +//UNUSED2008-05 { +//UNUSED2008-05 if (pOld) +//UNUSED2008-05 RemoveSubShell(pOld); // alte SubShell entfernen +//UNUSED2008-05 if (pShell) +//UNUSED2008-05 AddSubShell(*pShell); // neue setzen +//UNUSED2008-05 } +//UNUSED2008-05 } + +sal_Bool ScTabViewShell::IsDrawTextShell() const +{ + return ( pDrawTextShell && ( GetMySubShell() == pDrawTextShell ) ); +} + +sal_Bool ScTabViewShell::IsAuditShell() const +{ + return ( pAuditingShell && ( GetMySubShell() == pAuditingShell ) ); +} + +void ScTabViewShell::SetDrawTextUndo( ::svl::IUndoManager* pNewUndoMgr ) +{ + // Default: Undo-Manager der DocShell + if (!pNewUndoMgr) + pNewUndoMgr = GetViewData()->GetDocShell()->GetUndoManager(); + + if (pDrawTextShell) + { + pDrawTextShell->SetUndoManager(pNewUndoMgr); + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + if ( pNewUndoMgr == pDocSh->GetUndoManager() && + !pDocSh->GetDocument()->IsUndoEnabled() ) + { + pNewUndoMgr->SetMaxUndoActionCount( 0 ); + } + } + else + { + DBG_ERROR("SetDrawTextUndo ohne DrawTextShell"); + } +} + +//------------------------------------------------------------------ + +ScTabViewShell* ScTabViewShell::GetActiveViewShell() +{ + return PTR_CAST(ScTabViewShell,Current()); +} + +//------------------------------------------------------------------ + +SfxPrinter* __EXPORT ScTabViewShell::GetPrinter( sal_Bool bCreate ) +{ + // Drucker ist immer da (wird fuer die FontListe schon beim Starten angelegt) + return GetViewData()->GetDocShell()->GetPrinter(bCreate); +} + +sal_uInt16 __EXPORT ScTabViewShell::SetPrinter( SfxPrinter *pNewPrinter, sal_uInt16 nDiffFlags, bool ) +{ + return GetViewData()->GetDocShell()->SetPrinter( pNewPrinter, nDiffFlags ); +} + +SfxTabPage* ScTabViewShell::CreatePrintOptionsPage( Window *pParent, const SfxItemSet &rOptions ) +{ + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + //CHINA001 return ScTpPrintOptions::Create( pParent, rOptions ); + ::CreateTabPage ScTpPrintOptionsCreate = pFact->GetTabPageCreatorFunc( RID_SCPAGE_PRINT ); + if ( ScTpPrintOptionsCreate ) + return (*ScTpPrintOptionsCreate)( pParent, rOptions); + return 0; +} + +void ScTabViewShell::StopEditShell() +{ + if ( pEditShell != NULL && !bDontSwitch ) + SetEditShell(NULL, sal_False ); +} + +//------------------------------------------------------------------ + +// close handler to ensure function of dialog: + +IMPL_LINK( ScTabViewShell, SimpleRefClose, String*, EMPTYARG ) +{ + SfxInPlaceClient* pClient = GetIPClient(); + if ( pClient && pClient->IsObjectInPlaceActive() ) + { + // If range selection was started with an active embedded object, + // switch back to original sheet (while the dialog is still open). + + SetTabNo( GetViewData()->GetRefTabNo() ); + } + + ScSimpleRefDlgWrapper::SetAutoReOpen( sal_True ); + return 0; +} + +// handlers to call UNO listeners: + +ScTabViewObj* lcl_GetViewObj( ScTabViewShell& rShell ) +{ + ScTabViewObj* pRet = NULL; + SfxViewFrame* pViewFrame = rShell.GetViewFrame(); + if (pViewFrame) + { + SfxFrame& rFrame = pViewFrame->GetFrame(); + uno::Reference<frame::XController> xController = rFrame.GetController(); + if (xController.is()) + pRet = ScTabViewObj::getImplementation( xController ); + } + return pRet; +} + +IMPL_LINK( ScTabViewShell, SimpleRefDone, String*, pResult ) +{ + ScTabViewObj* pImpObj = lcl_GetViewObj( *this ); + if ( pImpObj && pResult ) + pImpObj->RangeSelDone( *pResult ); + return 0; +} + +IMPL_LINK( ScTabViewShell, SimpleRefAborted, String*, pResult ) +{ + ScTabViewObj* pImpObj = lcl_GetViewObj( *this ); + if ( pImpObj && pResult ) + pImpObj->RangeSelAborted( *pResult ); + return 0; +} + +IMPL_LINK( ScTabViewShell, SimpleRefChange, String*, pResult ) +{ + ScTabViewObj* pImpObj = lcl_GetViewObj( *this ); + if ( pImpObj && pResult ) + pImpObj->RangeSelChanged( *pResult ); + return 0; +} + +void ScTabViewShell::StartSimpleRefDialog( + const String& rTitle, const String& rInitVal, + sal_Bool bCloseOnButtonUp, sal_Bool bSingleCell, sal_Bool bMultiSelection ) +{ + SfxViewFrame* pViewFrm = GetViewFrame(); + + if ( GetActiveViewShell() != this ) + { + // #i18833# / #i34499# The API method can be called for a view that's not active. + // Then the view has to be activated first, the same way as in Execute for SID_CURRENTDOC. + // Can't use GrabFocus here, because it needs to take effect immediately. + + pViewFrm->GetFrame().Appear(); + } + + sal_uInt16 nId = ScSimpleRefDlgWrapper::GetChildWindowId(); + + SC_MOD()->SetRefDialog( nId, sal_True, pViewFrm ); + + ScSimpleRefDlgWrapper* pWnd = (ScSimpleRefDlgWrapper*)pViewFrm->GetChildWindow( nId ); + if (pWnd) + { + pWnd->SetCloseHdl( LINK( this, ScTabViewShell, SimpleRefClose ) ); + pWnd->SetUnoLinks( LINK( this, ScTabViewShell, SimpleRefDone ), + LINK( this, ScTabViewShell, SimpleRefAborted ), + LINK( this, ScTabViewShell, SimpleRefChange ) ); + pWnd->SetRefString( rInitVal ); + pWnd->SetFlags( bCloseOnButtonUp, bSingleCell, bMultiSelection ); + pWnd->SetAutoReOpen( sal_False ); + Window* pWin = pWnd->GetWindow(); + pWin->SetText( rTitle ); + pWnd->StartRefInput(); + } +} + +void ScTabViewShell::StopSimpleRefDialog() +{ + SfxViewFrame* pViewFrm = GetViewFrame(); + sal_uInt16 nId = ScSimpleRefDlgWrapper::GetChildWindowId(); + + ScSimpleRefDlgWrapper* pWnd = (ScSimpleRefDlgWrapper*)pViewFrm->GetChildWindow( nId ); + if (pWnd) + { + Window* pWin = pWnd->GetWindow(); + if (pWin && pWin->IsSystemWindow()) + ((SystemWindow*)pWin)->Close(); // calls abort handler + } +} + +//------------------------------------------------------------------ + +sal_Bool ScTabViewShell::TabKeyInput(const KeyEvent& rKEvt) +{ + ScModule* pScMod = SC_MOD(); + + SfxViewFrame* pThisFrame = GetViewFrame(); + if ( pThisFrame->GetChildWindow( SID_OPENDLG_FUNCTION ) ) + return sal_False; + + KeyCode aCode = rKEvt.GetKeyCode(); + sal_Bool bShift = aCode.IsShift(); + sal_Bool bControl = aCode.IsMod1(); + sal_Bool bAlt = aCode.IsMod2(); + sal_uInt16 nCode = aCode.GetCode(); + sal_Bool bUsed = sal_False; + sal_Bool bInPlace = pScMod->IsEditMode(); // Editengine bekommt alles + sal_Bool bAnyEdit = pScMod->IsInputMode(); // nur Zeichen & Backspace + sal_Bool bDraw = IsDrawTextEdit(); + + HideNoteMarker(); // Notiz-Anzeige + + // don't do extra HideCursor/ShowCursor calls if EnterHandler will switch to a different sheet + sal_Bool bOnRefSheet = ( GetViewData()->GetRefTabNo() == GetViewData()->GetTabNo() ); + sal_Bool bHideCursor = ( ( nCode == KEY_RETURN && bInPlace ) || nCode == KEY_TAB ) && bOnRefSheet; + + if (bHideCursor) + HideAllCursors(); + + ScDocument* pDoc = GetViewData()->GetDocument(); + if ( pDoc ) + pDoc->KeyInput( rKEvt ); // TimerDelays etc. + + if( bInPlace ) + { + bUsed = pScMod->InputKeyEvent( rKEvt ); // Eingabe + if( !bUsed ) + bUsed = sal::static_int_cast<sal_Bool>(SfxViewShell::KeyInput( rKEvt )); // accelerators + } + else if( bAnyEdit ) + { + sal_Bool bIsType = sal_False; + sal_uInt16 nModi = aCode.GetModifier(); + sal_uInt16 nGroup = aCode.GetGroup(); + + if ( nGroup == KEYGROUP_NUM || nGroup == KEYGROUP_ALPHA || nGroup == 0 ) + if ( !bControl && !bAlt ) + bIsType = sal_True; + + if ( nGroup == KEYGROUP_MISC ) + switch ( nCode ) + { + case KEY_RETURN: + bIsType = bControl && !bAlt; // Control, Shift-Control-Return + if ( !bIsType && nModi == 0 ) + { + // Will der InputHandler auch ein einfaches Return? + + ScInputHandler* pHdl = pScMod->GetInputHdl(this); + bIsType = pHdl && pHdl->TakesReturn(); + } + break; + case KEY_SPACE: + bIsType = !bControl && !bAlt; // ohne Modifier oder Shift-Space + break; + case KEY_ESCAPE: + case KEY_BACKSPACE: + bIsType = (nModi == 0); // nur ohne Modifier + break; + default: + bIsType = sal_True; + } + + if( bIsType ) + bUsed = pScMod->InputKeyEvent( rKEvt ); // Eingabe + + if( !bUsed ) + bUsed = sal::static_int_cast<sal_Bool>(SfxViewShell::KeyInput( rKEvt )); // accelerators + + if ( !bUsed && !bIsType && nCode != KEY_RETURN ) // Eingabe nochmal hinterher + bUsed = pScMod->InputKeyEvent( rKEvt ); + } + else + { + // #51889# Spezialfall: Copy/Cut bei Mehrfachselektion -> Fehlermeldung + // (Slot ist disabled, SfxViewShell::KeyInput wuerde also kommentarlos verschluckt) + KeyFuncType eFunc = aCode.GetFunction(); + if ( eFunc == KEYFUNC_CUT ) + { + ScRange aDummy; + ScMarkType eMarkType = GetViewData()->GetSimpleArea( aDummy ); + if ( eMarkType != SC_MARK_SIMPLE && + !(eFunc == KEYFUNC_COPY && eMarkType == SC_MARK_SIMPLE_FILTERED) ) + { + ErrorMessage(STR_NOMULTISELECT); + bUsed = sal_True; + } + } + if (!bUsed) + bUsed = sal::static_int_cast<sal_Bool>(SfxViewShell::KeyInput( rKEvt )); // accelerators + + // #74696# during inplace editing, some slots are handled by the + // container app and are executed during Window::KeyInput. + // -> don't pass keys to input handler that would be used there + // but should call slots instead. + sal_Bool bParent = ( GetViewFrame()->GetFrame().IsInPlace() && eFunc != KEYFUNC_DONTKNOW ); + + if( !bUsed && !bDraw && nCode != KEY_RETURN && !bParent ) + bUsed = pScMod->InputKeyEvent( rKEvt, sal_True ); // Eingabe + } + + if (!bInPlace && !bUsed && !bDraw) + { + switch (nCode) + { + case KEY_RETURN: + { + sal_Bool bNormal = !bControl && !bAlt; + if ( !bAnyEdit && bNormal ) + { + // je nach Optionen mit Enter in den Edit-Modus schalten + + const ScInputOptions& rOpt = pScMod->GetInputOptions(); + if ( rOpt.GetEnterEdit() ) + { + pScMod->SetInputMode( SC_INPUT_TABLE ); + bUsed = sal_True; + } + } + + sal_Bool bEditReturn = bControl && !bShift; // An Edit-Engine weiter + if ( !bUsed && !bEditReturn ) + { + if ( bOnRefSheet ) + HideAllCursors(); + + sal_uInt8 nMode = SC_ENTER_NORMAL; + if ( bShift && bControl ) + nMode = SC_ENTER_MATRIX; + else if ( bAlt ) + nMode = SC_ENTER_BLOCK; + pScMod->InputEnterHandler(nMode); + + if (nMode == SC_ENTER_NORMAL) + { + if( bShift ) + GetViewData()->GetDispatcher().Execute( SID_CURSORENTERUP, + SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD ); + else + GetViewData()->GetDispatcher().Execute( SID_CURSORENTERDOWN, + SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD ); + } + else + UpdateInputHandler(sal_True); + + if ( bOnRefSheet ) + ShowAllCursors(); + + // hier kein UpdateInputHandler, weil bei Referenzeingabe auf ein + // anderes Dokument diese ViewShell nicht die ist, auf der eingegeben + // wird! + + bUsed = sal_True; + } + } + break; + } + } + + // Alt-Cursortasten hart codiert, weil Alt nicht konfigurierbar ist + + if ( !bUsed && bAlt && !bControl ) + { + sal_uInt16 nSlotId = 0; + switch (nCode) + { + case KEY_UP: + ModifyCellSize( DIR_TOP, bShift ); + bUsed = sal_True; + break; + case KEY_DOWN: + ModifyCellSize( DIR_BOTTOM, bShift ); + bUsed = sal_True; + break; + case KEY_LEFT: + ModifyCellSize( DIR_LEFT, bShift ); + bUsed = sal_True; + break; + case KEY_RIGHT: + ModifyCellSize( DIR_RIGHT, bShift ); + bUsed = sal_True; + break; + case KEY_PAGEUP: + nSlotId = bShift ? SID_CURSORPAGELEFT_SEL : SID_CURSORPAGELEFT_; + break; + case KEY_PAGEDOWN: + nSlotId = bShift ? SID_CURSORPAGERIGHT_SEL : SID_CURSORPAGERIGHT_; + break; + } + if ( nSlotId ) + { + GetViewData()->GetDispatcher().Execute( nSlotId, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD ); + bUsed = sal_True; + } + } + + if (bHideCursor) + ShowAllCursors(); + + return bUsed; +} + +sal_Bool ScTabViewShell::SfxKeyInput(const KeyEvent& rKeyEvent) +{ + return sal::static_int_cast<sal_Bool>(SfxViewShell::KeyInput( rKeyEvent )); +} + +FASTBOOL __EXPORT ScTabViewShell::KeyInput( const KeyEvent &rKeyEvent ) +{ +// return SfxViewShell::KeyInput( rKeyEvent ); + return TabKeyInput( rKeyEvent ); +} + +//------------------------------------------------------------------ + +#define __INIT_ScTabViewShell \ + eCurOST(OST_NONE), \ + nDrawSfxId(0), \ + nCtrlSfxId(USHRT_MAX), \ + nFormSfxId(USHRT_MAX), \ + pDrawShell(NULL), \ + pDrawTextShell(NULL), \ + pEditShell(NULL), \ + pPivotShell(NULL), \ + pAuditingShell(NULL), \ + pDrawFormShell(NULL), \ + pCellShell(NULL), \ + pOleObjectShell(NULL), \ + pChartShell(NULL), \ + pGraphicShell(NULL), \ + pMediaShell(NULL), \ + pPageBreakShell(NULL), \ + pExtrusionBarShell(NULL), \ + pFontworkBarShell(NULL), \ + pFormShell(NULL), \ + pInputHandler(NULL), \ + pCurFrameLine(NULL), \ + aTarget( this ), \ + pDialogDPObject(NULL), \ + pNavSettings(NULL), \ + bActiveDrawSh(sal_False), \ + bActiveDrawTextSh(sal_False), \ + bActivePivotSh(sal_False), \ + bActiveAuditingSh(sal_False), \ + bActiveDrawFormSh(sal_False), \ + bActiveOleObjectSh(sal_False), \ + bActiveChartSh(sal_False), \ + bActiveGraphicSh(sal_False), \ + bActiveMediaSh(sal_False), \ + bActiveEditSh(sal_False), \ + bFormShellAtTop(sal_False), \ + bDontSwitch(sal_False), \ + bInFormatDialog(sal_False), \ + bPrintSelected(sal_False), \ + bReadOnly(sal_False), \ + pScSbxObject(NULL), \ + /*bChartDlgIsEdit(sal_False),*/ \ + bChartAreaValid(sal_False), \ + nCurRefDlgId(0), \ + pAccessibilityBroadcaster(NULL) + + +//------------------------------------------------------------------ + +void ScTabViewShell::Construct( sal_uInt8 nForceDesignMode ) +{ + SfxApplication* pSfxApp = SFX_APP(); + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + + bReadOnly = pDocSh->IsReadOnly(); + + SetName( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("View")) ); // fuer SBX + Color aColBlack( COL_BLACK ); +// SetPool( &pSfxApp->GetPool() ); + SetPool( &SC_MOD()->GetPool() ); + SetWindow( GetActiveWin() ); + + pCurFrameLine = new SvxBorderLine( &aColBlack, 20, 0, 0 ); + pPivotSource = new ScArea; + StartListening(*GetViewData()->GetDocShell(),sal_True); + StartListening(*GetViewFrame(),sal_True); + StartListening(*pSfxApp,sal_True); // #i62045# #i62046# application is needed for Calc's own hints + + SfxViewFrame* pFirst = SfxViewFrame::GetFirst(pDocSh); + sal_Bool bFirstView = !pFirst + || (pFirst == GetViewFrame() && !SfxViewFrame::GetNext(*pFirst,pDocSh)); + + if ( pDocSh->GetCreateMode() == SFX_CREATE_MODE_EMBEDDED ) + { + //TODO/LATER: is there a difference between the two GetVisArea methods? + Rectangle aVisArea = ((const SfxObjectShell*)pDocSh)->GetVisArea(); + + SCTAB nVisTab = pDoc->GetVisibleTab(); + if (!pDoc->HasTable(nVisTab)) + { + nVisTab = 0; + pDoc->SetVisibleTab(nVisTab); + } + SetTabNo( nVisTab ); + sal_Bool bNegativePage = pDoc->IsNegativePage( nVisTab ); + // show the right cells + GetViewData()->SetScreenPos( bNegativePage ? aVisArea.TopRight() : aVisArea.TopLeft() ); + + if ( GetViewFrame()->GetFrame().IsInPlace() ) // inplace + { + pDocSh->SetInplace( sal_True ); // schon so initialisiert + if (pDoc->IsEmbedded()) + pDoc->ResetEmbedded(); // keine blaue Markierung + } + else if ( bFirstView ) + { + pDocSh->SetInplace( sal_False ); + GetViewData()->RefreshZoom(); // recalculate PPT + if (!pDoc->IsEmbedded()) + pDoc->SetEmbedded( aVisArea ); // VisArea markieren + } + } + + // ViewInputHandler + // #48721# jeder Task hat neuerdings sein eigenes InputWindow, + // darum muesste eigentlich entweder jeder Task seinen InputHandler bekommen, + // oder das InputWindow muesste sich beim App-InputHandler anmelden, wenn der + // Task aktiv wird, oder das InputWindow muesste sich den InputHandler selbst + // anlegen (dann immer ueber das InputWindow suchen, und nur wenn das nicht da + // ist, den InputHandler von der App nehmen). + // Als Sofortloesung bekommt erstmal jede View ihren Inputhandler, das gibt + // nur noch Probleme, wenn zwei Views in einem Task-Fenster sind. + + pInputHandler = new ScInputHandler; + + // Alte Version: + // if ( !GetViewFrame()->ISA(SfxTopViewFrame) ) // OLE oder Plug-In + // pInputHandler = new ScInputHandler; + + // FormShell vor MakeDrawView anlegen, damit die DrawView auf jeden Fall + // an der FormShell angemeldet werden kann + // Gepusht wird die FormShell im ersten Activate + pFormShell = new FmFormShell(this); + pFormShell->SetControlActivationHandler( LINK( this, ScTabViewShell, FormControlActivated ) ); + + // DrawView darf nicht im TabView - ctor angelegt werden, + // wenn die ViewShell noch nicht kostruiert ist... + if (pDoc->GetDrawLayer()) + MakeDrawView( nForceDesignMode ); + ViewOptionsHasChanged(sal_False); // legt auch evtl. DrawView an + + ::svl::IUndoManager* pMgr = pDocSh->GetUndoManager(); + SetUndoManager( pMgr ); + pFormShell->SetUndoManager( pMgr ); + if ( !pDoc->IsUndoEnabled() ) + { + pMgr->SetMaxUndoActionCount( 0 ); + } + SetRepeatTarget( &aTarget ); + pFormShell->SetRepeatTarget( &aTarget ); + SetHelpId( HID_SCSHELL_TABVWSH ); + + if ( bFirstView ) // first view? + { + pDoc->SetDocVisible( sal_True ); // used when creating new sheets + if ( pDocSh->IsEmpty() ) + { + // set first sheet's RTL flag (following will already be initialized because of SetDocVisible) + pDoc->SetLayoutRTL( 0, ScGlobal::IsSystemRTL() ); + + // append additional sheets (not for OLE object) + if ( pDocSh->GetCreateMode() != SFX_CREATE_MODE_EMBEDDED ) + { + SCTAB nInitTabCount = 3; //! konfigurierbar !!! + for (SCTAB i=1; i<nInitTabCount; i++) + pDoc->MakeTable(i,false); + } + + pDocSh->SetEmpty( sal_False ); // #i6232# make sure this is done only once + } + + // ReadExtOptions is now in Activate + + // Link-Update nicht verschachteln + if ( pDocSh->GetCreateMode() != SFX_CREATE_MODE_INTERNAL && + pDocSh->IsUpdateEnabled() ) // #105575#; update only in the first creation of the ViewShell + { + // Check if there are any external data. + bool bLink = pDoc->GetExternalRefManager()->hasExternalData(); + if (!bLink) + { + // #i100042# sheet links can still exist independently from external formula references + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB i=0; i<nTabCount && !bLink; i++) + if (pDoc->IsLinked(i)) + bLink = true; + } + if (!bLink) + if (pDoc->HasDdeLinks() || pDoc->HasAreaLinks()) + bLink = sal_True; + if (bLink) + { + if ( !pFirst ) + pFirst = GetViewFrame(); + + if(SC_MOD()->GetCurRefDlgId()==0) + { + pFirst->GetDispatcher()->Execute( SID_UPDATETABLINKS, + SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD ); + } + } + + sal_Bool bReImport = sal_False; // importierte Daten aktualisieren + ScDBCollection* pDBColl = pDoc->GetDBCollection(); + if ( pDBColl ) + { + sal_uInt16 nCount = pDBColl->GetCount(); + for (sal_uInt16 i=0; i<nCount && !bReImport; i++) + { + ScDBData* pData = (*pDBColl)[i]; + if ( pData->IsStripData() && + pData->HasImportParam() && !pData->HasImportSelection() ) + bReImport = sal_True; + } + } + if (bReImport) + { + if ( !pFirst ) + pFirst = GetViewFrame(); + if(SC_MOD()->GetCurRefDlgId()==0) + { + pFirst->GetDispatcher()->Execute( SID_REIMPORT_AFTER_LOAD, + SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD ); + } + } + } + } + + UpdateAutoFillMark(); + + // ScDispatchProviderInterceptor registers itself in ctor + xDisProvInterceptor = new ScDispatchProviderInterceptor( this ); + + bFirstActivate = sal_True; // NavigatorUpdate aufschieben bis Activate() + + // #105575#; update only in the first creation of the ViewShell + pDocSh->SetUpdateEnabled(sal_False); + + if ( GetViewFrame()->GetFrame().IsInPlace() ) + UpdateHeaderWidth(); // The implace activation requires headers to be calculated + + SvBorder aBorder; + GetBorderSize( aBorder, Size() ); + SetBorderPixel( aBorder ); +} + +//------------------------------------------------------------------ + +//UNUSED2008-05 ScTabViewShell::ScTabViewShell( SfxViewFrame* pViewFrame, +//UNUSED2008-05 const ScTabViewShell& rWin ) : +//UNUSED2008-05 SfxViewShell( pViewFrame, SFX_VIEW_MAXIMIZE_FIRST | SFX_VIEW_CAN_PRINT | SFX_VIEW_HAS_PRINTOPTIONS ), +//UNUSED2008-05 ScDBFunc( &pViewFrame->GetWindow(), rWin, this ), +//UNUSED2008-05 __INIT_ScTabViewShell +//UNUSED2008-05 { +//UNUSED2008-05 RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScTabViewShell::ScTabViewShell" ); +//UNUSED2008-05 +//UNUSED2008-05 Construct(); +//UNUSED2008-05 +//UNUSED2008-05 UpdatePageBreakData(); +//UNUSED2008-05 +//UNUSED2008-05 /*uno::Reference<frame::XFrame> xFrame = pViewFrame->GetFrame().GetFrameInterface(); +//UNUSED2008-05 if (xFrame.is()) +//UNUSED2008-05 xFrame->setComponent( uno::Reference<awt::XWindow>(), new ScTabViewObj( this ) );*/ +//UNUSED2008-05 // make Controller known to SFX +//UNUSED2008-05 new ScTabViewObj( this ); +//UNUSED2008-05 +//UNUSED2008-05 SetCurSubShell(OST_Cell); +//UNUSED2008-05 SvBorder aBorder; +//UNUSED2008-05 GetBorderSize( aBorder, Size() ); +//UNUSED2008-05 SetBorderPixel( aBorder ); +//UNUSED2008-05 } + +//------------------------------------------------------------------ + +ScTabViewShell::ScTabViewShell( SfxViewFrame* pViewFrame, + SfxViewShell* pOldSh ) : + SfxViewShell( pViewFrame, SFX_VIEW_CAN_PRINT | SFX_VIEW_HAS_PRINTOPTIONS ), + ScDBFunc( &pViewFrame->GetWindow(), (ScDocShell&)*pViewFrame->GetObjectShell(), this ), + __INIT_ScTabViewShell +{ + RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScTabViewShell::ScTabViewShell" ); + + const ScAppOptions& rAppOpt = SC_MOD()->GetAppOptions(); + + // if switching back from print preview, + // restore the view settings that were active when creating the preview + // #89897# ReadUserData must not happen from ctor, because the view's edit window + // has to be shown by the sfx. ReadUserData is deferred until the first Activate call. + // #106334# old DesignMode state from form layer must be restored, too + + sal_uInt8 nForceDesignMode = SC_FORCEMODE_NONE; + if ( pOldSh && pOldSh->ISA( ScPreviewShell ) ) + { + ScPreviewShell* pPreviewShell = ((ScPreviewShell*)pOldSh); + nForceDesignMode = pPreviewShell->GetSourceDesignMode(); + } + + Construct( nForceDesignMode ); + + if ( GetViewData()->GetDocShell()->IsPreview() ) + { + // preview for template dialog: always show whole page + SetZoomType( SVX_ZOOM_WHOLEPAGE, sal_True ); // zoom value is recalculated at next Resize + } + else + { + Fraction aFract( rAppOpt.GetZoom(), 100 ); + SetZoom( aFract, aFract, sal_True ); + SetZoomType( rAppOpt.GetZoomType(), sal_True ); + } + + /*uno::Reference<frame::XFrame> xFrame = pViewFrame->GetFrame().GetFrameInterface(); + if (xFrame.is()) + xFrame->setComponent( uno::Reference<awt::XWindow>(), new ScTabViewObj( this ) );*/ + // make Controller known to SFX + new ScTabViewObj( this ); + + SetCurSubShell(OST_Cell); + SvBorder aBorder; + GetBorderSize( aBorder, Size() ); + SetBorderPixel( aBorder ); + + // #114409# + MakeDrawLayer(); +} + +#undef __INIT_ScTabViewShell + +//------------------------------------------------------------------ + +__EXPORT ScTabViewShell::~ScTabViewShell() +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + EndListening(*pDocSh); + EndListening(*GetViewFrame()); + EndListening(*SFX_APP()); // #i62045# #i62046# needed now - SfxViewShell no longer does it + + SC_MOD()->ViewShellGone(this); + + RemoveSubShell(); // alle + SetWindow(0); + + // #54104# alles auf NULL, falls aus dem TabView-dtor noch darauf zugegriffen wird + //! (soll eigentlich nicht !??!?!) + + DELETEZ(pFontworkBarShell); + DELETEZ(pExtrusionBarShell); + DELETEZ(pCellShell); + DELETEZ(pPageBreakShell); + DELETEZ(pDrawShell); + DELETEZ(pDrawFormShell); + DELETEZ(pOleObjectShell); + DELETEZ(pChartShell); + DELETEZ(pGraphicShell); + DELETEZ(pMediaShell); + DELETEZ(pDrawTextShell); + DELETEZ(pEditShell); + DELETEZ(pPivotShell); + DELETEZ(pAuditingShell); + DELETEZ(pCurFrameLine); + DELETEZ(pInputHandler); + DELETEZ(pPivotSource); + DELETEZ(pDialogDPObject); + DELETEZ(pNavSettings); + + DELETEZ(pFormShell); + DELETEZ(pAccessibilityBroadcaster); +} + +//------------------------------------------------------------------ + +void ScTabViewShell::SetDialogDPObject( const ScDPObject* pObj ) +{ + delete pDialogDPObject; + if (pObj) + pDialogDPObject = new ScDPObject( *pObj ); + else + pDialogDPObject = NULL; +} + +//------------------------------------------------------------------ + +void ScTabViewShell::FillFieldData( ScHeaderFieldData& rData ) +{ + ScDocShell* pDocShell = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocShell->GetDocument(); + SCTAB nTab = GetViewData()->GetTabNo(); + pDoc->GetName( nTab, rData.aTabName ); + + rData.aTitle = pDocShell->GetTitle(); + const INetURLObject& rURLObj = pDocShell->GetMedium()->GetURLObject(); + rData.aLongDocName = rURLObj.GetMainURL( INetURLObject::DECODE_UNAMBIGUOUS ); + if ( rData.aLongDocName.Len() ) + rData.aShortDocName = rURLObj.GetName( INetURLObject::DECODE_UNAMBIGUOUS ); + else + rData.aShortDocName = rData.aLongDocName = rData.aTitle; + rData.nPageNo = 1; + rData.nTotalPages = 99; + + // eNumType kennt der Dialog selber +} + +//------------------------------------------------------------------ + +void ScTabViewShell::SetChartArea( const ScRangeListRef& rSource, const Rectangle& rDest ) +{ + bChartAreaValid = sal_True; + aChartSource = rSource; + aChartPos = rDest; + nChartDestTab = GetViewData()->GetTabNo(); +} + +//UNUSED2008-05 void ScTabViewShell::ResetChartArea() +//UNUSED2008-05 { +//UNUSED2008-05 bChartAreaValid = sal_False; +//UNUSED2008-05 } + +sal_Bool ScTabViewShell::GetChartArea( ScRangeListRef& rSource, Rectangle& rDest, SCTAB& rTab ) const +{ + rSource = aChartSource; + rDest = aChartPos; + rTab = nChartDestTab; + return bChartAreaValid; +} + +//UNUSED2008-05 sal_Bool ScTabViewShell::IsChartDlgEdit() const +//UNUSED2008-05 { +//UNUSED2008-05 return bChartDlgIsEdit; +//UNUSED2008-05 } +//UNUSED2008-05 +//UNUSED2008-05 const String& ScTabViewShell::GetEditChartName() const +//UNUSED2008-05 { +//UNUSED2008-05 return aEditChartName; +//UNUSED2008-05 } + +ScNavigatorSettings* ScTabViewShell::GetNavigatorSettings() +{ + if( !pNavSettings ) + pNavSettings = new ScNavigatorSettings; + return pNavSettings; +} + + +//------------------------------------------------------------------ + +void ScTabViewShell::ExecTbx( SfxRequest& rReq ) +{ + const SfxItemSet* pReqArgs = rReq.GetArgs(); + sal_uInt16 nSlot = rReq.GetSlot(); + const SfxPoolItem* pItem = NULL; + if ( pReqArgs ) + pReqArgs->GetItemState( nSlot, sal_True, &pItem ); + + switch ( nSlot ) + { + case SID_TBXCTL_INSERT: + if ( pItem ) + nInsertCtrlState = ((const SfxUInt16Item*)pItem)->GetValue(); + break; + case SID_TBXCTL_INSCELLS: + if ( pItem ) + nInsCellsCtrlState = ((const SfxUInt16Item*)pItem)->GetValue(); + break; + case SID_TBXCTL_INSOBJ: + if ( pItem ) + nInsObjCtrlState = ((const SfxUInt16Item*)pItem)->GetValue(); + break; + default: + DBG_ERROR("Slot im Wald"); + } + GetViewFrame()->GetBindings().Invalidate( nSlot ); +} + +void ScTabViewShell::GetTbxState( SfxItemSet& rSet ) +{ + rSet.Put( SfxUInt16Item( SID_TBXCTL_INSERT, nInsertCtrlState ) ); + rSet.Put( SfxUInt16Item( SID_TBXCTL_INSCELLS, nInsCellsCtrlState ) ); + + // ohne installiertes Chart darf Chart nicht Default sein... + if ( nInsObjCtrlState == SID_DRAW_CHART && !SvtModuleOptions().IsChart() ) + nInsObjCtrlState = SID_INSERT_OBJECT; + + rSet.Put( SfxUInt16Item( SID_TBXCTL_INSOBJ, nInsObjCtrlState ) ); +} + + + + + diff --git a/sc/source/ui/view/tabvwsh5.cxx b/sc/source/ui/view/tabvwsh5.cxx new file mode 100644 index 000000000000..406e608cff9b --- /dev/null +++ b/sc/source/ui/view/tabvwsh5.cxx @@ -0,0 +1,429 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- +#define _ZFORLIST_DECLARE_TABLE +#include "scitems.hxx" +#include <svl/smplhint.hxx> +#include <svl/zforlist.hxx> +#include <svx/numfmtsh.hxx> +#include <svx/numinf.hxx> +#include <svx/svxids.hrc> +#include <sfx2/dispatch.hxx> +#include <sfx2/objsh.hxx> + +#include "tabvwsh.hxx" +#include "sc.hrc" +#include "global.hxx" +#include "docsh.hxx" +#include "document.hxx" +#include "cell.hxx" +#include "globstr.hrc" +#include "scmod.hxx" +#include "uiitems.hxx" +#include "editsh.hxx" +#include "hints.hxx" + + +//================================================================== + +void __EXPORT ScTabViewShell::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) +{ + if (rHint.ISA(SfxSimpleHint)) // ohne Parameter + { + sal_uLong nSlot = ((SfxSimpleHint&)rHint).GetId(); + switch ( nSlot ) + { + case FID_DATACHANGED: + UpdateFormulas(); + break; + + case FID_REFMODECHANGED: + { + sal_Bool bRefMode = SC_MOD()->IsFormulaMode(); + if (!bRefMode) + StopRefMode(); + else + { + GetSelEngine()->Reset(); + GetFunctionSet()->SetAnchorFlag(sal_True); + // AnchorFlag, damit gleich mit Control angehaengt werden kann + } + } + break; + + case FID_KILLEDITVIEW: + case FID_KILLEDITVIEW_NOPAINT: + StopEditShell(); + KillEditView( nSlot == FID_KILLEDITVIEW_NOPAINT ); + break; + + case SFX_HINT_DOCCHANGED: + { + ScDocument* pDoc = GetViewData()->GetDocument(); + if (!pDoc->HasTable( GetViewData()->GetTabNo() )) + { + SetTabNo(0); + } + } + break; + + case SC_HINT_DRWLAYER_NEW: + MakeDrawView(); + break; + + case SC_HINT_DOC_SAVED: + { + // beim "Save as" kann ein vorher schreibgeschuetztes Dokument + // bearbeitbar werden, deshalb die Layer-Locks neu (#39884#) + // (Invalidate etc. passiert schon vom Sfx her) + // #42091# bei SID_EDITDOC kommt kein SFX_HINT_TITLECHANGED, darum + // der eigene Hint aus DoSaveCompleted + //! was ist mit SFX_HINT_SAVECOMPLETED ? + + UpdateLayerLocks(); + + // #54891# Design-Modus bei jedem Speichern anzupassen, waere zuviel + // (beim Speichern unter gleichem Namen soll er unveraendert bleiben) + // Darum nur bei SFX_HINT_MODECHANGED (vom ViewFrame) + } + break; + + case SFX_HINT_MODECHANGED: + // #54891#/#58510# Da man sich nicht mehr darauf verlassen kann, woher + // dieser Hint kommt, den Design-Modus immer dann umschalten, wenn der + // ReadOnly-Status sich wirklich geaendert hat: + + if ( GetViewData()->GetSfxDocShell()->IsReadOnly() != bReadOnly ) + { + bReadOnly = GetViewData()->GetSfxDocShell()->IsReadOnly(); + + SfxBoolItem aItem( SID_FM_DESIGN_MODE, !bReadOnly); + GetViewData()->GetDispatcher().Execute( SID_FM_DESIGN_MODE, SFX_CALLMODE_ASYNCHRON, + &aItem, 0L ); + + UpdateInputContext(); + } + break; + + case SC_HINT_SHOWRANGEFINDER: + PaintRangeFinder(); + break; + + case SC_HINT_FORCESETTAB: + SetTabNo( GetViewData()->GetTabNo(), sal_True ); + break; + + default: + break; + } + } + else if (rHint.ISA(ScPaintHint)) // neu zeichnen + { + ScPaintHint* pHint = (ScPaintHint*) &rHint; + sal_uInt16 nParts = pHint->GetParts(); + SCTAB nTab = GetViewData()->GetTabNo(); + if (pHint->GetStartTab() <= nTab && pHint->GetEndTab() >= nTab) + { + if (nParts & PAINT_EXTRAS) // zuerst, falls Tabelle weg ist !!! + if (PaintExtras()) + nParts = PAINT_ALL; + + // if the current sheet has pending row height updates (sheet links refreshed), + // execute them before invalidating the window + GetViewData()->GetDocShell()->UpdatePendingRowHeights( GetViewData()->GetTabNo() ); + + if (nParts & PAINT_SIZE) + RepeatResize(); //! InvalidateBorder ??? + if (nParts & PAINT_GRID) + PaintArea( pHint->GetStartCol(), pHint->GetStartRow(), + pHint->GetEndCol(), pHint->GetEndRow() ); + if (nParts & PAINT_MARKS) + PaintArea( pHint->GetStartCol(), pHint->GetStartRow(), + pHint->GetEndCol(), pHint->GetEndRow(), SC_UPDATE_MARKS ); + if (nParts & PAINT_LEFT) + PaintLeftArea( pHint->GetStartRow(), pHint->GetEndRow() ); + if (nParts & PAINT_TOP) + PaintTopArea( pHint->GetStartCol(), pHint->GetEndCol() ); + if (nParts & PAINT_INVERT) + InvertBlockMark( pHint->GetStartCol(), pHint->GetStartRow(), + pHint->GetEndCol(), pHint->GetEndRow() ); + + // #i84689# call UpdateAllOverlays here instead of in ScTabView::PaintArea + if (nParts & ( PAINT_LEFT | PAINT_TOP )) // only if widths or heights changed + UpdateAllOverlays(); + + HideNoteMarker(); + } + } + else if (rHint.ISA(ScEditViewHint)) // Edit-View anlegen + { + // ScEditViewHint kommt nur an aktiver View an + + ScEditViewHint* pHint = (ScEditViewHint*) &rHint; + SCTAB nTab = GetViewData()->GetTabNo(); + if ( pHint->GetTab() == nTab ) + { + SCCOL nCol = pHint->GetCol(); + SCROW nRow = pHint->GetRow(); + { + HideNoteMarker(); + + MakeEditView( pHint->GetEngine(), nCol, nRow ); + + StopEditShell(); // sollte nicht gesetzt sein + + ScSplitPos eActive = GetViewData()->GetActivePart(); + if ( GetViewData()->HasEditView(eActive) ) + { + // MakeEditView geht schief, wenn der Cursor ausserhalb des + // Bildschirms steht. GetEditView gibt dann eine nicht aktive + // View zurueck, darum die Abfrage HasEditView. + + EditView* pView = GetViewData()->GetEditView(eActive); // ist nicht 0 + + SetEditShell(pView ,sal_True); + } + } + } + } + else if (rHint.ISA(ScTablesHint)) // Tabelle eingefuegt / geloescht + { + // aktuelle Tabelle zuerst holen (kann bei DeleteTab an ViewData geaendert werden) + SCTAB nActiveTab = GetViewData()->GetTabNo(); + + const ScTablesHint& rTabHint = (const ScTablesHint&)rHint; + SCTAB nTab1 = rTabHint.GetTab1(); + SCTAB nTab2 = rTabHint.GetTab2(); + sal_uInt16 nId = rTabHint.GetId(); + switch (nId) + { + case SC_TAB_INSERTED: + GetViewData()->InsertTab( nTab1 ); + break; + case SC_TAB_DELETED: + GetViewData()->DeleteTab( nTab1 ); + break; + case SC_TAB_MOVED: + GetViewData()->MoveTab( nTab1, nTab2 ); + break; + case SC_TAB_COPIED: + GetViewData()->CopyTab( nTab1, nTab2 ); + break; + case SC_TAB_HIDDEN: + break; + default: + DBG_ERROR("unbekannter ScTablesHint"); + } + + // hier keine Abfrage auf IsActive() mehr, weil die Aktion von Basic ausgehen + // kann und dann auch die aktive View umgeschaltet werden muss. + + SCTAB nNewTab = nActiveTab; + bool bStayOnActiveTab = true; + switch (nId) + { + case SC_TAB_INSERTED: + if ( nTab1 <= nNewTab ) // vorher eingefuegt + ++nNewTab; + break; + case SC_TAB_DELETED: + if ( nTab1 < nNewTab ) // vorher geloescht + --nNewTab; + else if ( nTab1 == nNewTab ) // aktuelle geloescht + bStayOnActiveTab = false; + break; + case SC_TAB_MOVED: + if ( nNewTab == nTab1 ) // verschobene Tabelle + nNewTab = nTab2; + else if ( nTab1 < nTab2 ) // nach hinten verschoben + { + if ( nNewTab > nTab1 && nNewTab <= nTab2 ) // nachrueckender Bereich + --nNewTab; + } + else // nach vorne verschoben + { + if ( nNewTab >= nTab2 && nNewTab < nTab1 ) // nachrueckender Bereich + ++nNewTab; + } + break; + case SC_TAB_COPIED: + if ( nNewTab >= nTab2 ) // vorher eingefuegt + ++nNewTab; + break; + case SC_TAB_HIDDEN: + if ( nTab1 == nNewTab ) // aktuelle ausgeblendet + bStayOnActiveTab = false; + break; + } + + ScDocument* pDoc = GetViewData()->GetDocument(); + if ( nNewTab >= pDoc->GetTableCount() ) + nNewTab = pDoc->GetTableCount() - 1; + + sal_Bool bForce = !bStayOnActiveTab; + SetTabNo( nNewTab, bForce, sal_False, bStayOnActiveTab ); + } + else if (rHint.ISA(ScIndexHint)) + { + const ScIndexHint& rIndexHint = (const ScIndexHint&)rHint; + sal_uInt16 nId = rIndexHint.GetId(); + sal_uInt16 nIndex = rIndexHint.GetIndex(); + switch (nId) + { + case SC_HINT_SHOWRANGEFINDER: + PaintRangeFinder( nIndex ); + break; + } + } + + SfxViewShell::Notify( rBC, rHint ); +} + +//------------------------------------------------------------------ + +void ScTabViewShell::MakeNumberInfoItem( ScDocument* pDoc, + ScViewData* pViewData, + SvxNumberInfoItem** ppItem ) +{ + //------------------------------ + // NumberInfo-Item konstruieren: + //------------------------------ + ScBaseCell* pCell = NULL; + SvxNumberValueType eValType = SVX_VALUE_TYPE_UNDEFINED; + double nCellValue = 0; + String aCellString; + + pDoc->GetCell( pViewData->GetCurX(), + pViewData->GetCurY(), + pViewData->GetTabNo(), + pCell ); + + if ( pCell ) + { + switch ( pCell->GetCellType() ) + { + case CELLTYPE_VALUE: + { + nCellValue = ((ScValueCell*)pCell)->GetValue(); + eValType = SVX_VALUE_TYPE_NUMBER; + aCellString.Erase(); + } + break; + + case CELLTYPE_STRING: + { + ((ScStringCell*)pCell)->GetString( aCellString ); + eValType = SVX_VALUE_TYPE_STRING; + } + break; + + case CELLTYPE_FORMULA: + { + if ( ((ScFormulaCell*)pCell)->IsValue() ) + { + nCellValue = ((ScFormulaCell*)pCell)->GetValue(); + eValType = SVX_VALUE_TYPE_NUMBER; + } + else + { + nCellValue = 0; + eValType = SVX_VALUE_TYPE_UNDEFINED; + } + aCellString.Erase(); + } + break; + + default: + nCellValue = 0; + eValType = SVX_VALUE_TYPE_UNDEFINED; + aCellString.Erase(); + } + } + else // Zelle noch leer (== nicht erzeugt) + { + nCellValue = 0; + eValType = SVX_VALUE_TYPE_UNDEFINED; + aCellString.Erase(); + } + + switch ( eValType ) + { + case SVX_VALUE_TYPE_STRING: + *ppItem = new SvxNumberInfoItem( + pDoc->GetFormatTable(), + aCellString, + SID_ATTR_NUMBERFORMAT_INFO ); + break; + + case SVX_VALUE_TYPE_NUMBER: + *ppItem = new SvxNumberInfoItem( + pDoc->GetFormatTable(), + nCellValue, + SID_ATTR_NUMBERFORMAT_INFO ); + break; + + case SVX_VALUE_TYPE_UNDEFINED: + default: + *ppItem = new SvxNumberInfoItem( + pDoc->GetFormatTable(), + (const sal_uInt16) + SID_ATTR_NUMBERFORMAT_INFO ); + } +} + +//------------------------------------------------------------------ + +void ScTabViewShell::UpdateNumberFormatter( + ScDocument* pDoc, + const SvxNumberInfoItem& rInfoItem ) +{ + const sal_uInt32 nDelCount = rInfoItem.GetDelCount(); + + if ( nDelCount > 0 ) + { + const sal_uInt32* pDelArr = rInfoItem.GetDelArray(); + + for ( sal_uInt16 i=0; i<nDelCount; i++ ) + rInfoItem.GetNumberFormatter()->DeleteEntry( pDelArr[i] ); + } + + // sollte besser UpdateNumberFormats() heissen ? + pDoc->DeleteNumberFormat( rInfoItem.GetDelArray(), + rInfoItem.GetDelCount() ); +} + + + + + + diff --git a/sc/source/ui/view/tabvwsh8.cxx b/sc/source/ui/view/tabvwsh8.cxx new file mode 100644 index 000000000000..298dbe787f0e --- /dev/null +++ b/sc/source/ui/view/tabvwsh8.cxx @@ -0,0 +1,104 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include "scitems.hxx" +#include <editeng/boxitem.hxx> + +#include "tabvwsh.hxx" +#include "document.hxx" + + +//------------------------------------------------------------------ + +void ScTabViewShell::SetDefaultFrameLine( const SvxBorderLine* pLine ) +{ + if ( pLine ) + { + delete pCurFrameLine; + pCurFrameLine = new SvxBorderLine( &pLine->GetColor(), + pLine->GetOutWidth(), + pLine->GetInWidth(), + pLine->GetDistance() ); + } + else if ( pCurFrameLine ) + { + delete pCurFrameLine; + pCurFrameLine = NULL; + } +} + +//------------------------------------------------------------------ + +sal_Bool __EXPORT ScTabViewShell::HasSelection( sal_Bool bText ) const +{ + sal_Bool bHas = sal_False; + ScViewData* pData = (ScViewData*)GetViewData(); // const weggecasted + if ( bText ) + { + // Text enthalten: Anzahl2 >= 1 + ScDocument* pDoc = pData->GetDocument(); + ScMarkData& rMark = pData->GetMarkData(); + ScAddress aCursor( pData->GetCurX(), pData->GetCurY(), pData->GetTabNo() ); + double fVal = 0.0; + if ( pDoc->GetSelectionFunction( SUBTOTAL_FUNC_CNT2, aCursor, rMark, fVal ) ) + bHas = ( fVal > 0.5 ); + } + else + { + ScRange aRange; + ScMarkType eMarkType = pData->GetSimpleArea( aRange ); + if ( eMarkType == SC_MARK_SIMPLE ) + bHas = ( aRange.aStart != aRange.aEnd ); // more than 1 cell + else + bHas = sal_True; // multiple selection or filtered + } + return bHas; +} + +//------------------------------------------------------------------ + +void ScTabViewShell::UIDeactivated( SfxInPlaceClient* pClient ) +{ + ClearHighlightRanges(); + + // Move an der ViewShell soll eigentlich vom Sfx gerufen werden, wenn sich + // das Frame-Window wegen unterschiedlicher Toolboxen o.ae. verschiebt + // (um nicht aus Versehen z.B. Zeichenobjekte zu verschieben, #56515#). + // Dieser Mechanismus funktioniert aber momentan nicht, darum hier der Aufruf + // per Hand (im Move wird verglichen, ob die Position wirklich geaendert ist). + ForceMove(); + SfxViewShell::UIDeactivated( pClient ); +} + + diff --git a/sc/source/ui/view/tabvwsh9.cxx b/sc/source/ui/view/tabvwsh9.cxx new file mode 100644 index 000000000000..8ba9174a6b7a --- /dev/null +++ b/sc/source/ui/view/tabvwsh9.cxx @@ -0,0 +1,295 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include <svx/svdmark.hxx> +#include <svx/svdview.hxx> +#include <svx/galbrws.hxx> +#include <svx/gallery.hxx> +#include <svx/hlnkitem.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/request.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/dispatch.hxx> +#include <svl/whiter.hxx> +#include <avmedia/mediaplayer.hxx> + +#include "tabvwsh.hxx" +#include "viewdata.hxx" +#include "tabview.hxx" +#include "drwlayer.hxx" +#include "userdat.hxx" +#include "docsh.hxx" + +// forwards -> galwrap.cxx (wg. CLOOKs) + +sal_uInt16 GallerySGA_FORMAT_GRAPHIC(); +Graphic GalleryGetGraphic (); +sal_Bool GalleryIsLinkage (); +String GalleryGetFullPath (); +String GalleryGetFilterName (); + +// forwards -> imapwrap.cxx (wg. CLOOKs) + +class SvxIMapDlg; + +sal_uInt16 ScIMapChildWindowId(); +SvxIMapDlg* ScGetIMapDlg(); +const void* ScIMapDlgGetObj( SvxIMapDlg* pDlg ); +const ImageMap& ScIMapDlgGetMap( SvxIMapDlg* pDlg ); + +//------------------------------------------------------------------ + +void ScTabViewShell::ExecChildWin(SfxRequest& rReq) +{ + sal_uInt16 nSlot = rReq.GetSlot(); + switch(nSlot) + { + case SID_GALLERY: + { + SfxViewFrame* pThisFrame = GetViewFrame(); + pThisFrame->ToggleChildWindow( GalleryChildWindow::GetChildWindowId() ); + pThisFrame->GetBindings().Invalidate( SID_GALLERY ); + rReq.Ignore(); + } + break; + + case SID_AVMEDIA_PLAYER: + { + SfxViewFrame* pThisFrame = GetViewFrame(); + pThisFrame->ToggleChildWindow( ::avmedia::MediaPlayer::GetChildWindowId() ); + pThisFrame->GetBindings().Invalidate( SID_AVMEDIA_PLAYER ); + rReq.Ignore(); + } + break; + } +} + +void ScTabViewShell::GetChildWinState( SfxItemSet& rSet ) +{ + if( SFX_ITEM_AVAILABLE == rSet.GetItemState( SID_GALLERY ) ) + { + sal_uInt16 nId = GalleryChildWindow::GetChildWindowId(); + rSet.Put( SfxBoolItem( SID_GALLERY, GetViewFrame()->HasChildWindow( nId ) ) ); + } + else if( SFX_ITEM_AVAILABLE == rSet.GetItemState( SID_AVMEDIA_PLAYER ) ) + { + sal_uInt16 nId = ::avmedia::MediaPlayer::GetChildWindowId(); + rSet.Put( SfxBoolItem( SID_AVMEDIA_PLAYER, GetViewFrame()->HasChildWindow( nId ) ) ); + } +} + +//------------------------------------------------------------------ + +void ScTabViewShell::ExecGallery( SfxRequest& rReq ) +{ + const SfxItemSet* pArgs = rReq.GetArgs(); + + if ( pArgs ) + { + const SfxPoolItem* pItem = NULL; + SfxItemState eState = pArgs->GetItemState(SID_GALLERY_FORMATS, sal_True, &pItem); + if ( eState == SFX_ITEM_SET ) + { + sal_uInt32 nFormats = ((const SfxUInt32Item*)pItem)->GetValue(); + + /****************************************************************** + * Graphik einfuegen + ******************************************************************/ + if ( nFormats & GallerySGA_FORMAT_GRAPHIC() ) + { + MakeDrawLayer(); + + Graphic aGraphic = GalleryGetGraphic(); + Point aPos = GetInsertPos(); + + String aPath, aFilter; + if ( GalleryIsLinkage() ) // als Link einfuegen? + { + aPath = GalleryGetFullPath(); + aFilter = GalleryGetFilterName(); + } + + PasteGraphic( aPos, aGraphic, aPath, aFilter ); + } + else if ( nFormats & SGA_FORMAT_SOUND ) + { + // #98115# for sounds (linked or not), insert a hyperlink button, + // like in Impress and Writer + + GalleryExplorer* pGal = SVX_GALLERY(); + if ( pGal ) + { + const SfxStringItem aMediaURLItem( SID_INSERT_AVMEDIA, pGal->GetURL().GetMainURL( INetURLObject::NO_DECODE ) ); + GetViewFrame()->GetDispatcher()->Execute( SID_INSERT_AVMEDIA, SFX_CALLMODE_SYNCHRON, &aMediaURLItem, 0L ); + } + } + } + } +} + +void ScTabViewShell::GetGalleryState( SfxItemSet& /* rSet */ ) +{ +} + +//------------------------------------------------------------------ + +ScInputHandler* ScTabViewShell::GetInputHandler() const +{ + return pInputHandler; +} + +//------------------------------------------------------------------ + +String __EXPORT ScTabViewShell::GetDescription() const +{ + return String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(" ** Test ** ")); +} + +void ScTabViewShell::ExecImageMap( SfxRequest& rReq ) +{ + sal_uInt16 nSlot = rReq.GetSlot(); + switch(nSlot) + { + case SID_IMAP: + { + SfxViewFrame* pThisFrame = GetViewFrame(); + sal_uInt16 nId = ScIMapChildWindowId(); + pThisFrame->ToggleChildWindow( nId ); + GetViewFrame()->GetBindings().Invalidate( SID_IMAP ); + + if ( pThisFrame->HasChildWindow( nId ) ) + { + SvxIMapDlg* pDlg = ScGetIMapDlg(); + if ( pDlg ) + { + SdrView* pDrView = GetSdrView(); + if ( pDrView ) + { + const SdrMarkList& rMarkList = pDrView->GetMarkedObjectList(); + if ( rMarkList.GetMarkCount() == 1 ) + UpdateIMap( rMarkList.GetMark( 0 )->GetMarkedSdrObj() ); + } + } + } + + rReq.Ignore(); + } + break; + + case SID_IMAP_EXEC: + { + SdrView* pDrView = GetSdrView(); + SdrMark* pMark = pDrView ? pDrView->GetMarkedObjectList().GetMark(0) : 0; + + if ( pMark ) + { + SdrObject* pSdrObj = pMark->GetMarkedSdrObj(); + SvxIMapDlg* pDlg = ScGetIMapDlg(); + + if ( ScIMapDlgGetObj(pDlg) == (void*) pSdrObj ) + { + const ImageMap& rImageMap = ScIMapDlgGetMap(pDlg); + ScIMapInfo* pIMapInfo = ScDrawLayer::GetIMapInfo( pSdrObj ); + + if ( !pIMapInfo ) + pSdrObj->InsertUserData( new ScIMapInfo( rImageMap ) ); + else + pIMapInfo->SetImageMap( rImageMap ); + + GetViewData()->GetDocShell()->SetDrawModified(); + } + } + } + break; + } +} + +void ScTabViewShell::GetImageMapState( SfxItemSet& rSet ) +{ + SfxWhichIter aIter(rSet); + sal_uInt16 nWhich = aIter.FirstWhich(); + while ( nWhich ) + { + switch ( nWhich ) + { + case SID_IMAP: + { + // Disabled wird nicht mehr... + + sal_Bool bThere = sal_False; + SfxViewFrame* pThisFrame = GetViewFrame(); + sal_uInt16 nId = ScIMapChildWindowId(); + if ( pThisFrame->KnowsChildWindow(nId) ) + if ( pThisFrame->HasChildWindow(nId) ) + bThere = sal_True; + + ObjectSelectionType eType=GetCurObjectSelectionType(); + sal_Bool bEnable=(eType==OST_OleObject) ||(eType==OST_Graphic); + if(!bThere && !bEnable) + { + rSet.DisableItem( nWhich ); + } + else + { + rSet.Put( SfxBoolItem( nWhich, bThere ) ); + } + } + break; + + case SID_IMAP_EXEC: + { + sal_Bool bDisable = sal_True; + + SdrView* pDrView = GetSdrView(); + if ( pDrView ) + { + const SdrMarkList& rMarkList = pDrView->GetMarkedObjectList(); + if ( rMarkList.GetMarkCount() == 1 ) + if ( ScIMapDlgGetObj(ScGetIMapDlg()) == + (void*) rMarkList.GetMark(0)->GetMarkedSdrObj() ) + bDisable = sal_False; + } + + rSet.Put( SfxBoolItem( SID_IMAP_EXEC, bDisable ) ); + } + break; + } + + nWhich = aIter.NextWhich(); + } +} + + + + diff --git a/sc/source/ui/view/tabvwsha.cxx b/sc/source/ui/view/tabvwsha.cxx new file mode 100644 index 000000000000..f8199100fc6d --- /dev/null +++ b/sc/source/ui/view/tabvwsha.cxx @@ -0,0 +1,803 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#define _ZFORLIST_DECLARE_TABLE +#include "scitems.hxx" +#include <svl/stritem.hxx> +#include <svl/whiter.hxx> +#include <svl/zformat.hxx> +#include <editeng/boxitem.hxx> +#include <svx/numinf.hxx> +#include <svl/srchitem.hxx> +#include <svx/zoomslideritem.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/request.hxx> +#include <vcl/msgbox.hxx> + +#include "global.hxx" +#include "attrib.hxx" +#include "patattr.hxx" +#include "document.hxx" +#include "cell.hxx" // Input Status Edit-Zellen +#include "globstr.hrc" +#include "scmod.hxx" +#include "inputhdl.hxx" +#include "inputwin.hxx" +#include "docsh.hxx" +#include "viewdata.hxx" +//CHINA001 #include "attrdlg.hxx" +#include "appoptio.hxx" +#include "sc.hrc" +#include "stlpool.hxx" +#include "tabvwsh.hxx" +#include "dwfunctr.hxx" +#include "scabstdlg.hxx" //CHINA001 +#include "compiler.hxx" + + +sal_Bool ScTabViewShell::GetFunction( String& rFuncStr, sal_uInt16 nErrCode ) +{ + String aStr; + + ScSubTotalFunc eFunc = (ScSubTotalFunc) SC_MOD()->GetAppOptions().GetStatusFunc(); + ScViewData* pViewData = GetViewData(); + ScMarkData& rMark = pViewData->GetMarkData(); + bool bIgnoreError = (rMark.IsMarked() || rMark.IsMultiMarked()); + + if (bIgnoreError && (eFunc == SUBTOTAL_FUNC_CNT || eFunc == SUBTOTAL_FUNC_CNT2)) + nErrCode = 0; + + if (nErrCode) + { + rFuncStr = ScGlobal::GetLongErrorString(nErrCode); + return true; + } + + sal_uInt16 nGlobStrId = 0; + switch (eFunc) + { + case SUBTOTAL_FUNC_AVE: nGlobStrId = STR_FUN_TEXT_AVG; break; + case SUBTOTAL_FUNC_CNT: nGlobStrId = STR_FUN_TEXT_COUNT; break; + case SUBTOTAL_FUNC_CNT2: nGlobStrId = STR_FUN_TEXT_COUNT2; break; + case SUBTOTAL_FUNC_MAX: nGlobStrId = STR_FUN_TEXT_MAX; break; + case SUBTOTAL_FUNC_MIN: nGlobStrId = STR_FUN_TEXT_MIN; break; + case SUBTOTAL_FUNC_SUM: nGlobStrId = STR_FUN_TEXT_SUM; break; + default: + { + // added to avoid warnings + } + } + if (nGlobStrId) + { + ScDocument* pDoc = pViewData->GetDocument(); + SCCOL nPosX = pViewData->GetCurX(); + SCROW nPosY = pViewData->GetCurY(); + SCTAB nTab = pViewData->GetTabNo(); + + aStr = ScGlobal::GetRscString(nGlobStrId); + aStr += '='; + + ScAddress aCursor( nPosX, nPosY, nTab ); + double nVal; + if ( pDoc->GetSelectionFunction( eFunc, aCursor, rMark, nVal ) ) + { + if ( nVal == 0.0 ) + aStr += '0'; + else + { + // Anzahl im Standardformat, die anderen nach Cursorposition + SvNumberFormatter* pFormatter = pDoc->GetFormatTable(); + sal_uInt32 nNumFmt = 0; + if ( eFunc != SUBTOTAL_FUNC_CNT && eFunc != SUBTOTAL_FUNC_CNT2 ) + { + // Zahlformat aus Attributen oder Formel + pDoc->GetNumberFormat( nPosX, nPosY, nTab, nNumFmt ); + if ( (nNumFmt % SV_COUNTRY_LANGUAGE_OFFSET) == 0 ) + { + ScBaseCell* pCell; + pDoc->GetCell( nPosX, nPosY, nTab, pCell ); + if (pCell && pCell->GetCellType() == CELLTYPE_FORMULA) + { + + nNumFmt = ((ScFormulaCell*)pCell)->GetStandardFormat(*pFormatter, nNumFmt ); + } + } + } + + String aValStr; + Color* pDummy; + pFormatter->GetOutputString( nVal, nNumFmt, aValStr, &pDummy ); + aStr += aValStr; + } + } + + rFuncStr = aStr; + return sal_True; + } + + return sal_False; +} + + + +// Funktionen, die je nach Selektion disabled sind +// Default: +// SID_DELETE, +// SID_DELETE_CONTENTS, +// FID_DELETE_CELL +// FID_VALIDATION + + +void __EXPORT ScTabViewShell::GetState( SfxItemSet& rSet ) +{ + ScViewData* pViewData = GetViewData(); + ScDocument* pDoc = pViewData->GetDocument(); + ScDocShell* pDocShell = pViewData->GetDocShell(); + ScMarkData& rMark = pViewData->GetMarkData(); + SCCOL nPosX = pViewData->GetCurX(); + SCROW nPosY = pViewData->GetCurY(); + SCTAB nTab = pViewData->GetTabNo(); + sal_uInt16 nMyId = 0; + + SfxViewFrame* pThisFrame = GetViewFrame(); + sal_Bool bOle = GetViewFrame()->GetFrame().IsInPlace(); + + SCTAB nTabCount = pDoc->GetTableCount(); + SCTAB nTabSelCount = rMark.GetSelectCount(); + + SfxWhichIter aIter(rSet); + sal_uInt16 nWhich = aIter.FirstWhich(); + + while ( nWhich ) + { + switch ( nWhich ) + { + case FID_CHG_COMMENT: + { + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScAddress aPos( nPosX, nPosY, nTab ); + if ( pDocSh->IsReadOnly() || !pDocSh->GetChangeAction(aPos) || pDocSh->IsDocShared() ) + rSet.DisableItem( nWhich ); + } + break; + + case SID_OPENDLG_EDIT_PRINTAREA: + case SID_ADD_PRINTAREA: + case SID_DEFINE_PRINTAREA: + { + if ( pDocShell && pDocShell->IsDocShared() ) + { + rSet.DisableItem( nWhich ); + } + } + break; + + case SID_DELETE_PRINTAREA: + if ( nTabSelCount > 1 ) + { + // #i22589# also take "Print Entire Sheet" into account here + sal_Bool bHas = sal_False; + for (SCTAB i=0; !bHas && i<nTabCount; i++) + bHas = rMark.GetTableSelect(i) && (pDoc->GetPrintRangeCount(i) || pDoc->IsPrintEntireSheet(i)); + if (!bHas) + rSet.DisableItem( nWhich ); + } + else if ( !pDoc->GetPrintRangeCount( nTab ) && !pDoc->IsPrintEntireSheet( nTab ) ) + rSet.DisableItem( nWhich ); + if ( pDocShell && pDocShell->IsDocShared() ) + { + rSet.DisableItem( nWhich ); + } + break; + + case SID_STATUS_PAGESTYLE: + case SID_HFEDIT: + GetViewData()->GetDocShell()->GetStatePageStyle( *this, rSet, nTab ); + break; + + case SID_SEARCH_ITEM: + rSet.Put( ScGlobal::GetSearchItem() ); + break; + + case SID_SEARCH_OPTIONS: + { + sal_uInt16 nOptions = 0xffff; // alles erlaubt + // wenn ReadOnly, kein Ersetzen: + if (GetViewData()->GetDocShell()->IsReadOnly()) + nOptions &= ~( SEARCH_OPTIONS_REPLACE | SEARCH_OPTIONS_REPLACE_ALL ); + rSet.Put( SfxUInt16Item( nWhich, nOptions ) ); + } + break; + + case SID_CURRENTCELL: + { + ScAddress aScAddress( GetViewData()->GetCurX(), GetViewData()->GetCurY(), 0 ); + String aAddr; + aScAddress.Format( aAddr, SCA_ABS, NULL, pDoc->GetAddressConvention() ); + SfxStringItem aPosItem( SID_CURRENTCELL, aAddr ); + + rSet.Put( aPosItem ); + } + break; + + case SID_CURRENTTAB: + // Tabelle fuer Basic ist 1-basiert + rSet.Put( SfxUInt16Item( nWhich, static_cast<sal_uInt16>(GetViewData()->GetTabNo()) + 1 ) ); + break; + + case SID_CURRENTDOC: + rSet.Put( SfxStringItem( nWhich, GetViewData()->GetDocShell()->GetTitle() ) ); + break; + + case FID_TOGGLEINPUTLINE: + { + sal_uInt16 nId = ScInputWindowWrapper::GetChildWindowId(); + + if ( pThisFrame->KnowsChildWindow( nId ) ) + { + SfxChildWindow* pWnd = pThisFrame->GetChildWindow( nId ); + rSet.Put( SfxBoolItem( nWhich, pWnd ? sal_True : sal_False ) ); + } + else + rSet.DisableItem( nWhich ); + } + break; + + case FID_DEL_MANUALBREAKS: + if (!pDoc->HasManualBreaks(nTab)) + rSet.DisableItem( nWhich ); + break; + + case FID_RESET_PRINTZOOM: + { + // disablen, wenn schon Default eingestellt + + String aStyleName = pDoc->GetPageStyle( nTab ); + ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool(); + SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName, + SFX_STYLE_FAMILY_PAGE ); + DBG_ASSERT( pStyleSheet, "PageStyle not found" ); + if ( pStyleSheet ) + { + SfxItemSet& rStyleSet = pStyleSheet->GetItemSet(); + sal_uInt16 nScale = ((const SfxUInt16Item&) + rStyleSet.Get(ATTR_PAGE_SCALE)).GetValue(); + sal_uInt16 nPages = ((const SfxUInt16Item&) + rStyleSet.Get(ATTR_PAGE_SCALETOPAGES)).GetValue(); + if ( nScale == 100 && nPages == 0 ) + rSet.DisableItem( nWhich ); + } + } + break; + + case FID_SCALE: + case SID_ATTR_ZOOM: + if ( bOle ) + rSet.DisableItem( nWhich ); + else + { + const Fraction& rOldY = GetViewData()->GetZoomY(); + sal_uInt16 nZoom = (sal_uInt16)(( rOldY.GetNumerator() * 100 ) + / rOldY.GetDenominator()); + rSet.Put( SvxZoomItem( SVX_ZOOM_PERCENT, nZoom, nWhich ) ); + } + break; + + case SID_ATTR_ZOOMSLIDER: + { + if ( bOle ) + rSet.DisableItem( nWhich ); + else + { + const Fraction& rOldY = GetViewData()->GetZoomY(); + sal_uInt16 nCurrentZoom = (sal_uInt16)(( rOldY.GetNumerator() * 100 ) / rOldY.GetDenominator()); + + if( nCurrentZoom ) + { + SvxZoomSliderItem aZoomSliderItem( nCurrentZoom, MINZOOM, MAXZOOM, SID_ATTR_ZOOMSLIDER ); + aZoomSliderItem.AddSnappingPoint( 100 ); + rSet.Put( aZoomSliderItem ); + } + } + } + break; + + case FID_TOGGLESYNTAX: + rSet.Put(SfxBoolItem(nWhich, GetViewData()->IsSyntaxMode())); + break; + + case FID_TOGGLEHEADERS: + rSet.Put(SfxBoolItem(nWhich, GetViewData()->IsHeaderMode())); + break; + + case FID_TOGGLEFORMULA: + { + const ScViewOptions& rOpts = pViewData->GetOptions(); + sal_Bool bFormulaMode = rOpts.GetOption( VOPT_FORMULAS ); + rSet.Put(SfxBoolItem(nWhich, bFormulaMode )); + } + break; + + case FID_NORMALVIEWMODE: + case FID_PAGEBREAKMODE: + // always handle both slots - they exclude each other + if ( bOle ) + { + rSet.DisableItem( FID_NORMALVIEWMODE ); + rSet.DisableItem( FID_PAGEBREAKMODE ); + } + else + { + rSet.Put(SfxBoolItem(FID_NORMALVIEWMODE, !GetViewData()->IsPagebreakMode())); + rSet.Put(SfxBoolItem(FID_PAGEBREAKMODE, GetViewData()->IsPagebreakMode())); + } + break; + + case FID_FUNCTION_BOX: + nMyId = ScFunctionChildWindow::GetChildWindowId(); + rSet.Put(SfxBoolItem(FID_FUNCTION_BOX, pThisFrame->HasChildWindow(nMyId))); + break; + + case FID_PROTECT_DOC: + { + if ( pDocShell && pDocShell->IsDocShared() ) + { + rSet.DisableItem( nWhich ); + } + else + { + rSet.Put( SfxBoolItem( nWhich, pDoc->IsDocProtected() ) ); + } + } + break; + + case FID_PROTECT_TABLE: + { + if ( pDocShell && pDocShell->IsDocShared() ) + { + rSet.DisableItem( nWhich ); + } + else + { + rSet.Put( SfxBoolItem( nWhich, pDoc->IsTabProtected( nTab ) ) ); + } + } + break; + + case SID_AUTO_OUTLINE: + { + if (pDoc->GetChangeTrack()!=NULL || GetViewData()->IsMultiMarked()) + { + rSet.DisableItem( nWhich ); + } + } + break; + + case SID_OUTLINE_DELETEALL: + { + SCTAB nOlTab = GetViewData()->GetTabNo(); + ScOutlineTable* pOlTable = pDoc->GetOutlineTable( nOlTab ); + if (pOlTable == NULL) + rSet.DisableItem( nWhich ); + } + break; + + case SID_WINDOW_SPLIT: + rSet.Put(SfxBoolItem(nWhich, + pViewData->GetHSplitMode() == SC_SPLIT_NORMAL || + pViewData->GetVSplitMode() == SC_SPLIT_NORMAL )); + break; + + case SID_WINDOW_FIX: + rSet.Put(SfxBoolItem(nWhich, + pViewData->GetHSplitMode() == SC_SPLIT_FIX || + pViewData->GetVSplitMode() == SC_SPLIT_FIX )); + break; + + case FID_CHG_SHOW: + { + if ( pDoc->GetChangeTrack() == NULL || ( pDocShell && pDocShell->IsDocShared() ) ) + rSet.DisableItem( nWhich ); + } + break; + case FID_CHG_ACCEPT: + { + rSet.Put(SfxBoolItem(FID_CHG_ACCEPT, + pThisFrame->HasChildWindow(FID_CHG_ACCEPT))); + if(pDoc->GetChangeTrack()==NULL) + { + if ( !pThisFrame->HasChildWindow(FID_CHG_ACCEPT) ) + { + rSet.DisableItem( nWhich); + } + } + if ( pDocShell && pDocShell->IsDocShared() ) + { + rSet.DisableItem( nWhich ); + } + } + break; + + case SID_FORMATPAGE: + //! bei geschuetzten Tabellen ??? + if ( pDocShell && ( pDocShell->IsReadOnly() || pDocShell->IsDocShared() ) ) + rSet.DisableItem( nWhich ); + break; + + case SID_PRINTPREVIEW: + // #58924# Toggle-Slot braucht einen State + rSet.Put( SfxBoolItem( nWhich, sal_False ) ); + break; + + case SID_READONLY_MODE: + rSet.Put( SfxBoolItem( nWhich, GetViewData()->GetDocShell()->IsReadOnly() ) ); + break; + + case FID_TAB_DESELECTALL: + if ( nTabSelCount == 1 ) + rSet.DisableItem( nWhich ); // enabled only if several sheets are selected + break; + + } // switch ( nWitch ) + nWhich = aIter.NextWhich(); + } // while ( nWitch ) +} + +//------------------------------------------------------------------ +void ScTabViewShell::ExecuteCellFormatDlg( SfxRequest& rReq, sal_uInt16 nTabPage ) +{ + //CHINA001 ScAttrDlg* pDlg = NULL; + SfxAbstractTabDialog * pDlg = NULL; //CHINA001 + ScDocument* pDoc = GetViewData()->GetDocument(); + + SvxBoxItem aLineOuter( ATTR_BORDER ); + SvxBoxInfoItem aLineInner( ATTR_BORDER_INNER ); + + SvxNumberInfoItem* pNumberInfoItem = NULL; + const ScPatternAttr* pOldAttrs = GetSelectionPattern(); + SfxItemSet* pOldSet = new SfxItemSet( + pOldAttrs->GetItemSet() ); + + + // Umrandungs-Items holen und in den Set packen: + GetSelectionFrame( aLineOuter, aLineInner ); + pOldSet->Put( aLineOuter ); + pOldSet->Put( aLineInner ); + + // NumberFormat Value aus Value und Language erzeugen und eintueten + pOldSet->Put( SfxUInt32Item( ATTR_VALUE_FORMAT, + pOldAttrs->GetNumberFormat( pDoc->GetFormatTable() ) ) ); + + MakeNumberInfoItem( pDoc, GetViewData(), &pNumberInfoItem ); + + pOldSet->MergeRange( SID_ATTR_NUMBERFORMAT_INFO, SID_ATTR_NUMBERFORMAT_INFO ); + pOldSet->Put(*pNumberInfoItem ); + + bInFormatDialog = sal_True; + //CHINA001 pDlg = new ScAttrDlg( GetViewFrame(), GetDialogParent(), pOldSet ); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + pDlg = pFact->CreateScAttrDlg( GetViewFrame(), GetDialogParent(), pOldSet, RID_SCDLG_ATTR); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + if ( nTabPage != 0xffff ) + pDlg->SetCurPageId( nTabPage ); + short nResult = pDlg->Execute(); + bInFormatDialog = sal_False; + + if ( nResult == RET_OK ) + { + const SfxItemSet* pOutSet = pDlg->GetOutputItemSet(); + + const SfxPoolItem* pItem=NULL; + if(pOutSet->GetItemState(SID_ATTR_NUMBERFORMAT_INFO,sal_True,&pItem)==SFX_ITEM_SET) + { + + UpdateNumberFormatter( pDoc,(const SvxNumberInfoItem&)*pItem); + } + + ApplyAttributes( pOutSet, pOldSet ); + + rReq.Done( *pOutSet ); + } + delete pOldSet; + delete pNumberInfoItem; + delete pDlg; +} + +//------------------------------------------------------------------ + +bool ScTabViewShell::IsRefInputMode() const +{ + ScModule* pScMod = SC_MOD(); + if ( pScMod ) + { + if( pScMod->IsRefDialogOpen() ) + return pScMod->IsFormulaMode(); + if( pScMod->IsFormulaMode() ) + { + ScInputHandler* pHdl = pScMod->GetInputHdl(); + if ( pHdl ) + { + String aString = pHdl->GetEditString(); + if ( !pHdl->GetSelIsRef() && aString.Len() > 1 && + ( aString.GetChar(0) == '+' || aString.GetChar(0) == '-' ) ) + { + const ScViewData* pViewData = GetViewData(); + if ( pViewData ) + { + ScDocument* pDoc = pViewData->GetDocument(); + if ( pDoc ) + { + const ScAddress aPos( pViewData->GetCurPos() ); + ScCompiler aComp( pDoc, aPos ); + aComp.SetGrammar(pDoc->GetGrammar()); + aComp.SetCloseBrackets( false ); + ScTokenArray* pArr = aComp.CompileString( aString ); + if ( pArr && pArr->MayReferenceFollow() ) + { + return true; + } + } + } + } + else + { + return true; + } + } + } + } + + return false; +} + +//------------------------------------------------------------------ + +void ScTabViewShell::ExecuteInputDirect() +{ + if ( !IsRefInputMode() ) + { + ScModule* pScMod = SC_MOD(); + if ( pScMod ) + { + pScMod->InputEnterHandler(); + } + } +} + +//------------------------------------------------------------------ + +void ScTabViewShell::UpdateInputHandler( sal_Bool bForce /* = sal_False */, sal_Bool bStopEditing /* = sal_True */ ) +{ + ScInputHandler* pHdl = pInputHandler ? pInputHandler : SC_MOD()->GetInputHdl(); + + if ( pHdl ) + { + String aString; + const EditTextObject* pObject = NULL; + ScViewData* pViewData = GetViewData(); + ScDocument* pDoc = pViewData->GetDocument(); + CellType eType; + SCCOL nPosX = pViewData->GetCurX(); + SCROW nPosY = pViewData->GetCurY(); + SCTAB nTab = pViewData->GetTabNo(); + SCTAB nStartTab = 0; + SCTAB nEndTab = 0; + SCCOL nStartCol = 0; + SCROW nStartRow = 0; + SCCOL nEndCol = 0; + SCROW nEndRow = 0; + + pViewData->GetSimpleArea( nStartCol, nStartRow, nStartTab, + nEndCol, nEndRow, nEndTab ); + + PutInOrder( nStartCol, nEndCol ); + PutInOrder( nStartRow, nEndRow ); + PutInOrder( nStartTab, nEndTab ); + + sal_Bool bHideFormula = sal_False; + sal_Bool bHideAll = sal_False; + + if (pDoc->IsTabProtected(nTab)) + { + const ScProtectionAttr* pProt = (const ScProtectionAttr*) + pDoc->GetAttr( nPosX,nPosY,nTab, + ATTR_PROTECTION); + bHideFormula = pProt->GetHideFormula(); + bHideAll = pProt->GetHideCell(); + } + + if (!bHideAll) + { + pDoc->GetCellType( nPosX, nPosY, nTab, eType ); + if (eType == CELLTYPE_FORMULA) + { + if (!bHideFormula) + pDoc->GetFormula( nPosX, nPosY, nTab, aString ); + } + else if (eType == CELLTYPE_EDIT) + { + ScBaseCell* pCell; + pDoc->GetCell( nPosX, nPosY, nTab, pCell ); + ((ScEditCell*)pCell)->GetData( pObject ); + } + else + { + pDoc->GetInputString( nPosX, nPosY, nTab, aString ); + if (eType == CELLTYPE_STRING) + { + // Bei Bedarf ein ' vorneweg, damit der String nicht ungewollt + // als Zahl interpretiert wird, und um dem Benutzer zu zeigen, + // dass es ein String ist (#35060#). + //! Auch bei Zahlformat "Text"? -> dann beim Editieren wegnehmen + + SvNumberFormatter* pFormatter = pDoc->GetFormatTable(); + sal_uInt32 nNumFmt; + pDoc->GetNumberFormat( nPosX, nPosY, nTab, nNumFmt ); + double fDummy; + if ( pFormatter->IsNumberFormat(aString, nNumFmt, fDummy) ) + aString.Insert('\'',0); + } + } + } + + ScInputHdlState aState( ScAddress( nPosX, nPosY, nTab ), + ScAddress( nStartCol, nStartRow, nTab ), + ScAddress( nEndCol, nEndRow, nTab ), + aString, + pObject ); + + // if using the view's local input handler, this view can always be set + // as current view inside NotifyChange. + ScTabViewShell* pSourceSh = pInputHandler ? this : NULL; + + pHdl->NotifyChange( &aState, bForce, pSourceSh, bStopEditing ); + } + + SfxBindings& rBindings = GetViewFrame()->GetBindings(); + rBindings.Invalidate( SID_STATUS_SUM ); // immer zusammen mit Eingabezeile + rBindings.Invalidate( SID_ATTR_SIZE ); + rBindings.Invalidate( SID_TABLE_CELL ); +} + +void ScTabViewShell::UpdateInputHandlerCellAdjust( SvxCellHorJustify eJust ) +{ + if( ScInputHandler* pHdl = pInputHandler ? pInputHandler : SC_MOD()->GetInputHdl() ) + pHdl->UpdateCellAdjust( eJust ); +} + +//------------------------------------------------------------------ + +void __EXPORT ScTabViewShell::ExecuteSave( SfxRequest& rReq ) +{ + // nur SID_SAVEDOC / SID_SAVEASDOC + + // Eingabe auf jeden Fall abschliessen, auch wenn eine Formel bearbeitet wird + SC_MOD()->InputEnterHandler(); + + if ( GetViewData()->GetDocShell()->IsDocShared() ) + { + GetViewData()->GetDocShell()->SetDocumentModified(); + } + + // ansonsten normal weiter + GetViewData()->GetDocShell()->ExecuteSlot( rReq ); +} + +void __EXPORT ScTabViewShell::GetSaveState( SfxItemSet& rSet ) +{ + SfxShell* pDocSh = GetViewData()->GetDocShell(); + + SfxWhichIter aIter(rSet); + sal_uInt16 nWhich = aIter.FirstWhich(); + while( nWhich ) + { + if ( nWhich != SID_SAVEDOC || !GetViewData()->GetDocShell()->IsDocShared() ) + { + // get state from DocShell + pDocSh->GetSlotState( nWhich, NULL, &rSet ); + } + nWhich = aIter.NextWhich(); + } +} + +//------------------------------------------------------------------ + +void ScTabViewShell::ExecDrawOpt( SfxRequest& rReq ) +{ + ScViewOptions aViewOptions = GetViewData()->GetOptions(); + ScGridOptions aGridOptions = aViewOptions.GetGridOptions(); + + SfxBindings& rBindings = GetViewFrame()->GetBindings(); + const SfxItemSet* pArgs = rReq.GetArgs(); + const SfxPoolItem* pItem; + sal_uInt16 nSlotId = rReq.GetSlot(); + switch (nSlotId) + { + case SID_GRID_VISIBLE: + if ( pArgs && pArgs->GetItemState(nSlotId,sal_True,&pItem) == SFX_ITEM_SET ) + { + aGridOptions.SetGridVisible( ((const SfxBoolItem*)pItem)->GetValue() ); + aViewOptions.SetGridOptions(aGridOptions); + rBindings.Invalidate(SID_GRID_VISIBLE); + } + break; + + case SID_GRID_USE: + if ( pArgs && pArgs->GetItemState(nSlotId,sal_True,&pItem) == SFX_ITEM_SET ) + { + aGridOptions.SetUseGridSnap( ((const SfxBoolItem*)pItem)->GetValue() ); + aViewOptions.SetGridOptions(aGridOptions); + rBindings.Invalidate(SID_GRID_USE); + } + break; + + case SID_HELPLINES_MOVE: + if ( pArgs && pArgs->GetItemState(nSlotId,sal_True,&pItem) == SFX_ITEM_SET ) + { + aViewOptions.SetOption( VOPT_HELPLINES, ((const SfxBoolItem*)pItem)->GetValue() ); + rBindings.Invalidate(SID_HELPLINES_MOVE); + } + break; + } + + GetViewData()->SetOptions(aViewOptions); +} + +void ScTabViewShell::GetDrawOptState( SfxItemSet& rSet ) +{ + SfxBoolItem aBool; + + const ScViewOptions& rViewOptions = GetViewData()->GetOptions(); + const ScGridOptions& rGridOptions = rViewOptions.GetGridOptions(); + + aBool.SetValue(rGridOptions.GetGridVisible()); + aBool.SetWhich( SID_GRID_VISIBLE ); + rSet.Put( aBool ); + + aBool.SetValue(rGridOptions.GetUseGridSnap()); + aBool.SetWhich( SID_GRID_USE ); + rSet.Put( aBool ); + + aBool.SetValue(rViewOptions.GetOption( VOPT_HELPLINES )); + aBool.SetWhich( SID_HELPLINES_MOVE ); + rSet.Put( aBool ); +} + + + + diff --git a/sc/source/ui/view/tabvwshb.cxx b/sc/source/ui/view/tabvwshb.cxx new file mode 100644 index 000000000000..2001ba165531 --- /dev/null +++ b/sc/source/ui/view/tabvwshb.cxx @@ -0,0 +1,586 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" +#include <com/sun/star/embed/NoVisualAreaSizeException.hpp> +#include <com/sun/star/chart2/data/XDataReceiver.hpp> + + + +//------------------------------------------------------------------ + +#ifdef _MSC_VER +#pragma optimize ("", off) +#endif + +// INCLUDE --------------------------------------------------------------- + +#include <com/sun/star/embed/EmbedMisc.hpp> +#include <com/sun/star/embed/EmbedStates.hpp> +#include <sfx2/app.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <svx/svxdlg.hxx> +#include <svx/dataaccessdescriptor.hxx> +#include <svx/pfiledlg.hxx> +#include <svx/svditer.hxx> +#include <svx/svdmark.hxx> +#include <svx/svdograf.hxx> +#include <svx/svdogrp.hxx> +#include <svx/svdoole2.hxx> +#include <svx/svdouno.hxx> +#include <svx/svdview.hxx> +#include <sfx2/linkmgr.hxx> +#include <svx/fontworkbar.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/viewfrm.hxx> +#include <svtools/soerr.hxx> +#include <svl/rectitem.hxx> +#include <svl/slstitm.hxx> +#include <svl/whiter.hxx> +#include <unotools/moduleoptions.hxx> +#include <sot/exchange.hxx> +#include <tools/diagnose_ex.h> + +#include "tabvwsh.hxx" +#include "globstr.hrc" +#include "scmod.hxx" +#include "document.hxx" +#include "sc.hrc" +#include "client.hxx" +#include "fuinsert.hxx" +#include "docsh.hxx" +#include "chartarr.hxx" +#include "drawview.hxx" +#include "ChartRangeSelectionListener.hxx" + +using namespace com::sun::star; + +// STATIC DATA ----------------------------------------------------------- + +void ScTabViewShell::ConnectObject( SdrOle2Obj* pObj ) +{ + // wird aus dem Paint gerufen + + uno::Reference < embed::XEmbeddedObject > xObj = pObj->GetObjRef(); + Window* pWin = GetActiveWin(); + + // #41412# wenn schon connected ist, nicht nochmal SetObjArea/SetSizeScale + + SfxInPlaceClient* pClient = FindIPClient( xObj, pWin ); + if ( !pClient ) + { + pClient = new ScClient( this, pWin, GetSdrView()->GetModel(), pObj ); + Rectangle aRect = pObj->GetLogicRect(); + Size aDrawSize = aRect.GetSize(); + + Size aOleSize = pObj->GetOrigObjSize(); + + Fraction aScaleWidth (aDrawSize.Width(), aOleSize.Width() ); + Fraction aScaleHeight(aDrawSize.Height(), aOleSize.Height() ); + aScaleWidth.ReduceInaccurate(10); // kompatibel zum SdrOle2Obj + aScaleHeight.ReduceInaccurate(10); + pClient->SetSizeScale(aScaleWidth,aScaleHeight); + + // sichtbarer Ausschnitt wird nur inplace veraendert! + // the object area must be set after the scaling since it triggers the resizing + aRect.SetSize( aOleSize ); + pClient->SetObjArea( aRect ); + + ((ScClient*)pClient)->SetGrafEdit( NULL ); + } +} + +sal_Bool ScTabViewShell::ActivateObject( SdrOle2Obj* pObj, long nVerb ) +{ + // #41081# Gueltigkeits-Hinweisfenster nicht ueber dem Objekt stehenlassen + RemoveHintWindow(); + + uno::Reference < embed::XEmbeddedObject > xObj = pObj->GetObjRef(); + Window* pWin = GetActiveWin(); + ErrCode nErr = ERRCODE_NONE; + sal_Bool bErrorShown = sal_False; + + // linked objects aren't supported +// if ( xIPObj->IsLink() ) +// nErr = xIPObj->DoVerb(nVerb); // gelinkt -> ohne Client etc. +// else + { + SfxInPlaceClient* pClient = FindIPClient( xObj, pWin ); + if ( !pClient ) + pClient = new ScClient( this, pWin, GetSdrView()->GetModel(), pObj ); + + if ( !(nErr & ERRCODE_ERROR_MASK) && xObj.is() ) + { + Rectangle aRect = pObj->GetLogicRect(); + Size aDrawSize = aRect.GetSize(); + + MapMode aMapMode( MAP_100TH_MM ); + Size aOleSize = pObj->GetOrigObjSize( &aMapMode ); + + if ( pClient->GetAspect() != embed::Aspects::MSOLE_ICON + && ( xObj->getStatus( pClient->GetAspect() ) & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE ) ) + { + // scale must always be 1 - change VisArea if different from client size + + if ( aDrawSize != aOleSize ) + { + MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( pClient->GetAspect() ) ); + aOleSize = OutputDevice::LogicToLogic( aDrawSize, + MAP_100TH_MM, aUnit ); + awt::Size aSz( aOleSize.Width(), aOleSize.Height() ); + xObj->setVisualAreaSize( pClient->GetAspect(), aSz ); + } + Fraction aOne( 1, 1 ); + pClient->SetSizeScale( aOne, aOne ); + } + else + { + // calculate scale from client and VisArea size + + Fraction aScaleWidth (aDrawSize.Width(), aOleSize.Width() ); + Fraction aScaleHeight(aDrawSize.Height(), aOleSize.Height() ); + aScaleWidth.ReduceInaccurate(10); // kompatibel zum SdrOle2Obj + aScaleHeight.ReduceInaccurate(10); + pClient->SetSizeScale(aScaleWidth,aScaleHeight); + } + + // sichtbarer Ausschnitt wird nur inplace veraendert! + // the object area must be set after the scaling since it triggers the resizing + aRect.SetSize( aOleSize ); + pClient->SetObjArea( aRect ); + + ((ScClient*)pClient)->SetGrafEdit( NULL ); + + nErr = pClient->DoVerb( nVerb ); + bErrorShown = sal_True; + // SfxViewShell::DoVerb zeigt seine Fehlermeldungen selber an + + // attach listener to selection changes in chart that affect cell + // ranges, so those can be highlighted + // note: do that after DoVerb, so that the chart controller exists + if ( SvtModuleOptions().IsChart() ) + { + SvGlobalName aObjClsId ( xObj->getClassID() ); + if (SotExchange::IsChart( aObjClsId )) + { + try + { + uno::Reference < embed::XComponentSupplier > xSup( xObj, uno::UNO_QUERY_THROW ); + uno::Reference< chart2::data::XDataReceiver > xDataReceiver( + xSup->getComponent(), uno::UNO_QUERY_THROW ); + uno::Reference< chart2::data::XRangeHighlighter > xRangeHightlighter( + xDataReceiver->getRangeHighlighter()); + if( xRangeHightlighter.is()) + { + uno::Reference< view::XSelectionChangeListener > xListener( + new ScChartRangeSelectionListener( this )); + xRangeHightlighter->addSelectionChangeListener( xListener ); + } + } + catch( const uno::Exception & ) + { + DBG_ERROR( "Exception caught while querying chart" ); + } + } + } + } + } + if (nErr != ERRCODE_NONE && !bErrorShown) + ErrorHandler::HandleError(nErr); + + //! SetDocumentName sollte schon im Sfx passieren ??? + //TODO/LATER: how "SetDocumentName"? + //xIPObj->SetDocumentName( GetViewData()->GetDocShell()->GetTitle() ); + + return ( !(nErr & ERRCODE_ERROR_MASK) ); +} + +ErrCode __EXPORT ScTabViewShell::DoVerb(long nVerb) +{ + SdrView* pView = GetSdrView(); + if (!pView) + return ERRCODE_SO_NOTIMPL; // soll nicht sein + + SdrOle2Obj* pOle2Obj = NULL; + SdrGrafObj* pGrafObj = NULL; + SdrObject* pObj = NULL; + ErrCode nErr = ERRCODE_NONE; + + const SdrMarkList& rMarkList = pView->GetMarkedObjectList(); + if (rMarkList.GetMarkCount() == 1) + { + pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + if (pObj->GetObjIdentifier() == OBJ_OLE2) + pOle2Obj = (SdrOle2Obj*) pObj; + else if (pObj->GetObjIdentifier() == OBJ_GRAF) + { + pGrafObj = (SdrGrafObj*) pObj; + } + } + + if (pOle2Obj) + { + ActivateObject( pOle2Obj, nVerb ); + } + else + { + DBG_ERROR("kein Objekt fuer Verb gefunden"); + } + + return nErr; +} + +void ScTabViewShell::DeactivateOle() +{ + // deactivate inplace editing if currently active + + ScModule* pScMod = SC_MOD(); + bool bUnoRefDialog = pScMod->IsRefDialogOpen() && pScMod->GetCurRefDlgId() == WID_SIMPLE_REF; + + ScClient* pClient = (ScClient*) GetIPClient(); + if ( pClient && pClient->IsObjectInPlaceActive() && !bUnoRefDialog ) + pClient->DeactivateObject(); +} + +void ScTabViewShell::ExecDrawIns(SfxRequest& rReq) +{ + sal_uInt16 nSlot = rReq.GetSlot(); + if (nSlot != SID_OBJECTRESIZE ) + { + SC_MOD()->InputEnterHandler(); + UpdateInputHandler(); + } + + // Rahmen fuer Chart einfuegen wird abgebrochen: + FuPoor* pPoor = GetDrawFuncPtr(); + if ( pPoor && pPoor->GetSlotID() == SID_DRAW_CHART ) + GetViewData()->GetDispatcher().Execute(SID_DRAW_CHART, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD); + + MakeDrawLayer(); + + SfxBindings& rBindings = GetViewFrame()->GetBindings(); + ScTabView* pTabView = GetViewData()->GetView(); + Window* pWin = pTabView->GetActiveWin(); + ScDrawView* pView = pTabView->GetScDrawView(); + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); +// SdrModel* pDrModel = pDocSh->MakeDrawLayer(); + SdrModel* pDrModel = pView->GetModel(); + + switch ( nSlot ) + { + case SID_INSERT_GRAPHIC: + FuInsertGraphic(this, pWin, pView, pDrModel, rReq); + // shell is set in MarkListHasChanged + break; + + case SID_INSERT_AVMEDIA: + FuInsertMedia(this, pWin, pView, pDrModel, rReq); + // shell is set in MarkListHasChanged + break; + + case SID_INSERT_DIAGRAM: + FuInsertChart(this, pWin, pView, pDrModel, rReq); +//? SC_MOD()->SetFunctionDlg( NULL );//XXX + break; + + case SID_INSERT_OBJECT: + case SID_INSERT_PLUGIN: + case SID_INSERT_SOUND: + case SID_INSERT_VIDEO: + case SID_INSERT_SMATH: + case SID_INSERT_FLOATINGFRAME: + FuInsertOLE(this, pWin, pView, pDrModel, rReq); + break; + + case SID_OBJECTRESIZE: + { + // Der Server moechte die Clientgrosse verandern + + SfxInPlaceClient* pClient = GetIPClient(); + + if ( pClient && pClient->IsObjectInPlaceActive() ) + { + const SfxRectangleItem& rRect = + (SfxRectangleItem&)rReq.GetArgs()->Get(SID_OBJECTRESIZE); + Rectangle aRect( pWin->PixelToLogic( rRect.GetValue() ) ); + + if ( pView->AreObjectsMarked() ) + { + const SdrMarkList& rMarkList = pView->GetMarkedObjectList(); + + if (rMarkList.GetMarkCount() == 1) + { + SdrMark* pMark = rMarkList.GetMark(0); + SdrObject* pObj = pMark->GetMarkedSdrObj(); + + sal_uInt16 nSdrObjKind = pObj->GetObjIdentifier(); + + if (nSdrObjKind == OBJ_OLE2) + { + if ( ( (SdrOle2Obj*) pObj)->GetObjRef().is() ) + { + pObj->SetLogicRect(aRect); + } + } + } + } + } + } + break; + + case SID_LINKS: + { + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + SfxAbstractLinksDialog* pDlg = pFact->CreateLinksDialog( pWin, pDoc->GetLinkManager() ); + if ( pDlg ) + { + pDlg->Execute(); + rBindings.Invalidate( nSlot ); + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); // Navigator + rReq.Done(); + } + } + break; + + // #98721# + case SID_FM_CREATE_FIELDCONTROL: + { + SFX_REQUEST_ARG( rReq, pDescriptorItem, SfxUnoAnyItem, SID_FM_DATACCESS_DESCRIPTOR, sal_False ); + DBG_ASSERT( pDescriptorItem, "SID_FM_CREATE_FIELDCONTROL: invalid request args!" ); + + if(pDescriptorItem) + { + //! merge with ScViewFunc::PasteDataFormat (SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE)? + + ScDrawView* pDrView = GetScDrawView(); + SdrPageView* pPageView = pDrView ? pDrView->GetSdrPageView() : NULL; + if(pPageView) + { + ::svx::ODataAccessDescriptor aDescriptor(pDescriptorItem->GetValue()); + SdrObject* pNewDBField = pDrView->CreateFieldControl(aDescriptor); + + if(pNewDBField) + { + Rectangle aVisArea = pWin->PixelToLogic(Rectangle(Point(0,0), pWin->GetOutputSizePixel())); + Point aObjPos(aVisArea.Center()); + Size aObjSize(pNewDBField->GetLogicRect().GetSize()); + aObjPos.X() -= aObjSize.Width() / 2; + aObjPos.Y() -= aObjSize.Height() / 2; + Rectangle aNewObjectRectangle(aObjPos, aObjSize); + + pNewDBField->SetLogicRect(aNewObjectRectangle); + + // controls must be on control layer, groups on front layer + if ( pNewDBField->ISA(SdrUnoObj) ) + pNewDBField->NbcSetLayer(SC_LAYER_CONTROLS); + else + pNewDBField->NbcSetLayer(SC_LAYER_FRONT); + if (pNewDBField->ISA(SdrObjGroup)) + { + SdrObjListIter aIter( *pNewDBField, IM_DEEPWITHGROUPS ); + SdrObject* pSubObj = aIter.Next(); + while (pSubObj) + { + if ( pSubObj->ISA(SdrUnoObj) ) + pSubObj->NbcSetLayer(SC_LAYER_CONTROLS); + else + pSubObj->NbcSetLayer(SC_LAYER_FRONT); + pSubObj = aIter.Next(); + } + } + + pView->InsertObjectAtView(pNewDBField, *pPageView); + } + } + } + rReq.Done(); + } + break; + + case SID_FONTWORK_GALLERY_FLOATER: + svx::FontworkBar::execute( pView, rReq, GetViewFrame()->GetBindings() ); + rReq.Ignore(); + break; + } +} + +void ScTabViewShell::GetDrawInsState(SfxItemSet &rSet) +{ + sal_Bool bOle = GetViewFrame()->GetFrame().IsInPlace(); + sal_Bool bTabProt = GetViewData()->GetDocument()->IsTabProtected(GetViewData()->GetTabNo()); + ScDocShell* pDocShell = ( GetViewData() ? GetViewData()->GetDocShell() : NULL ); + bool bShared = ( pDocShell ? pDocShell->IsDocShared() : false ); + + SfxWhichIter aIter(rSet); + sal_uInt16 nWhich = aIter.FirstWhich(); + while ( nWhich ) + { + switch ( nWhich ) + { + case SID_INSERT_DIAGRAM: + if ( bOle || bTabProt || !SvtModuleOptions().IsChart() || bShared ) + rSet.DisableItem( nWhich ); + break; + + case SID_INSERT_SMATH: + if ( bOle || bTabProt || !SvtModuleOptions().IsMath() || bShared ) + rSet.DisableItem( nWhich ); + break; + + case SID_INSERT_OBJECT: + case SID_INSERT_PLUGIN: + case SID_INSERT_FLOATINGFRAME: + if ( bOle || bTabProt || bShared ) + rSet.DisableItem( nWhich ); + break; + + case SID_INSERT_SOUND: + case SID_INSERT_VIDEO: + /* #i102735# discussed with NN: removed for performance reasons + || !SvxPluginFileDlg::IsAvailable(nWhich) + */ + if ( bOle || bTabProt || bShared ) + rSet.DisableItem( nWhich ); + break; + + case SID_INSERT_GRAPHIC: + case SID_INSERT_AVMEDIA: + case SID_FONTWORK_GALLERY_FLOATER: + if ( bTabProt || bShared ) + rSet.DisableItem( nWhich ); + break; + + case SID_LINKS: + { + if (GetViewData()->GetDocument()->GetLinkManager()->GetLinks().Count() == 0 ) + rSet.DisableItem( SID_LINKS ); + } + break; + } + nWhich = aIter.NextWhich(); + } +} + + +//------------------------------------------------------------------ + +void ScTabViewShell::ExecuteUndo(SfxRequest& rReq) +{ + SfxShell* pSh = GetViewData()->GetDispatcher().GetShell(0); + ::svl::IUndoManager* pUndoManager = pSh->GetUndoManager(); + + const SfxItemSet* pReqArgs = rReq.GetArgs(); + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + + sal_uInt16 nSlot = rReq.GetSlot(); + switch ( nSlot ) + { + case SID_UNDO: + case SID_REDO: + if ( pUndoManager ) + { + sal_Bool bIsUndo = ( nSlot == SID_UNDO ); + + sal_uInt16 nCount = 1; + const SfxPoolItem* pItem; + if ( pReqArgs && pReqArgs->GetItemState( nSlot, sal_True, &pItem ) == SFX_ITEM_SET ) + nCount = ((const SfxUInt16Item*)pItem)->GetValue(); + + // lock paint for more than one cell undo action (not for editing within a cell) + sal_Bool bLockPaint = ( nCount > 1 && pUndoManager == GetUndoManager() ); + if ( bLockPaint ) + pDocSh->LockPaint(); + + try + { + for (sal_uInt16 i=0; i<nCount; i++) + { + if ( bIsUndo ) + pUndoManager->Undo(); + else + pUndoManager->Redo(); + } + } + catch ( const uno::Exception& ) + { + // no need to handle. By definition, the UndoManager handled this by clearing the + // Undo/Redo stacks + } + + if ( bLockPaint ) + pDocSh->UnlockPaint(); + + GetViewFrame()->GetBindings().InvalidateAll(sal_False); + } + break; +// default: +// GetViewFrame()->ExecuteSlot( rReq ); + } +} + +void ScTabViewShell::GetUndoState(SfxItemSet &rSet) +{ + SfxShell* pSh = GetViewData()->GetDispatcher().GetShell(0); + ::svl::IUndoManager* pUndoManager = pSh->GetUndoManager(); + + SfxWhichIter aIter(rSet); + sal_uInt16 nWhich = aIter.FirstWhich(); + while ( nWhich ) + { + switch (nWhich) + { + case SID_GETUNDOSTRINGS: + case SID_GETREDOSTRINGS: + { + SfxStringListItem aStrLst( nWhich ); + if ( pUndoManager ) + { + List* pList = aStrLst.GetList(); + sal_Bool bIsUndo = ( nWhich == SID_GETUNDOSTRINGS ); + size_t nCount = bIsUndo ? pUndoManager->GetUndoActionCount() : pUndoManager->GetRedoActionCount(); + for (size_t i=0; i<nCount; i++) + pList->Insert( new String( bIsUndo ? pUndoManager->GetUndoActionComment(i) : + pUndoManager->GetRedoActionComment(i) ), + LIST_APPEND ); + } + rSet.Put( aStrLst ); + } + break; + default: + // get state from sfx view frame + GetViewFrame()->GetSlotState( nWhich, NULL, &rSet ); + } + + nWhich = aIter.NextWhich(); + } +} + + + diff --git a/sc/source/ui/view/tabvwshc.cxx b/sc/source/ui/view/tabvwshc.cxx new file mode 100644 index 000000000000..2e829d83e07d --- /dev/null +++ b/sc/source/ui/view/tabvwshc.cxx @@ -0,0 +1,327 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +//------------------------------------------------------------------ + +// INCLUDE --------------------------------------------------------------- +#include "scitems.hxx" +#include <vcl/msgbox.hxx> +#include <sfx2/childwin.hxx> +#include <sfx2/dispatch.hxx> + +#include "tabvwsh.hxx" +#include "sc.hrc" +#include "globstr.hrc" +#include "global.hxx" +#include "scmod.hxx" +#include "docsh.hxx" +#include "document.hxx" +#include "uiitems.hxx" +#include "pivot.hxx" +#include "namedlg.hxx" +#include "solvrdlg.hxx" +#include "optsolver.hxx" +#include "tabopdlg.hxx" +#include "autoform.hxx" // Core +#include "autofmt.hxx" // Dialog +#include "consdlg.hxx" +//CHINA001 #include "sortdlg.hxx" +#include "filtdlg.hxx" +#include "dbnamdlg.hxx" +#include "pvlaydlg.hxx" +#include "areasdlg.hxx" +#include "condfrmt.hxx" +#include "rangeutl.hxx" +#include "crnrdlg.hxx" +#include "formula.hxx" +#include "cell.hxx" // Input Status Edit-Zellen +#include "acredlin.hxx" +#include "highred.hxx" +#include "simpref.hxx" +#include "funcdesc.hxx" +#include "dpobject.hxx" + +//------------------------------------------------------------------ + +void ScTabViewShell::SetCurRefDlgId( sal_uInt16 nNew ) +{ + // CurRefDlgId is stored in ScModule to find if a ref dialog is open, + // and in the view to identify the view that has opened the dialog + nCurRefDlgId = nNew; +} + +SfxModelessDialog* ScTabViewShell::CreateRefDialog( + SfxBindings* pB, SfxChildWindow* pCW, SfxChildWinInfo* pInfo, + Window* pParent, sal_uInt16 nSlotId ) +{ + // Dialog nur aufmachen, wenn ueber ScModule::SetRefDialog gerufen, damit + // z.B. nach einem Absturz offene Ref-Dialoge nicht wiederkommen (#42341#). + + if ( SC_MOD()->GetCurRefDlgId() != nSlotId ) + return NULL; + + if ( nCurRefDlgId != nSlotId ) + { + // the dialog has been opened in a different view + // -> lock the dispatcher for this view (modal mode) + + GetViewData()->GetDispatcher().Lock( sal_True ); // lock is reset when closing dialog + return NULL; + } + + SfxModelessDialog* pResult = 0; + + if(pCW) + pCW->SetHideNotDelete(sal_True); + + switch( nSlotId ) + { + case FID_DEFINE_NAME: + pResult = new ScNameDlg( pB, pCW, pParent, GetViewData(), + ScAddress( GetViewData()->GetCurX(), + GetViewData()->GetCurY(), + GetViewData()->GetTabNo() ) ); + break; + + case SID_DEFINE_COLROWNAMERANGES: + { + pResult = new ScColRowNameRangesDlg( pB, pCW, pParent, GetViewData() ); + } + break; + + case SID_OPENDLG_CONSOLIDATE: + { + SfxItemSet aArgSet( GetPool(), + SCITEM_CONSOLIDATEDATA, + SCITEM_CONSOLIDATEDATA ); + + const ScConsolidateParam* pDlgData = + GetViewData()->GetDocument()->GetConsolidateDlgData(); + + if ( !pDlgData ) + { + ScConsolidateParam aConsParam; + SCCOL nStartCol, nEndCol; + SCROW nStartRow, nEndRow; + SCTAB nStartTab, nEndTab; + + GetViewData()->GetSimpleArea( nStartCol, nStartRow, nStartTab, + nEndCol, nEndRow, nEndTab ); + + PutInOrder( nStartCol, nEndCol ); + PutInOrder( nStartRow, nEndRow ); + PutInOrder( nStartTab, nEndTab ); + + aConsParam.nCol = nStartCol; + aConsParam.nRow = nStartRow; + aConsParam.nTab = nStartTab; + + aArgSet.Put( ScConsolidateItem( SCITEM_CONSOLIDATEDATA, + &aConsParam ) ); + } + else + { + aArgSet.Put( ScConsolidateItem( SCITEM_CONSOLIDATEDATA, pDlgData ) ); + } + pResult = new ScConsolidateDlg( pB, pCW, pParent, aArgSet ); + } + break; + + case SID_DEFINE_DBNAME: + { + // wenn auf einem bestehenden Bereich aufgerufen, den markieren + GetDBData( sal_True, SC_DB_OLD ); + const ScMarkData& rMark = GetViewData()->GetMarkData(); + if ( !rMark.IsMarked() && !rMark.IsMultiMarked() ) + MarkDataArea( sal_False ); + + pResult = new ScDbNameDlg( pB, pCW, pParent, GetViewData() ); + } + break; + + case SID_SPECIAL_FILTER: + { + ScQueryParam aQueryParam; + SfxItemSet aArgSet( GetPool(), + SCITEM_QUERYDATA, + SCITEM_QUERYDATA ); + + ScDBData* pDBData = GetDBData( sal_True, SC_DB_MAKE, SC_DBSEL_ROW_DOWN); + pDBData->GetQueryParam( aQueryParam ); + + ScQueryItem aItem( SCITEM_QUERYDATA, GetViewData(), &aQueryParam ); + ScRange aAdvSource; + if (pDBData->GetAdvancedQuerySource(aAdvSource)) + aItem.SetAdvancedQuerySource( &aAdvSource ); + + aArgSet.Put( aItem ); + + // aktuelle Tabelle merken (wg. RefInput im Dialog) + GetViewData()->SetRefTabNo( GetViewData()->GetTabNo() ); + + pResult = new ScSpecialFilterDlg( pB, pCW, pParent, aArgSet ); + } + break; + + case SID_FILTER: + { + + ScQueryParam aQueryParam; + SfxItemSet aArgSet( GetPool(), + SCITEM_QUERYDATA, + SCITEM_QUERYDATA ); + + ScDBData* pDBData = GetDBData( sal_True, SC_DB_MAKE, SC_DBSEL_ROW_DOWN); + pDBData->GetQueryParam( aQueryParam ); + + aArgSet.Put( ScQueryItem( SCITEM_QUERYDATA, + GetViewData(), + &aQueryParam ) ); + + // aktuelle Tabelle merken (wg. RefInput im Dialog) + GetViewData()->SetRefTabNo( GetViewData()->GetTabNo() ); + + pResult = new ScFilterDlg( pB, pCW, pParent, aArgSet ); + } + break; + + case SID_OPENDLG_TABOP: + { + ScViewData* pViewData = GetViewData(); + ScRefAddress aCurPos ( pViewData->GetCurX(), + pViewData->GetCurY(), + pViewData->GetTabNo(), + sal_False, sal_False, sal_False ); + + pResult = new ScTabOpDlg( pB, pCW, pParent, pViewData->GetDocument(), aCurPos ); + } + break; + + case SID_OPENDLG_SOLVE: + { + ScViewData* pViewData = GetViewData(); + ScAddress aCurPos( pViewData->GetCurX(), + pViewData->GetCurY(), + pViewData->GetTabNo()); + pResult = new ScSolverDlg( pB, pCW, pParent, pViewData->GetDocument(), aCurPos ); + } + break; + + case SID_OPENDLG_OPTSOLVER: + { + ScViewData* pViewData = GetViewData(); + ScAddress aCurPos( pViewData->GetCurX(), pViewData->GetCurY(), pViewData->GetTabNo()); + pResult = new ScOptSolverDlg( pB, pCW, pParent, pViewData->GetDocShell(), aCurPos ); + } + break; + + case SID_OPENDLG_PIVOTTABLE: + { + // all settings must be in pDialogDPObject + + if( pDialogDPObject ) + { + GetViewData()->SetRefTabNo( GetViewData()->GetTabNo() ); + pResult = new ScDPLayoutDlg( pB, pCW, pParent, *pDialogDPObject ); + } + } + break; + + case SID_OPENDLG_EDIT_PRINTAREA: + { + pResult = new ScPrintAreasDlg( pB, pCW, pParent ); + } + break; + + case SID_OPENDLG_CONDFRMT: + { + ScViewData* pViewData = GetViewData(); + + ScDocument* pDoc = pViewData->GetDocument(); + const ScConditionalFormat* pForm = pDoc->GetCondFormat( + pViewData->GetCurX(), pViewData->GetCurY(), pViewData->GetTabNo() ); + + // aktuelle Tabelle merken (wg. RefInput im Dialog) + pViewData->SetRefTabNo( pViewData->GetTabNo() ); + + pResult = new ScConditionalFormatDlg( pB, pCW, pParent, pDoc, pForm ); + } + break; + + case SID_OPENDLG_FUNCTION: + { + // Dialog schaut selber, was in der Zelle steht + + pResult = new ScFormulaDlg( pB, pCW, pParent, GetViewData(),ScGlobal::GetStarCalcFunctionMgr() ); + } + break; + + case FID_CHG_SHOW: + { + // Dialog schaut selber, was in der Zelle steht + + pResult = new ScHighlightChgDlg( pB, pCW, pParent, GetViewData() ); + } + break; + + case WID_SIMPLE_REF: + { + // Dialog schaut selber, was in der Zelle steht + + ScViewData* pViewData = GetViewData(); + pViewData->SetRefTabNo( pViewData->GetTabNo() ); + pResult = new ScSimpleRefDlg( pB, pCW, pParent, pViewData ); + } + break; + + + default: + DBG_ERROR( "ScTabViewShell::CreateRefDialog: unbekannte ID" ); + break; + } + + if (pResult) + { + // Die Dialoge gehen immer mit eingeklapptem Zusaetze-Button auf, + // darum muss die Groesse ueber das Initialize gerettet werden + // (oder den Zusaetze-Status mit speichern !!!) + + Size aSize = pResult->GetSizePixel(); + pResult->Initialize( pInfo ); + pResult->SetSizePixel(aSize); + } + + return pResult; +} + + + diff --git a/sc/source/ui/view/tabvwshd.cxx b/sc/source/ui/view/tabvwshd.cxx new file mode 100644 index 000000000000..d0eeee22fbf7 --- /dev/null +++ b/sc/source/ui/view/tabvwshd.cxx @@ -0,0 +1,100 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +//------------------------------------------------------------------ + +#ifdef _MSC_VER +#pragma optimize ("", off) +#endif + +// INCLUDE --------------------------------------------------------------- + +#include <sfx2/childwin.hxx> +#include <sfx2/request.hxx> +#include <sfx2/viewfrm.hxx> +#include <vcl/svapp.hxx> +#include <vcl/wrkwin.hxx> + +#include "tabvwsh.hxx" +#include "global.hxx" +#include "scmod.hxx" +#include "docsh.hxx" +#include "sc.hrc" + + +// STATIC DATA ----------------------------------------------------------- + +//------------------------------------------------------------------ + +#define IS_AVAILABLE(WhichId,ppItem) \ + (pReqArgs->GetItemState((WhichId), sal_True, ppItem ) == SFX_ITEM_SET) + +//! Parent-Window fuer Dialoge +//! Problem: OLE Server! + +Window* ScTabViewShell::GetDialogParent() +{ + // #95513# if a ref-input dialog is open, use it as parent + // (necessary when a slot is executed from the dialog's OK handler) + if ( nCurRefDlgId && nCurRefDlgId == SC_MOD()->GetCurRefDlgId() ) + { + SfxViewFrame* pViewFrm = GetViewFrame(); + if ( pViewFrm->HasChildWindow(nCurRefDlgId) ) + { + SfxChildWindow* pChild = pViewFrm->GetChildWindow(nCurRefDlgId); + if (pChild) + { + Window* pWin = pChild->GetWindow(); + if (pWin && pWin->IsVisible()) + return pWin; + } + } + } + + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + if ( pDocSh->IsOle() ) + { + //TODO/LATER: how to GetEditWindow in embedded document?! + //It should be OK to return the VieShell Window! + return GetWindow(); + //SvInPlaceEnvironment* pEnv = pDocSh->GetIPEnv(); + //if (pEnv) + // return pEnv->GetEditWin(); + } + + return GetActiveWin(); // for normal views, too +} + + + + + diff --git a/sc/source/ui/view/tabvwshe.cxx b/sc/source/ui/view/tabvwshe.cxx new file mode 100644 index 000000000000..0784d3143202 --- /dev/null +++ b/sc/source/ui/view/tabvwshe.cxx @@ -0,0 +1,343 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- +#include <editeng/eeitem.hxx> + +#include "scitems.hxx" +#include <editeng/editview.hxx> +#include <editeng/flditem.hxx> +#include <svx/hlnkitem.hxx> +#include <svl/srchitem.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/request.hxx> +#include <sfx2/objface.hxx> +#include <svl/stritem.hxx> +#include <vcl/sound.hxx> + +#include "tabvwsh.hxx" +#include "sc.hrc" +#include "scmod.hxx" +#include "impex.hxx" +#include "editsh.hxx" +#include "dociter.hxx" +#include "inputhdl.hxx" +#include "document.hxx" + +//================================================================== + +String __EXPORT ScTabViewShell::GetSelectionText( sal_Bool bWholeWord ) +{ + String aStrSelection; + + if ( pEditShell && pEditShell == GetMySubShell() ) + { + aStrSelection = pEditShell->GetSelectionText( bWholeWord ); + } + else + { + ScRange aRange; + + if ( GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE ) + { + ScDocument* pDoc = GetViewData()->GetDocument(); + if ( bInFormatDialog && aRange.aStart.Row() != aRange.aEnd.Row() ) + { + // Range auf eine Datenzeile begrenzen + // (#48613# nur wenn der Aufruf aus einem Format-Dialog kommt) + ScHorizontalCellIterator aIter( pDoc, aRange.aStart.Tab(), + aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Col(), aRange.aEnd.Row() ); + SCCOL nCol; + SCROW nRow; + if ( aIter.GetNext( nCol, nRow ) ) + { + aRange.aStart.SetCol( nCol ); + aRange.aStart.SetRow( nRow ); + aRange.aEnd.SetRow( nRow ); + } + else + aRange.aEnd = aRange.aStart; + } + else + { + // #i111531# with 1M rows it was necessary to limit the range + // to the actually used data area. + SCCOL nCol1, nCol2; + SCROW nRow1, nRow2; + SCTAB nTab1, nTab2; + aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2); + bool bShrunk; + pDoc->ShrinkToUsedDataArea( bShrunk, nTab1, nCol1, nRow1, nCol2, nRow2, false); + if (bShrunk) + { + aRange.aStart.SetCol( nCol1 ); + aRange.aStart.SetRow( nRow1 ); + aRange.aEnd.SetCol( nCol2 ); + aRange.aEnd.SetRow( nRow2 ); + } + } + + ScImportExport aObj( pDoc, aRange ); + aObj.SetFormulas( GetViewData()->GetOptions().GetOption( VOPT_FORMULAS ) ); + rtl::OUString aExportOUString; + aObj.ExportString( aExportOUString ); + aStrSelection = aExportOUString; + + aStrSelection.ConvertLineEnd( LINEEND_CR ); + + // Tab/CR durch Space ersetzen, wenn fuer Dialog oder per Basic/SelectionTextExt, + // oder wenn es eine einzelne Zeile ist. + // Sonst mehrzeilig mit Tabs beibehalten (z.B. Mail oder Basic/SelectionText). + // Fuer Mail werden die Tabs dann spaeter in (mehrere) Spaces gewandelt. + + if ( bInFormatDialog || bWholeWord || aRange.aEnd.Row() == aRange.aStart.Row() ) + { + xub_StrLen nAt; + while ( (nAt = aStrSelection.Search( CHAR_CR )) != STRING_NOTFOUND ) + aStrSelection.SetChar( nAt, ' ' ); + while ( (nAt = aStrSelection.Search( '\t' )) != STRING_NOTFOUND ) + aStrSelection.SetChar( nAt, ' ' ); + + aStrSelection.EraseTrailingChars( ' ' ); + } + } + } + + return aStrSelection; +} + +//------------------------------------------------------------------------ + +void ScTabViewShell::InsertURL( const String& rName, const String& rURL, const String& rTarget, + sal_uInt16 nMode ) +{ + SvxLinkInsertMode eMode = (SvxLinkInsertMode) nMode; + sal_Bool bAsText = ( eMode != HLINK_BUTTON ); // Default ist jetzt Text + + if ( bAsText ) + { + if ( GetViewData()->IsActive() ) + { + // if the view is active, always use InsertURLField, which starts EditMode + // and selects the URL, so it can be changed from the URL bar / dialog + + InsertURLField( rName, rURL, rTarget ); + } + else + { + // #91216# if the view is not active, InsertURLField doesn't work + // -> use InsertBookmark to directly manipulate cell content + // bTryReplace=sal_True -> if cell contains only one URL, replace it + + SCCOL nPosX = GetViewData()->GetCurX(); + SCROW nPosY = GetViewData()->GetCurY(); + InsertBookmark( rName, rURL, nPosX, nPosY, &rTarget, sal_True ); + } + } + else + { + SC_MOD()->InputEnterHandler(); + InsertURLButton( rName, rURL, rTarget ); + } +} + +//------------------------------------------------------------------------ + +// wenn CLOOKs: -> mit <editview.hxx> <flditem.hxx>in neue tabvwsh + +void lcl_SelectFieldAfterInsert( EditView& rView ) +{ + ESelection aSel = rView.GetSelection(); + if ( aSel.nStartPos == aSel.nEndPos && aSel.nStartPos > 0 ) + { + // Cursor is behind the inserted field -> extend selection to the left + + --aSel.nStartPos; + rView.SetSelection( aSel ); + } +} + +void ScTabViewShell::InsertURLField( const String& rName, const String& rURL, const String& rTarget ) +{ + SvxURLField aURLField( rURL, rName, SVXURLFORMAT_REPR ); + aURLField.SetTargetFrame( rTarget ); + SvxFieldItem aURLItem( aURLField, EE_FEATURE_FIELD ); + + ScViewData* pViewData = GetViewData(); + ScModule* pScMod = SC_MOD(); + ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() ); + + sal_Bool bSelectFirst = sal_False; + if ( !pScMod->IsEditMode() ) + { + if ( !SelectionEditable() ) + { + // no error message (may be called from drag&drop) + Sound::Beep(); + return; + } + + // single url in cell is shown in the dialog and replaced + bSelectFirst = HasBookmarkAtCursor( NULL ); + pScMod->SetInputMode( SC_INPUT_TABLE ); + } + + EditView* pTopView = pHdl->GetTopView(); + EditView* pTableView = pHdl->GetTableView(); + DBG_ASSERT( pTopView || pTableView, "No EditView" ); + + if ( bSelectFirst ) + { + if ( pTopView ) + pTopView->SetSelection( ESelection(0,0,0,1) ); + if ( pTableView ) + pTableView->SetSelection( ESelection(0,0,0,1) ); + } + + pHdl->DataChanging(); + + if ( pTopView ) + { + pTopView->InsertField( aURLItem ); + lcl_SelectFieldAfterInsert( *pTopView ); + } + if ( pTableView ) + { + pTableView->InsertField( aURLItem ); + lcl_SelectFieldAfterInsert( *pTableView ); + } + + pHdl->DataChanged(); +} + +void ScTabViewShell::ExecSearch( SfxRequest& rReq ) +{ + const SfxItemSet* pReqArgs = rReq.GetArgs(); + sal_uInt16 nSlot = rReq.GetSlot(); + const SfxPoolItem* pItem; + + switch ( nSlot ) + { + case FID_SEARCH_NOW: + { + if ( pReqArgs && + SFX_ITEM_SET == pReqArgs->GetItemState(SID_SEARCH_ITEM, sal_False, &pItem) ) + { + DBG_ASSERT( pItem->ISA(SvxSearchItem), "falsches Item" ); + const SvxSearchItem* pSearchItem = (const SvxSearchItem*) pItem; + + ScGlobal::SetSearchItem( *pSearchItem ); + SearchAndReplace( pSearchItem, sal_True, rReq.IsAPI() ); + rReq.Done(); + } + } + break; + + case SID_SEARCH_ITEM: + if (pReqArgs && SFX_ITEM_SET == + pReqArgs->GetItemState(SID_SEARCH_ITEM, sal_False, &pItem)) + { + // Search-Item merken + DBG_ASSERT( pItem->ISA(SvxSearchItem), "falsches Item" ); + ScGlobal::SetSearchItem( *(const SvxSearchItem*) pItem ); + } + else + { + DBG_ERROR("SID_SEARCH_ITEM ohne Parameter"); + } + break; + case FID_SEARCH: + case FID_REPLACE: + case FID_REPLACE_ALL: + case FID_SEARCH_ALL: + { + if (pReqArgs && SFX_ITEM_SET == pReqArgs->GetItemState(nSlot, sal_False, &pItem)) + { + // SearchItem holen + + SvxSearchItem aSearchItem = ScGlobal::GetSearchItem(); + + // SearchItem fuellen + + aSearchItem.SetSearchString(((SfxStringItem*)pItem)->GetValue()); + if(SFX_ITEM_SET == pReqArgs->GetItemState(FN_PARAM_1, sal_False, &pItem)) + aSearchItem.SetReplaceString(((SfxStringItem*)pItem)->GetValue()); + + if (nSlot == FID_SEARCH) + aSearchItem.SetCommand(SVX_SEARCHCMD_FIND); + else if(nSlot == FID_REPLACE) + aSearchItem.SetCommand(SVX_SEARCHCMD_REPLACE); + else if(nSlot == FID_REPLACE_ALL) + aSearchItem.SetCommand(SVX_SEARCHCMD_REPLACE_ALL); + else + aSearchItem.SetCommand(SVX_SEARCHCMD_FIND_ALL); + + // Request ausfuehren (dabei wird das SearchItem gespeichert) + + aSearchItem.SetWhich(SID_SEARCH_ITEM); + GetViewData()->GetDispatcher().Execute( FID_SEARCH_NOW, + rReq.IsAPI() ? SFX_CALLMODE_API|SFX_CALLMODE_SYNCHRON : + SFX_CALLMODE_STANDARD, + &aSearchItem, 0L ); + } + else + { + GetViewData()->GetDispatcher().Execute( + SID_SEARCH_DLG, SFX_CALLMODE_ASYNCHRON|SFX_CALLMODE_RECORD ); + } + } + break; + case FID_REPEAT_SEARCH: + { + // nochmal mit ScGlobal::GetSearchItem() + + SvxSearchItem aSearchItem = ScGlobal::GetSearchItem(); + aSearchItem.SetWhich(SID_SEARCH_ITEM); + GetViewData()->GetDispatcher().Execute( FID_SEARCH_NOW, + rReq.IsAPI() ? SFX_CALLMODE_API|SFX_CALLMODE_SYNCHRON : + SFX_CALLMODE_STANDARD, + &aSearchItem, 0L ); + } + break; +// case FID_SEARCH_COUNT: + } +} + +//-------------------------------------------------------------------- + + + + + + diff --git a/sc/source/ui/view/tabvwshf.cxx b/sc/source/ui/view/tabvwshf.cxx new file mode 100644 index 000000000000..10aea8a81dae --- /dev/null +++ b/sc/source/ui/view/tabvwshf.cxx @@ -0,0 +1,964 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +#include <boost/scoped_ptr.hpp> + +#include "scitems.hxx" +#include <sfx2/request.hxx> +#include <sfx2/viewfrm.hxx> +#include <basic/sbstar.hxx> +#include <layout/layout.hxx> +#include <svl/languageoptions.hxx> +#include <svl/stritem.hxx> +#include <svl/whiter.hxx> +#include <vcl/msgbox.hxx> +#include <sfx2/objface.hxx> +#include <svx/svxdlg.hxx> +#include <editeng/colritem.hxx> + +#include "tabvwsh.hxx" +#include "sc.hrc" +#include "docsh.hxx" +#include "document.hxx" +#include "shtabdlg.hxx" +#include "scresid.hxx" +//CHINA001 #include "instbdlg.hxx" +#include "globstr.hrc" +//CHINA001 #include "strindlg.hxx" +//CHINA001 #include "mvtabdlg.hxx" +#include "docfunc.hxx" +#include "eventuno.hxx" + +#include "scabstdlg.hxx" //CHINA001 + +#include "tabbgcolor.hxx" +#include "tabbgcolordlg.hxx" +#include "sccommands.h" + +using ::boost::scoped_ptr; +using namespace com::sun::star; + +#define IS_AVAILABLE(WhichId,ppItem) \ + (pReqArgs->GetItemState((WhichId), sal_True, ppItem ) == SFX_ITEM_SET) + +//------------------------------------------------------------------ + +void ScTabViewShell::ExecuteTable( SfxRequest& rReq ) +{ + ScViewData* pViewData = GetViewData(); + ScDocument* pDoc = pViewData->GetDocument(); + + SCTAB nCurrentTab = pViewData->GetTabNo(); + SCTAB nTabCount = pDoc->GetTableCount(); + sal_uInt16 nSlot = rReq.GetSlot(); + const SfxItemSet* pReqArgs = rReq.GetArgs(); + + HideListBox(); // Autofilter-DropDown-Listbox + + switch ( nSlot ) + { + case FID_TABLE_VISIBLE: + { + String aName; + pDoc->GetName( nCurrentTab, aName ); + + sal_Bool bVisible=sal_True; + if( pReqArgs != NULL ) + { + const SfxPoolItem* pItem; + if( IS_AVAILABLE( FID_TABLE_VISIBLE, &pItem ) ) + bVisible = ((const SfxBoolItem*)pItem)->GetValue(); + } + + if( ! bVisible ) // ausblenden + { + ScMarkData& rMark = pViewData->GetMarkData(); + SCTAB nTabSelCount = rMark.GetSelectCount(); + sal_uInt16 nVis = 0; + for ( SCTAB i=0; i < nTabCount && nVis<2; i++ ) + if (pDoc->IsVisible(i)) + ++nVis; + if ( nVis<2 || !pDoc->IsDocEditable() || nTabSelCount > 1 ) + break; + + SCTAB nHideTab; + if (pDoc->GetTable( aName, nHideTab )) + HideTable( nHideTab ); + } + else // einblenden + { + ShowTable( aName ); + } + } + break; + + case FID_TABLE_HIDE: + { + ScMarkData& rMark = pViewData->GetMarkData(); + SCTAB nTabSelCount = rMark.GetSelectCount(); + sal_uInt16 nVis = 0; + for ( SCTAB i=0; i < nTabCount && nVis<2; i++ ) + if (pDoc->IsVisible(i)) + ++nVis; + if ( nVis<2 || !pDoc->IsDocEditable() || nTabSelCount > 1 ) + break; + + + String aName; + if( pReqArgs != NULL ) + { + const SfxPoolItem* pItem; + if( IS_AVAILABLE( FID_TABLE_HIDE, &pItem ) ) + aName = ((const SfxStringItem*)pItem)->GetValue(); + } + + if (!aName.Len()) + { + pDoc->GetName( nCurrentTab, aName ); // aktuelle Tabelle + rReq.AppendItem( SfxStringItem( FID_TABLE_HIDE, aName ) ); + } + + SCTAB nHideTab; + if (pDoc->GetTable( aName, nHideTab )) + HideTable( nHideTab ); + + if( ! rReq.IsAPI() ) + rReq.Done(); + } + break; + + case FID_TABLE_SHOW: + { + String aName; + if ( pReqArgs ) + { + const SfxPoolItem* pItem; + if( IS_AVAILABLE( FID_TABLE_SHOW, &pItem ) ) + { + aName = ((const SfxStringItem*)pItem)->GetValue(); + + ShowTable( aName ); + + if( ! rReq.IsAPI() ) + rReq.Done(); + } + } + else + { + //CHINA001 ScShowTabDlg* pDlg = new ScShowTabDlg( GetDialogParent() ); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + AbstractScShowTabDlg* pDlg = pFact->CreateScShowTabDlg( GetDialogParent(), RID_SCDLG_SHOW_TAB); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + + String aTabName; + sal_Bool bFirst = sal_True; + for ( SCTAB i=0; i != nTabCount; i++ ) + { + if (!pDoc->IsVisible(i)) + { + pDoc->GetName( i, aTabName ); + pDlg->Insert( aTabName, bFirst ); + bFirst = sal_False; + } + } + + if ( pDlg->Execute() == RET_OK ) + { + sal_uInt16 nCount = pDlg->GetSelectEntryCount(); + for (sal_uInt16 nPos=0; nPos<nCount; nPos++) + { + aName = pDlg->GetSelectEntry(nPos); + ShowTable( aName ); + } + rReq.AppendItem( SfxStringItem( FID_TABLE_SHOW, aName ) ); + rReq.Done(); + } + delete pDlg; + } + } + break; + + case FID_INS_TABLE: + case FID_INS_TABLE_EXT: + { + ScMarkData& rMark = pViewData->GetMarkData(); + SCTAB nTabSelCount = rMark.GetSelectCount(); + SCTAB nTabNr = nCurrentTab; + + if ( !pDoc->IsDocEditable() ) + break; // gesperrt + + if ( pReqArgs != NULL ) // von Basic + { + sal_Bool bOk = sal_False; + const SfxPoolItem* pTabItem; + const SfxPoolItem* pNameItem; + String aName; + + if ( IS_AVAILABLE( FN_PARAM_1, &pTabItem ) && + IS_AVAILABLE( nSlot, &pNameItem ) ) + { + // Tabellennr. von Basic: 1-basiert + + aName = ((const SfxStringItem*)pNameItem)->GetValue(); + nTabNr = ((const SfxUInt16Item*)pTabItem)->GetValue() - 1; + if ( nTabNr < nTabCount ) + bOk = InsertTable( aName, nTabNr ); + } + + if (bOk) + rReq.Done( *pReqArgs ); + //! sonst Fehler setzen + } + else // Dialog + { +//CHINA001 ScInsertTableDlg* pDlg = new ScInsertTableDlg( +//CHINA001 GetDialogParent(), +//CHINA001 *pViewData,nTabSelCount); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + AbstractScInsertTableDlg* pDlg = pFact->CreateScInsertTableDlg( GetDialogParent(), *pViewData, + nTabSelCount, nSlot == FID_INS_TABLE_EXT, + RID_SCDLG_INSERT_TABLE); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + if ( RET_OK == pDlg->Execute() ) + { + if (pDlg->GetTablesFromFile()) + { + SCTAB nTabs[MAXTABCOUNT]; + SCTAB nCount = 0; + sal_uInt16 n = 0; + const String* pStr = pDlg->GetFirstTable( &n ); + while ( pStr ) + { + nTabs[nCount++] = static_cast<SCTAB>(n); + pStr = pDlg->GetNextTable( &n ); + } + sal_Bool bLink = pDlg->GetTablesAsLink(); + if (nCount != 0) + { + if(pDlg->IsTableBefore()) + { + ImportTables( pDlg->GetDocShellTables(), nCount, nTabs, + bLink,nTabNr ); + } + else + { + SCTAB nTabAfter = nTabNr+1; + + for(SCTAB j=nCurrentTab+1;j<nTabCount;j++) + { + if(!pDoc->IsScenario(j)) + { + nTabAfter=j; + break; + } + } + + ImportTables( pDlg->GetDocShellTables(), nCount, nTabs, + bLink,nTabAfter ); + } + } + } + else + { + SCTAB nCount=pDlg->GetTableCount(); + if(pDlg->IsTableBefore()) + { + if(nCount==1 && pDlg->GetFirstTable()->Len()>0) + { + rReq.AppendItem( SfxStringItem( FID_INS_TABLE, *pDlg->GetFirstTable() ) ); + rReq.AppendItem( SfxUInt16Item( FN_PARAM_1, static_cast<sal_uInt16>(nTabNr) + 1 ) ); // 1-based + rReq.Done(); + + InsertTable( *pDlg->GetFirstTable(), nTabNr ); + } + else + InsertTables( NULL, nTabNr,nCount ); + } + else + { + SCTAB nTabAfter = nTabNr+1; + SCTAB nSelHigh=0; + + for(SCTAB i=0;i<nTabCount;i++) + { + if(rMark.GetTableSelect(i)) + { + nSelHigh=i; + } + } + + for(SCTAB j=nSelHigh+1;j<nTabCount;j++) + { + if(!pDoc->IsScenario(j)) + { + nTabAfter=j; + break; + } + else // #101672#; increase nTabAfter, because it is possible that the scenario tables are the last + nTabAfter = j + 1; + } + + if(nCount==1 && pDlg->GetFirstTable()->Len()>0) + { + rReq.AppendItem( SfxStringItem( FID_INS_TABLE, *pDlg->GetFirstTable() ) ); + rReq.AppendItem( SfxUInt16Item( FN_PARAM_1, static_cast<sal_uInt16>(nTabAfter) + 1 ) ); // 1-based + rReq.Done(); + + InsertTable( *pDlg->GetFirstTable(), nTabAfter); + } + else + { + InsertTables( NULL, nTabAfter,nCount); + } + } + } + } + + delete pDlg; + } + } + break; + + case FID_TAB_APPEND: + case FID_TAB_RENAME: + case FID_TAB_MENU_RENAME: + { + // FID_TAB_MENU_RENAME - "umbenennen" im Menu + // FID_TAB_RENAME - "Name"-Property fuer Basic + // Execute ist gleich, aber im GetState wird MENU_RENAME evtl. disabled + + if ( nSlot == FID_TAB_MENU_RENAME ) + nSlot = FID_TAB_RENAME; // Execute ist gleich + + SCTAB nTabNr = pViewData->GetTabNo(); + ScMarkData& rMark = pViewData->GetMarkData(); + SCTAB nTabSelCount = rMark.GetSelectCount(); + + if ( !pDoc->IsDocEditable() ) + break; // alles gesperrt + + if ( nSlot != FID_TAB_APPEND && + ( pDoc->IsTabProtected( nTabNr ) || nTabSelCount > 1 ) ) + break; // kein Rename + +#if 0 + // ScSbxObject wird nicht mehr benutzt, stattdessen aus dem + // ScSbxTable::Notify die richtige Tabelle an der Basic-View eingestellt + if( rReq.IsAPI() ) + { + SbxObject* pObj = GetScSbxObject(); + ScSbxTable* pSbxTab = PTR_CAST( ScSbxTable, pObj ); + DBG_ASSERT( pSbxTab, "pSbxTab???" ); + + if( pSbxTab ) + nTabNr = pSbxTab->GetTableNr(); + } +#endif + + if( pReqArgs != NULL ) + { + sal_Bool bDone = sal_False; + const SfxPoolItem* pItem; + String aName; + + if( IS_AVAILABLE( FN_PARAM_1, &pItem ) ) + nTabNr = ((const SfxUInt16Item*)pItem)->GetValue(); + + if( IS_AVAILABLE( nSlot, &pItem ) ) + aName = ((const SfxStringItem*)pItem)->GetValue(); + + switch ( nSlot ) + { + case FID_TAB_APPEND: + bDone = AppendTable( aName ); + break; + case FID_TAB_RENAME: + bDone = RenameTable( aName, nTabNr ); + break; + } + + if( bDone ) + { + rReq.Done( *pReqArgs ); + } + } + else + { + sal_uInt16 nRet = RET_OK; + sal_Bool bDone = sal_False; + String aErrMsg ( ScGlobal::GetRscString( STR_INVALIDTABNAME ) ); + String aName; + String aDlgTitle; + const sal_Char* pHelpId = 0; + + switch ( nSlot ) + { + case FID_TAB_APPEND: + aDlgTitle = String(ScResId(SCSTR_APDTABLE)); + pDoc->CreateValidTabName( aName ); + pHelpId = HID_SC_APPEND_NAME; + break; + + case FID_TAB_RENAME: + aDlgTitle = String(ScResId(SCSTR_RENAMETAB)); + pDoc->GetName( pViewData->GetTabNo(), aName ); + pHelpId = HID_SC_RENAME_NAME; + break; + } + + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + AbstractScStringInputDlg* pDlg = pFact->CreateScStringInputDlg( GetDialogParent(), + aDlgTitle, + String(ScResId(SCSTR_NAME)), + aName, + GetStaticInterface()->GetSlot(nSlot)->GetCommand(), pHelpId, RID_SCDLG_STRINPUT); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + + while ( !bDone && nRet == RET_OK ) + { + nRet = pDlg->Execute(); + + if ( nRet == RET_OK ) + { + pDlg->GetInputString( aName ); + + + switch ( nSlot ) + { + case FID_TAB_APPEND: + bDone = AppendTable( aName ); + break; + case FID_TAB_RENAME: + bDone = RenameTable( aName, nTabNr ); + break; + } + + if ( bDone ) + { + rReq.AppendItem( SfxStringItem( nSlot, aName ) ); + rReq.Done(); + } + else + { + if( rReq.IsAPI() ) + { + StarBASIC::Error( SbERR_SETPROP_FAILED ); // XXX Fehlerbehandlung??? + } + else + { + nRet = ErrorBox( GetDialogParent(), + WinBits( WB_OK | WB_DEF_OK ), + aErrMsg + ).Execute(); + } + } + } + } + delete pDlg; + } + } + break; + + case FID_TAB_MOVE: + { + if ( pDoc->GetChangeTrack() != NULL ) + break; // bei aktiviertem ChangeTracking kein TabMove + + sal_Bool bDoIt = sal_False; + sal_uInt16 nDoc = 0; + SCTAB nTab = pViewData->GetTabNo(); + sal_Bool bCpy = sal_False; + String aDocName; + + if( pReqArgs != NULL ) + { + SCTAB nTableCount = pDoc->GetTableCount(); + const SfxPoolItem* pItem; + + if( IS_AVAILABLE( FID_TAB_MOVE, &pItem ) ) + aDocName = ((const SfxStringItem*)pItem)->GetValue(); + if( IS_AVAILABLE( FN_PARAM_1, &pItem ) ) + { + // Tabelle ist 1-basiert + nTab = ((const SfxUInt16Item*)pItem)->GetValue() - 1; + if ( nTab >= nTableCount ) + nTab = SC_TAB_APPEND; + } + if( IS_AVAILABLE( FN_PARAM_2, &pItem ) ) + bCpy = ((const SfxBoolItem*)pItem)->GetValue(); + + if( aDocName.Len() ) + { + SfxObjectShell* pSh = SfxObjectShell::GetFirst(); + ScDocShell* pScSh = NULL; + sal_uInt16 i=0; + + while ( pSh ) + { + pScSh = PTR_CAST( ScDocShell, pSh ); + + if( pScSh ) + { + pScSh->GetTitle(); + + if( pScSh->GetTitle() == aDocName ) + { + nDoc = i; + ScDocument* pDestDoc = pScSh->GetDocument(); + nTableCount = pDestDoc->GetTableCount(); + bDoIt = pDestDoc->IsDocEditable(); + break; + } + + i++; // nur die ScDocShell's zaehlen + } + pSh = SfxObjectShell::GetNext( *pSh ); + } + } + else // Kein Dokumentname -> neues Dokument + { + nDoc = SC_DOC_NEW; + bDoIt = sal_True; + } + + if ( bDoIt && nTab >= nTableCount ) // ggf. anhaengen + nTab = SC_TAB_APPEND; + } + else + { + //CHINA001 ScMoveTableDlg* pDlg = new ScMoveTableDlg( GetDialogParent() ); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + AbstractScMoveTableDlg* pDlg = pFact->CreateScMoveTableDlg( GetDialogParent(), RID_SCDLG_MOVETAB ); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + + SCTAB nTableCount = pDoc->GetTableCount(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + SCTAB nTabSelCount = rMark.GetSelectCount(); + + + if(nTableCount==nTabSelCount) + { + pDlg->SetCopyTable(); + pDlg->EnableCopyTable(sal_False); + } + if ( pDlg->Execute() == RET_OK ) + { + nDoc = pDlg->GetSelectedDocument(); + nTab = pDlg->GetSelectedTable(); + bCpy = pDlg->GetCopyTable(); + bDoIt = sal_True; + + String aFoundDocName; + if ( nDoc != SC_DOC_NEW ) + { + ScDocShell* pSh = ScDocShell::GetShellByNum( nDoc ); + if (pSh) + { + aFoundDocName = pSh->GetTitle(); + if ( !pSh->GetDocument()->IsDocEditable() ) + { + ErrorMessage(STR_READONLYERR); + bDoIt = sal_False; + } + } + } + rReq.AppendItem( SfxStringItem( FID_TAB_MOVE, aFoundDocName ) ); + // Tabelle ist 1-basiert, wenn nicht APPEND + SCTAB nBasicTab = ( nTab <= MAXTAB ) ? (nTab+1) : nTab; + rReq.AppendItem( SfxUInt16Item( FN_PARAM_1, static_cast<sal_uInt16>(nBasicTab) ) ); + rReq.AppendItem( SfxBoolItem( FN_PARAM_2, bCpy ) ); + } + delete pDlg; + } + + if( bDoIt ) + { + rReq.Done(); // aufzeichnen, solange das Dokument noch aktiv ist + + MoveTable( nDoc, nTab, bCpy ); + } + } + break; + + case FID_DELETE_TABLE: + { + // Parameter war ueberfluessig, weil die Methode an der Table haengt + + sal_Bool bDoIt = rReq.IsAPI(); + if( !bDoIt ) + { + // wenn's nicht von Basic kommt, nochmal nachfragen: + +#if ENABLE_LAYOUT +// Using layout::QueryBox without client code modification is +// deprecated, rather add HIG-complient buttons with verbs. +#define QueryBox( parent, winbits, question ) layout::QueryBox (parent, question, ScGlobal::GetRscString (STR_UNDO_DELETE_TAB)) +#endif /* ENABLE_LAYOUT */ + + bDoIt = ( RET_YES == + QueryBox( GetDialogParent(), + WinBits( WB_YES_NO | WB_DEF_YES ), + ScGlobal::GetRscString(STR_QUERY_DELTAB) + ).Execute() ); + } + if( bDoIt ) + { + SCTAB nNewTab = nCurrentTab; + SCTAB nFirstTab=0; + sal_Bool bTabFlag=sal_False; + ScMarkData& rMark = pViewData->GetMarkData(); + SvShorts TheTabs; + for(SCTAB i=0;i<nTabCount;i++) + { + if(rMark.GetTableSelect(i) &&!pDoc->IsTabProtected(i)) + { + TheTabs.push_back(i); + bTabFlag=sal_True; + if(nNewTab==i) nNewTab++; + } + if(!bTabFlag) nFirstTab=i; + } + if(nNewTab>=nTabCount) nNewTab=nFirstTab; + + pViewData->SetTabNo(nNewTab); + DeleteTables(TheTabs); + TheTabs.clear(); + rReq.Done(); + } + } + break; + + case FID_TAB_RTL: + { + ScDocShell* pDocSh = pViewData->GetDocShell(); + ScDocFunc aFunc(*pDocSh); + sal_Bool bSet = !pDoc->IsLayoutRTL( nCurrentTab ); + + const ScMarkData& rMark = pViewData->GetMarkData(); + if ( rMark.GetSelectCount() != 0 ) + { + // handle several sheets + + ::svl::IUndoManager* pUndoManager = pDocSh->GetUndoManager(); + String aUndo = ScGlobal::GetRscString( STR_UNDO_TAB_RTL ); + pUndoManager->EnterListAction( aUndo, aUndo ); + + for (SCTAB nTab=0; nTab<nTabCount; nTab++) + if ( rMark.GetTableSelect(nTab) ) + aFunc.SetLayoutRTL( nTab, bSet, sal_False ); + + pUndoManager->LeaveListAction(); + } + else + aFunc.SetLayoutRTL( nCurrentTab, bSet, sal_False ); + } + break; + + case FID_TAB_SET_TAB_BG_COLOR: + case FID_TAB_MENU_SET_TAB_BG_COLOR: + { + if ( nSlot == FID_TAB_MENU_SET_TAB_BG_COLOR ) + nSlot = FID_TAB_SET_TAB_BG_COLOR; + SCTAB nTabNr = pViewData->GetTabNo(); + ScMarkData& rMark = pViewData->GetMarkData(); + SCTAB nTabSelCount = rMark.GetSelectCount(); + if ( !pDoc->IsDocEditable() ) + break; + + if ( pDoc->IsTabProtected( nTabNr ) ) // ||nTabSelCount > 1 + break; + + if( pReqArgs != NULL ) + { + sal_Bool bDone = sal_False; + const SfxPoolItem* pItem; + Color aColor; + if( IS_AVAILABLE( FN_PARAM_1, &pItem ) ) + nTabNr = ((const SfxUInt16Item*)pItem)->GetValue(); + + if( IS_AVAILABLE( nSlot, &pItem ) ) + aColor = ((const SvxColorItem*)pItem)->GetValue(); + + if ( nTabSelCount > 1 ) + { + scoped_ptr<ScUndoTabColorInfo::List> + pTabColorList(new ScUndoTabColorInfo::List); + for (SCTAB nTab=0; nTab<nTabCount; nTab++) + { + if ( rMark.GetTableSelect(nTab) && !pDoc->IsTabProtected(nTab) ) + { + ScUndoTabColorInfo aTabColorInfo(nTab); + aTabColorInfo.maNewTabBgColor = aColor; + pTabColorList->push_back(aTabColorInfo); + } + } + bDone = SetTabBgColor( *pTabColorList ); + } + else + { + bDone = SetTabBgColor( aColor, nCurrentTab ); //ScViewFunc.SetTabBgColor + } + if( bDone ) + { + rReq.Done( *pReqArgs ); + } + } + else + { + sal_uInt16 nRet = RET_OK; /// temp + sal_Bool bDone = sal_False; /// temp + Color aTabBgColor; + Color aNewTabBgColor; + + aTabBgColor = pDoc->GetTabBgColor( nCurrentTab ); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!"); + AbstractScTabBgColorDlg* pDlg = pFact->CreateScTabBgColorDlg( + GetDialogParent(), + String(ScResId(SCSTR_SET_TAB_BG_COLOR)), + String(ScResId(SCSTR_NO_TAB_BG_COLOR)), + aTabBgColor, + CMD_FID_TAB_SET_TAB_BG_COLOR, + RID_SCDLG_TAB_BG_COLOR); + while ( !bDone && nRet == RET_OK ) + { + nRet = pDlg->Execute(); + if( nRet == RET_OK ) + { + Color aSelectedColor; + pDlg->GetSelectedColor(aSelectedColor); + scoped_ptr<ScUndoTabColorInfo::List> + pTabColorList(new ScUndoTabColorInfo::List); + if ( nTabSelCount > 1 ) + { + for (SCTAB nTab=0; nTab<nTabCount; nTab++) + { + if ( rMark.GetTableSelect(nTab) && !pDoc->IsTabProtected(nTab) ) + { + ScUndoTabColorInfo aTabColorInfo(nTab); + aTabColorInfo.maNewTabBgColor = aSelectedColor; + pTabColorList->push_back(aTabColorInfo); + } + } + bDone = SetTabBgColor( *pTabColorList ); + } + else + { + bDone = SetTabBgColor( aSelectedColor, nCurrentTab ); //ScViewFunc.SetTabBgColor + } + if ( bDone ) + { + rReq.AppendItem( SvxColorItem( aTabBgColor, nSlot ) ); + rReq.Done(); + } + else + { + if( rReq.IsAPI() ) + { + StarBASIC::Error( SbERR_SETPROP_FAILED ); + } + } + } + } + delete( pDlg ); + } + } + break; + + case FID_TAB_EVENTS: + { + ScDocShell* pDocSh = pViewData->GetDocShell(); + uno::Reference<container::XNameReplace> xEvents( new ScSheetEventsObj( pDocSh, nCurrentTab ) ); + uno::Reference<frame::XFrame> xFrame = GetViewFrame()->GetFrame().GetFrameInterface(); + SvxAbstractDialogFactory* pDlgFactory = SvxAbstractDialogFactory::Create(); + if (pDlgFactory) + { + std::auto_ptr<VclAbstractDialog> pDialog( pDlgFactory->CreateSvxMacroAssignDlg( + GetDialogParent(), xFrame, false, xEvents, 0 ) ); + if ( pDialog.get() && pDialog->Execute() == RET_OK ) + { + // the dialog modifies the settings directly + } + } + } + break; + + default: + DBG_ERROR("Unbekannte Message bei ViewShell"); + break; + } +} + +//------------------------------------------------------------------ + +void ScTabViewShell::GetStateTable( SfxItemSet& rSet ) +{ + ScViewData* pViewData = GetViewData(); + ScDocument* pDoc = pViewData->GetDocument(); + ScDocShell* pDocShell = pViewData->GetDocShell(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + SCTAB nTab = pViewData->GetTabNo(); + + SCTAB nTabCount = pDoc->GetTableCount(); + SCTAB nTabSelCount = rMark.GetSelectCount(); + + SfxWhichIter aIter(rSet); + sal_uInt16 nWhich = aIter.FirstWhich(); + + while ( nWhich ) + { + switch ( nWhich ) + { + + case FID_TABLE_VISIBLE: + rSet.Put( SfxBoolItem( nWhich, pDoc->IsVisible(nTab) )); + break; + + case FID_TABLE_HIDE: + { + sal_uInt16 nVis = 0; + for ( SCTAB i=0; i < nTabCount && nVis<2; i++ ) + if (pDoc->IsVisible(i)) + ++nVis; + + if ( nVis<2 || !pDoc->IsDocEditable() || nTabSelCount > 1 ) + rSet.DisableItem( nWhich ); + } + break; + + case FID_TABLE_SHOW: + { + sal_Bool bHasHidden = sal_False; + for ( SCTAB i=0; i < nTabCount && !bHasHidden; i++ ) + if (!pDoc->IsVisible(i)) + bHasHidden = sal_True; + if ( !bHasHidden || pDoc->IsDocProtected() || nTabSelCount > 1 ) + rSet.DisableItem( nWhich ); + } + break; + + case FID_DELETE_TABLE: + { + if ( pDoc->GetChangeTrack() ) + rSet.DisableItem( nWhich ); + else + { + sal_uInt16 nVis = 0; + for ( SCTAB i=0; i < nTabCount && nVis<2; i++ ) + if (pDoc->IsVisible(i)) + ++nVis; + if ( pDoc->IsTabProtected(nTab) + || !pDoc->IsDocEditable() + || nVis < 2 + || nTabSelCount == nTabCount) + rSet.DisableItem( nWhich ); + } + } + break; + + case FID_INS_TABLE: + case FID_INS_TABLE_EXT: + case FID_TAB_APPEND: + if ( !pDoc->IsDocEditable() || + nTabCount > MAXTAB || + ( nWhich == FID_INS_TABLE_EXT && pDocShell && pDocShell->IsDocShared() ) ) + rSet.DisableItem( nWhich ); + break; + + case FID_TAB_MOVE: + if ( !pDoc->IsDocEditable() + || pDoc->GetChangeTrack() != NULL + || nTabCount > MAXTAB) + rSet.DisableItem( nWhich ); + break; + + // FID_TAB_MENU_RENAME - "umbenennen" im Menu + // FID_TAB_RENAME - "Name"-Property fuer Basic + + case FID_TAB_MENU_RENAME: + if ( !pDoc->IsDocEditable() || + pDoc->IsTabProtected(nTab) ||nTabSelCount > 1 || + ( pDocShell && pDocShell->IsDocShared() ) ) + rSet.DisableItem( nWhich ); + break; + + case FID_TAB_RENAME: + { + String aTabName; + pDoc->GetName( nTab, aTabName ); + + rSet.Put( SfxStringItem( nWhich, aTabName )); + + } + break; + + case FID_TAB_RTL: + { + SvtLanguageOptions aLangOpt; + if ( !aLangOpt.IsCTLFontEnabled() ) + rSet.DisableItem( nWhich ); + else + rSet.Put( SfxBoolItem( nWhich, pDoc->IsLayoutRTL( nTab ) ) ); + } + break; + + case FID_TAB_MENU_SET_TAB_BG_COLOR: + { + if ( !pDoc->IsDocEditable() + || ( pDocShell && pDocShell->IsDocShared() ) + || pDoc->IsTabProtected(nTab) ) + rSet.DisableItem( nWhich ); + } + break; + + case FID_TAB_SET_TAB_BG_COLOR: + { + Color aColor; + aColor = pDoc->GetTabBgColor( nTab ); + rSet.Put( SvxColorItem( aColor, nWhich ) ); + } + break; + } + nWhich = aIter.NextWhich(); + } +} + + + + diff --git a/sc/source/ui/view/tabvwshg.cxx b/sc/source/ui/view/tabvwshg.cxx new file mode 100644 index 000000000000..b30b07c43cb9 --- /dev/null +++ b/sc/source/ui/view/tabvwshg.cxx @@ -0,0 +1,140 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +//#define SI_VCDRAWOBJ + +#include <tools/urlobj.hxx> +#include <svx/fmglob.hxx> +#include <svx/svdouno.hxx> +#include <svx/svdpagv.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/docfile.hxx> + +#include <com/sun/star/form/FormButtonType.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/awt/XControlModel.hpp> + +using namespace com::sun::star; + +#include "tabvwsh.hxx" +#include "document.hxx" +#include "drawview.hxx" +#include "globstr.hrc" +#include <avmedia/mediawindow.hxx> + +//------------------------------------------------------------------------ + +void ScTabViewShell::InsertURLButton( const String& rName, const String& rURL, + const String& rTarget, + const Point* pInsPos ) +{ + // Tabelle geschuetzt ? + + ScViewData* pViewData = GetViewData(); + ScDocument* pDoc = pViewData->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + if ( pDoc->IsTabProtected(nTab) ) + { + ErrorMessage(STR_PROTECTIONERR); + return; + } + + MakeDrawLayer(); + + ScTabView* pView = pViewData->GetView(); +// SdrView* pDrView = pView->GetSdrView(); + ScDrawView* pDrView = pView->GetScDrawView(); + SdrModel* pModel = pDrView->GetModel(); + + SdrObject* pObj = SdrObjFactory::MakeNewObject(FmFormInventor, OBJ_FM_BUTTON, + pDrView->GetSdrPageView()->GetPage(), pModel); + SdrUnoObj* pUnoCtrl = PTR_CAST(SdrUnoObj, pObj); + + uno::Reference<awt::XControlModel> xControlModel = pUnoCtrl->GetUnoControlModel(); + DBG_ASSERT( xControlModel.is(), "UNO-Control ohne Model" ); + if( !xControlModel.is() ) + return; + + uno::Reference< beans::XPropertySet > xPropSet( xControlModel, uno::UNO_QUERY ); + uno::Any aAny; + + aAny <<= rtl::OUString(rName); + xPropSet->setPropertyValue( rtl::OUString::createFromAscii( "Label" ), aAny ); + + ::rtl::OUString aTmp = INetURLObject::GetAbsURL( pDoc->GetDocumentShell()->GetMedium()->GetBaseURL(), rURL ); + aAny <<= aTmp; + xPropSet->setPropertyValue( rtl::OUString::createFromAscii( "TargetURL" ), aAny ); + + if( rTarget.Len() ) + { + aAny <<= rtl::OUString(rTarget); + xPropSet->setPropertyValue( rtl::OUString::createFromAscii( "TargetFrame" ), aAny ); + } + + form::FormButtonType eButtonType = form::FormButtonType_URL; + aAny <<= eButtonType; + xPropSet->setPropertyValue( rtl::OUString::createFromAscii( "ButtonType" ), aAny ); + + if ( ::avmedia::MediaWindow::isMediaURL( rURL ) ) + { + // #105638# OJ + aAny <<= sal_True; + xPropSet->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DispatchURLInternal" )), aAny ); + } + + Point aPos; + if (pInsPos) + aPos = *pInsPos; + else + aPos = GetInsertPos(); + + // Groesse wie in 3.1: + Size aSize = GetActiveWin()->PixelToLogic(Size(140, 20)); + + if ( pDoc->IsNegativePage(nTab) ) + aPos.X() -= aSize.Width(); + + pObj->SetLogicRect(Rectangle(aPos, aSize)); +// pObj->Resize(Point(), Fraction(1, 1), Fraction(1, 1)); + + // am alten VC-Button musste die Position/Groesse nochmal explizit + // gesetzt werden - das scheint mit UnoControls nicht noetig zu sein + + // nicht markieren wenn Ole + pDrView->InsertObjectSafe( pObj, *pDrView->GetSdrPageView() ); +} + + + + diff --git a/sc/source/ui/view/tabvwshh.cxx b/sc/source/ui/view/tabvwshh.cxx new file mode 100644 index 000000000000..7622832f9094 --- /dev/null +++ b/sc/source/ui/view/tabvwshh.cxx @@ -0,0 +1,293 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include <svx/svdmark.hxx> +#include <svx/svdoole2.hxx> +#include <svx/svdview.hxx> +#include <sfx2/app.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/request.hxx> +#include <basic/sbxcore.hxx> +#include <svl/whiter.hxx> +#include <vcl/msgbox.hxx> + +#include "tabvwsh.hxx" +#include "client.hxx" +#include "document.hxx" +#include "docsh.hxx" +#include "sc.hrc" +#include "drwlayer.hxx" // GetVisibleName +#include "retypepassdlg.hxx" +#include "tabprotection.hxx" + +#include <memory> + +using namespace com::sun::star; + +//------------------------------------------------------------------ + +void ScTabViewShell::ExecuteSbx( SfxRequest& /* rReq */ ) +{ + // SID_RANGE_OFFSET (Offset), + // SID_PIVOT_CREATE (DataPilotCreate) - removed (old Basic) +} + +void ScTabViewShell::GetSbxState( SfxItemSet& /* rSet */ ) +{ + // SID_RANGE_REGION (CurrentRegion) - removed (old Basic) +} + +//------------------------------------------------------------------ + +void ScTabViewShell::ExecuteObject( SfxRequest& rReq ) +{ + sal_uInt16 nSlotId = rReq.GetSlot(); + const SfxItemSet* pReqArgs = rReq.GetArgs(); + + // Objekte aktivieren/deaktivieren immer auf der sichtbaren View + + ScTabViewShell* pVisibleSh = this; + if ( nSlotId == SID_OLE_SELECT || nSlotId == SID_OLE_ACTIVATE || nSlotId == SID_OLE_DEACTIVATE ) + { + DBG_ERROR("old slot SID_OLE..."); + } + + switch (nSlotId) + { + case SID_OLE_SELECT: + case SID_OLE_ACTIVATE: + { + // in beiden Faellen erstmal auf der sichtbaren View selektieren + + String aName; + SdrView* pDrView = GetSdrView(); + if (pDrView) + { + const SdrMarkList& rMarkList = pDrView->GetMarkedObjectList(); + if (rMarkList.GetMarkCount() == 1) + aName = ScDrawLayer::GetVisibleName( rMarkList.GetMark(0)->GetMarkedSdrObj() ); + } + pVisibleSh->SelectObject( aName ); + + // aktivieren + + if ( nSlotId == SID_OLE_ACTIVATE ) + pVisibleSh->DoVerb( 0 ); + } + break; + case SID_OLE_DEACTIVATE: + pVisibleSh->DeactivateOle(); + break; + + case SID_OBJECT_LEFT: + case SID_OBJECT_TOP: + case SID_OBJECT_WIDTH: + case SID_OBJECT_HEIGHT: + { + sal_Bool bDone = sal_False; + const SfxPoolItem* pItem; + if ( pReqArgs && pReqArgs->GetItemState( nSlotId, sal_True, &pItem ) == SFX_ITEM_SET ) + { + long nNewVal = ((const SfxInt32Item*)pItem)->GetValue(); + if ( nNewVal < 0 ) + nNewVal = 0; + + //! von irgendwas in 1/100mm umrechnen ?????? + + SdrView* pDrView = GetSdrView(); + if ( pDrView ) + { + const SdrMarkList& rMarkList = pDrView->GetMarkedObjectList(); + if (rMarkList.GetMarkCount() == 1) + { + SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + Rectangle aRect = pObj->GetLogicRect(); + + if ( nSlotId == SID_OBJECT_LEFT ) + pDrView->MoveMarkedObj( Size( nNewVal - aRect.Left(), 0 ) ); + else if ( nSlotId == SID_OBJECT_TOP ) + pDrView->MoveMarkedObj( Size( 0, nNewVal - aRect.Top() ) ); + else if ( nSlotId == SID_OBJECT_WIDTH ) + pDrView->ResizeMarkedObj( aRect.TopLeft(), + Fraction( nNewVal, aRect.GetWidth() ), + Fraction( 1, 1 ) ); + else // if ( nSlotId == SID_OBJECT_HEIGHT ) + pDrView->ResizeMarkedObj( aRect.TopLeft(), + Fraction( 1, 1 ), + Fraction( nNewVal, aRect.GetHeight() ) ); + bDone = sal_True; + } + } + } + if (!bDone) + SbxBase::SetError( SbxERR_BAD_PARAMETER ); // Basic-Fehler + } + break; + + } +} + +uno::Reference < embed::XEmbeddedObject > lcl_GetSelectedObj( SdrView* pDrView ) //! Member von ScDrawView? +{ + uno::Reference < embed::XEmbeddedObject > xRet; + if (pDrView) + { + const SdrMarkList& rMarkList = pDrView->GetMarkedObjectList(); + if (rMarkList.GetMarkCount() == 1) + { + SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + if (pObj->GetObjIdentifier() == OBJ_OLE2) + { + SdrOle2Obj* pOle2Obj = (SdrOle2Obj*) pObj; + xRet = pOle2Obj->GetObjRef(); + } + } + } + + return xRet; +} + +void ScTabViewShell::GetObjectState( SfxItemSet& rSet ) +{ + // SID_OLE_OBJECT - removed (old Basic) + + SfxWhichIter aIter(rSet); + sal_uInt16 nWhich = aIter.FirstWhich(); + while ( nWhich ) + { + switch (nWhich) + { + case SID_ACTIVE_OBJ_NAME: + { + String aName; + uno::Reference < embed::XEmbeddedObject > xOLE = lcl_GetSelectedObj( GetSdrView() ); + if (xOLE.is()) + { + aName = GetViewData()->GetSfxDocShell()->GetEmbeddedObjectContainer().GetEmbeddedObjectName( xOLE ); + } + rSet.Put( SfxStringItem( nWhich, aName ) ); + } + break; + case SID_OBJECT_LEFT: + case SID_OBJECT_TOP: + case SID_OBJECT_WIDTH: + case SID_OBJECT_HEIGHT: + { + SdrView* pDrView = GetSdrView(); + if ( pDrView ) + { + const SdrMarkList& rMarkList = pDrView->GetMarkedObjectList(); + if (rMarkList.GetMarkCount() == 1) + { + SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + Rectangle aRect = pObj->GetLogicRect(); + + long nVal; + if ( nWhich == SID_OBJECT_LEFT ) + nVal = aRect.Left(); + else if ( nWhich == SID_OBJECT_TOP ) + nVal = aRect.Top(); + else if ( nWhich == SID_OBJECT_WIDTH ) + nVal = aRect.GetWidth(); + else // if ( nWhich == SID_OBJECT_HEIGHT ) + nVal = aRect.GetHeight(); + + //! von 1/100mm in irgendwas umrechnen ?????? + + rSet.Put( SfxInt32Item( nWhich, nVal ) ); + } + } + } + break; + } + nWhich = aIter.NextWhich(); + } +} + +void ScTabViewShell::AddAccessibilityObject( SfxListener& rObject ) +{ + if (!pAccessibilityBroadcaster) + pAccessibilityBroadcaster = new SfxBroadcaster; + + rObject.StartListening( *pAccessibilityBroadcaster ); + ScDocument* pDoc = GetViewData()->GetDocument(); + if (pDoc) + pDoc->AddUnoObject(rObject); +} + +void ScTabViewShell::RemoveAccessibilityObject( SfxListener& rObject ) +{ + if (pAccessibilityBroadcaster) + { + rObject.EndListening( *pAccessibilityBroadcaster ); + ScDocument* pDoc = GetViewData()->GetDocument(); + if (pDoc) + pDoc->RemoveUnoObject(rObject); + } + else + { + DBG_ERROR("kein Accessibility-Broadcaster?"); + } +} + +void ScTabViewShell::BroadcastAccessibility( const SfxHint &rHint ) +{ + if (pAccessibilityBroadcaster) + pAccessibilityBroadcaster->Broadcast( rHint ); +} + +sal_Bool ScTabViewShell::HasAccessibilityObjects() +{ + return pAccessibilityBroadcaster != NULL; +} + +bool ScTabViewShell::ExecuteRetypePassDlg(ScPasswordHash eDesiredHash) +{ + using ::std::auto_ptr; + + ScDocument* pDoc = GetViewData()->GetDocument(); + + auto_ptr<ScRetypePassDlg> pDlg(new ScRetypePassDlg(GetDialogParent())); + pDlg->SetDataFromDocument(*pDoc); + pDlg->SetDesiredHash(eDesiredHash); + if (pDlg->Execute() != RET_OK) + return false; + + pDlg->WriteNewDataToDocument(*pDoc); + return true; +} + + + + diff --git a/sc/source/ui/view/viewdata.cxx b/sc/source/ui/view/viewdata.cxx new file mode 100644 index 000000000000..088d3580bd67 --- /dev/null +++ b/sc/source/ui/view/viewdata.cxx @@ -0,0 +1,3179 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include "scitems.hxx" +#include <editeng/eeitem.hxx> + + +#include <sfx2/viewfrm.hxx> +#include <editeng/adjitem.hxx> +#include <svx/algitem.hxx> +#include <editeng/brshitem.hxx> +#include <svtools/colorcfg.hxx> +#include <editeng/editview.hxx> +#include <editeng/editstat.hxx> +#include <editeng/outliner.hxx> +#include <editeng/unolingu.hxx> + +#include <vcl/svapp.hxx> +#include <rtl/math.hxx> + +#include "viewdata.hxx" +#include "docoptio.hxx" +#include "scmod.hxx" +#include "global.hxx" +#include "document.hxx" +#include "attrib.hxx" +#include "tabview.hxx" +#include "tabvwsh.hxx" +#include "docsh.hxx" +#include "sc.hrc" +#include "patattr.hxx" +#include "editutil.hxx" +#include "scextopt.hxx" +#include "miscuno.hxx" +#include "unonames.hxx" +#include "inputopt.hxx" +#include "viewutil.hxx" +#include <xmloff/xmluconv.hxx> +#include "ViewSettingsSequenceDefines.hxx" +#include <rtl/ustrbuf.hxx> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/container/XNameContainer.hpp> + +using namespace com::sun::star; + +// STATIC DATA ----------------------------------------------------------- + +#define SC_GROWY_SMALL_EXTRA 100 +#define SC_GROWY_BIG_EXTRA 200 + +#define TAG_TABBARWIDTH "tw:" + +static sal_Bool bMoveArea = sal_False; //! Member? +sal_uInt16 nEditAdjust = SVX_ADJUST_LEFT; //! Member !!! + +//================================================================== + +ScViewDataTable::ScViewDataTable() : + eZoomType( SVX_ZOOM_PERCENT ), + aZoomX( 1,1 ), + aZoomY( 1,1 ), + aPageZoomX( 3,5 ), // Page-Default: 60% + aPageZoomY( 3,5 ), + nHSplitPos( 0 ), + nVSplitPos( 0 ), + eHSplitMode( SC_SPLIT_NONE ), + eVSplitMode( SC_SPLIT_NONE ), + eWhichActive( SC_SPLIT_BOTTOMLEFT ), + nFixPosX( 0 ), + nFixPosY( 0 ), + nCurX( 0 ), + nCurY( 0 ), + bOldCurValid( sal_False ) +{ + nPosX[0]=nPosX[1]=0; + nPosY[0]=nPosY[1]=0; + nTPosX[0]=nTPosX[1]=0; + nTPosY[0]=nTPosY[1]=0; + nMPosX[0]=nMPosX[1]=0; + nMPosY[0]=nMPosY[1]=0; + nPixPosX[0]=nPixPosX[1]=0; + nPixPosY[0]=nPixPosY[1]=0; +} + +ScViewDataTable::~ScViewDataTable() +{ +} + +void ScViewDataTable::WriteUserDataSequence(uno::Sequence <beans::PropertyValue>& rSettings, const ScViewData& /*rViewData*/, SCTAB /*nTab*/) +{ + rSettings.realloc(SC_TABLE_VIEWSETTINGS_COUNT); + beans::PropertyValue* pSettings = rSettings.getArray(); + if (pSettings) + { + pSettings[SC_CURSOR_X].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_CURSORPOSITIONX)); + pSettings[SC_CURSOR_X].Value <<= sal_Int32(nCurX); + pSettings[SC_CURSOR_Y].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_CURSORPOSITIONY)); + pSettings[SC_CURSOR_Y].Value <<= sal_Int32(nCurY); + pSettings[SC_HORIZONTAL_SPLIT_MODE].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_HORIZONTALSPLITMODE)); + pSettings[SC_HORIZONTAL_SPLIT_MODE].Value <<= sal_Int16(eHSplitMode); + pSettings[SC_VERTICAL_SPLIT_MODE].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_VERTICALSPLITMODE)); + pSettings[SC_VERTICAL_SPLIT_MODE].Value <<= sal_Int16(eVSplitMode); + pSettings[SC_HORIZONTAL_SPLIT_POSITION].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_HORIZONTALSPLITPOSITION)); + if (eHSplitMode == SC_SPLIT_FIX) + pSettings[SC_HORIZONTAL_SPLIT_POSITION].Value <<= sal_Int32(nFixPosX); + else + pSettings[SC_HORIZONTAL_SPLIT_POSITION].Value <<= sal_Int32(nHSplitPos); + pSettings[SC_VERTICAL_SPLIT_POSITION].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_VERTICALSPLITPOSITION)); + if (eVSplitMode == SC_SPLIT_FIX) + pSettings[SC_VERTICAL_SPLIT_POSITION].Value <<= sal_Int32(nFixPosY); + else + pSettings[SC_VERTICAL_SPLIT_POSITION].Value <<= sal_Int32(nVSplitPos); + pSettings[SC_ACTIVE_SPLIT_RANGE].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_ACTIVESPLITRANGE)); + pSettings[SC_ACTIVE_SPLIT_RANGE].Value <<= sal_Int16(eWhichActive); + pSettings[SC_POSITION_LEFT].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_POSITIONLEFT)); + pSettings[SC_POSITION_LEFT].Value <<= sal_Int32(nPosX[SC_SPLIT_LEFT]); + pSettings[SC_POSITION_RIGHT].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_POSITIONRIGHT)); + pSettings[SC_POSITION_RIGHT].Value <<= sal_Int32(nPosX[SC_SPLIT_RIGHT]); + pSettings[SC_POSITION_TOP].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_POSITIONTOP)); + pSettings[SC_POSITION_TOP].Value <<= sal_Int32(nPosY[SC_SPLIT_TOP]); + pSettings[SC_POSITION_BOTTOM].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_POSITIONBOTTOM)); + pSettings[SC_POSITION_BOTTOM].Value <<= sal_Int32(nPosY[SC_SPLIT_BOTTOM]); + + sal_Int32 nZoomValue ((aZoomY.GetNumerator() * 100) / aZoomY.GetDenominator()); + sal_Int32 nPageZoomValue ((aPageZoomY.GetNumerator() * 100) / aPageZoomY.GetDenominator()); + pSettings[SC_TABLE_ZOOM_TYPE].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_ZOOMTYPE)); + pSettings[SC_TABLE_ZOOM_TYPE].Value <<= sal_Int16(eZoomType); + pSettings[SC_TABLE_ZOOM_VALUE].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_ZOOMVALUE)); + pSettings[SC_TABLE_ZOOM_VALUE].Value <<= nZoomValue; + pSettings[SC_TABLE_PAGE_VIEW_ZOOM_VALUE].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_PAGEVIEWZOOMVALUE)); + pSettings[SC_TABLE_PAGE_VIEW_ZOOM_VALUE].Value <<= nPageZoomValue; + } +} + +void ScViewDataTable::ReadUserDataSequence(const uno::Sequence <beans::PropertyValue>& aSettings, ScViewData& rViewData, SCTAB nTab, bool& rHasZoom ) +{ + rHasZoom = false; + + sal_Int32 nCount(aSettings.getLength()); + sal_Int32 nTemp32(0); + sal_Int16 nTemp16(0); + sal_Int32 nTempPosV(0); + sal_Int32 nTempPosH(0); + sal_Int32 nTempPosVTw(0); + sal_Int32 nTempPosHTw(0); + bool bHasVSplitInTwips = false; + bool bHasHSplitInTwips = false; + for (sal_Int32 i = 0; i < nCount; i++) + { + rtl::OUString sName(aSettings[i].Name); + if (sName.compareToAscii(SC_CURSORPOSITIONX) == 0) + { + aSettings[i].Value >>= nTemp32; + nCurX = SanitizeCol( static_cast<SCCOL>(nTemp32)); + } + else if (sName.compareToAscii(SC_CURSORPOSITIONY) == 0) + { + aSettings[i].Value >>= nTemp32; + nCurY = SanitizeRow( static_cast<SCROW>(nTemp32)); + } + else if (sName.compareToAscii(SC_HORIZONTALSPLITMODE) == 0) + { + aSettings[i].Value >>= nTemp16; + eHSplitMode = static_cast<ScSplitMode>(nTemp16); + } + else if (sName.compareToAscii(SC_VERTICALSPLITMODE) == 0) + { + aSettings[i].Value >>= nTemp16; + eVSplitMode = static_cast<ScSplitMode>(nTemp16); + } + else if (sName.compareToAscii(SC_HORIZONTALSPLITPOSITION) == 0) + { + aSettings[i].Value >>= nTempPosH; + bHasHSplitInTwips = false; + } + else if (sName.compareToAscii(SC_VERTICALSPLITPOSITION) == 0) + { + aSettings[i].Value >>= nTempPosV; + bHasVSplitInTwips = false; + } + else if (sName.compareToAscii(SC_HORIZONTALSPLITPOSITION_TWIPS) == 0) + { + aSettings[i].Value >>= nTempPosHTw; + bHasHSplitInTwips = true; + } + else if (sName.compareToAscii(SC_VERTICALSPLITPOSITION_TWIPS) == 0) + { + aSettings[i].Value >>= nTempPosVTw; + bHasVSplitInTwips = true; + } + else if (sName.compareToAscii(SC_ACTIVESPLITRANGE) == 0) + { + aSettings[i].Value >>= nTemp16; + eWhichActive = static_cast<ScSplitPos>(nTemp16); + } + else if (sName.compareToAscii(SC_POSITIONLEFT) == 0) + { + aSettings[i].Value >>= nTemp32; + nPosX[SC_SPLIT_LEFT] = SanitizeCol( static_cast<SCCOL>(nTemp32)); + } + else if (sName.compareToAscii(SC_POSITIONRIGHT) == 0) + { + aSettings[i].Value >>= nTemp32; + nPosX[SC_SPLIT_RIGHT] = SanitizeCol( static_cast<SCCOL>(nTemp32)); + } + else if (sName.compareToAscii(SC_POSITIONTOP) == 0) + { + aSettings[i].Value >>= nTemp32; + nPosY[SC_SPLIT_TOP] = SanitizeRow( static_cast<SCROW>(nTemp32)); + } + else if (sName.compareToAscii(SC_POSITIONBOTTOM) == 0) + { + aSettings[i].Value >>= nTemp32; + nPosY[SC_SPLIT_BOTTOM] = SanitizeRow( static_cast<SCROW>(nTemp32)); + } + else if (sName.compareToAscii(SC_ZOOMTYPE) == 0) + { + aSettings[i].Value >>= nTemp16; + eZoomType = SvxZoomType(nTemp16); + rHasZoom = true; // set if there is any zoom information + } + else if (sName.compareToAscii(SC_ZOOMVALUE) == 0) + { + aSettings[i].Value >>= nTemp32; + Fraction aZoom(nTemp32, 100); + aZoomX = aZoomY = aZoom; + rHasZoom = true; + } + else if (sName.compareToAscii(SC_PAGEVIEWZOOMVALUE) == 0) + { + aSettings[i].Value >>= nTemp32; + Fraction aZoom(nTemp32, 100); + aPageZoomX = aPageZoomY = aZoom; + rHasZoom = true; + } + else if (sName.compareToAscii(SC_TABLESELECTED) == 0) + { + bool bSelected = false; + aSettings[i].Value >>= bSelected; + rViewData.GetMarkData().SelectTable( nTab, bSelected ); + } + else if (sName.compareToAscii(SC_UNONAME_TABCOLOR) == 0) + { + // There are documents out there that have their tab color defined as a view setting. + sal_Int32 nColor = COL_AUTO; + aSettings[i].Value >>= nColor; + if (static_cast<ColorData>(nColor) != COL_AUTO) + { + ScDocument* pDoc = rViewData.GetDocument(); + pDoc->SetTabBgColor(nTab, Color(static_cast<ColorData>(nColor))); + } + } + } + if (eHSplitMode == SC_SPLIT_FIX) + nFixPosX = SanitizeCol( static_cast<SCCOL>( bHasHSplitInTwips ? nTempPosHTw : nTempPosH )); + else + nHSplitPos = bHasHSplitInTwips ? static_cast< long >( nTempPosHTw * rViewData.GetPPTX() ) : nTempPosH; + + if (eVSplitMode == SC_SPLIT_FIX) + nFixPosY = SanitizeRow( static_cast<SCROW>( bHasVSplitInTwips ? nTempPosVTw : nTempPosV )); + else + nVSplitPos = bHasVSplitInTwips ? static_cast< long >( nTempPosVTw * rViewData.GetPPTY() ) : nTempPosV; +} + +//================================================================== + +ScViewData::ScViewData( ScDocShell* pDocSh, ScTabViewShell* pViewSh ) + : pDocShell ( pDocSh ), + pDoc ( NULL ), + pView ( pViewSh ), + pViewShell ( pViewSh ), + pOptions ( new ScViewOptions ), + pSpellingView ( NULL ), + aLogicMode ( MAP_100TH_MM ), + eDefZoomType( SVX_ZOOM_PERCENT ), + aDefZoomX ( 1,1 ), + aDefZoomY ( 1,1 ), + aDefPageZoomX( 3,5 ), + aDefPageZoomY( 3,5 ), + eRefType ( SC_REFTYPE_NONE ), + nTabNo ( 0 ), + nRefTabNo ( 0 ), + eEditActivePart( SC_SPLIT_BOTTOMLEFT ), + bActive ( sal_True ), //! wie initialisieren? + bIsRefMode ( sal_False ), + bDelMarkValid( sal_False ), + nFillMode ( SC_FILL_NONE ), + bPagebreak ( sal_False ), + bSelCtrlMouseClick( sal_False ) +{ + + SetGridMode ( sal_True ); + SetSyntaxMode ( sal_False ); + SetHeaderMode ( sal_True ); + SetTabMode ( sal_True ); + SetVScrollMode ( sal_True ); + SetHScrollMode ( sal_True ); + SetOutlineMode ( sal_True ); + + aScrSize = Size( (long) ( STD_COL_WIDTH * PIXEL_PER_TWIPS * OLE_STD_CELLS_X ), + (long) ( ScGlobal::nStdRowHeight * PIXEL_PER_TWIPS * OLE_STD_CELLS_Y ) ); + pTabData[0] = new ScViewDataTable; + for ( SCTAB i = 1; i <= MAXTAB; i++ ) + pTabData[i] = NULL; + pThisTab = pTabData[nTabNo]; + for (sal_uInt16 j=0; j<4; j++) + { + pEditView[j] = NULL; + bEditActive[j] = sal_False; + } + + nEditEndCol = nEditStartCol = nEditCol = 0; + nEditEndRow = nEditRow = 0; + nTabStartCol = SC_TABSTART_NONE; + + if (pDocShell) + { + pDoc = pDocShell->GetDocument(); + *pOptions = pDoc->GetViewOptions(); + } + + // keine ausgeblendete Tabelle anzeigen: + if (pDoc && !pDoc->IsVisible(nTabNo)) + { + while ( !pDoc->IsVisible(nTabNo) && pDoc->HasTable(nTabNo+1) ) + ++nTabNo; + + pTabData[nTabNo] = new ScViewDataTable; + pThisTab = pTabData[nTabNo]; + } + + CalcPPT(); +} + +ScViewData::ScViewData( const ScViewData& rViewData ) + : pDocShell ( rViewData.pDocShell ), + pDoc ( rViewData.pDoc ), + pView ( rViewData.pView ), + pViewShell ( rViewData.pViewShell ), + pOptions ( new ScViewOptions( *(rViewData.pOptions) ) ), + pSpellingView ( rViewData.pSpellingView ), + aLogicMode ( rViewData.aLogicMode ), + eDefZoomType( rViewData.eDefZoomType ), + aDefZoomX ( rViewData.aDefZoomX ), + aDefZoomY ( rViewData.aDefZoomY ), + aDefPageZoomX( rViewData.aDefPageZoomX ), + aDefPageZoomY( rViewData.aDefPageZoomY ), + eRefType ( SC_REFTYPE_NONE ), + nTabNo ( rViewData.nTabNo ), + nRefTabNo ( rViewData.nTabNo ), // kein RefMode + eEditActivePart( rViewData.eEditActivePart ), + bActive ( sal_True ), //! wie initialisieren? + bIsRefMode ( sal_False ), + bDelMarkValid( sal_False ), + nFillMode ( SC_FILL_NONE ), + bPagebreak ( rViewData.bPagebreak ), + bSelCtrlMouseClick( rViewData.bSelCtrlMouseClick ) +{ + + SetGridMode ( rViewData.IsGridMode() ); + SetSyntaxMode ( rViewData.IsSyntaxMode() ); + SetHeaderMode ( rViewData.IsHeaderMode() ); + SetTabMode ( rViewData.IsTabMode() ); + SetVScrollMode ( rViewData.IsVScrollMode() ); + SetHScrollMode ( rViewData.IsHScrollMode() ); + SetOutlineMode ( rViewData.IsOutlineMode() ); + + aScrSize = rViewData.aScrSize; + for ( SCTAB i = 0; i <= MAXTAB; i++ ) + if (rViewData.pTabData[i]) + pTabData[i] = new ScViewDataTable( *rViewData.pTabData[i] ); + else + pTabData[i] = NULL; + pThisTab = pTabData[nTabNo]; + for (sal_uInt16 j=0; j<4; j++) + { + pEditView[j] = NULL; + bEditActive[j] = sal_False; + } + + nEditEndCol = nEditStartCol = nEditCol = 0; + nEditEndRow = nEditRow = 0; + nTabStartCol = SC_TABSTART_NONE; + CalcPPT(); +} + +void ScViewData::InitData( ScDocument* pDocument ) +{ + pDoc = pDocument; + *pOptions = pDoc->GetViewOptions(); +} + +//UNUSED2008-05 void ScViewData::InitFrom( const ScViewData* pRef ) +//UNUSED2008-05 { +//UNUSED2008-05 if (pRef==NULL) +//UNUSED2008-05 { +//UNUSED2008-05 DBG_ERROR("ScViewData::InitFrom mit NULL"); +//UNUSED2008-05 return; +//UNUSED2008-05 } +//UNUSED2008-05 +//UNUSED2008-05 aScrSize = pRef->aScrSize; +//UNUSED2008-05 nTabNo = pRef->nTabNo; +//UNUSED2008-05 eDefZoomType = pRef->eDefZoomType; +//UNUSED2008-05 aDefZoomX = pRef->aDefZoomX; +//UNUSED2008-05 aDefZoomY = pRef->aDefZoomY; +//UNUSED2008-05 aDefPageZoomX = pRef->aDefPageZoomX; +//UNUSED2008-05 aDefPageZoomY = pRef->aDefPageZoomY; +//UNUSED2008-05 bPagebreak = pRef->bPagebreak; +//UNUSED2008-05 aLogicMode = pRef->aLogicMode; +//UNUSED2008-05 +//UNUSED2008-05 SetGridMode ( pRef->IsGridMode() ); +//UNUSED2008-05 SetSyntaxMode ( pRef->IsSyntaxMode() ); +//UNUSED2008-05 SetHeaderMode ( pRef->IsHeaderMode() ); +//UNUSED2008-05 SetTabMode ( pRef->IsTabMode() ); +//UNUSED2008-05 SetVScrollMode ( pRef->IsVScrollMode() ); +//UNUSED2008-05 SetHScrollMode ( pRef->IsHScrollMode() ); +//UNUSED2008-05 SetOutlineMode ( pRef->IsOutlineMode() ); +//UNUSED2008-05 +//UNUSED2008-05 for (SCTAB i=0; i<=MAXTAB; i++) +//UNUSED2008-05 { +//UNUSED2008-05 delete pTabData[i]; +//UNUSED2008-05 if (pRef->pTabData[i]) +//UNUSED2008-05 pTabData[i] = new ScViewDataTable( *pRef->pTabData[i] ); +//UNUSED2008-05 else +//UNUSED2008-05 pTabData[i] = NULL; +//UNUSED2008-05 } +//UNUSED2008-05 pThisTab = pTabData[nTabNo]; +//UNUSED2008-05 CalcPPT(); +//UNUSED2008-05 } +//UNUSED2008-05 +//UNUSED2008-05 void ScViewData::SetDocShell( ScDocShell* pShell ) +//UNUSED2008-05 { +//UNUSED2008-05 pDocShell = pShell; +//UNUSED2008-05 pDoc = pDocShell->GetDocument(); +//UNUSED2008-05 *pOptions = pDoc->GetViewOptions(); +//UNUSED2008-05 CalcPPT(); +//UNUSED2008-05 } + +ScDocument* ScViewData::GetDocument() const +{ + if (pDoc) + return pDoc; + else if (pDocShell) + return pDocShell->GetDocument(); + + DBG_ERROR("kein Document an ViewData"); + return NULL; +} + +ScViewData::~ScViewData() +{ + for (SCTAB i=0; i<=MAXTAB; i++) + if (pTabData[i]) + delete pTabData[i]; + + KillEditView(); + delete pOptions; +} + +void ScViewData::UpdateThis() +{ + do + { + pThisTab = pTabData[nTabNo]; + if (!pThisTab) + { + if (nTabNo>0) + --nTabNo; + else + pThisTab = pTabData[0] = new ScViewDataTable; + + // hier keine Assertion, weil sonst Paints kommen, bevor alles initialisiert ist! + } + } + while (!pThisTab); +} + +void ScViewData::InsertTab( SCTAB nTab ) +{ + delete pTabData[MAXTAB]; + + for (SCTAB i=MAXTAB; i>nTab; i--) + pTabData[i] = pTabData[i-1]; + + pTabData[nTab] = NULL; // force creating new + CreateTabData( nTab ); + + UpdateThis(); + aMarkData.InsertTab( nTab ); +} + +void ScViewData::DeleteTab( SCTAB nTab ) +{ + delete pTabData[nTab]; + + for (SCTAB i=nTab; i<MAXTAB; i++) + pTabData[i] = pTabData[i+1]; + + pTabData[MAXTAB] = NULL; + + UpdateThis(); + aMarkData.DeleteTab( nTab ); +} + +void ScViewData::CopyTab( SCTAB nSrcTab, SCTAB nDestTab ) +{ + if (nDestTab==SC_TAB_APPEND) + nDestTab = pDoc->GetTableCount() - 1; // am Doc muss vorher kopiert worden sein + + if (nDestTab > MAXTAB) + { + DBG_ERROR("Zuviele Tabellen"); + return; + } + + delete pTabData[MAXTAB]; + + for (SCTAB i=MAXTAB; i>nDestTab; i--) + pTabData[i] = pTabData[i-1]; + + if ( pTabData[nSrcTab] ) + pTabData[nDestTab] = new ScViewDataTable( *pTabData[nSrcTab] ); + else + pTabData[nDestTab] = NULL; + + UpdateThis(); + aMarkData.InsertTab( nDestTab ); +} + +void ScViewData::MoveTab( SCTAB nSrcTab, SCTAB nDestTab ) +{ + if (nDestTab==SC_TAB_APPEND) + nDestTab = pDoc->GetTableCount() - 1; + + SCTAB i; + ScViewDataTable* pTab = pTabData[nSrcTab]; + + SCTAB nInsTab = nDestTab; + if ( nSrcTab < nDestTab ) + { + --nInsTab; + for (i=nSrcTab; i<nDestTab; i++) + pTabData[i] = pTabData[i+1]; + } + else + for (i=nSrcTab; i>nDestTab; i--) + pTabData[i] = pTabData[i-1]; + + pTabData[nDestTab] = pTab; + + UpdateThis(); + aMarkData.DeleteTab( nSrcTab ); + aMarkData.InsertTab( nInsTab ); // ggf. angepasst +} + +//UNUSED2008-05 void ScViewData::UpdateOle( ScSplitPos /* eWhich */ ) +//UNUSED2008-05 { +//UNUSED2008-05 GetDocShell()->UpdateOle(this); +//UNUSED2008-05 } + +void ScViewData::SetViewShell( ScTabViewShell* pViewSh ) +{ + if (pViewSh) + { + pViewShell = pViewSh; + pView = pViewSh; + } + else + { + pViewShell = NULL; + pView = NULL; + } +} +void ScViewData::CreateTabData( std::vector< SCTAB >& rvTabs ) +{ + std::vector< SCTAB >::iterator it_end = rvTabs.end(); + for ( std::vector< SCTAB >::iterator it = rvTabs.begin(); it != it_end; ++it ) + if ( !pTabData[*it] ) + CreateTabData( *it ); +} + +void ScViewData::SetZoomType( SvxZoomType eNew, std::vector< SCTAB >& tabs ) +{ + sal_Bool bAll = ( tabs.size() == 0 ); + + if ( !bAll ) // create associated table data + CreateTabData( tabs ); + + if ( bAll ) + { + for ( SCTAB i = 0; i <= MAXTAB; ++i ) + { + if ( pTabData[i] ) + pTabData[i]->eZoomType = eNew; + } + eDefZoomType = eNew; + } + else + { + std::vector< SCTAB >::iterator it_end = tabs.end(); + std::vector< SCTAB >::iterator it = tabs.begin(); + for ( ; it != it_end; ++it ) + { + SCTAB i = *it; + if ( pTabData[i] ) + pTabData[i]->eZoomType = eNew; + } + } +} + +void ScViewData::SetZoomType( SvxZoomType eNew, sal_Bool bAll ) +{ + std::vector< SCTAB > vTabs; // Empty for all tabs + if ( !bAll ) // get selected tabs + { + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB i=0; i<nTabCount; i++) + { + if ( aMarkData.GetTableSelect(i) ) + vTabs.push_back( i ); + } + } + SetZoomType( eNew, vTabs ); +} + +void ScViewData::SetZoom( const Fraction& rNewX, const Fraction& rNewY, std::vector< SCTAB >& tabs ) +{ + sal_Bool bAll = ( tabs.size() == 0 ); + if ( !bAll ) // create associated table data + CreateTabData( tabs ); + Fraction aFrac20( 1,5 ); + Fraction aFrac400( 4,1 ); + + Fraction aValidX = rNewX; + if (aValidX<aFrac20) + aValidX = aFrac20; + if (aValidX>aFrac400) + aValidX = aFrac400; + + Fraction aValidY = rNewY; + if (aValidY<aFrac20) + aValidY = aFrac20; + if (aValidY>aFrac400) + aValidY = aFrac400; + + if ( bAll ) + { + for ( SCTAB i = 0; i <= MAXTAB; ++i ) + { + if ( pTabData[i] ) + { + if ( bPagebreak ) + { + pTabData[i]->aPageZoomX = aValidX; + pTabData[i]->aPageZoomY = aValidY; + } + else + { + pTabData[i]->aZoomX = aValidX; + pTabData[i]->aZoomY = aValidY; + } + } + } + if ( bPagebreak ) + { + aDefPageZoomX = aValidX; + aDefPageZoomY = aValidY; + } + else + { + aDefZoomX = aValidX; + aDefZoomY = aValidY; + } + } + else + { + std::vector< SCTAB >::iterator it_end = tabs.end(); + std::vector< SCTAB >::iterator it = tabs.begin(); + for ( ; it != it_end; ++it ) + { + SCTAB i = *it; + if ( pTabData[i] ) + { + if ( bPagebreak ) + { + pTabData[i]->aPageZoomX = aValidX; + pTabData[i]->aPageZoomY = aValidY; + } + else + { + pTabData[i]->aZoomX = aValidX; + pTabData[i]->aZoomY = aValidY; + } + } + } + } + RefreshZoom(); +} + +void ScViewData::SetZoom( const Fraction& rNewX, const Fraction& rNewY, sal_Bool bAll ) +{ + std::vector< SCTAB > vTabs; + if ( !bAll ) // get selected tabs + { + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB i=0; i<nTabCount; i++) + { + if ( aMarkData.GetTableSelect(i) ) + vTabs.push_back( i ); + } + } + SetZoom( rNewX, rNewY, vTabs ); +} + +void ScViewData::RefreshZoom() +{ + // recalculate zoom-dependent values (only for current sheet) + + CalcPPT(); + RecalcPixPos(); + aScenButSize = Size(0,0); + aLogicMode.SetScaleX( GetZoomX() ); + aLogicMode.SetScaleY( GetZoomY() ); +} + +void ScViewData::SetPagebreakMode( sal_Bool bSet ) +{ + bPagebreak = bSet; + + RefreshZoom(); +} + + +ScMarkType ScViewData::GetSimpleArea( ScRange & rRange, ScMarkData & rNewMark ) const +{ + ScMarkType eMarkType = SC_MARK_NONE; + + if ( rNewMark.IsMarked() || rNewMark.IsMultiMarked() ) + { + if ( rNewMark.IsMultiMarked() ) + rNewMark.MarkToSimple(); + + if ( rNewMark.IsMarked() && !rNewMark.IsMultiMarked() ) + { + rNewMark.GetMarkArea( rRange ); + if (ScViewUtil::HasFiltered( rRange, GetDocument())) + eMarkType = SC_MARK_SIMPLE_FILTERED; + else + eMarkType = SC_MARK_SIMPLE; + } + else + eMarkType = SC_MARK_MULTI; + } + if (eMarkType != SC_MARK_SIMPLE && eMarkType != SC_MARK_SIMPLE_FILTERED) + { + if (eMarkType == SC_MARK_NONE) + eMarkType = SC_MARK_SIMPLE; + rRange = ScRange( GetCurX(), GetCurY(), GetTabNo() ); + } + return eMarkType; +} + + +ScMarkType ScViewData::GetSimpleArea( SCCOL& rStartCol, SCROW& rStartRow, SCTAB& rStartTab, + SCCOL& rEndCol, SCROW& rEndRow, SCTAB& rEndTab ) const +{ + // parameter bMergeMark is no longer needed: The view's selection is never modified + // (a local copy is used), and a multi selection that adds to a single range can always + // be treated like a single selection (#108266# - GetSimpleArea isn't used in selection + // handling itself) + + ScRange aRange; + ScMarkData aNewMark( aMarkData ); // use a local copy for MarkToSimple + ScMarkType eMarkType = GetSimpleArea( aRange, aNewMark); + aRange.GetVars( rStartCol, rStartRow, rStartTab, rEndCol, rEndRow, rEndTab); + return eMarkType; +} + +ScMarkType ScViewData::GetSimpleArea( ScRange& rRange ) const +{ + // parameter bMergeMark is no longer needed, see above + + ScMarkData aNewMark( aMarkData ); // use a local copy for MarkToSimple + return GetSimpleArea( rRange, aNewMark); +} + +void ScViewData::GetMultiArea( ScRangeListRef& rRange ) const +{ + // parameter bMergeMark is no longer needed, see GetSimpleArea + + ScMarkData aNewMark( aMarkData ); // use a local copy for MarkToSimple + + sal_Bool bMulti = aNewMark.IsMultiMarked(); + if (bMulti) + { + aNewMark.MarkToSimple(); + bMulti = aNewMark.IsMultiMarked(); + } + if (bMulti) + { + rRange = new ScRangeList; + aNewMark.FillRangeListWithMarks( rRange, sal_False ); + } + else + { + ScRange aSimple; + GetSimpleArea(aSimple); + rRange = new ScRangeList; + rRange->Append(aSimple); + } +} + +sal_Bool ScViewData::SimpleColMarked() +{ + SCCOL nStartCol; + SCROW nStartRow; + SCTAB nStartTab; + SCCOL nEndCol; + SCROW nEndRow; + SCTAB nEndTab; + if (GetSimpleArea(nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab) == SC_MARK_SIMPLE) + if (nStartRow==0 && nEndRow==MAXROW) + return sal_True; + + return sal_False; +} + +sal_Bool ScViewData::SimpleRowMarked() +{ + SCCOL nStartCol; + SCROW nStartRow; + SCTAB nStartTab; + SCCOL nEndCol; + SCROW nEndRow; + SCTAB nEndTab; + if (GetSimpleArea(nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab) == SC_MARK_SIMPLE) + if (nStartCol==0 && nEndCol==MAXCOL) + return sal_True; + + return sal_False; +} + +sal_Bool ScViewData::IsMultiMarked() +{ + // Test for "real" multi selection, calling MarkToSimple on a local copy, + // and taking filtered in simple area marks into account. + + ScRange aDummy; + ScMarkType eType = GetSimpleArea(aDummy); + return (eType & SC_MARK_SIMPLE) != SC_MARK_SIMPLE; +} + +void ScViewData::SetFillMode( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow ) +{ + nFillMode = SC_FILL_FILL; + nFillStartX = nStartCol; + nFillStartY = nStartRow; + nFillEndX = nEndCol; + nFillEndY = nEndRow; +} + +void ScViewData::SetDragMode( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, + sal_uInt8 nMode ) +{ + nFillMode = nMode; + nFillStartX = nStartCol; + nFillStartY = nStartRow; + nFillEndX = nEndCol; + nFillEndY = nEndRow; +} + +void ScViewData::ResetFillMode() +{ + nFillMode = SC_FILL_NONE; +} + +void ScViewData::GetFillData( SCCOL& rStartCol, SCROW& rStartRow, + SCCOL& rEndCol, SCROW& rEndRow ) +{ + rStartCol = nFillStartX; + rStartRow = nFillStartY; + rEndCol = nFillEndX; + rEndRow = nFillEndY; +} + +SCCOL ScViewData::GetOldCurX() const +{ + if (pThisTab->bOldCurValid) + return pThisTab->nOldCurX; + else + return pThisTab->nCurX; +} + +SCROW ScViewData::GetOldCurY() const +{ + if (pThisTab->bOldCurValid) + return pThisTab->nOldCurY; + else + return pThisTab->nCurY; +} + +void ScViewData::SetOldCursor( SCCOL nNewX, SCROW nNewY ) +{ + pThisTab->nOldCurX = nNewX; + pThisTab->nOldCurY = nNewY; + pThisTab->bOldCurValid = sal_True; +} + +void ScViewData::ResetOldCursor() +{ + pThisTab->bOldCurValid = sal_False; +} + +Rectangle ScViewData::GetEditArea( ScSplitPos eWhich, SCCOL nPosX, SCROW nPosY, + Window* pWin, const ScPatternAttr* pPattern, + sal_Bool bForceToTop ) +{ + return ScEditUtil( pDoc, nPosX, nPosY, nTabNo, GetScrPos(nPosX,nPosY,eWhich,sal_True), + pWin, nPPTX, nPPTY, GetZoomX(), GetZoomY() ). + GetEditArea( pPattern, bForceToTop ); +} + +void ScViewData::SetEditEngine( ScSplitPos eWhich, + ScEditEngineDefaulter* pNewEngine, + Window* pWin, SCCOL nNewX, SCROW nNewY ) +{ + sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTabNo ); + ScHSplitPos eHWhich = WhichH(eWhich); + + sal_Bool bWasThere = sal_False; + if (pEditView[eWhich]) + { + // Wenn die View schon da ist, nichts aufrufen, was die Cursorposition aendert + + if (bEditActive[eWhich]) + bWasThere = sal_True; + else + pEditView[eWhich]->SetEditEngine(pNewEngine); + + if (pEditView[eWhich]->GetWindow() != pWin) + { + pEditView[eWhich]->SetWindow(pWin); + DBG_ERROR("EditView Window geaendert"); + } + } + else + { + pEditView[eWhich] = new EditView( pNewEngine, pWin ); + } + + // bei IdleFormat wird manchmal ein Cursor gemalt, wenn die View schon weg ist (23576) + + sal_uLong nEC = pNewEngine->GetControlWord(); + pNewEngine->SetControlWord(nEC & ~EE_CNTRL_DOIDLEFORMAT); + + sal_uLong nVC = pEditView[eWhich]->GetControlWord(); + pEditView[eWhich]->SetControlWord(nVC & ~EV_CNTRL_AUTOSCROLL); + + bEditActive[eWhich] = sal_True; + + const ScPatternAttr* pPattern = pDoc->GetPattern( nNewX, nNewY, nTabNo ); + SvxCellHorJustify eJust = (SvxCellHorJustify)((const SvxHorJustifyItem&) + pPattern->GetItem( ATTR_HOR_JUSTIFY )).GetValue(); + + sal_Bool bBreak = ( eJust == SVX_HOR_JUSTIFY_BLOCK ) || + ((SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK)).GetValue(); + + sal_Bool bAsianVertical = pNewEngine->IsVertical(); // set by InputHandler + + Rectangle aPixRect = ScEditUtil( pDoc, nNewX,nNewY,nTabNo, GetScrPos(nNewX,nNewY,eWhich), + pWin, nPPTX,nPPTY,GetZoomX(),GetZoomY() ). + GetEditArea( pPattern, sal_True ); + + // when right-aligned, leave space for the cursor + // in vertical mode, editing is always right-aligned + if ( nEditAdjust == SVX_ADJUST_RIGHT || bAsianVertical ) + aPixRect.Right() += 1; + + Rectangle aOutputArea = pWin->PixelToLogic( aPixRect, GetLogicMode() ); + pEditView[eWhich]->SetOutputArea( aOutputArea ); + + if ( bActive && eWhich == GetActivePart() ) + { + // keep the part that has the active edit view available after + // switching sheets or reference input on a different part + eEditActivePart = eWhich; + + // modify members nEditCol etc. only if also extending for needed area + nEditCol = nNewX; + nEditRow = nNewY; + const ScMergeAttr* pMergeAttr = (ScMergeAttr*)&pPattern->GetItem(ATTR_MERGE); + nEditEndCol = nEditCol; + if (pMergeAttr->GetColMerge() > 1) + nEditEndCol += pMergeAttr->GetColMerge() - 1; + nEditEndRow = nEditRow; + if (pMergeAttr->GetRowMerge() > 1) + nEditEndRow += pMergeAttr->GetRowMerge() - 1; + nEditStartCol = nEditCol; + + // For growing use only the alignment value from the attribute, numbers + // (existing or started) with default aligment extend to the right. + sal_Bool bGrowCentered = ( eJust == SVX_HOR_JUSTIFY_CENTER ); + sal_Bool bGrowToLeft = ( eJust == SVX_HOR_JUSTIFY_RIGHT ); // visual left + sal_Bool bGrowBackwards = bGrowToLeft; // logical left + if ( bLayoutRTL ) + bGrowBackwards = !bGrowBackwards; // invert on RTL sheet + if ( bAsianVertical ) + bGrowCentered = bGrowToLeft = bGrowBackwards = sal_False; // keep old behavior for asian mode + + long nSizeXPix; + if (bBreak && !bAsianVertical) + nSizeXPix = aPixRect.GetWidth(); // Papersize -> kein H-Scrolling + else + { + DBG_ASSERT(pView,"keine View fuer EditView"); + + if ( bGrowCentered ) + { + // growing into both directions until one edge is reached + //! should be limited to whole cells in both directions + long nLeft = aPixRect.Left(); + long nRight = pView->GetGridWidth(eHWhich) - aPixRect.Right(); + nSizeXPix = aPixRect.GetWidth() + 2 * Min( nLeft, nRight ); + } + else if ( bGrowToLeft ) + nSizeXPix = aPixRect.Right(); // space that's available in the window when growing to the left + else + nSizeXPix = pView->GetGridWidth(eHWhich) - aPixRect.Left(); + + if ( nSizeXPix <= 0 ) + nSizeXPix = aPixRect.GetWidth(); // editing outside to the right of the window -> keep cell width + } + DBG_ASSERT(pView,"keine View fuer EditView"); + long nSizeYPix = pView->GetGridHeight(WhichV(eWhich)) - aPixRect.Top(); + if ( nSizeYPix <= 0 ) + nSizeYPix = aPixRect.GetHeight(); // editing outside below the window -> keep cell height + + Size aPaperSize = pView->GetActiveWin()->PixelToLogic( Size( nSizeXPix, nSizeYPix ), GetLogicMode() ); + if ( bBreak && !bAsianVertical && SC_MOD()->GetInputOptions().GetTextWysiwyg() ) + { + // #95593# if text is formatted for printer, use the exact same paper width + // (and same line breaks) as for output. + + Fraction aFract(1,1); + Rectangle aUtilRect = ScEditUtil( pDoc,nNewX,nNewY,nTabNo, Point(0,0), pWin, + HMM_PER_TWIPS, HMM_PER_TWIPS, aFract, aFract ).GetEditArea( pPattern, sal_False ); + aPaperSize.Width() = aUtilRect.GetWidth(); + } + pNewEngine->SetPaperSize( aPaperSize ); + + // sichtbarer Ausschnitt + Size aPaper = pNewEngine->GetPaperSize(); + Rectangle aVis = pEditView[eWhich]->GetVisArea(); + long nDiff = aVis.Right() - aVis.Left(); + if ( nEditAdjust == SVX_ADJUST_RIGHT ) + { + aVis.Right() = aPaper.Width() - 1; + bMoveArea = !bLayoutRTL; + } + else if ( nEditAdjust == SVX_ADJUST_CENTER ) + { + aVis.Right() = ( aPaper.Width() - 1 + nDiff ) / 2; + bMoveArea = sal_True; // always + } + else + { + aVis.Right() = nDiff; + bMoveArea = bLayoutRTL; + } + aVis.Left() = aVis.Right() - nDiff; + // --> OD 2005-12-22 #i49561# + // Important note: + // The set offset of the visible area of the EditView for centered and + // right alignment in horizontal layout is consider by instances of + // class <ScEditObjectViewForwarder> in its methods <LogicToPixel(..)> + // and <PixelToLogic(..)>. This is needed for the correct visibility + // of paragraphs in edit mode at the accessibility API. + // <-- + pEditView[eWhich]->SetVisArea(aVis); + // + + // UpdateMode has been disabled in ScInputHandler::StartTable + // must be enabled before EditGrowY (GetTextHeight) + pNewEngine->SetUpdateMode( sal_True ); + + pNewEngine->SetStatusEventHdl( LINK( this, ScViewData, EditEngineHdl ) ); + + EditGrowY( sal_True ); // adjust to existing text content + EditGrowX(); + + Point aDocPos = pEditView[eWhich]->GetWindowPosTopLeft(0); + if (aDocPos.Y() < aOutputArea.Top()) + pEditView[eWhich]->Scroll( 0, aOutputArea.Top() - aDocPos.Y() ); + + //! Status (Event) zuruecksetzen + } + + // hier muss bEditActive schon gesetzt sein + // (wegen Map-Mode bei Paint) + if (!bWasThere) + pNewEngine->InsertView(pEditView[eWhich]); + + // Hintergrundfarbe der Zelle + Color aBackCol = ((const SvxBrushItem&)pPattern->GetItem(ATTR_BACKGROUND)).GetColor(); + + ScModule* pScMod = SC_MOD(); + // #105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed sal_True) + if ( aBackCol.GetTransparency() > 0 || + Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) + { + aBackCol.SetColor( pScMod->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor ); + } + pEditView[eWhich]->SetBackgroundColor( aBackCol ); + + pEditView[eWhich]->Invalidate(); // noetig ?? + // noetig, wenn Position geaendert +} + +IMPL_LINK_INLINE_START( ScViewData, EmptyEditHdl, EditStatus *, EMPTYARG ) +{ + return 0; +} +IMPL_LINK_INLINE_END( ScViewData, EmptyEditHdl, EditStatus *, EMPTYARG ) + +IMPL_LINK( ScViewData, EditEngineHdl, EditStatus *, pStatus ) +{ + sal_uLong nStatus = pStatus->GetStatusWord(); + if (nStatus & (EE_STAT_HSCROLL | EE_STAT_TEXTHEIGHTCHANGED | EE_STAT_TEXTWIDTHCHANGED | EE_STAT_CURSOROUT)) + { + EditGrowY(); + EditGrowX(); + + if (nStatus & EE_STAT_CURSOROUT) + { + ScSplitPos eWhich = GetActivePart(); + if (pEditView[eWhich]) + pEditView[eWhich]->ShowCursor(sal_False); + } + } + return 0; +} + +void ScViewData::EditGrowX() +{ + ScDocument* pLocalDoc = GetDocument(); + + ScSplitPos eWhich = GetActivePart(); + ScHSplitPos eHWhich = WhichH(eWhich); + EditView* pCurView = pEditView[eWhich]; + + if ( !pCurView || !bEditActive[eWhich]) + return; + + sal_Bool bLayoutRTL = pLocalDoc->IsLayoutRTL( nTabNo ); + + ScEditEngineDefaulter* pEngine = + (ScEditEngineDefaulter*) pCurView->GetEditEngine(); + Window* pWin = pCurView->GetWindow(); + + SCCOL nLeft = GetPosX(eHWhich); + SCCOL nRight = nLeft + VisibleCellsX(eHWhich); + + Size aSize = pEngine->GetPaperSize(); + Rectangle aArea = pCurView->GetOutputArea(); + long nOldRight = aArea.Right(); + + // Margin ist schon bei der urspruenglichen Breite beruecksichtigt + long nTextWidth = pEngine->CalcTextWidth(); + + sal_Bool bChanged = sal_False; + sal_Bool bAsianVertical = pEngine->IsVertical(); + + // get bGrow... variables the same way as in SetEditEngine + const ScPatternAttr* pPattern = pLocalDoc->GetPattern( nEditCol, nEditRow, nTabNo ); + SvxCellHorJustify eJust = (SvxCellHorJustify)((const SvxHorJustifyItem&) + pPattern->GetItem( ATTR_HOR_JUSTIFY )).GetValue(); + sal_Bool bGrowCentered = ( eJust == SVX_HOR_JUSTIFY_CENTER ); + sal_Bool bGrowToLeft = ( eJust == SVX_HOR_JUSTIFY_RIGHT ); // visual left + sal_Bool bGrowBackwards = bGrowToLeft; // logical left + if ( bLayoutRTL ) + bGrowBackwards = !bGrowBackwards; // invert on RTL sheet + if ( bAsianVertical ) + bGrowCentered = bGrowToLeft = bGrowBackwards = sal_False; // keep old behavior for asian mode + + sal_Bool bUnevenGrow = sal_False; + if ( bGrowCentered ) + { + while (aArea.GetWidth() + 0 < nTextWidth && ( nEditStartCol > nLeft || nEditEndCol < nRight ) ) + { + long nLogicLeft = 0; + if ( nEditStartCol > nLeft ) + { + --nEditStartCol; + long nLeftPix = ToPixel( pLocalDoc->GetColWidth( nEditStartCol, nTabNo ), nPPTX ); + nLogicLeft = pWin->PixelToLogic(Size(nLeftPix,0)).Width(); + } + long nLogicRight = 0; + if ( nEditEndCol < nRight ) + { + ++nEditEndCol; + long nRightPix = ToPixel( pLocalDoc->GetColWidth( nEditEndCol, nTabNo ), nPPTX ); + nLogicRight = pWin->PixelToLogic(Size(nRightPix,0)).Width(); + } + + aArea.Left() -= bLayoutRTL ? nLogicRight : nLogicLeft; + aArea.Right() += bLayoutRTL ? nLogicLeft : nLogicRight; + + if ( aArea.Right() > aArea.Left() + aSize.Width() - 1 ) + { + long nCenter = ( aArea.Left() + aArea.Right() ) / 2; + long nHalf = aSize.Width() / 2; + aArea.Left() = nCenter - nHalf + 1; + aArea.Right() = nCenter + aSize.Width() - nHalf - 1; + } + + bChanged = sal_True; + if ( nLogicLeft != nLogicRight ) + bUnevenGrow = sal_True; + } + } + else if ( bGrowBackwards ) + { + while (aArea.GetWidth() + 0 < nTextWidth && nEditStartCol > nLeft) + { + --nEditStartCol; + long nPix = ToPixel( pLocalDoc->GetColWidth( nEditStartCol, nTabNo ), nPPTX ); + long nLogicWidth = pWin->PixelToLogic(Size(nPix,0)).Width(); + if ( !bLayoutRTL ) + aArea.Left() -= nLogicWidth; + else + aArea.Right() += nLogicWidth; + + if ( aArea.Right() > aArea.Left() + aSize.Width() - 1 ) + { + if ( !bLayoutRTL ) + aArea.Left() = aArea.Right() - aSize.Width() + 1; + else + aArea.Right() = aArea.Left() + aSize.Width() - 1; + } + + bChanged = sal_True; + } + } + else + { + while (aArea.GetWidth() + 0 < nTextWidth && nEditEndCol < nRight) + { + ++nEditEndCol; + long nPix = ToPixel( pLocalDoc->GetColWidth( nEditEndCol, nTabNo ), nPPTX ); + long nLogicWidth = pWin->PixelToLogic(Size(nPix,0)).Width(); + if ( bLayoutRTL ) + aArea.Left() -= nLogicWidth; + else + aArea.Right() += nLogicWidth; + + if ( aArea.Right() > aArea.Left() + aSize.Width() - 1 ) + { + if ( bLayoutRTL ) + aArea.Left() = aArea.Right() - aSize.Width() + 1; + else + aArea.Right() = aArea.Left() + aSize.Width() - 1; + } + + bChanged = sal_True; + } + } + + if (bChanged) + { + if ( bMoveArea || bGrowCentered || bGrowBackwards || bLayoutRTL ) + { + Rectangle aVis = pCurView->GetVisArea(); + + if ( bGrowCentered ) + { + // switch to center-aligned (undo?) and reset VisArea to center + + pEngine->SetDefaultItem( SvxAdjustItem( SVX_ADJUST_CENTER, EE_PARA_JUST ) ); + + long nCenter = aSize.Width() / 2; + long nVisSize = aArea.GetWidth(); + aVis.Left() = nCenter - nVisSize / 2; + aVis.Right() = aVis.Left() + nVisSize - 1; + } + else if ( bGrowToLeft ) + { + // switch to right-aligned (undo?) and reset VisArea to the right + + pEngine->SetDefaultItem( SvxAdjustItem( SVX_ADJUST_RIGHT, EE_PARA_JUST ) ); + + aVis.Right() = aSize.Width() - 1; + aVis.Left() = aSize.Width() - aArea.GetWidth(); // with the new, increased area + } + else + { + // switch to left-aligned (undo?) and reset VisArea to the left + + pEngine->SetDefaultItem( SvxAdjustItem( SVX_ADJUST_LEFT, EE_PARA_JUST ) ); + + long nMove = aVis.Left(); + aVis.Left() = 0; + aVis.Right() -= nMove; + } + pCurView->SetVisArea( aVis ); + bMoveArea = sal_False; + } + + pCurView->SetOutputArea(aArea); + + // In vertical mode, the whole text is moved to the next cell (right-aligned), + // so everything must be repainted. Otherwise, paint only the new area. + // If growing in centered alignment, if the cells left and right have different sizes, + // the whole text will move, and may not even obscure all of the original display. + if ( bUnevenGrow ) + { + aArea.Left() = pWin->PixelToLogic( Point(0,0) ).X(); + aArea.Right() = pWin->PixelToLogic( aScrSize ).Width(); + } + else if ( !bAsianVertical && !bGrowToLeft && !bGrowCentered ) + aArea.Left() = nOldRight; + pWin->Invalidate(aArea); + } +} + +void ScViewData::EditGrowY( sal_Bool bInitial ) +{ + ScSplitPos eWhich = GetActivePart(); + ScVSplitPos eVWhich = WhichV(eWhich); + EditView* pCurView = pEditView[eWhich]; + + if ( !pCurView || !bEditActive[eWhich]) + return; + + sal_uLong nControl = pEditView[eWhich]->GetControlWord(); + if ( nControl & EV_CNTRL_AUTOSCROLL ) + { + // if end of screen had already been reached and scrolling enabled, + // don't further try to grow the edit area + + pCurView->SetOutputArea( pCurView->GetOutputArea() ); // re-align to pixels + return; + } + + EditEngine* pEngine = pCurView->GetEditEngine(); + Window* pWin = pCurView->GetWindow(); + + SCROW nBottom = GetPosY(eVWhich) + VisibleCellsY(eVWhich); + + Size aSize = pEngine->GetPaperSize(); + Rectangle aArea = pCurView->GetOutputArea(); + long nOldBottom = aArea.Bottom(); + long nTextHeight = pEngine->GetTextHeight(); + + // #106635# When editing a formula in a cell with optimal height, allow a larger portion + // to be clipped before extending to following rows, to avoid obscuring cells for + // reference input (next row is likely to be useful in formulas). + long nAllowedExtra = SC_GROWY_SMALL_EXTRA; + if ( nEditEndRow == nEditRow && !( pDoc->GetRowFlags( nEditRow, nTabNo ) & CR_MANUALSIZE ) && + pEngine->GetParagraphCount() <= 1 ) + { + // If the (only) paragraph starts with a '=', it's a formula. + // If this is the initial call and the text is empty, allow the larger value, too, + // because this occurs in the normal progress of editing a formula. + // Subsequent calls with empty text might involve changed attributes (including + // font height), so they are treated like normal text. + String aText = pEngine->GetText( (sal_uInt16) 0 ); + if ( ( aText.Len() == 0 && bInitial ) || aText.GetChar(0) == (sal_Unicode)'=' ) + nAllowedExtra = SC_GROWY_BIG_EXTRA; + } + + sal_Bool bChanged = sal_False; + sal_Bool bMaxReached = sal_False; + while (aArea.GetHeight() + nAllowedExtra < nTextHeight && nEditEndRow < nBottom && !bMaxReached) + { + ++nEditEndRow; + ScDocument* pLocalDoc = GetDocument(); + long nPix = ToPixel( pLocalDoc->GetRowHeight( nEditEndRow, nTabNo ), nPPTY ); + aArea.Bottom() += pWin->PixelToLogic(Size(0,nPix)).Height(); + + if ( aArea.Bottom() > aArea.Top() + aSize.Height() - 1 ) + { + aArea.Bottom() = aArea.Top() + aSize.Height() - 1; + bMaxReached = sal_True; // don't occupy more cells beyond paper size + } + + bChanged = sal_True; + nAllowedExtra = SC_GROWY_SMALL_EXTRA; // larger value is only for first row + } + + if (bChanged) + { + pCurView->SetOutputArea(aArea); + + if (nEditEndRow >= nBottom || bMaxReached) + { + if ((nControl & EV_CNTRL_AUTOSCROLL) == 0) + pCurView->SetControlWord( nControl | EV_CNTRL_AUTOSCROLL ); + } + + aArea.Top() = nOldBottom; + pWin->Invalidate(aArea); + } +} + +void ScViewData::ResetEditView() +{ + EditEngine* pEngine = NULL; + for (sal_uInt16 i=0; i<4; i++) + if (pEditView[i]) + { + if (bEditActive[i]) + { + pEngine = pEditView[i]->GetEditEngine(); + pEngine->RemoveView(pEditView[i]); + pEditView[i]->SetOutputArea( Rectangle() ); + } + bEditActive[i] = sal_False; + } + + if (pEngine) + pEngine->SetStatusEventHdl( LINK( this, ScViewData, EmptyEditHdl ) ); +} + +void ScViewData::KillEditView() +{ + for (sal_uInt16 i=0; i<4; i++) + if (pEditView[i]) + { + if (bEditActive[i]) + pEditView[i]->GetEditEngine()->RemoveView(pEditView[i]); + delete pEditView[i]; + pEditView[i] = NULL; + } +} + +void ScViewData::GetEditView( ScSplitPos eWhich, EditView*& rViewPtr, SCCOL& rCol, SCROW& rRow ) +{ + rViewPtr = pEditView[eWhich]; + rCol = nEditCol; + rRow = nEditRow; +} + +void ScViewData::CreateTabData( SCTAB nNewTab ) +{ + if (!pTabData[nNewTab]) + { + pTabData[nNewTab] = new ScViewDataTable; + + pTabData[nNewTab]->eZoomType = eDefZoomType; + pTabData[nNewTab]->aZoomX = aDefZoomX; + pTabData[nNewTab]->aZoomY = aDefZoomY; + pTabData[nNewTab]->aPageZoomX = aDefPageZoomX; + pTabData[nNewTab]->aPageZoomY = aDefPageZoomY; + } +} + +void ScViewData::CreateSelectedTabData() +{ + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB i=0; i<nTabCount; i++) + if ( aMarkData.GetTableSelect(i) && !pTabData[i] ) + CreateTabData( i ); +} + +void ScViewData::SetTabNo( SCTAB nNewTab ) +{ + if (!ValidTab(nNewTab)) + { + DBG_ERROR("falsche Tabellennummer"); + return; + } + + nTabNo = nNewTab; + CreateTabData(nTabNo); + pThisTab = pTabData[nTabNo]; + + CalcPPT(); // for common column width correction + RecalcPixPos(); //! nicht immer noetig! +} + +void ScViewData::SetActivePart( ScSplitPos eNewActive ) +{ + pThisTab->eWhichActive = eNewActive; +} + +Point ScViewData::GetScrPos( SCCOL nWhereX, SCROW nWhereY, ScHSplitPos eWhich ) const +{ + DBG_ASSERT( eWhich==SC_SPLIT_LEFT || eWhich==SC_SPLIT_RIGHT, "Falsche Position" ); + ScSplitPos ePos = ( eWhich == SC_SPLIT_LEFT ) ? SC_SPLIT_BOTTOMLEFT : SC_SPLIT_BOTTOMRIGHT; + return GetScrPos( nWhereX, nWhereY, ePos ); +} + +Point ScViewData::GetScrPos( SCCOL nWhereX, SCROW nWhereY, ScVSplitPos eWhich ) const +{ + DBG_ASSERT( eWhich==SC_SPLIT_TOP || eWhich==SC_SPLIT_BOTTOM, "Falsche Position" ); + ScSplitPos ePos = ( eWhich == SC_SPLIT_TOP ) ? SC_SPLIT_TOPLEFT : SC_SPLIT_BOTTOMLEFT; + return GetScrPos( nWhereX, nWhereY, ePos ); +} + +Point ScViewData::GetScrPos( SCCOL nWhereX, SCROW nWhereY, ScSplitPos eWhich, + sal_Bool bAllowNeg ) const +{ + ScHSplitPos eWhichX = SC_SPLIT_LEFT; + ScVSplitPos eWhichY = SC_SPLIT_BOTTOM; + switch( eWhich ) + { + case SC_SPLIT_TOPLEFT: + eWhichX = SC_SPLIT_LEFT; + eWhichY = SC_SPLIT_TOP; + break; + case SC_SPLIT_TOPRIGHT: + eWhichX = SC_SPLIT_RIGHT; + eWhichY = SC_SPLIT_TOP; + break; + case SC_SPLIT_BOTTOMLEFT: + eWhichX = SC_SPLIT_LEFT; + eWhichY = SC_SPLIT_BOTTOM; + break; + case SC_SPLIT_BOTTOMRIGHT: + eWhichX = SC_SPLIT_RIGHT; + eWhichY = SC_SPLIT_BOTTOM; + break; + } + + if (pView) + { + ((ScViewData*)this)->aScrSize.Width() = pView->GetGridWidth(eWhichX); + ((ScViewData*)this)->aScrSize.Height() = pView->GetGridHeight(eWhichY); + } + + sal_uInt16 nTSize; + + SCCOL nPosX = GetPosX(eWhichX); + SCCOL nX; + + long nScrPosX=0; + if (nWhereX >= nPosX) + for (nX=nPosX; nX<nWhereX && (bAllowNeg || nScrPosX<=aScrSize.Width()); nX++) + { + if ( nX > MAXCOL ) + nScrPosX = 65535; + else + { + nTSize = pDoc->GetColWidth( nX, nTabNo ); + if (nTSize) + { + long nSizeXPix = ToPixel( nTSize, nPPTX ); + nScrPosX += nSizeXPix; + } + } + } + else if (bAllowNeg) + for (nX=nPosX; nX>nWhereX;) + { + --nX; + nTSize = pDoc->GetColWidth( nX, nTabNo ); + if (nTSize) + { + long nSizeXPix = ToPixel( nTSize, nPPTX ); + nScrPosX -= nSizeXPix; + } + } + + SCROW nPosY = GetPosY(eWhichY); + SCROW nY; + + long nScrPosY=0; + if (nWhereY >= nPosY) + for (nY=nPosY; nY<nWhereY && (bAllowNeg || nScrPosY<=aScrSize.Height()); nY++) + { + if ( nY > MAXROW ) + nScrPosY = 65535; + else + { + nTSize = pDoc->GetRowHeight( nY, nTabNo ); + if (nTSize) + { + long nSizeYPix = ToPixel( nTSize, nPPTY ); + nScrPosY += nSizeYPix; + } + else if ( nY < MAXROW ) + { + // skip multiple hidden rows (forward only for now) + SCROW nNext = pDoc->FirstVisibleRow(nY + 1, MAXROW, nTabNo); + if ( nNext > MAXROW ) + nY = MAXROW; + else + nY = nNext - 1; // +=nDir advances to next visible row + } + } + } + else if (bAllowNeg) + for (nY=nPosY; nY>nWhereY;) + { + --nY; + nTSize = pDoc->GetRowHeight( nY, nTabNo ); + if (nTSize) + { + long nSizeYPix = ToPixel( nTSize, nPPTY ); + nScrPosY -= nSizeYPix; + } + } + + if ( pDoc->IsLayoutRTL( nTabNo ) ) + { + // mirror horizontal position + nScrPosX = aScrSize.Width() - 1 - nScrPosX; + } + + if (nScrPosX > 32767) nScrPosX=32767; + if (nScrPosY > 32767) nScrPosY=32767; + return Point( nScrPosX, nScrPosY ); +} + +// +// Anzahl Zellen auf einem Bildschirm +// + +SCCOL ScViewData::CellsAtX( SCsCOL nPosX, SCsCOL nDir, ScHSplitPos eWhichX, sal_uInt16 nScrSizeX ) const +{ + DBG_ASSERT( nDir==1 || nDir==-1, "falscher CellsAt Aufruf" ); + + if (pView) + ((ScViewData*)this)->aScrSize.Width() = pView->GetGridWidth(eWhichX); + + SCsCOL nX; + sal_uInt16 nScrPosX = 0; + if (nScrSizeX == SC_SIZE_NONE) nScrSizeX = (sal_uInt16) aScrSize.Width(); + + if (nDir==1) + nX = nPosX; // vorwaerts + else + nX = nPosX-1; // rueckwaerts + + sal_Bool bOut = sal_False; + for ( ; nScrPosX<=nScrSizeX && !bOut; nX = sal::static_int_cast<SCsCOL>(nX + nDir) ) + { + SCsCOL nColNo = nX; + if ( nColNo < 0 || nColNo > MAXCOL ) + bOut = sal_True; + else + { + sal_uInt16 nTSize = pDoc->GetColWidth( nColNo, nTabNo ); + if (nTSize) + { + long nSizeXPix = ToPixel( nTSize, nPPTX ); + nScrPosX = sal::static_int_cast<sal_uInt16>( nScrPosX + (sal_uInt16) nSizeXPix ); + } + } + } + + if (nDir==1) + nX = sal::static_int_cast<SCsCOL>( nX - nPosX ); + else + nX = (nPosX-1)-nX; + + if (nX>0) --nX; + return nX; +} + +SCROW ScViewData::CellsAtY( SCsROW nPosY, SCsROW nDir, ScVSplitPos eWhichY, sal_uInt16 nScrSizeY ) const +{ + DBG_ASSERT( nDir==1 || nDir==-1, "falscher CellsAt Aufruf" ); + + if (pView) + ((ScViewData*)this)->aScrSize.Height() = pView->GetGridHeight(eWhichY); + + if (nScrSizeY == SC_SIZE_NONE) nScrSizeY = (sal_uInt16) aScrSize.Height(); + + SCROW nY; + + if (nDir==1) + { + // forward + nY = nPosY; + long nScrPosY = 0; + AddPixelsWhile( nScrPosY, nScrSizeY, nY, MAXROW, nPPTY, pDoc, nTabNo); + // Original loop ended on last evaluated +1 or if that was MAXROW even + // on MAXROW+2. + nY += (nY == MAXROW ? 2 : 1); + nY -= nPosY; + } + else + { + // backward + nY = nPosY-1; + long nScrPosY = 0; + AddPixelsWhileBackward( nScrPosY, nScrSizeY, nY, 0, nPPTY, pDoc, nTabNo); + // Original loop ended on last evaluated -1 or if that was 0 even on + // -2. + nY -= (nY == 0 ? 2 : 1); + nY = (nPosY-1)-nY; + } + + if (nY>0) --nY; + return nY; +} + +SCCOL ScViewData::VisibleCellsX( ScHSplitPos eWhichX ) const +{ + return CellsAtX( GetPosX( eWhichX ), 1, eWhichX, SC_SIZE_NONE ); +} + +SCROW ScViewData::VisibleCellsY( ScVSplitPos eWhichY ) const +{ + return CellsAtY( GetPosY( eWhichY ), 1, eWhichY, SC_SIZE_NONE ); +} + +SCCOL ScViewData::PrevCellsX( ScHSplitPos eWhichX ) const +{ + return CellsAtX( GetPosX( eWhichX ), -1, eWhichX, SC_SIZE_NONE ); +} + +SCROW ScViewData::PrevCellsY( ScVSplitPos eWhichY ) const +{ + return CellsAtY( GetPosY( eWhichY ), -1, eWhichY, SC_SIZE_NONE ); +} + +//UNUSED2008-05 SCCOL ScViewData::LastCellsX( ScHSplitPos eWhichX ) const +//UNUSED2008-05 { +//UNUSED2008-05 return CellsAtX( MAXCOL+1, -1, eWhichX, SC_SIZE_NONE ); +//UNUSED2008-05 } +//UNUSED2008-05 +//UNUSED2008-05 SCROW ScViewData::LastCellsY( ScVSplitPos eWhichY ) const +//UNUSED2008-05 { +//UNUSED2008-05 return CellsAtY( MAXROW+1, -1, eWhichY, SC_SIZE_NONE ); +//UNUSED2008-05 } + +sal_Bool ScViewData::GetMergeSizePixel( SCCOL nX, SCROW nY, long& rSizeXPix, long& rSizeYPix ) +{ + const ScMergeAttr* pMerge = (const ScMergeAttr*) pDoc->GetAttr( nX,nY,nTabNo, ATTR_MERGE ); + if ( pMerge->GetColMerge() > 1 || pMerge->GetRowMerge() > 1 ) + { + long nOutWidth = 0; + long nOutHeight = 0; + SCCOL nCountX = pMerge->GetColMerge(); + for (SCCOL i=0; i<nCountX; i++) + nOutWidth += ToPixel( pDoc->GetColWidth(nX+i,nTabNo), nPPTX ); + SCROW nCountY = pMerge->GetRowMerge(); + + for (SCROW nRow = nY; nRow <= nY+nCountY-1; ++nRow) + { + SCROW nLastRow = nRow; + if (pDoc->RowHidden(nRow, nTabNo, NULL, &nLastRow)) + { + nRow = nLastRow; + continue; + } + + sal_uInt16 nHeight = pDoc->GetRowHeight(nRow, nTabNo); + nOutHeight += ToPixel(nHeight, nPPTY); + } + + rSizeXPix = nOutWidth; + rSizeYPix = nOutHeight; + return sal_True; + } + else + { + rSizeXPix = ToPixel( pDoc->GetColWidth( nX, nTabNo ), nPPTX ); + rSizeYPix = ToPixel( pDoc->GetRowHeight( nY, nTabNo ), nPPTY ); + return sal_False; + } +} + +sal_Bool ScViewData::GetPosFromPixel( long nClickX, long nClickY, ScSplitPos eWhich, + SCsCOL& rPosX, SCsROW& rPosY, + sal_Bool bTestMerge, sal_Bool bRepair, sal_Bool bNextIfLarge ) +{ + // special handling of 0 is now in ScViewFunctionSet::SetCursorAtPoint + + ScHSplitPos eHWhich = WhichH(eWhich); + ScVSplitPos eVWhich = WhichV(eWhich); + + if ( pDoc->IsLayoutRTL( nTabNo ) ) + { + // mirror horizontal position + if (pView) + aScrSize.Width() = pView->GetGridWidth(eHWhich); + nClickX = aScrSize.Width() - 1 - nClickX; + } + + SCsCOL nStartPosX = GetPosX(eHWhich); + SCsROW nStartPosY = GetPosY(eVWhich); + rPosX = nStartPosX; + rPosY = nStartPosY; + long nScrX = 0; + long nScrY = 0; + + if (nClickX > 0) + { + while ( rPosX<=MAXCOL && nClickX >= nScrX ) + { + nScrX += ToPixel( pDoc->GetColWidth( rPosX, nTabNo ), nPPTX ); + ++rPosX; + } + --rPosX; + } + else + { + while ( rPosX>0 && nClickX < nScrX ) + { + --rPosX; + nScrX -= ToPixel( pDoc->GetColWidth( rPosX, nTabNo ), nPPTX ); + } + } + + if (nClickY > 0) + AddPixelsWhile( nScrY, nClickY, rPosY, MAXROW, nPPTY, pDoc, nTabNo ); + else + { + /* TODO: could need some "SubPixelsWhileBackward" method */ + while ( rPosY>0 && nClickY < nScrY ) + { + --rPosY; + nScrY -= ToPixel( pDoc->GetRowHeight( rPosY, nTabNo ), nPPTY ); + } + } + + if (bNextIfLarge) // zu grosse Zellen ? + { + if ( rPosX == nStartPosX && nClickX > 0 ) + { + if (pView) + aScrSize.Width() = pView->GetGridWidth(eHWhich); + if ( nClickX > aScrSize.Width() ) + ++rPosX; + } + if ( rPosY == nStartPosY && nClickY > 0 ) + { + if (pView) + aScrSize.Height() = pView->GetGridHeight(eVWhich); + if ( nClickY > aScrSize.Height() ) + ++rPosY; + } + } + + if (rPosX<0) rPosX=0; + if (rPosX>MAXCOL) rPosX=MAXCOL; + if (rPosY<0) rPosY=0; + if (rPosY>MAXROW) rPosY=MAXROW; + + if (bTestMerge) + { + //! public Methode um Position anzupassen + + sal_Bool bHOver = sal_False; + while (pDoc->IsHorOverlapped( rPosX, rPosY, nTabNo )) + { --rPosX; bHOver=sal_True; } + sal_Bool bVOver = sal_False; + while (pDoc->IsVerOverlapped( rPosX, rPosY, nTabNo )) + { --rPosY; bVOver=sal_True; } + + if ( bRepair && ( bHOver || bVOver ) ) + { + const ScMergeAttr* pMerge = (const ScMergeAttr*) + pDoc->GetAttr( rPosX, rPosY, nTabNo, ATTR_MERGE ); + if ( ( bHOver && pMerge->GetColMerge() <= 1 ) || + ( bVOver && pMerge->GetRowMerge() <= 1 ) ) + { + DBG_ERROR("Merge-Fehler gefunden"); + + pDoc->RemoveFlagsTab( 0,0, MAXCOL,MAXROW, nTabNo, SC_MF_HOR | SC_MF_VER ); + SCCOL nEndCol = MAXCOL; + SCROW nEndRow = MAXROW; + pDoc->ExtendMerge( 0,0, nEndCol,nEndRow, nTabNo, sal_True, sal_False ); + if (pDocShell) + pDocShell->PostPaint( ScRange(0,0,nTabNo,MAXCOL,MAXROW,nTabNo), PAINT_GRID ); + } + } + } + + return sal_False; +} + +void ScViewData::GetMouseQuadrant( const Point& rClickPos, ScSplitPos eWhich, + SCsCOL nPosX, SCsROW nPosY, sal_Bool& rLeft, sal_Bool& rTop ) +{ + sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTabNo ); + long nLayoutSign = bLayoutRTL ? -1 : 1; + + Point aCellStart = GetScrPos( nPosX, nPosY, eWhich, sal_True ); + long nSizeX; + long nSizeY; + GetMergeSizePixel( nPosX, nPosY, nSizeX, nSizeY ); + rLeft = ( rClickPos.X() - aCellStart.X() ) * nLayoutSign <= nSizeX / 2; + rTop = rClickPos.Y() - aCellStart.Y() <= nSizeY / 2; +} + +void ScViewData::SetPosX( ScHSplitPos eWhich, SCCOL nNewPosX ) +{ + if (nNewPosX != 0) + { + SCCOL nOldPosX = pThisTab->nPosX[eWhich]; + long nTPosX = pThisTab->nTPosX[eWhich]; + long nPixPosX = pThisTab->nPixPosX[eWhich]; + SCCOL i; + if ( nNewPosX > nOldPosX ) + for ( i=nOldPosX; i<nNewPosX; i++ ) + { + long nThis = pDoc->GetColWidth( i,nTabNo ); + nTPosX -= nThis; + nPixPosX -= ToPixel(sal::static_int_cast<sal_uInt16>(nThis), nPPTX); + } + else + for ( i=nNewPosX; i<nOldPosX; i++ ) + { + long nThis = pDoc->GetColWidth( i,nTabNo ); + nTPosX += nThis; + nPixPosX += ToPixel(sal::static_int_cast<sal_uInt16>(nThis), nPPTX); + } + + pThisTab->nPosX[eWhich] = nNewPosX; + pThisTab->nTPosX[eWhich] = nTPosX; + pThisTab->nMPosX[eWhich] = (long) (nTPosX * HMM_PER_TWIPS); + pThisTab->nPixPosX[eWhich] = nPixPosX; + } + else + pThisTab->nPixPosX[eWhich] = + pThisTab->nTPosX[eWhich] = + pThisTab->nMPosX[eWhich] = + pThisTab->nPosX[eWhich] = 0; +} + +void ScViewData::SetPosY( ScVSplitPos eWhich, SCROW nNewPosY ) +{ + if (nNewPosY != 0) + { + SCROW nOldPosY = pThisTab->nPosY[eWhich]; + long nTPosY = pThisTab->nTPosY[eWhich]; + long nPixPosY = pThisTab->nPixPosY[eWhich]; + SCROW i, nHeightEndRow; + if ( nNewPosY > nOldPosY ) + for ( i=nOldPosY; i<nNewPosY; i++ ) + { + long nThis = pDoc->GetRowHeight( i, nTabNo, NULL, &nHeightEndRow ); + SCROW nRows = std::min( nNewPosY, nHeightEndRow + 1) - i; + i = nHeightEndRow; + nTPosY -= nThis * nRows; + nPixPosY -= ToPixel(sal::static_int_cast<sal_uInt16>(nThis), nPPTY) * nRows; + } + else + for ( i=nNewPosY; i<nOldPosY; i++ ) + { + long nThis = pDoc->GetRowHeight( i, nTabNo, NULL, &nHeightEndRow ); + SCROW nRows = std::min( nOldPosY, nHeightEndRow + 1) - i; + i = nHeightEndRow; + nTPosY += nThis * nRows; + nPixPosY += ToPixel(sal::static_int_cast<sal_uInt16>(nThis), nPPTY) * nRows; + } + + pThisTab->nPosY[eWhich] = nNewPosY; + pThisTab->nTPosY[eWhich] = nTPosY; + pThisTab->nMPosY[eWhich] = (long) (nTPosY * HMM_PER_TWIPS); + pThisTab->nPixPosY[eWhich] = nPixPosY; + } + else + pThisTab->nPixPosY[eWhich] = + pThisTab->nTPosY[eWhich] = + pThisTab->nMPosY[eWhich] = + pThisTab->nPosY[eWhich] = 0; +} + +void ScViewData::RecalcPixPos() // nach Zoom-Aenderungen +{ + for (sal_uInt16 eWhich=0; eWhich<2; eWhich++) + { + long nPixPosX = 0; + SCCOL nPosX = pThisTab->nPosX[eWhich]; + for (SCCOL i=0; i<nPosX; i++) + nPixPosX -= ToPixel(pDoc->GetColWidth(i,nTabNo), nPPTX); + pThisTab->nPixPosX[eWhich] = nPixPosX; + + long nPixPosY = 0; + SCROW nPosY = pThisTab->nPosY[eWhich]; + for (SCROW j=0; j<nPosY; j++) + nPixPosY -= ToPixel(pDoc->GetRowHeight(j,nTabNo), nPPTY); + pThisTab->nPixPosY[eWhich] = nPixPosY; + } +} + +const MapMode& ScViewData::GetLogicMode( ScSplitPos eWhich ) +{ + aLogicMode.SetOrigin( Point( pThisTab->nMPosX[WhichH(eWhich)], + pThisTab->nMPosY[WhichV(eWhich)] ) ); + return aLogicMode; +} + +const MapMode& ScViewData::GetLogicMode() +{ + aLogicMode.SetOrigin( Point() ); + return aLogicMode; +} + +void ScViewData::SetScreen( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) +{ + SCCOL nCol; + SCROW nRow; + sal_uInt16 nTSize; + long nSizePix; + long nScrPosX = 0; + long nScrPosY = 0; + + SetActivePart( SC_SPLIT_BOTTOMLEFT ); + SetPosX( SC_SPLIT_LEFT, nCol1 ); + SetPosY( SC_SPLIT_BOTTOM, nRow1 ); + + for (nCol=nCol1; nCol<=nCol2; nCol++) + { + nTSize = pDoc->GetColWidth( nCol, nTabNo ); + if (nTSize) + { + nSizePix = ToPixel( nTSize, nPPTX ); + nScrPosX += (sal_uInt16) nSizePix; + } + } + + for (nRow=nRow1; nRow<=nRow2; nRow++) + { + nTSize = pDoc->GetRowHeight( nRow, nTabNo ); + if (nTSize) + { + nSizePix = ToPixel( nTSize, nPPTY ); + nScrPosY += (sal_uInt16) nSizePix; + } + } + + aScrSize = Size( nScrPosX, nScrPosY ); +} + +void ScViewData::SetScreenPos( const Point& rVisAreaStart ) +{ + long nSize; + long nTwips; + long nAdd; + sal_Bool bEnd; + + nSize = 0; + nTwips = (long) (rVisAreaStart.X() / HMM_PER_TWIPS); + if ( pDoc->IsLayoutRTL( nTabNo ) ) + nTwips = -nTwips; + SCCOL nX1 = 0; + bEnd = sal_False; + while (!bEnd) + { + nAdd = (long) pDoc->GetColWidth(nX1,nTabNo); + if (nSize+nAdd <= nTwips+1 && nX1<MAXCOL) + { + nSize += nAdd; + ++nX1; + } + else + bEnd = sal_True; + } + + nSize = 0; + nTwips = (long) (rVisAreaStart.Y() / HMM_PER_TWIPS); + SCROW nY1 = 0; + bEnd = sal_False; + while (!bEnd) + { + nAdd = (long) pDoc->GetRowHeight(nY1,nTabNo); + if (nSize+nAdd <= nTwips+1 && nY1<MAXROW) + { + nSize += nAdd; + ++nY1; + } + else + bEnd = sal_True; + } + + SetActivePart( SC_SPLIT_BOTTOMLEFT ); + SetPosX( SC_SPLIT_LEFT, nX1 ); + SetPosY( SC_SPLIT_BOTTOM, nY1 ); + + SetCurX( nX1 ); + SetCurY( nY1 ); +} + +void ScViewData::SetScreen( const Rectangle& rVisArea ) +{ + SetScreenPos( rVisArea.TopLeft() ); + + // hier ohne GetOutputFactor(), weil fuer Ausgabe in Metafile + + aScrSize = rVisArea.GetSize(); + aScrSize.Width() = (long) + ( aScrSize.Width() * ScGlobal::nScreenPPTX / HMM_PER_TWIPS ); + aScrSize.Height() = (long) + ( aScrSize.Height() * ScGlobal::nScreenPPTY / HMM_PER_TWIPS ); +} + +SfxObjectShell* ScViewData::GetSfxDocShell() const +{ + return pDocShell; +} + +SfxBindings& ScViewData::GetBindings() +{ + DBG_ASSERT( pViewShell, "GetBindings() without ViewShell" ); + return pViewShell->GetViewFrame()->GetBindings(); +} + +SfxDispatcher& ScViewData::GetDispatcher() +{ + DBG_ASSERT( pViewShell, "GetDispatcher() without ViewShell" ); + return *pViewShell->GetViewFrame()->GetDispatcher(); +} + +Window* ScViewData::GetDialogParent() +{ + DBG_ASSERT( pViewShell, "GetDialogParent() ohne ViewShell" ); + return pViewShell->GetDialogParent(); +} + +Window* ScViewData::GetActiveWin() +{ + DBG_ASSERT( pView, "GetActiveWin() ohne View" ); + return pView->GetActiveWin(); +} + +ScDrawView* ScViewData::GetScDrawView() +{ + DBG_ASSERT( pView, "GetScDrawView() ohne View" ); + return pView->GetScDrawView(); +} + +sal_Bool ScViewData::IsMinimized() +{ + DBG_ASSERT( pView, "IsMinimized() ohne View" ); + return pView->IsMinimized(); +} + +void ScViewData::UpdateScreenZoom( const Fraction& rNewX, const Fraction& rNewY ) +{ + Fraction aOldX = GetZoomX(); + Fraction aOldY = GetZoomY(); + + SetZoom( rNewX, rNewY, sal_False ); + + Fraction aWidth = GetZoomX(); + aWidth *= Fraction( aScrSize.Width(),1 ); + aWidth /= aOldX; + + Fraction aHeight = GetZoomY(); + aHeight *= Fraction( aScrSize.Height(),1 ); + aHeight /= aOldY; + + aScrSize.Width() = (long) aWidth; + aScrSize.Height() = (long) aHeight; +} + +void ScViewData::CalcPPT() +{ + nPPTX = ScGlobal::nScreenPPTX * (double) GetZoomX(); + if (pDocShell) + nPPTX = nPPTX / pDocShell->GetOutputFactor(); // Faktor ist Drucker zu Bildschirm + nPPTY = ScGlobal::nScreenPPTY * (double) GetZoomY(); + + // #83616# if detective objects are present, + // try to adjust horizontal scale so the most common column width has minimal rounding errors, + // to avoid differences between cell and drawing layer output + + if ( pDoc && pDoc->HasDetectiveObjects(nTabNo) ) + { + SCCOL nEndCol = 0; + SCROW nDummy = 0; + pDoc->GetTableArea( nTabNo, nEndCol, nDummy ); + if (nEndCol<20) + nEndCol = 20; // same end position as when determining draw scale + + sal_uInt16 nTwips = pDoc->GetCommonWidth( nEndCol, nTabNo ); + if ( nTwips ) + { + double fOriginal = nTwips * nPPTX; + if ( fOriginal < static_cast<double>(nEndCol) ) + { + // if one column is smaller than the column count, + // rounding errors are likely to add up to a whole column. + + double fRounded = ::rtl::math::approxFloor( fOriginal + 0.5 ); + if ( fRounded > 0.0 ) + { + double fScale = fRounded / fOriginal + 1E-6; + if ( fScale >= 0.9 && fScale <= 1.1 ) + nPPTX *= fScale; + } + } + } + } +} + +//------------------------------------------------------------------ + +#define SC_OLD_TABSEP '/' +#define SC_NEW_TABSEP '+' + +void ScViewData::WriteUserData(String& rData) +{ + // nZoom (bis 364v) oder nZoom/nPageZoom/bPageMode (ab 364w) + // nTab + // Tab-ControlBreite + // pro Tabelle: + // CursorX/CursorY/HSplitMode/VSplitMode/HSplitPos/VSplitPos/SplitActive/ + // PosX[links]/PosX[rechts]/PosY[oben]/PosY[unten] + // wenn Zeilen groesser 8192, "+" statt "/" + + sal_uInt16 nZoom = (sal_uInt16)((pThisTab->aZoomY.GetNumerator() * 100) / pThisTab->aZoomY.GetDenominator()); + rData = String::CreateFromInt32( nZoom ); + rData += '/'; + nZoom = (sal_uInt16)((pThisTab->aPageZoomY.GetNumerator() * 100) / pThisTab->aPageZoomY.GetDenominator()); + rData += String::CreateFromInt32( nZoom ); + rData += '/'; + if (bPagebreak) + rData += '1'; + else + rData += '0'; + + rData += ';'; + rData += String::CreateFromInt32( nTabNo ); + rData += ';'; + rData.AppendAscii(RTL_CONSTASCII_STRINGPARAM( TAG_TABBARWIDTH )); + rData += String::CreateFromInt32( pView->GetTabBarWidth() ); + + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB i=0; i<nTabCount; i++) + { + rData += ';'; // Numerierung darf auf keinen Fall durcheinanderkommen + if (pTabData[i]) + { + sal_Unicode cTabSep = SC_OLD_TABSEP; // wie 3.1 + if ( pTabData[i]->nCurY > MAXROW_30 || + pTabData[i]->nPosY[0] > MAXROW_30 || pTabData[i]->nPosY[1] > MAXROW_30 || + ( pTabData[i]->eVSplitMode == SC_SPLIT_FIX && + pTabData[i]->nFixPosY > MAXROW_30 ) ) + { + cTabSep = SC_NEW_TABSEP; // um eine 3.1-Version nicht umzubringen + } + + + rData += String::CreateFromInt32( pTabData[i]->nCurX ); + rData += cTabSep; + rData += String::CreateFromInt32( pTabData[i]->nCurY ); + rData += cTabSep; + rData += String::CreateFromInt32( pTabData[i]->eHSplitMode ); + rData += cTabSep; + rData += String::CreateFromInt32( pTabData[i]->eVSplitMode ); + rData += cTabSep; + if ( pTabData[i]->eHSplitMode == SC_SPLIT_FIX ) + rData += String::CreateFromInt32( pTabData[i]->nFixPosX ); + else + rData += String::CreateFromInt32( pTabData[i]->nHSplitPos ); + rData += cTabSep; + if ( pTabData[i]->eVSplitMode == SC_SPLIT_FIX ) + rData += String::CreateFromInt32( pTabData[i]->nFixPosY ); + else + rData += String::CreateFromInt32( pTabData[i]->nVSplitPos ); + rData += cTabSep; + rData += String::CreateFromInt32( pTabData[i]->eWhichActive ); + rData += cTabSep; + rData += String::CreateFromInt32( pTabData[i]->nPosX[0] ); + rData += cTabSep; + rData += String::CreateFromInt32( pTabData[i]->nPosX[1] ); + rData += cTabSep; + rData += String::CreateFromInt32( pTabData[i]->nPosY[0] ); + rData += cTabSep; + rData += String::CreateFromInt32( pTabData[i]->nPosY[1] ); + } + } +} + +void ScViewData::ReadUserData(const String& rData) +{ + if (!rData.Len()) // Leerer String kommt bei "neu Laden" + return; // dann auch ohne Assertion beenden + + xub_StrLen nCount = rData.GetTokenCount(';'); + if ( nCount <= 2 ) + { + // #45208# beim Reload in der Seitenansicht sind evtl. die Preview-UserData + // stehengelassen worden. Den Zoom von der Preview will man hier nicht... + DBG_ERROR("ReadUserData: das sind nicht meine Daten"); + return; + } + + String aTabOpt; + xub_StrLen nTagLen = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(TAG_TABBARWIDTH)).Len(); + + //------------------- + // nicht pro Tabelle: + //------------------- + SCTAB nTabStart = 2; + + Fraction aZoomX, aZoomY, aPageZoomX, aPageZoomY; //! evaluate (all sheets?) + + String aZoomStr = rData.GetToken(0); // Zoom/PageZoom/Modus + sal_uInt16 nNormZoom = sal::static_int_cast<sal_uInt16>(aZoomStr.GetToken(0,'/').ToInt32()); + if ( nNormZoom >= MINZOOM && nNormZoom <= MAXZOOM ) + aZoomX = aZoomY = Fraction( nNormZoom, 100 ); // "normaler" Zoom (immer) + sal_uInt16 nPageZoom = sal::static_int_cast<sal_uInt16>(aZoomStr.GetToken(1,'/').ToInt32()); + if ( nPageZoom >= MINZOOM && nPageZoom <= MAXZOOM ) + aPageZoomX = aPageZoomY = Fraction( nPageZoom, 100 ); // Pagebreak-Zoom, wenn gesetzt + sal_Unicode cMode = aZoomStr.GetToken(2,'/').GetChar(0); // 0 oder "0"/"1" + SetPagebreakMode( cMode == '1' ); + // SetPagebreakMode muss immer gerufen werden wegen CalcPPT / RecalcPixPos() + + // + // Tabelle kann ungueltig geworden sein (z.B. letzte Version): + // + SCTAB nNewTab = static_cast<SCTAB>(rData.GetToken(1).ToInt32()); + if (pDoc->HasTable( nNewTab )) + SetTabNo(nNewTab); + + // + // wenn vorhanden, TabBar-Breite holen: + // + aTabOpt = rData.GetToken(2); + + if ( nTagLen && aTabOpt.Copy(0,nTagLen).EqualsAscii(TAG_TABBARWIDTH) ) + { + pView->SetTabBarWidth( aTabOpt.Copy(nTagLen).ToInt32() ); + nTabStart = 3; + } + + //------------- + // pro Tabelle: + //------------- + SCTAB nPos = 0; + while ( nCount > nPos+nTabStart ) + { + aTabOpt = rData.GetToken(static_cast<xub_StrLen>(nPos+nTabStart)); + if (!pTabData[nPos]) + pTabData[nPos] = new ScViewDataTable; + + sal_Unicode cTabSep = 0; + if (aTabOpt.GetTokenCount(SC_OLD_TABSEP) >= 11) + cTabSep = SC_OLD_TABSEP; +#ifndef SC_LIMIT_ROWS + else if (aTabOpt.GetTokenCount(SC_NEW_TABSEP) >= 11) + cTabSep = SC_NEW_TABSEP; + // '+' ist nur erlaubt, wenn wir mit Zeilen > 8192 umgehen koennen +#endif + + if (cTabSep) + { + pTabData[nPos]->nCurX = SanitizeCol( static_cast<SCCOL>(aTabOpt.GetToken(0,cTabSep).ToInt32())); + pTabData[nPos]->nCurY = SanitizeRow( aTabOpt.GetToken(1,cTabSep).ToInt32()); + pTabData[nPos]->eHSplitMode = (ScSplitMode) aTabOpt.GetToken(2,cTabSep).ToInt32(); + pTabData[nPos]->eVSplitMode = (ScSplitMode) aTabOpt.GetToken(3,cTabSep).ToInt32(); + + if ( pTabData[nPos]->eHSplitMode == SC_SPLIT_FIX ) + { + pTabData[nPos]->nFixPosX = SanitizeCol( static_cast<SCCOL>(aTabOpt.GetToken(4,cTabSep).ToInt32())); + UpdateFixX(nPos); + } + else + pTabData[nPos]->nHSplitPos = aTabOpt.GetToken(4,cTabSep).ToInt32(); + + if ( pTabData[nPos]->eVSplitMode == SC_SPLIT_FIX ) + { + pTabData[nPos]->nFixPosY = SanitizeRow( aTabOpt.GetToken(5,cTabSep).ToInt32()); + UpdateFixY(nPos); + } + else + pTabData[nPos]->nVSplitPos = aTabOpt.GetToken(5,cTabSep).ToInt32(); + + pTabData[nPos]->eWhichActive = (ScSplitPos) aTabOpt.GetToken(6,cTabSep).ToInt32(); + pTabData[nPos]->nPosX[0] = SanitizeCol( static_cast<SCCOL>(aTabOpt.GetToken(7,cTabSep).ToInt32())); + pTabData[nPos]->nPosX[1] = SanitizeCol( static_cast<SCCOL>(aTabOpt.GetToken(8,cTabSep).ToInt32())); + pTabData[nPos]->nPosY[0] = SanitizeRow( aTabOpt.GetToken(9,cTabSep).ToInt32()); + pTabData[nPos]->nPosY[1] = SanitizeRow( aTabOpt.GetToken(10,cTabSep).ToInt32()); + + // Test, ob der aktive Teil laut SplitMode ueberhaupt existiert + // (Bug #44516#) + ScSplitPos eTest = pTabData[nPos]->eWhichActive; + if ( ( WhichH( eTest ) == SC_SPLIT_RIGHT && + pTabData[nPos]->eHSplitMode == SC_SPLIT_NONE ) || + ( WhichV( eTest ) == SC_SPLIT_TOP && + pTabData[nPos]->eVSplitMode == SC_SPLIT_NONE ) ) + { + // dann wieder auf Default (unten links) + pTabData[nPos]->eWhichActive = SC_SPLIT_BOTTOMLEFT; + DBG_ERROR("SplitPos musste korrigiert werden"); + } + } + ++nPos; + } + + RecalcPixPos(); +} + +void ScViewData::WriteExtOptions( ScExtDocOptions& rDocOpt ) const +{ + // *** Fill extended document data for export filters *** + + // document settings + ScExtDocSettings& rDocSett = rDocOpt.GetDocSettings(); + + // displayed sheet + rDocSett.mnDisplTab = GetTabNo(); + + // width of the tabbar, relative to frame window width + rDocSett.mfTabBarWidth = pView->GetPendingRelTabBarWidth(); + if( rDocSett.mfTabBarWidth < 0.0 ) + rDocSett.mfTabBarWidth = pView->GetRelTabBarWidth(); + + // sheet settings + for( SCTAB nTab = 0, nTabCount = pDoc->GetTableCount(); nTab < nTabCount; ++nTab ) + { + if( const ScViewDataTable* pViewTab = pTabData[ nTab ] ) + { + ScExtTabSettings& rTabSett = rDocOpt.GetOrCreateTabSettings( nTab ); + + // split mode + ScSplitMode eHSplit = pViewTab->eHSplitMode; + ScSplitMode eVSplit = pViewTab->eVSplitMode; + bool bHSplit = eHSplit != SC_SPLIT_NONE; + bool bVSplit = eVSplit != SC_SPLIT_NONE; + bool bRealSplit = (eHSplit == SC_SPLIT_NORMAL) || (eVSplit == SC_SPLIT_NORMAL); + bool bFrozen = (eHSplit == SC_SPLIT_FIX) || (eVSplit == SC_SPLIT_FIX); + DBG_ASSERT( !bRealSplit || !bFrozen, "ScViewData::WriteExtOptions - split and freeze in same sheet" ); + rTabSett.mbFrozenPanes = !bRealSplit && bFrozen; + + // split and freeze position + rTabSett.maSplitPos = Point( 0, 0 ); + rTabSett.maFreezePos.Set( 0, 0, nTab ); + if( bRealSplit ) + { + Point& rSplitPos = rTabSett.maSplitPos; + rSplitPos = Point( bHSplit ? pViewTab->nHSplitPos : 0, bVSplit ? pViewTab->nVSplitPos : 0 ); + rSplitPos = Application::GetDefaultDevice()->PixelToLogic( rSplitPos, MapMode( MAP_TWIP ) ); + if( pDocShell ) + rSplitPos.X() = (long)((double)rSplitPos.X() / pDocShell->GetOutputFactor()); + } + else if( bFrozen ) + { + if( bHSplit ) rTabSett.maFreezePos.SetCol( pViewTab->nFixPosX ); + if( bVSplit ) rTabSett.maFreezePos.SetRow( pViewTab->nFixPosY ); + } + + // first visible cell in top-left and additional panes + rTabSett.maFirstVis.Set( pViewTab->nPosX[ SC_SPLIT_LEFT ], pViewTab->nPosY[ bVSplit ? SC_SPLIT_TOP : SC_SPLIT_BOTTOM ], nTab ); + rTabSett.maSecondVis.Set( pViewTab->nPosX[ SC_SPLIT_RIGHT ], pViewTab->nPosY[ SC_SPLIT_BOTTOM ], nTab ); + + // active pane + switch( pViewTab->eWhichActive ) + { + // no horizontal split -> always use left panes + // no vertical split -> always use top panes + case SC_SPLIT_TOPLEFT: + rTabSett.meActivePane = SCEXT_PANE_TOPLEFT; + break; + case SC_SPLIT_TOPRIGHT: + rTabSett.meActivePane = bHSplit ? SCEXT_PANE_TOPRIGHT : SCEXT_PANE_TOPLEFT; + break; + case SC_SPLIT_BOTTOMLEFT: + rTabSett.meActivePane = bVSplit ? SCEXT_PANE_BOTTOMLEFT : SCEXT_PANE_TOPLEFT; + break; + case SC_SPLIT_BOTTOMRIGHT: + rTabSett.meActivePane = bHSplit ? + (bVSplit ? SCEXT_PANE_BOTTOMRIGHT : SCEXT_PANE_TOPRIGHT) : + (bVSplit ? SCEXT_PANE_BOTTOMLEFT : SCEXT_PANE_TOPLEFT); + break; + } + + // cursor position + rTabSett.maCursor.Set( pViewTab->nCurX, pViewTab->nCurY, nTab ); + + // sheet selection and selected ranges + const ScMarkData& rMarkData = GetMarkData(); + rTabSett.mbSelected = rMarkData.GetTableSelect( nTab ); + rMarkData.FillRangeListWithMarks( &rTabSett.maSelection, sal_True ); + + // grid color + rTabSett.maGridColor.SetColor( COL_AUTO ); + if( pOptions ) + { + const Color& rGridColor = pOptions->GetGridColor(); + if( rGridColor.GetColor() != SC_STD_GRIDCOLOR ) + rTabSett.maGridColor = rGridColor; + } + + // view mode and zoom + rTabSett.mbPageMode = bPagebreak; + rTabSett.mnNormalZoom = static_cast< long >( pViewTab->aZoomY * Fraction( 100.0 ) ); + rTabSett.mnPageZoom = static_cast< long >( pViewTab->aPageZoomY * Fraction( 100.0 ) ); + } + } +} + +void ScViewData::ReadExtOptions( const ScExtDocOptions& rDocOpt ) +{ + // *** Get extended document data from import filters *** + + if( !rDocOpt.IsChanged() ) return; + + // document settings + const ScExtDocSettings& rDocSett = rDocOpt.GetDocSettings(); + + // displayed sheet + SetTabNo( rDocSett.mnDisplTab ); + + /* Width of the tabbar, relative to frame window width. We do not have the + correct width of the frame window here -> store in ScTabView, which sets + the size in the next resize. */ + pView->SetPendingRelTabBarWidth( rDocSett.mfTabBarWidth ); + + // sheet settings + for( SCTAB nTab = 0, nTabCount = pDoc->GetTableCount(); nTab < nTabCount; ++nTab ) + { + if( const ScExtTabSettings* pTabSett = rDocOpt.GetTabSettings( nTab ) ) + { + if( !pTabData[ nTab ] ) + pTabData[ nTab ] = new ScViewDataTable; + + const ScExtTabSettings& rTabSett = *pTabSett; + ScViewDataTable& rViewTab = *pTabData[ nTab ]; + + // split mode initialization + bool bFrozen = rTabSett.mbFrozenPanes; + bool bHSplit = bFrozen ? (rTabSett.maFreezePos.Col() > 0) : (rTabSett.maSplitPos.X() > 0); + bool bVSplit = bFrozen ? (rTabSett.maFreezePos.Row() > 0) : (rTabSett.maSplitPos.Y() > 0); + + // first visible cell of top-left pane and additional panes + rViewTab.nPosX[ SC_SPLIT_LEFT ] = rTabSett.maFirstVis.Col(); + rViewTab.nPosY[ bVSplit ? SC_SPLIT_TOP : SC_SPLIT_BOTTOM ] = rTabSett.maFirstVis.Row(); + if( bHSplit ) rViewTab.nPosX[ SC_SPLIT_RIGHT ] = rTabSett.maSecondVis.Col(); + if( bVSplit ) rViewTab.nPosY[ SC_SPLIT_BOTTOM ] = rTabSett.maSecondVis.Row(); + + // split mode, split and freeze position + rViewTab.eHSplitMode = rViewTab.eVSplitMode = SC_SPLIT_NONE; + rViewTab.nHSplitPos = rViewTab.nVSplitPos = 0; + rViewTab.nFixPosX = 0; + rViewTab.nFixPosY = 0; + if( bFrozen ) + { + if( bHSplit ) + { + rViewTab.eHSplitMode = SC_SPLIT_FIX; + rViewTab.nFixPosX = rTabSett.maFreezePos.Col(); + UpdateFixX( nTab ); + } + if( bVSplit ) + { + rViewTab.eVSplitMode = SC_SPLIT_FIX; + rViewTab.nFixPosY = rTabSett.maFreezePos.Row(); + UpdateFixY( nTab ); + } + } + else + { + Point aPixel = Application::GetDefaultDevice()->LogicToPixel( + rTabSett.maSplitPos, MapMode( MAP_TWIP ) ); //! Zoom? + // #109648# - the test for use of printer metrics for text formatting here + // effectively results in the nFactor = 1.0 regardless of the Option setting. + if( pDocShell && SC_MOD()->GetInputOptions().GetTextWysiwyg()) + { + double nFactor = pDocShell->GetOutputFactor(); + aPixel.X() = (long)( aPixel.X() * nFactor + 0.5 ); + } + if( bHSplit ) + { + rViewTab.eHSplitMode = SC_SPLIT_NORMAL; + rViewTab.nHSplitPos = aPixel.X(); + } + if( bVSplit ) + { + rViewTab.eVSplitMode = SC_SPLIT_NORMAL; + rViewTab.nVSplitPos = aPixel.Y(); + } + } + + // active pane + ScSplitPos ePos = SC_SPLIT_BOTTOMLEFT; + switch( rTabSett.meActivePane ) + { + // no horizontal split -> always use left panes + // no vertical split -> always use *bottom* panes + case SCEXT_PANE_TOPLEFT: + ePos = bVSplit ? SC_SPLIT_TOPLEFT : SC_SPLIT_BOTTOMLEFT; + break; + case SCEXT_PANE_TOPRIGHT: + ePos = bHSplit ? + (bVSplit ? SC_SPLIT_TOPRIGHT : SC_SPLIT_BOTTOMRIGHT) : + (bVSplit ? SC_SPLIT_TOPLEFT : SC_SPLIT_BOTTOMLEFT); + break; + case SCEXT_PANE_BOTTOMLEFT: + ePos = SC_SPLIT_BOTTOMLEFT; + break; + case SCEXT_PANE_BOTTOMRIGHT: + ePos = bHSplit ? SC_SPLIT_BOTTOMRIGHT : SC_SPLIT_BOTTOMLEFT; + break; + } + rViewTab.eWhichActive = ePos; + + // cursor position + const ScAddress& rCursor = rTabSett.maCursor; + if( rCursor.IsValid() ) + { + rViewTab.nCurX = rCursor.Col(); + rViewTab.nCurY = rCursor.Row(); + } + + // sheet selection and selected ranges + ScMarkData& rMarkData = GetMarkData(); + rMarkData.SelectTable( nTab, rTabSett.mbSelected ); + + // zoom for each sheet + if( rTabSett.mnNormalZoom ) + rViewTab.aZoomX = rViewTab.aZoomY = Fraction( rTabSett.mnNormalZoom, 100L ); + if( rTabSett.mnPageZoom ) + rViewTab.aPageZoomX = rViewTab.aPageZoomY = Fraction( rTabSett.mnPageZoom, 100L ); + + // get some settings from displayed Excel sheet, set at Calc document + if( nTab == GetTabNo() ) + { + // selection only for displayed sheet, do not select single cell +// Disabled, does not work correctly. Anyway, our own XML filters do not import a selection at all. +// const ScRangeList& rSel = rTabSett.maSelection; +// if( (rSel.Count() >= 2) || ((rSel.Count() == 1) && (*rSel.GetObject( 0 ) != ScRange( rCursor ))) ) +// rMarkData.MarkFromRangeList( rTabSett.maSelection, sal_False ); + + // grid color -- #i47435# set automatic grid color explicitly + if( pOptions ) + { + Color aGridColor( rTabSett.maGridColor ); + if( aGridColor.GetColor() == COL_AUTO ) + aGridColor.SetColor( SC_STD_GRIDCOLOR ); + pOptions->SetGridColor( aGridColor, EMPTY_STRING ); + } + + // view mode and default zoom (for new sheets) from current sheet + if( rTabSett.mnNormalZoom ) + aDefZoomX = aDefZoomY = Fraction( rTabSett.mnNormalZoom, 100L ); + if( rTabSett.mnPageZoom ) + aDefPageZoomX = aDefPageZoomY = Fraction( rTabSett.mnPageZoom, 100L ); + /* #i46820# set pagebreak mode via SetPagebreakMode(), this will + update map modes that are needed to draw text correctly. */ + SetPagebreakMode( rTabSett.mbPageMode ); + } + } + } + + // RecalcPixPos oder so - auch nMPos - auch bei ReadUserData ??!?! +} + +void ScViewData::WriteUserDataSequence(uno::Sequence <beans::PropertyValue>& rSettings) +{ + rSettings.realloc(SC_VIEWSETTINGS_COUNT); + // + 1, because we have to put the view id in the sequence + beans::PropertyValue* pSettings = rSettings.getArray(); + if (pSettings) + { + sal_uInt16 nViewID(pViewShell->GetViewFrame()->GetCurViewId()); + pSettings[SC_VIEW_ID].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_VIEWID)); + rtl::OUStringBuffer sBuffer(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_VIEW))); + SvXMLUnitConverter::convertNumber(sBuffer, static_cast<sal_Int32>(nViewID)); + pSettings[SC_VIEW_ID].Value <<= sBuffer.makeStringAndClear(); + + SCTAB nTabCount (pDoc->GetTableCount()); + uno::Reference<lang::XMultiServiceFactory> xServiceFactory = + comphelper::getProcessServiceFactory(); + DBG_ASSERT( xServiceFactory.is(), "got no service manager" ); + if( xServiceFactory.is() ) + { + rtl::OUString sName(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.document.NamedPropertyValues")); + uno::Reference<container::XNameContainer> xNameContainer = uno::Reference<container::XNameContainer>(xServiceFactory->createInstance(sName), uno::UNO_QUERY); + if (xNameContainer.is()) + { + for (SCTAB nTab=0; nTab<nTabCount; nTab++) + { + if (pTabData[nTab]) + { + uno::Sequence <beans::PropertyValue> aTableViewSettings; + pTabData[nTab]->WriteUserDataSequence(aTableViewSettings, *this, nTab); + String sTabName; + GetDocument()->GetName( nTab, sTabName ); + rtl::OUString sOUName(sTabName); + uno::Any aAny; + aAny <<= aTableViewSettings; + try + { + xNameContainer->insertByName(sTabName, aAny); + } + //#101739#; two tables with the same name are possible + catch ( container::ElementExistException& ) + { + DBG_ERRORFILE("seems there are two tables with the same name"); + } + catch ( uno::RuntimeException& ) + { + DBG_ERRORFILE("something went wrong"); + } + } + } + pSettings[SC_TABLE_VIEWSETTINGS].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_TABLES)); + pSettings[SC_TABLE_VIEWSETTINGS].Value <<= xNameContainer; + } + } + + String sName; + GetDocument()->GetName( nTabNo, sName ); + rtl::OUString sOUName(sName); + pSettings[SC_ACTIVE_TABLE].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_ACTIVETABLE)); + pSettings[SC_ACTIVE_TABLE].Value <<= sOUName; + pSettings[SC_HORIZONTAL_SCROLL_BAR_WIDTH].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_HORIZONTALSCROLLBARWIDTH)); + pSettings[SC_HORIZONTAL_SCROLL_BAR_WIDTH].Value <<= sal_Int32(pView->GetTabBarWidth()); + sal_Int32 nZoomValue ((pThisTab->aZoomY.GetNumerator() * 100) / pThisTab->aZoomY.GetDenominator()); + sal_Int32 nPageZoomValue ((pThisTab->aPageZoomY.GetNumerator() * 100) / pThisTab->aPageZoomY.GetDenominator()); + pSettings[SC_ZOOM_TYPE].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_ZOOMTYPE)); + pSettings[SC_ZOOM_TYPE].Value <<= sal_Int16(pThisTab->eZoomType); + pSettings[SC_ZOOM_VALUE].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_ZOOMVALUE)); + pSettings[SC_ZOOM_VALUE].Value <<= nZoomValue; + pSettings[SC_PAGE_VIEW_ZOOM_VALUE].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_PAGEVIEWZOOMVALUE)); + pSettings[SC_PAGE_VIEW_ZOOM_VALUE].Value <<= nPageZoomValue; + pSettings[SC_PAGE_BREAK_PREVIEW].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_SHOWPAGEBREAKPREVIEW)); + ScUnoHelpFunctions::SetBoolInAny( pSettings[SC_PAGE_BREAK_PREVIEW].Value, bPagebreak); + + if (pOptions) + { + pSettings[SC_SHOWZERO].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_SHOWZERO)); + ScUnoHelpFunctions::SetBoolInAny( pSettings[SC_SHOWZERO].Value, pOptions->GetOption( VOPT_NULLVALS ) ); + pSettings[SC_SHOWNOTES].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_SHOWNOTES)); + ScUnoHelpFunctions::SetBoolInAny( pSettings[SC_SHOWNOTES].Value, pOptions->GetOption( VOPT_NOTES ) ); + pSettings[SC_SHOWGRID].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_SHOWGRID)); + ScUnoHelpFunctions::SetBoolInAny( pSettings[SC_SHOWGRID].Value, pOptions->GetOption( VOPT_GRID ) ); + pSettings[SC_GRIDCOLOR].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_GRIDCOLOR)); + String aColorName; + Color aColor = pOptions->GetGridColor(&aColorName); + pSettings[SC_GRIDCOLOR].Value <<= static_cast<sal_Int64>(aColor.GetColor()); + pSettings[SC_SHOWPAGEBR].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_SHOWPAGEBR)); + ScUnoHelpFunctions::SetBoolInAny( pSettings[SC_SHOWPAGEBR].Value, pOptions->GetOption( VOPT_PAGEBREAKS ) ); + pSettings[SC_COLROWHDR].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_COLROWHDR)); + ScUnoHelpFunctions::SetBoolInAny( pSettings[SC_COLROWHDR].Value, pOptions->GetOption( VOPT_HEADER ) ); + pSettings[SC_SHEETTABS].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_SHEETTABS)); + ScUnoHelpFunctions::SetBoolInAny( pSettings[SC_SHEETTABS].Value, pOptions->GetOption( VOPT_TABCONTROLS ) ); + pSettings[SC_OUTLSYMB].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_OUTLSYMB)); + ScUnoHelpFunctions::SetBoolInAny( pSettings[SC_OUTLSYMB].Value, pOptions->GetOption( VOPT_OUTLINER ) ); + + const ScGridOptions& aGridOpt = pOptions->GetGridOptions(); + pSettings[SC_SNAPTORASTER].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_SNAPTORASTER)); + ScUnoHelpFunctions::SetBoolInAny( pSettings[SC_SNAPTORASTER].Value, aGridOpt.GetUseGridSnap() ); + pSettings[SC_RASTERVIS].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_RASTERVIS)); + ScUnoHelpFunctions::SetBoolInAny( pSettings[SC_RASTERVIS].Value, aGridOpt.GetGridVisible() ); + pSettings[SC_RASTERRESX].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_RASTERRESX)); + pSettings[SC_RASTERRESX].Value <<= static_cast<sal_Int32> ( aGridOpt.GetFldDrawX() ); + pSettings[SC_RASTERRESY].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_RASTERRESY)); + pSettings[SC_RASTERRESY].Value <<= static_cast<sal_Int32> ( aGridOpt.GetFldDrawY() ); + pSettings[SC_RASTERSUBX].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_RASTERSUBX)); + pSettings[SC_RASTERSUBX].Value <<= static_cast<sal_Int32> ( aGridOpt.GetFldDivisionX() ); + pSettings[SC_RASTERSUBY].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_RASTERSUBY)); + pSettings[SC_RASTERSUBY].Value <<= static_cast<sal_Int32> ( aGridOpt.GetFldDivisionY() ); + pSettings[SC_RASTERSYNC].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_RASTERSYNC)); + ScUnoHelpFunctions::SetBoolInAny( pSettings[SC_RASTERSYNC].Value, aGridOpt.GetSynchronize() ); + } + } +} + +void ScViewData::ReadUserDataSequence(const uno::Sequence <beans::PropertyValue>& rSettings) +{ + Fraction aZoomX, aZoomY, aPageZoomX, aPageZoomY; //! evaluate (all sheets?) + + std::vector<bool> aHasZoomVect( GetDocument()->GetTableCount(), false ); + + sal_Int32 nCount(rSettings.getLength()); + sal_Int32 nTemp32(0); + sal_Int16 nTemp16(0); + sal_Bool bPageMode(sal_False); + for (sal_Int32 i = 0; i < nCount; i++) + { + // SC_VIEWID has to parse and use by mba + rtl::OUString sName(rSettings[i].Name); + if (sName.compareToAscii(SC_TABLES) == 0) + { + uno::Reference<container::XNameContainer> xNameContainer; + if ((rSettings[i].Value >>= xNameContainer) && xNameContainer->hasElements()) + { + uno::Sequence< rtl::OUString > aNames(xNameContainer->getElementNames()); + for (sal_Int32 nTabPos = 0; nTabPos < aNames.getLength(); nTabPos++) + { + String sTabName(aNames[nTabPos]); + SCTAB nTab(0); + if (GetDocument()->GetTable(sTabName, nTab)) + { + uno::Any aAny = xNameContainer->getByName(aNames[nTabPos]); + uno::Sequence<beans::PropertyValue> aTabSettings; + if (aAny >>= aTabSettings) + { + pTabData[nTab] = new ScViewDataTable; + bool bHasZoom = false; + pTabData[nTab]->ReadUserDataSequence(aTabSettings, *this, nTab, bHasZoom); + aHasZoomVect[nTab] = bHasZoom; + } + } + } + } + } + else if (sName.compareToAscii(SC_ACTIVETABLE) == 0) + { + rtl::OUString sValue; + if(rSettings[i].Value >>= sValue) + { + String sTabName(sValue); + SCTAB nTab(0); + if (GetDocument()->GetTable(sTabName, nTab)) + nTabNo = nTab; + } + } + else if (sName.compareToAscii(SC_HORIZONTALSCROLLBARWIDTH) == 0) + { + if (rSettings[i].Value >>= nTemp32) + pView->SetTabBarWidth(nTemp32); + } + else if (sName.compareToAscii(SC_RELHORIZONTALTABBARWIDTH) == 0) + { + double fWidth = 0.0; + if (rSettings[i].Value >>= fWidth) + pView->SetPendingRelTabBarWidth( fWidth ); + } + else if (sName.compareToAscii(SC_ZOOMTYPE) == 0) + { + if (rSettings[i].Value >>= nTemp16) + eDefZoomType = SvxZoomType(nTemp16); + } + else if (sName.compareToAscii(SC_ZOOMVALUE) == 0) + { + if (rSettings[i].Value >>= nTemp32) + { + Fraction aZoom(nTemp32, 100); + aDefZoomX = aDefZoomY = aZoom; + } + } + else if (sName.compareToAscii(SC_PAGEVIEWZOOMVALUE) == 0) + { + if (rSettings[i].Value >>= nTemp32) + { + Fraction aZoom(nTemp32, 100); + aDefPageZoomX = aDefPageZoomY = aZoom; + } + } + else if (sName.compareToAscii(SC_SHOWPAGEBREAKPREVIEW) == 0) + bPageMode = ScUnoHelpFunctions::GetBoolFromAny( rSettings[i].Value ); + else if ( sName.compareToAscii( SC_UNO_SHOWZERO ) == 0 ) + pOptions->SetOption(VOPT_NULLVALS, ScUnoHelpFunctions::GetBoolFromAny( rSettings[i].Value ) ); + else if ( sName.compareToAscii( SC_UNO_SHOWNOTES ) == 0 ) + pOptions->SetOption(VOPT_NOTES, ScUnoHelpFunctions::GetBoolFromAny( rSettings[i].Value ) ); + else if ( sName.compareToAscii( SC_UNO_SHOWGRID ) == 0 ) + pOptions->SetOption(VOPT_GRID, ScUnoHelpFunctions::GetBoolFromAny( rSettings[i].Value ) ); + else if ( sName.compareToAscii( SC_UNO_GRIDCOLOR ) == 0 ) + { + sal_Int64 nColor = 0; + if (rSettings[i].Value >>= nColor) + { + String aColorName; + Color aColor(static_cast<sal_uInt32>(nColor)); + // #i47435# set automatic grid color explicitly + if( aColor.GetColor() == COL_AUTO ) + aColor.SetColor( SC_STD_GRIDCOLOR ); + pOptions->SetGridColor(aColor, aColorName); + } + } + else if ( sName.compareToAscii( SC_UNO_SHOWPAGEBR ) == 0 ) + pOptions->SetOption(VOPT_PAGEBREAKS, ScUnoHelpFunctions::GetBoolFromAny( rSettings[i].Value ) ); + else if ( sName.compareToAscii( SC_UNO_COLROWHDR ) == 0 ) + pOptions->SetOption(VOPT_HEADER, ScUnoHelpFunctions::GetBoolFromAny( rSettings[i].Value ) ); + else if ( sName.compareToAscii( SC_UNO_SHEETTABS ) == 0 ) + pOptions->SetOption(VOPT_TABCONTROLS, ScUnoHelpFunctions::GetBoolFromAny( rSettings[i].Value ) ); + else if ( sName.compareToAscii( SC_UNO_OUTLSYMB ) == 0 ) + pOptions->SetOption(VOPT_OUTLINER, ScUnoHelpFunctions::GetBoolFromAny( rSettings[i].Value ) ); + else if ( sName.compareToAscii( SC_UNO_SHOWOBJ ) == 0 ) + { + // #i80528# placeholders not supported anymore + if ( rSettings[i].Value >>= nTemp16 ) + pOptions->SetObjMode( VOBJ_TYPE_OLE, (nTemp16 == 1) ? VOBJ_MODE_HIDE : VOBJ_MODE_SHOW ); + } + else if ( sName.compareToAscii( SC_UNO_SHOWCHARTS ) == 0 ) + { + // #i80528# placeholders not supported anymore + if ( rSettings[i].Value >>= nTemp16 ) + pOptions->SetObjMode( VOBJ_TYPE_CHART, (nTemp16 == 1) ? VOBJ_MODE_HIDE : VOBJ_MODE_SHOW ); + } + else if ( sName.compareToAscii( SC_UNO_SHOWDRAW ) == 0 ) + { + // #i80528# placeholders not supported anymore + if ( rSettings[i].Value >>= nTemp16 ) + pOptions->SetObjMode( VOBJ_TYPE_DRAW, (nTemp16 == 1) ? VOBJ_MODE_HIDE : VOBJ_MODE_SHOW ); + } + else + { + ScGridOptions aGridOpt(pOptions->GetGridOptions()); + if ( sName.compareToAscii( SC_UNO_SNAPTORASTER ) == 0 ) + aGridOpt.SetUseGridSnap( ScUnoHelpFunctions::GetBoolFromAny( rSettings[i].Value ) ); + else if ( sName.compareToAscii( SC_UNO_RASTERVIS ) == 0 ) + aGridOpt.SetGridVisible( ScUnoHelpFunctions::GetBoolFromAny( rSettings[i].Value ) ); + else if ( sName.compareToAscii( SC_UNO_RASTERRESX ) == 0 ) + aGridOpt.SetFldDrawX( static_cast <sal_uInt32> ( ScUnoHelpFunctions::GetInt32FromAny( rSettings[i].Value ) ) ); + else if ( sName.compareToAscii( SC_UNO_RASTERRESY ) == 0 ) + aGridOpt.SetFldDrawY( static_cast <sal_uInt32> ( ScUnoHelpFunctions::GetInt32FromAny( rSettings[i].Value ) ) ); + else if ( sName.compareToAscii( SC_UNO_RASTERSUBX ) == 0 ) + aGridOpt.SetFldDivisionX( static_cast <sal_uInt32> ( ScUnoHelpFunctions::GetInt32FromAny( rSettings[i].Value ) ) ); + else if ( sName.compareToAscii( SC_UNO_RASTERSUBY ) == 0 ) + aGridOpt.SetFldDivisionY( static_cast <sal_uInt32> ( ScUnoHelpFunctions::GetInt32FromAny( rSettings[i].Value ) ) ); + else if ( sName.compareToAscii( SC_UNO_RASTERSYNC ) == 0 ) + aGridOpt.SetSynchronize( ScUnoHelpFunctions::GetBoolFromAny( rSettings[i].Value ) ); + pOptions->SetGridOptions(aGridOpt); + } + } + + // copy default zoom to sheets where a different one wasn't specified + for (SCTAB nZoomTab=0; nZoomTab<=MAXTAB; ++nZoomTab) + if (pTabData[nZoomTab] && ( nZoomTab >= static_cast<SCTAB>(aHasZoomVect.size()) || !aHasZoomVect[nZoomTab] )) + { + pTabData[nZoomTab]->eZoomType = eDefZoomType; + pTabData[nZoomTab]->aZoomX = aDefZoomX; + pTabData[nZoomTab]->aZoomY = aDefZoomY; + pTabData[nZoomTab]->aPageZoomX = aDefPageZoomX; + pTabData[nZoomTab]->aPageZoomY = aDefPageZoomY; + } + + if (nCount) + SetPagebreakMode( bPageMode ); + + // #i47426# write view options to document, needed e.g. for Excel export + pDoc->SetViewOptions( *pOptions ); +} + +void ScViewData::SetOptions( const ScViewOptions& rOpt ) +{ + // if visibility of horiz. ScrollBar is changed, TabBar may have to be resized... + sal_Bool bHScrollChanged = ( rOpt.GetOption(VOPT_HSCROLL) != pOptions->GetOption(VOPT_HSCROLL) ); + + // if graphics are turned on or off, animation has to be started or stopped + // graphics are controlled by VOBJ_TYPE_OLE + sal_Bool bGraphicsChanged = ( pOptions->GetObjMode(VOBJ_TYPE_OLE) != + rOpt.GetObjMode(VOBJ_TYPE_OLE) ); + + *pOptions = rOpt; + DBG_ASSERT( pView, "No View" ); + + if( pView ) + { + pView->ViewOptionsHasChanged( bHScrollChanged, bGraphicsChanged ); + } +} + +Point ScViewData::GetMousePosPixel() +{ + DBG_ASSERT( pView, "GetMousePosPixel() ohne View" ); + return pView->GetMousePosPixel(); +} + +void ScViewData::UpdateInputHandler( sal_Bool bForce, sal_Bool bStopEditing ) +{ + if (pViewShell) + pViewShell->UpdateInputHandler( bForce, bStopEditing ); +} + +sal_Bool ScViewData::IsOle() +{ + return pDocShell && pDocShell->IsOle(); +} + +sal_Bool ScViewData::UpdateFixX( SCTAB nTab ) // sal_True = Wert geaendert +{ + if (!ValidTab(nTab)) // Default + nTab=nTabNo; // akuelle Tabelle + + if (!pView || pTabData[nTab]->eHSplitMode != SC_SPLIT_FIX) + return sal_False; + + ScDocument* pLocalDoc = GetDocument(); + if (!pLocalDoc->HasTable(nTab)) // #114007# if called from reload, the sheet may not exist + return sal_False; + + SCCOL nFix = pTabData[nTab]->nFixPosX; + long nNewPos = 0; + for (SCCOL nX=pTabData[nTab]->nPosX[SC_SPLIT_LEFT]; nX<nFix; nX++) + { + sal_uInt16 nTSize = pLocalDoc->GetColWidth( nX, nTab ); + if (nTSize) + { + long nPix = ToPixel( nTSize, nPPTX ); + nNewPos += nPix; + } + } + nNewPos += pView->GetGridOffset().X(); + if (nNewPos != pTabData[nTab]->nHSplitPos) + { + pTabData[nTab]->nHSplitPos = nNewPos; + if (nTab == nTabNo) + RecalcPixPos(); //! sollte nicht noetig sein !!! + return sal_True; + } + + return sal_False; +} + +sal_Bool ScViewData::UpdateFixY( SCTAB nTab ) // sal_True = Wert geaendert +{ + if (!ValidTab(nTab)) // Default + nTab=nTabNo; // akuelle Tabelle + + if (!pView || pTabData[nTab]->eVSplitMode != SC_SPLIT_FIX) + return sal_False; + + ScDocument* pLocalDoc = GetDocument(); + if (!pLocalDoc->HasTable(nTab)) // #114007# if called from reload, the sheet may not exist + return sal_False; + + SCROW nFix = pTabData[nTab]->nFixPosY; + long nNewPos = 0; + for (SCROW nY=pTabData[nTab]->nPosY[SC_SPLIT_TOP]; nY<nFix; nY++) + { + sal_uInt16 nTSize = pLocalDoc->GetRowHeight( nY, nTab ); + if (nTSize) + { + long nPix = ToPixel( nTSize, nPPTY ); + nNewPos += nPix; + } + } + nNewPos += pView->GetGridOffset().Y(); + if (nNewPos != pTabData[nTab]->nVSplitPos) + { + pTabData[nTab]->nVSplitPos = nNewPos; + if (nTab == nTabNo) + RecalcPixPos(); //! sollte nicht noetig sein !!! + return sal_True; + } + + return sal_False; +} + +void ScViewData::UpdateOutlinerFlags( Outliner& rOutl ) const +{ + ScDocument* pLocalDoc = GetDocument(); + sal_Bool bOnlineSpell = pLocalDoc->GetDocOptions().IsAutoSpell(); + + sal_uLong nCntrl = rOutl.GetControlWord(); + nCntrl |= EE_CNTRL_URLSFXEXECUTE; + nCntrl |= EE_CNTRL_MARKFIELDS; + nCntrl |= EE_CNTRL_AUTOCORRECT; + if( bOnlineSpell ) + nCntrl |= EE_CNTRL_ONLINESPELLING; + else + nCntrl &= ~EE_CNTRL_ONLINESPELLING; + rOutl.SetControlWord(nCntrl); + + rOutl.SetCalcFieldValueHdl( LINK( SC_MOD(), ScModule, CalcFieldValueHdl ) ); + + // #97417# don't call GetSpellChecker if online spelling isn't enabled. + // The language for AutoCorrect etc. is taken from the pool defaults + // (set in ScDocument::UpdateDrawLanguages) + + if ( bOnlineSpell ) + { + com::sun::star::uno::Reference<com::sun::star::linguistic2::XSpellChecker1> xXSpellChecker1( LinguMgr::GetSpellChecker() ); + rOutl.SetSpeller( xXSpellChecker1 ); + } + + rOutl.SetDefaultHorizontalTextDirection( + (EEHorizontalTextDirection)pLocalDoc->GetEditTextDirection( nTabNo ) ); +} + +ScAddress ScViewData::GetCurPos() const +{ + return ScAddress( GetCurX(), GetCurY(), GetTabNo() ); +} + + +// static +void ScViewData::AddPixelsWhile( long & rScrY, long nEndPixels, SCROW & rPosY, + SCROW nEndRow, double nPPTY, const ScDocument * pDoc, SCTAB nTabNo ) +{ + SCROW nRow = rPosY; + while (rScrY <= nEndPixels && nRow <= nEndRow) + { + SCROW nHeightEndRow; + sal_uInt16 nHeight = pDoc->GetRowHeight( nRow, nTabNo, NULL, &nHeightEndRow); + if (nHeightEndRow > nEndRow) + nHeightEndRow = nEndRow; + if (!nHeight) + nRow = nHeightEndRow + 1; + else + { + SCROW nRows = nHeightEndRow - nRow + 1; + sal_Int64 nPixel = ToPixel( nHeight, nPPTY); + sal_Int64 nAdd = nPixel * nRows; + if (nAdd + rScrY > nEndPixels) + { + sal_Int64 nDiff = rScrY + nAdd - nEndPixels; + nRows -= static_cast<SCROW>(nDiff / nPixel); + nAdd = nPixel * nRows; + // We're looking for a value that satisfies loop condition. + if (nAdd + rScrY <= nEndPixels) + { + ++nRows; + nAdd += nPixel; + } + } + rScrY += static_cast<long>(nAdd); + nRow += nRows; + } + } + if (nRow > rPosY) + --nRow; + rPosY = nRow; +} + + +// static +void ScViewData::AddPixelsWhileBackward( long & rScrY, long nEndPixels, + SCROW & rPosY, SCROW nStartRow, double nPPTY, const ScDocument * pDoc, + SCTAB nTabNo ) +{ + SCROW nRow = rPosY; + while (rScrY <= nEndPixels && nRow >= nStartRow) + { + SCROW nHeightStartRow; + sal_uInt16 nHeight = pDoc->GetRowHeight( nRow, nTabNo, &nHeightStartRow, NULL); + if (nHeightStartRow < nStartRow) + nHeightStartRow = nStartRow; + if (!nHeight) + nRow = nHeightStartRow - 1; + else + { + SCROW nRows = nRow - nHeightStartRow + 1; + sal_Int64 nPixel = ToPixel( nHeight, nPPTY); + sal_Int64 nAdd = nPixel * nRows; + if (nAdd + rScrY > nEndPixels) + { + sal_Int64 nDiff = nAdd + rScrY - nEndPixels; + nRows -= static_cast<SCROW>(nDiff / nPixel); + nAdd = nPixel * nRows; + // We're looking for a value that satisfies loop condition. + if (nAdd + rScrY <= nEndPixels) + { + ++nRows; + nAdd += nPixel; + } + } + rScrY += static_cast<long>(nAdd); + nRow -= nRows; + } + } + if (nRow < rPosY) + ++nRow; + rPosY = nRow; +} diff --git a/sc/source/ui/view/viewfun2.cxx b/sc/source/ui/view/viewfun2.cxx new file mode 100644 index 000000000000..c8a02aa1ea2e --- /dev/null +++ b/sc/source/ui/view/viewfun2.cxx @@ -0,0 +1,3144 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +// INCLUDE --------------------------------------------------------------- + +#include "scitems.hxx" +#include <editeng/eeitem.hxx> + +#include <sfx2/app.hxx> +#define _SVSTDARR_STRINGS +#include <editeng/boxitem.hxx> +#include <editeng/fontitem.hxx> +#include <editeng/scripttypeitem.hxx> +#include <svl/srchitem.hxx> +#include <sfx2/linkmgr.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/docfilt.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/objitem.hxx> +#include <sfx2/viewfrm.hxx> +#include <svl/stritem.hxx> +#include <svl/zforlist.hxx> +#include <svl/svstdarr.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/sound.hxx> +#include <vcl/waitobj.hxx> + +#include "viewfunc.hxx" + +#include "sc.hrc" +#include "globstr.hrc" + +#include "attrib.hxx" +#include "autoform.hxx" +#include "cell.hxx" // EnterAutoSum +#include "compiler.hxx" +#include "docfunc.hxx" +#include "docpool.hxx" +#include "docsh.hxx" +#include "global.hxx" +#include "patattr.hxx" +#include "printfun.hxx" +#include "rangenam.hxx" +#include "rangeutl.hxx" +#include "refundo.hxx" +#include "tablink.hxx" +#include "tabvwsh.hxx" +#include "uiitems.hxx" +#include "undoblk.hxx" +#include "undocell.hxx" +#include "undotab.hxx" +#include "sizedev.hxx" +#include "editable.hxx" +#include "scmod.hxx" +#include "inputhdl.hxx" +#include "inputwin.hxx" +#include "funcdesc.hxx" +#include "docuno.hxx" +#include "charthelper.hxx" +#include "tabbgcolor.hxx" + +#include <basic/sbstar.hxx> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/script/XLibraryContainer.hpp> +using namespace com::sun::star; + +// helper func defined in docfunc.cxx +void VBA_DeleteModule( ScDocShell& rDocSh, String& sModuleName ); + +// STATIC DATA --------------------------------------------------------------- + + +//---------------------------------------------------------------------------- + +sal_Bool ScViewFunc::AdjustBlockHeight( sal_Bool bPaint, ScMarkData* pMarkData ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + if (!pMarkData) + pMarkData = &GetViewData()->GetMarkData(); + + ScDocument* pDoc = pDocSh->GetDocument(); + SCCOLROW* pRanges = new SCCOLROW[MAXCOLROWCOUNT]; + SCCOLROW nRangeCnt = pMarkData->GetMarkRowRanges( pRanges ); + if (nRangeCnt == 0) + { + pRanges[0] = pRanges[1] = GetViewData()->GetCurY(); + nRangeCnt = 1; + } + + double nPPTX = GetViewData()->GetPPTX(); + double nPPTY = GetViewData()->GetPPTY(); + Fraction aZoomX = GetViewData()->GetZoomX(); + Fraction aZoomY = GetViewData()->GetZoomY(); + + ScSizeDeviceProvider aProv(pDocSh); + if (aProv.IsPrinter()) + { + nPPTX = aProv.GetPPTX(); + nPPTY = aProv.GetPPTY(); + aZoomX = aZoomY = Fraction( 1, 1 ); + } + + sal_Bool bAnyChanged = sal_False; + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB nTab=0; nTab<nTabCount; nTab++) + { + if (pMarkData->GetTableSelect(nTab)) + { + SCCOLROW* pOneRange = pRanges; + sal_Bool bChanged = sal_False; + SCROW nPaintY = 0; + for (SCROW nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++) + { + SCROW nStartNo = *(pOneRange++); + SCROW nEndNo = *(pOneRange++); + if (pDoc->SetOptimalHeight( nStartNo, nEndNo, nTab, 0, aProv.GetDevice(), + nPPTX, nPPTY, aZoomX, aZoomY, sal_False )) + { + if (!bChanged) + nPaintY = nStartNo; + bAnyChanged = bChanged = sal_True; + } + } + if ( bPaint && bChanged ) + pDocSh->PostPaint( 0, nPaintY, nTab, MAXCOL, MAXROW, nTab, + PAINT_GRID | PAINT_LEFT ); + } + } + delete[] pRanges; + + if ( bPaint && bAnyChanged ) + pDocSh->UpdateOle(GetViewData()); + + return bAnyChanged; +} + + +//---------------------------------------------------------------------------- + +sal_Bool ScViewFunc::AdjustRowHeight( SCROW nStartRow, SCROW nEndRow, sal_Bool bPaint ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = GetViewData()->GetTabNo(); + double nPPTX = GetViewData()->GetPPTX(); + double nPPTY = GetViewData()->GetPPTY(); + Fraction aZoomX = GetViewData()->GetZoomX(); + Fraction aZoomY = GetViewData()->GetZoomY(); + sal_uInt16 nOldPixel = 0; + if (nStartRow == nEndRow) + nOldPixel = (sal_uInt16) (pDoc->GetRowHeight(nStartRow,nTab) * nPPTY); + + ScSizeDeviceProvider aProv(pDocSh); + if (aProv.IsPrinter()) + { + nPPTX = aProv.GetPPTX(); + nPPTY = aProv.GetPPTY(); + aZoomX = aZoomY = Fraction( 1, 1 ); + } + sal_Bool bChanged = pDoc->SetOptimalHeight( nStartRow, nEndRow, nTab, 0, aProv.GetDevice(), + nPPTX, nPPTY, aZoomX, aZoomY, sal_False ); + + if (bChanged && ( nStartRow == nEndRow )) + { + sal_uInt16 nNewPixel = (sal_uInt16) (pDoc->GetRowHeight(nStartRow,nTab) * nPPTY); + if ( nNewPixel == nOldPixel ) + bChanged = sal_False; + } + + if ( bPaint && bChanged ) + pDocSh->PostPaint( 0, nStartRow, nTab, MAXCOL, MAXROW, nTab, + PAINT_GRID | PAINT_LEFT ); + + return bChanged; +} + + +//---------------------------------------------------------------------------- + +enum ScAutoSum +{ + ScAutoSumNone = 0, + ScAutoSumData, + ScAutoSumSum +}; + + +ScAutoSum lcl_IsAutoSumData( ScDocument* pDoc, SCCOL nCol, SCROW nRow, + SCTAB nTab, ScDirection eDir, SCCOLROW& nExtend ) +{ + ScBaseCell* pCell; + pDoc->GetCell( nCol, nRow, nTab, pCell ); + if ( pCell && pCell->HasValueData() ) + { + if ( pCell->GetCellType() == CELLTYPE_FORMULA ) + { + ScTokenArray* pCode = ((ScFormulaCell*)pCell)->GetCode(); + if ( pCode && pCode->GetOuterFuncOpCode() == ocSum ) + { + if ( pCode->GetAdjacentExtendOfOuterFuncRefs( nExtend, + ScAddress( nCol, nRow, nTab ), eDir ) ) + return ScAutoSumSum; + } + } + return ScAutoSumData; + } + return ScAutoSumNone; +} + + +//---------------------------------------------------------------------------- + +#define SC_AUTOSUM_MAXCOUNT 20 + +ScAutoSum lcl_SeekAutoSumData( ScDocument* pDoc, SCCOL& nCol, SCROW& nRow, + SCTAB nTab, ScDirection eDir, SCCOLROW& nExtend ) +{ + sal_uInt16 nCount = 0; + while (nCount < SC_AUTOSUM_MAXCOUNT) + { + if ( eDir == DIR_TOP ) + { + if (nRow > 0) + --nRow; + else + return ScAutoSumNone; + } + else + { + if (nCol > 0) + --nCol; + else + return ScAutoSumNone; + } + ScAutoSum eSum; + if ( (eSum = lcl_IsAutoSumData( + pDoc, nCol, nRow, nTab, eDir, nExtend )) != ScAutoSumNone ) + return eSum; + ++nCount; + } + return ScAutoSumNone; +} + +#undef SC_AUTOSUM_MAXCOUNT + +//---------------------------------------------------------------------------- + +bool lcl_FindNextSumEntryInColumn( ScDocument* pDoc, SCCOL nCol, SCROW& nRow, + SCTAB nTab, SCCOLROW& nExtend, SCROW nMinRow ) +{ + const SCROW nTmp = nRow; + ScAutoSum eSkip = ScAutoSumNone; + while ( ( eSkip = lcl_IsAutoSumData( pDoc, nCol, nRow, nTab, DIR_TOP, nExtend ) ) == ScAutoSumData && + nRow > nMinRow ) + { + --nRow; + } + if ( eSkip == ScAutoSumSum && nRow < nTmp ) + { + return true; + } + return false; +} + +//---------------------------------------------------------------------------- + +bool lcl_FindNextSumEntryInRow( ScDocument* pDoc, SCCOL& nCol, SCROW nRow, + SCTAB nTab, SCCOLROW& nExtend, SCROW nMinCol ) +{ + const SCCOL nTmp = nCol; + ScAutoSum eSkip = ScAutoSumNone; + while ( ( eSkip = lcl_IsAutoSumData( pDoc, nCol, nRow, nTab, DIR_LEFT, nExtend ) ) == ScAutoSumData && + nCol > nMinCol ) + { + --nCol; + } + if ( eSkip == ScAutoSumSum && nCol < nTmp ) + { + return true; + } + return false; +} + +//---------------------------------------------------------------------------- + +bool lcl_GetAutoSumForColumnRange( ScDocument* pDoc, ScRangeList& rRangeList, const ScRange& rRange ) +{ + const ScAddress aStart = rRange.aStart; + const ScAddress aEnd = rRange.aEnd; + if ( aStart.Col() != aEnd.Col() ) + { + return false; + } + + const SCTAB nTab = aEnd.Tab(); + const SCCOL nCol = aEnd.Col(); + SCROW nEndRow = aEnd.Row(); + SCROW nStartRow = nEndRow; + SCCOLROW nExtend = 0; + const ScAutoSum eSum = lcl_IsAutoSumData( pDoc, nCol, nEndRow, nTab, DIR_TOP, nExtend /*out*/ ); + + if ( eSum == ScAutoSumSum ) + { + bool bContinue = false; + do + { + rRangeList.Append( ScRange( nCol, nStartRow, nTab, nCol, nEndRow, nTab ) ); + nEndRow = static_cast< SCROW >( nExtend ); + if ( ( bContinue = lcl_FindNextSumEntryInColumn( pDoc, nCol, nEndRow /*inout*/, nTab, nExtend /*out*/, aStart.Row() ) ) == true ) + { + nStartRow = nEndRow; + } + } while ( bContinue ); + } + else + { + while ( nStartRow > aStart.Row() && + lcl_IsAutoSumData( pDoc, nCol, nStartRow-1, nTab, DIR_TOP, nExtend /*out*/ ) != ScAutoSumSum ) + { + --nStartRow; + } + rRangeList.Append( ScRange( nCol, nStartRow, nTab, nCol, nEndRow, nTab ) ); + } + + return true; +} + +//---------------------------------------------------------------------------- + +bool lcl_GetAutoSumForRowRange( ScDocument* pDoc, ScRangeList& rRangeList, const ScRange& rRange ) +{ + const ScAddress aStart = rRange.aStart; + const ScAddress aEnd = rRange.aEnd; + if ( aStart.Row() != aEnd.Row() ) + { + return false; + } + + const SCTAB nTab = aEnd.Tab(); + const SCROW nRow = aEnd.Row(); + SCCOL nEndCol = aEnd.Col(); + SCCOL nStartCol = nEndCol; + SCCOLROW nExtend = 0; + const ScAutoSum eSum = lcl_IsAutoSumData( pDoc, nEndCol, nRow, nTab, DIR_LEFT, nExtend /*out*/ ); + + if ( eSum == ScAutoSumSum ) + { + bool bContinue = false; + do + { + rRangeList.Append( ScRange( nStartCol, nRow, nTab, nEndCol, nRow, nTab ) ); + nEndCol = static_cast< SCCOL >( nExtend ); + if ( ( bContinue = lcl_FindNextSumEntryInRow( pDoc, nEndCol /*inout*/, nRow, nTab, nExtend /*out*/, aStart.Col() ) ) == true ) + { + nStartCol = nEndCol; + } + } while ( bContinue ); + } + else + { + while ( nStartCol > aStart.Col() && + lcl_IsAutoSumData( pDoc, nStartCol-1, nRow, nTab, DIR_LEFT, nExtend /*out*/ ) != ScAutoSumSum ) + { + --nStartCol; + } + rRangeList.Append( ScRange( nStartCol, nRow, nTab, nEndCol, nRow, nTab ) ); + } + + return true; +} + +//---------------------------------------------------------------------------- + +sal_Bool ScViewFunc::GetAutoSumArea( ScRangeList& rRangeList ) +{ + ScDocument* pDoc = GetViewData()->GetDocument(); + SCTAB nTab = GetViewData()->GetTabNo(); + + SCCOL nCol = GetViewData()->GetCurX(); + SCROW nRow = GetViewData()->GetCurY(); + + SCCOL nStartCol = nCol; + SCROW nStartRow = nRow; + SCCOL nEndCol = nCol; + SCROW nEndRow = nRow; + SCCOL nSeekCol = nCol; + SCROW nSeekRow = nRow; + SCCOLROW nExtend; // wird per Reference gueltig bei ScAutoSumSum + + sal_Bool bCol = sal_False; + sal_Bool bRow = sal_False; + + ScAutoSum eSum; + if ( nRow != 0 + && ((eSum = lcl_IsAutoSumData( pDoc, nCol, nRow-1, nTab, + DIR_TOP, nExtend /*out*/ )) == ScAutoSumData ) + && ((eSum = lcl_IsAutoSumData( pDoc, nCol, nRow-1, nTab, + DIR_LEFT, nExtend /*out*/ )) == ScAutoSumData ) + ) + { + bRow = sal_True; + nSeekRow = nRow - 1; + } + else if ( nCol != 0 && (eSum = lcl_IsAutoSumData( pDoc, nCol-1, nRow, nTab, + DIR_LEFT, nExtend /*out*/ )) == ScAutoSumData ) + { + bCol = sal_True; + nSeekCol = nCol - 1; + } + else if ( (eSum = lcl_SeekAutoSumData( pDoc, nCol, nSeekRow, nTab, DIR_TOP, nExtend /*out*/ )) != ScAutoSumNone ) + bRow = sal_True; + else if (( eSum = lcl_SeekAutoSumData( pDoc, nSeekCol, nRow, nTab, DIR_LEFT, nExtend /*out*/ )) != ScAutoSumNone ) + bCol = sal_True; + + if ( bCol || bRow ) + { + if ( bRow ) + { + nStartRow = nSeekRow; // nSeekRow evtl. per Reference angepasst + if ( eSum == ScAutoSumSum ) + nEndRow = nStartRow; // nur Summen summieren + else + nEndRow = nRow - 1; // Datenbereich evtl. nach unten erweitern + } + else + { + nStartCol = nSeekCol; // nSeekCol evtl. per Reference angepasst + if ( eSum == ScAutoSumSum ) + nEndCol = nStartCol; // nur Summen summieren + else + nEndCol = nCol - 1; // Datenbereich evtl. nach rechts erweitern + } + sal_Bool bContinue = sal_False; + do + { + if ( eSum == ScAutoSumData ) + { + if ( bRow ) + { + while ( nStartRow != 0 && lcl_IsAutoSumData( pDoc, nCol, + nStartRow-1, nTab, DIR_TOP, nExtend /*out*/ ) == eSum ) + --nStartRow; + } + else + { + while ( nStartCol != 0 && lcl_IsAutoSumData( pDoc, nStartCol-1, + nRow, nTab, DIR_LEFT, nExtend /*out*/ ) == eSum ) + --nStartCol; + } + } + rRangeList.Append( + ScRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab ) ); + if ( eSum == ScAutoSumSum ) + { + if ( bRow ) + { + nEndRow = static_cast< SCROW >( nExtend ); + if ( ( bContinue = lcl_FindNextSumEntryInColumn( pDoc, nCol, nEndRow /*inout*/, nTab, nExtend /*out*/, 0 ) ) == true ) + { + nStartRow = nEndRow; + } + } + else + { + nEndCol = static_cast< SCCOL >( nExtend ); + if ( ( bContinue = lcl_FindNextSumEntryInRow( pDoc, nEndCol /*inout*/, nRow, nTab, nExtend /*out*/, 0 ) ) == true ) + { + nStartCol = nEndCol; + } + } + } + } while ( bContinue ); + return sal_True; + } + return sal_False; +} + +//---------------------------------------------------------------------------- + +void ScViewFunc::EnterAutoSum(const ScRangeList& rRangeList, sal_Bool bSubTotal) // Block mit Summen fuellen +{ + String aFormula = GetAutoSumFormula( rRangeList, bSubTotal ); + EnterBlock( aFormula, NULL ); +} + +//---------------------------------------------------------------------------- + +bool ScViewFunc::AutoSum( const ScRange& rRange, bool bSubTotal, bool bSetCursor, bool bContinue ) +{ + ScDocument* pDoc = GetViewData()->GetDocument(); + const SCTAB nTab = rRange.aStart.Tab(); + SCCOL nStartCol = rRange.aStart.Col(); + SCROW nStartRow = rRange.aStart.Row(); + const SCCOL nEndCol = rRange.aEnd.Col(); + const SCROW nEndRow = rRange.aEnd.Row(); + SCCOLROW nExtend = 0; // out parameter for lcl_IsAutoSumData + + // ignore rows at the top of the given range which don't contain autosum data + bool bRowData = false; + for ( SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow ) + { + for ( SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol ) + { + if ( lcl_IsAutoSumData( pDoc, nCol, nRow, nTab, DIR_TOP, nExtend ) != ScAutoSumNone ) + { + bRowData = true; + break; + } + } + if ( bRowData ) + { + nStartRow = nRow; + break; + } + } + if ( !bRowData ) + { + return false; + } + + // ignore columns at the left of the given range which don't contain autosum data + bool bColData = false; + for ( SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol ) + { + for ( SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow ) + { + if ( lcl_IsAutoSumData( pDoc, nCol, nRow, nTab, DIR_LEFT, nExtend ) != ScAutoSumNone ) + { + bColData = true; + break; + } + } + if ( bColData ) + { + nStartCol = nCol; + break; + } + } + if ( !bColData ) + { + return false; + } + + const bool bEndRowEmpty = pDoc->IsBlockEmpty( nTab, nStartCol, nEndRow, nEndCol, nEndRow ); + const bool bEndColEmpty = pDoc->IsBlockEmpty( nTab, nEndCol, nStartRow, nEndCol, nEndRow ); + bool bRow = ( ( nStartRow != nEndRow ) && ( bEndRowEmpty || ( !bEndRowEmpty && !bEndColEmpty ) ) ); + bool bCol = ( ( nStartCol != nEndCol ) && ( bEndColEmpty || nStartRow == nEndRow ) ); + + // find an empty row for entering the result + SCROW nInsRow = nEndRow; + if ( bRow && !bEndRowEmpty ) + { + if ( nInsRow < MAXROW ) + { + ++nInsRow; + while ( !pDoc->IsBlockEmpty( nTab, nStartCol, nInsRow, nEndCol, nInsRow ) ) + { + if ( nInsRow < MAXROW ) + { + ++nInsRow; + } + else + { + bRow = false; + break; + } + } + } + else + { + bRow = false; + } + } + + // find an empty column for entering the result + SCCOL nInsCol = nEndCol; + if ( bCol && !bEndColEmpty ) + { + if ( nInsCol < MAXCOL ) + { + ++nInsCol; + while ( !pDoc->IsBlockEmpty( nTab, nInsCol, nStartRow, nInsCol, nEndRow ) ) + { + if ( nInsCol < MAXCOL ) + { + ++nInsCol; + } + else + { + bCol = false; + break; + } + } + } + else + { + bCol = false; + } + } + + if ( !bRow && !bCol ) + { + return false; + } + + SCCOL nMarkEndCol = nEndCol; + SCROW nMarkEndRow = nEndRow; + + if ( bRow ) + { + // calculate the row sums for all columns of the given range + + SCROW nSumEndRow = nEndRow; + + if ( bEndRowEmpty ) + { + // the last row of the given range is empty; + // don't take into account for calculating the autosum + --nSumEndRow; + } + else + { + // increase mark range + ++nMarkEndRow; + } + + for ( SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol ) + { + if ( !pDoc->IsBlockEmpty( nTab, nCol, nStartRow, nCol, nSumEndRow ) ) + { + ScRangeList aRangeList; + const ScRange aRange( nCol, nStartRow, nTab, nCol, nSumEndRow, nTab ); + if ( lcl_GetAutoSumForColumnRange( pDoc, aRangeList, aRange ) ) + { + const String aFormula = GetAutoSumFormula( aRangeList, bSubTotal ); + EnterData( nCol, nInsRow, nTab, aFormula ); + } + } + } + } + + if ( bCol ) + { + // calculate the column sums for all rows of the given range + + SCCOL nSumEndCol = nEndCol; + + if ( bEndColEmpty ) + { + // the last column of the given range is empty; + // don't take into account for calculating the autosum + --nSumEndCol; + } + else + { + // increase mark range + ++nMarkEndCol; + } + + for ( SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow ) + { + if ( !pDoc->IsBlockEmpty( nTab, nStartCol, nRow, nSumEndCol, nRow ) ) + { + ScRangeList aRangeList; + const ScRange aRange( nStartCol, nRow, nTab, nSumEndCol, nRow, nTab ); + if ( lcl_GetAutoSumForRowRange( pDoc, aRangeList, aRange ) ) + { + const String aFormula = GetAutoSumFormula( aRangeList, bSubTotal ); + EnterData( nInsCol, nRow, nTab, aFormula ); + } + } + } + } + + // set new mark range and cursor position + const ScRange aMarkRange( nStartCol, nStartRow, nTab, nMarkEndCol, nMarkEndRow, nTab ); + MarkRange( aMarkRange, sal_False, bContinue ); + if ( bSetCursor ) + { + SetCursor( nMarkEndCol, nMarkEndRow ); + } + + return true; +} + +//---------------------------------------------------------------------------- + +String ScViewFunc::GetAutoSumFormula( const ScRangeList& rRangeList, bool bSubTotal ) +{ + String aFormula = '='; + ScFunctionMgr* pFuncMgr = ScGlobal::GetStarCalcFunctionMgr(); + const ScFuncDesc* pDesc = NULL; + if ( bSubTotal ) + { + pDesc = pFuncMgr->Get( SC_OPCODE_SUB_TOTAL ); + } + else + { + pDesc = pFuncMgr->Get( SC_OPCODE_SUM ); + } + if ( pDesc && pDesc->pFuncName ) + { + aFormula += *pDesc->pFuncName; + if ( bSubTotal ) + { + aFormula.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "(9;" ) ); + } + else + { + aFormula += '('; + } + ScDocument* pDoc = GetViewData()->GetDocument(); + String aRef; + rRangeList.Format( aRef, SCA_VALID, pDoc ); + aFormula += aRef; + aFormula += ')'; + } + return aFormula; +} + +//---------------------------------------------------------------------------- + +void ScViewFunc::EnterBlock( const String& rString, const EditTextObject* pData ) +{ + // Mehrfachselektion vorher abfragen... + + SCCOL nCol = GetViewData()->GetCurX(); + SCROW nRow = GetViewData()->GetCurY(); + SCTAB nTab = GetViewData()->GetTabNo(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + if ( rMark.IsMultiMarked() ) + { + rMark.MarkToSimple(); + if ( rMark.IsMultiMarked() ) + { // "Einfuegen auf Mehrfachselektion nicht moeglich" + ErrorMessage(STR_MSSG_PASTEFROMCLIP_0); + + // insert into single cell + if ( pData ) + EnterData( nCol, nRow, nTab, pData ); + else + EnterData( nCol, nRow, nTab, rString ); + return; + } + } + + ScDocument* pDoc = GetViewData()->GetDocument(); + String aNewStr = rString; + if ( pData ) + { + const ScPatternAttr* pOldPattern = pDoc->GetPattern( nCol, nRow, nTab ); + ScTabEditEngine aEngine( *pOldPattern, pDoc->GetEnginePool() ); + aEngine.SetText(*pData); + + ScEditAttrTester aTester( &aEngine ); + if (!aTester.NeedsObject()) + { + aNewStr = aEngine.GetText(); + pData = NULL; + } + } + + // Einfuegen per PasteFromClip + + WaitObject aWait( GetFrameWin() ); + + ScAddress aPos( nCol, nRow, nTab ); + + ScDocument* pInsDoc = new ScDocument( SCDOCMODE_CLIP ); + pInsDoc->ResetClip( pDoc, nTab ); + + if (aNewStr.GetChar(0) == '=') // Formel ? + { + // SetString geht nicht, weil in Clipboard-Dokumenten nicht kompiliert wird! + ScFormulaCell* pFCell = new ScFormulaCell( pDoc, aPos, aNewStr ); + pInsDoc->PutCell( nCol, nRow, nTab, pFCell ); + } + else if ( pData ) + pInsDoc->PutCell( nCol, nRow, nTab, new ScEditCell( pData, pDoc, NULL ) ); + else + pInsDoc->SetString( nCol, nRow, nTab, aNewStr ); + + pInsDoc->SetClipArea( ScRange(aPos) ); + // auf Block einfuegen, mit Undo etc. + if ( PasteFromClip( IDF_CONTENTS, pInsDoc, PASTE_NOFUNC, sal_False, sal_False, + sal_False, INS_NONE, IDF_ATTRIB ) ) + { + const SfxUInt32Item* pItem = (SfxUInt32Item*) pInsDoc->GetAttr( + nCol, nRow, nTab, ATTR_VALUE_FORMAT ); + if ( pItem ) + { // Numberformat setzen wenn inkompatibel + // MarkData wurde bereits in PasteFromClip MarkToSimple'ed + ScRange aRange; + rMark.GetMarkArea( aRange ); + ScPatternAttr* pPattern = new ScPatternAttr( pDoc->GetPool() ); + pPattern->GetItemSet().Put( *pItem ); + short nNewType = pDoc->GetFormatTable()->GetType( pItem->GetValue() ); + pDoc->ApplyPatternIfNumberformatIncompatible( aRange, rMark, + *pPattern, nNewType ); + delete pPattern; + } + } + + delete pInsDoc; +} + + +//---------------------------------------------------------------------------- + +//UNUSED2008-05 void ScViewFunc::PaintWidthHeight( sal_Bool bColumns, SCCOLROW nStart, SCCOLROW nEnd ) +//UNUSED2008-05 { +//UNUSED2008-05 SCTAB nTab = GetViewData()->GetTabNo(); +//UNUSED2008-05 ScDocument* pDoc = GetViewData()->GetDocument(); +//UNUSED2008-05 +//UNUSED2008-05 sal_uInt16 nParts = PAINT_GRID; +//UNUSED2008-05 SCCOL nStartCol = 0; +//UNUSED2008-05 SCROW nStartRow = 0; +//UNUSED2008-05 SCCOL nEndCol = MAXCOL; // fuer Test auf Merge +//UNUSED2008-05 SCROW nEndRow = MAXROW; +//UNUSED2008-05 if ( bColumns ) +//UNUSED2008-05 { +//UNUSED2008-05 nParts |= PAINT_TOP; +//UNUSED2008-05 nStartCol = static_cast<SCCOL>(nStart); +//UNUSED2008-05 nEndCol = static_cast<SCCOL>(nEnd); +//UNUSED2008-05 } +//UNUSED2008-05 else +//UNUSED2008-05 { +//UNUSED2008-05 nParts |= PAINT_LEFT; +//UNUSED2008-05 nStartRow = nStart; +//UNUSED2008-05 nEndRow = nEnd; +//UNUSED2008-05 } +//UNUSED2008-05 if (pDoc->HasAttrib( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab, +//UNUSED2008-05 HASATTR_MERGED | HASATTR_OVERLAPPED )) +//UNUSED2008-05 { +//UNUSED2008-05 nStartCol = 0; +//UNUSED2008-05 nStartRow = 0; +//UNUSED2008-05 } +//UNUSED2008-05 GetViewData()->GetDocShell()->PostPaint( nStartCol,nStartRow,nTab, MAXCOL,MAXROW,nTab, nParts ); +//UNUSED2008-05 } + + +//---------------------------------------------------------------------------- +// manueller Seitenumbruch + +void ScViewFunc::InsertPageBreak( sal_Bool bColumn, sal_Bool bRecord, const ScAddress* pPos, + sal_Bool bSetModified ) +{ + SCTAB nTab = GetViewData()->GetTabNo(); + ScAddress aCursor; + if (pPos) + aCursor = *pPos; + else + aCursor = ScAddress( GetViewData()->GetCurX(), GetViewData()->GetCurY(), nTab ); + + sal_Bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc(). + InsertPageBreak( bColumn, aCursor, bRecord, bSetModified, sal_False ); + + if ( bSuccess && bSetModified ) + UpdatePageBreakData( sal_True ); // fuer PageBreak-Modus +} + + +//---------------------------------------------------------------------------- + +void ScViewFunc::DeletePageBreak( sal_Bool bColumn, sal_Bool bRecord, const ScAddress* pPos, + sal_Bool bSetModified ) +{ + SCTAB nTab = GetViewData()->GetTabNo(); + ScAddress aCursor; + if (pPos) + aCursor = *pPos; + else + aCursor = ScAddress( GetViewData()->GetCurX(), GetViewData()->GetCurY(), nTab ); + + sal_Bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc(). + RemovePageBreak( bColumn, aCursor, bRecord, bSetModified, sal_False ); + + if ( bSuccess && bSetModified ) + UpdatePageBreakData( sal_True ); // fuer PageBreak-Modus +} + +//---------------------------------------------------------------------------- + +void ScViewFunc::RemoveManualBreaks() +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = GetViewData()->GetTabNo(); + sal_Bool bUndo(pDoc->IsUndoEnabled()); + + if (bUndo) + { + ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_True ); + pDoc->CopyToDocument( 0,0,nTab, MAXCOL,MAXROW,nTab, IDF_NONE, sal_False, pUndoDoc ); + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoRemoveBreaks( pDocSh, nTab, pUndoDoc ) ); + } + + pDoc->RemoveManualBreaks(nTab); + pDoc->UpdatePageBreaks(nTab); + + UpdatePageBreakData( sal_True ); + pDocSh->SetDocumentModified(); + pDocSh->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID ); +} + +//---------------------------------------------------------------------------- + +void ScViewFunc::SetPrintZoom(sal_uInt16 nScale, sal_uInt16 nPages) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + SCTAB nTab = GetViewData()->GetTabNo(); + pDocSh->SetPrintZoom( nTab, nScale, nPages ); +} + +void ScViewFunc::AdjustPrintZoom() +{ + ScRange aRange; + if ( GetViewData()->GetSimpleArea( aRange ) != SC_MARK_SIMPLE ) + GetViewData()->GetMarkData().GetMultiMarkArea( aRange ); + GetViewData()->GetDocShell()->AdjustPrintZoom( aRange ); +} + +//---------------------------------------------------------------------------- + +void ScViewFunc::SetPrintRanges( sal_Bool bEntireSheet, const String* pPrint, + const String* pRepCol, const String* pRepRow, + sal_Bool bAddPrint ) +{ + // on all selected tables + + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTabCount = pDoc->GetTableCount(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + SCTAB nTab; + sal_Bool bUndo (pDoc->IsUndoEnabled()); + + ScPrintRangeSaver* pOldRanges = pDoc->CreatePrintRangeSaver(); + + ScAddress::Details aDetails(pDoc->GetAddressConvention(), 0, 0); + + for (nTab=0; nTab<nTabCount; nTab++) + if (rMark.GetTableSelect(nTab)) + { + ScRange aRange( 0,0,nTab ); + + // print ranges + + if( !bAddPrint ) + pDoc->ClearPrintRanges( nTab ); + + if( bEntireSheet ) + { + pDoc->SetPrintEntireSheet( nTab ); + } + else if ( pPrint ) + { + if ( pPrint->Len() ) + { + const sal_Unicode sep = ScCompiler::GetNativeSymbol(ocSep).GetChar(0); + sal_uInt16 nTCount = pPrint->GetTokenCount(sep); + for (sal_uInt16 i=0; i<nTCount; i++) + { + String aToken = pPrint->GetToken(i, sep); + if ( aRange.ParseAny( aToken, pDoc, aDetails ) & SCA_VALID ) + pDoc->AddPrintRange( nTab, aRange ); + } + } + } + else // NULL = use selection (print range is always set), use empty string to delete all ranges + { + if ( GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE ) + { + pDoc->AddPrintRange( nTab, aRange ); + } + else if ( rMark.IsMultiMarked() ) + { + rMark.MarkToMulti(); + ScRangeListRef aList( new ScRangeList ); + rMark.FillRangeListWithMarks( aList, sal_False ); + sal_uInt16 nCnt = (sal_uInt16) aList->Count(); + if ( nCnt ) + { + ScRangePtr pR; + sal_uInt16 i; + for ( pR = aList->First(), i=0; i < nCnt; + pR = aList->Next(), i++ ) + { + pDoc->AddPrintRange( nTab, *pR ); + } + } + } + } + + // repeat columns + + if ( pRepCol ) + { + if ( !pRepCol->Len() ) + pDoc->SetRepeatColRange( nTab, NULL ); + else + if ( aRange.ParseAny( *pRepCol, pDoc, aDetails ) & SCA_VALID ) + pDoc->SetRepeatColRange( nTab, &aRange ); + } + + // repeat rows + + if ( pRepRow ) + { + if ( !pRepRow->Len() ) + pDoc->SetRepeatRowRange( nTab, NULL ); + else + if ( aRange.ParseAny( *pRepRow, pDoc, aDetails ) & SCA_VALID ) + pDoc->SetRepeatRowRange( nTab, &aRange ); + } + } + + // undo (for all tables) + if (bUndo) + { + SCTAB nCurTab = GetViewData()->GetTabNo(); + ScPrintRangeSaver* pNewRanges = pDoc->CreatePrintRangeSaver(); + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoPrintRange( pDocSh, nCurTab, pOldRanges, pNewRanges ) ); + } + + // update page breaks + + for (nTab=0; nTab<nTabCount; nTab++) + if (rMark.GetTableSelect(nTab)) + ScPrintFunc( pDocSh, pDocSh->GetPrinter(), nTab ).UpdatePages(); + + SfxBindings& rBindings = GetViewData()->GetBindings(); + rBindings.Invalidate( SID_DELETE_PRINTAREA ); + + pDocSh->SetDocumentModified(); +} + +//---------------------------------------------------------------------------- +// Zellen zusammenfassen + +sal_Bool ScViewFunc::TestMergeCells() // Vorab-Test (fuer Menue) +{ + // simple test: sal_True if there's a selection but no multi selection and not filtered + + const ScMarkData& rMark = GetViewData()->GetMarkData(); + if ( rMark.IsMarked() || rMark.IsMultiMarked() ) + { + ScRange aDummy; + return GetViewData()->GetSimpleArea( aDummy) == SC_MARK_SIMPLE; + } + else + return sal_False; +} + + +//---------------------------------------------------------------------------- + +sal_Bool ScViewFunc::MergeCells( sal_Bool bApi, sal_Bool& rDoContents, sal_Bool bRecord ) +{ + // Editable- und Verschachtelungs-Abfrage muss vorneweg sein (auch in DocFunc), + // damit dann nicht die Inhalte-QueryBox kommt + ScEditableTester aTester( this ); + if (!aTester.IsEditable()) + { + ErrorMessage(aTester.GetMessageId()); + return sal_False; + } + + ScMarkData& rMark = GetViewData()->GetMarkData(); + rMark.MarkToSimple(); + if (!rMark.IsMarked()) + { + ErrorMessage(STR_NOMULTISELECT); + return sal_False; + } + + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + + ScRange aMarkRange; + rMark.GetMarkArea( aMarkRange ); + SCCOL nStartCol = aMarkRange.aStart.Col(); + SCROW nStartRow = aMarkRange.aStart.Row(); + SCTAB nStartTab = aMarkRange.aStart.Tab(); + SCCOL nEndCol = aMarkRange.aEnd.Col(); + SCROW nEndRow = aMarkRange.aEnd.Row(); + SCTAB nEndTab = aMarkRange.aEnd.Tab(); + if ( nStartCol == nEndCol && nStartRow == nEndRow ) + { + // nichts zu tun + return sal_True; + } + + if ( pDoc->HasAttrib( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab, + HASATTR_MERGED | HASATTR_OVERLAPPED ) ) + { // "Zusammenfassen nicht verschachteln !" + ErrorMessage(STR_MSSG_MERGECELLS_0); + return sal_False; + } + + sal_Bool bOk = sal_True; + + if ( !pDoc->IsBlockEmpty( nStartTab, nStartCol,nStartRow+1, nStartCol,nEndRow, true ) || + !pDoc->IsBlockEmpty( nStartTab, nStartCol+1,nStartRow, nEndCol,nEndRow, true ) ) + { + if (!bApi) + { + MessBox aBox( GetViewData()->GetDialogParent(), + WinBits(WB_YES_NO_CANCEL | WB_DEF_NO), + ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_0 ), + ScGlobal::GetRscString( STR_MERGE_NOTEMPTY ) ); + sal_uInt16 nRetVal = aBox.Execute(); + + if ( nRetVal == RET_YES ) + rDoContents = sal_True; + else if ( nRetVal == RET_CANCEL ) + bOk = sal_False; + } + } + + if (bOk) + { + HideCursor(); + bOk = pDocSh->GetDocFunc().MergeCells( aMarkRange, rDoContents, bRecord, bApi ); + ShowCursor(); + + if (bOk) + { + SetCursor( nStartCol, nStartRow ); + //DoneBlockMode( sal_False); + Unmark(); + + pDocSh->UpdateOle(GetViewData()); + UpdateInputLine(); + } + } + + return bOk; +} + + +//---------------------------------------------------------------------------- + +sal_Bool ScViewFunc::TestRemoveMerge() +{ + sal_Bool bMerged = sal_False; + ScRange aRange; + if (GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE) + { + ScDocument* pDoc = GetViewData()->GetDocument(); + if ( pDoc->HasAttrib( aRange, HASATTR_MERGED ) ) + bMerged = sal_True; + } + return bMerged; +} + + +//---------------------------------------------------------------------------- + +sal_Bool ScViewFunc::RemoveMerge( sal_Bool bRecord ) +{ + ScRange aRange; + ScEditableTester aTester( this ); + if (!aTester.IsEditable()) + { + ErrorMessage(aTester.GetMessageId()); + return sal_False; + } + else if (GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE) + { + ScRange aExtended( aRange ); + GetViewData()->GetDocument()->ExtendMerge( aExtended ); + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + + HideCursor(); + sal_Bool bOk = pDocSh->GetDocFunc().UnmergeCells( aRange, bRecord, sal_False ); + MarkRange( aExtended ); + ShowCursor(); + + if (bOk) + pDocSh->UpdateOle(GetViewData()); + } + return sal_True; //! bOk ?? +} + +//---------------------------------------------------------------------------- + +void ScViewFunc::FillSimple( FillDir eDir, sal_Bool bRecord ) +{ + ScRange aRange; + if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE) + { + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + const ScMarkData& rMark = GetViewData()->GetMarkData(); + sal_Bool bSuccess = pDocSh->GetDocFunc().FillSimple( aRange, &rMark, eDir, bRecord, sal_False ); + if (bSuccess) + { + pDocSh->UpdateOle(GetViewData()); + UpdateScrollBars(); + } + } + else + ErrorMessage(STR_NOMULTISELECT); +} + +//---------------------------------------------------------------------------- + +void ScViewFunc::FillSeries( FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd, + double fStart, double fStep, double fMax, sal_Bool bRecord ) +{ + ScRange aRange; + if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE) + { + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + const ScMarkData& rMark = GetViewData()->GetMarkData(); + sal_Bool bSuccess = pDocSh->GetDocFunc(). + FillSeries( aRange, &rMark, eDir, eCmd, eDateCmd, + fStart, fStep, fMax, bRecord, sal_False ); + if (bSuccess) + { + pDocSh->UpdateOle(GetViewData()); + UpdateScrollBars(); + + // #i97876# Spreadsheet data changes are not notified + ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() ); + if ( pModelObj && pModelObj->HasChangesListeners() ) + { + ScRangeList aChangeRanges; + aChangeRanges.Append( aRange ); + pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges ); + } + } + } + else + ErrorMessage(STR_NOMULTISELECT); +} + +//---------------------------------------------------------------------------- + +void ScViewFunc::FillAuto( FillDir eDir, SCCOL nStartCol, SCROW nStartRow, + SCCOL nEndCol, SCROW nEndRow, sal_uLong nCount, sal_Bool bRecord ) +{ + SCTAB nTab = GetViewData()->GetTabNo(); + ScRange aRange( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab ); + ScRange aSourceRange( aRange ); + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + const ScMarkData& rMark = GetViewData()->GetMarkData(); + sal_Bool bSuccess = pDocSh->GetDocFunc(). + FillAuto( aRange, &rMark, eDir, nCount, bRecord, sal_False ); + if (bSuccess) + { + MarkRange( aRange, sal_False ); // aRange ist in FillAuto veraendert worden + pDocSh->UpdateOle(GetViewData()); + UpdateScrollBars(); + + // #i97876# Spreadsheet data changes are not notified + ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() ); + if ( pModelObj && pModelObj->HasChangesListeners() ) + { + ScRangeList aChangeRanges; + ScRange aChangeRange( aRange ); + switch ( eDir ) + { + case FILL_TO_BOTTOM: + { + aChangeRange.aStart.SetRow( aSourceRange.aEnd.Row() + 1 ); + } + break; + case FILL_TO_TOP: + { + aChangeRange.aEnd.SetRow( aSourceRange.aStart.Row() - 1 ); + } + break; + case FILL_TO_RIGHT: + { + aChangeRange.aStart.SetCol( aSourceRange.aEnd.Col() + 1 ); + } + break; + case FILL_TO_LEFT: + { + aChangeRange.aEnd.SetCol( aSourceRange.aStart.Col() - 1 ); + } + break; + default: + { + + } + break; + } + aChangeRanges.Append( aChangeRange ); + pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges ); + } + } +} + +//---------------------------------------------------------------------------- + +void ScViewFunc::FillTab( sal_uInt16 nFlags, sal_uInt16 nFunction, sal_Bool bSkipEmpty, sal_Bool bAsLink ) +{ + //! allow source sheet to be protected + ScEditableTester aTester( this ); + if (!aTester.IsEditable()) + { + ErrorMessage(aTester.GetMessageId()); + return; + } + + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + SCTAB nTab = GetViewData()->GetTabNo(); + sal_Bool bUndo(pDoc->IsUndoEnabled()); + + ScRange aMarkRange; + rMark.MarkToSimple(); + sal_Bool bMulti = rMark.IsMultiMarked(); + if (bMulti) + rMark.GetMultiMarkArea( aMarkRange ); + else if (rMark.IsMarked()) + rMark.GetMarkArea( aMarkRange ); + else + aMarkRange = ScRange( GetViewData()->GetCurX(), GetViewData()->GetCurY(), nTab ); + + ScDocument* pUndoDoc = NULL; +// if ( bRecord ) + if (bUndo) + { + pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + pUndoDoc->InitUndo( pDoc, nTab, nTab ); +// pUndoDoc->SelectTable( nTab, sal_True ); // nur fuer Markierung + + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB i=0; i<nTabCount; i++) + if (i != nTab && rMark.GetTableSelect(i)) + { + pUndoDoc->AddUndoTab( i, i ); + aMarkRange.aStart.SetTab( i ); + aMarkRange.aEnd.SetTab( i ); + pDoc->CopyToDocument( aMarkRange, IDF_ALL, bMulti, pUndoDoc ); +// pUndoDoc->SelectTable( i, sal_True ); + } + } + + if (bMulti) + pDoc->FillTabMarked( nTab, rMark, nFlags, nFunction, bSkipEmpty, bAsLink ); + else + { + aMarkRange.aStart.SetTab( nTab ); + aMarkRange.aEnd.SetTab( nTab ); + pDoc->FillTab( aMarkRange, rMark, nFlags, nFunction, bSkipEmpty, bAsLink ); + } + +// if ( bRecord ) + if (bUndo) + { //! fuer ChangeTrack erst zum Schluss + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoFillTable( pDocSh, rMark, + aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nTab, + aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), nTab, + pUndoDoc, bMulti, nTab, nFlags, nFunction, bSkipEmpty, bAsLink ) ); + } + + pDocSh->PostPaintGridAll(); + pDocSh->PostDataChanged(); +} + +//---------------------------------------------------------------------------- + +/** Downward fill of selected cell(s) by double-clicking cross-hair cursor + + Extends a current selection down to the last non-empty cell of an adjacent + column when the lower-right corner of the selection is double-clicked. It + uses a left-adjoining non-empty column as a guide if such is available, + otherwise a right-adjoining non-empty column is used. + + @author Kohei Yoshida (kohei@openoffice.org) + + @return No return value + + @see #i12313# +*/ +void ScViewFunc::FillCrossDblClick() +{ + ScRange aRange; + GetViewData()->GetSimpleArea( aRange ); + aRange.Justify(); + + SCTAB nTab = GetViewData()->GetCurPos().Tab(); + SCCOL nStartX = aRange.aStart.Col(); + SCROW nStartY = aRange.aStart.Row(); + SCCOL nEndX = aRange.aEnd.Col(); + SCROW nEndY = aRange.aEnd.Row(); + + ScDocument* pDoc = GetViewData()->GetDocument(); + + // Make sure the selection is not empty + if ( pDoc->IsBlockEmpty( nTab, nStartX, nStartY, nEndX, nEndY ) ) + return; + + if ( nEndY < MAXROW ) + { + if ( nStartX > 0 ) + { + SCCOL nMovX = nStartX - 1; + SCROW nMovY = nStartY; + + if ( pDoc->HasData( nMovX, nStartY, nTab ) && + pDoc->HasData( nMovX, nStartY + 1, nTab ) ) + { + pDoc->FindAreaPos( nMovX, nMovY, nTab, 0, 1 ); + + if ( nMovY > nEndY ) + { + FillAuto( FILL_TO_BOTTOM, nStartX, nStartY, nEndX, nEndY, + nMovY - nEndY ); + return; + } + } + } + + if ( nEndX < MAXCOL ) + { + SCCOL nMovX = nEndX + 1; + SCROW nMovY = nStartY; + + if ( pDoc->HasData( nMovX, nStartY, nTab ) && + pDoc->HasData( nMovX, nStartY + 1, nTab ) ) + { + pDoc->FindAreaPos( nMovX, nMovY, nTab, 0, 1 ); + + if ( nMovY > nEndY ) + { + FillAuto( FILL_TO_BOTTOM, nStartX, nStartY, nEndX, nEndY, + nMovY - nEndY ); + return; + } + } + } + } +} + +//---------------------------------------------------------------------------- + +void ScViewFunc::TransliterateText( sal_Int32 nType ) +{ + ScMarkData aFuncMark = GetViewData()->GetMarkData(); + if ( !aFuncMark.IsMarked() && !aFuncMark.IsMultiMarked() ) + { + // no selection -> use cursor position + + ScAddress aCursor( GetViewData()->GetCurX(), GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); + aFuncMark.SetMarkArea( ScRange( aCursor ) ); + } + + sal_Bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc(). + TransliterateText( aFuncMark, nType, sal_True, sal_False ); + if (bSuccess) + { + GetViewData()->GetViewShell()->UpdateInputHandler(); + } +} + +//---------------------------------------------------------------------------- +// AutoFormat + +ScAutoFormatData* ScViewFunc::CreateAutoFormatData() +{ + ScAutoFormatData* pData = NULL; + SCCOL nStartCol; + SCROW nStartRow; + SCTAB nStartTab; + SCCOL nEndCol; + SCROW nEndRow; + SCTAB nEndTab; + if (GetViewData()->GetSimpleArea(nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab) == SC_MARK_SIMPLE) + { + if ( nEndCol-nStartCol >= 3 && nEndRow-nStartRow >= 3 ) + { + ScDocument* pDoc = GetViewData()->GetDocument(); + pData = new ScAutoFormatData; + pDoc->GetAutoFormatData( nStartTab, nStartCol,nStartRow,nEndCol,nEndRow, *pData ); + } + } + return pData; +} + + +//---------------------------------------------------------------------------- + +void ScViewFunc::AutoFormat( sal_uInt16 nFormatNo, sal_Bool bRecord ) +{ +#if 1 + + ScRange aRange; + if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE) + { + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + + sal_Bool bSuccess = pDocSh->GetDocFunc().AutoFormat( aRange, &rMark, nFormatNo, bRecord, sal_False ); + if (bSuccess) + pDocSh->UpdateOle(GetViewData()); + } + else + ErrorMessage(STR_NOMULTISELECT); + +#else + + // nur wegen Matrix nicht editierbar? Attribute trotzdem ok + sal_Bool bOnlyNotBecauseOfMatrix; + if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix ) + { + ErrorMessage(STR_PROTECTIONERR); + return; + } + + SCCOL nStartCol; + SCROW nStartRow; + SCTAB nStartTab; + SCCOL nEndCol; + SCROW nEndRow; + SCTAB nEndTab; + + if (GetViewData()->GetSimpleArea(nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab) == SC_MARK_SIMPLE) + { + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + sal_Bool bSize = (*ScGlobal::GetAutoFormat())[nFormatNo]->GetIncludeWidthHeight(); + if (bRecord && !pDoc->IsUndoEnabled()) + bRecord = sal_False; + + ScDocument* pUndoDoc = NULL; + if ( bRecord ) + { + pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab, bSize, bSize ); + pDoc->CopyToDocument( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab, + IDF_ATTRIB, sal_False, pUndoDoc ); + if (bSize) + { + pDoc->CopyToDocument( nStartCol,0,nStartTab, nEndCol,MAXROW,nEndTab, + IDF_NONE, sal_False, pUndoDoc ); + pDoc->CopyToDocument( 0,nStartRow,nStartTab, MAXCOL,nEndRow,nEndTab, + IDF_NONE, sal_False, pUndoDoc ); + } + pDoc->BeginDrawUndo(); + } + + GetFrameWin()->EnterWait(); + pDoc->AutoFormat( nStartCol, nStartRow, nEndCol, nEndRow, nFormatNo, rMark ); + GetFrameWin()->LeaveWait(); + + if (bSize) + { + SetMarkedWidthOrHeight( sal_True, SC_SIZE_VISOPT, STD_EXTRA_WIDTH, sal_False, sal_False ); + SetMarkedWidthOrHeight( sal_False, SC_SIZE_VISOPT, 0, sal_False, sal_False ); + pDocSh->PostPaint( 0,0,nStartTab, MAXCOL,MAXROW,nStartTab, + PAINT_GRID | PAINT_LEFT | PAINT_TOP ); + } + else + { + sal_Bool bAdj = AdjustBlockHeight( sal_False ); + if (bAdj) + pDocSh->PostPaint( 0,nStartRow,nStartTab, MAXCOL,MAXROW,nStartTab, + PAINT_GRID | PAINT_LEFT ); + else + pDocSh->PostPaint( nStartCol, nStartRow, nStartTab, + nEndCol, nEndRow, nEndTab, PAINT_GRID ); + } + + if ( bRecord ) // Draw-Undo erst jetzt verfuegbar + { + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoAutoFormat( pDocSh, + ScRange(nStartCol,nStartRow,nStartTab, nEndCol,nEndRow,nEndTab), + pUndoDoc, rMark, bSize, nFormatNo ) ); + } + + pDocSh->UpdateOle(GetViewData()); + pDocSh->SetDocumentModified(); + } + else + ErrorMessage(STR_NOMULTISELECT); + +#endif +} + + +//---------------------------------------------------------------------------- +// Suchen & Ersetzen + +void ScViewFunc::SearchAndReplace( const SvxSearchItem* pSearchItem, + sal_Bool bAddUndo, sal_Bool bIsApi ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + if (bAddUndo && !pDoc->IsUndoEnabled()) + bAddUndo = sal_False; + + SCCOL nCol = GetViewData()->GetCurX(); + SCROW nRow = GetViewData()->GetCurY(); + SCTAB nTab = GetViewData()->GetTabNo(); +// sal_Bool bAttrib = pSearchItem->GetPattern(); + sal_uInt16 nCommand = pSearchItem->GetCommand(); + sal_Bool bAllTables = pSearchItem->IsAllTables(); + sal_Bool* pOldSelectedTables = NULL; + sal_uInt16 nOldSelectedCount = 0; + SCTAB nOldTab = nTab; + SCTAB nLastTab = pDoc->GetTableCount() - 1; + SCTAB nStartTab, nEndTab; + if ( bAllTables ) + { + nStartTab = 0; + nEndTab = nLastTab; + pOldSelectedTables = new sal_Bool [ nEndTab + 1 ]; + for ( SCTAB j = 0; j <= nEndTab; j++ ) + { + pOldSelectedTables[j] = rMark.GetTableSelect( j ); + if ( pOldSelectedTables[j] ) + ++nOldSelectedCount; + } + } + else + { //! mindestens eine ist immer selektiert + nStartTab = nEndTab = rMark.GetFirstSelected(); + for ( SCTAB j = nStartTab + 1; j <= nLastTab; j++ ) + { + if ( rMark.GetTableSelect( j ) ) + nEndTab = j; + } + } + + if ( nCommand == SVX_SEARCHCMD_REPLACE + || nCommand == SVX_SEARCHCMD_REPLACE_ALL ) + { + for ( SCTAB j = nStartTab; j <= nEndTab; j++ ) + { + if ( (bAllTables || rMark.GetTableSelect( j )) && + pDoc->IsTabProtected( j ) ) + { + if ( pOldSelectedTables ) + delete [] pOldSelectedTables; + ErrorMessage(STR_PROTECTIONERR); + return; + } + } + } + + if ( nCommand == SVX_SEARCHCMD_FIND + || nCommand == SVX_SEARCHCMD_FIND_ALL) + bAddUndo = sal_False; + + //! bAttrib bei Undo beruecksichtigen !!! + + ScDocument* pUndoDoc = NULL; + ScMarkData* pUndoMark = NULL; + String aUndoStr; + if (bAddUndo) + { + pUndoMark = new ScMarkData( rMark ); // Markierung wird veraendert + if ( nCommand == SVX_SEARCHCMD_REPLACE_ALL ) + { + pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab ); + } + } + + if ( bAllTables ) + { //! alles selektieren, erst nachdem pUndoMark erzeugt wurde + for ( SCTAB j = nStartTab; j <= nEndTab; j++ ) + { + rMark.SelectTable( j, sal_True ); + } + } + + DoneBlockMode(sal_True); // Markierung nicht loeschen! + InitOwnBlockMode(); + + // wenn vom Anfang an gesucht wird, nicht nochmal fragen ob vom Anfang gesucht werden soll + sal_Bool bFirst = sal_True; + if ( nCol == 0 && nRow == 0 && nTab == nStartTab && !pSearchItem->GetBackward() ) + bFirst = sal_False; + + sal_Bool bFound = sal_False; + while (sal_True) + { + GetFrameWin()->EnterWait(); + if (pDoc->SearchAndReplace( *pSearchItem, nCol, nRow, nTab, rMark, aUndoStr, pUndoDoc ) ) + { + bFound = sal_True; + bFirst = sal_True; + if (bAddUndo) + { + GetViewData()->GetDocShell()->GetUndoManager()->AddUndoAction( + new ScUndoReplace( GetViewData()->GetDocShell(), *pUndoMark, + nCol, nRow, nTab, + aUndoStr, pUndoDoc, pSearchItem ) ); + pUndoDoc = NULL; + } + + break; // Abbruch while True + } + else if ( bFirst && (nCommand == SVX_SEARCHCMD_FIND || + nCommand == SVX_SEARCHCMD_REPLACE) ) + { + bFirst = sal_False; + sal_uInt16 nRetVal; + GetFrameWin()->LeaveWait(); + if ( bIsApi ) + nRetVal = RET_NO; + else + { + // Suchen-Dialog als Parent, wenn vorhanden + Window* pParent = GetParentOrChild(SID_SEARCH_DLG); + sal_uInt16 nStrId; + if ( pSearchItem->GetBackward() ) + { + if ( nStartTab == nEndTab ) + nStrId = STR_MSSG_SEARCHANDREPLACE_1; + else + nStrId = STR_MSSG_SEARCHANDREPLACE_4; + } + else + { + if ( nStartTab == nEndTab ) + nStrId = STR_MSSG_SEARCHANDREPLACE_2; + else + nStrId = STR_MSSG_SEARCHANDREPLACE_5; + } + MessBox aBox( pParent, WinBits(WB_YES_NO | WB_DEF_YES), + ScGlobal::GetRscString( STR_MSSG_SEARCHANDREPLACE_3 ), + ScGlobal::GetRscString( nStrId ) ); + nRetVal = aBox.Execute(); + } + + if ( nRetVal == RET_YES ) + { + ScDocument::GetSearchAndReplaceStart( *pSearchItem, nCol, nRow ); + if (pSearchItem->GetBackward()) + nTab = nEndTab; + else + nTab = nStartTab; + } + else + { + break; // Abbruch while True + } + } + else // nichts gefunden + { + if ( nCommand == SVX_SEARCHCMD_FIND_ALL || nCommand == SVX_SEARCHCMD_REPLACE_ALL ) + { + pDocSh->PostPaintGridAll(); // Markierung + } + + GetFrameWin()->LeaveWait(); + if (!bIsApi) + { + // Suchen-Dialog als Parent, wenn vorhanden + Window* pParent = GetParentOrChild(SID_SEARCH_DLG); + // "nichts gefunden" + InfoBox aBox( pParent, ScGlobal::GetRscString( STR_MSSG_SEARCHANDREPLACE_0 ) ); + aBox.Execute(); + } + + break; // Abbruch while True + } + } // of while sal_True + + if ( pOldSelectedTables ) + { // urspruenglich selektierte Tabellen wiederherstellen + for ( SCTAB j = nStartTab; j <= nEndTab; j++ ) + { + rMark.SelectTable( j, pOldSelectedTables[j] ); + } + if ( bFound ) + { // durch Fundstelle neu selektierte Tabelle bleibt + rMark.SelectTable( nTab, sal_True ); + // wenn vorher nur eine selektiert war, ist es ein Tausch + //! wenn nicht, ist jetzt evtl. eine mehr selektiert + if ( nOldSelectedCount == 1 && nTab != nOldTab ) + rMark.SelectTable( nOldTab, sal_False ); + } + delete [] pOldSelectedTables; + } + + MarkDataChanged(); + + if ( bFound ) + { + if ( nTab != GetViewData()->GetTabNo() ) + SetTabNo( nTab ); + + // wenn nichts markiert ist, DoneBlockMode, damit von hier aus + // direkt per Shift-Cursor markiert werden kann: + if (!rMark.IsMarked() && !rMark.IsMultiMarked()) + DoneBlockMode(sal_True); + + AlignToCursor( nCol, nRow, SC_FOLLOW_JUMP ); + SetCursor( nCol, nRow, sal_True ); + + if ( nCommand == SVX_SEARCHCMD_REPLACE + || nCommand == SVX_SEARCHCMD_REPLACE_ALL ) + { + if ( nCommand == SVX_SEARCHCMD_REPLACE ) + pDocSh->PostPaint( nCol,nRow,nTab, nCol,nRow,nTab, PAINT_GRID ); + else + pDocSh->PostPaintGridAll(); + pDocSh->SetDocumentModified(); + } + else if ( nCommand == SVX_SEARCHCMD_FIND_ALL ) + pDocSh->PostPaintGridAll(); // Markierung + GetFrameWin()->LeaveWait(); + } + + delete pUndoDoc; // loeschen wenn nicht benutzt + delete pUndoMark; // kann immer geloescht werden +} + + +//---------------------------------------------------------------------------- +// Zielwertsuche + +void ScViewFunc::Solve( const ScSolveParam& rParam ) +{ + ScDocument* pDoc = GetViewData()->GetDocument(); + + SCCOL nDestCol = rParam.aRefVariableCell.Col(); + SCROW nDestRow = rParam.aRefVariableCell.Row(); + SCTAB nDestTab = rParam.aRefVariableCell.Tab(); + + ScEditableTester aTester( pDoc, nDestTab, nDestCol,nDestRow, nDestCol,nDestRow ); + if (!aTester.IsEditable()) + { + ErrorMessage(aTester.GetMessageId()); + return; + } + + if ( pDoc ) + { + String aTargetValStr; + if ( rParam.pStrTargetVal != NULL ) + aTargetValStr = *(rParam.pStrTargetVal); + + String aMsgStr; + String aResStr; + double nSolveResult; + + GetFrameWin()->EnterWait(); + + sal_Bool bExact = + pDoc->Solver( + rParam.aRefFormulaCell.Col(), + rParam.aRefFormulaCell.Row(), + rParam.aRefFormulaCell.Tab(), + nDestCol, nDestRow, nDestTab, + aTargetValStr, + nSolveResult ); + + GetFrameWin()->LeaveWait(); + + SvNumberFormatter* pFormatter = pDoc->GetFormatTable(); + sal_uLong nFormat = 0; + const ScPatternAttr* pPattern = pDoc->GetPattern( nDestCol, nDestRow, nDestTab ); + if ( pPattern ) + nFormat = pPattern->GetNumberFormat( pFormatter ); + Color* p; + pFormatter->GetOutputString( nSolveResult, nFormat, aResStr, &p ); + + if ( bExact ) + { + aMsgStr = ScGlobal::GetRscString( STR_MSSG_SOLVE_0 ); + aMsgStr += ScGlobal::GetRscString( STR_MSSG_SOLVE_1 ); + aMsgStr += String( aResStr ); + aMsgStr += ScGlobal::GetRscString( STR_MSSG_SOLVE_2 ); + } + else + { + aMsgStr = ScGlobal::GetRscString( STR_MSSG_SOLVE_3 ); + aMsgStr += ScGlobal::GetRscString( STR_MSSG_SOLVE_4 ); + aMsgStr += ScGlobal::GetRscString( STR_MSSG_SOLVE_5 ); + aMsgStr += String( aResStr ); + aMsgStr += ScGlobal::GetRscString( STR_MSSG_SOLVE_6 ); + } + + MessBox aBox( GetViewData()->GetDialogParent(), + WinBits(WB_YES_NO | WB_DEF_NO), + ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_0 ), aMsgStr ); + sal_uInt16 nRetVal = aBox.Execute(); + + if ( RET_YES == nRetVal ) + EnterValue( nDestCol, nDestRow, nDestTab, nSolveResult ); + + GetViewData()->GetViewShell()->UpdateInputHandler( sal_True ); + } +} + + +//---------------------------------------------------------------------------- +// Mehrfachoperation + +void ScViewFunc::TabOp( const ScTabOpParam& rParam, sal_Bool bRecord ) +{ + ScRange aRange; + if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE) + { + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + pDocSh->GetDocFunc().TabOp( aRange, &rMark, rParam, bRecord, sal_False ); + } + else + ErrorMessage(STR_NOMULTISELECT); +} + + +//---------------------------------------------------------------------------- + +void ScViewFunc::MakeScenario( const String& rName, const String& rComment, + const Color& rColor, sal_uInt16 nFlags ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + SCTAB nTab = GetViewData()->GetTabNo(); + + SCTAB nNewTab = pDocSh->MakeScenario( nTab, rName, rComment, rColor, nFlags, rMark ); + if (nFlags & SC_SCENARIO_COPYALL) + SetTabNo( nNewTab, sal_True ); // SC_SCENARIO_COPYALL -> sichtbar + else + { + SfxBindings& rBindings = GetViewData()->GetBindings(); + rBindings.Invalidate( SID_STATUS_DOCPOS ); // Statusbar + rBindings.Invalidate( SID_TABLES_COUNT ); + rBindings.Invalidate( SID_SELECT_SCENARIO ); + rBindings.Invalidate( FID_TABLE_SHOW ); + } +} + + +//---------------------------------------------------------------------------- + +void ScViewFunc::ExtendScenario() +{ + ScEditableTester aTester( this ); + if (!aTester.IsEditable()) + { + ErrorMessage(aTester.GetMessageId()); + return; + } + + // Undo: Attribute anwenden + + ScDocument* pDoc = GetViewData()->GetDocument(); + ScPatternAttr aPattern( pDoc->GetPool() ); + aPattern.GetItemSet().Put( ScMergeFlagAttr( SC_MF_SCENARIO ) ); + aPattern.GetItemSet().Put( ScProtectionAttr( sal_True ) ); + ApplySelectionPattern(aPattern); +} + + +//---------------------------------------------------------------------------- + +void ScViewFunc::UseScenario( const String& rName ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + SCTAB nTab = GetViewData()->GetTabNo(); + + DoneBlockMode(); + InitOwnBlockMode(); + pDocSh->UseScenario( nTab, rName ); +} + + +//---------------------------------------------------------------------------- +// Tabelle einfuegen + +sal_Bool ScViewFunc::InsertTable( const String& rName, SCTAB nTab, sal_Bool bRecord ) +{ + // Reihenfolge Tabelle/Name ist bei DocFunc umgekehrt + sal_Bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc(). + InsertTable( nTab, rName, bRecord, sal_False ); + if (bSuccess) + SetTabNo( nTab, sal_True ); + + return bSuccess; +} + +//---------------------------------------------------------------------------- +// Tabellen einfuegen + +sal_Bool ScViewFunc::InsertTables(SvStrings *pNames, SCTAB nTab, + SCTAB nCount, sal_Bool bRecord ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + if (bRecord && !pDoc->IsUndoEnabled()) + bRecord = sal_False; + + SvStrings *pNameList= NULL; + + WaitObject aWait( GetFrameWin() ); + + if (bRecord) + { + pNameList= new SvStrings; + pDoc->BeginDrawUndo(); // InsertTab erzeugt ein SdrUndoNewPage + } + + sal_Bool bFlag=sal_False; + + String aValTabName; + String *pStr; + + for(SCTAB i=0;i<nCount;i++) + { + if(pNames!=NULL) + { + pStr=pNames->GetObject(static_cast<sal_uInt16>(i)); + } + else + { + aValTabName.Erase(); + pDoc->CreateValidTabName( aValTabName); + pStr=&aValTabName; + } + + if(pDoc->InsertTab( nTab+i,*pStr)) + { + bFlag=sal_True; + pDocSh->Broadcast( ScTablesHint( SC_TAB_INSERTED, nTab+i ) ); + } + else + { + break; + } + + if(pNameList!=NULL) + pNameList->Insert(new String(*pStr),pNameList->Count()); + + } + + if (bFlag) + { + if (bRecord) + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoInsertTables( pDocSh, nTab, sal_False, pNameList)); + + // Views updaten: + + SetTabNo( nTab, sal_True ); + pDocSh->PostPaintExtras(); + pDocSh->SetDocumentModified(); + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); + return sal_True; + } + else + { + return sal_False; + } +} + + +//---------------------------------------------------------------------------- + +sal_Bool ScViewFunc::AppendTable( const String& rName, sal_Bool bRecord ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + if (bRecord && !pDoc->IsUndoEnabled()) + bRecord = sal_False; + + WaitObject aWait( GetFrameWin() ); + + if (bRecord) + pDoc->BeginDrawUndo(); // InsertTab erzeugt ein SdrUndoNewPage + + if (pDoc->InsertTab( SC_TAB_APPEND, rName )) + { + SCTAB nTab = pDoc->GetTableCount()-1; + if (bRecord) + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoInsertTab( pDocSh, nTab, sal_True, rName)); + GetViewData()->InsertTab( nTab ); + SetTabNo( nTab, sal_True ); + pDocSh->PostPaintExtras(); + pDocSh->SetDocumentModified(); + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); + return sal_True; + } + else + { + return sal_False; + } +} + + +//---------------------------------------------------------------------------- + +sal_Bool ScViewFunc::DeleteTable( SCTAB nTab, sal_Bool bRecord ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + + sal_Bool bSuccess = pDocSh->GetDocFunc().DeleteTable( nTab, bRecord, sal_False ); + if (bSuccess) + { + SCTAB nNewTab = nTab; + if ( nNewTab >= pDoc->GetTableCount() ) + --nNewTab; + SetTabNo( nNewTab, sal_True ); + } + return bSuccess; +} + +sal_Bool ScViewFunc::DeleteTables(const SvShorts &TheTabs, sal_Bool bRecord ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + sal_Bool bVbaEnabled = pDoc ? pDoc->IsInVBAMode() : sal_False; + SCTAB nNewTab = TheTabs.front(); + WaitObject aWait( GetFrameWin() ); + if (bRecord && !pDoc->IsUndoEnabled()) + bRecord = sal_False; + + while ( nNewTab > 0 && !pDoc->IsVisible( nNewTab ) ) + --nNewTab; + + sal_Bool bWasLinked = sal_False; + ScDocument* pUndoDoc = NULL; + ScRefUndoData* pUndoData = NULL; + if (bRecord) + { + pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); +// pUndoDoc->InitDrawLayer( pDocSh ); + SCTAB nCount = pDoc->GetTableCount(); + +// pUndoDoc->InitUndo( pDoc, 0, nCount-1 ); // incl. Ref. + + String aOldName; + for (size_t i = 0; i < TheTabs.size(); i++) + { + SCTAB nTab = TheTabs[i]; + if (i==0) + pUndoDoc->InitUndo( pDoc, nTab,nTab, sal_True,sal_True ); // incl. Spalten/Zeilenflags + else + pUndoDoc->AddUndoTab( nTab,nTab, sal_True,sal_True ); // incl. Spalten/Zeilenflags + + pDoc->CopyToDocument(0,0,nTab, MAXCOL,MAXROW,nTab, IDF_ALL,sal_False, pUndoDoc ); + pDoc->GetName( nTab, aOldName ); + pUndoDoc->RenameTab( nTab, aOldName, sal_False ); + if (pDoc->IsLinked(nTab)) + { + bWasLinked = sal_True; + pUndoDoc->SetLink( nTab, pDoc->GetLinkMode(nTab), pDoc->GetLinkDoc(nTab), + pDoc->GetLinkFlt(nTab), pDoc->GetLinkOpt(nTab), + pDoc->GetLinkTab(nTab), + pDoc->GetLinkRefreshDelay(nTab) ); + } + if ( pDoc->IsScenario(nTab) ) + { + pUndoDoc->SetScenario( nTab, sal_True ); + String aComment; + Color aColor; + sal_uInt16 nScenFlags; + pDoc->GetScenarioData( nTab, aComment, aColor, nScenFlags ); + pUndoDoc->SetScenarioData( nTab, aComment, aColor, nScenFlags ); + sal_Bool bActive = pDoc->IsActiveScenario( nTab ); + pUndoDoc->SetActiveScenario( nTab, bActive ); + } + pUndoDoc->SetVisible( nTab, pDoc->IsVisible( nTab ) ); + pUndoDoc->SetTabBgColor( nTab, pDoc->GetTabBgColor(nTab) ); + pUndoDoc->SetSheetEvents( nTab, pDoc->GetSheetEvents( nTab ) ); + + if ( pDoc->IsTabProtected( nTab ) ) + pUndoDoc->SetTabProtection(nTab, pDoc->GetTabProtection(nTab)); + + // Drawing-Layer muss sein Undo selbst in der Hand behalten !!! + // pUndoDoc->TransferDrawPage(pDoc, nTab,nTab); + } + + pUndoDoc->AddUndoTab( 0, nCount-1 ); // alle Tabs fuer Referenzen + + pDoc->BeginDrawUndo(); // DeleteTab erzeugt ein SdrUndoDelPage + + pUndoData = new ScRefUndoData( pDoc ); + } + + sal_Bool bDelDone = sal_False; + + for (size_t i = TheTabs.size(); i > 0; i--) + { + String sCodeName; + sal_Bool bHasCodeName = pDoc->GetCodeName( TheTabs[i-1], sCodeName ); + if (pDoc->DeleteTab( TheTabs[i-1], pUndoDoc )) + { + bDelDone = sal_True; + if( bVbaEnabled ) + { + if( bHasCodeName ) + { + VBA_DeleteModule( *pDocSh, sCodeName ); + } + } + pDocSh->Broadcast( ScTablesHint( SC_TAB_DELETED, TheTabs[i-1] ) ); + } + } + if (bRecord) + { + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoDeleteTab( GetViewData()->GetDocShell(), TheTabs, + pUndoDoc, pUndoData )); + } + + + if (bDelDone) + { + if ( nNewTab >= pDoc->GetTableCount() ) + nNewTab = pDoc->GetTableCount() - 1; + + SetTabNo( nNewTab, sal_True ); + + if (bWasLinked) + { + pDocSh->UpdateLinks(); // Link-Manager updaten + GetViewData()->GetBindings().Invalidate(SID_LINKS); + } + + pDocSh->PostPaintExtras(); + pDocSh->SetDocumentModified(); + + SfxApplication* pSfxApp = SFX_APP(); // Navigator + pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); + pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) ); + pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); + } + else + { + delete pUndoDoc; + delete pUndoData; + } + return bDelDone; +} + + +//---------------------------------------------------------------------------- + +sal_Bool ScViewFunc::RenameTable( const String& rName, SCTAB nTab ) +{ + // Reihenfolge Tabelle/Name ist bei DocFunc umgekehrt + sal_Bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc(). + RenameTable( nTab, rName, sal_True, sal_False ); + if (bSuccess) + { + // Der Tabellenname koennte in einer Formel vorkommen... + GetViewData()->GetViewShell()->UpdateInputHandler(); + } + return bSuccess; +} + + +//---------------------------------------------------------------------------- + +bool ScViewFunc::SetTabBgColor( const Color& rColor, SCTAB nTab ) +{ + bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc().SetTabBgColor( nTab, rColor, sal_True, sal_False ); + if (bSuccess) + { + GetViewData()->GetViewShell()->UpdateInputHandler(); + } + return bSuccess; +} + +bool ScViewFunc::SetTabBgColor( ScUndoTabColorInfo::List& rUndoSetTabBgColorInfoList ) +{ + bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc().SetTabBgColor( rUndoSetTabBgColorInfoList, sal_True, sal_False ); + if (bSuccess) + { + GetViewData()->GetViewShell()->UpdateInputHandler(); + } + return bSuccess; +} + +//---------------------------------------------------------------------------- + +void ScViewFunc::InsertAreaLink( const String& rFile, + const String& rFilter, const String& rOptions, + const String& rSource, sal_uLong nRefresh ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + SCCOL nPosX = GetViewData()->GetCurX(); + SCROW nPosY = GetViewData()->GetCurY(); + SCTAB nTab = GetViewData()->GetTabNo(); + ScAddress aPos( nPosX, nPosY, nTab ); + + pDocSh->GetDocFunc().InsertAreaLink( rFile, rFilter, rOptions, rSource, aPos, nRefresh, sal_False, sal_False ); +} + + +//---------------------------------------------------------------------------- + +void ScViewFunc::InsertTableLink( const String& rFile, + const String& rFilter, const String& rOptions, + const String& rTabName ) +{ + String aFilterName = rFilter; + String aOpt = rOptions; + ScDocumentLoader aLoader( rFile, aFilterName, aOpt ); + if (!aLoader.IsError()) + { + ScDocShell* pSrcSh = aLoader.GetDocShell(); + ScDocument* pSrcDoc = pSrcSh->GetDocument(); + SCTAB nTab = MAXTAB+1; + if (!rTabName.Len()) // kein Name angegeben -> erste Tabelle + nTab = 0; + else + { + String aTemp; + SCTAB nCount = pSrcDoc->GetTableCount(); + for (SCTAB i=0; i<nCount; i++) + { + pSrcDoc->GetName( i, aTemp ); + if ( aTemp == rTabName ) + nTab = i; + } + } + + if ( nTab <= MAXTAB ) + ImportTables( pSrcSh, 1, &nTab, sal_True, + GetViewData()->GetTabNo() ); + } +} + + +//---------------------------------------------------------------------------- +// Tabellen aus anderem Dokument kopieren / linken + +void ScViewFunc::ImportTables( ScDocShell* pSrcShell, + SCTAB nCount, const SCTAB* pSrcTabs, sal_Bool bLink,SCTAB nTab ) +{ + ScDocument* pSrcDoc = pSrcShell->GetDocument(); + + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + sal_Bool bUndo(pDoc->IsUndoEnabled()); + //SCTAB nTab = GetViewData()->GetTabNo(); + + sal_Bool bError = sal_False; + sal_Bool bRefs = sal_False; + sal_Bool bName = sal_False; + + if (pSrcDoc->GetDrawLayer()) + pDocSh->MakeDrawLayer(); + + if (bUndo) + pDoc->BeginDrawUndo(); // drawing layer must do its own undo actions + + SCTAB nInsCount = 0; + SCTAB i; + for( i=0; i<nCount; i++ ) + { // #63304# insert sheets first and update all references + String aName; + pSrcDoc->GetName( pSrcTabs[i], aName ); + pDoc->CreateValidTabName( aName ); + if ( !pDoc->InsertTab( nTab+i, aName ) ) + { + bError = sal_True; // total error + break; // for + } + ++nInsCount; + } + for (i=0; i<nCount && !bError; i++) + { + SCTAB nSrcTab = pSrcTabs[i]; + SCTAB nDestTab1=nTab+i; + sal_uLong nErrVal = pDoc->TransferTab( pSrcDoc, nSrcTab, nDestTab1, + sal_False ); // no insert + + switch (nErrVal) + { + case 0: // interner Fehler oder voll Fehler + bError = sal_True; + break; + case 2: + bRefs = sal_True; + break; + case 3: + bName = sal_True; + break; + case 4: + bRefs = bName = sal_True; + break; + } + + // TransferTab doesn't copy drawing objects with bInsertNew=FALSE + if ( !bError ) + pDoc->TransferDrawPage( pSrcDoc, nSrcTab, nDestTab1 ); + + if(!bError &&pSrcDoc->IsScenario(nSrcTab)) + { + String aComment; + Color aColor; + sal_uInt16 nFlags; + + pSrcDoc->GetScenarioData(nSrcTab, aComment,aColor, nFlags); + pDoc->SetScenario( nDestTab1,sal_True); + pDoc->SetScenarioData( nTab+i,aComment,aColor,nFlags); + sal_Bool bActive = pSrcDoc->IsActiveScenario(nSrcTab ); + pDoc->SetActiveScenario( nDestTab1, bActive ); + sal_Bool bVisible=pSrcDoc->IsVisible(nSrcTab); + pDoc->SetVisible(nDestTab1,bVisible ); + + } + } + + if (bLink) + { + sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager(); + + SfxMedium* pMed = pSrcShell->GetMedium(); + String aFileName = pMed->GetName(); + String aFilterName; + if (pMed->GetFilter()) + aFilterName = pMed->GetFilter()->GetFilterName(); + String aOptions = ScDocumentLoader::GetOptions(*pMed); + + sal_Bool bWasThere = pDoc->HasLink( aFileName, aFilterName, aOptions ); + + sal_uLong nRefresh = 0; + String aTabStr; + for (i=0; i<nInsCount; i++) + { + pSrcDoc->GetName( pSrcTabs[i], aTabStr ); + pDoc->SetLink( nTab+i, SC_LINK_NORMAL, + aFileName, aFilterName, aOptions, aTabStr, nRefresh ); + } + + if (!bWasThere) // Link pro Quelldokument nur einmal eintragen + { + ScTableLink* pLink = new ScTableLink( pDocSh, aFileName, aFilterName, aOptions, nRefresh ); + pLink->SetInCreate( sal_True ); + pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, aFileName, &aFilterName ); + pLink->Update(); + pLink->SetInCreate( sal_False ); + + SfxBindings& rBindings = GetViewData()->GetBindings(); + rBindings.Invalidate( SID_LINKS ); + } + } + + + if (bUndo) + { + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoImportTab( pDocSh, nTab, nCount, bLink ) ); + } + + for (i=0; i<nInsCount; i++) + GetViewData()->InsertTab(nTab); + SetTabNo(nTab,sal_True); + pDocSh->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, + PAINT_GRID | PAINT_TOP | PAINT_LEFT | PAINT_EXTRAS ); + + SfxApplication* pSfxApp = SFX_APP(); + pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); + pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) ); + + pDocSh->PostPaintExtras(); + pDocSh->PostPaintGridAll(); + pDocSh->SetDocumentModified(); + + if (bRefs) + ErrorMessage(STR_ABSREFLOST); + if (bName) + ErrorMessage(STR_NAMECONFLICT); +} + + +//---------------------------------------------------------------------------- +// Tabelle in anderes Dokument verschieben / kopieren + +void ScViewFunc::MoveTable( sal_uInt16 nDestDocNo, SCTAB nDestTab, sal_Bool bCopy ) +{ + ScDocument* pDoc = GetViewData()->GetDocument(); + ScDocShell* pDocShell = GetViewData()->GetDocShell(); + ScDocument* pDestDoc = NULL; + ScDocShell* pDestShell = NULL; + ScTabViewShell* pDestViewSh = NULL; + sal_Bool bUndo (pDoc->IsUndoEnabled()); + + sal_Bool bNewDoc = ( nDestDocNo == SC_DOC_NEW ); + if ( bNewDoc ) + { + nDestTab = 0; // als erstes einfuegen + + // ohne SFX_CALLMODE_RECORD ausfuehren, weil schon im Move-Befehl enthalten: + + String aUrl = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("private:factory/")); + aUrl.AppendAscii(RTL_CONSTASCII_STRINGPARAM( STRING_SCAPP )); // "scalc" + SfxStringItem aItem( SID_FILE_NAME, aUrl ); + SfxStringItem aTarget( SID_TARGETNAME, String::CreateFromAscii("_blank") ); + + const SfxPoolItem* pRetItem = GetViewData()->GetDispatcher().Execute( + SID_OPENDOC, SFX_CALLMODE_API|SFX_CALLMODE_SYNCHRON, &aItem, &aTarget, 0L ); + if ( pRetItem ) + { + if ( pRetItem->ISA( SfxObjectItem ) ) + pDestShell = PTR_CAST( ScDocShell, ((const SfxObjectItem*)pRetItem)->GetShell() ); + else if ( pRetItem->ISA( SfxViewFrameItem ) ) + { + SfxViewFrame* pFrm = ((const SfxViewFrameItem*)pRetItem)->GetFrame(); + if (pFrm) + pDestShell = PTR_CAST( ScDocShell, pFrm->GetObjectShell() ); + } + if (pDestShell) + pDestViewSh = pDestShell->GetBestViewShell(); + } + } + else + pDestShell = ScDocShell::GetShellByNum( nDestDocNo ); + + if (!pDestShell) + { + DBG_ERROR("Dest-Doc nicht gefunden !!!"); + return; + } + + pDestDoc = pDestShell->GetDocument(); + + SCTAB nTab = GetViewData()->GetTabNo(); + + if (pDestDoc != pDoc) + { + if (bNewDoc) + { + while (pDestDoc->GetTableCount() > 1) + pDestDoc->DeleteTab(0); + pDestDoc->RenameTab( 0, + String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("______42_____")), + sal_False ); + } + + ScMarkData& rMark = GetViewData()->GetMarkData(); + SCTAB nTabCount = pDoc->GetTableCount(); + SCTAB nTabSelCount = rMark.GetSelectCount(); + + SvShorts TheTabs; + + for(SCTAB i=0;i<nTabCount;i++) + { + if(rMark.GetTableSelect(i)) + { + String aTabName; + pDoc->GetName( i, aTabName); + TheTabs.push_back(i); + for(SCTAB j=i+1;j<nTabCount;j++) + { + if((!pDoc->IsVisible(j))&&(pDoc->IsScenario(j))) + { + pDoc->GetName( j, aTabName); + TheTabs.push_back(j); + i=j; + } + else break; + } + } + } + + GetFrameWin()->EnterWait(); + + if (pDoc->GetDrawLayer()) + pDestShell->MakeDrawLayer(); + + if (!bNewDoc && bUndo) + pDestDoc->BeginDrawUndo(); // drawing layer must do its own undo actions + + sal_uLong nErrVal =1; + if(nDestTab==SC_TAB_APPEND) + nDestTab=pDestDoc->GetTableCount(); + SCTAB nDestTab1=nDestTab; + for( size_t j=0; j<TheTabs.size(); j++, nDestTab1++ ) + { // #63304# insert sheets first and update all references + String aName; + pDoc->GetName( TheTabs[j], aName ); + pDestDoc->CreateValidTabName( aName ); + if ( !pDestDoc->InsertTab( nDestTab1, aName ) ) + { + nErrVal = 0; // total error + break; // for + } + } + if ( nErrVal > 0 ) + { + nDestTab1 = nDestTab; + for(size_t i=0;i<TheTabs.size();i++) + { + nErrVal = pDestDoc->TransferTab( pDoc, TheTabs[i], nDestTab1, + sal_False ); // no insert + + // TransferTab doesn't copy drawing objects with bInsertNew=FALSE + if ( nErrVal > 0 ) + pDestDoc->TransferDrawPage( pDoc, TheTabs[i], nDestTab1 ); + + if(nErrVal>0 && pDoc->IsScenario(TheTabs[i])) + { + String aComment; + Color aColor; + sal_uInt16 nFlags; + + pDoc->GetScenarioData(TheTabs[i], aComment,aColor, nFlags); + pDestDoc->SetScenario(nDestTab1,sal_True); + pDestDoc->SetScenarioData(nDestTab1,aComment,aColor,nFlags); + sal_Bool bActive = pDoc->IsActiveScenario(TheTabs[i]); + pDestDoc->SetActiveScenario(nDestTab1, bActive ); + + sal_Bool bVisible=pDoc->IsVisible(TheTabs[i]); + pDestDoc->SetVisible(nDestTab1,bVisible ); + + } + + if ( nErrVal > 0 && pDoc->IsTabProtected( TheTabs[i] ) ) + pDestDoc->SetTabProtection(nDestTab1, pDoc->GetTabProtection(TheTabs[i])); + + nDestTab1++; + } + } + String sName; + if (!bNewDoc && bUndo) + { + pDestDoc->GetName(nDestTab, sName); + pDestShell->GetUndoManager()->AddUndoAction( + new ScUndoImportTab( pDestShell, nDestTab, + static_cast<SCTAB>(TheTabs.size()), sal_False)); + + } + else + { + pDestShell->GetUndoManager()->Clear(); + } + + GetFrameWin()->LeaveWait(); + switch (nErrVal) + { + case 0: // interner Fehler oder voll Fehler + { + ErrorMessage(STR_TABINSERT_ERROR); + return; + } + //break; + case 2: + ErrorMessage(STR_ABSREFLOST); + break; + case 3: + ErrorMessage(STR_NAMECONFLICT); + break; + case 4: + { + ErrorMessage(STR_ABSREFLOST); + ErrorMessage(STR_NAMECONFLICT); + } + break; + default: + break; + } + //pDestShell->GetUndoManager()->Clear(); //! Undo implementieren !!! +/* + String sName; + pDestDoc->GetName(nDestTab, sName); + pDestShell->GetUndoManager()->AddUndoAction( + new ScUndoInsertTab( pDestShell, nDestTab, sal_True, sName ) ); +*/ + if (!bCopy) + { + if(nTabCount!=nTabSelCount) + DeleteTables(TheTabs);// incl. Paint & Undo + else + ErrorMessage(STR_TABREMOVE_ERROR); + } + + if (bNewDoc) + { + // ChartListenerCollection must be updated before DeleteTab + if ( pDestDoc->IsChartListenerCollectionNeedsUpdate() ) + pDestDoc->UpdateChartListenerCollection(); + + pDestDoc->DeleteTab(static_cast<SCTAB>(TheTabs.size())); // first old table +//? pDestDoc->SelectTable(0, sal_True); // neue erste Tabelle selektieren + if (pDestViewSh) + pDestViewSh->TabChanged(); // Pages auf dem Drawing-Layer + pDestShell->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, + PAINT_GRID | PAINT_TOP | PAINT_LEFT | + PAINT_EXTRAS | PAINT_SIZE ); + // PAINT_SIZE fuer Gliederung + } + else + { + pDestShell->Broadcast( ScTablesHint( SC_TAB_INSERTED, nDestTab ) ); + pDestShell->PostPaintExtras(); + pDestShell->PostPaintGridAll(); + } + + TheTabs.clear(); + + pDestShell->SetDocumentModified(); + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); + } + else // within the documents + { + + ScMarkData& rMark = GetViewData()->GetMarkData(); + SCTAB nTabCount = pDoc->GetTableCount(); + + SvShorts TheTabs; + SvShorts TheDestTabs; + SvStrings TheTabNames; + String aDestName; + String *pString; + + for(SCTAB i=0;i<nTabCount;i++) + { + if(rMark.GetTableSelect(i)) + { + String aTabName; + pDoc->GetName( i, aTabName); + TheTabNames.Insert(new String(aTabName),TheTabNames.Count()); + + for(SCTAB j=i+1;j<nTabCount;j++) + { + if((!pDoc->IsVisible(j))&&(pDoc->IsScenario(j))) + { + pDoc->GetName( j, aTabName); + TheTabNames.Insert(new String(aTabName),TheTabNames.Count()); + i=j; + } + else break; + } + + } + } + + if (bCopy && bUndo) + pDoc->BeginDrawUndo(); // drawing layer must do its own undo actions + + pDoc->GetName( nDestTab, aDestName); + SCTAB nDestTab1=nDestTab; + SCTAB nMovTab=0; + for(int j=0;j<TheTabNames.Count();j++) + { + nTabCount = pDoc->GetTableCount(); + pString=TheTabNames[sal::static_int_cast<sal_uInt16>(j)]; + if(!pDoc->GetTable(*pString,nMovTab)) + { + nMovTab=nTabCount; + } + if(!pDoc->GetTable(aDestName,nDestTab1)) + { + nDestTab1=nTabCount; + } + pDocShell->MoveTable( nMovTab, nDestTab1, bCopy, sal_False ); // Undo ist hier + + if(bCopy && pDoc->IsScenario(nMovTab)) + { + String aComment; + Color aColor; + sal_uInt16 nFlags; + + pDoc->GetScenarioData(nMovTab, aComment,aColor, nFlags); + pDoc->SetScenario(nDestTab1,sal_True); + pDoc->SetScenarioData(nDestTab1,aComment,aColor,nFlags); + sal_Bool bActive = pDoc->IsActiveScenario(nMovTab ); + pDoc->SetActiveScenario( nDestTab1, bActive ); + sal_Bool bVisible=pDoc->IsVisible(nMovTab); + pDoc->SetVisible(nDestTab1,bVisible ); + } + + TheTabs.push_back(nMovTab); + + if(!bCopy) + { + if(!pDoc->GetTable(*pString,nDestTab1)) + { + nDestTab1=nTabCount; + } + } + + TheDestTabs.push_back(nDestTab1); + delete pString; + } + + nTab = GetViewData()->GetTabNo(); + + if (bUndo) + { + if (bCopy) + { + pDocShell->GetUndoManager()->AddUndoAction( + new ScUndoCopyTab( pDocShell, TheTabs, TheDestTabs)); + } + else + { + pDocShell->GetUndoManager()->AddUndoAction( + new ScUndoMoveTab( pDocShell, TheTabs, TheDestTabs)); + } + } + + SCTAB nNewTab = nDestTab; + if (nNewTab == SC_TAB_APPEND) + nNewTab = pDoc->GetTableCount()-1; + else if (!bCopy && nTab<nDestTab) + nNewTab--; + + SetTabNo( nNewTab, sal_True ); + + //#i29848# adjust references to data on the copied sheet + if( bCopy ) + ScChartHelper::AdjustRangesOfChartsOnDestinationPage( pDoc, pDestDoc, nTab, nNewTab ); + } +} + + +//---------------------------------------------------------------------------- + +void ScViewFunc::ShowTable( const String& rName ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + sal_Bool bUndo(pDoc->IsUndoEnabled()); + sal_Bool bFound = sal_False; + SCTAB nPos = 0; + String aTabName; + SCTAB nCount = pDoc->GetTableCount(); + for (SCTAB i=0; i<nCount; i++) + { + pDoc->GetName( i, aTabName ); + if ( aTabName == rName ) + { + nPos = i; + bFound = sal_True; + } + } + + if (bFound) + { + pDoc->SetVisible( nPos, sal_True ); + if (bUndo) + { + pDocSh->GetUndoManager()->AddUndoAction( new ScUndoShowHideTab( pDocSh, nPos, sal_True ) ); + } + SetTabNo( nPos, sal_True ); + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); + pDocSh->PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_EXTRAS); + pDocSh->SetDocumentModified(); + } + else + Sound::Beep(); +} + + +//---------------------------------------------------------------------------- + +void ScViewFunc::HideTable( SCTAB nTab ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + sal_Bool bUndo(pDoc->IsUndoEnabled()); + SCTAB nVisible = 0; + SCTAB nCount = pDoc->GetTableCount(); + for (SCTAB i=0; i<nCount; i++) + { + if (pDoc->IsVisible(i)) + ++nVisible; + } + + if (nVisible > 1) + { + pDoc->SetVisible( nTab, sal_False ); + if (bUndo) + { + pDocSh->GetUndoManager()->AddUndoAction( new ScUndoShowHideTab( pDocSh, nTab, sal_False ) ); + } + + // Views updaten: + pDocSh->Broadcast( ScTablesHint( SC_TAB_HIDDEN, nTab ) ); + + SetTabNo( nTab, sal_True ); + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); + pDocSh->PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_EXTRAS); + pDocSh->SetDocumentModified(); + } + else + Sound::Beep(); +} + + +//---------------------------------------------------------------------------- + +void ScViewFunc::InsertSpecialChar( const String& rStr, const Font& rFont ) +{ + ScEditableTester aTester( this ); + if (!aTester.IsEditable()) + { + ErrorMessage(aTester.GetMessageId()); + return; + } + + const sal_Unicode* pChar = rStr.GetBuffer(); + ScTabViewShell* pViewShell = GetViewData()->GetViewShell(); + SvxFontItem aFontItem( rFont.GetFamily(), + rFont.GetName(), + rFont.GetStyleName(), + rFont.GetPitch(), + rFont.GetCharSet(), + ATTR_FONT ); + + // if string contains WEAK characters, set all fonts + sal_uInt8 nScript; + ScDocument* pDoc = GetViewData()->GetDocument(); + if ( pDoc->HasStringWeakCharacters( rStr ) ) + nScript = SCRIPTTYPE_LATIN | SCRIPTTYPE_ASIAN | SCRIPTTYPE_COMPLEX; + else + nScript = pDoc->GetStringScriptType( rStr ); + + SvxScriptSetItem aSetItem( SID_ATTR_CHAR_FONT, pViewShell->GetPool() ); + aSetItem.PutItemForScriptType( nScript, aFontItem ); + ApplyUserItemSet( aSetItem.GetItemSet() ); + + while ( *pChar ) + pViewShell->TabKeyInput( KeyEvent( *(pChar++), KeyCode() ) ); +} + + +//---------------------------------------------------------------------------- + +void ScViewFunc::UpdateLineAttrs( SvxBorderLine& rLine, + const SvxBorderLine* pDestLine, + const SvxBorderLine* pSrcLine, + sal_Bool bColor ) +{ + if ( pSrcLine && pDestLine ) + { + if ( bColor ) + { + rLine.SetColor ( pSrcLine->GetColor() ); + rLine.SetOutWidth ( pDestLine->GetOutWidth() ); + rLine.SetInWidth ( pDestLine->GetInWidth() ); + rLine.SetDistance ( pDestLine->GetDistance() ); + } + else + { + rLine.SetColor ( pDestLine->GetColor() ); + rLine.SetOutWidth ( pSrcLine->GetOutWidth() ); + rLine.SetInWidth ( pSrcLine->GetInWidth() ); + rLine.SetDistance ( pSrcLine->GetDistance() ); + } + } +} + + +#define SET_LINE_ATTRIBUTES(LINE,BOXLINE) \ + pBoxLine = aBoxItem.Get##LINE(); \ + if ( pBoxLine ) \ + { \ + if ( pLine ) \ + { \ + UpdateLineAttrs( aLine, pBoxLine, pLine, bColorOnly ); \ + aBoxItem.SetLine( &aLine, BOXLINE ); \ + } \ + else \ + aBoxItem.SetLine( NULL, BOXLINE ); \ + } + + +//---------------------------------------------------------------------------- + +void ScViewFunc::SetSelectionFrameLines( const SvxBorderLine* pLine, + sal_Bool bColorOnly ) +{ + // nur wegen Matrix nicht editierbar? Attribute trotzdem ok + sal_Bool bOnlyNotBecauseOfMatrix; + if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix ) + { + ErrorMessage(STR_PROTECTIONERR); + return; + } + + ScDocument* pDoc = GetViewData()->GetDocument(); + ScMarkData aFuncMark( GetViewData()->GetMarkData() ); // local copy for UnmarkFiltered + ScViewUtil::UnmarkFiltered( aFuncMark, pDoc ); + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + const ScPatternAttr* pSelAttrs = GetSelectionPattern(); + const SfxItemSet& rSelItemSet = pSelAttrs->GetItemSet(); + + const SfxPoolItem* pBorderAttr = NULL; + SfxItemState eItemState = rSelItemSet.GetItemState( ATTR_BORDER, sal_True, &pBorderAttr ); + + const SfxPoolItem* pTLBRItem = 0; + SfxItemState eTLBRState = rSelItemSet.GetItemState( ATTR_BORDER_TLBR, sal_True, &pTLBRItem ); + + const SfxPoolItem* pBLTRItem = 0; + SfxItemState eBLTRState = rSelItemSet.GetItemState( ATTR_BORDER_BLTR, sal_True, &pBLTRItem ); + + // any of the lines visible? + if( (eItemState != SFX_ITEM_DEFAULT) || (eTLBRState != SFX_ITEM_DEFAULT) || (eBLTRState != SFX_ITEM_DEFAULT) ) + { + // none of the lines don't care? + if( (eItemState != SFX_ITEM_DONTCARE) && (eTLBRState != SFX_ITEM_DONTCARE) && (eBLTRState != SFX_ITEM_DONTCARE) ) + { + SfxItemSet* pOldSet = new SfxItemSet( + *(pDoc->GetPool()), + ATTR_PATTERN_START, + ATTR_PATTERN_END ); + SfxItemSet* pNewSet = new SfxItemSet( + *(pDoc->GetPool()), + ATTR_PATTERN_START, + ATTR_PATTERN_END ); + + //------------------------------------------------------------ + const SvxBorderLine* pBoxLine = NULL; + SvxBorderLine aLine; + + // hier wird die pBoxLine benutzt: + + if( pBorderAttr ) + { + SvxBoxItem aBoxItem( *(const SvxBoxItem*)pBorderAttr ); + SvxBoxInfoItem aBoxInfoItem( ATTR_BORDER_INNER ); + + SET_LINE_ATTRIBUTES(Top,BOX_LINE_TOP) + SET_LINE_ATTRIBUTES(Bottom,BOX_LINE_BOTTOM) + SET_LINE_ATTRIBUTES(Left,BOX_LINE_LEFT) + SET_LINE_ATTRIBUTES(Right,BOX_LINE_RIGHT) + + aBoxInfoItem.SetLine( aBoxItem.GetTop(), BOXINFO_LINE_HORI ); + aBoxInfoItem.SetLine( aBoxItem.GetLeft(), BOXINFO_LINE_VERT ); + aBoxInfoItem.ResetFlags(); // Lines auf Valid setzen + + pOldSet->Put( *pBorderAttr ); + pNewSet->Put( aBoxItem ); + pNewSet->Put( aBoxInfoItem ); + } + + if( pTLBRItem && ((const SvxLineItem*)pTLBRItem)->GetLine() ) + { + SvxLineItem aTLBRItem( *(const SvxLineItem*)pTLBRItem ); + UpdateLineAttrs( aLine, aTLBRItem.GetLine(), pLine, bColorOnly ); + aTLBRItem.SetLine( &aLine ); + pOldSet->Put( *pTLBRItem ); + pNewSet->Put( aTLBRItem ); + } + + if( pBLTRItem && ((const SvxLineItem*)pBLTRItem)->GetLine() ) + { + SvxLineItem aBLTRItem( *(const SvxLineItem*)pBLTRItem ); + UpdateLineAttrs( aLine, aBLTRItem.GetLine(), pLine, bColorOnly ); + aBLTRItem.SetLine( &aLine ); + pOldSet->Put( *pBLTRItem ); + pNewSet->Put( aBLTRItem ); + } + + ApplyAttributes( pNewSet, pOldSet ); + + delete pOldSet; + delete pNewSet; + } + else // if ( eItemState == SFX_ITEM_DONTCARE ) + { + aFuncMark.MarkToMulti(); + pDoc->ApplySelectionLineStyle( aFuncMark, pLine, bColorOnly ); + } + + ScRange aMarkRange; + aFuncMark.GetMultiMarkArea( aMarkRange ); + SCCOL nStartCol = aMarkRange.aStart.Col(); + SCROW nStartRow = aMarkRange.aStart.Row(); + SCTAB nStartTab = aMarkRange.aStart.Tab(); + SCCOL nEndCol = aMarkRange.aEnd.Col(); + SCROW nEndRow = aMarkRange.aEnd.Row(); + SCTAB nEndTab = aMarkRange.aEnd.Tab(); + pDocSh->PostPaint( nStartCol, nStartRow, nStartTab, + nEndCol, nEndRow, nEndTab, + PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE ); + + pDocSh->UpdateOle( GetViewData() ); + pDocSh->SetDocumentModified(); + } +} + +#undef SET_LINE_ATTRIBUTES + + +//---------------------------------------------------------------------------- + +void ScViewFunc::SetConditionalFormat( const ScConditionalFormat& rNew ) +{ + ScDocument* pDoc = GetViewData()->GetDocument(); + sal_uLong nIndex = pDoc->AddCondFormat(rNew); // dafuer gibt's kein Undo + SfxUInt32Item aItem( ATTR_CONDITIONAL, nIndex ); + + ApplyAttr( aItem ); // mit Paint und Undo... +} + + +//---------------------------------------------------------------------------- + +void ScViewFunc::SetValidation( const ScValidationData& rNew ) +{ + ScDocument* pDoc = GetViewData()->GetDocument(); + sal_uLong nIndex = pDoc->AddValidationEntry(rNew); // dafuer gibt's kein Undo + SfxUInt32Item aItem( ATTR_VALIDDATA, nIndex ); + + ApplyAttr( aItem ); // mit Paint und Undo... +} + + diff --git a/sc/source/ui/view/viewfun3.cxx b/sc/source/ui/view/viewfun3.cxx new file mode 100644 index 000000000000..0f4893cf3512 --- /dev/null +++ b/sc/source/ui/view/viewfun3.cxx @@ -0,0 +1,1837 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +//---------------------------------------------------------------------------- + +#define _SV_NOXSOUND + +#define _BASE_DLGS_HXX +#define _BIGINT_HXX +#define _CACHESTR_HXX +#define _CONFIG_HXX +#define _CURSOR_HXX +#define _CTRLTOOL_HXX +#define _DLGCFG_HXX +#define _DYNARR_HXX +#define _EXTATTR_HXX +#define _FILDLG_HXX +#define _FONTDLG_HXX +#define _FRM3D_HXX +#define _INTRO_HXX +#define _ISETBWR_HXX +#define _NO_SVRTF_PARSER_HXX +#define _MACRODLG_HXX +#define _MODALDLG_HXX +#define _MOREBUTTON_HXX +#define _OUTLINER_HXX +//#define _PRNDLG_HXX +//#define _POLY_HXX +#define _PVRWIN_HXX +//#define _QUEUE_HXX +#define _RULER_HXX +#define _SCRWIN_HXX +#define _SETBRW_HXX +//#define _STACK_HXX +//#define _STATUS_HXX *** +#define _STDCTRL_HXX +#define _STDMENU_HXX +//#define _TAB_HXX +#define _TABBAR_HXX +#define _TREELIST_HXX +#define _VALUESET_HXX +#define _VCATTR_HXX +#define _VCBRW_HXX +#define _VCTRLS_HXX +#define _VCSBX_HXX +#define _VCONT_HXX +#define _VDRWOBJ_HXX + +//#define _SELENG_HXX +//#define _SOUND_HXX +//#define _SYSDLG_HXX + + + + +#define _PASSWD_HXX + +#define _SFX_DOCFILE_HXX +//#define _SFX_DOCFILT_HXX +#define _SFX_DOCINF_HXX +#define _SFX_DOCSH_HXX +//#define _SFXDOCFILT_HXX +//#define _SFXDOCINF_HXX +//#define _SFXDOCSH_HXX +#define _SFX_PRNMON_HXX +#define _SFX_RESMGR_HXX +#define _SFX_TEMPLDLG_HXX +//#define _SFXAPPWIN_HXX +#define _SFXBASIC_HXX +#define _SFXCTRLITEM +#define _SFXDLGCFG_HXX +//#define _SFXDISPATCH_HXX +#define _SFXFILEDLG_HXX +//#define _SFXIMGMGR_HXX +#define _SFXIPFRM_HXX +#define _SFX_MACRO_HXX +#define _SFXMNUITEM_HXX +#define _SFXMNUMGR_HXX +#define _SFXMULTISEL_HXX +//#define _SFXMSG_HXX +#define _SFXMSGDESCR_HXX +#define _SFXMSGPOOL_HXX +#define _SFX_MINFITEM_HXX +#define _SFXOBJFACE_HXX +#define _SFXOBJFAC_HXX +#define _SFX_SAVEOPT_HXX +#define _SFXSTBITEM_HXX +#define _SFXSTBMGR_HXX +#define _SFXTBXCTRL_HXX +#define _SFXTBXMGR_HXX + +#define _SI_HXX +//#define _SI_DLL_HXX +//#define _SIDLL_HXX +//#define _SI_NOITEMS +//#define _SI_NOOTHERFORMS +//#define _SI_NOSBXCONTROLS +//#define _SINOSBXCONTROLS +//#define _SI_NODRW +//#define _SI_NOCONTROL + +#define _SVBOXITM_HXX +#define _SVCONTNR_HXX // + +#define _SDR_NOTRANSFORM + +#define _SVDRAG_HXX +#define _SVINCVW_HXX +//#define _SV_MULTISEL_HXX +#define _SVRTV_HXX +#define _SVTABBX_HXX +#define _SVTREEBOX_HXX +#define _SVTREELIST_HXX + +#define _SVX_DAILDLL_HXX +#define _SVX_HYPHEN_HXX +#define _SVX_IMPGRF_HXX +#define _SVX_LAYCTRL_HXX +#define _SVX_OPTITEMS_HXX +#define _SVX_OPTGERL_HXX +#define _SVX_OPTSAVE_HXX +#define _SVX_OPTSPELL_HXX +#define _SVX_OPTPATH_HXX +#define _SVX_OPTLINGU_HXX +#define _SVX_RULER_HXX +#define _SVX_RULRITEM_HXX +#define _SVX_SELCTRL_HXX +#define _SVX_SPLWRAP_HXX +#define _SVX_SPLDLG_HXX +#define _SVX_STDDLG_HXX +#define _SVX_THESDLG_HXX + +// INCLUDE ------------------------------------------------------------------- + +#include "scitems.hxx" +#include <svx/dbexch.hrc> +#include <svx/svdetc.hxx> +#include <svx/svditer.hxx> +#include <svx/svdoole2.hxx> +#include <svx/svdpage.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/docfile.hxx> +#include <svl/stritem.hxx> +#include <svl/ptitem.hxx> +#include <svl/urlbmk.hxx> +#include <sot/clsids.hxx> +#include <sot/formats.hxx> +#include <vcl/graph.hxx> +#include <vcl/virdev.hxx> +#include <vcl/msgbox.hxx> +#include <tools/urlobj.hxx> +#include <sot/exchange.hxx> +#include <memory> + +#include "attrib.hxx" +#include "patattr.hxx" +#include "dociter.hxx" +#include "viewfunc.hxx" +#include "tabvwsh.hxx" +#include "docsh.hxx" +#include "docfunc.hxx" +#include "undoblk.hxx" +#include "refundo.hxx" +#include "globstr.hrc" +#include "global.hxx" +#include "transobj.hxx" +#include "drwtrans.hxx" +#include "rangenam.hxx" +#include "dbcolect.hxx" +#include "impex.hxx" // Sylk-ID fuer CB +#include "chgtrack.hxx" +#include "waitoff.hxx" +#include "scmod.hxx" +#include "sc.hrc" +#include "inputopt.hxx" +#include "warnbox.hxx" +#include "drwlayer.hxx" +#include "editable.hxx" +#include "transobj.hxx" +#include "drwtrans.hxx" +#include "docuno.hxx" +#include "clipparam.hxx" +#include "drawview.hxx" +#include "chartlis.hxx" +#include "charthelper.hxx" + + +using namespace com::sun::star; + +// STATIC DATA --------------------------------------------------------------- + + +//============================================================================ + +// GlobalName der Writer-DocShell kommt jetzt aus comphelper/classids.hxx + +//---------------------------------------------------------------------------- +// C U T + +void ScViewFunc::CutToClip( ScDocument* pClipDoc, sal_Bool bIncludeObjects ) +{ + UpdateInputLine(); + + ScEditableTester aTester( this ); + if (!aTester.IsEditable()) // selection editable? + { + ErrorMessage( aTester.GetMessageId() ); + return; + } + + ScRange aRange; // zu loeschender Bereich + if ( GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE ) + { + ScDocument* pDoc = GetViewData()->GetDocument(); + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + const sal_Bool bRecord(pDoc->IsUndoEnabled()); // Undo/Redo + + ScDocShellModificator aModificator( *pDocSh ); + + if ( !rMark.IsMarked() && !rMark.IsMultiMarked() ) // mark the range if not marked yet + { + DoneBlockMode(); + InitOwnBlockMode(); + rMark.SetMarkArea( aRange ); + MarkDataChanged(); + } + + CopyToClip( pClipDoc, sal_True, sal_False, bIncludeObjects ); // Ab ins Clipboard + + ScAddress aOldEnd( aRange.aEnd ); // Zusammengefasste Zellen im Bereich? + pDoc->ExtendMerge( aRange, sal_True ); + + ScDocument* pUndoDoc = NULL; + if ( bRecord ) + { + pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + pUndoDoc->InitUndoSelected( pDoc, rMark ); + // all sheets - CopyToDocument skips those that don't exist in pUndoDoc + ScRange aCopyRange = aRange; + aCopyRange.aStart.SetTab(0); + aCopyRange.aEnd.SetTab(pDoc->GetTableCount()-1); + pDoc->CopyToDocument( aCopyRange, (IDF_ALL & ~IDF_OBJECTS) | IDF_NOCAPTIONS, sal_False, pUndoDoc ); + pDoc->BeginDrawUndo(); + } + + sal_uInt16 nExtFlags = 0; + pDocSh->UpdatePaintExt( nExtFlags, aRange ); + + HideCursor(); // Cursor aendert sich ! + + rMark.MarkToMulti(); + pDoc->DeleteSelection( IDF_ALL, rMark ); + if ( bIncludeObjects ) + pDoc->DeleteObjectsInSelection( rMark ); + rMark.MarkToSimple(); + + if ( !AdjustRowHeight( aRange.aStart.Row(), aRange.aEnd.Row() ) ) + pDocSh->PostPaint( aRange, PAINT_GRID, nExtFlags ); + + if ( bRecord ) // erst jetzt ist Draw-Undo verfuegbar + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoCut( pDocSh, aRange, aOldEnd, rMark, pUndoDoc ) ); + + aModificator.SetDocumentModified(); + ShowCursor(); // Cursor aendert sich ! + pDocSh->UpdateOle(GetViewData()); + + CellContentChanged(); + } + else + ErrorMessage( STR_NOMULTISELECT ); +} + + +//---------------------------------------------------------------------------- +// C O P Y + +sal_Bool ScViewFunc::CopyToClip( ScDocument* pClipDoc, sal_Bool bCut, sal_Bool bApi, sal_Bool bIncludeObjects, sal_Bool bStopEdit ) +{ + sal_Bool bDone = sal_False; + if ( bStopEdit ) + UpdateInputLine(); + + ScRange aRange; + ScMarkType eMarkType = GetViewData()->GetSimpleArea( aRange ); + ScDocument* pDoc = GetViewData()->GetDocument(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + if ( eMarkType == SC_MARK_SIMPLE || eMarkType == SC_MARK_SIMPLE_FILTERED ) + { + if ( !pDoc->HasSelectedBlockMatrixFragment( + aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Col(), aRange.aEnd.Row(), + rMark ) ) + { + sal_Bool bSysClip = sal_False; + if ( !pClipDoc ) // no clip doc specified + { + pClipDoc = new ScDocument( SCDOCMODE_CLIP ); // create one (deleted by ScTransferObj) + bSysClip = sal_True; // and copy into system + } + + if ( !bCut ) + { + ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); + if ( pChangeTrack ) + pChangeTrack->ResetLastCut(); // kein CutMode mehr + } + + if ( bSysClip && bIncludeObjects ) + { + sal_Bool bAnyOle = pDoc->HasOLEObjectsInArea( aRange, &rMark ); + // update ScGlobal::pDrawClipDocShellRef + ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) ); + } + + ScClipParam aClipParam(aRange, bCut); + aClipParam.setSourceDocID( pDoc->GetDocumentID() ); + pDoc->CopyToClip(aClipParam, pClipDoc, &rMark, false, false, bIncludeObjects); + + if ( pDoc && pClipDoc ) + { + ScDrawLayer* pDrawLayer = pClipDoc->GetDrawLayer(); + if ( pDrawLayer ) + { + ScClipParam& rClipParam = pClipDoc->GetClipParam(); + ScRangeListVector& rRangesVector = rClipParam.maProtectedChartRangesVector; + SCTAB nTabCount = pClipDoc->GetTableCount(); + for ( SCTAB nTab = 0; nTab < nTabCount; ++nTab ) + { + SdrPage* pPage = pDrawLayer->GetPage( static_cast< sal_uInt16 >( nTab ) ); + if ( pPage ) + { + ScChartHelper::FillProtectedChartRangesVector( rRangesVector, pDoc, pPage ); + } + } + } + } + + if (bSysClip) + { + ScDrawLayer::SetGlobalDrawPersist(NULL); + + ScGlobal::SetClipDocName( pDoc->GetDocumentShell()->GetTitle( SFX_TITLE_FULLNAME ) ); + } + pClipDoc->ExtendMerge( aRange, sal_True ); + + if (bSysClip) + { + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + TransferableObjectDescriptor aObjDesc; + pDocSh->FillTransferableObjectDescriptor( aObjDesc ); + aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass(); + // maSize is set in ScTransferObj ctor + + ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc ); + uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj ); + + if ( ScGlobal::pDrawClipDocShellRef ) + { + SfxObjectShellRef aPersistRef( &(*ScGlobal::pDrawClipDocShellRef) ); + pTransferObj->SetDrawPersist( aPersistRef ); // keep persist for ole objects alive + } + + pTransferObj->CopyToClipboard( GetActiveWin() ); // system clipboard + SC_MOD()->SetClipObject( pTransferObj, NULL ); // internal clipboard + } + + bDone = sal_True; + } + else + { + if (!bApi) + ErrorMessage(STR_MATRIXFRAGMENTERR); + } + } + else if (eMarkType == SC_MARK_MULTI) + { + bool bSuccess = false; + ScClipParam aClipParam; + aClipParam.mbCutMode = false; + rMark.MarkToSimple(); + rMark.FillRangeListWithMarks(&aClipParam.maRanges, false); + + do + { + if (bCut) + // We con't support cutting of multi-selections. + break; + + if (pClipDoc) + // TODO: What's this for? + break; + + ::std::auto_ptr<ScDocument> pDocClip(new ScDocument(SCDOCMODE_CLIP)); + + // Check for geometrical feasibility of the ranges. + bool bValidRanges = true; + ScRangePtr p = aClipParam.maRanges.First(); + SCCOL nPrevColDelta = 0; + SCROW nPrevRowDelta = 0; + SCCOL nPrevCol = p->aStart.Col(); + SCROW nPrevRow = p->aStart.Row(); + SCCOL nPrevColSize = p->aEnd.Col() - p->aStart.Col() + 1; + SCROW nPrevRowSize = p->aEnd.Row() - p->aStart.Row() + 1; + for (p = aClipParam.maRanges.Next(); p; p = aClipParam.maRanges.Next()) + { + if (pDoc->HasSelectedBlockMatrixFragment( + p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(), rMark)) + { + if (!bApi) + ErrorMessage(STR_MATRIXFRAGMENTERR); + return false; + } + + SCCOL nColDelta = p->aStart.Col() - nPrevCol; + SCROW nRowDelta = p->aStart.Row() - nPrevRow; + + if ((nColDelta && nRowDelta) || (nPrevColDelta && nRowDelta) || (nPrevRowDelta && nColDelta)) + { + bValidRanges = false; + break; + } + + if (aClipParam.meDirection == ScClipParam::Unspecified) + { + if (nColDelta) + aClipParam.meDirection = ScClipParam::Column; + if (nRowDelta) + aClipParam.meDirection = ScClipParam::Row; + } + + SCCOL nColSize = p->aEnd.Col() - p->aStart.Col() + 1; + SCROW nRowSize = p->aEnd.Row() - p->aStart.Row() + 1; + + if (aClipParam.meDirection == ScClipParam::Column && nRowSize != nPrevRowSize) + { + // column-oriented ranges must have identical row size. + bValidRanges = false; + break; + } + if (aClipParam.meDirection == ScClipParam::Row && nColSize != nPrevColSize) + { + // likewise, row-oriented ranges must have identical + // column size. + bValidRanges = false; + break; + } + + nPrevCol = p->aStart.Col(); + nPrevRow = p->aStart.Row(); + nPrevColDelta = nColDelta; + nPrevRowDelta = nRowDelta; + nPrevColSize = nColSize; + nPrevRowSize = nRowSize; + } + if (!bValidRanges) + break; + + pDoc->CopyToClip(aClipParam, pDocClip.get(), &rMark, false, false, bIncludeObjects); + + ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); + if ( pChangeTrack ) + pChangeTrack->ResetLastCut(); // kein CutMode mehr + + { + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + TransferableObjectDescriptor aObjDesc; + pDocSh->FillTransferableObjectDescriptor( aObjDesc ); + aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass(); + // maSize is set in ScTransferObj ctor + + ScTransferObj* pTransferObj = new ScTransferObj( pDocClip.release(), aObjDesc ); + uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj ); + + if ( ScGlobal::pDrawClipDocShellRef ) + { + SfxObjectShellRef aPersistRef( &(*ScGlobal::pDrawClipDocShellRef) ); + pTransferObj->SetDrawPersist( aPersistRef ); // keep persist for ole objects alive + } + + pTransferObj->CopyToClipboard( GetActiveWin() ); // system clipboard + SC_MOD()->SetClipObject( pTransferObj, NULL ); // internal clipboard + } + + bSuccess = true; + } + while (false); + + if (!bSuccess && !bApi) + ErrorMessage(STR_NOMULTISELECT); + + bDone = bSuccess; + } + else + { + if (!bApi) + ErrorMessage(STR_NOMULTISELECT); + } + + return bDone; +} + +ScTransferObj* ScViewFunc::CopyToTransferable() +{ + ScRange aRange; + if ( GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE ) + { + ScDocument* pDoc = GetViewData()->GetDocument(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + if ( !pDoc->HasSelectedBlockMatrixFragment( + aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Col(), aRange.aEnd.Row(), + rMark ) ) + { + ScDocument *pClipDoc = new ScDocument( SCDOCMODE_CLIP ); // create one (deleted by ScTransferObj) + + sal_Bool bAnyOle = pDoc->HasOLEObjectsInArea( aRange, &rMark ); + ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) ); + + ScClipParam aClipParam(aRange, false); + pDoc->CopyToClip(aClipParam, pClipDoc, &rMark, false, false, true); + + ScDrawLayer::SetGlobalDrawPersist(NULL); + pClipDoc->ExtendMerge( aRange, sal_True ); + + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + TransferableObjectDescriptor aObjDesc; + pDocSh->FillTransferableObjectDescriptor( aObjDesc ); + aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass(); + ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc ); + return pTransferObj; + } + } + + return NULL; +} + +//---------------------------------------------------------------------------- +// P A S T E + +void ScViewFunc::PasteDraw() +{ + ScViewData* pViewData = GetViewData(); + SCCOL nPosX = pViewData->GetCurX(); + SCROW nPosY = pViewData->GetCurY(); + Window* pWin = GetActiveWin(); + Point aPos = pWin->PixelToLogic( pViewData->GetScrPos( nPosX, nPosY, + pViewData->GetActivePart() ) ); + ScDrawTransferObj* pDrawClip = ScDrawTransferObj::GetOwnClipboard( pWin ); + if (pDrawClip) + PasteDraw( aPos, pDrawClip->GetModel(), sal_False, + pDrawClip->GetSourceDocID() == pViewData->GetDocument()->GetDocumentID() ); +} + +void ScViewFunc::PasteFromSystem() +{ + UpdateInputLine(); + + Window* pWin = GetActiveWin(); + ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin ); + ScDrawTransferObj* pDrawClip = ScDrawTransferObj::GetOwnClipboard( pWin ); + + if (pOwnClip) + { + // #129384# keep a reference in case the clipboard is changed during PasteFromClip + uno::Reference<datatransfer::XTransferable> aOwnClipRef( pOwnClip ); + PasteFromClip( IDF_ALL, pOwnClip->GetDocument(), + PASTE_NOFUNC, sal_False, sal_False, sal_False, INS_NONE, IDF_NONE, + sal_True ); // allow warning dialog + } + else if (pDrawClip) + PasteDraw(); + else + { + TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) ); + +// if (pClipObj.Is()) + { + sal_uLong nBiff8 = SotExchange::RegisterFormatName( + String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Biff8"))); + sal_uLong nBiff5 = SotExchange::RegisterFormatName( + String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Biff5"))); + + // als erstes SvDraw-Model, dann Grafik + // (Grafik darf nur bei einzelner Grafik drinstehen) + + if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING )) + { + // special case for tables from drawing + if( aDataHelper.HasFormat( SOT_FORMAT_RTF ) ) + { + PasteFromSystem( FORMAT_RTF ); + } + else + { + PasteFromSystem( SOT_FORMATSTR_ID_DRAWING ); + } + } + else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB )) + PasteFromSystem( SOT_FORMATSTR_ID_SVXB ); + else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE )) + { + // If it's a Writer object, insert RTF instead of OLE + + sal_Bool bDoRtf = sal_False; + TransferableObjectDescriptor aObjDesc; + if( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) ) + { + bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) || + aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) ) + && aDataHelper.HasFormat( SOT_FORMAT_RTF ) ); + } + if ( bDoRtf ) + PasteFromSystem( FORMAT_RTF ); + else + PasteFromSystem( SOT_FORMATSTR_ID_EMBED_SOURCE ); + } + else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE )) + PasteFromSystem( SOT_FORMATSTR_ID_LINK_SOURCE ); + // the following format can not affect scenario from #89579# + else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE )) + PasteFromSystem( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ); + // FORMAT_PRIVATE no longer here (can't work if pOwnClip is NULL) + else if (aDataHelper.HasFormat(nBiff8)) // before xxx_OLE formats + PasteFromSystem(nBiff8); + else if (aDataHelper.HasFormat(nBiff5)) + PasteFromSystem(nBiff5); + else if (aDataHelper.HasFormat(FORMAT_RTF)) + PasteFromSystem(FORMAT_RTF); + else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_HTML)) + PasteFromSystem(SOT_FORMATSTR_ID_HTML); + else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_HTML_SIMPLE)) + PasteFromSystem(SOT_FORMATSTR_ID_HTML_SIMPLE); + else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_SYLK)) + PasteFromSystem(SOT_FORMATSTR_ID_SYLK); + else if (aDataHelper.HasFormat(FORMAT_STRING)) + PasteFromSystem(FORMAT_STRING); + else if (aDataHelper.HasFormat(FORMAT_GDIMETAFILE)) + PasteFromSystem(FORMAT_GDIMETAFILE); + else if (aDataHelper.HasFormat(FORMAT_BITMAP)) + PasteFromSystem(FORMAT_BITMAP); + // #89579# xxx_OLE formats come last, like in SotExchange tables + else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE )) + PasteFromSystem( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ); + else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE )) + PasteFromSystem( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ); +// else +// ErrorMessage(STR_PASTE_ERROR); + } +// else +// ErrorMessage(STR_PASTE_ERROR); + } + + // keine Fehlermeldung, weil SID_PASTE in der idl das FastCall-Flag hat, + // also auch gerufen wird, wenn nichts im Clipboard steht (#42531#) +} + +void ScViewFunc::PasteFromTransferable( const uno::Reference<datatransfer::XTransferable>& rxTransferable ) +{ + ScTransferObj *pOwnClip=0; + ScDrawTransferObj *pDrawClip=0; + uno::Reference<lang::XUnoTunnel> xTunnel( rxTransferable, uno::UNO_QUERY ); + if ( xTunnel.is() ) + { + sal_Int64 nHandle = xTunnel->getSomething( ScTransferObj::getUnoTunnelId() ); + if ( nHandle ) + pOwnClip = (ScTransferObj*) (sal_IntPtr) nHandle; + else + { + nHandle = xTunnel->getSomething( ScDrawTransferObj::getUnoTunnelId() ); + if ( nHandle ) + pDrawClip = (ScDrawTransferObj*) (sal_IntPtr) nHandle; + } + } + + if (pOwnClip) + { + PasteFromClip( IDF_ALL, pOwnClip->GetDocument(), + PASTE_NOFUNC, sal_False, sal_False, sal_False, INS_NONE, IDF_NONE, + sal_True ); // allow warning dialog + } + else if (pDrawClip) + { + ScViewData* pViewData = GetViewData(); + SCCOL nPosX = pViewData->GetCurX(); + SCROW nPosY = pViewData->GetCurY(); + Window* pWin = GetActiveWin(); + Point aPos = pWin->PixelToLogic( pViewData->GetScrPos( nPosX, nPosY, pViewData->GetActivePart() ) ); + PasteDraw( aPos, pDrawClip->GetModel(), sal_False, pDrawClip->GetSourceDocID() == pViewData->GetDocument()->GetDocumentID() ); + } + else + { + TransferableDataHelper aDataHelper( rxTransferable ); + { + sal_uLong nBiff8 = SotExchange::RegisterFormatName( + String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Biff8"))); + sal_uLong nBiff5 = SotExchange::RegisterFormatName( + String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Biff5"))); + sal_uLong nFormatId = 0; + // als erstes SvDraw-Model, dann Grafik + // (Grafik darf nur bei einzelner Grafik drinstehen) + + if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING )) + nFormatId = SOT_FORMATSTR_ID_DRAWING; + else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB )) + nFormatId = SOT_FORMATSTR_ID_SVXB; + else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE )) + { + // If it's a Writer object, insert RTF instead of OLE + sal_Bool bDoRtf = sal_False; + TransferableObjectDescriptor aObjDesc; + if( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) ) + { + bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) || + aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) ) + && aDataHelper.HasFormat( SOT_FORMAT_RTF ) ); + } + if ( bDoRtf ) + nFormatId = FORMAT_RTF; + else + nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE; + } + else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE )) + nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE; + // the following format can not affect scenario from #89579# + else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE )) + nFormatId = SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE; + // FORMAT_PRIVATE no longer here (can't work if pOwnClip is NULL) + else if (aDataHelper.HasFormat(nBiff8)) // before xxx_OLE formats + nFormatId = nBiff8; + else if (aDataHelper.HasFormat(nBiff5)) + nFormatId = nBiff5; + else if (aDataHelper.HasFormat(FORMAT_RTF)) + nFormatId = FORMAT_RTF; + else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_HTML)) + nFormatId = SOT_FORMATSTR_ID_HTML; + else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_HTML_SIMPLE)) + nFormatId = SOT_FORMATSTR_ID_HTML_SIMPLE; + else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_SYLK)) + nFormatId = SOT_FORMATSTR_ID_SYLK; + else if (aDataHelper.HasFormat(FORMAT_STRING)) + nFormatId = FORMAT_STRING; + else if (aDataHelper.HasFormat(FORMAT_GDIMETAFILE)) + nFormatId = FORMAT_GDIMETAFILE; + else if (aDataHelper.HasFormat(FORMAT_BITMAP)) + nFormatId = FORMAT_BITMAP; + // #89579# xxx_OLE formats come last, like in SotExchange tables + else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE )) + nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE_OLE; + else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE )) + nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE; + else + return; + + PasteDataFormat( nFormatId, aDataHelper.GetTransferable(), + GetViewData()->GetCurX(), GetViewData()->GetCurY(), + NULL, sal_False, sal_False ); + } + } +} + +sal_Bool ScViewFunc::PasteFromSystem( sal_uLong nFormatId, sal_Bool bApi ) +{ + UpdateInputLine(); + + sal_Bool bRet = sal_True; + Window* pWin = GetActiveWin(); + ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin ); + if ( nFormatId == 0 && pOwnClip ) + { + // #129384# keep a reference in case the clipboard is changed during PasteFromClip + uno::Reference<datatransfer::XTransferable> aOwnClipRef( pOwnClip ); + PasteFromClip( IDF_ALL, pOwnClip->GetDocument(), + PASTE_NOFUNC, sal_False, sal_False, sal_False, INS_NONE, IDF_NONE, + !bApi ); // allow warning dialog + } + else + { + TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) ); + if ( !aDataHelper.GetTransferable().is() ) + return sal_False; + + bRet = PasteDataFormat( nFormatId, aDataHelper.GetTransferable(), + GetViewData()->GetCurX(), GetViewData()->GetCurY(), + NULL, sal_False, !bApi ); // allow warning dialog + + if ( !bRet && !bApi ) + ErrorMessage(STR_PASTE_ERROR); + } + return bRet; +} + + +//---------------------------------------------------------------------------- +// P A S T E + +sal_Bool ScViewFunc::PasteOnDrawObject( const uno::Reference<datatransfer::XTransferable>& rxTransferable, + SdrObject* pHitObj, sal_Bool bLink ) +{ + sal_Bool bRet = sal_False; + if ( bLink ) + { + TransferableDataHelper aDataHelper( rxTransferable ); + if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ) ) + { + SotStorageStreamRef xStm; + if( aDataHelper.GetSotStorageStream( SOT_FORMATSTR_ID_SVXB, xStm ) ) + { + Graphic aGraphic; + *xStm >> aGraphic; + bRet = ApplyGraphicToObject( pHitObj, aGraphic ); + } + } + else if ( aDataHelper.HasFormat( SOT_FORMAT_GDIMETAFILE ) ) + { + GDIMetaFile aMtf; + if( aDataHelper.GetGDIMetaFile( FORMAT_GDIMETAFILE, aMtf ) ) + bRet = ApplyGraphicToObject( pHitObj, Graphic(aMtf) ); + } + else if ( aDataHelper.HasFormat( SOT_FORMAT_BITMAP ) ) + { + Bitmap aBmp; + if( aDataHelper.GetBitmap( FORMAT_BITMAP, aBmp ) ) + bRet = ApplyGraphicToObject( pHitObj, Graphic(aBmp) ); + } + } + else + { + // ham' wa noch nich + } + return bRet; +} + +sal_Bool lcl_SelHasAttrib( ScDocument* pDoc, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, + const ScMarkData& rTabSelection, sal_uInt16 nMask ) +{ + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB nTab=0; nTab<nTabCount; nTab++) + if ( rTabSelection.GetTableSelect(nTab) && pDoc->HasAttrib( nCol1, nRow1, nTab, nCol2, nRow2, nTab, nMask ) ) + return sal_True; + return sal_False; +} + +// +// Einfuegen auf Tabelle: +// + +// internes Paste + +namespace { + +class CursorSwitcher +{ +public: + CursorSwitcher(ScViewFunc* pViewFunc) : + mpViewFunc(pViewFunc) + { + mpViewFunc->HideCursor(); + } + + ~CursorSwitcher() + { + mpViewFunc->ShowCursor(); + } +private: + ScViewFunc* mpViewFunc; +}; + +bool lcl_checkDestRangeForOverwrite(const ScRange& rDestRange, const ScDocument* pDoc, const ScMarkData& rMark, Window* pParentWnd) +{ + bool bIsEmpty = true; + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB nTab=0; nTab < nTabCount && bIsEmpty; ++nTab) + { + if (!rMark.GetTableSelect(nTab)) + continue; + + bIsEmpty = pDoc->IsBlockEmpty(nTab, rDestRange.aStart.Col(), rDestRange.aStart.Row(), + rDestRange.aEnd.Col(), rDestRange.aEnd.Row()); + } + + if (!bIsEmpty) + { + ScReplaceWarnBox aBox(pParentWnd); + if (aBox.Execute() != RET_YES) + { + // changing the configuration is within the ScReplaceWarnBox + return false; + } + } + return true; +} + +} + +sal_Bool ScViewFunc::PasteFromClip( sal_uInt16 nFlags, ScDocument* pClipDoc, + sal_uInt16 nFunction, sal_Bool bSkipEmpty, + sal_Bool bTranspose, sal_Bool bAsLink, + InsCellCmd eMoveMode, sal_uInt16 nUndoExtraFlags, + sal_Bool bAllowDialogs ) +{ + if (!pClipDoc) + { + DBG_ERROR("PasteFromClip: pClipDoc=0 not allowed"); + return sal_False; + } + + // fuer Undo etc. immer alle oder keine Inhalte sichern + sal_uInt16 nContFlags = IDF_NONE; + if (nFlags & IDF_CONTENTS) + nContFlags |= IDF_CONTENTS; + if (nFlags & IDF_ATTRIB) + nContFlags |= IDF_ATTRIB; + // evtl. Attribute ins Undo ohne sie vom Clip ins Doc zu kopieren + sal_uInt16 nUndoFlags = nContFlags; + if (nUndoExtraFlags & IDF_ATTRIB) + nUndoFlags |= IDF_ATTRIB; + // do not copy note captions into undo document + nUndoFlags |= IDF_NOCAPTIONS; + + ScClipParam& rClipParam = pClipDoc->GetClipParam(); + if (rClipParam.isMultiRange()) + return PasteMultiRangesFromClip( + nFlags, pClipDoc, nFunction, bSkipEmpty, bTranspose, bAsLink, bAllowDialogs, + eMoveMode, nContFlags, nUndoFlags); + + sal_Bool bCutMode = pClipDoc->IsCutMode(); // if transposing, take from original clipdoc + sal_Bool bIncludeFiltered = bCutMode; + + // paste drawing: also if IDF_NOTE is set (to create drawing layer for note captions) + sal_Bool bPasteDraw = ( pClipDoc->GetDrawLayer() && ( nFlags & (IDF_OBJECTS|IDF_NOTE) ) ); + + ScDocShellRef aTransShellRef; // for objects in xTransClip - must remain valid as long as xTransClip + ScDocument* pOrigClipDoc = NULL; + ::std::auto_ptr< ScDocument > xTransClip; + if ( bTranspose ) + { + SCCOL nX; + SCROW nY; + // include filtered rows until TransposeClip can skip them + bIncludeFiltered = sal_True; + pClipDoc->GetClipArea( nX, nY, sal_True ); + if ( nY > static_cast<sal_Int32>(MAXCOL) ) // zuviele Zeilen zum Transponieren + { + ErrorMessage(STR_PASTE_FULL); + return sal_False; + } + pOrigClipDoc = pClipDoc; // fuer Referenzen + + if ( bPasteDraw ) + { + aTransShellRef = new ScDocShell; // DocShell needs a Ref immediately + aTransShellRef->DoInitNew(NULL); + } + ScDrawLayer::SetGlobalDrawPersist(aTransShellRef); + + xTransClip.reset( new ScDocument( SCDOCMODE_CLIP )); + pClipDoc->TransposeClip( xTransClip.get(), nFlags, bAsLink ); + pClipDoc = xTransClip.get(); + + ScDrawLayer::SetGlobalDrawPersist(NULL); + } + + SCCOL nStartCol; + SCROW nStartRow; + SCTAB nStartTab; + SCCOL nEndCol; + SCROW nEndRow; + SCTAB nEndTab; + SCCOL nClipSizeX; + SCROW nClipSizeY; + pClipDoc->GetClipArea( nClipSizeX, nClipSizeY, sal_True ); // size in clipboard doc + + // size in target doc: include filtered rows only if CutMode is set + SCCOL nDestSizeX; + SCROW nDestSizeY; + pClipDoc->GetClipArea( nDestSizeX, nDestSizeY, bIncludeFiltered ); + + ScDocument* pDoc = GetViewData()->GetDocument(); + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager(); + const sal_Bool bRecord(pDoc->IsUndoEnabled()); + + ScDocShellModificator aModificator( *pDocSh ); + + ScRange aMarkRange; + ScMarkData aFilteredMark( rMark); // local copy for all modifications + ScMarkType eMarkType = GetViewData()->GetSimpleArea( aMarkRange, aFilteredMark); + bool bMarkIsFiltered = (eMarkType == SC_MARK_SIMPLE_FILTERED); + bool bNoPaste = ((eMarkType != SC_MARK_SIMPLE && !bMarkIsFiltered) || + (bMarkIsFiltered && (eMoveMode != INS_NONE || bAsLink))); + if (!bNoPaste && !rMark.IsMarked()) + { + // Create a selection with clipboard row count and check that for + // filtered. + nStartCol = GetViewData()->GetCurX(); + nStartRow = GetViewData()->GetCurY(); + nStartTab = GetViewData()->GetTabNo(); + nEndCol = nStartCol + nDestSizeX; + nEndRow = nStartRow + nDestSizeY; + nEndTab = nStartTab; + aMarkRange = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab); + if (ScViewUtil::HasFiltered( aMarkRange, pDoc)) + { + bMarkIsFiltered = true; + // Fit to clipboard's row count unfiltered rows. If there is no + // fit assume that pasting is not possible. Note that nDestSizeY is + // size-1 (difference). + if (!ScViewUtil::FitToUnfilteredRows( aMarkRange, pDoc, nDestSizeY+1)) + bNoPaste = true; + } + aFilteredMark.SetMarkArea( aMarkRange); + } + if (bNoPaste) + { + ErrorMessage(STR_MSSG_PASTEFROMCLIP_0); + return sal_False; + } + + SCROW nUnfilteredRows = aMarkRange.aEnd.Row() - aMarkRange.aStart.Row() + 1; + ScRangeList aRangeList; + if (bMarkIsFiltered) + { + ScViewUtil::UnmarkFiltered( aFilteredMark, pDoc); + aFilteredMark.FillRangeListWithMarks( &aRangeList, sal_False); + nUnfilteredRows = 0; + for (ScRange* p = aRangeList.First(); p; p = aRangeList.Next()) + { + nUnfilteredRows += p->aEnd.Row() - p->aStart.Row() + 1; + } +#if 0 + /* This isn't needed but could be a desired restriction. */ + // For filtered, destination rows have to be an exact multiple of + // source rows. Note that nDestSizeY is size-1 (difference), so + // nDestSizeY==0 fits always. + if ((nUnfilteredRows % (nDestSizeY+1)) != 0) + { + /* FIXME: this should be a more descriptive error message then. */ + ErrorMessage(STR_MSSG_PASTEFROMCLIP_0); + return sal_False; + } +#endif + } + + SCCOL nMarkAddX = 0; + SCROW nMarkAddY = 0; + + // Also for a filtered selection the area is used, for undo et al. + if ( aFilteredMark.IsMarked() || bMarkIsFiltered ) + { + aMarkRange.GetVars( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab); + SCCOL nBlockAddX = nEndCol-nStartCol; + SCROW nBlockAddY = nEndRow-nStartRow; + + // #58422# Nachfrage, wenn die Selektion groesser als 1 Zeile/Spalte, aber kleiner + // als das Clipboard ist (dann wird ueber die Selektion hinaus eingefuegt) + + // ClipSize is not size, but difference + if ( ( nBlockAddX != 0 && nBlockAddX < nDestSizeX ) || + ( nBlockAddY != 0 && nBlockAddY < nDestSizeY ) || + ( bMarkIsFiltered && nUnfilteredRows < nDestSizeY+1 ) ) + { + ScWaitCursorOff aWaitOff( GetFrameWin() ); + String aMessage = ScGlobal::GetRscString( STR_PASTE_BIGGER ); + QueryBox aBox( GetViewData()->GetDialogParent(), + WinBits(WB_YES_NO | WB_DEF_NO), aMessage ); + if ( aBox.Execute() != RET_YES ) + { + return sal_False; + } + } + + if (nBlockAddX > nDestSizeX) + nMarkAddX = nBlockAddX - nDestSizeX; // fuer Merge-Test + else + nEndCol = nStartCol + nDestSizeX; + + if (nBlockAddY > nDestSizeY) + nMarkAddY = nBlockAddY - nDestSizeY; // fuer Merge-Test + else + { + nEndRow = nStartRow + nDestSizeY; + if (bMarkIsFiltered || nEndRow > aMarkRange.aEnd.Row()) + { + // Same as above if nothing was marked: re-fit selection to + // unfiltered rows. Extending the selection actually may + // introduce filtered rows where there weren't any before, so + // we also need to test for that. + aMarkRange = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab); + if (bMarkIsFiltered || ScViewUtil::HasFiltered( aMarkRange, pDoc)) + { + bMarkIsFiltered = true; + // Worst case: all rows up to the end of the sheet are filtered. + if (!ScViewUtil::FitToUnfilteredRows( aMarkRange, pDoc, nDestSizeY+1)) + { + ErrorMessage(STR_PASTE_FULL); + return sal_False; + } + } + aMarkRange.GetVars( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab); + aFilteredMark.SetMarkArea( aMarkRange); + if (bMarkIsFiltered) + { + ScViewUtil::UnmarkFiltered( aFilteredMark, pDoc); + aFilteredMark.FillRangeListWithMarks( &aRangeList, sal_True); + } + } + } + } + else + { + nStartCol = GetViewData()->GetCurX(); + nStartRow = GetViewData()->GetCurY(); + nStartTab = GetViewData()->GetTabNo(); + nEndCol = nStartCol + nDestSizeX; + nEndRow = nStartRow + nDestSizeY; + nEndTab = nStartTab; + } + + bool bOffLimits = !ValidCol(nEndCol) || !ValidRow(nEndRow); + + // Zielbereich, wie er angezeigt wird: + ScRange aUserRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ); + + // Sollen Zellen eingefuegt werden? + // (zu grosse nEndCol/nEndRow werden weiter unten erkannt) + sal_Bool bInsertCells = ( eMoveMode != INS_NONE && !bOffLimits ); + if ( bInsertCells ) + { + // #94115# Instead of EnterListAction, the paste undo action is merged into the + // insert action, so Repeat can insert the right cells + + MarkRange( aUserRange ); // wird vor CopyFromClip sowieso gesetzt + + // #72930# CutMode is reset on insertion of cols/rows but needed again on cell move + sal_Bool bCut = pClipDoc->IsCutMode(); + if (!InsertCells( eMoveMode, bRecord, sal_True )) // is inserting possible? + { + return sal_False; + // #i21036# EnterListAction isn't used, and InsertCells doesn't insert + // its undo action on failure, so no undo handling is needed here + } + if ( bCut ) + pClipDoc->SetCutMode( bCut ); + } + else if (!bOffLimits) + { + sal_Bool bAskIfNotEmpty = bAllowDialogs && + ( nFlags & IDF_CONTENTS ) && + nFunction == PASTE_NOFUNC && + SC_MOD()->GetInputOptions().GetReplaceCellsWarn(); + if ( bAskIfNotEmpty ) + { + if (!lcl_checkDestRangeForOverwrite(aUserRange, pDoc, aFilteredMark, GetViewData()->GetDialogParent())) + return false; + } + } + + SCCOL nClipStartX; // Clipboard-Bereich erweitern + SCROW nClipStartY; + pClipDoc->GetClipStart( nClipStartX, nClipStartY ); + SCCOL nUndoEndCol = nClipStartX + nClipSizeX; + SCROW nUndoEndRow = nClipStartY + nClipSizeY; // end of source area in clipboard document + sal_Bool bClipOver = sal_False; + // #i68690# ExtendMerge for the clip doc must be called with the clipboard's sheet numbers. + // The same end column/row can be used for all calls because the clip doc doesn't contain + // content outside the clip area. + for (SCTAB nClipTab=0; nClipTab<=MAXTAB; nClipTab++) + if ( pClipDoc->HasTable(nClipTab) ) + if ( pClipDoc->ExtendMerge( nClipStartX,nClipStartY, nUndoEndCol,nUndoEndRow, nClipTab, sal_False ) ) + bClipOver = sal_True; + nUndoEndCol -= nClipStartX + nClipSizeX; + nUndoEndRow -= nClipStartY + nClipSizeY; // now contains only the difference added by ExtendMerge + nUndoEndCol = sal::static_int_cast<SCCOL>( nUndoEndCol + nEndCol ); + nUndoEndRow = sal::static_int_cast<SCROW>( nUndoEndRow + nEndRow ); // destination area, expanded for merged cells + +// if (nUndoEndCol < nEndCol) nUndoEndCol = nEndCol; +// if (nUndoEndRow < nEndRow) nUndoEndRow = nEndRow; + +// nUndoEndCol += nMarkAddX; +// nUndoEndRow += nMarkAddY; + + if (nUndoEndCol>MAXCOL || nUndoEndRow>MAXROW) + { + ErrorMessage(STR_PASTE_FULL); + return sal_False; + } + + pDoc->ExtendMergeSel( nStartCol,nStartRow, nUndoEndCol,nUndoEndRow, aFilteredMark, sal_False ); + + // Test auf Zellschutz + + ScEditableTester aTester( pDoc, nStartTab, nStartCol,nStartRow, nUndoEndCol,nUndoEndRow ); + if (!aTester.IsEditable()) + { + ErrorMessage(aTester.GetMessageId()); + return sal_False; + } + + //! Test auf Ueberlappung + //! nur wirkliche Schnittmenge testen !!!!!!! + + // pDoc->HasCommonAttr( StartCol,nStartRow, nUndoEndCol,nUndoEndRow, nStartTab, + // pClipDoc, nClipStartX, nClipStartY ); + + ScDocFunc& rDocFunc = pDocSh->GetDocFunc(); + if ( bRecord ) + { + String aUndo = ScGlobal::GetRscString( pClipDoc->IsCutMode() ? STR_UNDO_MOVE : STR_UNDO_COPY ); + pUndoMgr->EnterListAction( aUndo, aUndo ); + } + + if (bClipOver) + if (lcl_SelHasAttrib( pDoc, nStartCol,nStartRow, nUndoEndCol,nUndoEndRow, aFilteredMark, HASATTR_OVERLAPPED )) + { // "Cell merge not possible if cells already merged" + ScDocAttrIterator aIter( pDoc, nStartTab, nStartCol, nStartRow, nUndoEndCol, nUndoEndRow ); + const ScPatternAttr* pPattern = NULL; + const ScMergeAttr* pMergeFlag = NULL; + const ScMergeFlagAttr* pMergeFlagAttr = NULL; + SCCOL nCol = -1; + SCROW nRow1 = -1; + SCROW nRow2 = -1; + while ( ( pPattern = aIter.GetNext( nCol, nRow1, nRow2 ) ) != NULL ) + { + pMergeFlag = (const ScMergeAttr*) &pPattern->GetItem(ATTR_MERGE); + pMergeFlagAttr = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG); + if( ( pMergeFlag && pMergeFlag->IsMerged() ) || ( pMergeFlagAttr && pMergeFlagAttr->IsOverlapped() ) ) + { + ScRange aRange(nCol, nRow1, nStartTab); + pDoc->ExtendOverlapped(aRange); + pDoc->ExtendMerge(aRange, sal_True, sal_True); + rDocFunc.UnmergeCells(aRange, bRecord, sal_True); + } + } + } + + if ( !bCutMode ) + { + ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); + if ( pChangeTrack ) + pChangeTrack->ResetLastCut(); // kein CutMode mehr + } + + sal_Bool bColInfo = ( nStartRow==0 && nEndRow==MAXROW ); + sal_Bool bRowInfo = ( nStartCol==0 && nEndCol==MAXCOL ); + + ScDocument* pUndoDoc = NULL; + ScDocument* pRefUndoDoc = NULL; + ScDocument* pRedoDoc = NULL; + ScRefUndoData* pUndoData = NULL; + + if ( bRecord ) + { + pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + pUndoDoc->InitUndoSelected( pDoc, aFilteredMark, bColInfo, bRowInfo ); + + // all sheets - CopyToDocument skips those that don't exist in pUndoDoc + SCTAB nTabCount = pDoc->GetTableCount(); + pDoc->CopyToDocument( nStartCol, nStartRow, 0, nUndoEndCol, nUndoEndRow, nTabCount-1, + nUndoFlags, sal_False, pUndoDoc ); + + if ( bCutMode ) + { + pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, sal_False, sal_False ); + + pUndoData = new ScRefUndoData( pDoc ); + } + } + + sal_uInt16 nExtFlags = 0; + pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab, + nEndCol, nEndRow, nEndTab ); // content before the change + + if (GetViewData()->IsActive()) + { + DoneBlockMode(); + InitOwnBlockMode(); + } + rMark.SetMarkArea( aUserRange ); + MarkDataChanged(); + + HideCursor(); // Cursor aendert sich ! + + // + // Aus Clipboard kopieren, + // wenn gerechnet werden soll, Originaldaten merken + // + + ScDocument* pMixDoc = NULL; + if ( bSkipEmpty || nFunction ) + { + if ( nFlags & IDF_CONTENTS ) + { + pMixDoc = new ScDocument( SCDOCMODE_UNDO ); + pMixDoc->InitUndo( pDoc, nStartTab, nEndTab ); + pDoc->CopyToDocument( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab, + IDF_CONTENTS, sal_False, pMixDoc ); + } + } + + /* Make draw layer and start drawing undo. + - Needed before AdjustBlockHeight to track moved drawing objects. + - Needed before pDoc->CopyFromClip to track inserted note caption objects. + */ + if ( bPasteDraw ) + pDocSh->MakeDrawLayer(); + if ( bRecord ) + pDoc->BeginDrawUndo(); + + sal_uInt16 nNoObjFlags = nFlags & ~IDF_OBJECTS; + if (!bAsLink) + { + // copy normally (original range) + pDoc->CopyFromClip( aUserRange, aFilteredMark, nNoObjFlags, + pRefUndoDoc, pClipDoc, sal_True, sal_False, bIncludeFiltered, + bSkipEmpty, (bMarkIsFiltered ? &aRangeList : NULL) ); + + // bei Transpose Referenzen per Hand anpassen + if ( bTranspose && bCutMode && (nFlags & IDF_CONTENTS) ) + pDoc->UpdateTranspose( aUserRange.aStart, pOrigClipDoc, aFilteredMark, pRefUndoDoc ); + } + else if (!bTranspose) + { + // copy with bAsLink=TRUE + pDoc->CopyFromClip( aUserRange, aFilteredMark, nNoObjFlags, pRefUndoDoc, pClipDoc, + sal_True, sal_True, bIncludeFiltered, bSkipEmpty ); + } + else + { + // alle Inhalte kopieren (im TransClipDoc stehen nur Formeln) + pDoc->CopyFromClip( aUserRange, aFilteredMark, nContFlags, pRefUndoDoc, pClipDoc ); + } + + // skipped rows and merged cells don't mix + if ( !bIncludeFiltered && pClipDoc->HasClipFilteredRows() ) + rDocFunc.UnmergeCells( aUserRange, sal_False, sal_True ); + + pDoc->ExtendMergeSel( nStartCol, nStartRow, nEndCol, nEndRow, aFilteredMark, sal_True ); // Refresh + // und Bereich neu + + if ( pMixDoc ) // Rechenfunktionen mit Original-Daten auszufuehren ? + { + pDoc->MixDocument( aUserRange, nFunction, bSkipEmpty, pMixDoc ); + } + delete pMixDoc; + + AdjustBlockHeight(); // update row heights before pasting objects + + ::std::vector< ::rtl::OUString > aExcludedChartNames; + SdrPage* pPage = NULL; + + if ( nFlags & IDF_OBJECTS ) + { + ScDrawView* pScDrawView = GetScDrawView(); + SdrModel* pModel = ( pScDrawView ? pScDrawView->GetModel() : NULL ); + pPage = ( pModel ? pModel->GetPage( static_cast< sal_uInt16 >( nStartTab ) ) : NULL ); + if ( pPage ) + { + ScChartHelper::GetChartNames( aExcludedChartNames, pPage ); + } + + // Paste the drawing objects after the row heights have been updated. + + pDoc->CopyFromClip( aUserRange, aFilteredMark, IDF_OBJECTS, pRefUndoDoc, pClipDoc, + sal_True, sal_False, bIncludeFiltered ); + } + + // + // + // + + pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab, + nEndCol, nEndRow, nEndTab ); // content after the change + + + // ggf. Autofilter-Koepfe loeschen + if (bCutMode) + if (pDoc->RefreshAutoFilter( nClipStartX,nClipStartY, nClipStartX+nClipSizeX, + nClipStartY+nClipSizeY, nStartTab )) + pDocSh->PostPaint( nClipStartX,nClipStartY,nStartTab, + nClipStartX+nClipSizeX,nClipStartY,nStartTab, + PAINT_GRID ); + + ShowCursor(); // Cursor aendert sich ! + + //! Block-Bereich bei RefUndoDoc weglassen !!! + + if ( bRecord ) + { + // Redo-Daten werden erst beim ersten Undo kopiert + // ohne RefUndoDoc muss das Redo-Doc noch nicht angelegt werden + + if (pRefUndoDoc) + { + pRedoDoc = new ScDocument( SCDOCMODE_UNDO ); + pRedoDoc->InitUndo( pDoc, nStartTab, nEndTab, bColInfo, bRowInfo ); + + // angepasste Referenzen ins Redo-Doc + + SCTAB nTabCount = pDoc->GetTableCount(); + pRedoDoc->AddUndoTab( 0, nTabCount-1 ); + pDoc->CopyUpdated( pRefUndoDoc, pRedoDoc ); + + // alte Referenzen ins Undo-Doc + + //! Tabellen selektieren ? + pUndoDoc->AddUndoTab( 0, nTabCount-1 ); + pRefUndoDoc->DeleteArea( nStartCol, nStartRow, nEndCol, nEndRow, aFilteredMark, IDF_ALL ); + pRefUndoDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1, + IDF_FORMULA, sal_False, pUndoDoc ); + delete pRefUndoDoc; + } + + // DeleteUnchanged for pUndoData is in ScUndoPaste ctor, + // UndoData for redo is made during first undo + + ScUndoPasteOptions aOptions; // store options for repeat + aOptions.nFunction = nFunction; + aOptions.bSkipEmpty = bSkipEmpty; + aOptions.bTranspose = bTranspose; + aOptions.bAsLink = bAsLink; + aOptions.eMoveMode = eMoveMode; + + SfxUndoAction* pUndo = new ScUndoPaste( pDocSh, + nStartCol, nStartRow, nStartTab, + nUndoEndCol, nUndoEndRow, nEndTab, aFilteredMark, + pUndoDoc, pRedoDoc, nFlags | nUndoFlags, + pUndoData, NULL, NULL, NULL, + sal_False, &aOptions ); // sal_False = Redo data not yet copied + + if ( bInsertCells ) + { + // Merge the paste undo action into the insert action. + // Use ScUndoWrapper so the ScUndoPaste pointer can be stored in the insert action. + + pUndoMgr->AddUndoAction( new ScUndoWrapper( pUndo ), sal_True ); + } + else + pUndoMgr->AddUndoAction( pUndo ); + pUndoMgr->LeaveListAction(); + } + + sal_uInt16 nPaint = PAINT_GRID; + if (bColInfo) + { + nPaint |= PAINT_TOP; + nUndoEndCol = MAXCOL; // nur zum Zeichnen ! + } + if (bRowInfo) + { + nPaint |= PAINT_LEFT; + nUndoEndRow = MAXROW; // nur zum Zeichnen ! + } + pDocSh->PostPaint( nStartCol, nStartRow, nStartTab, + nUndoEndCol, nUndoEndRow, nEndTab, nPaint, nExtFlags ); + // AdjustBlockHeight has already been called above + + aModificator.SetDocumentModified(); + PostPasteFromClip(aUserRange, rMark); + + if ( nFlags & IDF_OBJECTS ) + { + ScModelObj* pModelObj = ( pDocSh ? ScModelObj::getImplementation( pDocSh->GetModel() ) : NULL ); + if ( pDoc && pPage && pModelObj ) + { + bool bSameDoc = ( rClipParam.getSourceDocID() == pDoc->GetDocumentID() ); + const ScRangeListVector& rProtectedChartRangesVector( rClipParam.maProtectedChartRangesVector ); + ScChartHelper::CreateProtectedChartListenersAndNotify( pDoc, pPage, pModelObj, nStartTab, + rProtectedChartRangesVector, aExcludedChartNames, bSameDoc ); + } + } + + return sal_True; +} + +bool ScViewFunc::PasteMultiRangesFromClip( + sal_uInt16 nFlags, ScDocument* pClipDoc, sal_uInt16 nFunction, + bool bSkipEmpty, bool bTranspose, bool bAsLink, bool bAllowDialogs, + InsCellCmd eMoveMode, sal_uInt16 /*nContFlags*/, sal_uInt16 nUndoFlags) +{ + ScViewData& rViewData = *GetViewData(); + ScDocument* pDoc = rViewData.GetDocument(); + ScDocShell* pDocSh = rViewData.GetDocShell(); + ScMarkData aMark(rViewData.GetMarkData()); + const ScAddress& rCurPos = rViewData.GetCurPos(); + ScClipParam& rClipParam = pClipDoc->GetClipParam(); + SCCOL nColSize = rClipParam.getPasteColSize(); + SCROW nRowSize = rClipParam.getPasteRowSize(); + + if (bTranspose) + { + if (static_cast<SCROW>(rCurPos.Col()) + nRowSize-1 > static_cast<SCROW>(MAXCOL)) + { + ErrorMessage(STR_PASTE_FULL); + return false; + } + + ::std::auto_ptr<ScDocument> pTransClip(new ScDocument(SCDOCMODE_CLIP)); + pClipDoc->TransposeClip(pTransClip.get(), nFlags, bAsLink); + pClipDoc = pTransClip.release(); + SCCOL nTempColSize = nColSize; + nColSize = static_cast<SCCOL>(nRowSize); + nRowSize = static_cast<SCROW>(nTempColSize); + } + + if (!ValidCol(rCurPos.Col()+nColSize-1) || !ValidRow(rCurPos.Row()+nRowSize-1)) + { + ErrorMessage(STR_PASTE_FULL); + return false; + } + + // Determine the first and last selected sheet numbers. + SCTAB nTab1 = aMark.GetFirstSelected(); + SCTAB nTab2 = nTab1; + for (SCTAB i = nTab1+1; i <= MAXTAB; ++i) + if (aMark.GetTableSelect(i)) + nTab2 = i; + + ScDocShellModificator aModificator(*pDocSh); + + // For multi-selection paste, we don't support cell duplication for larger + // destination range. In case the destination is marked, we reset it to + // the clip size. + ScRange aMarkedRange(rCurPos.Col(), rCurPos.Row(), nTab1, + rCurPos.Col()+nColSize-1, rCurPos.Row()+nRowSize-1, nTab2); + + // Extend the marked range to account for filtered rows in the destination + // area. + if (ScViewUtil::HasFiltered(aMarkedRange, pDoc)) + { + if (!ScViewUtil::FitToUnfilteredRows(aMarkedRange, pDoc, nRowSize)) + return false; + } + + bool bAskIfNotEmpty = + bAllowDialogs && (nFlags & IDF_CONTENTS) && + nFunction == PASTE_NOFUNC && SC_MOD()->GetInputOptions().GetReplaceCellsWarn(); + + if (bAskIfNotEmpty) + { + if (!lcl_checkDestRangeForOverwrite(aMarkedRange, pDoc, aMark, rViewData.GetDialogParent())) + return false; + } + + aMark.SetMarkArea(aMarkedRange); + MarkRange(aMarkedRange); + + bool bInsertCells = (eMoveMode != INS_NONE); + if (bInsertCells) + { + if (!InsertCells(eMoveMode, pDoc->IsUndoEnabled(), true)) + return false; + } + + ::std::auto_ptr<ScDocument> pUndoDoc; + if (pDoc->IsUndoEnabled()) + { + pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO)); + pUndoDoc->InitUndoSelected(pDoc, aMark, false, false); + pDoc->CopyToDocument(aMarkedRange, nUndoFlags, false, pUndoDoc.get(), &aMark, true); + } + + ::std::auto_ptr<ScDocument> pMixDoc; + if ( bSkipEmpty || nFunction ) + { + if ( nFlags & IDF_CONTENTS ) + { + pMixDoc.reset(new ScDocument(SCDOCMODE_UNDO)); + pMixDoc->InitUndoSelected(pDoc, aMark, false, false); + pDoc->CopyToDocument(aMarkedRange, IDF_CONTENTS, false, pMixDoc.get(), &aMark, true); + } + } + + /* Make draw layer and start drawing undo. + - Needed before AdjustBlockHeight to track moved drawing objects. + - Needed before pDoc->CopyFromClip to track inserted note caption objects. + */ + if (nFlags & IDF_OBJECTS) + pDocSh->MakeDrawLayer(); + if (pDoc->IsUndoEnabled()) + pDoc->BeginDrawUndo(); + + CursorSwitcher aCursorSwitch(this); + sal_uInt16 nNoObjFlags = nFlags & ~IDF_OBJECTS; + pDoc->CopyMultiRangeFromClip(rCurPos, aMark, nNoObjFlags, pClipDoc, + true, bAsLink, false, bSkipEmpty); + + if (pMixDoc.get()) + pDoc->MixDocument(aMarkedRange, nFunction, bSkipEmpty, pMixDoc.get()); + + AdjustBlockHeight(); // update row heights before pasting objects + + if (nFlags & IDF_OBJECTS) + { + // Paste the drawing objects after the row heights have been updated. + pDoc->CopyMultiRangeFromClip(rCurPos, aMark, IDF_OBJECTS, pClipDoc, + true, false, false, true); + } + + pDocSh->PostPaint( + aMarkedRange.aStart.Col(), aMarkedRange.aStart.Row(), nTab1, + aMarkedRange.aEnd.Col(), aMarkedRange.aEnd.Row(), nTab1, PAINT_GRID); + + if (pDoc->IsUndoEnabled()) + { + ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager(); + String aUndo = ScGlobal::GetRscString( + pClipDoc->IsCutMode() ? STR_UNDO_CUT : STR_UNDO_COPY); + pUndoMgr->EnterListAction(aUndo, aUndo); + + ScUndoPasteOptions aOptions; // store options for repeat + aOptions.nFunction = nFunction; + aOptions.bSkipEmpty = bSkipEmpty; + aOptions.bTranspose = bTranspose; + aOptions.bAsLink = bAsLink; + aOptions.eMoveMode = eMoveMode; + + ScUndoPaste* pUndo = new ScUndoPaste(pDocSh, + aMarkedRange.aStart.Col(), + aMarkedRange.aStart.Row(), + aMarkedRange.aStart.Tab(), + aMarkedRange.aEnd.Col(), + aMarkedRange.aEnd.Row(), + aMarkedRange.aEnd.Tab(), + aMark, pUndoDoc.release(), NULL, nFlags|nUndoFlags, NULL, NULL, NULL, NULL, false, &aOptions); + + if (bInsertCells) + pUndoMgr->AddUndoAction(new ScUndoWrapper(pUndo), true); + else + pUndoMgr->AddUndoAction(pUndo, false); + + pUndoMgr->LeaveListAction(); + } + aModificator.SetDocumentModified(); + PostPasteFromClip(aMarkedRange, aMark); + return true; +} + +void ScViewFunc::PostPasteFromClip(const ScRange& rPasteRange, const ScMarkData& rMark) +{ + ScViewData* pViewData = GetViewData(); + ScDocShell* pDocSh = pViewData->GetDocShell(); + ScDocument* pDoc = pViewData->GetDocument(); + pDocSh->UpdateOle(pViewData); + + SelectionChanged(); + + // #i97876# Spreadsheet data changes are not notified + ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() ); + if ( pModelObj && pModelObj->HasChangesListeners() ) + { + ScRangeList aChangeRanges; + SCTAB nTabCount = pDoc->GetTableCount(); + for ( SCTAB i = 0; i < nTabCount; ++i ) + { + if ( rMark.GetTableSelect( i ) ) + { + ScRange aChangeRange(rPasteRange); + aChangeRange.aStart.SetTab( i ); + aChangeRange.aEnd.SetTab( i ); + aChangeRanges.Append( aChangeRange ); + } + } + pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges ); + } +} + + +//---------------------------------------------------------------------------- +// D R A G A N D D R O P +// +// innerhalb des Dokuments + +sal_Bool ScViewFunc::MoveBlockTo( const ScRange& rSource, const ScAddress& rDestPos, + sal_Bool bCut, sal_Bool bRecord, sal_Bool bPaint, sal_Bool bApi ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + HideAllCursors(); // wegen zusammengefassten + + sal_Bool bSuccess = sal_True; + SCTAB nDestTab = rDestPos.Tab(); + const ScMarkData& rMark = GetViewData()->GetMarkData(); + if ( rSource.aStart.Tab() == nDestTab && rSource.aEnd.Tab() == nDestTab && rMark.GetSelectCount() > 1 ) + { + // moving within one table and several tables selected -> apply to all selected tables + + if ( bRecord ) + { + String aUndo = ScGlobal::GetRscString( bCut ? STR_UNDO_MOVE : STR_UNDO_COPY ); + pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo ); + } + + // collect ranges of consecutive selected tables + + ScRange aLocalSource = rSource; + ScAddress aLocalDest = rDestPos; + SCTAB nTabCount = pDocSh->GetDocument()->GetTableCount(); + SCTAB nStartTab = 0; + while ( nStartTab < nTabCount && bSuccess ) + { + while ( nStartTab < nTabCount && !rMark.GetTableSelect(nStartTab) ) + ++nStartTab; + if ( nStartTab < nTabCount ) + { + SCTAB nEndTab = nStartTab; + while ( nEndTab+1 < nTabCount && rMark.GetTableSelect(nEndTab+1) ) + ++nEndTab; + + aLocalSource.aStart.SetTab( nStartTab ); + aLocalSource.aEnd.SetTab( nEndTab ); + aLocalDest.SetTab( nStartTab ); + + bSuccess = pDocSh->GetDocFunc().MoveBlock( + aLocalSource, aLocalDest, bCut, bRecord, bPaint, bApi ); + + nStartTab = nEndTab + 1; + } + } + + if ( bRecord ) + pDocSh->GetUndoManager()->LeaveListAction(); + } + else + { + // move the block as specified + bSuccess = pDocSh->GetDocFunc().MoveBlock( + rSource, rDestPos, bCut, bRecord, bPaint, bApi ); + } + + ShowAllCursors(); + if (bSuccess) + { + // Zielbereich markieren + ScAddress aDestEnd( + rDestPos.Col() + rSource.aEnd.Col() - rSource.aStart.Col(), + rDestPos.Row() + rSource.aEnd.Row() - rSource.aStart.Row(), + nDestTab ); + + sal_Bool bIncludeFiltered = bCut; + if ( !bIncludeFiltered ) + { + // find number of non-filtered rows + SCROW nPastedCount = pDocSh->GetDocument()->CountNonFilteredRows( + rSource.aStart.Row(), rSource.aEnd.Row(), rSource.aStart.Tab()); + + if ( nPastedCount == 0 ) + nPastedCount = 1; + aDestEnd.SetRow( rDestPos.Row() + nPastedCount - 1 ); + } + + MarkRange( ScRange( rDestPos, aDestEnd ), sal_False ); //! sal_False ??? + + pDocSh->UpdateOle(GetViewData()); + SelectionChanged(); + } + return bSuccess; +} + +// Link innerhalb des Dokuments + +sal_Bool ScViewFunc::LinkBlock( const ScRange& rSource, const ScAddress& rDestPos, sal_Bool bApi ) +{ + // Test auf Ueberlappung + + if ( rSource.aStart.Tab() == rDestPos.Tab() ) + { + SCCOL nDestEndCol = rDestPos.Col() + ( rSource.aEnd.Col() - rSource.aStart.Col() ); + SCROW nDestEndRow = rDestPos.Row() + ( rSource.aEnd.Row() - rSource.aStart.Row() ); + + if ( rSource.aStart.Col() <= nDestEndCol && rDestPos.Col() <= rSource.aEnd.Col() && + rSource.aStart.Row() <= nDestEndRow && rDestPos.Row() <= rSource.aEnd.Row() ) + { + if (!bApi) + ErrorMessage( STR_ERR_LINKOVERLAP ); + return sal_False; + } + } + + // Ausfuehren per Paste + + ScDocument* pDoc = GetViewData()->GetDocument(); + ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP ); + pDoc->CopyTabToClip( rSource.aStart.Col(), rSource.aStart.Row(), + rSource.aEnd.Col(), rSource.aEnd.Row(), + rSource.aStart.Tab(), pClipDoc ); + + // Zielbereich markieren (Cursor setzen, keine Markierung) + + if ( GetViewData()->GetTabNo() != rDestPos.Tab() ) + SetTabNo( rDestPos.Tab() ); + + MoveCursorAbs( rDestPos.Col(), rDestPos.Row(), SC_FOLLOW_NONE, sal_False, sal_False ); + + // Paste + + PasteFromClip( IDF_ALL, pClipDoc, PASTE_NOFUNC, sal_False, sal_False, sal_True ); // als Link + + delete pClipDoc; + + return sal_True; +} + + + + diff --git a/sc/source/ui/view/viewfun4.cxx b/sc/source/ui/view/viewfun4.cxx new file mode 100644 index 000000000000..c3f58e7d9b74 --- /dev/null +++ b/sc/source/ui/view/viewfun4.cxx @@ -0,0 +1,848 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include "scitems.hxx" +#include <editeng/eeitem.hxx> + +#include <editeng/editobj.hxx> +#include <editeng/editstat.hxx> +#include <editeng/editview.hxx> +#include <editeng/flditem.hxx> +#include <svx/hlnkitem.hxx> +#include <editeng/langitem.hxx> +#include <svx/svxerr.hxx> +#include <editeng/unolingu.hxx> + +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/fcontnr.hxx> +#include <svtools/langtab.hxx> +#include <svtools/filter.hxx> +#include <svl/stritem.hxx> +#include <svtools/transfer.hxx> +#include <svl/urlbmk.hxx> +#include <vcl/msgbox.hxx> +#include <avmedia/mediawindow.hxx> + +#include <comphelper/storagehelper.hxx> +#include <comphelper/processfactory.hxx> + +#include "viewfunc.hxx" +#include "docsh.hxx" +#include "docsh.hxx" +#include "document.hxx" +#include "docpool.hxx" +#include "globstr.hrc" +#include "global.hxx" +#include "undoblk.hxx" +#include "undocell.hxx" +#include "cell.hxx" +#include "scmod.hxx" +#include "spelleng.hxx" +#include "patattr.hxx" +#include "sc.hrc" +#include "tabvwsh.hxx" +#include "impex.hxx" +#include "editutil.hxx" +#include "editable.hxx" +#include "dociter.hxx" +#include "reffind.hxx" +#include "compiler.hxx" + +using namespace com::sun::star; + +// STATIC DATA ----------------------------------------------------------- + +sal_Bool bPasteIsDrop = sal_False; + +//================================================================== + +void ScViewFunc::PasteRTF( SCCOL nStartCol, SCROW nStartRow, + const ::com::sun::star::uno::Reference< + ::com::sun::star::datatransfer::XTransferable >& rxTransferable ) +{ + TransferableDataHelper aDataHelper( rxTransferable ); + if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EDITENGINE ) ) + { + HideAllCursors(); + + ScDocument* pUndoDoc = NULL; + + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = GetViewData()->GetTabNo(); + const sal_Bool bRecord (pDoc->IsUndoEnabled()); + + const ScPatternAttr* pPattern = pDoc->GetPattern( nStartCol, nStartRow, nTab ); + ScTabEditEngine* pEngine = new ScTabEditEngine( *pPattern, pDoc->GetEnginePool() ); + pEngine->EnableUndo( sal_False ); + + Window* pActWin = GetActiveWin(); + if (pActWin) + { + pEngine->SetPaperSize(Size(100000,100000)); + Window aWin( pActWin ); + EditView aEditView( pEngine, &aWin ); + aEditView.SetOutputArea(Rectangle(0,0,100000,100000)); + + // same method now for clipboard or drag&drop + // mba: clipboard always must contain absolute URLs (could be from alien source) + aEditView.InsertText( rxTransferable, String(), sal_True ); + } + + sal_uLong nParCnt = pEngine->GetParagraphCount(); + if (nParCnt) + { + SCROW nEndRow = nStartRow + static_cast<SCROW>(nParCnt) - 1; + if (nEndRow > MAXROW) + nEndRow = MAXROW; + + if (bRecord) + { + pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + pUndoDoc->InitUndo( pDoc, nTab, nTab ); + pDoc->CopyToDocument( nStartCol,nStartRow,nTab, nStartCol,nEndRow,nTab, IDF_ALL, sal_False, pUndoDoc ); + } + + SCROW nRow = nStartRow; + for( sal_uInt16 n = 0; n < nParCnt; n++ ) + { + EditTextObject* pObject = pEngine->CreateTextObject( n ); + EnterData( nStartCol, nRow, nTab, pObject, sal_False, sal_True ); + // kein Undo, auf einfache Strings testen + delete pObject; + if( ++nRow > MAXROW ) + break; + } + + if (bRecord) + { + ScDocument* pRedoDoc = new ScDocument( SCDOCMODE_UNDO ); + pRedoDoc->InitUndo( pDoc, nTab, nTab ); + pDoc->CopyToDocument( nStartCol,nStartRow,nTab, nStartCol,nEndRow,nTab, IDF_ALL|IDF_NOCAPTIONS, sal_False, pRedoDoc ); + + ScMarkData aDestMark; + aDestMark.SelectOneTable( nTab ); + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoPaste( pDocSh, nStartCol,nStartRow,nTab, nStartCol,nEndRow,nTab, + aDestMark, + pUndoDoc, pRedoDoc, IDF_ALL, NULL,NULL,NULL,NULL ) ); + } + } + + delete pEngine; + + ShowAllCursors(); + } + else + { + HideAllCursors(); + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScImportExport aImpEx( pDocSh->GetDocument(), + ScAddress( nStartCol, nStartRow, GetViewData()->GetTabNo() ) ); + + ::rtl::OUString aStr; + SotStorageStreamRef xStream; + if ( aDataHelper.GetSotStorageStream( SOT_FORMAT_RTF, xStream ) && xStream.Is() ) + // mba: clipboard always must contain absolute URLs (could be from alien source) + aImpEx.ImportStream( *xStream, String(), SOT_FORMAT_RTF ); + else if ( aDataHelper.GetString( SOT_FORMAT_RTF, aStr ) ) + aImpEx.ImportString( aStr, SOT_FORMAT_RTF ); + + AdjustRowHeight( nStartRow, aImpEx.GetRange().aEnd.Row() ); + pDocSh->UpdateOle(GetViewData()); + ShowAllCursors(); + } +} +void ScViewFunc::DoRefConversion( sal_Bool bRecord ) +{ + ScDocument* pDoc = GetViewData()->GetDocument(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + SCTAB nTabCount = pDoc->GetTableCount(); + if (bRecord && !pDoc->IsUndoEnabled()) + bRecord = sal_False; + + ScRange aMarkRange; + rMark.MarkToSimple(); + sal_Bool bMulti = rMark.IsMultiMarked(); + if (bMulti) + rMark.GetMultiMarkArea( aMarkRange ); + else if (rMark.IsMarked()) + rMark.GetMarkArea( aMarkRange ); + else + { + aMarkRange = ScRange( GetViewData()->GetCurX(), + GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); + } + ScEditableTester aTester( pDoc, aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), + aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(),rMark ); + if (!aTester.IsEditable()) + { + ErrorMessage(aTester.GetMessageId()); + return; + } + + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + sal_Bool bOk = sal_False; + + ScDocument* pUndoDoc = NULL; + if (bRecord) + { + pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + SCTAB nTab = aMarkRange.aStart.Tab(); + pUndoDoc->InitUndo( pDoc, nTab, nTab ); + + if ( rMark.GetSelectCount() > 1 ) + { + for (SCTAB i=0; i<nTabCount; i++) + if ( rMark.GetTableSelect(i) && i != nTab ) + pUndoDoc->AddUndoTab( i, i ); + } + ScRange aCopyRange = aMarkRange; + aCopyRange.aStart.SetTab(0); + aCopyRange.aEnd.SetTab(nTabCount-1); + pDoc->CopyToDocument( aCopyRange, IDF_ALL, bMulti, pUndoDoc, &rMark ); + } + + ScRangeListRef xRanges; + GetViewData()->GetMultiArea( xRanges ); + sal_uLong nCount = xRanges->Count(); + + for (SCTAB i=0; i<nTabCount; i++) + { + if (rMark.GetTableSelect(i)) + { + for (sal_uLong j=0; j<nCount; j++) + { + ScRange aRange = *xRanges->GetObject(j); + aRange.aStart.SetTab(i); + aRange.aEnd.SetTab(i); + ScCellIterator aIter( pDoc, aRange ); + ScBaseCell* pCell = aIter.GetFirst(); + while ( pCell ) + { + if (pCell->GetCellType() == CELLTYPE_FORMULA) + { + String aOld; + ((ScFormulaCell*)pCell)->GetFormula(aOld); + xub_StrLen nLen = aOld.Len(); + ScRefFinder aFinder( aOld, pDoc ); + aFinder.ToggleRel( 0, nLen ); + if (aFinder.GetFound()) + { + ScAddress aPos = ((ScFormulaCell*)pCell)->aPos; + String aNew = aFinder.GetText(); + ScCompiler aComp( pDoc, aPos); + aComp.SetGrammar(pDoc->GetGrammar()); + ScTokenArray* pArr = aComp.CompileString( aNew ); + ScFormulaCell* pNewCell = new ScFormulaCell( pDoc, aPos, + pArr,formula::FormulaGrammar::GRAM_DEFAULT, MM_NONE ); + pDoc->PutCell( aPos, pNewCell ); + bOk = sal_True; + } + } + pCell = aIter.GetNext(); + } + } + } + } + if (bRecord) + { + ScDocument* pRedoDoc = new ScDocument( SCDOCMODE_UNDO ); + SCTAB nTab = aMarkRange.aStart.Tab(); + pRedoDoc->InitUndo( pDoc, nTab, nTab ); + + if ( rMark.GetSelectCount() > 1 ) + { + for (SCTAB i=0; i<nTabCount; i++) + if ( rMark.GetTableSelect(i) && i != nTab ) + pRedoDoc->AddUndoTab( i, i ); + } + ScRange aCopyRange = aMarkRange; + aCopyRange.aStart.SetTab(0); + aCopyRange.aEnd.SetTab(nTabCount-1); + pDoc->CopyToDocument( aCopyRange, IDF_ALL, bMulti, pRedoDoc, &rMark ); + + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoRefConversion( pDocSh, + aMarkRange, rMark, pUndoDoc, pRedoDoc, bMulti, IDF_ALL) ); + } + + pDocSh->PostPaint( aMarkRange, PAINT_GRID ); + pDocSh->UpdateOle(GetViewData()); + pDocSh->SetDocumentModified(); + CellContentChanged(); + + if (!bOk) + ErrorMessage(STR_ERR_NOREF); +} +// Thesaurus - Undo ok +void ScViewFunc::DoThesaurus( sal_Bool bRecord ) +{ + SCCOL nCol; + SCROW nRow; + SCTAB nTab; + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + ScSplitPos eWhich = GetViewData()->GetActivePart(); + CellType eCellType; + EESpellState eState; + String sOldText, sNewString; + EditTextObject* pOldTObj = NULL; + const EditTextObject* pTObject = NULL; + ScBaseCell* pCell = NULL; + EditView* pEditView = NULL; + ESelection* pEditSel = NULL; + ScEditEngineDefaulter* pThesaurusEngine; + sal_Bool bIsEditMode = GetViewData()->HasEditView(eWhich); + if (bRecord && !pDoc->IsUndoEnabled()) + bRecord = sal_False; + if (bIsEditMode) // Edit-Mode aktiv + { + GetViewData()->GetEditView(eWhich, pEditView, nCol, nRow); + pEditSel = new ESelection(pEditView->GetSelection()); + SC_MOD()->InputEnterHandler(); + GetViewData()->GetBindings().Update(); // sonst kommt der Sfx durcheinander... + } + else + { + nCol = GetViewData()->GetCurX(); + nRow = GetViewData()->GetCurY(); + } + nTab = GetViewData()->GetTabNo(); + + ScEditableTester aTester( pDoc, nCol, nRow, nCol, nRow, rMark ); + if (!aTester.IsEditable()) + { + ErrorMessage(aTester.GetMessageId()); + delete pEditSel; + return; + } + pDoc->GetCellType(nCol, nRow, nTab, eCellType); + if (eCellType != CELLTYPE_STRING && eCellType != CELLTYPE_EDIT) + { + ErrorMessage(STR_THESAURUS_NO_STRING); + return; + } + + com::sun::star::uno::Reference<com::sun::star::linguistic2::XSpellChecker1> + xSpeller = LinguMgr::GetSpellChecker(); + //! if (...) // thesaurus not available + //! { + //! ErrorMessage(STR_EXPORT_ASCII_WARNING); + //! delete pEditSel; + //! return; + //! } + + pThesaurusEngine = new ScEditEngineDefaulter( pDoc->GetEnginePool() ); + pThesaurusEngine->SetEditTextObjectPool( pDoc->GetEditPool() ); + pThesaurusEngine->SetRefDevice(GetViewData()->GetActiveWin()); + pThesaurusEngine->SetSpeller(xSpeller); + MakeEditView(pThesaurusEngine, nCol, nRow ); + const ScPatternAttr* pPattern = NULL; + SfxItemSet* pEditDefaults = new SfxItemSet(pThesaurusEngine->GetEmptyItemSet()); + pPattern = pDoc->GetPattern(nCol, nRow, nTab); + if (pPattern ) + { + pPattern->FillEditItemSet( pEditDefaults ); + pThesaurusEngine->SetDefaults( *pEditDefaults ); + } + + if (eCellType == CELLTYPE_STRING) + { + pDoc->GetString(nCol, nRow, nTab, sOldText); + pThesaurusEngine->SetText(sOldText); + } + else if (eCellType == CELLTYPE_EDIT) + { + pDoc->GetCell(nCol, nRow, nTab, pCell); + if (pCell) + { + ((ScEditCell*) pCell)->GetData(pTObject); + if (pTObject) + { + pOldTObj = pTObject->Clone(); + pThesaurusEngine->SetText(*pTObject); + } + } + } + else + { + DBG_ERROR("DoThesaurus: Keine String oder Editzelle"); + } + pEditView = GetViewData()->GetEditView(GetViewData()->GetActivePart());; + if (pEditSel) + pEditView->SetSelection(*pEditSel); + else + pEditView->SetSelection(ESelection(0,0,0,0)); + + pThesaurusEngine->ClearModifyFlag(); + + // language is now in EditEngine attributes -> no longer passed to StartThesaurus + + eState = pEditView->StartThesaurus(); + DBG_ASSERT(eState != EE_SPELL_NOSPELLER, "No SpellChecker"); + + if (eState == EE_SPELL_ERRORFOUND) // sollte spaeter durch Wrapper geschehen! + { + LanguageType eLnge = ScViewUtil::GetEffLanguage( pDoc, ScAddress( nCol, nRow, nTab ) ); + SvtLanguageTable aLangTab; + String aErr = aLangTab.GetString(eLnge); + aErr += ScGlobal::GetRscString( STR_SPELLING_NO_LANG ); + InfoBox aBox( GetViewData()->GetDialogParent(), aErr ); + aBox.Execute(); + } + if (pThesaurusEngine->IsModified()) + { + EditTextObject* pNewTObj = NULL; + if (pCell && pTObject) + { + pNewTObj = pThesaurusEngine->CreateTextObject(); + pCell = new ScEditCell( pNewTObj, pDoc, + pThesaurusEngine->GetEditTextObjectPool() ); + pDoc->PutCell( nCol, nRow, nTab, pCell ); + } + else + { + sNewString = pThesaurusEngine->GetText(); + pDoc->SetString(nCol, nRow, nTab, sNewString); + } +// erack! it's broadcasted +// pDoc->SetDirty(); + pDocSh->SetDocumentModified(); + if (bRecord) + { + GetViewData()->GetDocShell()->GetUndoManager()->AddUndoAction( + new ScUndoThesaurus( GetViewData()->GetDocShell(), + nCol, nRow, nTab, + sOldText, pOldTObj, sNewString, pNewTObj)); + } + delete pNewTObj; + } + KillEditView(sal_True); + delete pEditDefaults; + delete pThesaurusEngine; + delete pOldTObj; + delete pEditSel; + pDocSh->PostPaintGridAll(); +} + +//UNUSED2008-05 // Spelling Checker - Undo ok +//UNUSED2008-05 void ScViewFunc::DoSpellingChecker( sal_Bool bRecord ) +//UNUSED2008-05 { +//UNUSED2008-05 DoSheetConversion( ScConversionParam( SC_CONVERSION_SPELLCHECK ), bRecord ); +//UNUSED2008-05 } + +void ScViewFunc::DoHangulHanjaConversion( sal_Bool bRecord ) +{ + ScConversionParam aConvParam( SC_CONVERSION_HANGULHANJA, LANGUAGE_KOREAN, 0, true ); + DoSheetConversion( aConvParam, bRecord ); +} + +void ScViewFunc::DoSheetConversion( const ScConversionParam& rConvParam, sal_Bool bRecord ) +{ + SCCOL nCol; + SCROW nRow; + SCTAB nTab; + ScViewData& rViewData = *GetViewData(); + ScDocShell* pDocSh = rViewData.GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + ScMarkData& rMark = rViewData.GetMarkData(); + ScSplitPos eWhich = rViewData.GetActivePart(); + EditView* pEditView = NULL; + ESelection* pEditSel = NULL; + sal_Bool bIsEditMode = rViewData.HasEditView(eWhich); + if (bRecord && !pDoc->IsUndoEnabled()) + bRecord = sal_False; + if (bIsEditMode) // Edit-Mode aktiv + { + rViewData.GetEditView(eWhich, pEditView, nCol, nRow); + pEditSel = new ESelection(pEditView->GetSelection()); + SC_MOD()->InputEnterHandler(); + } + else + { + nCol = rViewData.GetCurX(); + nRow = rViewData.GetCurY(); + + AlignToCursor( nCol, nRow, SC_FOLLOW_JUMP); + } + nTab = rViewData.GetTabNo(); + + rMark.MarkToMulti(); + sal_Bool bMarked = rMark.IsMultiMarked(); + if (bMarked) + { + ScEditableTester aTester( pDoc, rMark ); + if (!aTester.IsEditable()) + { + ErrorMessage(aTester.GetMessageId()); + delete pEditSel; + return; + } + } + + ScDocument* pUndoDoc = NULL; + ScDocument* pRedoDoc = NULL; + if (bRecord) + { + pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + pUndoDoc->InitUndo( pDoc, nTab, nTab ); + pRedoDoc = new ScDocument( SCDOCMODE_UNDO ); + pRedoDoc->InitUndo( pDoc, nTab, nTab ); + + if ( rMark.GetSelectCount() > 1 ) + { + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB i=0; i<nTabCount; i++) + if ( rMark.GetTableSelect(i) && i != nTab ) + { + pUndoDoc->AddUndoTab( i, i ); + pRedoDoc->AddUndoTab( i, i ); + } + } + } + + // ab hier kein return mehr + + sal_Bool bOldDis = pDoc->IsIdleDisabled(); + pDoc->DisableIdle( sal_True ); // #42726# stop online spelling + + // *** create and init the edit engine *** -------------------------------- + + ScConversionEngineBase* pEngine = NULL; + switch( rConvParam.GetType() ) + { + case SC_CONVERSION_SPELLCHECK: + pEngine = new ScSpellingEngine( + pDoc->GetEnginePool(), rViewData, pUndoDoc, pRedoDoc, LinguMgr::GetSpellChecker() ); + break; + case SC_CONVERSION_HANGULHANJA: + case SC_CONVERSION_CHINESE_TRANSL: + pEngine = new ScTextConversionEngine( + pDoc->GetEnginePool(), rViewData, rConvParam, pUndoDoc, pRedoDoc ); + break; + default: + DBG_ERRORFILE( "ScViewFunc::DoSheetConversion - unknown conversion type" ); + } + + MakeEditView( pEngine, nCol, nRow ); + pEngine->SetRefDevice( rViewData.GetActiveWin() ); + // dummy Zelle simulieren: + pEditView = rViewData.GetEditView( rViewData.GetActivePart() ); + rViewData.SetSpellingView( pEditView ); + Rectangle aRect( Point( 0, 0 ), Point( 0, 0 ) ); + pEditView->SetOutputArea( aRect ); + pEngine->SetControlWord( EE_CNTRL_USECHARATTRIBS ); + pEngine->EnableUndo( sal_False ); + pEngine->SetPaperSize( aRect.GetSize() ); + pEngine->SetText( EMPTY_STRING ); + + // *** do the conversion *** ---------------------------------------------- + + pEngine->ClearModifyFlag(); + pEngine->ConvertAll( *pEditView ); + + // *** undo/redo *** ------------------------------------------------------ + + if( pEngine->IsAnyModified() ) + { + if (bRecord) + { + SCCOL nNewCol = rViewData.GetCurX(); + SCROW nNewRow = rViewData.GetCurY(); + rViewData.GetDocShell()->GetUndoManager()->AddUndoAction( + new ScUndoConversion( + pDocSh, rMark, + nCol, nRow, nTab, pUndoDoc, + nNewCol, nNewRow, nTab, pRedoDoc, rConvParam ) ); + } + pDoc->SetDirty(); + pDocSh->SetDocumentModified(); + } + else + { + delete pUndoDoc; + delete pRedoDoc; + } + + // *** final cleanup *** -------------------------------------------------- + + rViewData.SetSpellingView( NULL ); + KillEditView(sal_True); + delete pEngine; + delete pEditSel; + pDocSh->PostPaintGridAll(); + rViewData.GetViewShell()->UpdateInputHandler(); + pDoc->DisableIdle(bOldDis); +} + + +//UNUSED2008-05 IMPL_LINK_INLINE_START( ScViewFunc, SpellError, void *, nLang ) +//UNUSED2008-05 { +//UNUSED2008-05 SvtLanguageTable aLangTab; +//UNUSED2008-05 String aErr = aLangTab.GetString((LanguageType) (sal_uLong) nLang); +//UNUSED2008-05 ErrorHandler::HandleError(*new StringErrorInfo( +//UNUSED2008-05 ERRCODE_SVX_LINGU_LANGUAGENOTEXISTS, aErr) ); +//UNUSED2008-05 +//UNUSED2008-05 return 0; +//UNUSED2008-05 } +//UNUSED2008-05 IMPL_LINK_INLINE_END( ScViewFunc, SpellError, void *, nLang ) + +// Pasten von FORMAT_FILE-Items +// wird nicht direkt aus Drop aufgerufen, sondern asynchron -> Dialoge sind erlaubt + +sal_Bool ScViewFunc::PasteFile( const Point& rPos, const String& rFile, sal_Bool bLink ) +{ + INetURLObject aURL; + aURL.SetSmartURL( rFile ); + String aStrURL = aURL.GetMainURL( INetURLObject::NO_DECODE ); + + // is it a media URL? + if( ::avmedia::MediaWindow::isMediaURL( aStrURL ) ) + { + const SfxStringItem aMediaURLItem( SID_INSERT_AVMEDIA, aStrURL ); + return sal_Bool( 0 != GetViewData()->GetDispatcher().Execute( + SID_INSERT_AVMEDIA, SFX_CALLMODE_SYNCHRON, + &aMediaURLItem, 0L ) ); + } + + if (!bLink) // bei bLink nur Grafik oder URL + { + // 1. Kann ich die Datei oeffnen? + const SfxFilter* pFlt = NULL; + + // nur nach eigenen Filtern suchen, ohne Auswahlbox (wie in ScDocumentLoader) + SfxFilterMatcher aMatcher( ScDocShell::Factory().GetFilterContainer()->GetName() ); + SfxMedium aSfxMedium( aStrURL, (STREAM_READ | STREAM_SHARE_DENYNONE), sal_False ); + // #i73992# GuessFilter no longer calls UseInteractionHandler. + // This is UI, so it can be called here. + aSfxMedium.UseInteractionHandler(sal_True); + ErrCode nErr = aMatcher.GuessFilter( aSfxMedium, &pFlt ); + + if ( pFlt && !nErr ) + { + // Code aus dem SFX geklaut! + SfxDispatcher &rDispatcher = GetViewData()->GetDispatcher(); + SfxStringItem aFileNameItem( SID_FILE_NAME, aStrURL ); + SfxStringItem aFilterItem( SID_FILTER_NAME, pFlt->GetName() ); + // #i69524# add target, as in SfxApplication when the Open dialog is used + SfxStringItem aTargetItem( SID_TARGETNAME, String::CreateFromAscii("_default") ); + + // Asynchron oeffnen, kann naemlich auch aus D&D heraus passieren + // und das bekommt dem MAC nicht so gut ... + return sal_Bool( 0 != rDispatcher.Execute( SID_OPENDOC, + SFX_CALLMODE_ASYNCHRON, &aFileNameItem, &aFilterItem, &aTargetItem, 0L) ); + } + } + + // 2. Kann die Datei ueber die Grafik-Filter eingefuegt werden? + // (als Link, weil Gallery das so anbietet) + + sal_uInt16 nFilterFormat; + Graphic aGraphic; + GraphicFilter* pGraphicFilter = GraphicFilter::GetGraphicFilter(); + +// GraphicProgress aGraphicProgress(&aGraphicFilter); + + if (!pGraphicFilter->ImportGraphic(aGraphic, aURL, + GRFILTER_FORMAT_DONTKNOW, &nFilterFormat )) + { + if ( bLink ) + { + String aFltName = pGraphicFilter->GetImportFormatName(nFilterFormat); + return PasteGraphic( rPos, aGraphic, aStrURL, aFltName ); + } + else + { + // #i76709# if bLink isn't set, pass empty URL/filter, so a non-linked image is inserted + return PasteGraphic( rPos, aGraphic, EMPTY_STRING, EMPTY_STRING ); + } + } + + if (bLink) // bei bLink alles, was nicht Grafik ist, als URL + { + Rectangle aRect( rPos, Size(0,0) ); + ScRange aRange = GetViewData()->GetDocument()-> + GetRange( GetViewData()->GetTabNo(), aRect ); + SCCOL nPosX = aRange.aStart.Col(); + SCROW nPosY = aRange.aStart.Row(); + + InsertBookmark( aStrURL, aStrURL, nPosX, nPosY ); + return sal_True; + } + else + { + // 3. Kann die Datei als OLE eingefuegt werden? + // auch nicht-Storages, z.B. Sounds (#38282#) + uno::Reference < embed::XStorage > xStorage = comphelper::OStorageHelper::GetTemporaryStorage(); + + //TODO/LATER: what about "bLink"? + + uno::Sequence < beans::PropertyValue > aMedium(1); + aMedium[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) ); + aMedium[0].Value <<= ::rtl::OUString( aStrURL ); + + comphelper::EmbeddedObjectContainer aCnt( xStorage ); + ::rtl::OUString aName; + uno::Reference < embed::XEmbeddedObject > xObj = aCnt.InsertEmbeddedObject( aMedium, aName ); + if( xObj.is() ) + return PasteObject( rPos, xObj ); + + // #105851# If an OLE object can't be created, insert a URL button + + GetViewData()->GetViewShell()->InsertURLButton( aStrURL, aStrURL, EMPTY_STRING, &rPos ); + return sal_True; + } +} + +sal_Bool ScViewFunc::PasteBookmark( sal_uLong nFormatId, + const ::com::sun::star::uno::Reference< + ::com::sun::star::datatransfer::XTransferable >& rxTransferable, + SCCOL nPosX, SCROW nPosY ) +{ + INetBookmark aBookmark; + TransferableDataHelper aDataHelper( rxTransferable ); + if ( !aDataHelper.GetINetBookmark( nFormatId, aBookmark ) ) + return sal_False; + + InsertBookmark( aBookmark.GetDescription(), aBookmark.GetURL(), nPosX, nPosY ); + return sal_True; +} + +void ScViewFunc::InsertBookmark( const String& rDescription, const String& rURL, + SCCOL nPosX, SCROW nPosY, const String* pTarget, + sal_Bool bTryReplace ) +{ + ScViewData* pViewData = GetViewData(); + if ( pViewData->HasEditView( pViewData->GetActivePart() ) && + nPosX >= pViewData->GetEditStartCol() && nPosX <= pViewData->GetEditEndCol() && + nPosY >= pViewData->GetEditStartRow() && nPosY <= pViewData->GetEditEndRow() ) + { + // in die gerade editierte Zelle einfuegen + + String aTargetFrame; + if (pTarget) + aTargetFrame = *pTarget; + pViewData->GetViewShell()->InsertURLField( rDescription, rURL, aTargetFrame ); + return; + } + + // in nicht editierte Zelle einfuegen + + ScDocument* pDoc = GetViewData()->GetDocument(); + SCTAB nTab = GetViewData()->GetTabNo(); + ScAddress aCellPos( nPosX, nPosY, nTab ); + ScBaseCell* pCell = pDoc->GetCell( aCellPos ); + EditEngine aEngine( pDoc->GetEnginePool() ); + if (pCell) + { + if (pCell->GetCellType() == CELLTYPE_EDIT) + { + const EditTextObject* pOld = ((ScEditCell*)pCell)->GetData(); + if (pOld) + aEngine.SetText(*pOld); + } + else + { + String aOld; + pDoc->GetInputString( nPosX, nPosY, nTab, aOld ); + if (aOld.Len()) + aEngine.SetText(aOld); + } + } + + sal_uInt16 nPara = aEngine.GetParagraphCount(); + if (nPara) + --nPara; + xub_StrLen nTxtLen = aEngine.GetTextLen(nPara); + ESelection aInsSel( nPara, nTxtLen, nPara, nTxtLen ); + + if ( bTryReplace && HasBookmarkAtCursor( NULL ) ) + { + // if called from hyperlink slot and cell contains only a URL, + // replace old URL with new one + + aInsSel = ESelection( 0, 0, 0, 1 ); // replace first character (field) + } + + SvxURLField aField( rURL, rDescription, SVXURLFORMAT_APPDEFAULT ); + if (pTarget) + aField.SetTargetFrame(*pTarget); + aEngine.QuickInsertField( SvxFieldItem( aField, EE_FEATURE_FIELD ), aInsSel ); + + EditTextObject* pData = aEngine.CreateTextObject(); + EnterData( nPosX, nPosY, nTab, pData ); + delete pData; +} + +sal_Bool ScViewFunc::HasBookmarkAtCursor( SvxHyperlinkItem* pContent ) +{ + ScAddress aPos( GetViewData()->GetCurX(), GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); + ScDocument* pDoc = GetViewData()->GetDocShell()->GetDocument(); + + ScBaseCell* pCell = pDoc->GetCell( aPos ); + if ( pCell && pCell->GetCellType() == CELLTYPE_EDIT ) + { + const EditTextObject* pData = ((ScEditCell*)pCell)->GetData(); + if (pData) + { + sal_Bool bField = pData->IsFieldObject(); + if (bField) + { + const SvxFieldItem* pFieldItem = pData->GetField(); + if (pFieldItem) + { + const SvxFieldData* pField = pFieldItem->GetField(); + if ( pField && pField->ISA(SvxURLField) ) + { + if (pContent) + { + const SvxURLField* pURLField = (const SvxURLField*)pField; + pContent->SetName( pURLField->GetRepresentation() ); + pContent->SetURL( pURLField->GetURL() ); + pContent->SetTargetFrame( pURLField->GetTargetFrame() ); + } + return sal_True; + } + } + } + } + } + return sal_False; +} + + diff --git a/sc/source/ui/view/viewfun5.cxx b/sc/source/ui/view/viewfun5.cxx new file mode 100644 index 000000000000..205a0532eb3a --- /dev/null +++ b/sc/source/ui/view/viewfun5.cxx @@ -0,0 +1,749 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" +#include <com/sun/star/embed/XEmbedObjectClipboardCreator.hpp> +#include <com/sun/star/embed/Aspects.hpp> + + +#include <svx/unomodel.hxx> +#include <unotools/streamwrap.hxx> + +//------------------------------------------------------------------ + +#include <svx/dbexch.hrc> +#include <svx/fmmodel.hxx> +#include <svx/svdetc.hxx> +#include <svx/svditer.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdogrp.hxx> +#include <svx/svdouno.hxx> +#include <svx/svdoole2.hxx> +#include <svx/svdpage.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/docfile.hxx> +#include <sot/clsids.hxx> +#include <sot/formats.hxx> +#include <sot/filelist.hxx> +#include <unotools/pathoptions.hxx> +#include <svl/ptitem.hxx> +#include <svl/stritem.hxx> +#include <svtools/transfer.hxx> +#include <vcl/graph.hxx> + +#include <comphelper/storagehelper.hxx> +#include <comphelper/processfactory.hxx> + +#include <sot/formats.hxx> +#define SOT_FORMATSTR_ID_STARCALC_CURRENT SOT_FORMATSTR_ID_STARCALC_50 + +#include "viewfunc.hxx" +#include "docsh.hxx" +#include "drawview.hxx" +#include "impex.hxx" +#include "dbfunc.hxx" +#include "dbcolect.hxx" +#include "sc.hrc" +#include "filter.hxx" +#include "scextopt.hxx" +#include "tabvwsh.hxx" // wegen GetViewFrame +#include "compiler.hxx" + +#include "asciiopt.hxx" +#include "scabstdlg.hxx" +#include "clipparam.hxx" +#include <vcl/msgbox.hxx> +#include <sfx2/viewfrm.hxx> +#include <svx/dbaexchange.hxx> + +using namespace com::sun::star; + +//------------------------------------------------------------------ + +sal_Bool ScViewFunc::PasteDataFormat( sal_uLong nFormatId, + const uno::Reference<datatransfer::XTransferable>& rxTransferable, + SCCOL nPosX, SCROW nPosY, Point* pLogicPos, sal_Bool bLink, sal_Bool bAllowDialogs ) +{ + ScDocument* pDoc = GetViewData()->GetDocument(); + pDoc->SetPastingDrawFromOtherDoc( sal_True ); + + Point aPos; // inserting position (1/100 mm) + if (pLogicPos) + aPos = *pLogicPos; + else + { + // inserting position isn't needed for text formats + sal_Bool bIsTextFormat = ( ScImportExport::IsFormatSupported( nFormatId ) || + nFormatId == FORMAT_RTF ); + if ( !bIsTextFormat ) + { + // Window MapMode isn't drawing MapMode if DrawingLayer hasn't been created yet + + SCTAB nTab = GetViewData()->GetTabNo(); + long nXT = 0; + for (SCCOL i=0; i<nPosX; i++) + nXT += pDoc->GetColWidth(i,nTab); + if (pDoc->IsNegativePage(nTab)) + nXT = -nXT; + sal_uLong nYT = pDoc->GetRowHeight( 0, nPosY-1, nTab); + aPos = Point( (long)(nXT * HMM_PER_TWIPS), (long)(nYT * HMM_PER_TWIPS) ); + } + } + + TransferableDataHelper aDataHelper( rxTransferable ); + sal_Bool bRet = sal_False; + + // + // handle individual formats + // + + if ( nFormatId == SOT_FORMATSTR_ID_EMBED_SOURCE || + nFormatId == SOT_FORMATSTR_ID_LINK_SOURCE || + nFormatId == SOT_FORMATSTR_ID_EMBED_SOURCE_OLE || + nFormatId == SOT_FORMATSTR_ID_LINK_SOURCE_OLE || + nFormatId == SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) + { + uno::Reference < io::XInputStream > xStm; + TransferableObjectDescriptor aObjDesc; + + if( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) && + aDataHelper.GetInputStream( nFormatId, xStm ) ) + { + if ( aObjDesc.maClassName == SvGlobalName( SO3_SC_CLASSID_60 ) ) + { + uno::Reference < embed::XStorage > xStore = ::comphelper::OStorageHelper::GetStorageFromInputStream( xStm ); + + // mba: BaseURL doesn't make sense for clipboard + // #i43716# Medium must be allocated with "new". + // DoLoad stores the pointer and deletes it with the SfxObjectShell. + SfxMedium* pMedium = new SfxMedium( xStore, String() ); + + // TODO/LATER: is it a problem that we don't support binary formats here? + ScDocShellRef xDocShRef = new ScDocShell(SFX_CREATE_MODE_EMBEDDED); + if (xDocShRef->DoLoad(pMedium)) + { + ScDocument* pSrcDoc = xDocShRef->GetDocument(); + SCTAB nSrcTab = pSrcDoc->GetVisibleTab(); + if (!pSrcDoc->HasTable(nSrcTab)) + nSrcTab = 0; + + ScMarkData aSrcMark; + aSrcMark.SelectOneTable( nSrcTab ); // for CopyToClip + ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP ); + + SCCOL nFirstCol, nLastCol; + SCROW nFirstRow, nLastRow; + if ( pSrcDoc->GetDataStart( nSrcTab, nFirstCol, nFirstRow ) ) + pSrcDoc->GetCellArea( nSrcTab, nLastCol, nLastRow ); + else + { + nFirstCol = nLastCol = 0; + nFirstRow = nLastRow = 0; + } + ScClipParam aClipParam(ScRange(nFirstCol, nFirstRow, 0, nLastCol, nLastRow, 0), false); + pSrcDoc->CopyToClip(aClipParam, pClipDoc, &aSrcMark); + ScGlobal::SetClipDocName( xDocShRef->GetTitle( SFX_TITLE_FULLNAME ) ); + + SetCursor( nPosX, nPosY ); + Unmark(); + PasteFromClip( IDF_ALL, pClipDoc, + PASTE_NOFUNC, sal_False, sal_False, sal_False, INS_NONE, IDF_NONE, + bAllowDialogs ); + delete pClipDoc; + bRet = sal_True; + } + + xDocShRef->DoClose(); + xDocShRef.Clear(); + } + else + { + ::rtl::OUString aName; + uno::Reference < embed::XEmbeddedObject > xObj = GetViewData()->GetViewShell()->GetObjectShell()-> + GetEmbeddedObjectContainer().InsertEmbeddedObject( xStm, aName ); + if ( xObj.is() ) + { + // try to get the replacement image from the clipboard + Graphic aGraphic; + sal_uLong nGrFormat = 0; +// (wg. Selection Manager bei Trustet Solaris) +#ifndef SOLARIS +/* + if( aDataHelper.GetGraphic( SOT_FORMATSTR_ID_SVXB, aGraphic ) ) + nGrFormat = SOT_FORMATSTR_ID_SVXB; + else if( aDataHelper.GetGraphic( FORMAT_GDIMETAFILE, aGraphic ) ) + nGrFormat = SOT_FORMAT_GDIMETAFILE; + else if( aDataHelper.GetGraphic( FORMAT_BITMAP, aGraphic ) ) + nGrFormat = SOT_FORMAT_BITMAP; +*/ +#endif + + // insert replacement image ( if there is one ) into the object helper + if ( nGrFormat ) + { + datatransfer::DataFlavor aDataFlavor; + SotExchange::GetFormatDataFlavor( nGrFormat, aDataFlavor ); + PasteObject( aPos, xObj, &aObjDesc.maSize, &aGraphic, aDataFlavor.MimeType, aObjDesc.mnViewAspect ); + } + else + PasteObject( aPos, xObj, &aObjDesc.maSize ); + + bRet = sal_True; + } + else + { + DBG_ERROR("Error in CreateAndLoad"); + } + } + } + else + { +// uno::Reference < io::XInputStream > xStm; +// TransferableObjectDescriptor aObjDesc; + + if ( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR_OLE, aObjDesc ) ) + { + ::rtl::OUString aName; + uno::Reference < embed::XEmbeddedObject > xObj; + + if ( aDataHelper.GetInputStream( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE, xStm ) + || aDataHelper.GetInputStream( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE, xStm ) ) + { + xObj = GetViewData()->GetDocShell()->GetEmbeddedObjectContainer().InsertEmbeddedObject( xStm, aName ); + } + else + { + try + { + uno::Reference< embed::XStorage > xTmpStor = ::comphelper::OStorageHelper::GetTemporaryStorage(); + uno::Reference < embed::XEmbedObjectClipboardCreator > xClipboardCreator( + ::comphelper::getProcessServiceFactory()->createInstance( ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.MSOLEObjectSystemCreator") ) ), + uno::UNO_QUERY_THROW ); + + embed::InsertedObjectInfo aInfo = xClipboardCreator->createInstanceInitFromClipboard( + xTmpStor, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "DummyName" ) ), + uno::Sequence< beans::PropertyValue >() ); + + // TODO/LATER: in future InsertedObjectInfo will be used to get container related information + // for example whether the object should be an iconified one + xObj = aInfo.Object; + if ( xObj.is() ) + GetViewData()->GetDocShell()->GetEmbeddedObjectContainer().InsertEmbeddedObject( xObj, aName ); + } + catch( uno::Exception& ) + {} + } + + if ( xObj.is() ) + { + // try to get the replacement image from the clipboard + Graphic aGraphic; + sal_uLong nGrFormat = 0; + +// (wg. Selection Manager bei Trustet Solaris) +#ifndef SOLARIS + if( aDataHelper.GetGraphic( SOT_FORMATSTR_ID_SVXB, aGraphic ) ) + nGrFormat = SOT_FORMATSTR_ID_SVXB; + else if( aDataHelper.GetGraphic( FORMAT_GDIMETAFILE, aGraphic ) ) + nGrFormat = SOT_FORMAT_GDIMETAFILE; + else if( aDataHelper.GetGraphic( FORMAT_BITMAP, aGraphic ) ) + nGrFormat = SOT_FORMAT_BITMAP; +#endif + + // insert replacement image ( if there is one ) into the object helper + if ( nGrFormat ) + { + datatransfer::DataFlavor aDataFlavor; + SotExchange::GetFormatDataFlavor( nGrFormat, aDataFlavor ); + PasteObject( aPos, xObj, &aObjDesc.maSize, &aGraphic, aDataFlavor.MimeType, aObjDesc.mnViewAspect ); + } + else + PasteObject( aPos, xObj, &aObjDesc.maSize ); + + // let object stay in loaded state after insertion + SdrOle2Obj::Unload( xObj, embed::Aspects::MSOLE_CONTENT ); + bRet = sal_True; + } + else + { + DBG_ERROR("Error creating external OLE object"); + } + } + //TODO/LATER: if format is not available, create picture + } + } + else if ( nFormatId == SOT_FORMATSTR_ID_LINK ) // LINK is also in ScImportExport + { + bRet = PasteDDE( rxTransferable ); + } + else if ( ScImportExport::IsFormatSupported( nFormatId ) || nFormatId == SOT_FORMAT_RTF ) + { + if ( nFormatId == SOT_FORMAT_RTF && aDataHelper.HasFormat( SOT_FORMATSTR_ID_EDITENGINE ) ) + { + // use EditView's PasteSpecial / Drop + PasteRTF( nPosX, nPosY, rxTransferable ); + bRet = sal_True; + } + else + { + ScAddress aCellPos( nPosX, nPosY, GetViewData()->GetTabNo() ); + ScImportExport aObj( GetViewData()->GetDocument(), aCellPos ); + + ::rtl::OUString aStr; + SotStorageStreamRef xStream; + if ( aDataHelper.GetSotStorageStream( nFormatId, xStream ) && xStream.Is() ) + // mba: clipboard always must contain absolute URLs (could be from alien source) + bRet = aObj.ImportStream( *xStream, String(), nFormatId ); + else if (nFormatId == FORMAT_STRING && aDataHelper.GetString( nFormatId, aStr )) + { + // Do CSV dialog if more than one line. + sal_Int32 nDelim = aStr.indexOf('\n'); +#if 0 + ::rtl::OString tmpStr = OUStringToOString( aStr, + RTL_TEXTENCODING_UTF8 ); + fprintf( stderr, "String is '%s' (%d) [%d]\n", tmpStr.getStr(), + tmpStr.getLength(), nDelim); +#endif + if (nDelim >= 0 && nDelim != aStr.getLength () - 1) + { + ScImportStringStream aStrm( aStr); + ScAbstractDialogFactory* pFact = + ScAbstractDialogFactory::Create(); + AbstractScImportAsciiDlg *pDlg = + pFact->CreateScImportAsciiDlg( NULL, String(), &aStrm, + RID_SCDLG_ASCII); + + if (pDlg->Execute() == RET_OK) + { + ScAsciiOptions aOptions; + pDlg->GetOptions( aOptions ); + aObj.SetExtOptions( aOptions ); + + bRet = aObj.ImportString( aStr, nFormatId ); + + // TODO: what if (aObj.IsOverflow()) + // Content was partially pasted, which can be undone by + // the user though. + if (aObj.IsOverflow()) + bRet = sal_False; + } + else + bRet = sal_True; + // Yes, no failure, don't raise a "couldn't paste" + // dialog if user cancelled. + delete pDlg; + } + else + bRet = aObj.ImportString( aStr, nFormatId ); + } + else if (nFormatId != FORMAT_STRING && aDataHelper.GetString( nFormatId, aStr )) + bRet = aObj.ImportString( aStr, nFormatId ); + + InvalidateAttribs(); + GetViewData()->UpdateInputHandler(); + } + } + else if (nFormatId == SOT_FORMATSTR_ID_SBA_DATAEXCHANGE) + { + // import of database data into table + + String sDataDesc; + if ( aDataHelper.GetString( nFormatId, sDataDesc ) ) + { + SfxStringItem aDataDesc(SID_SBA_IMPORT, sDataDesc); + + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + SCTAB nTab = GetViewData()->GetTabNo(); + + ClickCursor(nPosX, nPosY, sal_False); // set cursor position + + // Creation of database area "Import1" isn't here, but in the DocShell + // slot execute, so it can be added to the undo action + + ScDBData* pDBData = pDocSh->GetDBData( ScRange(nPosX,nPosY,nTab), SC_DB_OLD, SC_DBSEL_KEEP ); + String sTarget; + if (pDBData) + sTarget = pDBData->GetName(); + else + { + ScAddress aCellPos( nPosX,nPosY,nTab ); + aCellPos.Format( sTarget, SCA_ABS_3D, pDoc, pDoc->GetAddressConvention() ); + } + SfxStringItem aTarget(FN_PARAM_1, sTarget); + + sal_Bool bAreaIsNew = !pDBData; + SfxBoolItem aAreaNew(FN_PARAM_2, bAreaIsNew); + + ::svx::ODataAccessDescriptor aDesc; + DataFlavorExVector& rVector = aDataHelper.GetDataFlavorExVector(); + ::std::auto_ptr<SfxUsrAnyItem> pCursorItem; + if ( ::svx::ODataAccessObjectTransferable::canExtractObjectDescriptor(rVector) ) + { + aDesc = ::svx::ODataAccessObjectTransferable::extractObjectDescriptor(aDataHelper); + if ( aDesc.has(::svx::daCursor) ) + pCursorItem.reset(new SfxUsrAnyItem(FN_PARAM_3, aDesc[::svx::daCursor])); + } + + // asynchronous, to avoid doing the whole import in drop handler + SfxDispatcher& rDisp = GetViewData()->GetDispatcher(); + rDisp.Execute(SID_SBA_IMPORT, SFX_CALLMODE_ASYNCHRON, + &aDataDesc, &aTarget, &aAreaNew, pCursorItem.get(), (void*)0 ); + + bRet = sal_True; + } + } + else if (nFormatId == SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE) + { + // insert database field control + + if ( ::svx::OColumnTransferable::canExtractColumnDescriptor( aDataHelper.GetDataFlavorExVector(), CTF_COLUMN_DESCRIPTOR | CTF_CONTROL_EXCHANGE ) ) + { + MakeDrawLayer(); + ScDrawView* pScDrawView = GetScDrawView(); + SdrObject* pObj = pScDrawView->CreateFieldControl( ::svx::OColumnTransferable::extractColumnDescriptor( aDataHelper ) ); + if (pObj) + { + Point aInsPos = aPos; + Rectangle aRect(pObj->GetLogicRect()); + aInsPos.X() -= aRect.GetSize().Width() / 2; + aInsPos.Y() -= aRect.GetSize().Height() / 2; + if ( aInsPos.X() < 0 ) aInsPos.X() = 0; + if ( aInsPos.Y() < 0 ) aInsPos.Y() = 0; + aRect.SetPos(aInsPos); + pObj->SetLogicRect(aRect); + + if ( pObj->ISA(SdrUnoObj) ) + pObj->NbcSetLayer(SC_LAYER_CONTROLS); + else + pObj->NbcSetLayer(SC_LAYER_FRONT); + if (pObj->ISA(SdrObjGroup)) + { + SdrObjListIter aIter( *pObj, IM_DEEPWITHGROUPS ); + SdrObject* pSubObj = aIter.Next(); + while (pSubObj) + { + if ( pSubObj->ISA(SdrUnoObj) ) + pSubObj->NbcSetLayer(SC_LAYER_CONTROLS); + else + pSubObj->NbcSetLayer(SC_LAYER_FRONT); + pSubObj = aIter.Next(); + } + } + + pScDrawView->InsertObjectSafe(pObj, *pScDrawView->GetSdrPageView()); + + GetViewData()->GetViewShell()->SetDrawShell( sal_True ); + bRet = sal_True; + } + } + } + else if (nFormatId == SOT_FORMAT_BITMAP) + { + Bitmap aBmp; + if( aDataHelper.GetBitmap( FORMAT_BITMAP, aBmp ) ) + bRet = PasteBitmap( aPos, aBmp ); + } + else if (nFormatId == SOT_FORMAT_GDIMETAFILE) + { + GDIMetaFile aMtf; + if( aDataHelper.GetGDIMetaFile( FORMAT_GDIMETAFILE, aMtf ) ) + bRet = PasteMetaFile( aPos, aMtf ); + } + else if (nFormatId == SOT_FORMATSTR_ID_SVXB) + { + SotStorageStreamRef xStm; + if( aDataHelper.GetSotStorageStream( SOT_FORMATSTR_ID_SVXB, xStm ) ) + { + Graphic aGraphic; + *xStm >> aGraphic; + bRet = PasteGraphic( aPos, aGraphic, EMPTY_STRING, EMPTY_STRING ); + } + } + else if ( nFormatId == SOT_FORMATSTR_ID_DRAWING ) + { + SotStorageStreamRef xStm; + if( aDataHelper.GetSotStorageStream( SOT_FORMATSTR_ID_DRAWING, xStm ) ) + { + MakeDrawLayer(); // before loading model, so 3D factory has been created + + SvtPathOptions aPathOpt; + String aPath = aPathOpt.GetPalettePath(); + + ScDocShellRef aDragShellRef( new ScDocShell ); + aDragShellRef->DoInitNew(NULL); + FmFormModel* pModel = new FmFormModel( aPath, NULL, aDragShellRef ); + + pModel->GetItemPool().FreezeIdRanges(); + xStm->Seek(0); + + com::sun::star::uno::Reference< com::sun::star::io::XInputStream > xInputStream( new utl::OInputStreamWrapper( *xStm ) ); + SvxDrawingLayerImport( pModel, xInputStream ); + + // set everything to right layer: + sal_uLong nObjCount = 0; + sal_uInt16 nPages = pModel->GetPageCount(); + for (sal_uInt16 i=0; i<nPages; i++) + { + SdrPage* pPage = pModel->GetPage(i); + SdrObjListIter aIter( *pPage, IM_DEEPWITHGROUPS ); + SdrObject* pObject = aIter.Next(); + while (pObject) + { + if ( pObject->ISA(SdrUnoObj) ) + pObject->NbcSetLayer(SC_LAYER_CONTROLS); + else + pObject->NbcSetLayer(SC_LAYER_FRONT); + pObject = aIter.Next(); + } + + nObjCount += pPage->GetObjCount(); // #105888# count group object only once + } + + PasteDraw( aPos, pModel, (nObjCount > 1) ); // grouped if more than 1 object + delete pModel; + aDragShellRef->DoClose(); + bRet = sal_True; + } + } + else if ( (nFormatId == SOT_FORMATSTR_ID_BIFF_5) || (nFormatId == SOT_FORMATSTR_ID_BIFF_8) ) + { + // do excel import into a clipboard document + //TODO/MBA: testing + uno::Reference < io::XInputStream > xStm; + if( aDataHelper.GetInputStream( nFormatId, xStm ) ) + { +#if 0 + SotStorage aDest( "d:\\test.xls" ); // to see the file + pStor->CopyTo( &aDest ); +#endif + ScDocument* pInsDoc = new ScDocument( SCDOCMODE_CLIP ); + SCTAB nSrcTab = 0; // Biff5 in clipboard: always sheet 0 + pInsDoc->ResetClip( pDoc, nSrcTab ); + + SfxMedium aMed; + aMed.GetItemSet()->Put( SfxUsrAnyItem( SID_INPUTSTREAM, uno::makeAny( xStm ) ) ); + FltError eErr = ScFormatFilter::Get().ScImportExcel( aMed, pInsDoc, EIF_AUTO ); + if ( eErr == eERR_OK ) + { + ScRange aSource; + const ScExtDocOptions* pExtOpt = pInsDoc->GetExtDocOptions(); + const ScExtTabSettings* pTabSett = pExtOpt ? pExtOpt->GetTabSettings( nSrcTab ) : 0; + if( pTabSett && pTabSett->maUsedArea.IsValid() ) + { + aSource = pTabSett->maUsedArea; + // ensure correct sheet indexes + aSource.aStart.SetTab( nSrcTab ); + aSource.aEnd.SetTab( nSrcTab ); +// #92240# don't use selection area: if cursor is moved in Excel after Copy, selection +// represents the new cursor position and not the copied area + } + else + { + DBG_ERROR("no dimension"); //! possible? + SCCOL nFirstCol, nLastCol; + SCROW nFirstRow, nLastRow; + if ( pInsDoc->GetDataStart( nSrcTab, nFirstCol, nFirstRow ) ) + pInsDoc->GetCellArea( nSrcTab, nLastCol, nLastRow ); + else + { + nFirstCol = nLastCol = 0; + nFirstRow = nLastRow = 0; + } + aSource = ScRange( nFirstCol, nFirstRow, nSrcTab, + nLastCol, nLastRow, nSrcTab ); + } + + if ( pLogicPos ) + { + // position specified (Drag&Drop) - change selection + MoveCursorAbs( nPosX, nPosY, SC_FOLLOW_NONE, sal_False, sal_False ); + Unmark(); + } + + pInsDoc->SetClipArea( aSource ); + PasteFromClip( IDF_ALL, pInsDoc, + PASTE_NOFUNC, sal_False, sal_False, sal_False, INS_NONE, IDF_NONE, + bAllowDialogs ); + delete pInsDoc; + + bRet = sal_True; + } + } + } + else if ( nFormatId == SOT_FORMAT_FILE ) + { + String aFile; + if ( aDataHelper.GetString( nFormatId, aFile ) ) + bRet = PasteFile( aPos, aFile, bLink ); + } + else if ( nFormatId == SOT_FORMAT_FILE_LIST ) + { + FileList aFileList; + if ( aDataHelper.GetFileList( nFormatId, aFileList ) ) + { + sal_uLong nCount = aFileList.Count(); + for( sal_uLong i = 0; i < nCount ; i++ ) + { + String aFile = aFileList.GetFile( i ); + + PasteFile( aPos, aFile, bLink ); +#if 0 + SfxStringItem aNameItem( FID_INSERT_FILE, aFile ); + SfxPointItem aPosItem( FN_PARAM_1, aPos ); + SfxDispatcher* pDisp = + GetViewData()->GetViewShell()->GetViewFrame()->GetDispatcher(); + if (pDisp) + pDisp->Execute( FID_INSERT_FILE, SFX_CALLMODE_ASYNCHRON, + &aNameItem, &aPosItem, (void*)0 ); +#endif + + aPos.X() += 400; + aPos.Y() += 400; + } + bRet = sal_True; + } + } + else if ( nFormatId == SOT_FORMATSTR_ID_SOLK || + nFormatId == SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR || + nFormatId == SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK || + nFormatId == SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) + { + bRet = PasteBookmark( nFormatId, rxTransferable, nPosX, nPosY ); + } + + pDoc->SetPastingDrawFromOtherDoc( sal_False ); + + return bRet; +} + +ByteString lcl_GetSubString( sal_Char* pData, long nStart, long nDataSize ) +{ + if ( nDataSize <= nStart /* || pData[nDataSize] != 0 */ ) + { + DBG_ERROR("DDE Data: invalid data"); + return ByteString(); + } + return ByteString( pData + nStart ); +} + +sal_Bool ScViewFunc::PasteDDE( const uno::Reference<datatransfer::XTransferable>& rxTransferable ) +{ + TransferableDataHelper aDataHelper( rxTransferable ); + + // get link data from transferable before string data, + // so the source knows it will be used for a link + + uno::Sequence<sal_Int8> aSequence; + if ( !aDataHelper.GetSequence( SOT_FORMATSTR_ID_LINK, aSequence ) ) + { + DBG_ERROR("DDE Data not found."); + return sal_False; + } + + // check size (only if string is available in transferable) + + sal_uInt16 nCols = 1; + sal_uInt16 nRows = 1; + if ( aDataHelper.HasFormat( SOT_FORMAT_STRING ) ) + { + String aDataStr; + if ( aDataHelper.GetString( SOT_FORMAT_STRING, aDataStr ) ) + { + // get size from string the same way as in ScDdeLink::DataChanged + + aDataStr.ConvertLineEnd(LINEEND_LF); + xub_StrLen nLen = aDataStr.Len(); + if (nLen && aDataStr.GetChar(nLen-1) == '\n') + aDataStr.Erase(nLen-1); + + if (aDataStr.Len()) + { + nRows = aDataStr.GetTokenCount( '\n' ); + String aLine = aDataStr.GetToken( 0, '\n' ); + if (aLine.Len()) + nCols = aLine.GetTokenCount( '\t' ); + } + } + } + + // create formula + + long nSeqLen = aSequence.getLength(); + sal_Char* pData = (sal_Char*)aSequence.getConstArray(); + + rtl_TextEncoding eSysEnc = gsl_getSystemTextEncoding(); + + ByteString aByteApp = lcl_GetSubString( pData, 0, nSeqLen ); + ByteString aByteTopic = lcl_GetSubString( pData, aByteApp.Len() + 1, nSeqLen ); + ByteString aByteItem = lcl_GetSubString( pData, aByteApp.Len() + aByteTopic.Len() + 2, nSeqLen ); + + String aApp( aByteApp, eSysEnc ); + String aTopic( aByteTopic, eSysEnc ); + String aItem( aByteItem, eSysEnc ); + + // TODO: we could define ocQuote for " + const String aQuote( '"' ); + const String& sSep = ScCompiler::GetNativeSymbol( ocSep); + String aFormula( '=' ); + aFormula += ScCompiler::GetNativeSymbol( ocDde); + aFormula += ScCompiler::GetNativeSymbol( ocOpen); + aFormula += aQuote; + aFormula += aApp; + aFormula += aQuote; + aFormula += sSep; + aFormula += aQuote; + aFormula += aTopic; + aFormula += aQuote; + aFormula += sSep; + aFormula += aQuote; + aFormula += aItem; + aFormula += aQuote; + aFormula += ScCompiler::GetNativeSymbol( ocClose); + + // mark range + + SCTAB nTab = GetViewData()->GetTabNo(); + SCCOL nCurX = GetViewData()->GetCurX(); + SCROW nCurY = GetViewData()->GetCurY(); + HideAllCursors(); + DoneBlockMode(); + InitBlockMode( nCurX, nCurY, nTab ); + MarkCursor( nCurX+static_cast<SCCOL>(nCols)-1, nCurY+static_cast<SCROW>(nRows)-1, nTab ); + ShowAllCursors(); + + // enter formula + + EnterMatrix( aFormula ); + CursorPosChanged(); + + return sal_True; +} + + diff --git a/sc/source/ui/view/viewfun6.cxx b/sc/source/ui/view/viewfun6.cxx new file mode 100644 index 000000000000..ded17fb9ccf4 --- /dev/null +++ b/sc/source/ui/view/viewfun6.cxx @@ -0,0 +1,197 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +#include <svx/svdundo.hxx> +#include <svx/svdocapt.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/sound.hxx> + +#include "viewfunc.hxx" +#include "detfunc.hxx" +#include "detdata.hxx" +#include "viewdata.hxx" +#include "drwlayer.hxx" +#include "docsh.hxx" +#include "undocell.hxx" +#include "futext.hxx" +#include "docfunc.hxx" +#include "globstr.hrc" +#include "sc.hrc" +#include "fusel.hxx" + +//================================================================== + +void ScViewFunc::DetectiveAddPred() +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + sal_Bool bDone = pDocSh->GetDocFunc(). + DetectiveAddPred( GetViewData()->GetCurPos() ); + if (!bDone) + Sound::Beep(); + + RecalcPPT(); //! use broadcast in DocFunc instead? +} + +void ScViewFunc::DetectiveDelPred() +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + sal_Bool bDone = pDocSh->GetDocFunc(). + DetectiveDelPred( GetViewData()->GetCurPos() ); + if (!bDone) + Sound::Beep(); + + RecalcPPT(); +} + +void ScViewFunc::DetectiveAddSucc() +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + sal_Bool bDone = pDocSh->GetDocFunc(). + DetectiveAddSucc( GetViewData()->GetCurPos() ); + if (!bDone) + Sound::Beep(); + + RecalcPPT(); +} + +void ScViewFunc::DetectiveDelSucc() +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + sal_Bool bDone = pDocSh->GetDocFunc(). + DetectiveDelSucc( GetViewData()->GetCurPos() ); + if (!bDone) + Sound::Beep(); + + RecalcPPT(); +} + +void ScViewFunc::DetectiveAddError() +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + sal_Bool bDone = pDocSh->GetDocFunc(). + DetectiveAddError( GetViewData()->GetCurPos() ); + if (!bDone) + Sound::Beep(); + + RecalcPPT(); +} + +void ScViewFunc::DetectiveDelAll() +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + sal_Bool bDone = pDocSh->GetDocFunc(). + DetectiveDelAll( GetViewData()->GetTabNo() ); + if (!bDone) + Sound::Beep(); + + RecalcPPT(); +} + +void ScViewFunc::DetectiveMarkInvalid() +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + sal_Bool bDone = pDocSh->GetDocFunc(). + DetectiveMarkInvalid( GetViewData()->GetTabNo() ); + if (!bDone) + Sound::Beep(); + + RecalcPPT(); +} + +void ScViewFunc::DetectiveRefresh() +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + sal_Bool bDone = pDocSh->GetDocFunc().DetectiveRefresh(); + if (!bDone) + Sound::Beep(); + + RecalcPPT(); +} + +//--------------------------------------------------------------------------- + +void ScViewFunc::ShowNote( bool bShow ) +{ + if( bShow ) + HideNoteMarker(); + const ScViewData& rViewData = *GetViewData(); + ScAddress aPos( rViewData.GetCurX(), rViewData.GetCurY(), rViewData.GetTabNo() ); + // show note moved to ScDocFunc, to be able to use it in notesuno.cxx + rViewData.GetDocShell()->GetDocFunc().ShowNote( aPos, bShow ); +} + +void ScViewFunc::EditNote() +{ + // zum Editieren einblenden und aktivieren + + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + SCCOL nCol = GetViewData()->GetCurX(); + SCROW nRow = GetViewData()->GetCurY(); + SCTAB nTab = GetViewData()->GetTabNo(); + ScAddress aPos( nCol, nRow, nTab ); + + // start drawing undo to catch undo action for insertion of the caption object + pDocSh->MakeDrawLayer(); + ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer(); + pDrawLayer->BeginCalcUndo(); + // generated undo action is processed in FuText::StopEditMode + + // get existing note or create a new note (including caption drawing object) + if( ScPostIt* pNote = pDoc->GetOrCreateNote( aPos ) ) + { + // hide temporary note caption + HideNoteMarker(); + // show caption object without changing internal visibility state + pNote->ShowCaptionTemp( aPos ); + + /* Drawing object has been created in ScDocument::GetOrCreateNote() or + in ScPostIt::ShowCaptionTemp(), so ScPostIt::GetCaption() should + return a caption object. */ + if( SdrCaptionObj* pCaption = pNote->GetCaption() ) + { + // #i33764# enable the resize handles before starting edit mode + if( FuPoor* pDraw = GetDrawFuncPtr() ) + static_cast< FuSelection* >( pDraw )->ActivateNoteHandles( pCaption ); + + // activate object (as in FuSelection::TestComment) + GetViewData()->GetDispatcher().Execute( SID_DRAW_NOTEEDIT, SFX_CALLMODE_SYNCHRON | SFX_CALLMODE_RECORD ); + // jetzt den erzeugten FuText holen und in den EditModus setzen + FuPoor* pPoor = GetDrawFuncPtr(); + if ( pPoor && (pPoor->GetSlotID() == SID_DRAW_NOTEEDIT) ) // hat keine RTTI + { + ScrollToObject( pCaption ); // Objekt komplett sichtbar machen + static_cast< FuText* >( pPoor )->SetInEditMode( pCaption ); + } + } + } +} diff --git a/sc/source/ui/view/viewfun7.cxx b/sc/source/ui/view/viewfun7.cxx new file mode 100644 index 000000000000..5ee4893a0a9a --- /dev/null +++ b/sc/source/ui/view/viewfun7.cxx @@ -0,0 +1,492 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" +#include <com/sun/star/embed/NoVisualAreaSizeException.hpp> + + + +// INCLUDE --------------------------------------------------------------- + +#include <svx/svditer.hxx> +#include <svx/svdograf.hxx> +#include <svx/svdoole2.hxx> +#include <svx/svdouno.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svdundo.hxx> +#include <svx/xbitmap.hxx> +#include <svx/xbtmpit.hxx> +#include <svx/xoutbmp.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/viewfrm.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <com/sun/star/embed/Aspects.hpp> + +#include "document.hxx" // fuer MapMode Initialisierung in PasteDraw +#include "viewfunc.hxx" +#include "tabvwsh.hxx" +#include "drawview.hxx" +#include "scmod.hxx" +#include "drwlayer.hxx" +#include "drwtrans.hxx" +#include "globstr.hrc" +#include "chartlis.hxx" +#include "docuno.hxx" +#include "docsh.hxx" +#include "convuno.hxx" + +extern Point aDragStartDiff; + +// STATIC DATA ----------------------------------------------------------- + +sal_Bool bPasteIsMove = sal_False; + +using namespace com::sun::star; + +//================================================================== + +void lcl_AdjustInsertPos( ScViewData* pData, Point& rPos, Size& rSize ) +{ +// SdrPage* pPage = pData->GetDocument()->GetDrawLayer()->GetPage( pData->GetTabNo() ); + SdrPage* pPage = pData->GetScDrawView()->GetModel()->GetPage( static_cast<sal_uInt16>(pData->GetTabNo()) ); + DBG_ASSERT(pPage,"pPage ???"); + Size aPgSize( pPage->GetSize() ); + if (aPgSize.Width() < 0) + aPgSize.Width() = -aPgSize.Width(); + long x = aPgSize.Width() - rPos.X() - rSize.Width(); + long y = aPgSize.Height() - rPos.Y() - rSize.Height(); + // ggf. Ajustments (80/200) fuer Pixel-Rundungsfehler + if( x < 0 ) + rPos.X() += x + 80; + if( y < 0 ) + rPos.Y() += y + 200; + rPos.X() += rSize.Width() / 2; // Position bei Paste gibt Mittelpunkt an + rPos.Y() += rSize.Height() / 2; +} + +void ScViewFunc::PasteDraw( const Point& rLogicPos, SdrModel* pModel, + sal_Bool bGroup, sal_Bool bSameDocClipboard ) +{ + MakeDrawLayer(); + Point aPos( rLogicPos ); + + // #64184# MapMode am Outliner-RefDevice muss stimmen (wie in FuText::MakeOutliner) + //! mit FuText::MakeOutliner zusammenfassen? + MapMode aOldMapMode; + OutputDevice* pRef = GetViewData()->GetDocument()->GetDrawLayer()->GetRefDevice(); + if (pRef) + { + aOldMapMode = pRef->GetMapMode(); + pRef->SetMapMode( MapMode(MAP_100TH_MM) ); + } + + sal_Bool bNegativePage = GetViewData()->GetDocument()->IsNegativePage( GetViewData()->GetTabNo() ); + + SdrView* pDragEditView = NULL; + ScModule* pScMod = SC_MOD(); + const ScDragData& rData = pScMod->GetDragData(); + ScDrawTransferObj* pDrawTrans = rData.pDrawTransfer; + if (pDrawTrans) + { + pDragEditView = pDrawTrans->GetDragSourceView(); + + aPos -= aDragStartDiff; + if ( bNegativePage ) + { + if (aPos.X() > 0) aPos.X() = 0; + } + else + { + if (aPos.X() < 0) aPos.X() = 0; + } + if (aPos.Y() < 0) aPos.Y() = 0; + } + + ScDrawView* pScDrawView = GetScDrawView(); + if (bGroup) + pScDrawView->BegUndo( ScGlobal::GetRscString( STR_UNDO_PASTE ) ); + + sal_Bool bSameDoc = ( pDragEditView && pDragEditView->GetModel() == pScDrawView->GetModel() ); + if (bSameDoc) + { + // lokal kopieren - incl. Charts + + Point aSourceStart = pDragEditView->GetAllMarkedRect().TopLeft(); + long nDiffX = aPos.X() - aSourceStart.X(); + long nDiffY = aPos.Y() - aSourceStart.Y(); + + // innerhalb einer Page verschieben? + + if ( bPasteIsMove && + pScDrawView->GetSdrPageView()->GetPage() == + pDragEditView->GetSdrPageView()->GetPage() ) + { + if ( nDiffX != 0 || nDiffY != 0 ) + pDragEditView->MoveAllMarked(Size(nDiffX,nDiffY), sal_False); + } + else + { + SdrModel* pDrawModel = pDragEditView->GetModel(); + SCTAB nTab = GetViewData()->GetTabNo(); + SdrPage* pDestPage = pDrawModel->GetPage( static_cast< sal_uInt16 >( nTab ) ); + DBG_ASSERT(pDestPage,"nanu, Page?"); + + ::std::vector< ::rtl::OUString > aExcludedChartNames; + if ( pDestPage ) + { + ScChartHelper::GetChartNames( aExcludedChartNames, pDestPage ); + } + + SdrMarkList aMark = pDragEditView->GetMarkedObjectList(); + aMark.ForceSort(); + sal_uLong nMarkAnz=aMark.GetMarkCount(); + for (sal_uLong nm=0; nm<nMarkAnz; nm++) { + const SdrMark* pM=aMark.GetMark(nm); + const SdrObject* pObj=pM->GetMarkedSdrObj(); + + // #116235# + SdrObject* pNeuObj=pObj->Clone(); + //SdrObject* pNeuObj=pObj->Clone(pDestPage,pDrawModel); + + if (pNeuObj!=NULL) + { + pNeuObj->SetModel(pDrawModel); + pNeuObj->SetPage(pDestPage); + + // #68787# copy graphics within the same model - always needs new name + if ( pNeuObj->ISA(SdrGrafObj) && !bPasteIsMove ) + pNeuObj->SetName(((ScDrawLayer*)pDrawModel)->GetNewGraphicName()); + + if (nDiffX!=0 || nDiffY!=0) + pNeuObj->NbcMove(Size(nDiffX,nDiffY)); + pDestPage->InsertObject( pNeuObj ); + pScDrawView->AddUndo(new SdrUndoInsertObj( *pNeuObj )); + + // Chart braucht nicht mehr getrennt behandelt zu werden, + // weil es seine Daten jetzt selber hat + } + } + + if (bPasteIsMove) + pDragEditView->DeleteMarked(); + + ScDocument* pDocument = GetViewData()->GetDocument(); + ScDocShell* pDocShell = GetViewData()->GetDocShell(); + ScModelObj* pModelObj = ( pDocShell ? ScModelObj::getImplementation( pDocShell->GetModel() ) : NULL ); + if ( pDocument && pDestPage && pModelObj && pDrawTrans ) + { + const ScRangeListVector& rProtectedChartRangesVector( pDrawTrans->GetProtectedChartRangesVector() ); + ScChartHelper::CreateProtectedChartListenersAndNotify( pDocument, pDestPage, pModelObj, nTab, + rProtectedChartRangesVector, aExcludedChartNames, bSameDoc ); + } + } + } + else + { + bPasteIsMove = sal_False; // kein internes Verschieben passiert + + SdrView aView(pModel); // #i71529# never create a base class of SdrView directly! + SdrPageView* pPv = aView.ShowSdrPage(aView.GetModel()->GetPage(0)); + aView.MarkAllObj(pPv); + Size aSize = aView.GetAllMarkedRect().GetSize(); + lcl_AdjustInsertPos( GetViewData(), aPos, aSize ); + + // #41333# Markierung nicht aendern, wenn Ole-Objekt aktiv + // (bei Drop aus Ole-Objekt wuerde sonst mitten im ExecuteDrag deaktiviert!) + + sal_uLong nOptions = 0; + SfxInPlaceClient* pClient = GetViewData()->GetViewShell()->GetIPClient(); + if ( pClient && pClient->IsObjectInPlaceActive() ) + nOptions |= SDRINSERT_DONTMARK; + + ::std::vector< ::rtl::OUString > aExcludedChartNames; + SCTAB nTab = GetViewData()->GetTabNo(); + SdrPage* pPage = pScDrawView->GetModel()->GetPage( static_cast< sal_uInt16 >( nTab ) ); + DBG_ASSERT( pPage, "Page?" ); + if ( pPage ) + { + ScChartHelper::GetChartNames( aExcludedChartNames, pPage ); + } + + // #89247# Set flag for ScDocument::UpdateChartListeners() which is + // called during paste. + if ( !bSameDocClipboard ) + GetViewData()->GetDocument()->SetPastingDrawFromOtherDoc( sal_True ); + + pScDrawView->Paste( *pModel, aPos, NULL, nOptions ); + + if ( !bSameDocClipboard ) + GetViewData()->GetDocument()->SetPastingDrawFromOtherDoc( sal_False ); + + // #68991# Paste puts all objects on the active (front) layer + // controls must be on SC_LAYER_CONTROLS + if (pPage) + { + SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); + SdrObject* pObject = aIter.Next(); + while (pObject) + { + if ( pObject->ISA(SdrUnoObj) && pObject->GetLayer() != SC_LAYER_CONTROLS ) + pObject->NbcSetLayer(SC_LAYER_CONTROLS); + pObject = aIter.Next(); + } + } + + // #75299# all graphics objects must have names + GetViewData()->GetDocument()->EnsureGraphicNames(); + + ScDocument* pDocument = GetViewData()->GetDocument(); + ScDocShell* pDocShell = GetViewData()->GetDocShell(); + ScModelObj* pModelObj = ( pDocShell ? ScModelObj::getImplementation( pDocShell->GetModel() ) : NULL ); + ScDrawTransferObj* pTransferObj = ScDrawTransferObj::GetOwnClipboard( NULL ); + if ( pDocument && pPage && pModelObj && ( pTransferObj || pDrawTrans ) ) + { + const ScRangeListVector& rProtectedChartRangesVector( + pTransferObj ? pTransferObj->GetProtectedChartRangesVector() : pDrawTrans->GetProtectedChartRangesVector() ); + ScChartHelper::CreateProtectedChartListenersAndNotify( pDocument, pPage, pModelObj, nTab, + rProtectedChartRangesVector, aExcludedChartNames, bSameDocClipboard ); + } + } + + if (bGroup) + { + pScDrawView->GroupMarked(); + pScDrawView->EndUndo(); + } + + if (pRef) + pRef->SetMapMode( aOldMapMode ); + + // GetViewData()->GetViewShell()->SetDrawShell( sal_True ); + // #99759# It is not sufficient to just set the DrawShell if we pasted, for + // example, a chart. SetDrawShellOrSub() would only work for D&D in the + // same document but not if inserting from the clipboard, therefore + // MarkListHasChanged() is what we need. + pScDrawView->MarkListHasChanged(); + +} + +sal_Bool ScViewFunc::PasteObject( const Point& rPos, const uno::Reference < embed::XEmbeddedObject >& xObj, + const Size* pDescSize, const Graphic* pReplGraph, const ::rtl::OUString& aMediaType, sal_Int64 nAspect ) +{ + MakeDrawLayer(); + if ( xObj.is() ) + { + ::rtl::OUString aName; + //TODO/MBA: is that OK? + comphelper::EmbeddedObjectContainer& aCnt = GetViewData()->GetViewShell()->GetObjectShell()->GetEmbeddedObjectContainer(); + if ( !aCnt.HasEmbeddedObject( xObj ) ) + aCnt.InsertEmbeddedObject( xObj, aName ); + else + aName = aCnt.GetEmbeddedObjectName( xObj ); + + svt::EmbeddedObjectRef aObjRef( xObj, nAspect ); + if ( pReplGraph ) + aObjRef.SetGraphic( *pReplGraph, aMediaType ); + + Size aSize; + if ( nAspect == embed::Aspects::MSOLE_ICON ) + { + MapMode aMapMode( MAP_100TH_MM ); + aSize = aObjRef.GetSize( &aMapMode ); + } + else + { + // working with visual area can switch object to running state + MapUnit aMapObj = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) ); + MapUnit aMap100 = MAP_100TH_MM; + + if ( pDescSize && pDescSize->Width() && pDescSize->Height() ) + { + // use size from object descriptor if given + aSize = OutputDevice::LogicToLogic( *pDescSize, aMap100, aMapObj ); + awt::Size aSz; + aSz.Width = aSize.Width(); + aSz.Height = aSize.Height(); + xObj->setVisualAreaSize( nAspect, aSz ); + } + + awt::Size aSz; + try + { + aSz = xObj->getVisualAreaSize( nAspect ); + } + catch ( embed::NoVisualAreaSizeException& ) + { + // the default size will be set later + } + + aSize = Size( aSz.Width, aSz.Height ); + aSize = OutputDevice::LogicToLogic( aSize, aMapObj, aMap100 ); // fuer SdrOle2Obj + + if( aSize.Height() == 0 || aSize.Width() == 0 ) + { + DBG_ERROR("SvObjectDescriptor::GetSize == 0"); + aSize.Width() = 5000; + aSize.Height() = 5000; + aSize = OutputDevice::LogicToLogic( aSize, aMap100, aMapObj ); + aSz.Width = aSize.Width(); + aSz.Height = aSize.Height(); + xObj->setVisualAreaSize( nAspect, aSz ); + } + } + + // don't call AdjustInsertPos + Point aInsPos = rPos; + if ( GetViewData()->GetDocument()->IsNegativePage( GetViewData()->GetTabNo() ) ) + aInsPos.X() -= aSize.Width(); + Rectangle aRect( aInsPos, aSize ); + + ScDrawView* pDrView = GetScDrawView(); + SdrOle2Obj* pSdrObj = new SdrOle2Obj( aObjRef, aName, aRect ); + + SdrPageView* pPV = pDrView->GetSdrPageView(); + pDrView->InsertObjectSafe( pSdrObj, *pPV ); // nicht markieren wenn Ole + GetViewData()->GetViewShell()->SetDrawShell( sal_True ); + return sal_True; + } + else + return sal_False; +} + +sal_Bool ScViewFunc::PasteBitmap( const Point& rPos, const Bitmap& rBmp ) +{ + String aEmpty; + Graphic aGraphic(rBmp); + return PasteGraphic( rPos, aGraphic, aEmpty, aEmpty ); +} + +sal_Bool ScViewFunc::PasteMetaFile( const Point& rPos, const GDIMetaFile& rMtf ) +{ + String aEmpty; + Graphic aGraphic(rMtf); + return PasteGraphic( rPos, aGraphic, aEmpty, aEmpty ); +} + +sal_Bool ScViewFunc::PasteGraphic( const Point& rPos, const Graphic& rGraphic, + const String& rFile, const String& rFilter ) +{ + MakeDrawLayer(); + ScDrawView* pScDrawView = GetScDrawView(); + + Point aPos( rPos ); + Window* pWin = GetActiveWin(); + MapMode aSourceMap = rGraphic.GetPrefMapMode(); + MapMode aDestMap( MAP_100TH_MM ); + + if (aSourceMap.GetMapUnit() == MAP_PIXEL) + { + // Pixel-Korrektur beruecksichtigen, damit Bitmap auf dem Bildschirm stimmt + + Fraction aScaleX, aScaleY; + pScDrawView->CalcNormScale( aScaleX, aScaleY ); + aDestMap.SetScaleX(aScaleX); + aDestMap.SetScaleY(aScaleY); + } + + Size aSize = pWin->LogicToLogic( rGraphic.GetPrefSize(), &aSourceMap, &aDestMap ); +// lcl_AdjustInsertPos( GetViewData(), aPos, aSize ); + if ( GetViewData()->GetDocument()->IsNegativePage( GetViewData()->GetTabNo() ) ) + aPos.X() -= aSize.Width(); + + GetViewData()->GetViewShell()->SetDrawShell( sal_True ); + + Rectangle aRect(aPos, aSize); + SdrGrafObj* pGrafObj = new SdrGrafObj(rGraphic, aRect); + + // #118522# calling SetGraphicLink here doesn't work + + // #49961# Pfad wird nicht mehr als Name der Grafik gesetzt + + ScDrawLayer* pLayer = (ScDrawLayer*) pScDrawView->GetModel(); + String aName = pLayer->GetNewGraphicName(); // "Grafik x" + pGrafObj->SetName(aName); + + // nicht markieren wenn Ole + pScDrawView->InsertObjectSafe(pGrafObj, *pScDrawView->GetSdrPageView()); + + // #118522# SetGraphicLink has to be used after inserting the object, + // otherwise an empty graphic is swapped in and the contact stuff crashes. + // See #i37444#. + if (rFile.Len()) + pGrafObj->SetGraphicLink( rFile, rFilter ); + + return sal_True; +} + +sal_Bool ScViewFunc::ApplyGraphicToObject( SdrObject* pPickObj, const Graphic& rGraphic ) +{ + sal_Bool bRet = sal_False; + SdrGrafObj* pNewGrafObj = NULL; + + ScDrawView* pScDrawView = GetScDrawView(); + if ( pScDrawView && pPickObj ) + { + /********************************************************************** + * Objekt neu attributieren + **********************************************************************/ + SdrPageView* pPV = pScDrawView->GetSdrPageView(); + if (pPickObj->ISA(SdrGrafObj)) + { + /****************************************************************** + * Das Graphik-Objekt bekommt eine neue Graphik + ******************************************************************/ + pNewGrafObj = (SdrGrafObj*) pPickObj->Clone(); + pNewGrafObj->SetGraphic(rGraphic); + + pScDrawView->BegUndo(ScGlobal::GetRscString(STR_UNDO_DRAGDROP)); + pScDrawView->ReplaceObjectAtView(pPickObj, *pPV, pNewGrafObj); + pScDrawView->EndUndo(); + + bRet = sal_True; + } + else if (pPickObj->IsClosedObj() && !pPickObj->ISA(SdrOle2Obj)) + { + /****************************************************************** + * Das Objekt wird mit der Graphik gefuellt + ******************************************************************/ + //pScDrawView->BegUndo(ScGlobal::GetRscString(STR_UNDO_DRAGDROP)); + pScDrawView->AddUndo(new SdrUndoAttrObj(*pPickObj)); + //pScDrawView->EndUndo(); + + XOBitmap aXOBitmap( rGraphic.GetBitmap() ); + SfxItemSet aSet( pScDrawView->GetModel()->GetItemPool(), + XATTR_FILLSTYLE, XATTR_FILLBITMAP ); + aSet.Put(XFillStyleItem(XFILL_BITMAP)); + aSet.Put(XFillBitmapItem(String(), aXOBitmap)); + + pPickObj->SetMergedItemSetAndBroadcast(aSet); + + bRet = sal_True; + } + } + return bRet; +} + + diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx new file mode 100644 index 000000000000..8c309b3cc6a1 --- /dev/null +++ b/sc/source/ui/view/viewfunc.cxx @@ -0,0 +1,3018 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +//------------------------------------------------------------------ + +// INCLUDE --------------------------------------------------------------- + +#include "scitems.hxx" +#include <editeng/eeitem.hxx> + +#include <sfx2/app.hxx> +#include <svx/algitem.hxx> +#include <editeng/boxitem.hxx> +#include <editeng/editobj.hxx> +#include <editeng/editview.hxx> +#include <editeng/langitem.hxx> +#include <editeng/scripttypeitem.hxx> +#include <sfx2/bindings.hxx> +#include <svl/zforlist.hxx> +#include <svl/zformat.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/sound.hxx> +#include <vcl/virdev.hxx> +#include <vcl/waitobj.hxx> +#include <vcl/wrkwin.hxx> +#include <stdlib.h> // qsort + +#include "viewfunc.hxx" +#include "tabvwsh.hxx" +#include "docsh.hxx" +#include "attrib.hxx" +#include "patattr.hxx" +#include "docpool.hxx" +#include "uiitems.hxx" +#include "sc.hrc" +#include "undocell.hxx" +#include "undoblk.hxx" +#include "undotab.hxx" +#include "refundo.hxx" +#include "dbcolect.hxx" +#include "olinetab.hxx" +#include "rangeutl.hxx" +#include "rangenam.hxx" +#include "globstr.hrc" +#include "global.hxx" +#include "stlsheet.hxx" +#include "editutil.hxx" +//CHINA001 #include "namecrea.hxx" // wegen Flags +#include "cell.hxx" +#include "scresid.hxx" +#include "inputhdl.hxx" +#include "scmod.hxx" +#include "inputopt.hxx" +#include "compiler.hxx" +#include "docfunc.hxx" +#include "appoptio.hxx" +#include "dociter.hxx" +#include "sizedev.hxx" +#include "editable.hxx" +#include "scui_def.hxx" //CHINA001 +#include "funcdesc.hxx" +#include "docuno.hxx" +#include "cellsuno.hxx" +//================================================================== + +ScViewFunc::ScViewFunc( Window* pParent, ScDocShell& rDocSh, ScTabViewShell* pViewShell ) : + ScTabView( pParent, rDocSh, pViewShell ), + bFormatValid( sal_False ) +{ +} + +//UNUSED2008-05 ScViewFunc::ScViewFunc( Window* pParent, const ScViewFunc& rViewFunc, ScTabViewShell* pViewShell ) : +//UNUSED2008-05 ScTabView( pParent, rViewFunc, pViewShell ), +//UNUSED2008-05 bFormatValid( sal_False ) +//UNUSED2008-05 { +//UNUSED2008-05 } + +ScViewFunc::~ScViewFunc() +{ +} + +//------------------------------------------------------------------------------------ + +void ScViewFunc::StartFormatArea() +{ + // ueberhaupt aktiviert? + if ( !SC_MOD()->GetInputOptions().GetExtendFormat() ) + return; + + // start only with single cell (marked or cursor position) + ScRange aMarkRange; + sal_Bool bOk = (GetViewData()->GetSimpleArea( aMarkRange ) == SC_MARK_SIMPLE); + if ( bOk && aMarkRange.aStart != aMarkRange.aEnd ) + bOk = sal_False; + + if (bOk) + { + bFormatValid = sal_True; + aFormatSource = aMarkRange.aStart; + aFormatArea = ScRange( aFormatSource ); + } + else + bFormatValid = sal_False; // keinen alten Bereich behalten +} + +sal_Bool ScViewFunc::TestFormatArea( SCCOL nCol, SCROW nRow, SCTAB nTab, sal_Bool bAttrChanged ) +{ + // ueberhaupt aktiviert? + if ( !SC_MOD()->GetInputOptions().GetExtendFormat() ) + return sal_False; + + // Test: Eingabe mit Zahlformat (bAttrChanged) immer als neue Attributierung behandeln + // (alte Area verwerfen). Wenn das nicht gewollt ist, den if-Teil weglassen: + if ( bAttrChanged ) + { + StartFormatArea(); + return sal_False; + } + + //! Abfrage, ob Zelle leer war ??? + + sal_Bool bFound = sal_False; + ScRange aNewRange = aFormatArea; + if ( bFormatValid && nTab == aFormatSource.Tab() ) + { + if ( nRow >= aFormatArea.aStart.Row() && nRow <= aFormatArea.aEnd.Row() ) + { + // innerhalb ? + if ( nCol >= aFormatArea.aStart.Col() && nCol <= aFormatArea.aEnd.Col() ) + { + bFound = sal_True; // Bereich nicht aendern + } + // links ? + if ( nCol+1 == aFormatArea.aStart.Col() ) + { + bFound = sal_True; + aNewRange.aStart.SetCol( nCol ); + } + // rechts ? + if ( nCol == aFormatArea.aEnd.Col()+1 ) + { + bFound = sal_True; + aNewRange.aEnd.SetCol( nCol ); + } + } + if ( nCol >= aFormatArea.aStart.Col() && nCol <= aFormatArea.aEnd.Col() ) + { + // oben ? + if ( nRow+1 == aFormatArea.aStart.Row() ) + { + bFound = sal_True; + aNewRange.aStart.SetRow( nRow ); + } + // unten ? + if ( nRow == aFormatArea.aEnd.Row()+1 ) + { + bFound = sal_True; + aNewRange.aEnd.SetRow( nRow ); + } + } + } + + if (bFound) + aFormatArea = aNewRange; // erweitern + else + { + bFormatValid = sal_False; // ausserhalb -> abbrechen + if ( bAttrChanged ) // Wert mit Zahlformat eingegeben? + StartFormatArea(); // dann ggf. neu starten + } + + return bFound; +} + +void ScViewFunc::DoAutoAttributes( SCCOL nCol, SCROW nRow, SCTAB nTab, + sal_Bool bAttrChanged, sal_Bool bAddUndo ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + if (bAddUndo && !pDoc->IsUndoEnabled()) + bAddUndo = sal_False; + + const ScPatternAttr* pSource = pDoc->GetPattern( + aFormatSource.Col(), aFormatSource.Row(), nTab ); + if ( !((const ScMergeAttr&)pSource->GetItem(ATTR_MERGE)).IsMerged() ) + { + const ScPatternAttr* pDocOld = pDoc->GetPattern( nCol, nRow, nTab ); + // pDocOld ist nur bis zum Apply... gueltig! + + ScPatternAttr* pOldPattern = NULL; + if ( bAddUndo ) + pOldPattern = new ScPatternAttr( *pDocOld ); + + const ScStyleSheet* pSrcStyle = pSource->GetStyleSheet(); + if ( pSrcStyle && pSrcStyle != pDocOld->GetStyleSheet() ) + pDoc->ApplyStyle( nCol, nRow, nTab, *pSrcStyle ); + pDoc->ApplyPattern( nCol, nRow, nTab, *pSource ); + AdjustRowHeight( nRow, nRow, sal_True ); //! nicht doppelt ? + + if ( bAddUndo ) + { + const ScPatternAttr* pNewPattern = pDoc->GetPattern( nCol, nRow, nTab ); + + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoCursorAttr( pDocSh, nCol, nRow, nTab, + pOldPattern, pNewPattern, pSource, + sal_True ) ); + + delete pOldPattern; // wird im Undo kopiert (Pool) + } + } + + if ( bAttrChanged ) // Wert mit Zahlformat eingegeben? + aFormatSource.Set( nCol, nRow, nTab ); // dann als neue Quelle +} + +//------------------------------------------------------------------------------------ + +// Hilfsroutinen + +sal_uInt16 ScViewFunc::GetOptimalColWidth( SCCOL nCol, SCTAB nTab, sal_Bool bFormula ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + + double nPPTX = GetViewData()->GetPPTX(); + double nPPTY = GetViewData()->GetPPTY(); + Fraction aZoomX = GetViewData()->GetZoomX(); + Fraction aZoomY = GetViewData()->GetZoomY(); + + ScSizeDeviceProvider aProv(pDocSh); + if (aProv.IsPrinter()) + { + nPPTX = aProv.GetPPTX(); + nPPTY = aProv.GetPPTY(); + aZoomX = aZoomY = Fraction( 1, 1 ); + } + + sal_uInt16 nTwips = pDoc->GetOptimalColWidth( nCol, nTab, aProv.GetDevice(), + nPPTX, nPPTY, aZoomX, aZoomY, bFormula, &rMark ); + return nTwips; +} + +sal_Bool ScViewFunc::SelectionEditable( sal_Bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) +{ + sal_Bool bRet; + ScDocument* pDoc = GetViewData()->GetDocument(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + if (rMark.IsMarked() || rMark.IsMultiMarked()) + bRet = pDoc->IsSelectionEditable( rMark, pOnlyNotBecauseOfMatrix ); + else + { + SCCOL nCol = GetViewData()->GetCurX(); + SCROW nRow = GetViewData()->GetCurY(); + SCTAB nTab = GetViewData()->GetTabNo(); + bRet = pDoc->IsBlockEditable( nTab, nCol, nRow, nCol, nRow, + pOnlyNotBecauseOfMatrix ); + } + return bRet; +} + +#ifndef LRU_MAX +#define LRU_MAX 10 +#endif + +sal_Bool lcl_FunctionKnown( sal_uInt16 nOpCode ) +{ + const ScFunctionList* pFuncList = ScGlobal::GetStarCalcFunctionList(); + if ( pFuncList ) + { + sal_uLong nCount = pFuncList->GetCount(); + for (sal_uLong i=0; i<nCount; i++) + if ( pFuncList->GetFunction(i)->nFIndex == nOpCode ) + return sal_True; + } + return sal_False; +} + +sal_Bool lcl_AddFunction( ScAppOptions& rAppOpt, sal_uInt16 nOpCode ) +{ + sal_uInt16 nOldCount = rAppOpt.GetLRUFuncListCount(); + sal_uInt16* pOldList = rAppOpt.GetLRUFuncList(); + sal_uInt16 nPos; + for (nPos=0; nPos<nOldCount; nPos++) + if (pOldList[nPos] == nOpCode) // is the function already in the list? + { + if ( nPos == 0 ) + return sal_False; // already at the top -> no change + + // count doesn't change, so the original array is modified + + for (sal_uInt16 nCopy=nPos; nCopy>0; nCopy--) + pOldList[nCopy] = pOldList[nCopy-1]; + pOldList[0] = nOpCode; + + return sal_True; // list has changed + } + + if ( !lcl_FunctionKnown( nOpCode ) ) + return sal_False; // not in function list -> no change + + sal_uInt16 nNewCount = Min( (sal_uInt16)(nOldCount + 1), (sal_uInt16)LRU_MAX ); + sal_uInt16 nNewList[LRU_MAX]; + nNewList[0] = nOpCode; + for (nPos=1; nPos<nNewCount; nPos++) + nNewList[nPos] = pOldList[nPos-1]; + rAppOpt.SetLRUFuncList( nNewList, nNewCount ); + + return sal_True; // list has changed +} + +// eigentliche Funktionen + +// Eingabe - Undo OK + +void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const String& rString, + sal_Bool bRecord, const EditTextObject* pData ) +{ + ScDocument* pDoc = GetViewData()->GetDocument(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + SCTAB nTabCount = pDoc->GetTableCount(); + SCTAB nSelCount = rMark.GetSelectCount(); + SCTAB i; + if (bRecord && !pDoc->IsUndoEnabled()) + bRecord = sal_False; + + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocShellModificator aModificator( *pDocSh ); + + ScEditableTester aTester( pDoc, nCol,nRow, nCol,nRow, rMark ); + if (aTester.IsEditable()) + { + sal_Bool bEditDeleted = sal_False; + sal_uInt8 nOldScript = 0; + + ScBaseCell** ppOldCells = NULL; + sal_Bool* pHasFormat = NULL; + sal_uLong* pOldFormats = NULL; + SCTAB* pTabs = NULL; + SCTAB nUndoPos = 0; + EditTextObject* pUndoData = NULL; + if ( bRecord ) + { + ppOldCells = new ScBaseCell*[nSelCount]; + pHasFormat = new sal_Bool[nSelCount]; + pOldFormats = new sal_uLong[nSelCount]; + pTabs = new SCTAB[nSelCount]; + nUndoPos = 0; + + for (i=0; i<nTabCount; i++) + if (rMark.GetTableSelect(i)) + { + pTabs[nUndoPos] = i; + ScBaseCell* pDocCell; + pDoc->GetCell( nCol, nRow, i, pDocCell ); + if ( pDocCell ) + { + ppOldCells[nUndoPos] = pDocCell->CloneWithoutNote( *pDoc ); + if ( pDocCell->GetCellType() == CELLTYPE_EDIT ) + bEditDeleted = sal_True; + + sal_uInt8 nDocScript = pDoc->GetScriptType( nCol, nRow, i, pDocCell ); + if ( nOldScript == 0 ) + nOldScript = nDocScript; + else if ( nDocScript != nOldScript ) + bEditDeleted = sal_True; + } + else + { + ppOldCells[nUndoPos] = NULL; + } + + const SfxPoolItem* pItem; + const ScPatternAttr* pPattern = pDoc->GetPattern(nCol, nRow, i); + if ( SFX_ITEM_SET == pPattern->GetItemSet().GetItemState( + ATTR_VALUE_FORMAT,sal_False,&pItem) ) + { + pHasFormat[nUndoPos] = sal_True; + pOldFormats[nUndoPos] = ((const SfxUInt32Item*)pItem)->GetValue(); + } + else + pHasFormat[nUndoPos] = sal_False; + + ++nUndoPos; + } + + DBG_ASSERT( nUndoPos==nSelCount, "nUndoPos!=nSelCount" ); + + pUndoData = ( pData ? pData->Clone() : NULL ); + } + + bool bFormula = false; + + // a single '=' character is handled as string (needed for special filters) + if ( rString.Len() > 1 ) + { + if ( rString.GetChar(0) == '=' ) + { + // handle as formula + bFormula = true; + } + else if ( rString.GetChar(0) == '+' || rString.GetChar(0) == '-' ) + { + // if there is more than one leading '+' or '-' character, remove the additional ones + String aString( rString ); + xub_StrLen nIndex = 1; + xub_StrLen nLen = aString.Len(); + while ( nIndex < nLen && ( aString.GetChar( nIndex ) == '+' || aString.GetChar( nIndex ) == '-' ) ) + { + ++nIndex; + } + aString.Erase( 1, nIndex - 1 ); + + // if the remaining part without the leading '+' or '-' character + // is non-empty and not a number, handle as formula + if ( aString.Len() > 1 ) + { + sal_uInt32 nFormat = 0; + pDoc->GetNumberFormat( nCol, nRow, nTab, nFormat ); + SvNumberFormatter* pFormatter = pDoc->GetFormatTable(); + double fNumber = 0; + if ( !pFormatter->IsNumberFormat( aString, nFormat, fNumber ) ) + { + bFormula = true; + } + } + } + } + + sal_Bool bNumFmtChanged = sal_False; + if ( bFormula ) + { // Formel, compile mit AutoCorrection + for (i=0; i<nTabCount; i++) + if (rMark.GetTableSelect(i)) + break; + ScAddress aPos( nCol, nRow, i ); + ScCompiler aComp( pDoc, aPos); + aComp.SetGrammar(pDoc->GetGrammar()); +//2do: AutoCorrection via CalcOptions abschaltbar machen + aComp.SetAutoCorrection( sal_True ); + if ( rString.GetChar(0) == '+' || rString.GetChar(0) == '-' ) + { + aComp.SetExtendedErrorDetection( true ); + } + String aFormula( rString ); + ScTokenArray* pArr; + sal_Bool bAgain; + do + { + bAgain = sal_False; + sal_Bool bAddEqual = sal_False; + ScTokenArray* pArrFirst = pArr = aComp.CompileString( aFormula ); + sal_Bool bCorrected = aComp.IsCorrected(); + if ( bCorrected ) + { // probieren, mit erster Parser-Korrektur neu zu parsen + pArr = aComp.CompileString( aComp.GetCorrectedFormula() ); + } + if ( !pArr->GetCodeError() ) + { + bAddEqual = sal_True; + aComp.CompileTokenArray(); + bCorrected |= aComp.IsCorrected(); + } + if ( bCorrected ) + { + String aCorrectedFormula; + if ( bAddEqual ) + { + aCorrectedFormula = '='; + aCorrectedFormula += aComp.GetCorrectedFormula(); + } + else + aCorrectedFormula = aComp.GetCorrectedFormula(); + short nResult; + if ( aCorrectedFormula.Len() == 1 ) + nResult = RET_NO; // leere Formel, nur '=' + else + { + String aMessage( ScResId( SCSTR_FORMULA_AUTOCORRECTION ) ); + aMessage += aCorrectedFormula; + nResult = QueryBox( GetViewData()->GetDialogParent(), + WinBits(WB_YES_NO | WB_DEF_YES), + aMessage ).Execute(); + } + if ( nResult == RET_YES ) + { + aFormula = aCorrectedFormula; + if ( pArr != pArrFirst ) + delete pArrFirst; + bAgain = sal_True; + } + else + { + if ( pArr != pArrFirst ) + { + delete pArr; + pArr = pArrFirst; + } + } + } + } while ( bAgain ); + // um in mehreren Tabellen eingesetzt zu werden, muss die Formel + // via ScFormulaCell copy-ctor evtl. wegen RangeNames neu kompiliert + // werden, gleiches Code-Array fuer alle Zellen geht nicht. + // Wenn das Array einen Fehler enthaelt, muss in den neu erzeugten + // Zellen RPN geloescht und der Fehler explizit gesetzt werden, da + // via FormulaCell copy-ctor und Interpreter das, wenn moeglich, + // wieder glattgebuegelt wird, zu intelligent.. z.B.: =1)) + sal_uInt16 nError = pArr->GetCodeError(); + if ( !nError ) + { + // #68693# update list of recent functions with all functions that + // are not within parentheses + + ScModule* pScMod = SC_MOD(); + ScAppOptions aAppOpt = pScMod->GetAppOptions(); + sal_Bool bOptChanged = sal_False; + + formula::FormulaToken** ppToken = pArr->GetArray(); + sal_uInt16 nTokens = pArr->GetLen(); + sal_uInt16 nLevel = 0; + for (sal_uInt16 nTP=0; nTP<nTokens; nTP++) + { + formula::FormulaToken* pTok = ppToken[nTP]; + OpCode eOp = pTok->GetOpCode(); + if ( eOp == ocOpen ) + ++nLevel; + else if ( eOp == ocClose && nLevel ) + --nLevel; + if ( nLevel == 0 && pTok->IsFunction() && + lcl_AddFunction( aAppOpt, sal::static_int_cast<sal_uInt16>( eOp ) ) ) + bOptChanged = sal_True; + } + + if ( bOptChanged ) + { + pScMod->SetAppOptions(aAppOpt); + pScMod->RecentFunctionsChanged(); + } + } + + ScFormulaCell aCell( pDoc, aPos, pArr,formula::FormulaGrammar::GRAM_DEFAULT, MM_NONE ); + delete pArr; + sal_Bool bAutoCalc = pDoc->GetAutoCalc(); + SvNumberFormatter* pFormatter = pDoc->GetFormatTable(); + for ( ; i<nTabCount; i++) + { + if (rMark.GetTableSelect(i)) + { + aPos.SetTab( i ); + sal_uLong nIndex = (sal_uLong) ((SfxUInt32Item*) pDoc->GetAttr( + nCol, nRow, i, ATTR_VALUE_FORMAT ))->GetValue(); + if ( pFormatter->GetType( nIndex ) == NUMBERFORMAT_TEXT || + ( ( rString.GetChar(0) == '+' || rString.GetChar(0) == '-' ) && nError && rString.Equals( aFormula ) ) ) + { + if ( pData ) + { + ScEditCell* pCell = new ScEditCell( pData, pDoc, NULL ); + pDoc->PutCell( aPos, pCell ); + } + else + { + ScStringCell* pCell = new ScStringCell( aFormula ); + pDoc->PutCell( aPos, pCell ); + } + } + else + { + DELETEZ(pUndoData); + ScFormulaCell* pCell = new ScFormulaCell( aCell, *pDoc, aPos ); + if ( nError ) + { + pCell->GetCode()->DelRPN(); + pCell->SetErrCode( nError ); + if(pCell->GetCode()->IsHyperLink()) + pCell->GetCode()->SetHyperLink(sal_False); + } + pDoc->PutCell( aPos, pCell ); + if ( !bAutoCalc ) + { // einmal nur die Zelle berechnen und wieder dirty setzen + pCell->Interpret(); + pCell->SetDirtyVar(); + pDoc->PutInFormulaTree( pCell ); + } + } + + } + } + } + else + { + for (i=0; i<nTabCount; i++) + if (rMark.GetTableSelect(i)) + if (pDoc->SetString( nCol, nRow, i, rString )) + bNumFmtChanged = sal_True; + } + + // row height must be changed if new text has a different script type + for (i=0; i<nTabCount && !bEditDeleted; i++) + if (rMark.GetTableSelect(i)) + if ( pDoc->GetScriptType( nCol, nRow, i ) != nOldScript ) + bEditDeleted = sal_True; + + HideAllCursors(); + + if (bEditDeleted || pDoc->HasAttrib( nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_NEEDHEIGHT )) + AdjustRowHeight(nRow,nRow); + + sal_Bool bAutoFormat = TestFormatArea(nCol, nRow, nTab, bNumFmtChanged); + if (bAutoFormat) + DoAutoAttributes(nCol, nRow, nTab, bNumFmtChanged, bRecord); + + if ( bRecord ) + { // wg. ChangeTrack erst jetzt + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoEnterData( pDocSh, nCol, nRow, nTab, nUndoPos, pTabs, + ppOldCells, pHasFormat, pOldFormats, + rString, pUndoData ) ); + } + + for (i=0; i<nTabCount; i++) + if (rMark.GetTableSelect(i)) + pDocSh->PostPaintCell( nCol, nRow, i ); + + ShowAllCursors(); + + pDocSh->UpdateOle(GetViewData()); + + // #i97876# Spreadsheet data changes are not notified + ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() ); + if ( pModelObj && pModelObj->HasChangesListeners() ) + { + ScRangeList aChangeRanges; + for ( i = 0; i < nTabCount; ++i ) + { + if ( rMark.GetTableSelect( i ) ) + { + aChangeRanges.Append( ScRange( nCol, nRow, i ) ); + } + } + pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges ); + } + + aModificator.SetDocumentModified(); + } + else + { + ErrorMessage(aTester.GetMessageId()); + PaintArea( nCol, nRow, nCol, nRow ); // da steht evtl. noch die Edit-Engine + } +} + +// Wert in einzele Zelle eintragen (nur auf nTab) + +void ScViewFunc::EnterValue( SCCOL nCol, SCROW nRow, SCTAB nTab, const double& rValue ) +{ + ScDocument* pDoc = GetViewData()->GetDocument(); + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + sal_Bool bUndo (pDoc->IsUndoEnabled()); + + if ( pDoc && pDocSh ) + { + ScDocShellModificator aModificator( *pDocSh ); + + ScEditableTester aTester( pDoc, nTab, nCol,nRow, nCol,nRow ); + if (aTester.IsEditable()) + { + ScAddress aPos( nCol, nRow, nTab ); + ScBaseCell* pOldCell = pDoc->GetCell( aPos ); + sal_Bool bNeedHeight = ( pOldCell && pOldCell->GetCellType() == CELLTYPE_EDIT ) + || pDoc->HasAttrib( + nCol,nRow,nTab, nCol,nRow,nTab, HASATTR_NEEDHEIGHT ); + + // Undo + ScBaseCell* pUndoCell = (bUndo && pOldCell) ? pOldCell->CloneWithoutNote( *pDoc ) : 0; + + pDoc->SetValue( nCol, nRow, nTab, rValue ); + + // wg. ChangeTrack nach Aenderung im Dokument + if (bUndo) + { + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoEnterValue( pDocSh, aPos, pUndoCell, rValue, bNeedHeight ) ); + } + +/*! Zeilenhoehe anpassen? Dann auch bei Undo... + if (bNeedHeight) + AdjustRowHeight(nRow,nRow); +*/ + + pDocSh->PostPaintCell( aPos ); + pDocSh->UpdateOle(GetViewData()); + aModificator.SetDocumentModified(); + } + else + ErrorMessage(aTester.GetMessageId()); + } +} + +void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const EditTextObject* pData, + sal_Bool bRecord, sal_Bool bTestSimple ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + ScDocument* pDoc = pDocSh->GetDocument(); + if (bRecord && !pDoc->IsUndoEnabled()) + bRecord = sal_False; + + ScDocShellModificator aModificator( *pDocSh ); + + ScEditableTester aTester( pDoc, nTab, nCol,nRow, nCol,nRow ); + if (aTester.IsEditable()) + { + // + // Test auf Attribute + // + sal_Bool bSimple = sal_False; + sal_Bool bCommon = sal_False; + ScPatternAttr* pCellAttrs = NULL; + EditTextObject* pNewData = NULL; + String aString; + + const ScPatternAttr* pOldPattern = pDoc->GetPattern( nCol, nRow, nTab ); + ScTabEditEngine aEngine( *pOldPattern, pDoc->GetEnginePool() ); + aEngine.SetText(*pData); + + if (bTestSimple) // Testen, ob einfacher String ohne Attribute + { + ScEditAttrTester aAttrTester( &aEngine ); + bSimple = !aAttrTester.NeedsObject(); + bCommon = aAttrTester.NeedsCellAttr(); + + // formulas have to be recognized even if they're formatted + // (but commmon attributes are still collected) + + if ( !bSimple && aEngine.GetParagraphCount() == 1 ) + { + String aParStr = aEngine.GetText( (sal_uInt16) 0 ); + if ( aParStr.GetChar(0) == '=' ) + bSimple = sal_True; + } + + if (bCommon) // Attribute fuer Tabelle + { + pCellAttrs = new ScPatternAttr( *pOldPattern ); + pCellAttrs->GetFromEditItemSet( &aAttrTester.GetAttribs() ); + //! remove common attributes from EditEngine? + } + } + + // #i97726# always get text for "repeat" of undo action + aString = ScEditUtil::GetSpaceDelimitedString(aEngine); + + // + // Undo + // + + SCTAB nTabCount = pDoc->GetTableCount(); + SCTAB nSelCount = rMark.GetSelectCount(); + SCTAB i; + ScBaseCell** ppOldCells = NULL; + SCTAB* pTabs = NULL; + SCTAB nPos = 0; + EditTextObject* pUndoData = NULL; + if (bRecord && !bSimple) + { + ppOldCells = new ScBaseCell*[nSelCount]; + pTabs = new SCTAB[nSelCount]; + nPos = 0; + + for (i=0; i<nTabCount; i++) + if (rMark.GetTableSelect(i)) + { + pTabs[nPos] = i; + ScBaseCell* pDocCell; + pDoc->GetCell( nCol, nRow, i, pDocCell ); + ppOldCells[nPos] = pDocCell ? pDocCell->CloneWithoutNote( *pDoc ) : 0; + ++nPos; + } + + DBG_ASSERT( nPos==nSelCount, "nPos!=nSelCount" ); + + pUndoData = pData->Clone(); + } + + // + // Daten eintragen + // + + if (bCommon) + pDoc->ApplyPattern(nCol,nRow,nTab,*pCellAttrs); //! Undo + + if (bSimple) + { + if (bCommon) + AdjustRowHeight(nRow,nRow); + + EnterData(nCol,nRow,nTab,aString,bRecord); + } + else + { + for (i=0; i<nTabCount; i++) + if (rMark.GetTableSelect(i)) + pDoc->PutCell( nCol, nRow, i, new ScEditCell( pData, pDoc, NULL ) ); + + if ( bRecord ) + { // wg. ChangeTrack erst jetzt + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoEnterData( pDocSh, nCol, nRow, nTab, nPos, pTabs, + ppOldCells, NULL, NULL, aString, + pUndoData ) ); + } + + HideAllCursors(); + + AdjustRowHeight(nRow,nRow); + + for (i=0; i<nTabCount; i++) + if (rMark.GetTableSelect(i)) + pDocSh->PostPaintCell( nCol, nRow, i ); + + ShowAllCursors(); + + pDocSh->UpdateOle(GetViewData()); + + // #i97876# Spreadsheet data changes are not notified + ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() ); + if ( pModelObj && pModelObj->HasChangesListeners() ) + { + ScRangeList aChangeRanges; + for ( i = 0; i < nTabCount; ++i ) + { + if ( rMark.GetTableSelect( i ) ) + { + aChangeRanges.Append( ScRange( nCol, nRow, i ) ); + } + } + pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges ); + } + + aModificator.SetDocumentModified(); + } + + delete pCellAttrs; + delete pNewData; + } + else + { + ErrorMessage(aTester.GetMessageId()); + PaintArea( nCol, nRow, nCol, nRow ); // da steht evtl. noch die Edit-Engine + } +} + +void ScViewFunc::EnterDataAtCursor( const String& rString ) +{ + SCCOL nPosX = GetViewData()->GetCurX(); + SCROW nPosY = GetViewData()->GetCurY(); + SCTAB nTab = GetViewData()->GetTabNo(); + + EnterData( nPosX, nPosY, nTab, rString ); +} + +void ScViewFunc::EnterMatrix( const String& rString ) +{ + ScViewData* pData = GetViewData(); + const ScMarkData& rMark = pData->GetMarkData(); + if ( !rMark.IsMarked() && !rMark.IsMultiMarked() ) + { + // nichts markiert -> automatisch Block mit Groesse des Ergebnisses + // Formel temporaer berechnen, um an die Groesse heranzukommen + + ScDocument* pDoc = pData->GetDocument(); + SCCOL nCol = pData->GetCurX(); + SCROW nRow = pData->GetCurY(); + SCTAB nTab = pData->GetTabNo(); + ScFormulaCell aFormCell( pDoc, ScAddress(nCol,nRow,nTab), rString,formula::FormulaGrammar::GRAM_DEFAULT, MM_FORMULA ); + + SCSIZE nSizeX; + SCSIZE nSizeY; + aFormCell.GetResultDimensions( nSizeX, nSizeY ); + if ( nSizeX != 0 && nSizeY != 0 && + nCol+nSizeX-1 <= sal::static_int_cast<SCSIZE>(MAXCOL) && + nRow+nSizeY-1 <= sal::static_int_cast<SCSIZE>(MAXROW) ) + { + ScRange aResult( nCol, nRow, nTab, + sal::static_int_cast<SCCOL>(nCol+nSizeX-1), + sal::static_int_cast<SCROW>(nRow+nSizeY-1), nTab ); + MarkRange( aResult, sal_False ); + } + } + + ScRange aRange; + if (pData->GetSimpleArea(aRange) == SC_MARK_SIMPLE) + { + ScDocShell* pDocSh = pData->GetDocShell(); + sal_Bool bSuccess = pDocSh->GetDocFunc().EnterMatrix( aRange, &rMark, NULL, rString, sal_False, sal_False, EMPTY_STRING, formula::FormulaGrammar::GRAM_DEFAULT ); + if (bSuccess) + pDocSh->UpdateOle(GetViewData()); + } + else + ErrorMessage(STR_NOMULTISELECT); +} + +sal_uInt8 ScViewFunc::GetSelectionScriptType() +{ + sal_uInt8 nScript = 0; + + ScDocument* pDoc = GetViewData()->GetDocument(); + const ScMarkData& rMark = GetViewData()->GetMarkData(); + if ( !rMark.IsMarked() && !rMark.IsMultiMarked() ) + { + // no selection -> cursor + + nScript = pDoc->GetScriptType( GetViewData()->GetCurX(), + GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); + } + else + { + ScRangeList aRanges; + rMark.FillRangeListWithMarks( &aRanges, sal_False ); + sal_uLong nCount = aRanges.Count(); + for (sal_uLong i=0; i<nCount; i++) + { + ScRange aRange = *aRanges.GetObject(i); + ScCellIterator aIter( pDoc, aRange ); + ScBaseCell* pCell = aIter.GetFirst(); + while ( pCell ) + { + nScript |= pDoc->GetScriptType( aIter.GetCol(), aIter.GetRow(), aIter.GetTab(), pCell ); + pCell = aIter.GetNext(); + } + } + } + + if (nScript == 0) + nScript = ScGlobal::GetDefaultScriptType(); + + return nScript; +} + +const ScPatternAttr* ScViewFunc::GetSelectionPattern() +{ + // Don't use UnmarkFiltered in slot state functions, for performance reasons. + // The displayed state is always that of the whole selection including filtered rows. + + const ScMarkData& rMark = GetViewData()->GetMarkData(); + ScDocument* pDoc = GetViewData()->GetDocument(); + if ( rMark.IsMarked() || rMark.IsMultiMarked() ) + { + // MarkToMulti is no longer necessary for pDoc->GetSelectionPattern + const ScPatternAttr* pAttr = pDoc->GetSelectionPattern( rMark ); + return pAttr; + } + else + { + SCCOL nCol = GetViewData()->GetCurX(); + SCROW nRow = GetViewData()->GetCurY(); + SCTAB nTab = GetViewData()->GetTabNo(); + + ScMarkData aTempMark( rMark ); // copy sheet selection + aTempMark.SetMarkArea( ScRange( nCol, nRow, nTab ) ); + const ScPatternAttr* pAttr = pDoc->GetSelectionPattern( aTempMark ); + return pAttr; + } +} + +void ScViewFunc::GetSelectionFrame( SvxBoxItem& rLineOuter, + SvxBoxInfoItem& rLineInner ) +{ + ScDocument* pDoc = GetViewData()->GetDocument(); + const ScMarkData& rMark = GetViewData()->GetMarkData(); + + if ( rMark.IsMarked() || rMark.IsMultiMarked() ) + { + if ( rMark.IsMultiMarked() ) + { + ScMarkData aNewMark( rMark ); // use local copy for MarkToSimple + aNewMark.MarkToSimple(); // simple block is needed for GetSelectionFrame + pDoc->GetSelectionFrame( aNewMark, rLineOuter, rLineInner ); + } + else + pDoc->GetSelectionFrame( rMark, rLineOuter, rLineInner ); + } + else + { + const ScPatternAttr* pAttrs = + pDoc->GetPattern( GetViewData()->GetCurX(), + GetViewData()->GetCurY(), + GetViewData()->GetTabNo() ); + + rLineOuter = (const SvxBoxItem&) (pAttrs->GetItem( ATTR_BORDER )); + rLineInner = (const SvxBoxInfoItem&)(pAttrs->GetItem( ATTR_BORDER_INNER )); + rLineInner.SetTable(sal_False); + rLineInner.SetDist(sal_True); + rLineInner.SetMinDist(sal_False); + } +} + +// +// Attribute anwenden - Undo OK +// +// kompletter Set ( ATTR_STARTINDEX, ATTR_ENDINDEX ) +// + +void ScViewFunc::ApplyAttributes( const SfxItemSet* pDialogSet, + const SfxItemSet* pOldSet, + sal_Bool bRecord ) +{ + // nur wegen Matrix nicht editierbar? Attribute trotzdem ok + sal_Bool bOnlyNotBecauseOfMatrix; + if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix ) + { + ErrorMessage(STR_PROTECTIONERR); + return; + } + + ScPatternAttr aOldAttrs( new SfxItemSet(*pOldSet) ); + ScPatternAttr aNewAttrs( new SfxItemSet(*pDialogSet) ); + aNewAttrs.DeleteUnchanged( &aOldAttrs ); + + if ( pDialogSet->GetItemState( ATTR_VALUE_FORMAT ) == SFX_ITEM_SET ) + { // #82521# don't reset to default SYSTEM GENERAL if not intended + sal_uInt32 nOldFormat = + ((const SfxUInt32Item&)pOldSet->Get( ATTR_VALUE_FORMAT )).GetValue(); + sal_uInt32 nNewFormat = + ((const SfxUInt32Item&)pDialogSet->Get( ATTR_VALUE_FORMAT )).GetValue(); + if ( nNewFormat != nOldFormat ) + { + SvNumberFormatter* pFormatter = + GetViewData()->GetDocument()->GetFormatTable(); + const SvNumberformat* pOldEntry = pFormatter->GetEntry( nOldFormat ); + LanguageType eOldLang = + pOldEntry ? pOldEntry->GetLanguage() : LANGUAGE_DONTKNOW; + const SvNumberformat* pNewEntry = pFormatter->GetEntry( nNewFormat ); + LanguageType eNewLang = + pNewEntry ? pNewEntry->GetLanguage() : LANGUAGE_DONTKNOW; + if ( eNewLang != eOldLang ) + { + aNewAttrs.GetItemSet().Put( + SvxLanguageItem( eNewLang, ATTR_LANGUAGE_FORMAT ) ); + + // #40606# nur die Sprache geaendert -> Zahlformat-Attribut nicht anfassen + sal_uInt32 nNewMod = nNewFormat % SV_COUNTRY_LANGUAGE_OFFSET; + if ( nNewMod == ( nOldFormat % SV_COUNTRY_LANGUAGE_OFFSET ) && + nNewMod <= SV_MAX_ANZ_STANDARD_FORMATE ) + aNewAttrs.GetItemSet().ClearItem( ATTR_VALUE_FORMAT ); + } + } + } + + const SvxBoxItem* pOldOuter = (const SvxBoxItem*) &pOldSet->Get( ATTR_BORDER ); + const SvxBoxItem* pNewOuter = (const SvxBoxItem*) &pDialogSet->Get( ATTR_BORDER ); + const SvxBoxInfoItem* pOldInner = (const SvxBoxInfoItem*) &pOldSet->Get( ATTR_BORDER_INNER ); + const SvxBoxInfoItem* pNewInner = (const SvxBoxInfoItem*) &pDialogSet->Get( ATTR_BORDER_INNER ); + SfxItemSet& rNewSet = aNewAttrs.GetItemSet(); + SfxItemPool* pNewPool = rNewSet.GetPool(); + + pNewPool->Put( *pNewOuter ); // noch nicht loeschen + pNewPool->Put( *pNewInner ); + rNewSet.ClearItem( ATTR_BORDER ); + rNewSet.ClearItem( ATTR_BORDER_INNER ); + + /* + * Feststellen, ob Rahmenattribute zu setzen sind: + * 1. Neu != Alt + * 2. Ist eine der Linien nicht-DontCare (seit 238.f: IsxxValid()) + * + */ + + sal_Bool bFrame = (pDialogSet->GetItemState( ATTR_BORDER ) != SFX_ITEM_DEFAULT) + || (pDialogSet->GetItemState( ATTR_BORDER_INNER ) != SFX_ITEM_DEFAULT); + + if ( pNewOuter==pOldOuter && pNewInner==pOldInner ) + bFrame = sal_False; + + // das sollte doch der Pool abfangen: ?!??!?? + + if ( bFrame && pNewOuter && pNewInner ) + if ( *pNewOuter == *pOldOuter && *pNewInner == *pOldInner ) + bFrame = sal_False; + + if ( pNewInner ) + { + bFrame = bFrame + && ( pNewInner->IsValid(VALID_LEFT) + || pNewInner->IsValid(VALID_RIGHT) + || pNewInner->IsValid(VALID_TOP) + || pNewInner->IsValid(VALID_BOTTOM) + || pNewInner->IsValid(VALID_HORI) + || pNewInner->IsValid(VALID_VERT) ); + } + else + bFrame = sal_False; + + if (!bFrame) + ApplySelectionPattern( aNewAttrs, bRecord ); // nur normale + else + { + // wenn neue Items Default-Items sind, so muessen die + // alten Items geputtet werden: + + sal_Bool bDefNewOuter = ( SFX_ITEMS_STATICDEFAULT == pNewOuter->GetKind() ); + sal_Bool bDefNewInner = ( SFX_ITEMS_STATICDEFAULT == pNewInner->GetKind() ); + + ApplyPatternLines( aNewAttrs, + bDefNewOuter ? pOldOuter : pNewOuter, + bDefNewInner ? pOldInner : pNewInner, + bRecord ); + } + + pNewPool->Remove( *pNewOuter ); // freigeben + pNewPool->Remove( *pNewInner ); + + // Hoehen anpassen + AdjustBlockHeight(); + + // CellContentChanged wird von ApplySelectionPattern / ApplyPatternLines gerufen +} + +void ScViewFunc::ApplyAttr( const SfxPoolItem& rAttrItem ) +{ + // nur wegen Matrix nicht editierbar? Attribute trotzdem ok + sal_Bool bOnlyNotBecauseOfMatrix; + if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix ) + { + ErrorMessage(STR_PROTECTIONERR); + return; + } + + ScPatternAttr aNewAttrs( new SfxItemSet( *GetViewData()->GetDocument()->GetPool(), + ATTR_PATTERN_START, ATTR_PATTERN_END ) ); + + aNewAttrs.GetItemSet().Put( rAttrItem ); + // Wenn Ausrichtung eingestellt wird (ueber Buttons), immer Einzug 0 + if ( rAttrItem.Which() == ATTR_HOR_JUSTIFY ) + aNewAttrs.GetItemSet().Put( SfxUInt16Item( ATTR_INDENT, 0 ) ); + ApplySelectionPattern( aNewAttrs ); + + AdjustBlockHeight(); + + // CellContentChanged wird von ApplySelectionPattern gerufen +} + + +// Pattern und Rahmen + +void ScViewFunc::ApplyPatternLines( const ScPatternAttr& rAttr, const SvxBoxItem* pNewOuter, + const SvxBoxInfoItem* pNewInner, sal_Bool bRecord ) +{ + ScDocument* pDoc = GetViewData()->GetDocument(); + ScMarkData aFuncMark( GetViewData()->GetMarkData() ); // local copy for UnmarkFiltered + ScViewUtil::UnmarkFiltered( aFuncMark, pDoc ); + if (bRecord && !pDoc->IsUndoEnabled()) + bRecord = sal_False; + + ScRange aMarkRange; + aFuncMark.MarkToSimple(); + sal_Bool bMulti = aFuncMark.IsMultiMarked(); + if (bMulti) + aFuncMark.GetMultiMarkArea( aMarkRange ); + else if (aFuncMark.IsMarked()) + aFuncMark.GetMarkArea( aMarkRange ); + else + { + aMarkRange = ScRange( GetViewData()->GetCurX(), + GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); + DoneBlockMode(); + InitOwnBlockMode(); + aFuncMark.SetMarkArea(aMarkRange); + MarkDataChanged(); + } + + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + + ScDocShellModificator aModificator( *pDocSh ); + + if (bRecord) + { + ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + SCTAB nStartTab = aMarkRange.aStart.Tab(); + SCTAB nTabCount = pDoc->GetTableCount(); + pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab ); + for (SCTAB i=0; i<nTabCount; i++) + if (i != nStartTab && aFuncMark.GetTableSelect(i)) + pUndoDoc->AddUndoTab( i, i ); + + ScRange aCopyRange = aMarkRange; + aCopyRange.aStart.SetTab(0); + aCopyRange.aEnd.SetTab(nTabCount-1); + pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, bMulti, pUndoDoc, &aFuncMark ); + + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoSelectionAttr( + pDocSh, aFuncMark, + aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), aMarkRange.aStart.Tab(), + aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), aMarkRange.aEnd.Tab(), + pUndoDoc, bMulti, &rAttr, pNewOuter, pNewInner ) ); + } + + sal_uInt16 nExt = SC_PF_TESTMERGE; + pDocSh->UpdatePaintExt( nExt, aMarkRange ); // content before the change + + pDoc->ApplySelectionFrame( aFuncMark, pNewOuter, pNewInner ); + + pDocSh->UpdatePaintExt( nExt, aMarkRange ); // content after the change + + aFuncMark.MarkToMulti(); + pDoc->ApplySelectionPattern( rAttr, aFuncMark ); + + pDocSh->PostPaint( aMarkRange, PAINT_GRID, nExt ); + pDocSh->UpdateOle(GetViewData()); + aModificator.SetDocumentModified(); + CellContentChanged(); + + StartFormatArea(); +} + +// nur Pattern + +void ScViewFunc::ApplySelectionPattern( const ScPatternAttr& rAttr, + sal_Bool bRecord, sal_Bool bCursorOnly ) +{ + ScViewData* pViewData = GetViewData(); + ScDocShell* pDocSh = pViewData->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + ScMarkData aFuncMark( pViewData->GetMarkData() ); // local copy for UnmarkFiltered + ScViewUtil::UnmarkFiltered( aFuncMark, pDoc ); + + if (bRecord && !pDoc->IsUndoEnabled()) + bRecord = sal_False; + + // State from old ItemSet doesn't matter for paint flags, as any change will be + // from SFX_ITEM_SET in the new ItemSet (default is ignored in ApplyPattern). + // New alignment is checked (check in PostPaint isn't enough) in case a right + // alignment is changed to left. + const SfxItemSet& rNewSet = rAttr.GetItemSet(); + sal_Bool bSetLines = rNewSet.GetItemState( ATTR_BORDER, sal_True ) == SFX_ITEM_SET || + rNewSet.GetItemState( ATTR_SHADOW, sal_True ) == SFX_ITEM_SET; + sal_Bool bSetAlign = rNewSet.GetItemState( ATTR_HOR_JUSTIFY, sal_True ) == SFX_ITEM_SET; + + sal_uInt16 nExtFlags = 0; + if ( bSetLines ) + nExtFlags |= SC_PF_LINES; + if ( bSetAlign ) + nExtFlags |= SC_PF_WHOLEROWS; + + ScDocShellModificator aModificator( *pDocSh ); + + sal_Bool bMulti = aFuncMark.IsMultiMarked(); + aFuncMark.MarkToMulti(); + sal_Bool bOnlyTab = (!aFuncMark.IsMultiMarked() && !bCursorOnly && aFuncMark.GetSelectCount() > 1); + if (bOnlyTab) + { + SCCOL nCol = pViewData->GetCurX(); + SCROW nRow = pViewData->GetCurY(); + SCTAB nTab = pViewData->GetTabNo(); + aFuncMark.SetMarkArea(ScRange(nCol,nRow,nTab)); + aFuncMark.MarkToMulti(); + } + + ScRangeList aChangeRanges; + + if (aFuncMark.IsMultiMarked() && !bCursorOnly) + { + ScRange aMarkRange; + aFuncMark.GetMultiMarkArea( aMarkRange ); + SCTAB nTabCount = pDoc->GetTableCount(); + for ( SCTAB i = 0; i < nTabCount; ++i ) + { + if ( aFuncMark.GetTableSelect( i ) ) + { + ScRange aChangeRange( aMarkRange ); + aChangeRange.aStart.SetTab( i ); + aChangeRange.aEnd.SetTab( i ); + aChangeRanges.Append( aChangeRange ); + } + } + + SCCOL nStartCol = aMarkRange.aStart.Col(); + SCROW nStartRow = aMarkRange.aStart.Row(); + SCTAB nStartTab = aMarkRange.aStart.Tab(); + SCCOL nEndCol = aMarkRange.aEnd.Col(); + SCROW nEndRow = aMarkRange.aEnd.Row(); + SCTAB nEndTab = aMarkRange.aEnd.Tab(); + + if (bRecord) + { + ScRange aCopyRange = aMarkRange; + aCopyRange.aStart.SetTab(0); + aCopyRange.aEnd.SetTab(nTabCount-1); + + ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab ); + for (SCTAB i=0; i<nTabCount; i++) + if (i != nStartTab && aFuncMark.GetTableSelect(i)) + pUndoDoc->AddUndoTab( i, i ); + pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, bMulti, pUndoDoc, &aFuncMark ); + + aFuncMark.MarkToMulti(); + + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoSelectionAttr( + pDocSh, aFuncMark, + nStartCol, nStartRow, nStartTab, + nEndCol, nEndRow, nEndTab, + pUndoDoc, bMulti, &rAttr ) ); + } + + pDoc->ApplySelectionPattern( rAttr, aFuncMark ); + + pDocSh->PostPaint( nStartCol, nStartRow, nStartTab, + nEndCol, nEndRow, nEndTab, + PAINT_GRID, nExtFlags | SC_PF_TESTMERGE ); + pDocSh->UpdateOle(GetViewData()); + aModificator.SetDocumentModified(); + CellContentChanged(); + } + else // einzelne Zelle - Undo einfacher + { + SCCOL nCol = pViewData->GetCurX(); + SCROW nRow = pViewData->GetCurY(); + SCTAB nTab = pViewData->GetTabNo(); + aChangeRanges.Append( ScRange( nCol, nRow, nTab ) ); + ScPatternAttr* pOldPat = new ScPatternAttr(*pDoc->GetPattern( nCol, nRow, nTab )); + + pDoc->ApplyPattern( nCol, nRow, nTab, rAttr ); + + const ScPatternAttr* pNewPat = pDoc->GetPattern( nCol, nRow, nTab ); + + if (bRecord) + { + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoCursorAttr( pDocSh, + nCol, nRow, nTab, + pOldPat, pNewPat, &rAttr, + sal_False ) ); // sal_False = nicht automatisch + } + delete pOldPat; // wird im Undo kopiert (Pool) + + pDocSh->PostPaint( nCol,nRow,nTab, nCol,nRow,nTab, PAINT_GRID, nExtFlags | SC_PF_TESTMERGE ); + pDocSh->UpdateOle(GetViewData()); + aModificator.SetDocumentModified(); + CellContentChanged(); + } + + // #i97876# Spreadsheet data changes are not notified + ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() ); + if ( pModelObj && pModelObj->HasChangesListeners() ) + { + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aProperties; + sal_Int32 nCount = 0; + const SfxItemPropertyMap* pMap = ScCellObj::GetCellPropertyMap(); + PropertyEntryVector_t aPropVector = pMap->getPropertyEntries(); + for ( sal_uInt16 nWhich = ATTR_PATTERN_START; nWhich <= ATTR_PATTERN_END; ++nWhich ) + { + const SfxPoolItem* pItem = 0; + if ( rNewSet.GetItemState( nWhich, sal_True, &pItem ) == SFX_ITEM_SET && pItem ) + { + PropertyEntryVector_t::const_iterator aIt = aPropVector.begin(); + while ( aIt != aPropVector.end()) + { + if ( aIt->nWID == nWhich ) + { + ::com::sun::star::uno::Any aVal; + pItem->QueryValue( aVal, aIt->nMemberId ); + aProperties.realloc( nCount + 1 ); + aProperties[ nCount ].Name = aIt->sName; + aProperties[ nCount ].Value <<= aVal; + ++nCount; + } + ++aIt; + } + } + } + pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "attribute" ) ), aChangeRanges, aProperties ); + } + + StartFormatArea(); +} + +void ScViewFunc::ApplyUserItemSet( const SfxItemSet& rItemSet ) +{ + // ItemSet from UI, may have different pool + + sal_Bool bOnlyNotBecauseOfMatrix; + if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix ) + { + ErrorMessage(STR_PROTECTIONERR); + return; + } + + ScPatternAttr aNewAttrs( GetViewData()->GetDocument()->GetPool() ); + SfxItemSet& rNewSet = aNewAttrs.GetItemSet(); + rNewSet.Put( rItemSet, sal_False ); + ApplySelectionPattern( aNewAttrs ); + + AdjustBlockHeight(); +} + +const SfxStyleSheet* ScViewFunc::GetStyleSheetFromMarked() +{ + // Don't use UnmarkFiltered in slot state functions, for performance reasons. + // The displayed state is always that of the whole selection including filtered rows. + + const ScStyleSheet* pSheet = NULL; + ScViewData* pViewData = GetViewData(); + ScDocument* pDoc = pViewData->GetDocument(); + ScMarkData& rMark = pViewData->GetMarkData(); + + if ( rMark.IsMarked() || rMark.IsMultiMarked() ) + pSheet = pDoc->GetSelectionStyle( rMark ); // MarkToMulti isn't necessary + else + pSheet = pDoc->GetStyle( pViewData->GetCurX(), + pViewData->GetCurY(), + pViewData->GetTabNo() ); + + return pSheet; +} + +void ScViewFunc::SetStyleSheetToMarked( SfxStyleSheet* pStyleSheet, sal_Bool bRecord ) +{ + // nur wegen Matrix nicht editierbar? Attribute trotzdem ok + sal_Bool bOnlyNotBecauseOfMatrix; + if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix ) + { + ErrorMessage(STR_PROTECTIONERR); + return; + } + + if ( !pStyleSheet) return; + // ------------------------------------------------------------------- + + ScViewData* pViewData = GetViewData(); + ScDocShell* pDocSh = pViewData->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + ScMarkData aFuncMark( pViewData->GetMarkData() ); // local copy for UnmarkFiltered + ScViewUtil::UnmarkFiltered( aFuncMark, pDoc ); + SCTAB nTabCount = pDoc->GetTableCount(); + if (bRecord && !pDoc->IsUndoEnabled()) + bRecord = sal_False; + + ScDocShellModificator aModificator( *pDocSh ); + + if ( aFuncMark.IsMarked() || aFuncMark.IsMultiMarked() ) + { + ScRange aMarkRange; + aFuncMark.MarkToMulti(); + aFuncMark.GetMultiMarkArea( aMarkRange ); + + if ( bRecord ) + { + SCTAB nTab = pViewData->GetTabNo(); + ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + pUndoDoc->InitUndo( pDoc, nTab, nTab ); + for (SCTAB i=0; i<nTabCount; i++) + if (i != nTab && aFuncMark.GetTableSelect(i)) + pUndoDoc->AddUndoTab( i, i ); + + ScRange aCopyRange = aMarkRange; + aCopyRange.aStart.SetTab(0); + aCopyRange.aEnd.SetTab(nTabCount-1); + pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, sal_True, pUndoDoc, &aFuncMark ); + aFuncMark.MarkToMulti(); + + String aName = pStyleSheet->GetName(); + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoSelectionStyle( pDocSh, aFuncMark, aMarkRange, aName, pUndoDoc ) ); + } + + pDoc->ApplySelectionStyle( (ScStyleSheet&)*pStyleSheet, aFuncMark ); + + if (!AdjustBlockHeight()) + pViewData->GetDocShell()->PostPaint( aMarkRange, PAINT_GRID ); + + aFuncMark.MarkToSimple(); + } + else + { + SCCOL nCol = pViewData->GetCurX(); + SCROW nRow = pViewData->GetCurY(); + SCTAB nTab = pViewData->GetTabNo(); + + if ( bRecord ) + { + ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + pUndoDoc->InitUndo( pDoc, nTab, nTab ); + for (SCTAB i=0; i<nTabCount; i++) + if (i != nTab && aFuncMark.GetTableSelect(i)) + pUndoDoc->AddUndoTab( i, i ); + + ScRange aCopyRange( nCol, nRow, 0, nCol, nRow, nTabCount-1 ); + pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, sal_False, pUndoDoc ); + + ScRange aMarkRange ( nCol, nRow, nTab ); + ScMarkData aUndoMark = aFuncMark; + aUndoMark.SetMultiMarkArea( aMarkRange ); + + String aName = pStyleSheet->GetName(); + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoSelectionStyle( pDocSh, aUndoMark, aMarkRange, aName, pUndoDoc ) ); + } + + for (SCTAB i=0; i<nTabCount; i++) + if (aFuncMark.GetTableSelect(i)) + pDoc->ApplyStyle( nCol, nRow, i, (ScStyleSheet&)*pStyleSheet ); + + if (!AdjustBlockHeight()) + pViewData->GetDocShell()->PostPaintCell( nCol, nRow, nTab ); + + } + + aModificator.SetDocumentModified(); + + StartFormatArea(); +} + + +void ScViewFunc::RemoveStyleSheetInUse( const SfxStyleSheetBase* pStyleSheet ) +{ + if ( !pStyleSheet) return; + // ------------------------------------------------------------------- + + ScViewData* pViewData = GetViewData(); + ScDocument* pDoc = pViewData->GetDocument(); + ScDocShell* pDocSh = pViewData->GetDocShell(); + + ScDocShellModificator aModificator( *pDocSh ); + + VirtualDevice aVirtDev; + aVirtDev.SetMapMode(MAP_PIXEL); + pDoc->StyleSheetChanged( pStyleSheet, sal_True, &aVirtDev, + pViewData->GetPPTX(), + pViewData->GetPPTY(), + pViewData->GetZoomX(), + pViewData->GetZoomY() ); + + pDocSh->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID|PAINT_LEFT ); + aModificator.SetDocumentModified(); + + ScInputHandler* pHdl = SC_MOD()->GetInputHdl(); + if (pHdl) + pHdl->ForgetLastPattern(); +} + +void ScViewFunc::UpdateStyleSheetInUse( const SfxStyleSheetBase* pStyleSheet ) +{ + if ( !pStyleSheet) return; + // ------------------------------------------------------------------- + + ScViewData* pViewData = GetViewData(); + ScDocument* pDoc = pViewData->GetDocument(); + ScDocShell* pDocSh = pViewData->GetDocShell(); + + ScDocShellModificator aModificator( *pDocSh ); + + VirtualDevice aVirtDev; + aVirtDev.SetMapMode(MAP_PIXEL); + pDoc->StyleSheetChanged( pStyleSheet, sal_False, &aVirtDev, + pViewData->GetPPTX(), + pViewData->GetPPTY(), + pViewData->GetZoomX(), + pViewData->GetZoomY() ); + + pDocSh->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID|PAINT_LEFT ); + aModificator.SetDocumentModified(); + + ScInputHandler* pHdl = SC_MOD()->GetInputHdl(); + if (pHdl) + pHdl->ForgetLastPattern(); +} + +// Zellen einfuegen - Undo OK + +sal_Bool ScViewFunc::InsertCells( InsCellCmd eCmd, sal_Bool bRecord, sal_Bool bPartOfPaste ) +{ + ScRange aRange; + if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE) + { + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + const ScMarkData& rMark = GetViewData()->GetMarkData(); + sal_Bool bSuccess = pDocSh->GetDocFunc().InsertCells( aRange, &rMark, eCmd, bRecord, sal_False, bPartOfPaste ); + if (bSuccess) + { + pDocSh->UpdateOle(GetViewData()); + CellContentChanged(); + + // #i97876# Spreadsheet data changes are not notified + ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() ); + if ( pModelObj && pModelObj->HasChangesListeners() ) + { + if ( eCmd == INS_INSROWS || eCmd == INS_INSCOLS ) + { + ScRangeList aChangeRanges; + aChangeRanges.Append( aRange ); + ::rtl::OUString aOperation = ( eCmd == INS_INSROWS ? + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert-rows" ) ) : + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert-columns" ) ) ); + pModelObj->NotifyChanges( aOperation, aChangeRanges ); + } + } + } + return bSuccess; + } + else + { + ErrorMessage(STR_NOMULTISELECT); + return sal_False; + } +} + +// Zellen loeschen - Undo OK + +void ScViewFunc::DeleteCells( DelCellCmd eCmd, sal_Bool bRecord ) +{ + ScRange aRange; + if ( GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE ) + { + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + const ScMarkData& rMark = GetViewData()->GetMarkData(); + + // #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, sal_False ); + --nCount; + } + } + else + { + pDocSh->GetDocFunc().DeleteCells( aRange, &rMark, eCmd, bRecord, sal_False ); + } + + pDocSh->UpdateOle(GetViewData()); + CellContentChanged(); + + // #i97876# Spreadsheet data changes are not notified + ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() ); + if ( pModelObj && pModelObj->HasChangesListeners() ) + { + if ( eCmd == DEL_DELROWS || eCmd == DEL_DELCOLS ) + { + ScRangeList aChangeRanges; + aChangeRanges.Append( aRange ); + ::rtl::OUString aOperation = ( eCmd == DEL_DELROWS ? + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete-rows" ) ) : + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete-columns" ) ) ); + pModelObj->NotifyChanges( aOperation, aChangeRanges ); + } + } + + // #58106# Cursor direkt hinter den geloeschten Bereich setzen + SCCOL nCurX = GetViewData()->GetCurX(); + SCROW nCurY = GetViewData()->GetCurY(); + if ( eCmd==DEL_CELLSLEFT || eCmd==DEL_DELCOLS ) + nCurX = aRange.aStart.Col(); + else + nCurY = aRange.aStart.Row(); + SetCursor( nCurX, nCurY ); + } + else + { + if (eCmd == DEL_DELCOLS) + DeleteMulti( sal_False, bRecord ); + else if (eCmd == DEL_DELROWS) + DeleteMulti( sal_True, bRecord ); + else + ErrorMessage(STR_NOMULTISELECT); + } + + Unmark(); +} + +void ScViewFunc::DeleteMulti( sal_Bool bRows, sal_Bool bRecord ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocShellModificator aModificator( *pDocSh ); + SCTAB nTab = GetViewData()->GetTabNo(); + ScDocument* pDoc = pDocSh->GetDocument(); + ScMarkData aFuncMark( GetViewData()->GetMarkData() ); // local copy for UnmarkFiltered + ScViewUtil::UnmarkFiltered( aFuncMark, pDoc ); + + if (bRecord && !pDoc->IsUndoEnabled()) + bRecord = sal_False; + SCCOLROW* pRanges = new SCCOLROW[MAXCOLROWCOUNT]; + SCCOLROW nRangeCnt = bRows ? aFuncMark.GetMarkRowRanges( pRanges ) : + aFuncMark.GetMarkColumnRanges( pRanges ); + if (nRangeCnt == 0) + { + pRanges[0] = pRanges[1] = bRows ? static_cast<SCCOLROW>(GetViewData()->GetCurY()) : static_cast<SCCOLROW>(GetViewData()->GetCurX()); + nRangeCnt = 1; + } + + // Test ob erlaubt + + SCCOLROW* pOneRange = pRanges; + sal_uInt16 nErrorId = 0; + sal_Bool bNeedRefresh = sal_False; + SCCOLROW nRangeNo; + for (nRangeNo=0; nRangeNo<nRangeCnt && !nErrorId; nRangeNo++) + { + SCCOLROW nStart = *(pOneRange++); + SCCOLROW nEnd = *(pOneRange++); + + SCCOL nStartCol, nEndCol; + SCROW nStartRow, nEndRow; + if ( bRows ) + { + nStartCol = 0; + nEndCol = MAXCOL; + nStartRow = static_cast<SCROW>(nStart); + nEndRow = static_cast<SCROW>(nEnd); + } + else + { + nStartCol = static_cast<SCCOL>(nStart); + nEndCol = static_cast<SCCOL>(nEnd); + nStartRow = 0; + nEndRow = MAXROW; + } + + // cell protection (only needed for first range, as all following cells are moved) + if ( nRangeNo == 0 ) + { + // test to the end of the sheet + ScEditableTester aTester( pDoc, nTab, nStartCol, nStartRow, MAXCOL, MAXROW ); + if (!aTester.IsEditable()) + nErrorId = aTester.GetMessageId(); + } + + // merged cells + SCCOL nMergeStartX = nStartCol; + SCROW nMergeStartY = nStartRow; + SCCOL nMergeEndX = nEndCol; + SCROW nMergeEndY = nEndRow; + pDoc->ExtendMerge( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, nTab ); + pDoc->ExtendOverlapped( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, nTab ); + + if ( nMergeStartX != nStartCol || nMergeStartY != nStartRow ) + { + // Disallow deleting parts of a merged cell. + // Deleting the start is allowed (merge is removed), so the end doesn't have to be checked. + + nErrorId = STR_MSSG_DELETECELLS_0; + } + if ( nMergeEndX != nEndCol || nMergeEndY != nEndRow ) + { + // detect if the start of a merged cell is deleted, so the merge flags can be refreshed + + bNeedRefresh = sal_True; + } + } + + if ( nErrorId ) + { + ErrorMessage( nErrorId ); + delete[] pRanges; + return; + } + + // ausfuehren + + WaitObject aWait( GetFrameWin() ); // wichtig wegen TrackFormulas bei UpdateReference + + ScDocument* pUndoDoc = NULL; + ScRefUndoData* pUndoData = NULL; + if (bRecord) + { + pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + pUndoDoc->InitUndo( pDoc, nTab, nTab, !bRows, bRows ); // Zeilenhoehen + + pOneRange = pRanges; + for (nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++) + { + SCCOLROW nStart = *(pOneRange++); + SCCOLROW nEnd = *(pOneRange++); + if (bRows) + pDoc->CopyToDocument( 0,nStart,nTab, MAXCOL,nEnd,nTab, IDF_ALL,sal_False,pUndoDoc ); + else + pDoc->CopyToDocument( static_cast<SCCOL>(nStart),0,nTab, + static_cast<SCCOL>(nEnd),MAXROW,nTab, + IDF_ALL,sal_False,pUndoDoc ); + } + + // alle Formeln wegen Referenzen + SCTAB nTabCount = pDoc->GetTableCount(); + pUndoDoc->AddUndoTab( 0, nTabCount-1, sal_False, sal_False ); + pDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,MAXTAB, IDF_FORMULA,sal_False,pUndoDoc ); + + pUndoData = new ScRefUndoData( pDoc ); + + pDoc->BeginDrawUndo(); + } + + pOneRange = &pRanges[2*nRangeCnt]; // rueckwaerts + for (nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++) + { + SCCOLROW nEnd = *(--pOneRange); + SCCOLROW nStart = *(--pOneRange); + + if (bRows) + pDoc->DeleteRow( 0,nTab, MAXCOL,nTab, nStart, static_cast<SCSIZE>(nEnd-nStart+1) ); + else + pDoc->DeleteCol( 0,nTab, MAXROW,nTab, static_cast<SCCOL>(nStart), static_cast<SCSIZE>(nEnd-nStart+1) ); + } + + if (bNeedRefresh) + { + SCCOLROW nFirstStart = pRanges[0]; + SCCOL nStartCol = bRows ? 0 : static_cast<SCCOL>(nFirstStart); + SCROW nStartRow = bRows ? static_cast<SCROW>(nFirstStart) : 0; + SCCOL nEndCol = MAXCOL; + SCROW nEndRow = MAXROW; + + pDoc->RemoveFlagsTab( nStartCol, nStartRow, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER ); + pDoc->ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow, nTab, sal_True ); + } + + if (bRecord) + { + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoDeleteMulti( pDocSh, bRows, bNeedRefresh, nTab, pRanges, nRangeCnt, + pUndoDoc, pUndoData ) ); + } + + if (!AdjustRowHeight(0, MAXROW)) + { + if (bRows) + pDocSh->PostPaint( 0,pRanges[0],nTab, MAXCOL,MAXROW,nTab, PAINT_GRID | PAINT_LEFT ); + else + pDocSh->PostPaint( static_cast<SCCOL>(pRanges[0]),0,nTab, + MAXCOL,MAXROW,nTab, PAINT_GRID | PAINT_TOP ); + } + aModificator.SetDocumentModified(); + + CellContentChanged(); + + // #58106# Cursor direkt hinter den ersten geloeschten Bereich setzen + SCCOL nCurX = GetViewData()->GetCurX(); + SCROW nCurY = GetViewData()->GetCurY(); + if ( bRows ) + nCurY = pRanges[0]; + else + nCurX = static_cast<SCCOL>(pRanges[0]); + SetCursor( nCurX, nCurY ); + + delete[] pRanges; + + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); +} + +// Inhalte loeschen + +void ScViewFunc::DeleteContents( sal_uInt16 nFlags, sal_Bool bRecord ) +{ + // nur wegen Matrix nicht editierbar? Attribute trotzdem ok + sal_Bool bOnlyNotBecauseOfMatrix; + sal_Bool bEditable = SelectionEditable( &bOnlyNotBecauseOfMatrix ); + if ( !bEditable ) + { + if ( !(bOnlyNotBecauseOfMatrix && + ((nFlags & (IDF_ATTRIB | IDF_EDITATTR)) == nFlags)) ) + { + ErrorMessage(bOnlyNotBecauseOfMatrix ? STR_MATRIXFRAGMENTERR : STR_PROTECTIONERR); + return; + } + } + + ScRange aMarkRange; + sal_Bool bSimple = sal_False; + + ScDocument* pDoc = GetViewData()->GetDocument(); + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScMarkData aFuncMark( GetViewData()->GetMarkData() ); // local copy for UnmarkFiltered + ScViewUtil::UnmarkFiltered( aFuncMark, pDoc ); + + if (bRecord && !pDoc->IsUndoEnabled()) + bRecord = sal_False; + + ScDocShellModificator aModificator( *pDocSh ); + + if ( !aFuncMark.IsMarked() && !aFuncMark.IsMultiMarked() ) + { + aMarkRange.aStart.SetCol(GetViewData()->GetCurX()); + aMarkRange.aStart.SetRow(GetViewData()->GetCurY()); + aMarkRange.aStart.SetTab(GetViewData()->GetTabNo()); + aMarkRange.aEnd = aMarkRange.aStart; + if ( pDoc->HasAttrib( aMarkRange, HASATTR_MERGED ) ) + { +// InitOwnBlockMode(); + aFuncMark.SetMarkArea( aMarkRange ); + } + else + bSimple = sal_True; + } + + aFuncMark.SetMarking(sal_False); // for MarkToMulti + aFuncMark.MarkToSimple(); // before bMulti test below + + DBG_ASSERT( aFuncMark.IsMarked() || aFuncMark.IsMultiMarked() || bSimple, "delete what?" ); + + ScDocument* pUndoDoc = NULL; + sal_Bool bMulti = !bSimple && aFuncMark.IsMultiMarked(); + if (!bSimple) + { + aFuncMark.MarkToMulti(); + aFuncMark.GetMultiMarkArea( aMarkRange ); + } + ScRange aExtendedRange(aMarkRange); + if (!bSimple) + { + if ( pDoc->ExtendMerge( aExtendedRange, sal_True ) ) + bMulti = sal_False; + } + + // keine Objekte auf geschuetzten Tabellen + sal_Bool bObjects = sal_False; + if ( nFlags & IDF_OBJECTS ) + { + bObjects = sal_True; + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB nTab=0; nTab<nTabCount; nTab++) + if (aFuncMark.GetTableSelect(nTab) && pDoc->IsTabProtected(nTab)) + bObjects = sal_False; + } + + sal_uInt16 nExtFlags = 0; // extra flags are needed only if attributes are deleted + if ( nFlags & IDF_ATTRIB ) + pDocSh->UpdatePaintExt( nExtFlags, aMarkRange ); + + // Reihenfolge: + // 1) BeginDrawUndo + // 2) Objekte loeschen (DrawUndo wird gefuellt) + // 3) Inhalte fuer Undo kopieren + // 4) Inhalte loeschen + // 5) Undo-Aktion anlegen + + sal_Bool bDrawUndo = bObjects || ( nFlags & IDF_NOTE ); // needed for shown notes + if ( bDrawUndo && bRecord ) + pDoc->BeginDrawUndo(); + + if (bObjects) + { + if (bMulti) + pDoc->DeleteObjectsInSelection( aFuncMark ); + else + pDoc->DeleteObjectsInArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), +/*!*/ aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), + aFuncMark ); + } + + if ( bRecord ) + { + pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + SCTAB nTab = aMarkRange.aStart.Tab(); + pUndoDoc->InitUndo( pDoc, nTab, nTab ); + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB i=0; i<nTabCount; i++) + if (i != nTab && aFuncMark.GetTableSelect(i)) + pUndoDoc->AddUndoTab( i, i ); + ScRange aCopyRange = aExtendedRange; + aCopyRange.aStart.SetTab(0); + aCopyRange.aEnd.SetTab(nTabCount-1); + + // bei "Format/Standard" alle Attribute kopieren, weil CopyToDocument + // nur mit IDF_HARDATTR zu langsam ist: + sal_uInt16 nUndoDocFlags = nFlags; + if (nFlags & IDF_ATTRIB) + nUndoDocFlags |= IDF_ATTRIB; + if (nFlags & IDF_EDITATTR) // Edit-Engine-Attribute + nUndoDocFlags |= IDF_STRING; // -> Zellen werden geaendert + if (nFlags & IDF_NOTE) + nUndoDocFlags |= IDF_CONTENTS; // #68795# copy all cells with their notes + // do not copy note captions to undo document + nUndoDocFlags |= IDF_NOCAPTIONS; + pDoc->CopyToDocument( aCopyRange, nUndoDocFlags, bMulti, pUndoDoc, &aFuncMark ); + } + + HideAllCursors(); // falls Zusammenfassung aufgehoben wird + if (bSimple) + pDoc->DeleteArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), + aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), + aFuncMark, nFlags ); + else + { + pDoc->DeleteSelection( nFlags, aFuncMark ); +// aFuncMark.MarkToSimple(); + } + + if ( bRecord ) + { + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoDeleteContents( pDocSh, aFuncMark, aExtendedRange, + pUndoDoc, bMulti, nFlags, bDrawUndo ) ); + } + + if (!AdjustRowHeight( aExtendedRange.aStart.Row(), aExtendedRange.aEnd.Row() )) + pDocSh->PostPaint( aExtendedRange, PAINT_GRID, nExtFlags ); + + pDocSh->UpdateOle(GetViewData()); + + // #i97876# Spreadsheet data changes are not notified + ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() ); + if ( pModelObj && pModelObj->HasChangesListeners() ) + { + ScRangeList aChangeRanges; + if ( bSimple ) + { + aChangeRanges.Append( aMarkRange ); + } + else + { + aFuncMark.FillRangeListWithMarks( &aChangeRanges, sal_False ); + } + pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges ); + } + + aModificator.SetDocumentModified(); + CellContentChanged(); + ShowAllCursors(); + + if ( nFlags & IDF_ATTRIB ) + { + if ( nFlags & IDF_CONTENTS ) + ForgetFormatArea(); + else + StartFormatArea(); // Attribute loeschen ist auch Attributierung + } +} + +// Spaltenbreiten/Zeilenhoehen (ueber Header) - Undo OK + +void ScViewFunc::SetWidthOrHeight( sal_Bool bWidth, SCCOLROW nRangeCnt, SCCOLROW* pRanges, + ScSizeMode eMode, sal_uInt16 nSizeTwips, + sal_Bool bRecord, sal_Bool bPaint, ScMarkData* pMarkData ) +{ + if (nRangeCnt == 0) + return; + + // use view's mark if none specified + if ( !pMarkData ) + pMarkData = &GetViewData()->GetMarkData(); + + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTabCount = pDoc->GetTableCount(); + SCTAB nFirstTab = pMarkData->GetFirstSelected(); + SCTAB nCurTab = GetViewData()->GetTabNo(); + SCTAB nTab; + if (bRecord && !pDoc->IsUndoEnabled()) + bRecord = sal_False; + + ScDocShellModificator aModificator( *pDocSh ); + + sal_Bool bAllowed = sal_True; + for (nTab=0; nTab<nTabCount && bAllowed; nTab++) + if (pMarkData->GetTableSelect(nTab)) + { + for ( SCCOLROW i=0; i<nRangeCnt && bAllowed; i++ ) + { + sal_Bool bOnlyMatrix; + if (bWidth) + bAllowed = pDoc->IsBlockEditable( nTab, + static_cast<SCCOL>(pRanges[2*i]),0, + static_cast<SCCOL>(pRanges[2*i+1]),MAXROW, + &bOnlyMatrix ) || bOnlyMatrix; + else + bAllowed = pDoc->IsBlockEditable( nTab, 0,pRanges[2*i], + MAXCOL,pRanges[2*i+1], &bOnlyMatrix ) || + bOnlyMatrix; + } + } + if ( !bAllowed ) + { + ErrorMessage(STR_PROTECTIONERR); + return; + } + + SCCOLROW nStart = pRanges[0]; + SCCOLROW nEnd = pRanges[2*nRangeCnt-1]; + + sal_Bool bFormula = sal_False; + if ( eMode == SC_SIZE_OPTIMAL ) + { + const ScViewOptions& rOpts = GetViewData()->GetOptions(); + bFormula = rOpts.GetOption( VOPT_FORMULAS ); + } + + ScDocument* pUndoDoc = NULL; + ScOutlineTable* pUndoTab = NULL; + SCCOLROW* pUndoRanges = NULL; + + if ( bRecord ) + { + pDoc->BeginDrawUndo(); // Drawing Updates + + pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + for (nTab=0; nTab<nTabCount; nTab++) + if (pMarkData->GetTableSelect(nTab)) + { + if (bWidth) + { + if ( nTab == nFirstTab ) + pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_False ); + else + pUndoDoc->AddUndoTab( nTab, nTab, sal_True, sal_False ); + pDoc->CopyToDocument( static_cast<SCCOL>(nStart), 0, nTab, + static_cast<SCCOL>(nEnd), MAXROW, nTab, IDF_NONE, + sal_False, pUndoDoc ); + } + else + { + if ( nTab == nFirstTab ) + pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_False, sal_True ); + else + pUndoDoc->AddUndoTab( nTab, nTab, sal_False, sal_True ); + pDoc->CopyToDocument( 0, nStart, nTab, MAXCOL, nEnd, nTab, IDF_NONE, sal_False, pUndoDoc ); + } + } + + pUndoRanges = new SCCOLROW[ 2*nRangeCnt ]; + memmove( pUndoRanges, pRanges, 2*nRangeCnt*sizeof(SCCOLROW) ); + + //! outlines from all tables? + ScOutlineTable* pTable = pDoc->GetOutlineTable( nCurTab ); + if (pTable) + pUndoTab = new ScOutlineTable( *pTable ); + } + + if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT ) + pMarkData->MarkToMulti(); + + sal_Bool bShow = nSizeTwips > 0 || eMode != SC_SIZE_DIRECT; + sal_Bool bOutline = sal_False; + + for (nTab=0; nTab<nTabCount; nTab++) + if (pMarkData->GetTableSelect(nTab)) + { + const SCCOLROW* pTabRanges = pRanges; + + pDoc->IncSizeRecalcLevel( nTab ); // nicht fuer jede Spalte einzeln + pDoc->InitializeNoteCaptions( nTab ); + for (SCCOLROW nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++) + { + SCCOLROW nStartNo = *(pTabRanges++); + SCCOLROW nEndNo = *(pTabRanges++); + + if ( !bWidth ) // Hoehen immer blockweise + { + if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT ) + { + sal_Bool bAll = ( eMode==SC_SIZE_OPTIMAL ); + if (!bAll) + { + // fuer alle eingeblendeten CR_MANUALSIZE loeschen, + // dann SetOptimalHeight mit bShrink = FALSE + for (SCROW nRow = nStartNo; nRow <= nEndNo; ++nRow) + { + SCROW nLastRow = nRow; + if (pDoc->RowHidden(nRow, nTab, NULL, &nLastRow)) + { + nRow = nLastRow; + continue; + } + + sal_uInt8 nOld = pDoc->GetRowFlags(nRow, nTab); + if (nOld & CR_MANUALSIZE) + pDoc->SetRowFlags(nRow, nTab, nOld & ~CR_MANUALSIZE); + } + } + + double nPPTX = GetViewData()->GetPPTX(); + double nPPTY = GetViewData()->GetPPTY(); + Fraction aZoomX = GetViewData()->GetZoomX(); + Fraction aZoomY = GetViewData()->GetZoomY(); + + ScSizeDeviceProvider aProv(pDocSh); + if (aProv.IsPrinter()) + { + nPPTX = aProv.GetPPTX(); + nPPTY = aProv.GetPPTY(); + aZoomX = aZoomY = Fraction( 1, 1 ); + } + + pDoc->SetOptimalHeight( nStartNo, nEndNo, nTab, nSizeTwips, aProv.GetDevice(), + nPPTX, nPPTY, aZoomX, aZoomY, bAll ); + if (bAll) + pDoc->ShowRows( nStartNo, nEndNo, nTab, sal_True ); + + // Manual-Flag wird bei bAll=sal_True schon in SetOptimalHeight gesetzt + // (an bei Extra-Height, sonst aus). + } + else if ( eMode==SC_SIZE_DIRECT ) + { + if (nSizeTwips) + { + pDoc->SetRowHeightRange( nStartNo, nEndNo, nTab, nSizeTwips ); + pDoc->SetManualHeight( nStartNo, nEndNo, nTab, sal_True ); // height was set manually + } + pDoc->ShowRows( nStartNo, nEndNo, nTab, nSizeTwips != 0 ); + } + else if ( eMode==SC_SIZE_SHOW ) + { + pDoc->ShowRows( nStartNo, nEndNo, nTab, sal_True ); + } + } + else // Spaltenbreiten + { + for (SCCOL nCol=static_cast<SCCOL>(nStartNo); nCol<=static_cast<SCCOL>(nEndNo); nCol++) + { + if ( eMode != SC_SIZE_VISOPT || !pDoc->ColHidden(nCol, nTab) ) + { + sal_uInt16 nThisSize = nSizeTwips; + + if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT ) + nThisSize = nSizeTwips + GetOptimalColWidth( nCol, nTab, bFormula ); + if ( nThisSize ) + pDoc->SetColWidth( nCol, nTab, nThisSize ); + + pDoc->ShowCol( nCol, nTab, bShow ); + } + } + } + + // Outline anpassen + + if (bWidth) + { + if ( pDoc->UpdateOutlineCol( static_cast<SCCOL>(nStartNo), + static_cast<SCCOL>(nEndNo), nTab, bShow ) ) + bOutline = sal_True; + } + else + { + if ( pDoc->UpdateOutlineRow( nStartNo, nEndNo, nTab, bShow ) ) + bOutline = sal_True; + } + } + pDoc->DecSizeRecalcLevel( nTab ); // nicht fuer jede Spalte einzeln + } + + + if (!bOutline) + DELETEZ(pUndoTab); + + if (bRecord) + { + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoWidthOrHeight( pDocSh, *pMarkData, + nStart, nCurTab, nEnd, nCurTab, + pUndoDoc, nRangeCnt, pUndoRanges, + pUndoTab, eMode, nSizeTwips, bWidth ) ); + } + + for (nTab=0; nTab<nTabCount; nTab++) + if (pMarkData->GetTableSelect(nTab)) + pDoc->UpdatePageBreaks( nTab ); + + GetViewData()->GetView()->UpdateScrollBars(); + + if (bPaint) + { + HideCursor(); + + for (nTab=0; nTab<nTabCount; nTab++) + if (pMarkData->GetTableSelect(nTab)) + { + if (bWidth) + { + if (pDoc->HasAttrib( static_cast<SCCOL>(nStart),0,nTab, + static_cast<SCCOL>(nEnd),MAXROW,nTab, + HASATTR_MERGED | HASATTR_OVERLAPPED )) + nStart = 0; + if (nStart > 0) // weiter oben anfangen wegen Linien und Cursor + --nStart; + pDocSh->PostPaint( static_cast<SCCOL>(nStart), 0, nTab, + MAXCOL, MAXROW, nTab, PAINT_GRID | PAINT_TOP ); + } + else + { + if (pDoc->HasAttrib( 0,nStart,nTab, MAXCOL,nEnd,nTab, HASATTR_MERGED | HASATTR_OVERLAPPED )) + nStart = 0; + if (nStart != 0) + --nStart; + pDocSh->PostPaint( 0, nStart, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID | PAINT_LEFT ); + } + } + + pDocSh->UpdateOle(GetViewData()); + aModificator.SetDocumentModified(); + + ShowCursor(); + } + + // #i97876# Spreadsheet data changes are not notified + if ( bWidth ) + { + ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() ); + if ( pModelObj && pModelObj->HasChangesListeners() ) + { + ScRangeList aChangeRanges; + for ( nTab = 0; nTab < nTabCount; ++nTab ) + { + if ( pMarkData->GetTableSelect( nTab ) ) + { + const SCCOLROW* pTabRanges = pRanges; + for ( SCCOLROW nRange = 0; nRange < nRangeCnt; ++nRange ) + { + SCCOL nStartCol = static_cast< SCCOL >( *(pTabRanges++) ); + SCCOL nEndCol = static_cast< SCCOL >( *(pTabRanges++) ); + for ( SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol ) + { + aChangeRanges.Append( ScRange( nCol, 0, nTab ) ); + } + } + } + } + pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "column-resize" ) ), aChangeRanges ); + } + } +} + +// Spaltenbreiten/Zeilenhoehen (ueber Blockmarken) + +void ScViewFunc::SetMarkedWidthOrHeight( sal_Bool bWidth, ScSizeMode eMode, sal_uInt16 nSizeTwips, + sal_Bool bRecord, sal_Bool bPaint ) +{ + ScMarkData& rMark = GetViewData()->GetMarkData(); + + rMark.MarkToMulti(); + if (!rMark.IsMultiMarked()) + { + SCCOL nCol = GetViewData()->GetCurX(); + SCROW nRow = GetViewData()->GetCurY(); + SCTAB nTab = GetViewData()->GetTabNo(); + DoneBlockMode(); + InitOwnBlockMode(); + rMark.SetMultiMarkArea( ScRange( nCol,nRow,nTab ), sal_True ); + MarkDataChanged(); + } + + SCCOLROW* pRanges = new SCCOLROW[MAXCOLROWCOUNT]; + SCCOLROW nRangeCnt = 0; + + if ( bWidth ) + nRangeCnt = rMark.GetMarkColumnRanges( pRanges ); + else + nRangeCnt = rMark.GetMarkRowRanges( pRanges ); + + SetWidthOrHeight( bWidth, nRangeCnt, pRanges, eMode, nSizeTwips, bRecord, bPaint ); + + delete[] pRanges; + rMark.MarkToSimple(); +} + +void ScViewFunc::ModifyCellSize( ScDirection eDir, sal_Bool bOptimal ) +{ + //! Schrittweiten einstellbar + // Schrittweite ist auch Minimum + sal_uInt16 nStepX = STD_COL_WIDTH / 5; + sal_uInt16 nStepY = ScGlobal::nStdRowHeight; + + ScModule* pScMod = SC_MOD(); + sal_Bool bAnyEdit = pScMod->IsInputMode(); + SCCOL nCol = GetViewData()->GetCurX(); + SCROW nRow = GetViewData()->GetCurY(); + SCTAB nTab = GetViewData()->GetTabNo(); + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + + sal_Bool bAllowed, bOnlyMatrix; + if ( eDir == DIR_LEFT || eDir == DIR_RIGHT ) + bAllowed = pDoc->IsBlockEditable( nTab, nCol,0, nCol,MAXROW, &bOnlyMatrix ); + else + bAllowed = pDoc->IsBlockEditable( nTab, 0,nRow, MAXCOL,nRow, &bOnlyMatrix ); + if ( !bAllowed && !bOnlyMatrix ) + { + ErrorMessage(STR_PROTECTIONERR); + return; + } + + HideAllCursors(); + + sal_uInt16 nWidth = pDoc->GetColWidth( nCol, nTab ); + sal_uInt16 nHeight = pDoc->GetRowHeight( nRow, nTab ); + SCCOLROW nRange[2]; + if ( eDir == DIR_LEFT || eDir == DIR_RIGHT ) + { + if (bOptimal) // Breite dieser einen Zelle + { + if ( bAnyEdit ) + { + // beim Editieren die aktuelle Breite der Eingabe + ScInputHandler* pHdl = pScMod->GetInputHdl( GetViewData()->GetViewShell() ); + if (pHdl) + { + long nEdit = pHdl->GetTextSize().Width(); // in 1/100mm + + const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab ); + const SvxMarginItem& rMItem = + (const SvxMarginItem&)pPattern->GetItem(ATTR_MARGIN); + sal_uInt16 nMargin = rMItem.GetLeftMargin() + rMItem.GetRightMargin(); + if ( ((const SvxHorJustifyItem&) pPattern-> + GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_LEFT ) + nMargin = sal::static_int_cast<sal_uInt16>( + nMargin + ((const SfxUInt16Item&)pPattern->GetItem(ATTR_INDENT)).GetValue() ); + + nWidth = (sal_uInt16)(nEdit * pDocSh->GetOutputFactor() / HMM_PER_TWIPS) + + nMargin + STD_EXTRA_WIDTH; + } + } + else + { + double nPPTX = GetViewData()->GetPPTX(); + double nPPTY = GetViewData()->GetPPTY(); + Fraction aZoomX = GetViewData()->GetZoomX(); + Fraction aZoomY = GetViewData()->GetZoomY(); + + ScSizeDeviceProvider aProv(pDocSh); + if (aProv.IsPrinter()) + { + nPPTX = aProv.GetPPTX(); + nPPTY = aProv.GetPPTY(); + aZoomX = aZoomY = Fraction( 1, 1 ); + } + + long nPixel = pDoc->GetNeededSize( nCol, nRow, nTab, aProv.GetDevice(), + nPPTX, nPPTY, aZoomX, aZoomY, sal_True ); + sal_uInt16 nTwips = (sal_uInt16)( nPixel / nPPTX ); + if (nTwips != 0) + nWidth = nTwips + STD_EXTRA_WIDTH; + else + nWidth = STD_COL_WIDTH; + } + } + else // vergroessern / verkleinern + { + if ( eDir == DIR_RIGHT ) + nWidth = sal::static_int_cast<sal_uInt16>( nWidth + nStepX ); + else if ( nWidth > nStepX ) + nWidth = sal::static_int_cast<sal_uInt16>( nWidth - nStepX ); + if ( nWidth < nStepX ) nWidth = nStepX; + if ( nWidth > MAX_COL_WIDTH ) nWidth = MAX_COL_WIDTH; + } + nRange[0] = nRange[1] = nCol; + SetWidthOrHeight( sal_True, 1, nRange, SC_SIZE_DIRECT, nWidth ); + + // hier bei Breite auch Hoehe anpassen (nur die eine Zeile) + + if (!bAnyEdit) + { + const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab ); + sal_Bool bNeedHeight = + ((const SfxBoolItem&)pPattern->GetItem( ATTR_LINEBREAK )).GetValue() || + ((const SvxHorJustifyItem&)pPattern-> + GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_BLOCK; + if (bNeedHeight) + AdjustRowHeight( nRow, nRow ); + } + } + else + { + ScSizeMode eMode; + if (bOptimal) + { + eMode = SC_SIZE_OPTIMAL; + nHeight = 0; + } + else + { + eMode = SC_SIZE_DIRECT; + if ( eDir == DIR_BOTTOM ) + nHeight = sal::static_int_cast<sal_uInt16>( nHeight + nStepY ); + else if ( nHeight > nStepY ) + nHeight = sal::static_int_cast<sal_uInt16>( nHeight - nStepY ); + if ( nHeight < nStepY ) nHeight = nStepY; + if ( nHeight > MAX_COL_HEIGHT ) nHeight = MAX_COL_HEIGHT; + //! MAX_COL_HEIGHT umbenennen in MAX_ROW_HEIGHT in global.hxx !!!!!! + } + nRange[0] = nRange[1] = nRow; + SetWidthOrHeight( sal_False, 1, nRange, eMode, nHeight ); + } + + if ( bAnyEdit ) + { + UpdateEditView(); + if ( pDoc->HasAttrib( nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_NEEDHEIGHT ) ) + { + ScInputHandler* pHdl = pScMod->GetInputHdl( GetViewData()->GetViewShell() ); + if (pHdl) + pHdl->SetModified(); // damit bei Enter die Hoehe angepasst wird + } + } + + ShowAllCursors(); +} + +void ScViewFunc::ProtectSheet( SCTAB nTab, const ScTableProtection& rProtect ) +{ + if (nTab == TABLEID_DOC) + return; + + ScMarkData& rMark = GetViewData()->GetMarkData(); + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + ScDocFunc aFunc(*pDocSh); + bool bUndo(pDoc->IsUndoEnabled()); + + // modifying several tables is handled here + + if (bUndo) + { + String aUndo = ScGlobal::GetRscString( STR_UNDO_PROTECT_TAB ); + pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo ); + } + + SCTAB nCount = pDocSh->GetDocument()->GetTableCount(); + for ( SCTAB i=0; i<nCount; i++ ) + if ( rMark.GetTableSelect(i) ) + aFunc.ProtectSheet(i, rProtect); + + if (bUndo) + pDocSh->GetUndoManager()->LeaveListAction(); + + UpdateLayerLocks(); //! broadcast to all views +} + +void ScViewFunc::Protect( SCTAB nTab, const String& rPassword ) +{ + ScMarkData& rMark = GetViewData()->GetMarkData(); + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + ScDocFunc aFunc(*pDocSh); + sal_Bool bUndo(pDoc->IsUndoEnabled()); + + if ( nTab == TABLEID_DOC || rMark.GetSelectCount() <= 1 ) + aFunc.Protect( nTab, rPassword, sal_False ); + else + { + // modifying several tables is handled here + + if (bUndo) + { + String aUndo = ScGlobal::GetRscString( STR_UNDO_PROTECT_TAB ); + pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo ); + } + + SCTAB nCount = pDocSh->GetDocument()->GetTableCount(); + for ( SCTAB i=0; i<nCount; i++ ) + if ( rMark.GetTableSelect(i) ) + aFunc.Protect( i, rPassword, sal_False ); + + if (bUndo) + pDocSh->GetUndoManager()->LeaveListAction(); + } + + UpdateLayerLocks(); //! broadcast to all views +} + +sal_Bool ScViewFunc::Unprotect( SCTAB nTab, const String& rPassword ) +{ + ScMarkData& rMark = GetViewData()->GetMarkData(); + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + ScDocFunc aFunc(*pDocSh); + sal_Bool bChanged = sal_False; + sal_Bool bUndo (pDoc->IsUndoEnabled()); + + if ( nTab == TABLEID_DOC || rMark.GetSelectCount() <= 1 ) + bChanged = aFunc.Unprotect( nTab, rPassword, sal_False ); + else + { + // modifying several tables is handled here + + if (bUndo) + { + String aUndo = ScGlobal::GetRscString( STR_UNDO_UNPROTECT_TAB ); + pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo ); + } + + SCTAB nCount = pDocSh->GetDocument()->GetTableCount(); + for ( SCTAB i=0; i<nCount; i++ ) + if ( rMark.GetTableSelect(i) ) + if ( aFunc.Unprotect( i, rPassword, sal_False ) ) + bChanged = sal_True; + + if (bUndo) + pDocSh->GetUndoManager()->LeaveListAction(); + } + + if (bChanged) + UpdateLayerLocks(); //! broadcast to all views + + return bChanged; +} + +void ScViewFunc::SetNoteText( const ScAddress& rPos, const String& rNoteText ) +{ + GetViewData()->GetDocShell()->GetDocFunc().SetNoteText( rPos, rNoteText, sal_False ); +} + +void ScViewFunc::ReplaceNote( const ScAddress& rPos, const String& rNoteText, const String* pAuthor, const String* pDate ) +{ + GetViewData()->GetDocShell()->GetDocFunc().ReplaceNote( rPos, rNoteText, pAuthor, pDate, sal_False ); +} + +void ScViewFunc::SetNumberFormat( short nFormatType, sal_uLong nAdd ) +{ + // nur wegen Matrix nicht editierbar? Attribute trotzdem ok + sal_Bool bOnlyNotBecauseOfMatrix; + if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix ) + { + ErrorMessage(STR_PROTECTIONERR); + return; + } + + sal_uInt32 nNumberFormat = 0; + ScViewData* pViewData = GetViewData(); + ScDocument* pDoc = pViewData->GetDocument(); + SvNumberFormatter* pNumberFormatter = pDoc->GetFormatTable(); + LanguageType eLanguage = ScGlobal::eLnge; + ScPatternAttr aNewAttrs( pDoc->GetPool() ); + + // #67936# always take language from cursor position, even if there is a selection + + sal_uInt32 nCurrentNumberFormat; + pDoc->GetNumberFormat( pViewData->GetCurX(), + pViewData->GetCurY(), + pViewData->GetTabNo(), + nCurrentNumberFormat ); + const SvNumberformat* pEntry = pNumberFormatter->GetEntry( nCurrentNumberFormat ); + if (pEntry) + eLanguage = pEntry->GetLanguage(); // sonst ScGlobal::eLnge behalten + + nNumberFormat = pNumberFormatter->GetStandardFormat( nFormatType, eLanguage ) + nAdd; + + SfxItemSet& rSet = aNewAttrs.GetItemSet(); + rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNumberFormat ) ); + // ATTR_LANGUAGE_FORMAT nicht + ApplySelectionPattern( aNewAttrs, sal_True ); +} + +void ScViewFunc::SetNumFmtByStr( const String& rCode ) +{ + // nur wegen Matrix nicht editierbar? Attribute trotzdem ok + sal_Bool bOnlyNotBecauseOfMatrix; + if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix ) + { + ErrorMessage(STR_PROTECTIONERR); + return; + } + + ScViewData* pViewData = GetViewData(); + ScDocument* pDoc = pViewData->GetDocument(); + SvNumberFormatter* pFormatter = pDoc->GetFormatTable(); + + // Sprache immer von Cursorposition + + sal_uInt32 nCurrentNumberFormat; + pDoc->GetNumberFormat( pViewData->GetCurX(), pViewData->GetCurY(), + pViewData->GetTabNo(), nCurrentNumberFormat ); + const SvNumberformat* pEntry = pFormatter->GetEntry( nCurrentNumberFormat ); + LanguageType eLanguage = pEntry ? pEntry->GetLanguage() : ScGlobal::eLnge; + + // Index fuer String bestimmen + + sal_Bool bOk = sal_True; + sal_uInt32 nNumberFormat = pFormatter->GetEntryKey( rCode, eLanguage ); + if ( nNumberFormat == NUMBERFORMAT_ENTRY_NOT_FOUND ) + { + // neu eintragen + + String aFormat = rCode; // wird veraendert + xub_StrLen nErrPos = 0; + short nType = 0; //! ??? + bOk = pFormatter->PutEntry( aFormat, nErrPos, nType, nNumberFormat, eLanguage ); + } + + if ( bOk ) // gueltiges Format? + { + ScPatternAttr aNewAttrs( pDoc->GetPool() ); + SfxItemSet& rSet = aNewAttrs.GetItemSet(); + rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNumberFormat ) ); + rSet.Put( SvxLanguageItem( eLanguage, ATTR_LANGUAGE_FORMAT ) ); + ApplySelectionPattern( aNewAttrs, sal_True ); + } + + //! sonst Fehler zuerueckgeben / Meldung ausgeben ??? +} + +void ScViewFunc::ChangeNumFmtDecimals( sal_Bool bIncrement ) +{ + // nur wegen Matrix nicht editierbar? Attribute trotzdem ok + sal_Bool bOnlyNotBecauseOfMatrix; + if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix ) + { + ErrorMessage(STR_PROTECTIONERR); + return; + } + + ScDocument* pDoc = GetViewData()->GetDocument(); + SvNumberFormatter* pFormatter = pDoc->GetFormatTable(); + + SCCOL nCol = GetViewData()->GetCurX(); + SCROW nRow = GetViewData()->GetCurY(); + SCTAB nTab = GetViewData()->GetTabNo(); + + sal_uInt32 nOldFormat; + pDoc->GetNumberFormat( nCol, nRow, nTab, nOldFormat ); + const SvNumberformat* pOldEntry = pFormatter->GetEntry( nOldFormat ); + if (!pOldEntry) + { + DBG_ERROR("Zahlformat nicht gefunden !!!"); + return; + } + + // was haben wir denn da? + + sal_uInt32 nNewFormat = nOldFormat; + sal_Bool bError = sal_False; + + LanguageType eLanguage = pOldEntry->GetLanguage(); + sal_Bool bThousand, bNegRed; + sal_uInt16 nPrecision, nLeading; + pOldEntry->GetFormatSpecialInfo( bThousand, bNegRed, nPrecision, nLeading ); + + short nOldType = pOldEntry->GetType(); + if ( 0 == ( nOldType & ( + NUMBERFORMAT_NUMBER | NUMBERFORMAT_CURRENCY | NUMBERFORMAT_PERCENT ) ) ) + { + // Datum, Zeit, Bruch, logisch, Text kann nicht angepasst werden + //! bei Wisssenschaftlich kann es der Numberformatter auch nicht + bError = sal_True; + } + + //! Das SvNumberformat hat einen Member bStandard, verraet ihn aber nicht + sal_Bool bWasStandard = ( nOldFormat == pFormatter->GetStandardIndex( eLanguage ) ); + if (bWasStandard) + { + // bei "Standard" die Nachkommastellen abhaengig vom Zellinhalt + // 0 bei leer oder Text -> keine Nachkommastellen + double nVal = pDoc->GetValue( ScAddress( nCol, nRow, nTab ) ); + + // Die Wege des Numberformatters sind unergruendlich, darum ausprobieren: + String aOut; + Color* pCol; + ((SvNumberformat*)pOldEntry)->GetOutputString( nVal, aOut, &pCol ); + + nPrecision = 0; + // 'E' fuer Exponential ist fest im Numberformatter + if ( aOut.Search('E') != STRING_NOTFOUND ) + bError = sal_True; // Exponential nicht veraendern + else + { + String aDecSep( pFormatter->GetFormatDecimalSep( nOldFormat ) ); + xub_StrLen nPos = aOut.Search( aDecSep ); + if ( nPos != STRING_NOTFOUND ) + nPrecision = aOut.Len() - nPos - aDecSep.Len(); + // sonst 0 behalten + } + } + + if (!bError) + { + if (bIncrement) + { + if (nPrecision<20) + ++nPrecision; // erhoehen + else + bError = sal_True; // 20 ist Maximum + } + else + { + if (nPrecision) + --nPrecision; // vermindern + else + bError = sal_True; // weniger als 0 geht nicht + } + } + + if (!bError) + { + String aNewPicture; + pFormatter->GenerateFormat( aNewPicture, nOldFormat, eLanguage, + bThousand, bNegRed, nPrecision, nLeading ); + + nNewFormat = pFormatter->GetEntryKey( aNewPicture, eLanguage ); + if ( nNewFormat == NUMBERFORMAT_ENTRY_NOT_FOUND ) + { + xub_StrLen nErrPos = 0; + short nNewType = 0; + sal_Bool bOk = pFormatter->PutEntry( aNewPicture, nErrPos, + nNewType, nNewFormat, eLanguage ); + DBG_ASSERT( bOk, "falsches Zahlformat generiert" ); + if (!bOk) + bError = sal_True; + } + } + + if (!bError) + { + ScPatternAttr aNewAttrs( pDoc->GetPool() ); + SfxItemSet& rSet = aNewAttrs.GetItemSet(); + rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNewFormat ) ); + // ATTR_LANGUAGE_FORMAT nicht + ApplySelectionPattern( aNewAttrs, sal_True ); + } + else + Sound::Beep(); // war nix +} + +void ScViewFunc::ChangeIndent( sal_Bool bIncrement ) +{ + ScViewData* pViewData = GetViewData(); + ScDocShell* pDocSh = pViewData->GetDocShell(); + ScMarkData& rMark = pViewData->GetMarkData(); + + ScMarkData aWorkMark = rMark; + ScViewUtil::UnmarkFiltered( aWorkMark, pDocSh->GetDocument() ); + aWorkMark.MarkToMulti(); + if (!aWorkMark.IsMultiMarked()) + { + SCCOL nCol = pViewData->GetCurX(); + SCROW nRow = pViewData->GetCurY(); + SCTAB nTab = pViewData->GetTabNo(); + aWorkMark.SetMultiMarkArea( ScRange(nCol,nRow,nTab) ); + } + + sal_Bool bSuccess = pDocSh->GetDocFunc().ChangeIndent( aWorkMark, bIncrement, sal_False ); + if (bSuccess) + { + pDocSh->UpdateOle(pViewData); + StartFormatArea(); + } +} + +sal_Bool ScViewFunc::InsertName( const String& rName, const String& rSymbol, + const String& rType ) +{ + // Type = P,R,C,F (und Kombinationen) + //! Undo... + + sal_Bool bOk = sal_False; + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = GetViewData()->GetTabNo(); + ScRangeName* pList = pDoc->GetRangeName(); + + RangeType nType = RT_NAME; + ScRangeData* pNewEntry = new ScRangeData( pDoc, rName, rSymbol, + ScAddress( GetViewData()->GetCurX(), GetViewData()->GetCurY(), + nTab), nType ); + String aUpType = rType; + aUpType.ToUpperAscii(); + if ( aUpType.Search( 'P' ) != STRING_NOTFOUND ) + nType |= RT_PRINTAREA; + if ( aUpType.Search( 'R' ) != STRING_NOTFOUND ) + nType |= RT_ROWHEADER; + if ( aUpType.Search( 'C' ) != STRING_NOTFOUND ) + nType |= RT_COLHEADER; + if ( aUpType.Search( 'F' ) != STRING_NOTFOUND ) + nType |= RT_CRITERIA; + pNewEntry->AddType(nType); + + if ( !pNewEntry->GetErrCode() ) // Text gueltig? + { + ScDocShellModificator aModificator( *pDocSh ); + + pDoc->CompileNameFormula( sal_True ); // CreateFormulaString + + // Eintrag bereits vorhanden? Dann vorher entfernen (=Aendern) + sal_uInt16 nFoundAt; + if ( pList->SearchName( rName, nFoundAt ) ) + { // alten Index uebernehmen + pNewEntry->SetIndex( ((ScRangeData*)pList->At(nFoundAt))->GetIndex() ); + pList->AtFree( nFoundAt ); + } + + if ( pList->Insert( pNewEntry ) ) + { + pNewEntry = NULL; // nicht loeschen + bOk = sal_True; + } + + pDoc->CompileNameFormula( sal_False ); // CompileFormulaString + aModificator.SetDocumentModified(); + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) ); + } + + delete pNewEntry; // wenn er nicht eingefuegt wurde + return bOk; +} + +void ScViewFunc::CreateNames( sal_uInt16 nFlags ) +{ + sal_Bool bDone = sal_False; + ScRange aRange; + if ( GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE ) + bDone = GetViewData()->GetDocShell()->GetDocFunc().CreateNames( aRange, nFlags, sal_False ); + + if (!bDone) + ErrorMessage(STR_CREATENAME_MARKERR); +} + +sal_uInt16 ScViewFunc::GetCreateNameFlags() +{ + sal_uInt16 nFlags = 0; + + SCCOL nStartCol, nEndCol; + SCROW nStartRow, nEndRow; + SCTAB nDummy; + if (GetViewData()->GetSimpleArea(nStartCol,nStartRow,nDummy,nEndCol,nEndRow,nDummy) == SC_MARK_SIMPLE) + { + ScDocument* pDoc = GetViewData()->GetDocument(); + SCTAB nTab = GetViewData()->GetTabNo(); + sal_Bool bOk; + SCCOL i; + SCROW j; + + bOk = sal_True; + SCCOL nFirstCol = nStartCol; + SCCOL nLastCol = nEndCol; + if (nStartCol+1 < nEndCol) { ++nFirstCol; --nLastCol; } + for (i=nFirstCol; i<=nLastCol && bOk; i++) + if (!pDoc->HasStringData( i,nStartRow,nTab )) + bOk = sal_False; + if (bOk) + nFlags |= NAME_TOP; + else // Bottom nur wenn nicht Top + { + bOk = sal_True; + for (i=nFirstCol; i<=nLastCol && bOk; i++) + if (!pDoc->HasStringData( i,nEndRow,nTab )) + bOk = sal_False; + if (bOk) + nFlags |= NAME_BOTTOM; + } + + bOk = sal_True; + SCROW nFirstRow = nStartRow; + SCROW nLastRow = nEndRow; + if (nStartRow+1 < nEndRow) { ++nFirstRow; --nLastRow; } + for (j=nFirstRow; j<=nLastRow && bOk; j++) + if (!pDoc->HasStringData( nStartCol,j,nTab )) + bOk = sal_False; + if (bOk) + nFlags |= NAME_LEFT; + else // Right nur wenn nicht Left + { + bOk = sal_True; + for (j=nFirstRow; j<=nLastRow && bOk; j++) + if (!pDoc->HasStringData( nEndCol,j,nTab )) + bOk = sal_False; + if (bOk) + nFlags |= NAME_RIGHT; + } + } + + if (nStartCol == nEndCol) + nFlags &= ~( NAME_LEFT | NAME_RIGHT ); + if (nStartRow == nEndRow) + nFlags &= ~( NAME_TOP | NAME_BOTTOM ); + + return nFlags; +} + +void ScViewFunc::InsertNameList() +{ + ScAddress aPos( GetViewData()->GetCurX(), GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + if ( pDocSh->GetDocFunc().InsertNameList( aPos, sal_False ) ) + pDocSh->UpdateOle(GetViewData()); +} + + + + diff --git a/sc/source/ui/view/viewutil.cxx b/sc/source/ui/view/viewutil.cxx new file mode 100644 index 000000000000..1c2691d8a33f --- /dev/null +++ b/sc/source/ui/view/viewutil.cxx @@ -0,0 +1,640 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- +#include <tools/list.hxx> +#include "scitems.hxx" +#include <sfx2/bindings.hxx> +#include <sfx2/viewsh.hxx> +#include <sfx2/dispatch.hxx> +#include <editeng/fontitem.hxx> +#include <editeng/langitem.hxx> +#include <editeng/scripttypeitem.hxx> +#include <svl/itempool.hxx> +#include <svl/itemset.hxx> +#include <svl/cjkoptions.hxx> +#include <svl/ctloptions.hxx> +#include <vcl/svapp.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/wrkwin.hxx> +#include <sfx2/request.hxx> +#include <sfx2/objsh.hxx> +#include <svl/stritem.hxx> +#include <svl/eitem.hxx> + +#include <com/sun/star/i18n/TransliterationModules.hpp> +#include <com/sun/star/i18n/TransliterationModulesExtra.hpp> + + +#include "viewutil.hxx" +#include "global.hxx" +#include "chgtrack.hxx" +#include "chgviset.hxx" +#include "markdata.hxx" + +#include <svx/svxdlg.hxx> //CHINA001 +#include <svx/dialogs.hrc> //CHINA001 +// STATIC DATA ----------------------------------------------------------- + +//================================================================== + +// static +void ScViewUtil::PutItemScript( SfxItemSet& rShellSet, const SfxItemSet& rCoreSet, + sal_uInt16 nWhichId, sal_uInt16 nScript ) +{ + // take the effective item from rCoreSet according to nScript + // and put in rShellSet under the (base) nWhichId + + SfxItemPool& rPool = *rShellSet.GetPool(); + SvxScriptSetItem aSetItem( rPool.GetSlotId(nWhichId), rPool ); + // use PutExtended with eDefaultAs = SFX_ITEM_SET, so defaults from rCoreSet + // (document pool) are read and put into rShellSet (MessagePool) + aSetItem.GetItemSet().PutExtended( rCoreSet, SFX_ITEM_DONTCARE, SFX_ITEM_SET ); + const SfxPoolItem* pI = aSetItem.GetItemOfScript( nScript ); + if (pI) + rShellSet.Put( *pI, nWhichId ); + else + rShellSet.InvalidateItem( nWhichId ); +} + +// static +sal_uInt16 ScViewUtil::GetEffLanguage( ScDocument* pDoc, const ScAddress& rPos ) +{ + // used for thesaurus + + sal_uInt8 nScript = pDoc->GetScriptType( rPos.Col(), rPos.Row(), rPos.Tab() ); + sal_uInt16 nWhich = ( nScript == SCRIPTTYPE_ASIAN ) ? ATTR_CJK_FONT_LANGUAGE : + ( ( nScript == SCRIPTTYPE_COMPLEX ) ? ATTR_CTL_FONT_LANGUAGE : ATTR_FONT_LANGUAGE ); + const SfxPoolItem* pItem = pDoc->GetAttr( rPos.Col(), rPos.Row(), rPos.Tab(), nWhich); + SvxLanguageItem* pLangIt = PTR_CAST( SvxLanguageItem, pItem ); + LanguageType eLnge; + if (pLangIt) + { + eLnge = (LanguageType) pLangIt->GetValue(); + if (eLnge == LANGUAGE_DONTKNOW) //! can this happen? + { + LanguageType eLatin, eCjk, eCtl; + pDoc->GetLanguage( eLatin, eCjk, eCtl ); + eLnge = ( nScript == SCRIPTTYPE_ASIAN ) ? eCjk : + ( ( nScript == SCRIPTTYPE_COMPLEX ) ? eCtl : eLatin ); + } + } + else + eLnge = LANGUAGE_ENGLISH_US; + if ( eLnge == LANGUAGE_SYSTEM ) + eLnge = Application::GetSettings().GetLanguage(); // never use SYSTEM for spelling + + return eLnge; +} + +// static +sal_Int32 ScViewUtil::GetTransliterationType( sal_uInt16 nSlotID ) +{ + sal_Int32 nType = 0; + switch ( nSlotID ) + { + case SID_TRANSLITERATE_SENTENCE_CASE: + nType = com::sun::star::i18n::TransliterationModulesExtra::SENTENCE_CASE; + break; + case SID_TRANSLITERATE_TITLE_CASE: + nType = com::sun::star::i18n::TransliterationModulesExtra::TITLE_CASE; + break; + case SID_TRANSLITERATE_TOGGLE_CASE: + nType = com::sun::star::i18n::TransliterationModulesExtra::TOGGLE_CASE; + break; + case SID_TRANSLITERATE_UPPER: + nType = com::sun::star::i18n::TransliterationModules_LOWERCASE_UPPERCASE; + break; + case SID_TRANSLITERATE_LOWER: + nType = com::sun::star::i18n::TransliterationModules_UPPERCASE_LOWERCASE; + break; + case SID_TRANSLITERATE_HALFWIDTH: + nType = com::sun::star::i18n::TransliterationModules_FULLWIDTH_HALFWIDTH; + break; + case SID_TRANSLITERATE_FULLWIDTH: + nType = com::sun::star::i18n::TransliterationModules_HALFWIDTH_FULLWIDTH; + break; + case SID_TRANSLITERATE_HIRAGANA: + nType = com::sun::star::i18n::TransliterationModules_KATAKANA_HIRAGANA; + break; + case SID_TRANSLITERATE_KATAGANA: + nType = com::sun::star::i18n::TransliterationModules_HIRAGANA_KATAKANA; + break; + } + return nType; +} + +// static +sal_Bool ScViewUtil::IsActionShown( const ScChangeAction& rAction, + const ScChangeViewSettings& rSettings, + ScDocument& rDocument ) +{ + // abgelehnte werden durch eine invertierende akzeptierte Action dargestellt, + // die Reihenfolge von ShowRejected/ShowAccepted ist deswegen wichtig + + if ( !rSettings.IsShowRejected() && rAction.IsRejecting() ) + return sal_False; + + if ( !rSettings.IsShowAccepted() && rAction.IsAccepted() && !rAction.IsRejecting() ) + return sal_False; + + if ( rSettings.HasAuthor() ) + { + if ( rSettings.IsEveryoneButMe() ) + { + // GetUser() am ChangeTrack ist der aktuelle Benutzer + ScChangeTrack* pTrack = rDocument.GetChangeTrack(); + if ( !pTrack || rAction.GetUser() == pTrack->GetUser() ) + return sal_False; + } + else if ( rAction.GetUser() != rSettings.GetTheAuthorToShow() ) + return sal_False; + } + + if ( rSettings.HasComment() ) + { + String aComStr=rAction.GetComment(); + aComStr.AppendAscii(RTL_CONSTASCII_STRINGPARAM( " (" )); + rAction.GetDescription( aComStr, &rDocument ); + aComStr+=')'; + + if(!rSettings.IsValidComment(&aComStr)) + return sal_False; + } + + if ( rSettings.HasRange() ) + if ( !rSettings.GetTheRangeList().Intersects( rAction.GetBigRange().MakeRange() ) ) + return sal_False; + + if ( rSettings.HasDate() && rSettings.GetTheDateMode() != SCDM_NO_DATEMODE ) + { + DateTime aDateTime = rAction.GetDateTime(); + const DateTime& rFirst = rSettings.GetTheFirstDateTime(); + const DateTime& rLast = rSettings.GetTheLastDateTime(); + switch ( rSettings.GetTheDateMode() ) + { // korrespondiert mit ScHighlightChgDlg::OKBtnHdl + case SCDM_DATE_BEFORE: + if ( aDateTime > rFirst ) + return sal_False; + break; + + case SCDM_DATE_SINCE: + if ( aDateTime < rFirst ) + return sal_False; + break; + + case SCDM_DATE_EQUAL: + case SCDM_DATE_BETWEEN: + if ( aDateTime < rFirst || aDateTime > rLast ) + return sal_False; + break; + + case SCDM_DATE_NOTEQUAL: + if ( aDateTime >= rFirst && aDateTime <= rLast ) + return sal_False; + break; + + case SCDM_DATE_SAVE: + { + ScChangeTrack* pTrack = rDocument.GetChangeTrack(); + if ( !pTrack || pTrack->GetLastSavedActionNumber() >= + rAction.GetActionNumber() ) + return sal_False; + } + break; + + default: + { + // added to avoid warnings + } + } + } + + if ( rSettings.HasActionRange() ) + { + sal_uLong nAction = rAction.GetActionNumber(); + sal_uLong nFirstAction; + sal_uLong nLastAction; + rSettings.GetTheActionRange( nFirstAction, nLastAction ); + if ( nAction < nFirstAction || nAction > nLastAction ) + { + return sal_False; + } + } + + return sal_True; +} + +// static +void ScViewUtil::UnmarkFiltered( ScMarkData& rMark, ScDocument* pDoc ) +{ + rMark.MarkToMulti(); + + ScRange aMultiArea; + rMark.GetMultiMarkArea( aMultiArea ); + SCCOL nStartCol = aMultiArea.aStart.Col(); + SCROW nStartRow = aMultiArea.aStart.Row(); + SCCOL nEndCol = aMultiArea.aEnd.Col(); + SCROW nEndRow = aMultiArea.aEnd.Row(); + + bool bChanged = false; + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB nTab=0; nTab<nTabCount; nTab++) + if ( rMark.GetTableSelect(nTab ) ) + { + for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow) + { + SCROW nLastRow = nRow; + if (pDoc->RowFiltered(nRow, nTab, NULL, &nLastRow)) + { + // use nStartCol/nEndCol, so the multi mark area isn't extended to all columns + // (visible in repaint for indentation) + rMark.SetMultiMarkArea( + ScRange(nStartCol, nRow, nTab, nEndCol, nLastRow, nTab), false); + bChanged = true; + nRow = nLastRow; + } + } + } + + if ( bChanged && !rMark.HasAnyMultiMarks() ) + rMark.ResetMark(); + + rMark.MarkToSimple(); +} + + +// static +bool ScViewUtil::FitToUnfilteredRows( ScRange & rRange, ScDocument * pDoc, size_t nRows ) +{ + SCTAB nTab = rRange.aStart.Tab(); + bool bOneTabOnly = (nTab == rRange.aEnd.Tab()); + // Always fit the range on its first sheet. + DBG_ASSERT( bOneTabOnly, "ScViewUtil::ExtendToUnfilteredRows: works only on one sheet"); + SCROW nStartRow = rRange.aStart.Row(); + SCROW nLastRow = pDoc->LastNonFilteredRow(nStartRow, MAXROW, nTab); + if (ValidRow(nLastRow)) + rRange.aEnd.SetRow(nLastRow); + SCROW nCount = pDoc->CountNonFilteredRows(nStartRow, MAXROW, nTab); + return static_cast<size_t>(nCount) == nRows && bOneTabOnly; +} + + +// static +bool ScViewUtil::HasFiltered( const ScRange& rRange, ScDocument* pDoc ) +{ + SCROW nStartRow = rRange.aStart.Row(); + SCROW nEndRow = rRange.aEnd.Row(); + for (SCTAB nTab=rRange.aStart.Tab(); nTab<=rRange.aEnd.Tab(); nTab++) + { + if (pDoc->HasFilteredRows(nStartRow, nEndRow, nTab)) + return true; + } + + return false; +} + +// static +void ScViewUtil::HideDisabledSlot( SfxItemSet& rSet, SfxBindings& rBindings, sal_uInt16 nSlotId ) +{ + SvtCJKOptions aCJKOptions; + SvtCTLOptions aCTLOptions; + bool bEnabled = true; + + switch( nSlotId ) + { + case SID_CHINESE_CONVERSION: + case SID_HANGUL_HANJA_CONVERSION: + bEnabled = aCJKOptions.IsAnyEnabled(); + break; + + case SID_TRANSLITERATE_HALFWIDTH: + case SID_TRANSLITERATE_FULLWIDTH: + case SID_TRANSLITERATE_HIRAGANA: + case SID_TRANSLITERATE_KATAGANA: + bEnabled = aCJKOptions.IsChangeCaseMapEnabled(); + break; + + case SID_INSERT_RLM: + case SID_INSERT_LRM: + case SID_INSERT_ZWNBSP: + case SID_INSERT_ZWSP: + bEnabled = aCTLOptions.IsCTLFontEnabled(); + break; + + default: + DBG_ERRORFILE( "ScViewUtil::HideDisabledSlot - unknown slot ID" ); + return; + } + + rBindings.SetVisibleState( nSlotId, bEnabled ); + if( !bEnabled ) + rSet.DisableItem( nSlotId ); +} + +//================================================================== + +sal_Bool ScViewUtil::ExecuteCharMap( const SvxFontItem& rOldFont, + SfxViewFrame& rFrame, + SvxFontItem& rNewFont, + String& rString ) +{ + sal_Bool bRet = sal_False; + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + if(pFact) + { + SfxAllItemSet aSet( rFrame.GetObjectShell()->GetPool() ); + aSet.Put( SfxBoolItem( FN_PARAM_1, sal_False ) ); + aSet.Put( SvxFontItem( rOldFont.GetFamily(), rOldFont.GetFamilyName(), rOldFont.GetStyleName(), rOldFont.GetPitch(), rOldFont.GetCharSet(), aSet.GetPool()->GetWhich( SID_ATTR_CHAR_FONT ) ) ); + SfxAbstractDialog* pDlg = pFact->CreateSfxDialog( &rFrame.GetWindow(), aSet, rFrame.GetFrame().GetFrameInterface(), RID_SVXDLG_CHARMAP ); + if ( pDlg->Execute() == RET_OK ) + { + SFX_ITEMSET_ARG( pDlg->GetOutputItemSet(), pItem, SfxStringItem, SID_CHARMAP, sal_False ); + SFX_ITEMSET_ARG( pDlg->GetOutputItemSet(), pFontItem, SvxFontItem, SID_ATTR_CHAR_FONT, sal_False ); + if ( pItem ) + rString = pItem->GetValue(); + if ( pFontItem ) + rNewFont = SvxFontItem( pFontItem->GetFamily(), pFontItem->GetFamilyName(), pFontItem->GetStyleName(), pFontItem->GetPitch(), pFontItem->GetCharSet(), rNewFont.Which() ); + bRet = sal_True; + } + delete pDlg; + } + return bRet; +} + +bool ScViewUtil::IsFullScreen( SfxViewShell& rViewShell ) +{ + SfxBindings& rBindings = rViewShell.GetViewFrame()->GetBindings(); + SfxPoolItem* pItem = 0; + bool bIsFullScreen = false; + + if (rBindings.QueryState( SID_WIN_FULLSCREEN, pItem ) >= SFX_ITEM_DEFAULT) + bIsFullScreen = static_cast< SfxBoolItem* >( pItem )->GetValue(); + return bIsFullScreen; +} + +void ScViewUtil::SetFullScreen( SfxViewShell& rViewShell, bool bSet ) +{ + if( IsFullScreen( rViewShell ) != bSet ) + { + SfxBoolItem aItem( SID_WIN_FULLSCREEN, bSet ); + rViewShell.GetDispatcher()->Execute( SID_WIN_FULLSCREEN, SFX_CALLMODE_RECORD, &aItem, 0L ); + } +} + +//------------------------------------------------------------------ + +ScUpdateRect::ScUpdateRect( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2 ) +{ + PutInOrder( nX1, nX2 ); + PutInOrder( nY1, nY2 ); + + nOldStartX = nX1; + nOldStartY = nY1; + nOldEndX = nX2; + nOldEndY = nY2; +} + +void ScUpdateRect::SetNew( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2 ) +{ + PutInOrder( nX1, nX2 ); + PutInOrder( nY1, nY2 ); + + nNewStartX = nX1; + nNewStartY = nY1; + nNewEndX = nX2; + nNewEndY = nY2; +} + +sal_Bool ScUpdateRect::GetDiff( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2 ) +{ + if ( nNewStartX == nOldStartX && nNewEndX == nOldEndX && + nNewStartY == nOldStartY && nNewEndY == nOldEndY ) + { + rX1 = nNewStartX; + rY1 = nNewStartY; + rX2 = nNewStartX; + rY2 = nNewStartY; + return sal_False; + } + + rX1 = Min(nNewStartX,nOldStartX); + rY1 = Min(nNewStartY,nOldStartY); + rX2 = Max(nNewEndX,nOldEndX); + rY2 = Max(nNewEndY,nOldEndY); + + if ( nNewStartX == nOldStartX && nNewEndX == nOldEndX ) + { + if ( nNewStartY == nOldStartY ) + { + rY1 = Min( nNewEndY, nOldEndY ); + rY2 = Max( nNewEndY, nOldEndY ); + } + else if ( nNewEndY == nOldEndY ) + { + rY1 = Min( nNewStartY, nOldStartY ); + rY2 = Max( nNewStartY, nOldStartY ); + } + } + else if ( nNewStartY == nOldStartY && nNewEndY == nOldEndY ) + { + if ( nNewStartX == nOldStartX ) + { + rX1 = Min( nNewEndX, nOldEndX ); + rX2 = Max( nNewEndX, nOldEndX ); + } + else if ( nNewEndX == nOldEndX ) + { + rX1 = Min( nNewStartX, nOldStartX ); + rX2 = Max( nNewStartX, nOldStartX ); + } + } + + return sal_True; +} + +#ifdef OLD_SELECTION_PAINT +sal_Bool ScUpdateRect::GetXorDiff( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2, sal_Bool& rCont ) +{ + rCont = sal_False; + + if (nNewStartX == nOldStartX && nNewEndX == nOldEndX && + nNewStartY == nOldStartY && nNewEndY == nOldEndY) + { + rX1 = nNewStartX; + rY1 = nNewStartY; + rX2 = nNewStartX; + rY2 = nNewStartY; + return sal_False; + } + + rX1 = Min(nNewStartX,nOldStartX); + rY1 = Min(nNewStartY,nOldStartY); + rX2 = Max(nNewEndX,nOldEndX); + rY2 = Max(nNewEndY,nOldEndY); + + if (nNewStartX == nOldStartX && nNewEndX == nOldEndX) // nur vertikal + { + if (nNewStartY == nOldStartY) + { + rY1 = Min( nNewEndY, nOldEndY ) + 1; + rY2 = Max( nNewEndY, nOldEndY ); + } + else if (nNewEndY == nOldEndY) + { + rY1 = Min( nNewStartY, nOldStartY ); + rY2 = Max( nNewStartY, nOldStartY ) - 1; + } + else + { + rY1 = Min( nNewStartY, nOldStartY ); + rY2 = Max( nNewStartY, nOldStartY ) - 1; + rCont = sal_True; + nContY1 = Min( nNewEndY, nOldEndY ) + 1; + nContY2 = Max( nNewEndY, nOldEndY ); + nContX1 = rX1; + nContX2 = rX2; + } + } + else if (nNewStartY == nOldStartY && nNewEndY == nOldEndY) // nur horizontal + { + if (nNewStartX == nOldStartX) + { + rX1 = Min( nNewEndX, nOldEndX ) + 1; + rX2 = Max( nNewEndX, nOldEndX ); + } + else if (nNewEndX == nOldEndX) + { + rX1 = Min( nNewStartX, nOldStartX ); + rX2 = Max( nNewStartX, nOldStartX ) - 1; + } + else + { + rX1 = Min( nNewStartX, nOldStartX ); + rX2 = Max( nNewStartX, nOldStartX ) - 1; + rCont = sal_True; + nContX1 = Min( nNewEndX, nOldEndX ) + 1; + nContX2 = Max( nNewEndX, nOldEndX ); + nContY1 = rY1; + nContY2 = rY2; + } + } + else if (nNewEndX == nOldEndX && nNewEndY == nOldEndY) // links oben + { + if ((nNewStartX<nOldStartX) == (nNewStartY<nOldStartY)) + rX1 = Min( nNewStartX, nOldStartX ); + else + rX1 = Max( nNewStartX, nOldStartX ); // Ecke weglassen + rX2 = nOldEndX; + rY1 = Min( nNewStartY, nOldStartY ); // oben + rY2 = Max( nNewStartY, nOldStartY ) - 1; + rCont = sal_True; + nContY1 = rY2+1; + nContY2 = nOldEndY; + nContX1 = Min( nNewStartX, nOldStartX ); // links + nContX2 = Max( nNewStartX, nOldStartX ) - 1; + } + else if (nNewStartX == nOldStartX && nNewEndY == nOldEndY) // rechts oben + { + if ((nNewEndX<nOldEndX) != (nNewStartY<nOldStartY)) + rX2 = Max( nNewEndX, nOldEndX ); + else + rX2 = Min( nNewEndX, nOldEndX ); // Ecke weglassen + rX1 = nOldStartX; + rY1 = Min( nNewStartY, nOldStartY ); // oben + rY2 = Max( nNewStartY, nOldStartY ) - 1; + rCont = sal_True; + nContY1 = rY2+1; + nContY2 = nOldEndY; + nContX1 = Min( nNewEndX, nOldEndX ) + 1; // rechts + nContX2 = Max( nNewEndX, nOldEndX ); + } + else if (nNewEndX == nOldEndX && nNewStartY == nOldStartY) // links unten + { + if ((nNewStartX<nOldStartX) != (nNewEndY<nOldEndY)) + rX1 = Min( nNewStartX, nOldStartX ); + else + rX1 = Max( nNewStartX, nOldStartX ); // Ecke weglassen + rX2 = nOldEndX; + rY1 = Min( nNewEndY, nOldEndY ) + 1; // unten + rY2 = Max( nNewEndY, nOldEndY ); + rCont = sal_True; + nContY1 = nOldStartY; + nContY2 = rY1-1; + nContX1 = Min( nNewStartX, nOldStartX ); // links + nContX2 = Max( nNewStartX, nOldStartX ) - 1; + } + else if (nNewStartX == nOldStartX && nNewStartY == nOldStartY) // rechts unten + { + if ((nNewEndX<nOldEndX) == (nNewEndY<nOldEndY)) + rX2 = Max( nNewEndX, nOldEndX ); + else + rX2 = Min( nNewEndX, nOldEndX ); // Ecke weglassen + rX1 = nOldStartX; + rY1 = Min( nNewEndY, nOldEndY ) + 1; // unten + rY2 = Max( nNewEndY, nOldEndY ); + rCont = sal_True; + nContY1 = nOldStartY; + nContY2 = rY1-1; + nContX1 = Min( nNewEndX, nOldEndX ) + 1; // rechts + nContX2 = Max( nNewEndX, nOldEndX ); + } + else // Ueberschlag + { + rX1 = nOldStartX; + rY1 = nOldStartY; + rX2 = nOldEndX; + rY2 = nOldEndY; + rCont = sal_True; + nContX1 = nNewStartX; + nContY1 = nNewStartY; + nContX2 = nNewEndX; + nContY2 = nNewEndY; + } + + return sal_True; +} + +void ScUpdateRect::GetContDiff( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2 ) +{ + rX1 = nContX1; + rY1 = nContY1; + rX2 = nContX2; + rY2 = nContY2; +} +#endif + + + + + + diff --git a/sc/source/ui/view/waitoff.cxx b/sc/source/ui/view/waitoff.cxx new file mode 100644 index 000000000000..2e3c3e8476af --- /dev/null +++ b/sc/source/ui/view/waitoff.cxx @@ -0,0 +1,70 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +//------------------------------------------------------------------------ + +#include <vcl/window.hxx> + +#include "waitoff.hxx" + +//------------------------------------------------------------------------ + +ScWaitCursorOff::ScWaitCursorOff( Window* pWinP ) + : + pWin( pWinP ), + nWaiters(0) +{ + if ( pWin ) + { + while ( pWin->IsWait() ) + { + nWaiters++; + pWin->LeaveWait(); + } + } +} + +ScWaitCursorOff::~ScWaitCursorOff() +{ + if ( pWin ) + { + while ( nWaiters ) + { + nWaiters--; + pWin->EnterWait(); + } + } +} + + + + |