1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: tabcont.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
36 // INCLUDE ---------------------------------------------------------------
38 #include <sfx2/viewfrm.hxx>
39 #include <sfx2/dispatch.hxx>
40 #include <sfx2/docfile.hxx>
41 #include <vcl/sound.hxx>
42 #include <tools/urlobj.hxx>
43 #include <vcl/svapp.hxx>
44 #include "tabcont.hxx"
45 #include "tabvwsh.hxx"
48 #include "scresid.hxx"
50 #include "globstr.hrc"
51 #include "transobj.hxx"
52 #include "clipparam.hxx"
55 // STATIC DATA -----------------------------------------------------------
57 //==================================================================
59 ScTabControl::ScTabControl( Window
* pParent
, ScViewData
* pData
) :
60 TabBar( pParent
, WinBits( WB_BORDER
| WB_3DLOOK
| WB_SCROLL
|
61 WB_RANGESELECT
| WB_MULTISELECT
| WB_DRAG
| WB_SIZEABLE
) ),
62 DropTargetHelper( this ),
63 DragSourceHelper( this ),
65 nMouseClickPageId( TABBAR_PAGE_NOTFOUND
),
66 nSelPageIdByMouse( TABBAR_PAGE_NOTFOUND
),
69 ScDocument
* pDoc
= pViewData
->GetDocument();
73 SCTAB nCount
= pDoc
->GetTableCount();
74 for (SCTAB i
=0; i
<nCount
; i
++)
76 if (pDoc
->IsVisible(i
))
78 if (pDoc
->GetName(i
,aString
))
80 if ( pDoc
->IsScenario(i
) )
81 InsertPage( static_cast<sal_uInt16
>(i
)+1, aString
, TPB_SPECIAL
);
83 InsertPage( static_cast<sal_uInt16
>(i
)+1, aString
);
84 if ( !pViewData
->IsDefaultTabBgColor(i
) )
86 aTabBgColor
= pViewData
->GetTabBgColor(i
);
87 /*SetTabBgColor(static_cast<sal_uInt16>(i)+1, aTabBgColor, pViewData->IsDefaultTabBgColor(i) );*/
88 SetTabBgColor( static_cast<sal_uInt16
>(i
)+1, aTabBgColor
);
94 SetCurPageId( static_cast<sal_uInt16
>(pViewData
->GetTabNo()) + 1 );
96 SetSizePixel( Size(SC_TABBAR_DEFWIDTH
, 0) );
98 SetSplitHdl( LINK( pViewData
->GetView(), ScTabView
, TabBarResize
) );
103 ScTabControl::~ScTabControl()
107 USHORT
ScTabControl::GetMaxId() const
109 USHORT nVisCnt
= GetPageCount();
111 return GetPageId(nVisCnt
-1);
116 SCTAB
ScTabControl::GetPrivatDropPos(const Point
& rPos
)
118 USHORT nPos
= ShowDropPos(rPos
);
120 SCTAB nRealPos
= static_cast<SCTAB
>(nPos
);
124 ScDocument
* pDoc
= pViewData
->GetDocument();
126 SCTAB nCount
= pDoc
->GetTableCount();
130 for (SCTAB i
=0; i
<nCount
; i
++)
132 if (pDoc
->IsVisible(i
))
138 for (j
=i
+1; j
<nCount
; j
++)
140 if (pDoc
->IsVisible(j
))
154 void ScTabControl::MouseButtonDown( const MouseEvent
& rMEvt
)
156 ScModule
* pScMod
= SC_MOD();
157 if ( !pScMod
->IsModalMode() && !pScMod
->IsFormulaMode() && !IsInEditMode() )
160 pViewData
->GetViewShell()->SetActive(); // Appear und SetViewFrame
161 pViewData
->GetView()->ActiveGrabFocus();
164 /* #47745# Click into free area -> insert new sheet (like in Draw).
165 Needing clean left click without modifiers (may be context menu).
166 #106948# Remember clicks to all pages, to be able to move mouse pointer later. */
167 if( rMEvt
.IsLeft() && (rMEvt
.GetModifier() == 0) )
168 nMouseClickPageId
= GetPageId( rMEvt
.GetPosPixel() );
170 nMouseClickPageId
= TABBAR_PAGE_NOTFOUND
;
172 TabBar::MouseButtonDown( rMEvt
);
175 void ScTabControl::MouseButtonUp( const MouseEvent
& rMEvt
)
177 Point aPos
= PixelToLogic( rMEvt
.GetPosPixel() );
179 // mouse button down and up on same page?
180 if( nMouseClickPageId
!= GetPageId( aPos
) )
181 nMouseClickPageId
= TABBAR_PAGE_NOTFOUND
;
183 if ( rMEvt
.GetClicks() == 2 && rMEvt
.IsLeft() && nMouseClickPageId
!= 0 && nMouseClickPageId
!= TAB_PAGE_NOTFOUND
)
185 SfxDispatcher
* pDispatcher
= pViewData
->GetViewShell()->GetViewFrame()->GetDispatcher();
186 pDispatcher
->Execute( FID_TAB_MENU_RENAME
, SFX_CALLMODE_SYNCHRON
| SFX_CALLMODE_RECORD
);
189 if( nMouseClickPageId
== 0 )
191 // Click in the area next to the existing tabs:
192 // #i70320# if several sheets are selected, deselect all ecxept the current sheet,
193 // otherwise add new sheet
194 USHORT nSlot
= ( GetSelectPageCount() > 1 ) ? FID_TAB_DESELECTALL
: FID_INS_TABLE
;
195 SfxDispatcher
* pDispatcher
= pViewData
->GetViewShell()->GetViewFrame()->GetDispatcher();
196 pDispatcher
->Execute( nSlot
, SFX_CALLMODE_SYNCHRON
| SFX_CALLMODE_RECORD
);
197 // forget page ID, to be really sure that the dialog is not called twice
198 nMouseClickPageId
= TABBAR_PAGE_NOTFOUND
;
201 TabBar::MouseButtonUp( rMEvt
);
204 void ScTabControl::Select()
206 /* Remember last clicked page ID. */
207 nSelPageIdByMouse
= nMouseClickPageId
;
208 /* Reset nMouseClickPageId, so that next Select() call may invalidate
209 nSelPageIdByMouse (i.e. if called from keyboard). */
210 nMouseClickPageId
= TABBAR_PAGE_NOTFOUND
;
212 ScModule
* pScMod
= SC_MOD();
213 ScDocument
* pDoc
= pViewData
->GetDocument();
214 ScMarkData
& rMark
= pViewData
->GetMarkData();
215 SCTAB nCount
= pDoc
->GetTableCount();
218 if ( pScMod
->IsTableLocked() ) // darf jetzt nicht umgeschaltet werden ?
220 // den alten Zustand des TabControls wiederherstellen:
222 for (i
=0; i
<nCount
; i
++)
223 SelectPage( static_cast<sal_uInt16
>(i
)+1, rMark
.GetTableSelect(i
) );
224 SetCurPageId( static_cast<sal_uInt16
>(pViewData
->GetTabNo()) + 1 );
230 USHORT nCurId
= GetCurPageId();
231 if (!nCurId
) return; // kann vorkommen, wenn bei Excel-Import alles versteckt ist
232 USHORT nPage
= nCurId
- 1;
234 // OLE-inplace deaktivieren
235 if ( nPage
!= static_cast<sal_uInt16
>(pViewData
->GetTabNo()) )
236 pViewData
->GetView()->DrawMarkListHasChanged();
238 // InputEnterHandler nur wenn nicht Referenzeingabe
240 BOOL bRefMode
= pScMod
->IsFormulaMode();
242 pScMod
->InputEnterHandler();
244 for (i
=0; i
<nCount
; i
++)
245 rMark
.SelectTable( i
, IsPageSelected(static_cast<sal_uInt16
>(i
)+1) );
247 /* Markierungen werden per Default nicht pro Tabelle gehalten
248 USHORT nSelCnt = GetSelectPageCount();
250 pDoc->ExtendMarksFromTable( nPage );
253 SfxDispatcher
& rDisp
= pViewData
->GetDispatcher();
254 if (rDisp
.IsLocked())
255 pViewData
->GetView()->SetTabNo( static_cast<SCTAB
>(nPage
) );
258 // Tabelle fuer Basic ist 1-basiert
259 SfxUInt16Item
aItem( SID_CURRENTTAB
, nPage
+ 1 );
260 rDisp
.Execute( SID_CURRENTTAB
, SFX_CALLMODE_SLOT
| SFX_CALLMODE_RECORD
,
261 &aItem
, (void*) NULL
);
264 SfxBindings
& rBind
= pViewData
->GetBindings();
265 rBind
.Invalidate( FID_FILL_TAB
);
266 rBind
.Invalidate( FID_TAB_DESELECTALL
);
268 rBind
.Invalidate( FID_INS_TABLE
);
269 rBind
.Invalidate( FID_TAB_APPEND
);
270 rBind
.Invalidate( FID_TAB_MOVE
);
271 rBind
.Invalidate( FID_TAB_RENAME
);
272 rBind
.Invalidate( FID_DELETE_TABLE
);
273 rBind
.Invalidate( FID_TABLE_SHOW
);
274 rBind
.Invalidate( FID_TABLE_HIDE
);
275 rBind
.Invalidate( FID_TAB_SET_TAB_BG_COLOR
);
277 // SetReference nur wenn der Konsolidieren-Dialog offen ist
278 // (fuer Referenzen ueber mehrere Tabellen)
279 // bei anderen gibt das nur unnoetiges Gezappel
281 if ( bRefMode
&& pViewData
->GetRefType() == SC_REFTYPE_REF
)
282 if ( pViewData
->GetViewShell()->GetViewFrame()->HasChildWindow(SID_OPENDLG_CONSOLIDATE
) )
285 pViewData
->GetRefStartX(), pViewData
->GetRefStartY(), pViewData
->GetRefStartZ(),
286 pViewData
->GetRefEndX(), pViewData
->GetRefEndY(), pViewData
->GetRefEndZ() );
287 pScMod
->SetReference( aRange
, pDoc
, &rMark
);
288 pScMod
->EndReference(); // wegen Auto-Hide
292 void ScTabControl::UpdateStatus()
294 ScDocument
* pDoc
= pViewData
->GetDocument();
295 ScMarkData
& rMark
= pViewData
->GetMarkData();
296 BOOL bActive
= pViewData
->IsActive();
298 SCTAB nCount
= pDoc
->GetTableCount();
301 SCTAB nMaxCnt
= Max( nCount
, static_cast<SCTAB
>(GetMaxId()) );
304 BOOL bModified
= FALSE
; // Tabellen-Namen
305 for (i
=0; i
<nMaxCnt
&& !bModified
; i
++)
307 if (pDoc
->IsVisible(i
))
309 pDoc
->GetName(i
,aString
);
310 aTabBgColor
= pViewData
->GetTabBgColor(i
);
317 if ( (GetPageText(static_cast<sal_uInt16
>(i
)+1) != aString
) || (GetTabBgColor(static_cast<sal_uInt16
>(i
)+1) != aTabBgColor
) )
324 for (i
=0; i
<nCount
; i
++)
326 if (pDoc
->IsVisible(i
))
328 if (pDoc
->GetName(i
,aString
))
330 if ( pDoc
->IsScenario(i
) )
331 InsertPage( static_cast<sal_uInt16
>(i
)+1, aString
, TPB_SPECIAL
);
333 InsertPage( static_cast<sal_uInt16
>(i
)+1, aString
);
334 if ( !pViewData
->IsDefaultTabBgColor(i
) )
336 aTabBgColor
= pViewData
->GetTabBgColor(i
);
337 SetTabBgColor( static_cast<sal_uInt16
>(i
)+1, aTabBgColor
);
343 SetCurPageId( static_cast<sal_uInt16
>(pViewData
->GetTabNo()) + 1 );
347 bModified
= FALSE
; // Selektion
348 for (i
=0; i
<nMaxCnt
&& !bModified
; i
++)
349 if ( rMark
.GetTableSelect(i
) != IsPageSelected(static_cast<sal_uInt16
>(i
)+1) )
352 // #i99576# the following loop is mis-optimized on unxsoli4 and the reason
353 // why this file is in NOOPTFILES.
355 for (i
=0; i
<nCount
; i
++)
356 SelectPage( static_cast<sal_uInt16
>(i
)+1, rMark
.GetTableSelect(i
) );
363 void ScTabControl::ActivateView(BOOL bActivate
)
365 // ScDocument* pDoc = pViewData->GetDocument();
366 ScMarkData
& rMark
= pViewData
->GetMarkData();
368 // ResetMark direkt in TabView
369 // pDoc->ResetMark();
371 USHORT nCurId
= GetCurPageId();
372 if (!nCurId
) return; // kann vorkommen, wenn bei Excel-Import alles versteckt ist
373 USHORT nPage
= nCurId
- 1;
374 // USHORT nCount = GetMaxId();
378 for (i=0; i<nCount; i++)
380 SelectPage( i+1, FALSE );
382 rMark.SelectTable( i, FALSE );
387 SelectPage( nPage
+1, TRUE
);
388 rMark
.SelectTable( static_cast<SCTAB
>(nPage
), TRUE
);
393 void ScTabControl::SetSheetLayoutRTL( BOOL bSheetRTL
)
395 SetEffectiveRTL( bSheetRTL
);
396 nSelPageIdByMouse
= TABBAR_PAGE_NOTFOUND
;
400 void ScTabControl::Command( const CommandEvent
& rCEvt
)
402 ScModule
* pScMod
= SC_MOD();
403 ScTabViewShell
* pViewSh
= pViewData
->GetViewShell();
404 BOOL bDisable
= pScMod
->IsFormulaMode() || pScMod
->IsModalMode();
406 // ViewFrame erstmal aktivieren (Bug 19493):
407 pViewSh
->SetActive();
409 USHORT nCmd
= rCEvt
.GetCommand();
410 if ( nCmd
== COMMAND_CONTEXTMENU
)
414 // #i18735# select the page that is under the mouse cursor
415 // if multiple tables are selected and the one under the cursor
416 // is not part of them then unselect them
417 USHORT nId
= GetPageId( rCEvt
.GetMousePosPixel() );
420 BOOL bAlreadySelected
= IsPageSelected( nId
);
421 //make the clicked page the current one
423 //change the selection when the current one is not already
424 //selected or part of a multi selection
425 if(!bAlreadySelected
)
427 USHORT nCount
= GetMaxId();
429 for (USHORT i
=1; i
<=nCount
; i
++)
430 SelectPage( i
, i
==nId
);
435 // #i52073# OLE inplace editing has to be stopped before showing the sheet tab context menu
436 pViewSh
->DeactivateOle();
439 // get Dispatcher from ViewData (ViewFrame) instead of Shell (Frame), so it can't be null
440 pViewData
->GetDispatcher().ExecutePopup( ScResId(RID_POPUP_TAB
) );
445 void ScTabControl::StartDrag( sal_Int8
/* nAction */, const Point
& rPosPixel
)
447 ScModule
* pScMod
= SC_MOD();
448 BOOL bDisable
= pScMod
->IsFormulaMode() || pScMod
->IsModalMode();
452 Region
aRegion( Rectangle(0,0,0,0) );
453 CommandEvent
aCEvt( rPosPixel
, COMMAND_STARTDRAG
, TRUE
); // needed for StartDrag
454 if (TabBar::StartDrag( aCEvt
, aRegion
))
459 void ScTabControl::DoDrag( const Region
& /* rRegion */ )
461 ScDocShell
* pDocSh
= pViewData
->GetDocShell();
462 ScDocument
* pDoc
= pDocSh
->GetDocument();
464 SCTAB nTab
= pViewData
->GetTabNo();
465 ScMarkData aTabMark
= pViewData
->GetMarkData();
466 aTabMark
.ResetMark(); // doesn't change marked table information
467 aTabMark
.SetMarkArea( ScRange(0,0,nTab
,MAXCOL
,MAXROW
,nTab
) );
469 ScDocument
* pClipDoc
= new ScDocument( SCDOCMODE_CLIP
);
470 ScClipParam
aClipParam(ScRange(0, 0, 0, MAXCOL
, MAXROW
, 0), false);
471 pDoc
->CopyToClip(aClipParam
, pClipDoc
, &aTabMark
, false);
473 TransferableObjectDescriptor aObjDesc
;
474 pDocSh
->FillTransferableObjectDescriptor( aObjDesc
);
475 aObjDesc
.maDisplayName
= pDocSh
->GetMedium()->GetURLObject().GetURLNoPass();
476 // maSize is set in ScTransferObj ctor
478 ScTransferObj
* pTransferObj
= new ScTransferObj( pClipDoc
, aObjDesc
);
479 com::sun::star::uno::Reference
<com::sun::star::datatransfer::XTransferable
> xTransferable( pTransferObj
);
481 pTransferObj
->SetDragSourceFlags( SC_DROP_TABLE
);
483 pTransferObj
->SetDragSource( pDocSh
, aTabMark
);
485 Window
* pWindow
= pViewData
->GetActiveWin();
486 SC_MOD()->SetDragObject( pTransferObj
, NULL
); // for internal D&D
487 pTransferObj
->StartDrag( pWindow
, DND_ACTION_COPYMOVE
| DND_ACTION_LINK
);
490 USHORT
lcl_DocShellNr( ScDocument
* pDoc
)
492 USHORT nShellCnt
= 0;
493 SfxObjectShell
* pShell
= SfxObjectShell::GetFirst();
496 if ( pShell
->Type() == TYPE(ScDocShell
) )
498 if ( ((ScDocShell
*)pShell
)->GetDocument() == pDoc
)
503 pShell
= SfxObjectShell::GetNext( *pShell
);
506 DBG_ERROR("Dokument nicht gefunden");
510 sal_Int8
ScTabControl::ExecuteDrop( const ExecuteDropEvent
& rEvt
)
514 ScDocument
* pDoc
= pViewData
->GetDocument();
515 const ScDragData
& rData
= SC_MOD()->GetDragData();
516 if ( rData
.pCellTransfer
&& ( rData
.pCellTransfer
->GetDragSourceFlags() & SC_DROP_TABLE
) &&
517 rData
.pCellTransfer
->GetSourceDocument() == pDoc
)
519 // moving of tables within the document
520 SCTAB nPos
= GetPrivatDropPos( rEvt
.maPosPixel
);
523 if ( nPos
== rData
.pCellTransfer
->GetVisibleTab() && rEvt
.mnAction
== DND_ACTION_MOVE
)
525 // #i83005# do nothing - don't move to the same position
526 // (too easily triggered unintentionally, and might take a long time in large documents)
530 if ( !pDoc
->GetChangeTrack() && pDoc
->IsDocEditable() )
532 //! use table selection from the tab control where dragging was started?
533 pViewData
->GetView()->MoveTable( lcl_DocShellNr(pDoc
), nPos
, rEvt
.mnAction
!= DND_ACTION_MOVE
);
535 rData
.pCellTransfer
->SetDragWasInternal(); // don't delete
546 sal_Int8
ScTabControl::AcceptDrop( const AcceptDropEvent
& rEvt
)
548 if ( rEvt
.mbLeaving
)
552 return rEvt
.mnAction
;
555 const ScDocument
* pDoc
= pViewData
->GetDocument();
556 const ScDragData
& rData
= SC_MOD()->GetDragData();
557 if ( rData
.pCellTransfer
&& ( rData
.pCellTransfer
->GetDragSourceFlags() & SC_DROP_TABLE
) &&
558 rData
.pCellTransfer
->GetSourceDocument() == pDoc
)
560 // moving of tables within the document
561 if ( !pDoc
->GetChangeTrack() && pDoc
->IsDocEditable() )
563 ShowDropPos( rEvt
.maPosPixel
);
564 return rEvt
.mnAction
;
567 else // switch sheets for all formats
569 SwitchPage( rEvt
.maPosPixel
); // switch sheet after timeout
570 return 0; // nothing can be dropped here
576 long ScTabControl::StartRenaming()
578 if ( pViewData
->GetDocument()->IsDocEditable() )
579 return TABBAR_RENAMING_YES
;
581 return TABBAR_RENAMING_NO
;
584 long ScTabControl::AllowRenaming()
586 ScTabViewShell
* pViewSh
= pViewData
->GetViewShell();
587 DBG_ASSERT( pViewSh
, "pViewData->GetViewShell()" );
589 long nRet
= TABBAR_RENAMING_CANCEL
;
590 USHORT nId
= GetEditPageId();
593 SCTAB nTab
= nId
- 1;
594 String aNewName
= GetEditText();
595 BOOL bDone
= pViewSh
->RenameTable( aNewName
, nTab
);
597 nRet
= TABBAR_RENAMING_YES
;
598 else if ( bErrorShown
)
600 // if the error message from this TabControl is currently visible,
601 // don't end edit mode now, to avoid problems when returning to
602 // the other call (showing the error) - this should not happen
603 DBG_ERROR("ScTabControl::AllowRenaming: nested calls");
604 nRet
= TABBAR_RENAMING_NO
;
606 else if ( Application::IsInModalMode() )
608 // #73472# don't show error message above any modal dialog
609 // instead cancel renaming without error message
610 nRet
= TABBAR_RENAMING_CANCEL
;
615 pViewSh
->ErrorMessage( STR_INVALIDTABNAME
);
617 nRet
= TABBAR_RENAMING_NO
;
623 void ScTabControl::EndRenaming()
626 pViewData
->GetView()->ActiveGrabFocus();
629 void ScTabControl::Mirror()
632 if( nSelPageIdByMouse
!= TABBAR_PAGE_NOTFOUND
)
634 Rectangle
aRect( GetPageRect( GetCurPageId() ) );
635 if( !aRect
.IsEmpty() )
636 SetPointerPosPixel( aRect
.Center() );
637 nSelPageIdByMouse
= TABBAR_PAGE_NOTFOUND
; // only once after a Select()