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: gridwin2.cxx,v $
10 * $Revision: 1.16.32.1 $
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 "scitems.hxx"
39 #include <vcl/msgbox.hxx>
40 #include <vcl/sound.hxx>
42 #include "gridwin.hxx"
43 #include "tabvwsh.hxx"
45 #include "viewdata.hxx"
47 //CHINA001 #include "pfiltdlg.hxx"
48 #include "uiitems.hxx"
49 #include "scresid.hxx"
51 #include "globstr.hrc"
52 #include "pagedata.hxx"
53 #include "dpobject.hxx"
55 #include "dpoutput.hxx" // ScDPPositionData
56 #include "dpshttab.hxx"
57 #include "dbdocfun.hxx"
58 #include "dpcontrol.hxx"
59 #include "dpcontrol.hrc"
60 #include "strload.hxx"
61 #include "userlist.hxx"
63 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
64 #include "scabstdlg.hxx" //CHINA001
69 using namespace com::sun::star
;
71 using ::std::auto_ptr
;
72 using ::std::hash_map
;
73 using ::rtl::OUString
;
74 using ::rtl::OUStringHash
;
76 // STATIC DATA -----------------------------------------------------------
78 // -----------------------------------------------------------------------
80 BOOL
ScGridWindow::HasPageFieldData( SCCOL nCol
, SCROW nRow
) const
82 ScDocument
* pDoc
= pViewData
->GetDocument();
83 SCTAB nTab
= pViewData
->GetTabNo();
84 ScDPObject
* pDPObj
= pDoc
->GetDPAtCursor(nCol
, nRow
, nTab
);
85 if ( pDPObj
&& nCol
> 0 )
87 // look for the dimension header left of the drop-down arrow
88 USHORT nOrient
= sheet::DataPilotFieldOrientation_HIDDEN
;
89 long nField
= pDPObj
->GetHeaderDim( ScAddress( nCol
-1, nRow
, nTab
), nOrient
);
90 if ( nField
>= 0 && nOrient
== sheet::DataPilotFieldOrientation_PAGE
)
92 BOOL bIsDataLayout
= FALSE
;
93 String aFieldName
= pDPObj
->GetDimName( nField
, bIsDataLayout
);
94 if ( aFieldName
.Len() && !bIsDataLayout
)
101 // private method for mouse button handling
102 BOOL
ScGridWindow::DoPageFieldSelection( SCCOL nCol
, SCROW nRow
)
104 if ( HasPageFieldData( nCol
, nRow
) )
106 DoPageFieldMenue( nCol
, nRow
);
112 void ScGridWindow::DoPushButton( SCCOL nCol
, SCROW nRow
, const MouseEvent
& rMEvt
)
114 ScDocument
* pDoc
= pViewData
->GetDocument();
115 SCTAB nTab
= pViewData
->GetTabNo();
117 ScDPObject
* pDPObj
= pDoc
->GetDPAtCursor(nCol
, nRow
, nTab
);
119 #if OLD_PIVOT_IMPLEMENTATION
120 ScPivotCollection
* pPivotCollection
= pDoc
->GetPivotCollection();
121 ScPivot
* pPivot
= pPivotCollection
->GetPivotAtCursor(nCol
, nRow
, nTab
);
123 if (pPivot
) // alte Pivottabellen
125 if (pPivot
->IsFilterAtCursor(nCol
, nRow
, nTab
))
127 ReleaseMouse(); // falls schon beim ButtonDown gecaptured, #44018#
129 ScQueryParam aQueryParam
;
130 pPivot
->GetQuery(aQueryParam
);
131 SCTAB nSrcTab
= pPivot
->GetSrcArea().aStart
.Tab();
133 SfxItemSet
aArgSet( pViewData
->GetViewShell()->GetPool(),
134 SCITEM_QUERYDATA
, SCITEM_QUERYDATA
);
135 aArgSet
.Put( ScQueryItem( SCITEM_QUERYDATA
, pViewData
, &aQueryParam
) );
137 //CHINA001 ScPivotFilterDlg* pDlg = new ScPivotFilterDlg(
138 //CHINA001 pViewData->GetViewShell()->GetDialogParent(),
139 //CHINA001 aArgSet, nSrcTab );
140 ScAbstractDialogFactory
* pFact
= ScAbstractDialogFactory::Create();
141 DBG_ASSERT(pFact
, "ScAbstractFactory create fail!");//CHINA001
143 AbstractScPivotFilterDlg
* pDlg
= pFact
->CreateScPivotFilterDlg( pViewData
->GetViewShell()->GetDialogParent(),
145 RID_SCDLG_PIVOTFILTER
);
146 DBG_ASSERT(pDlg
, "Dialog create fail!");//CHINA001
147 if ( pDlg
->Execute() == RET_OK
)
149 ScPivot
* pNewPivot
= pPivot
->CreateNew();
151 const ScQueryItem
& rQueryItem
= pDlg
->GetOutputItem();
152 pNewPivot
->SetQuery(rQueryItem
.GetQueryData());
154 PivotField
* pColArr
= new PivotField
[PIVOT_MAXFIELD
];
156 pPivot
->GetColFields( pColArr
, nColCount
);
157 PivotField
* pRowArr
= new PivotField
[PIVOT_MAXFIELD
];
159 pPivot
->GetRowFields( pRowArr
, nRowCount
);
160 PivotField
* pDataArr
= new PivotField
[PIVOT_MAXFIELD
];
162 pPivot
->GetDataFields( pDataArr
, nDataCount
);
164 pNewPivot
->SetColFields( pColArr
, nColCount
);
165 pNewPivot
->SetRowFields( pRowArr
, nRowCount
);
166 pNewPivot
->SetDataFields( pDataArr
, nDataCount
);
168 pNewPivot
->SetName( pPivot
->GetName() );
169 pNewPivot
->SetTag( pPivot
->GetTag() );
171 pViewData
->GetDocShell()->PivotUpdate( pPivot
, pNewPivot
);
178 if (pPivot
->GetColFieldAtCursor(nCol
, nRow
, nTab
, nField
))
181 nPivotField
= nField
;
182 bPivotColField
= TRUE
;
185 PivotTestMouse( rMEvt
, TRUE
);
189 else if (pPivot
->GetRowFieldAtCursor(nCol
, nRow
, nTab
, nField
))
192 nPivotField
= nField
;
193 bPivotColField
= FALSE
;
196 PivotTestMouse( rMEvt
, TRUE
);
206 USHORT nOrient
= sheet::DataPilotFieldOrientation_HIDDEN
;
207 ScAddress
aPos( nCol
, nRow
, nTab
);
208 long nField
= pDPObj
->GetHeaderDim( aPos
, nOrient
);
215 if (DPTestFieldPopupArrow(rMEvt
, aPos
, pDPObj
))
217 // field name pop up menu has been launched. Don't activate
223 DPTestMouse( rMEvt
, TRUE
);
226 else if ( pDPObj
->IsFilterButton(aPos
) )
228 ReleaseMouse(); // may have been captured in ButtonDown
230 ScQueryParam aQueryParam
;
232 const ScSheetSourceDesc
* pDesc
= pDPObj
->GetSheetDesc();
233 DBG_ASSERT(pDesc
, "no sheet source for filter button");
236 aQueryParam
= pDesc
->aQueryParam
;
237 nSrcTab
= pDesc
->aSourceRange
.aStart
.Tab();
240 SfxItemSet
aArgSet( pViewData
->GetViewShell()->GetPool(),
241 SCITEM_QUERYDATA
, SCITEM_QUERYDATA
);
242 aArgSet
.Put( ScQueryItem( SCITEM_QUERYDATA
, pViewData
, &aQueryParam
) );
244 //CHINA001 ScPivotFilterDlg* pDlg = new ScPivotFilterDlg(
245 //CHINA001 pViewData->GetViewShell()->GetDialogParent(),
246 //CHINA001 aArgSet, nSrcTab );
247 ScAbstractDialogFactory
* pFact
= ScAbstractDialogFactory::Create();
248 DBG_ASSERT(pFact
, "ScAbstractFactory create fail!");//CHINA001
250 AbstractScPivotFilterDlg
* pDlg
= pFact
->CreateScPivotFilterDlg( pViewData
->GetViewShell()->GetDialogParent(),
252 RID_SCDLG_PIVOTFILTER
);
253 DBG_ASSERT(pDlg
, "Dialog create fail!");//CHINA001
254 if ( pDlg
->Execute() == RET_OK
)
256 ScSheetSourceDesc aNewDesc
;
260 const ScQueryItem
& rQueryItem
= pDlg
->GetOutputItem();
261 aNewDesc
.aQueryParam
= rQueryItem
.GetQueryData();
263 ScDPObject
aNewObj( *pDPObj
);
264 aNewObj
.SetSheetDesc( aNewDesc
);
265 ScDBDocFunc
aFunc( *pViewData
->GetDocShell() );
266 aFunc
.DataPilotUpdate( pDPObj
, &aNewObj
, TRUE
, FALSE
);
267 pViewData
->GetView()->CursorPosChanged(); // shells may be switched
276 DBG_ERROR("Da is ja garnix");
280 #if OLD_PIVOT_IMPLEMENTATION
281 void ScGridWindow::DoPivotDrop( BOOL bDelete
, BOOL bToCols
, SCSIZE nDestPos
)
283 if ( nPivotField
== PIVOT_DATA_FIELD
&& bDelete
)
285 pViewData
->GetView()->ErrorMessage(STR_PIVOT_MOVENOTALLOWED
);
289 if ( bPivotColField
!= bToCols
&& !bDelete
)
291 SCSIZE nDestCount
= bToCols
? pDragPivot
->GetColFieldCount()
292 : pDragPivot
->GetRowFieldCount();
293 if ( nDestCount
>= PIVOT_MAXFIELD
) // schon voll?
295 // Versuch, mehr als PIVOT_MAXFIELD Eintraege zu erzeugen
296 pViewData
->GetView()->ErrorMessage(STR_PIVOT_ERROR
);
301 PivotField
* pColArr
= new PivotField
[PIVOT_MAXFIELD
];
303 pDragPivot
->GetColFields( pColArr
, nColCount
);
305 PivotField
* pRowArr
= new PivotField
[PIVOT_MAXFIELD
];
307 pDragPivot
->GetRowFields( pRowArr
, nRowCount
);
309 PivotField
* pDataArr
= new PivotField
[PIVOT_MAXFIELD
];
311 pDragPivot
->GetDataFields( pDataArr
, nDataCount
);
314 PivotField aMoveField
;
316 PivotField
* pSource
= bPivotColField
? pColArr
: pRowArr
;
317 SCSIZE
& rCount
= bPivotColField
? nColCount
: nRowCount
;
320 for (SCSIZE i
=0; i
<rCount
&& !bFound
; i
++)
321 if (pSource
[i
].nCol
== nPivotField
)
324 aMoveField
= pSource
[i
];
327 memmove( &pSource
[i
], &pSource
[i
+1], (rCount
-i
)*sizeof(PivotField
) );
328 if ( bPivotColField
== bToCols
)
338 PivotField
* pDest
= bToCols
? pColArr
: pRowArr
;
339 SCSIZE
& rDestCount
= bToCols
? nColCount
: nRowCount
;
341 if (nDestPos
< rDestCount
)
342 memmove( &pDest
[nDestPos
+1], &pDest
[nDestPos
],
343 (rDestCount
-nDestPos
)*sizeof(PivotField
) );
344 pDest
[nDestPos
] = aMoveField
;
348 BOOL bEmpty
= ( nColCount
+ nRowCount
== 0 ||
349 ( nColCount
+ nRowCount
== 1 && nDataCount
<= 1 ) );
351 if ( bEmpty
) // Pivottabelle loeschen
353 pViewData
->GetDocShell()->PivotUpdate( pDragPivot
, NULL
);
357 ScPivot
* pNewPivot
= pDragPivot
->CreateNew();
358 pNewPivot
->SetColFields( pColArr
, nColCount
);
359 pNewPivot
->SetRowFields( pRowArr
, nRowCount
);
360 pNewPivot
->SetDataFields( pDataArr
, nDataCount
);
362 pNewPivot
->SetName( pDragPivot
->GetName() );
363 pNewPivot
->SetTag( pDragPivot
->GetTag() );
365 pViewData
->GetDocShell()->PivotUpdate( pDragPivot
, pNewPivot
);
371 DBG_ASSERT(0,"Pivot-Eintrag nicht gefunden");
379 BOOL
ScGridWindow::PivotTestMouse( const MouseEvent
& rMEvt
, BOOL bMove
)
383 Point aPos
= rMEvt
.GetPosPixel();
391 Size aSize
= GetOutputSizePixel();
392 if ( aPos
.X() >= aSize
.Width() )
394 if ( aPos
.Y() >= aSize
.Height() )
396 if ( nDx
!= 0 || nDy
!= 0 )
400 // DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, FALSE );
402 UpdateDragRectOverlay();
406 pViewData
->GetView()->ScrollX( nDx
, WhichH(eWhich
) );
408 pViewData
->GetView()->ScrollY( nDy
, WhichV(eWhich
) );
415 pViewData
->GetPosFromPixel( aPos
.X(), aPos
.Y(), eWhich
, nPosX
, nPosY
);
418 pViewData
->GetMouseQuadrant( aPos
, eWhich
, nPosX
, nPosY
, bMouseLeft
, bMouseTop
);
425 pDragPivot
->GetDestArea( nPiCol1
, nPiRow1
, nPiCol2
, nPiRow2
, nTab
);
427 if ( nPosX
>= (SCsCOL
) nPiCol1
&& nPosX
<= (SCsCOL
) nPiCol2
&&
428 nPosY
>= (SCsROW
) nPiRow1
&& nPosY
<= (SCsROW
) nPiRow2
)
430 SCsROW nFilterAdd
= 2; // Platz fuer Filter-Button
431 SCsROW nColRows
= 1; //! Ueberschrift: 0, wenn keine Zeilen, aber mehrere Datenfelder
437 SCsCOL nRelX
= nPosX
- (SCsCOL
) nPiCol1
;
438 SCsROW nRelY
= nPosY
- (SCsROW
) nPiRow1
- nFilterAdd
;
440 PivotField
* pFieldArr
= new PivotField
[PIVOT_MAXFIELD
];
442 pDragPivot
->GetColFields( pFieldArr
, nColCount
);
444 pDragPivot
->GetRowFields( pFieldArr
, nRowCount
);
448 SCsCOL nColSize
= static_cast<SCsCOL
>(Max( nColCount
, (SCSIZE
) 1 ));
449 SCsROW nRowSize
= static_cast<SCsROW
>(Max( nRowCount
, (SCSIZE
) 1 ));
452 if (nRelX
< nColSize
&& nRelY
>= nRowSize
)
453 bToCols
= TRUE
; // links
454 else if (nRelY
< nRowSize
&& nRelX
>= nColSize
)
455 bToCols
= FALSE
; // oben
457 bToCols
= ( nRelY
-nRowSize
> static_cast<SCsCOLROW
>(nRelX
-nColSize
) );
461 BOOL bNothing
= FALSE
;
465 bBefore
= bMouseLeft
;
472 if (nDestCol
>= static_cast<SCsCOL
>(nColCount
))
474 nDestCol
= static_cast<SCsCOL
>(nColCount
)-1;
478 nNewStartY
= nPiRow1
+ nFilterAdd
+ static_cast<SCROW
>(nRowCount
) + nColRows
;
479 nNewEndY
= nPiRow2
- 1;
480 nNewStartX
= nPiCol1
+ (SCCOL
) nDestCol
;
481 nNewEndX
= nNewStartX
;
483 if ( !bPivotColField
) // von der anderen Seite
486 nNewEndX
= nNewStartX
- 1; // vor dem Feld
488 nNewStartX
= nNewEndX
+ 1; // hinter dem Feld
492 SCCOL nThisCol
= (SCCOL
) nPosX
; // absolute Spalte ( == Maus )
493 if ( nThisCol
< nPivotCol
)
495 nNewEndX
= nNewStartX
- 1; // vor dem Feld
498 else if ( nThisCol
> nPivotCol
)
500 nNewStartX
= nNewEndX
+ 1; // hinter dem Feld
506 SetPointer( Pointer( POINTER_PIVOT_ROW
) );
510 if (nRelY
<= 0 && static_cast<SCsCOLROW
>(nRelX
) < static_cast<SCsCOLROW
>(nColCount
)+static_cast<SCsCOLROW
>(nRowCount
))
512 nDestRow
= static_cast<SCsCOLROW
>(nRelX
) - static_cast<SCsCOLROW
>(nColCount
);
513 bBefore
= bMouseLeft
;
525 if (nDestRow
>= static_cast<SCsROW
>(nRowCount
))
527 nDestRow
= static_cast<SCsROW
>(nRowCount
)-1;
531 nNewStartX
= nPiCol1
+ (SCCOL
) nColCount
;
532 nNewEndX
= nPiCol2
- 1;
533 nNewStartY
= nPiRow1
+ nFilterAdd
+ nDestRow
+ nColRows
;
534 nNewEndY
= nNewStartY
;
535 if ( bPivotColField
) // von der anderen Seite
538 nNewEndY
= nNewStartY
- 1; // vor dem Feld
540 nNewStartY
= nNewEndY
+ 1; // hinter dem Feld
545 static_cast<SCCOL
>(static_cast<SCCOLROW
>(nDestRow
) +
546 static_cast<SCCOLROW
>(nColCount
) + nPiCol1
);
548 if ( nThisCol
< nPivotCol
)
551 nNewEndY
= nNewStartY
- 1; // vor dem Feld
553 else if ( nThisCol
> nPivotCol
)
556 nNewStartY
= nNewEndY
+ 1; // hinter dem Feld
561 SetPointer( Pointer( POINTER_PIVOT_COL
) );
566 if ( nNewStartX
!= nDragStartX
|| nNewEndX
!= nDragEndX
||
567 nNewStartY
!= nDragStartY
|| nNewEndY
!= nDragEndY
|| !bDragRect
)
570 // DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, FALSE );
572 nDragStartX
= nNewStartX
;
573 nDragStartY
= nNewStartY
;
574 nDragEndX
= nNewEndX
;
575 nDragEndY
= nNewEndY
;
578 // DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, FALSE );
580 UpdateDragRectOverlay();
587 // DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, FALSE );
589 UpdateDragRectOverlay();
594 SCSIZE nDestPos
= bToCols
? static_cast<SCSIZE
>(nDestCol
) : static_cast<SCSIZE
>(nDestRow
);
597 DoPivotDrop( FALSE
, bToCols
, nDestPos
);
606 SetPointer( Pointer( POINTER_PIVOT_DELETE
) );
608 // DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, FALSE );
610 UpdateDragRectOverlay();
613 DoPivotDrop( TRUE
, FALSE
,0 );
617 pViewData
->GetView()->SetTimer( this, rMEvt
); // Event wiederholen
619 pViewData
->GetView()->ResetTimer();
624 void ScGridWindow::PivotMouseMove( const MouseEvent
& rMEvt
)
626 PivotTestMouse( rMEvt
, TRUE
);
629 void ScGridWindow::PivotMouseButtonUp( const MouseEvent
& rMEvt
)
631 bPivotMouse
= FALSE
; // als erstes, falls PivotTestMouse eine Fehlermeldung bringt
634 PivotTestMouse( rMEvt
, FALSE
);
635 SetPointer( Pointer( POINTER_ARROW
) );
639 // -----------------------------------------------------------------------
641 // Data Pilot interaction
644 void ScGridWindow::DPTestMouse( const MouseEvent
& rMEvt
, BOOL bMove
)
646 DBG_ASSERT(pDragDPObj
, "pDragDPObj missing");
648 // scroll window if at edges
649 //! move this to separate method
652 Point aPixel
= rMEvt
.GetPosPixel();
656 if ( aPixel
.X() < 0 )
658 if ( aPixel
.Y() < 0 )
660 Size aSize
= GetOutputSizePixel();
661 if ( aPixel
.X() >= aSize
.Width() )
663 if ( aPixel
.Y() >= aSize
.Height() )
665 if ( nDx
!= 0 || nDy
!= 0 )
667 UpdateDragRect( FALSE
, Rectangle() );
670 pViewData
->GetView()->ScrollX( nDx
, WhichH(eWhich
) );
672 pViewData
->GetView()->ScrollY( nDy
, WhichV(eWhich
) );
681 pViewData
->GetPosFromPixel( aPixel
.X(), aPixel
.Y(), eWhich
, nPosX
, nPosY
);
684 pViewData
->GetMouseQuadrant( aPixel
, eWhich
, nPosX
, nPosY
, bMouseLeft
, bMouseTop
);
686 ScAddress
aPos( nPosX
, nPosY
, pViewData
->GetTabNo() );
691 BOOL bHasRange
= pDragDPObj
->GetHeaderDrag( aPos
, bMouseLeft
, bMouseTop
, nDPField
,
692 aPosRect
, nOrient
, nDimPos
);
693 UpdateDragRect( bHasRange
&& bMove
, aPosRect
);
695 if (bMove
) // set mouse pointer
697 PointerStyle ePointer
= POINTER_PIVOT_DELETE
;
701 case sheet::DataPilotFieldOrientation_COLUMN
: ePointer
= POINTER_PIVOT_COL
; break;
702 case sheet::DataPilotFieldOrientation_ROW
: ePointer
= POINTER_PIVOT_ROW
; break;
703 case sheet::DataPilotFieldOrientation_PAGE
:
704 case sheet::DataPilotFieldOrientation_DATA
: ePointer
= POINTER_PIVOT_FIELD
; break;
706 SetPointer( ePointer
);
708 else // execute change
711 nOrient
= sheet::DataPilotFieldOrientation_HIDDEN
;
714 String aDimName
= pDragDPObj
->GetDimName( nDPField
, bIsDataLayout
);
715 if ( bIsDataLayout
&& ( nOrient
!= sheet::DataPilotFieldOrientation_COLUMN
&&
716 nOrient
!= sheet::DataPilotFieldOrientation_ROW
) )
718 // removing data layout is not allowed
719 pViewData
->GetView()->ErrorMessage(STR_PIVOT_MOVENOTALLOWED
);
723 ScDPSaveData
aSaveData( *pDragDPObj
->GetSaveData() );
725 ScDPSaveDimension
* pDim
;
727 pDim
= aSaveData
.GetDataLayoutDimension();
729 pDim
= aSaveData
.GetDimensionByName(aDimName
);
730 pDim
->SetOrientation( nOrient
);
731 aSaveData
.SetPosition( pDim
, nDimPos
);
733 //! docfunc method with ScDPSaveData as argument?
735 ScDPObject
aNewObj( *pDragDPObj
);
736 aNewObj
.SetSaveData( aSaveData
);
737 ScDBDocFunc
aFunc( *pViewData
->GetDocShell() );
738 // when dragging fields, allow re-positioning (bAllowMove)
739 aFunc
.DataPilotUpdate( pDragDPObj
, &aNewObj
, TRUE
, FALSE
, TRUE
);
740 pViewData
->GetView()->CursorPosChanged(); // shells may be switched
745 pViewData
->GetView()->SetTimer( this, rMEvt
); // repeat event
747 pViewData
->GetView()->ResetTimer();
750 bool ScGridWindow::DPTestFieldPopupArrow(const MouseEvent
& rMEvt
, const ScAddress
& rPos
, ScDPObject
* pDPObj
)
752 // Get the geometry of the cell.
753 Point aSrcPos
= pViewData
->GetScrPos(rPos
.Col(), rPos
.Row(), eWhich
);
755 pViewData
->GetMergeSizePixel(rPos
.Col(), rPos
.Row(), nSizeX
, nSizeY
);
756 Size
aSrcSize(nSizeX
-1, nSizeY
-1);
758 // Check if the mouse cursor is clicking on the popup arrow box.
759 ScDPFieldButton
aBtn(this, &GetSettings().GetStyleSettings());
760 aBtn
.setBoundingBox(aSrcPos
, aSrcSize
);
763 aBtn
.getPopupBoundingBox(aPopupPos
, aPopupSize
);
764 Rectangle
aRec(aPopupPos
, aPopupSize
);
765 if (aRec
.IsInside(rMEvt
.GetPosPixel()))
767 // Mouse cursor inside the popup arrow box. Launch the field menu.
768 DPLaunchFieldPopupMenu(OutputToScreenPixel(aSrcPos
), aSrcSize
, rPos
, pDPObj
);
777 struct DPFieldPopupData
: public ScDPFieldPopupWindow::ExtendedData
779 ScPivotParam maDPParam
;
784 class DPFieldPopupOKAction
: public ScMenuFloatingWindow::Action
787 explicit DPFieldPopupOKAction(ScGridWindow
* p
) :
790 virtual void execute()
792 mpGridWindow
->UpdateDPFromFieldPopupMenu();
795 ScGridWindow
* mpGridWindow
;
798 class PopupSortAction
: public ScMenuFloatingWindow::Action
801 enum SortType
{ ASCENDING
, DESCENDING
, CUSTOM
};
803 explicit PopupSortAction(const ScAddress
& rPos
, SortType eType
, sal_uInt16 nUserListIndex
, ScTabViewShell
* pViewShell
) :
804 maPos(rPos
), meType(eType
), mnUserListIndex(nUserListIndex
), mpViewShell(pViewShell
) {}
806 virtual void execute()
811 mpViewShell
->DataPilotSort(maPos
, true);
814 mpViewShell
->DataPilotSort(maPos
, false);
817 mpViewShell
->DataPilotSort(maPos
, true, &mnUserListIndex
);
827 sal_uInt16 mnUserListIndex
;
828 ScTabViewShell
* mpViewShell
;
833 void ScGridWindow::DPLaunchFieldPopupMenu(
834 const Point
& rSrcPos
, const Size
& rSrcSize
, const ScAddress
& rPos
, ScDPObject
* pDPObj
)
836 // We need to get the list of field members.
837 auto_ptr
<DPFieldPopupData
> pDPData(new DPFieldPopupData
);
838 pDPObj
->FillLabelData(pDPData
->maDPParam
);
839 pDPData
->mpDPObj
= pDPObj
;
842 pDPData
->mnDim
= pDPObj
->GetHeaderDim(rPos
, nOrient
);
844 if (pDPData
->maDPParam
.maLabelArray
.size() <= static_cast<size_t>(pDPData
->mnDim
))
845 // out-of-bound dimension ID. This should never happen!
848 const ScDPLabelData
& rLabelData
= *pDPData
->maDPParam
.maLabelArray
[pDPData
->mnDim
];
850 mpDPFieldPopup
.reset(new ScDPFieldPopupWindow(this));
851 mpDPFieldPopup
->setExtendedData(pDPData
.release());
852 mpDPFieldPopup
->setOKAction(new DPFieldPopupOKAction(this));
854 sal_Int32 n
= rLabelData
.maMembers
.getLength();
855 mpDPFieldPopup
->setMemberSize(n
);
856 for (sal_Int32 i
= 0; i
< n
; ++i
)
857 mpDPFieldPopup
->addMember(rLabelData
.maMembers
[i
], rLabelData
.maVisible
[i
]);
858 mpDPFieldPopup
->initMembers();
861 vector
<OUString
> aUserSortNames
;
862 ScUserList
* pUserList
= ScGlobal::GetUserList();
865 sal_uInt16 n
= pUserList
->GetCount();
866 aUserSortNames
.reserve(n
);
867 for (sal_uInt16 i
= 0; i
< n
; ++i
)
869 ScUserListData
* pData
= static_cast<ScUserListData
*>((*pUserList
)[i
]);
870 aUserSortNames
.push_back(pData
->GetString());
874 // Populate the menus.
875 ScTabViewShell
* pViewShell
= pViewData
->GetViewShell();
876 mpDPFieldPopup
->addMenuItem(
877 ScRscStrLoader(RID_SC_DPCONTROL
, STR_MENU_SORT_ASC
).GetString(), true,
878 new PopupSortAction(rPos
, PopupSortAction::ASCENDING
, 0, pViewShell
));
879 mpDPFieldPopup
->addMenuItem(
880 ScRscStrLoader(RID_SC_DPCONTROL
, STR_MENU_SORT_DESC
).GetString(), true,
881 new PopupSortAction(rPos
, PopupSortAction::DESCENDING
, 0, pViewShell
));
882 ScMenuFloatingWindow
* pSubMenu
= mpDPFieldPopup
->addSubMenuItem(
883 ScRscStrLoader(RID_SC_DPCONTROL
, STR_MENU_SORT_CUSTOM
).GetString(), !aUserSortNames
.empty());
885 if (pSubMenu
&& !aUserSortNames
.empty())
887 size_t n
= aUserSortNames
.size();
888 for (size_t i
= 0; i
< n
; ++i
)
890 pSubMenu
->addMenuItem(
891 aUserSortNames
[i
], true,
892 new PopupSortAction(rPos
, PopupSortAction::CUSTOM
, i
, pViewShell
));
896 mpDPFieldPopup
->SetPopupModeEndHdl( LINK(this, ScGridWindow
, PopupModeEndHdl
) );
897 Rectangle
aCellRect(rSrcPos
, rSrcSize
);
898 mpDPFieldPopup
->StartPopupMode(aCellRect
, (FLOATWIN_POPUPMODE_DOWN
| FLOATWIN_POPUPMODE_GRABFOCUS
));
901 void ScGridWindow::UpdateDPFromFieldPopupMenu()
903 if (!mpDPFieldPopup
.get())
906 DPFieldPopupData
* pDPData
= static_cast<DPFieldPopupData
*>(mpDPFieldPopup
->getExtendedData());
910 ScDPObject
* pDPObj
= pDPData
->mpDPObj
;
911 ScDPObject
aNewDPObj(*pDPObj
);
912 aNewDPObj
.BuildAllDimensionMembers();
913 ScDPSaveData
* pSaveData
= aNewDPObj
.GetSaveData();
916 String aDimName
= pDPObj
->GetDimName(pDPData
->mnDim
, bIsDataLayout
);
917 ScDPSaveDimension
* pDim
= pSaveData
->GetDimensionByName(aDimName
);
921 hash_map
<OUString
, bool, OUStringHash
> aResult
;
922 mpDPFieldPopup
->getResult(aResult
);
923 pDim
->UpdateMemberVisibility(aResult
);
925 ScDBDocFunc
aFunc(*pViewData
->GetDocShell());
926 aFunc
.DataPilotUpdate(pDPObj
, &aNewDPObj
, true, false);
929 void ScGridWindow::DPMouseMove( const MouseEvent
& rMEvt
)
931 DPTestMouse( rMEvt
, TRUE
);
934 void ScGridWindow::DPMouseButtonUp( const MouseEvent
& rMEvt
)
939 DPTestMouse( rMEvt
, FALSE
);
940 SetPointer( Pointer( POINTER_ARROW
) );
943 // -----------------------------------------------------------------------
945 void ScGridWindow::UpdateDragRect( BOOL bShowRange
, const Rectangle
& rPosRect
)
947 SCCOL nStartX
= ( rPosRect
.Left() >= 0 ) ? static_cast<SCCOL
>(rPosRect
.Left()) : SCCOL_MAX
;
948 SCROW nStartY
= ( rPosRect
.Top() >= 0 ) ? static_cast<SCROW
>(rPosRect
.Top()) : SCROW_MAX
;
949 SCCOL nEndX
= ( rPosRect
.Right() >= 0 ) ? static_cast<SCCOL
>(rPosRect
.Right()) : SCCOL_MAX
;
950 SCROW nEndY
= ( rPosRect
.Bottom() >= 0 ) ? static_cast<SCROW
>(rPosRect
.Bottom()) : SCROW_MAX
;
952 if ( bShowRange
== bDragRect
&& nDragStartX
== nStartX
&& nDragEndX
== nEndX
&&
953 nDragStartY
== nStartY
&& nDragEndY
== nEndY
)
955 return; // everything unchanged
959 // DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, FALSE );
962 nDragStartX
= nStartX
;
963 nDragStartY
= nStartY
;
967 // DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, FALSE );
972 UpdateDragRectOverlay();
975 // -----------------------------------------------------------------------
979 USHORT
ScGridWindow::HitPageBreak( const Point
& rMouse
, ScRange
* pSource
,
980 SCCOLROW
* pBreak
, SCCOLROW
* pPrev
)
982 USHORT nFound
= SC_PD_NONE
; // 0
987 ScPageBreakData
* pPageData
= pViewData
->GetView()->GetPageBreakData();
995 long nMouseX
= rMouse
.X();
996 long nMouseY
= rMouse
.Y();
999 pViewData
->GetPosFromPixel( nMouseX
, nMouseY
, eWhich
, nPosX
, nPosY
);
1000 Point aTL
= pViewData
->GetScrPos( nPosX
, nPosY
, eWhich
);
1001 Point aBR
= pViewData
->GetScrPos( nPosX
+1, nPosY
+1, eWhich
);
1003 // Horizontal mehr Toleranz als vertikal, weil mehr Platz ist
1004 if ( nMouseX
<= aTL
.X() + 4 )
1009 else if ( nMouseX
>= aBR
.X() - 6 )
1012 nHitX
= nPosX
+1; // linker Rand der naechsten Zelle
1014 if ( nMouseY
<= aTL
.Y() + 2 )
1019 else if ( nMouseY
>= aBR
.Y() - 4 )
1022 nHitY
= nPosY
+1; // oberer Rand der naechsten Zelle
1025 if ( bHori
|| bVert
)
1027 USHORT nCount
= sal::static_int_cast
<USHORT
>( pPageData
->GetCount() );
1028 for (USHORT nPos
=0; nPos
<nCount
&& !nFound
; nPos
++)
1030 ScPrintRangeData
& rData
= pPageData
->GetData(nPos
);
1031 ScRange aRange
= rData
.GetPrintRange();
1032 BOOL bLHit
= ( bHori
&& nHitX
== aRange
.aStart
.Col() );
1033 BOOL bRHit
= ( bHori
&& nHitX
== aRange
.aEnd
.Col() + 1 );
1034 BOOL bTHit
= ( bVert
&& nHitY
== aRange
.aStart
.Row() );
1035 BOOL bBHit
= ( bVert
&& nHitY
== aRange
.aEnd
.Row() + 1 );
1036 BOOL bInsideH
= ( nPosX
>= aRange
.aStart
.Col() && nPosX
<= aRange
.aEnd
.Col() );
1037 BOOL bInsideV
= ( nPosY
>= aRange
.aStart
.Row() && nPosY
<= aRange
.aEnd
.Row() );
1042 nFound
= SC_PD_RANGE_TL
;
1044 nFound
= SC_PD_RANGE_BL
;
1045 else if ( bInsideV
)
1046 nFound
= SC_PD_RANGE_L
;
1051 nFound
= SC_PD_RANGE_TR
;
1053 nFound
= SC_PD_RANGE_BR
;
1054 else if ( bInsideV
)
1055 nFound
= SC_PD_RANGE_R
;
1057 else if ( bTHit
&& bInsideH
)
1058 nFound
= SC_PD_RANGE_T
;
1059 else if ( bBHit
&& bInsideH
)
1060 nFound
= SC_PD_RANGE_B
;
1066 if ( bVert
&& bInsideH
&& !nFound
)
1068 size_t nRowCount
= rData
.GetPagesY();
1069 const SCROW
* pRowEnd
= rData
.GetPageEndY();
1070 for (size_t nRowPos
=0; nRowPos
+1<nRowCount
; nRowPos
++)
1071 if ( pRowEnd
[nRowPos
]+1 == nHitY
)
1073 nFound
= SC_PD_BREAK_V
;
1077 nPrev
= pRowEnd
[nRowPos
-1]+1;
1079 nPrev
= aRange
.aStart
.Row();
1082 if ( bHori
&& bInsideV
&& !nFound
)
1084 size_t nColCount
= rData
.GetPagesX();
1085 const SCCOL
* pColEnd
= rData
.GetPageEndX();
1086 for (size_t nColPos
=0; nColPos
+1<nColCount
; nColPos
++)
1087 if ( pColEnd
[nColPos
]+1 == nHitX
)
1089 nFound
= SC_PD_BREAK_H
;
1093 nPrev
= pColEnd
[nColPos
-1]+1;
1095 nPrev
= aRange
.aStart
.Col();
1103 *pSource
= aSource
; // Druckbereich
1105 *pBreak
= nBreak
; // X/Y Position des verchobenen Seitenumbruchs
1107 *pPrev
= nPrev
; // X/Y Anfang der Seite, die am Umbruch zuende ist
1111 void ScGridWindow::PagebreakMove( const MouseEvent
& rMEvt
, BOOL bUp
)
1113 //! Scrolling und Umschalten mit RFMouseMove zusammenfassen !
1114 //! (Weginvertieren vor dem Scrolling ist anders)
1118 BOOL bTimer
= FALSE
;
1119 Point aPos
= rMEvt
.GetPosPixel();
1122 if ( aPos
.X() < 0 ) nDx
= -1;
1123 if ( aPos
.Y() < 0 ) nDy
= -1;
1124 Size aSize
= GetOutputSizePixel();
1125 if ( aPos
.X() >= aSize
.Width() )
1127 if ( aPos
.Y() >= aSize
.Height() )
1129 if ( nDx
!= 0 || nDy
!= 0 )
1131 if ( bPagebreakDrawn
) // weginvertieren
1133 // DrawDragRect( aPagebreakDrag.aStart.Col(), aPagebreakDrag.aStart.Row(),
1134 // aPagebreakDrag.aEnd.Col(), aPagebreakDrag.aEnd.Row(), FALSE );
1135 bPagebreakDrawn
= FALSE
;
1136 UpdateDragRectOverlay();
1139 if ( nDx
!= 0 ) pViewData
->GetView()->ScrollX( nDx
, WhichH(eWhich
) );
1140 if ( nDy
!= 0 ) pViewData
->GetView()->ScrollY( nDy
, WhichV(eWhich
) );
1144 // Umschalten bei Fixierung (damit Scrolling funktioniert)
1146 if ( eWhich
== pViewData
->GetActivePart() ) //??
1148 if ( pViewData
->GetHSplitMode() == SC_SPLIT_FIX
)
1151 if ( eWhich
== SC_SPLIT_TOPLEFT
)
1152 pViewData
->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT
);
1153 else if ( eWhich
== SC_SPLIT_BOTTOMLEFT
)
1154 pViewData
->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT
);
1157 if ( pViewData
->GetVSplitMode() == SC_SPLIT_FIX
)
1160 if ( eWhich
== SC_SPLIT_TOPLEFT
)
1161 pViewData
->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT
);
1162 else if ( eWhich
== SC_SPLIT_TOPRIGHT
)
1163 pViewData
->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT
);
1169 // gesucht wird eine Position zwischen den Zellen (vor nPosX / nPosY)
1172 pViewData
->GetPosFromPixel( aPos
.X(), aPos
.Y(), eWhich
, nPosX
, nPosY
);
1174 pViewData
->GetMouseQuadrant( aPos
, eWhich
, nPosX
, nPosY
, bLeft
, bTop
);
1175 if ( !bLeft
) ++nPosX
;
1176 if ( !bTop
) ++nPosY
;
1178 BOOL bBreak
= ( nPagebreakMouse
== SC_PD_BREAK_H
|| nPagebreakMouse
== SC_PD_BREAK_V
);
1180 BOOL bToEnd
= FALSE
;
1181 ScRange aDrawRange
= aPagebreakSource
;
1184 if ( nPagebreakMouse
== SC_PD_BREAK_H
)
1186 if ( nPosX
> aPagebreakSource
.aStart
.Col() &&
1187 nPosX
<= aPagebreakSource
.aEnd
.Col() + 1 ) // ans Ende ist auch erlaubt
1189 bToEnd
= ( nPosX
== aPagebreakSource
.aEnd
.Col() + 1 );
1190 aDrawRange
.aStart
.SetCol( nPosX
);
1191 aDrawRange
.aEnd
.SetCol( nPosX
- 1 );
1198 if ( nPosY
> aPagebreakSource
.aStart
.Row() &&
1199 nPosY
<= aPagebreakSource
.aEnd
.Row() + 1 ) // ans Ende ist auch erlaubt
1201 bToEnd
= ( nPosY
== aPagebreakSource
.aEnd
.Row() + 1 );
1202 aDrawRange
.aStart
.SetRow( nPosY
);
1203 aDrawRange
.aEnd
.SetRow( nPosY
- 1 );
1211 if ( nPagebreakMouse
& SC_PD_RANGE_L
)
1212 aDrawRange
.aStart
.SetCol( nPosX
);
1213 if ( nPagebreakMouse
& SC_PD_RANGE_T
)
1214 aDrawRange
.aStart
.SetRow( nPosY
);
1215 if ( nPagebreakMouse
& SC_PD_RANGE_R
)
1218 aDrawRange
.aEnd
.SetCol( nPosX
-1 );
1222 if ( nPagebreakMouse
& SC_PD_RANGE_B
)
1225 aDrawRange
.aEnd
.SetRow( nPosY
-1 );
1229 if ( aDrawRange
.aStart
.Col() > aDrawRange
.aEnd
.Col() ||
1230 aDrawRange
.aStart
.Row() > aDrawRange
.aEnd
.Row() )
1234 if ( !bPagebreakDrawn
|| bUp
|| aDrawRange
!= aPagebreakDrag
)
1238 if ( bPagebreakDrawn
)
1241 // DrawDragRect( aPagebreakDrag.aStart.Col(), aPagebreakDrag.aStart.Row(),
1242 // aPagebreakDrag.aEnd.Col(), aPagebreakDrag.aEnd.Row(), FALSE );
1243 bPagebreakDrawn
= FALSE
;
1245 aPagebreakDrag
= aDrawRange
;
1246 if ( !bUp
&& !bHide
)
1249 // DrawDragRect( aPagebreakDrag.aStart.Col(), aPagebreakDrag.aStart.Row(),
1250 // aPagebreakDrag.aEnd.Col(), aPagebreakDrag.aEnd.Row(), FALSE );
1251 bPagebreakDrawn
= TRUE
;
1253 UpdateDragRectOverlay();
1256 // bei ButtonUp die Aenderung ausfuehren
1260 ScViewFunc
* pViewFunc
= pViewData
->GetView();
1261 ScDocShell
* pDocSh
= pViewData
->GetDocShell();
1262 ScDocument
* pDoc
= pDocSh
->GetDocument();
1263 SCTAB nTab
= pViewData
->GetTabNo();
1264 BOOL
bUndo (pDoc
->IsUndoEnabled());
1268 BOOL bColumn
= ( nPagebreakMouse
== SC_PD_BREAK_H
);
1269 SCCOLROW nNew
= bColumn
? static_cast<SCCOLROW
>(nPosX
) : static_cast<SCCOLROW
>(nPosY
);
1270 if ( nNew
!= nPagebreakBreak
)
1274 String aUndo
= ScGlobal::GetRscString( STR_UNDO_DRAG_BREAK
);
1275 pDocSh
->GetUndoManager()->EnterListAction( aUndo
, aUndo
);
1278 BOOL bGrow
= !bHide
&& nNew
> nPagebreakBreak
;
1281 if (pDoc
->HasColBreak(static_cast<SCCOL
>(nPagebreakBreak
), nTab
) & BREAK_MANUAL
)
1283 ScAddress
aOldAddr( static_cast<SCCOL
>(nPagebreakBreak
), nPosY
, nTab
);
1284 pViewFunc
->DeletePageBreak( TRUE
, TRUE
, &aOldAddr
, FALSE
);
1286 if ( !bHide
&& !bToEnd
) // am Ende nicht
1288 ScAddress
aNewAddr( static_cast<SCCOL
>(nNew
), nPosY
, nTab
);
1289 pViewFunc
->InsertPageBreak( TRUE
, TRUE
, &aNewAddr
, FALSE
);
1293 // vorigen Break auf hart, und Skalierung aendern
1294 bool bManualBreak
= (pDoc
->HasColBreak(static_cast<SCCOL
>(nPagebreakPrev
), nTab
) & BREAK_MANUAL
);
1295 if ( static_cast<SCCOL
>(nPagebreakPrev
) > aPagebreakSource
.aStart
.Col() && !bManualBreak
)
1297 ScAddress
aPrev( static_cast<SCCOL
>(nPagebreakPrev
), nPosY
, nTab
);
1298 pViewFunc
->InsertPageBreak( TRUE
, TRUE
, &aPrev
, FALSE
);
1301 if (!pDocSh
->AdjustPrintZoom( ScRange(
1302 static_cast<SCCOL
>(nPagebreakPrev
),0,nTab
, static_cast<SCCOL
>(nNew
-1),0,nTab
) ))
1308 if (pDoc
->HasRowBreak(nPagebreakBreak
, nTab
) & BREAK_MANUAL
)
1310 ScAddress
aOldAddr( nPosX
, nPagebreakBreak
, nTab
);
1311 pViewFunc
->DeletePageBreak( FALSE
, TRUE
, &aOldAddr
, FALSE
);
1313 if ( !bHide
&& !bToEnd
) // am Ende nicht
1315 ScAddress
aNewAddr( nPosX
, nNew
, nTab
);
1316 pViewFunc
->InsertPageBreak( FALSE
, TRUE
, &aNewAddr
, FALSE
);
1320 // vorigen Break auf hart, und Skalierung aendern
1321 bool bManualBreak
= (pDoc
->HasRowBreak(nPagebreakPrev
, nTab
) & BREAK_MANUAL
);
1322 if ( nPagebreakPrev
> aPagebreakSource
.aStart
.Row() && !bManualBreak
)
1324 ScAddress
aPrev( nPosX
, nPagebreakPrev
, nTab
);
1325 pViewFunc
->InsertPageBreak( FALSE
, TRUE
, &aPrev
, FALSE
);
1328 if (!pDocSh
->AdjustPrintZoom( ScRange(
1329 0,nPagebreakPrev
,nTab
, 0,nNew
-1,nTab
) ))
1336 pDocSh
->GetUndoManager()->LeaveListAction();
1339 if (!bGrow
) // sonst in AdjustPrintZoom schon passiert
1341 pViewFunc
->UpdatePageBreakData( TRUE
);
1342 pDocSh
->SetDocumentModified();
1346 else if ( bHide
|| aPagebreakDrag
!= aPagebreakSource
)
1348 // Druckbereich setzen
1351 USHORT nOldCount
= pDoc
->GetPrintRangeCount( nTab
);
1354 for (USHORT nPos
=0; nPos
<nOldCount
; nPos
++)
1356 const ScRange
* pOld
= pDoc
->GetPrintRange( nTab
, nPos
);
1360 if ( *pOld
!= aPagebreakSource
)
1361 pOld
->Format( aTemp
, SCA_VALID
);
1363 aPagebreakDrag
.Format( aTemp
, SCA_VALID
);
1366 if ( aNewRanges
.Len() )
1368 aNewRanges
+= aTemp
;
1374 aPagebreakDrag
.Format( aNewRanges
, SCA_VALID
);
1376 pViewFunc
->SetPrintRanges( pDoc
->IsPrintEntireSheet( nTab
), &aNewRanges
, NULL
, NULL
, FALSE
);
1380 // Timer fuer Scrolling
1383 pViewData
->GetView()->SetTimer( this, rMEvt
); // Event wiederholen
1385 pViewData
->GetView()->ResetTimer();