merge the formfield patch from ooo-build
[ooovba.git] / sc / source / ui / view / tabcont.cxx
blobec447b1a899eda34acd8274cc58801cff26ddace
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 $
10 * $Revision: 1.17 $
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"
46 #include "docsh.hxx"
47 #include "scmod.hxx"
48 #include "scresid.hxx"
49 #include "sc.hrc"
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 ),
64 pViewData( pData ),
65 nMouseClickPageId( TABBAR_PAGE_NOTFOUND ),
66 nSelPageIdByMouse( TABBAR_PAGE_NOTFOUND ),
67 bErrorShown( FALSE )
69 ScDocument* pDoc = pViewData->GetDocument();
71 String aString;
72 Color aTabBgColor;
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 );
82 else
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 ) );
100 EnableEditMode();
103 ScTabControl::~ScTabControl()
107 USHORT ScTabControl::GetMaxId() const
109 USHORT nVisCnt = GetPageCount();
110 if (nVisCnt)
111 return GetPageId(nVisCnt-1);
113 return 0;
116 SCTAB ScTabControl::GetPrivatDropPos(const Point& rPos )
118 USHORT nPos = ShowDropPos(rPos);
120 SCTAB nRealPos = static_cast<SCTAB>(nPos);
122 if(nPos !=0 )
124 ScDocument* pDoc = pViewData->GetDocument();
126 SCTAB nCount = pDoc->GetTableCount();
128 USHORT nViewPos=0;
129 nRealPos = nCount;
130 for (SCTAB i=0; i<nCount; i++)
132 if (pDoc->IsVisible(i))
134 nViewPos++;
135 if(nViewPos==nPos)
137 SCTAB j;
138 for (j=i+1; j<nCount; j++)
140 if (pDoc->IsVisible(j))
142 break;
145 nRealPos =j;
146 break;
151 return nRealPos ;
154 void ScTabControl::MouseButtonDown( const MouseEvent& rMEvt )
156 ScModule* pScMod = SC_MOD();
157 if ( !pScMod->IsModalMode() && !pScMod->IsFormulaMode() && !IsInEditMode() )
159 // View aktivieren
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() );
169 else
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();
216 SCTAB i;
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 );
226 Sound::Beep();
227 return;
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();
241 if (!bRefMode)
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();
249 if (nSelCnt>1)
250 pDoc->ExtendMarksFromTable( nPage );
253 SfxDispatcher& rDisp = pViewData->GetDispatcher();
254 if (rDisp.IsLocked())
255 pViewData->GetView()->SetTabNo( static_cast<SCTAB>(nPage) );
256 else
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) )
284 ScRange aRange(
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();
299 SCTAB i;
300 String aString;
301 SCTAB nMaxCnt = Max( nCount, static_cast<SCTAB>(GetMaxId()) );
302 Color aTabBgColor;
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);
312 else
314 aString.Erase();
317 if ( (GetPageText(static_cast<sal_uInt16>(i)+1) != aString) || (GetTabBgColor(static_cast<sal_uInt16>(i)+1) != aTabBgColor) )
318 bModified = TRUE;
321 if (bModified)
323 Clear();
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 );
332 else
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 );
345 if (bActive)
347 bModified = FALSE; // Selektion
348 for (i=0; i<nMaxCnt && !bModified; i++)
349 if ( rMark.GetTableSelect(i) != IsPageSelected(static_cast<sal_uInt16>(i)+1) )
350 bModified = TRUE;
352 // #i99576# the following loop is mis-optimized on unxsoli4 and the reason
353 // why this file is in NOOPTFILES.
354 if ( bModified )
355 for (i=0; i<nCount; i++)
356 SelectPage( static_cast<sal_uInt16>(i)+1, rMark.GetTableSelect(i) );
358 else
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();
377 USHORT i;
378 for (i=0; i<nCount; i++)
380 SelectPage( i+1, FALSE );
381 if (bActivate)
382 rMark.SelectTable( i, FALSE );
385 if (bActivate)
387 SelectPage( nPage+1, TRUE );
388 rMark.SelectTable( static_cast<SCTAB>(nPage), TRUE );
390 Invalidate();
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 )
412 if (!bDisable)
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() );
418 if (nId)
420 BOOL bAlreadySelected = IsPageSelected( nId );
421 //make the clicked page the current one
422 SetCurPageId( nId );
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 );
431 Select();
435 // #i52073# OLE inplace editing has to be stopped before showing the sheet tab context menu
436 pViewSh->DeactivateOle();
438 // Popup-Menu:
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();
450 if (!bDisable)
452 Region aRegion( Rectangle(0,0,0,0) );
453 CommandEvent aCEvt( rPosPixel, COMMAND_STARTDRAG, TRUE ); // needed for StartDrag
454 if (TabBar::StartDrag( aCEvt, aRegion ))
455 DoDrag( 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();
494 while ( pShell )
496 if ( pShell->Type() == TYPE(ScDocShell) )
498 if ( ((ScDocShell*)pShell)->GetDocument() == pDoc )
499 return nShellCnt;
501 ++nShellCnt;
503 pShell = SfxObjectShell::GetNext( *pShell );
506 DBG_ERROR("Dokument nicht gefunden");
507 return 0;
510 sal_Int8 ScTabControl::ExecuteDrop( const ExecuteDropEvent& rEvt )
512 EndSwitchPage();
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 );
521 HideDropPos();
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)
528 else
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
536 return TRUE;
538 else
539 Sound::Beep();
543 return 0;
546 sal_Int8 ScTabControl::AcceptDrop( const AcceptDropEvent& rEvt )
548 if ( rEvt.mbLeaving )
550 EndSwitchPage();
551 HideDropPos();
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
573 return 0;
576 long ScTabControl::StartRenaming()
578 if ( pViewData->GetDocument()->IsDocEditable() )
579 return TABBAR_RENAMING_YES;
580 else
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();
591 if ( nId )
593 SCTAB nTab = nId - 1;
594 String aNewName = GetEditText();
595 BOOL bDone = pViewSh->RenameTable( aNewName, nTab );
596 if ( bDone )
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;
612 else
614 bErrorShown = TRUE;
615 pViewSh->ErrorMessage( STR_INVALIDTABNAME );
616 bErrorShown = FALSE;
617 nRet = TABBAR_RENAMING_NO;
620 return nRet;
623 void ScTabControl::EndRenaming()
625 if ( HasFocus() )
626 pViewData->GetView()->ActiveGrabFocus();
629 void ScTabControl::Mirror()
631 TabBar::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()