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
;
70 using ::com::sun::star::sheet::DataPilotFieldOrientation
;
72 using ::std::auto_ptr
;
73 using ::std::hash_map
;
74 using ::rtl::OUString
;
75 using ::rtl::OUStringHash
;
77 // STATIC DATA -----------------------------------------------------------
79 // -----------------------------------------------------------------------
81 DataPilotFieldOrientation
ScGridWindow::GetDPFieldOrientation( SCCOL nCol
, SCROW nRow
) const
83 using namespace ::com::sun::star::sheet
;
85 ScDocument
* pDoc
= pViewData
->GetDocument();
86 SCTAB nTab
= pViewData
->GetTabNo();
87 ScDPObject
* pDPObj
= pDoc
->GetDPAtCursor(nCol
, nRow
, nTab
);
89 return DataPilotFieldOrientation_HIDDEN
;
91 USHORT nOrient
= DataPilotFieldOrientation_HIDDEN
;
93 // Check for page field first.
96 // look for the dimension header left of the drop-down arrow
97 long nField
= pDPObj
->GetHeaderDim( ScAddress( nCol
-1, nRow
, nTab
), nOrient
);
98 if ( nField
>= 0 && nOrient
== DataPilotFieldOrientation_PAGE
)
100 BOOL bIsDataLayout
= FALSE
;
101 String aFieldName
= pDPObj
->GetDimName( nField
, bIsDataLayout
);
102 if ( aFieldName
.Len() && !bIsDataLayout
)
103 return DataPilotFieldOrientation_PAGE
;
107 nOrient
= sheet::DataPilotFieldOrientation_HIDDEN
;
109 // Now, check for row/column field.
110 long nField
= pDPObj
->GetHeaderDim(ScAddress(nCol
, nRow
, nTab
), nOrient
);
111 if (nField
>= 0 && (nOrient
== DataPilotFieldOrientation_COLUMN
|| nOrient
== DataPilotFieldOrientation_ROW
) )
113 BOOL bIsDataLayout
= FALSE
;
114 String aFieldName
= pDPObj
->GetDimName(nField
, bIsDataLayout
);
115 if (aFieldName
.Len() && !bIsDataLayout
)
116 return static_cast<DataPilotFieldOrientation
>(nOrient
);
119 return DataPilotFieldOrientation_HIDDEN
;
122 // private method for mouse button handling
123 BOOL
ScGridWindow::DoPageFieldSelection( SCCOL nCol
, SCROW nRow
)
125 if (GetDPFieldOrientation( nCol
, nRow
) == sheet::DataPilotFieldOrientation_PAGE
)
127 LaunchPageFieldMenu( nCol
, nRow
);
133 bool ScGridWindow::DoAutoFilterButton( SCCOL nCol
, SCROW nRow
, const MouseEvent
& rMEvt
)
135 ScDocument
* pDoc
= pViewData
->GetDocument();
136 SCTAB nTab
= pViewData
->GetTabNo();
137 Point aScrPos
= pViewData
->GetScrPos(nCol
, nRow
, eWhich
);
138 Point aDiffPix
= rMEvt
.GetPosPixel();
141 BOOL bLayoutRTL
= pDoc
->IsLayoutRTL( nTab
);
143 aDiffPix
.X() = -aDiffPix
.X();
146 pViewData
->GetMergeSizePixel( nCol
, nRow
, nSizeX
, nSizeY
);
147 Size
aScrSize(nSizeX
-1, nSizeY
-1);
149 // Check if the mouse cursor is clicking on the popup arrow box.
150 mpFilterButton
.reset(new ScDPFieldButton(this, &GetSettings().GetStyleSettings(), &pViewData
->GetZoomX(), &pViewData
->GetZoomY()));
151 mpFilterButton
->setBoundingBox(aScrPos
, aScrSize
);
154 mpFilterButton
->getPopupBoundingBox(aPopupPos
, aPopupSize
);
155 Rectangle
aRec(aPopupPos
, aPopupSize
);
156 if (aRec
.IsInside(rMEvt
.GetPosPixel()))
158 if ( DoPageFieldSelection( nCol
, nRow
) )
161 bool bFilterActive
= IsAutoFilterActive(nCol
, nRow
, nTab
);
162 mpFilterButton
->setHasHiddenMember(bFilterActive
);
163 mpFilterButton
->setDrawBaseButton(false);
164 mpFilterButton
->setDrawPopupButton(true);
165 mpFilterButton
->setPopupPressed(true);
167 mpFilterButton
->draw();
169 DoAutoFilterMenue(nCol
, nRow
, false);
176 void ScGridWindow::DoPushButton( SCCOL nCol
, SCROW nRow
, const MouseEvent
& rMEvt
)
178 ScDocument
* pDoc
= pViewData
->GetDocument();
179 SCTAB nTab
= pViewData
->GetTabNo();
181 ScDPObject
* pDPObj
= pDoc
->GetDPAtCursor(nCol
, nRow
, nTab
);
185 USHORT nOrient
= sheet::DataPilotFieldOrientation_HIDDEN
;
186 ScAddress
aPos( nCol
, nRow
, nTab
);
187 long nField
= pDPObj
->GetHeaderDim( aPos
, nOrient
);
194 if (DPTestFieldPopupArrow(rMEvt
, aPos
, pDPObj
))
196 // field name pop up menu has been launched. Don't activate
202 DPTestMouse( rMEvt
, TRUE
);
205 else if ( pDPObj
->IsFilterButton(aPos
) )
207 ReleaseMouse(); // may have been captured in ButtonDown
209 ScQueryParam aQueryParam
;
211 const ScSheetSourceDesc
* pDesc
= pDPObj
->GetSheetDesc();
212 DBG_ASSERT(pDesc
, "no sheet source for filter button");
215 aQueryParam
= pDesc
->aQueryParam
;
216 nSrcTab
= pDesc
->aSourceRange
.aStart
.Tab();
219 SfxItemSet
aArgSet( pViewData
->GetViewShell()->GetPool(),
220 SCITEM_QUERYDATA
, SCITEM_QUERYDATA
);
221 aArgSet
.Put( ScQueryItem( SCITEM_QUERYDATA
, pViewData
, &aQueryParam
) );
223 //CHINA001 ScPivotFilterDlg* pDlg = new ScPivotFilterDlg(
224 //CHINA001 pViewData->GetViewShell()->GetDialogParent(),
225 //CHINA001 aArgSet, nSrcTab );
226 ScAbstractDialogFactory
* pFact
= ScAbstractDialogFactory::Create();
227 DBG_ASSERT(pFact
, "ScAbstractFactory create fail!");//CHINA001
229 AbstractScPivotFilterDlg
* pDlg
= pFact
->CreateScPivotFilterDlg( pViewData
->GetViewShell()->GetDialogParent(),
231 RID_SCDLG_PIVOTFILTER
);
232 DBG_ASSERT(pDlg
, "Dialog create fail!");//CHINA001
233 if ( pDlg
->Execute() == RET_OK
)
235 ScSheetSourceDesc aNewDesc
;
239 const ScQueryItem
& rQueryItem
= pDlg
->GetOutputItem();
240 aNewDesc
.aQueryParam
= rQueryItem
.GetQueryData();
242 ScDPObject
aNewObj( *pDPObj
);
243 aNewObj
.SetSheetDesc( aNewDesc
);
244 ScDBDocFunc
aFunc( *pViewData
->GetDocShell() );
245 aFunc
.DataPilotUpdate( pDPObj
, &aNewObj
, TRUE
, FALSE
);
246 pViewData
->GetView()->CursorPosChanged(); // shells may be switched
255 DBG_ERROR("Da is ja garnix");
259 // -----------------------------------------------------------------------
261 // Data Pilot interaction
264 void ScGridWindow::DPTestMouse( const MouseEvent
& rMEvt
, BOOL bMove
)
266 DBG_ASSERT(pDragDPObj
, "pDragDPObj missing");
268 // scroll window if at edges
269 //! move this to separate method
272 Point aPixel
= rMEvt
.GetPosPixel();
276 if ( aPixel
.X() < 0 )
278 if ( aPixel
.Y() < 0 )
280 Size aSize
= GetOutputSizePixel();
281 if ( aPixel
.X() >= aSize
.Width() )
283 if ( aPixel
.Y() >= aSize
.Height() )
285 if ( nDx
!= 0 || nDy
!= 0 )
287 UpdateDragRect( FALSE
, Rectangle() );
290 pViewData
->GetView()->ScrollX( nDx
, WhichH(eWhich
) );
292 pViewData
->GetView()->ScrollY( nDy
, WhichV(eWhich
) );
301 pViewData
->GetPosFromPixel( aPixel
.X(), aPixel
.Y(), eWhich
, nPosX
, nPosY
);
304 pViewData
->GetMouseQuadrant( aPixel
, eWhich
, nPosX
, nPosY
, bMouseLeft
, bMouseTop
);
306 ScAddress
aPos( nPosX
, nPosY
, pViewData
->GetTabNo() );
311 BOOL bHasRange
= pDragDPObj
->GetHeaderDrag( aPos
, bMouseLeft
, bMouseTop
, nDPField
,
312 aPosRect
, nOrient
, nDimPos
);
313 UpdateDragRect( bHasRange
&& bMove
, aPosRect
);
315 if (bMove
) // set mouse pointer
317 PointerStyle ePointer
= POINTER_PIVOT_DELETE
;
321 case sheet::DataPilotFieldOrientation_COLUMN
: ePointer
= POINTER_PIVOT_COL
; break;
322 case sheet::DataPilotFieldOrientation_ROW
: ePointer
= POINTER_PIVOT_ROW
; break;
323 case sheet::DataPilotFieldOrientation_PAGE
:
324 case sheet::DataPilotFieldOrientation_DATA
: ePointer
= POINTER_PIVOT_FIELD
; break;
326 SetPointer( ePointer
);
328 else // execute change
331 nOrient
= sheet::DataPilotFieldOrientation_HIDDEN
;
334 String aDimName
= pDragDPObj
->GetDimName( nDPField
, bIsDataLayout
);
335 if ( bIsDataLayout
&& ( nOrient
!= sheet::DataPilotFieldOrientation_COLUMN
&&
336 nOrient
!= sheet::DataPilotFieldOrientation_ROW
) )
338 // removing data layout is not allowed
339 pViewData
->GetView()->ErrorMessage(STR_PIVOT_MOVENOTALLOWED
);
343 ScDPSaveData
aSaveData( *pDragDPObj
->GetSaveData() );
345 ScDPSaveDimension
* pDim
;
347 pDim
= aSaveData
.GetDataLayoutDimension();
349 pDim
= aSaveData
.GetDimensionByName(aDimName
);
350 pDim
->SetOrientation( nOrient
);
351 aSaveData
.SetPosition( pDim
, nDimPos
);
353 //! docfunc method with ScDPSaveData as argument?
355 ScDPObject
aNewObj( *pDragDPObj
);
356 aNewObj
.SetSaveData( aSaveData
);
357 ScDBDocFunc
aFunc( *pViewData
->GetDocShell() );
358 // when dragging fields, allow re-positioning (bAllowMove)
359 aFunc
.DataPilotUpdate( pDragDPObj
, &aNewObj
, TRUE
, FALSE
, TRUE
);
360 pViewData
->GetView()->CursorPosChanged(); // shells may be switched
365 pViewData
->GetView()->SetTimer( this, rMEvt
); // repeat event
367 pViewData
->GetView()->ResetTimer();
370 bool ScGridWindow::DPTestFieldPopupArrow(const MouseEvent
& rMEvt
, const ScAddress
& rPos
, ScDPObject
* pDPObj
)
372 // Get the geometry of the cell.
373 Point aScrPos
= pViewData
->GetScrPos(rPos
.Col(), rPos
.Row(), eWhich
);
375 pViewData
->GetMergeSizePixel(rPos
.Col(), rPos
.Row(), nSizeX
, nSizeY
);
376 Size
aScrSize(nSizeX
-1, nSizeY
-1);
378 // Check if the mouse cursor is clicking on the popup arrow box.
379 ScDPFieldButton
aBtn(this, &GetSettings().GetStyleSettings());
380 aBtn
.setBoundingBox(aScrPos
, aScrSize
);
383 aBtn
.getPopupBoundingBox(aPopupPos
, aPopupSize
);
384 Rectangle
aRec(aPopupPos
, aPopupSize
);
385 if (aRec
.IsInside(rMEvt
.GetPosPixel()))
387 // Mouse cursor inside the popup arrow box. Launch the field menu.
388 DPLaunchFieldPopupMenu(OutputToScreenPixel(aScrPos
), aScrSize
, rPos
, pDPObj
);
397 struct DPFieldPopupData
: public ScDPFieldPopupWindow::ExtendedData
399 ScPivotParam maDPParam
;
404 class DPFieldPopupOKAction
: public ScMenuFloatingWindow::Action
407 explicit DPFieldPopupOKAction(ScGridWindow
* p
) :
410 virtual void execute()
412 mpGridWindow
->UpdateDPFromFieldPopupMenu();
415 ScGridWindow
* mpGridWindow
;
418 class PopupSortAction
: public ScMenuFloatingWindow::Action
421 enum SortType
{ ASCENDING
, DESCENDING
, CUSTOM
};
423 explicit PopupSortAction(const ScAddress
& rPos
, SortType eType
, sal_uInt16 nUserListIndex
, ScTabViewShell
* pViewShell
) :
424 maPos(rPos
), meType(eType
), mnUserListIndex(nUserListIndex
), mpViewShell(pViewShell
) {}
426 virtual void execute()
431 mpViewShell
->DataPilotSort(maPos
, true);
434 mpViewShell
->DataPilotSort(maPos
, false);
437 mpViewShell
->DataPilotSort(maPos
, true, &mnUserListIndex
);
447 sal_uInt16 mnUserListIndex
;
448 ScTabViewShell
* mpViewShell
;
453 void ScGridWindow::DPLaunchFieldPopupMenu(
454 const Point
& rScrPos
, const Size
& rScrSize
, const ScAddress
& rPos
, ScDPObject
* pDPObj
)
456 // We need to get the list of field members.
457 auto_ptr
<DPFieldPopupData
> pDPData(new DPFieldPopupData
);
458 pDPObj
->FillLabelData(pDPData
->maDPParam
);
459 pDPData
->mpDPObj
= pDPObj
;
462 pDPData
->mnDim
= pDPObj
->GetHeaderDim(rPos
, nOrient
);
464 if (pDPData
->maDPParam
.maLabelArray
.size() <= static_cast<size_t>(pDPData
->mnDim
))
465 // out-of-bound dimension ID. This should never happen!
468 const ScDPLabelData
& rLabelData
= *pDPData
->maDPParam
.maLabelArray
[pDPData
->mnDim
];
470 mpDPFieldPopup
.reset(new ScDPFieldPopupWindow(this, pViewData
->GetDocument()));
471 mpDPFieldPopup
->setName(OUString::createFromAscii("DataPilot field member popup"));
472 mpDPFieldPopup
->setExtendedData(pDPData
.release());
473 mpDPFieldPopup
->setOKAction(new DPFieldPopupOKAction(this));
475 // Populate field members.
476 size_t n
= rLabelData
.maMembers
.size();
477 mpDPFieldPopup
->setMemberSize(n
);
478 for (size_t i
= 0; i
< n
; ++i
)
480 const ScDPLabelData::Member
& rMem
= rLabelData
.maMembers
[i
];
481 mpDPFieldPopup
->addMember(rMem
.getDisplayName(), rMem
.mbVisible
);
483 mpDPFieldPopup
->initMembers();
486 vector
<OUString
> aUserSortNames
;
487 ScUserList
* pUserList
= ScGlobal::GetUserList();
490 sal_uInt16 n
= pUserList
->GetCount();
491 aUserSortNames
.reserve(n
);
492 for (sal_uInt16 i
= 0; i
< n
; ++i
)
494 ScUserListData
* pData
= static_cast<ScUserListData
*>((*pUserList
)[i
]);
495 aUserSortNames
.push_back(pData
->GetString());
499 // Populate the menus.
500 ScTabViewShell
* pViewShell
= pViewData
->GetViewShell();
501 mpDPFieldPopup
->addMenuItem(
502 ScRscStrLoader(RID_POPUP_FILTER
, STR_MENU_SORT_ASC
).GetString(), true,
503 new PopupSortAction(rPos
, PopupSortAction::ASCENDING
, 0, pViewShell
));
504 mpDPFieldPopup
->addMenuItem(
505 ScRscStrLoader(RID_POPUP_FILTER
, STR_MENU_SORT_DESC
).GetString(), true,
506 new PopupSortAction(rPos
, PopupSortAction::DESCENDING
, 0, pViewShell
));
507 ScMenuFloatingWindow
* pSubMenu
= mpDPFieldPopup
->addSubMenuItem(
508 ScRscStrLoader(RID_POPUP_FILTER
, STR_MENU_SORT_CUSTOM
).GetString(), !aUserSortNames
.empty());
510 if (pSubMenu
&& !aUserSortNames
.empty())
512 size_t n
= aUserSortNames
.size();
513 for (size_t i
= 0; i
< n
; ++i
)
515 pSubMenu
->addMenuItem(
516 aUserSortNames
[i
], true,
517 new PopupSortAction(rPos
, PopupSortAction::CUSTOM
, i
, pViewShell
));
521 Rectangle
aCellRect(rScrPos
, rScrSize
);
522 const Size
& rPopupSize
= mpDPFieldPopup
->getWindowSize();
523 if (rScrSize
.getWidth() > rPopupSize
.getWidth())
525 // If the cell width is larger than the popup window width, launch it
526 // right-aligned with the cell.
527 long nXOffset
= rScrSize
.getWidth() - rPopupSize
.getWidth();
528 aCellRect
.SetPos(Point(rScrPos
.X() + nXOffset
, rScrPos
.Y()));
530 mpDPFieldPopup
->SetPopupModeEndHdl( LINK(this, ScGridWindow
, PopupModeEndHdl
) );
531 mpDPFieldPopup
->StartPopupMode(aCellRect
, (FLOATWIN_POPUPMODE_DOWN
| FLOATWIN_POPUPMODE_GRABFOCUS
));
534 void ScGridWindow::UpdateDPFromFieldPopupMenu()
536 typedef hash_map
<OUString
, OUString
, OUStringHash
> MemNameMapType
;
537 typedef hash_map
<OUString
, bool, OUStringHash
> MemVisibilityType
;
539 if (!mpDPFieldPopup
.get())
542 DPFieldPopupData
* pDPData
= static_cast<DPFieldPopupData
*>(mpDPFieldPopup
->getExtendedData());
546 ScDPObject
* pDPObj
= pDPData
->mpDPObj
;
547 ScDPObject
aNewDPObj(*pDPObj
);
548 aNewDPObj
.BuildAllDimensionMembers();
549 ScDPSaveData
* pSaveData
= aNewDPObj
.GetSaveData();
552 String aDimName
= pDPObj
->GetDimName(pDPData
->mnDim
, bIsDataLayout
);
553 ScDPSaveDimension
* pDim
= pSaveData
->GetDimensionByName(aDimName
);
557 // Build a map of layout names to original names.
558 const ScDPLabelData
& rLabelData
= *pDPData
->maDPParam
.maLabelArray
[pDPData
->mnDim
];
559 MemNameMapType aMemNameMap
;
560 for (vector
<ScDPLabelData::Member
>::const_iterator itr
= rLabelData
.maMembers
.begin(), itrEnd
= rLabelData
.maMembers
.end();
561 itr
!= itrEnd
; ++itr
)
562 aMemNameMap
.insert(MemNameMapType::value_type(itr
->maLayoutName
, itr
->maName
));
564 // The raw result may contain a mixture of layout names and original names.
565 MemVisibilityType aRawResult
;
566 mpDPFieldPopup
->getResult(aRawResult
);
568 MemVisibilityType aResult
;
569 for (MemVisibilityType::const_iterator itr
= aRawResult
.begin(), itrEnd
= aRawResult
.end(); itr
!= itrEnd
; ++itr
)
571 MemNameMapType::const_iterator itrNameMap
= aMemNameMap
.find(itr
->first
);
572 if (itrNameMap
== aMemNameMap
.end())
573 // This is an original member name. Use it as-is.
574 aResult
.insert(MemVisibilityType::value_type(itr
->first
, itr
->second
));
577 // This is a layout name. Get the original member name and use it.
578 aResult
.insert(MemVisibilityType::value_type(itrNameMap
->second
, itr
->second
));
581 pDim
->UpdateMemberVisibility(aResult
);
583 ScDBDocFunc
aFunc(*pViewData
->GetDocShell());
584 aFunc
.DataPilotUpdate(pDPObj
, &aNewDPObj
, true, false);
587 void ScGridWindow::DPMouseMove( const MouseEvent
& rMEvt
)
589 DPTestMouse( rMEvt
, TRUE
);
592 void ScGridWindow::DPMouseButtonUp( const MouseEvent
& rMEvt
)
597 DPTestMouse( rMEvt
, FALSE
);
598 SetPointer( Pointer( POINTER_ARROW
) );
601 // -----------------------------------------------------------------------
603 void ScGridWindow::UpdateDragRect( BOOL bShowRange
, const Rectangle
& rPosRect
)
605 SCCOL nStartX
= ( rPosRect
.Left() >= 0 ) ? static_cast<SCCOL
>(rPosRect
.Left()) : SCCOL_MAX
;
606 SCROW nStartY
= ( rPosRect
.Top() >= 0 ) ? static_cast<SCROW
>(rPosRect
.Top()) : SCROW_MAX
;
607 SCCOL nEndX
= ( rPosRect
.Right() >= 0 ) ? static_cast<SCCOL
>(rPosRect
.Right()) : SCCOL_MAX
;
608 SCROW nEndY
= ( rPosRect
.Bottom() >= 0 ) ? static_cast<SCROW
>(rPosRect
.Bottom()) : SCROW_MAX
;
610 if ( bShowRange
== bDragRect
&& nDragStartX
== nStartX
&& nDragEndX
== nEndX
&&
611 nDragStartY
== nStartY
&& nDragEndY
== nEndY
)
613 return; // everything unchanged
617 // DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, FALSE );
620 nDragStartX
= nStartX
;
621 nDragStartY
= nStartY
;
625 // DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, FALSE );
630 UpdateDragRectOverlay();
633 // -----------------------------------------------------------------------
637 USHORT
ScGridWindow::HitPageBreak( const Point
& rMouse
, ScRange
* pSource
,
638 SCCOLROW
* pBreak
, SCCOLROW
* pPrev
)
640 USHORT nFound
= SC_PD_NONE
; // 0
645 ScPageBreakData
* pPageData
= pViewData
->GetView()->GetPageBreakData();
653 long nMouseX
= rMouse
.X();
654 long nMouseY
= rMouse
.Y();
657 pViewData
->GetPosFromPixel( nMouseX
, nMouseY
, eWhich
, nPosX
, nPosY
);
658 Point aTL
= pViewData
->GetScrPos( nPosX
, nPosY
, eWhich
);
659 Point aBR
= pViewData
->GetScrPos( nPosX
+1, nPosY
+1, eWhich
);
661 // Horizontal mehr Toleranz als vertikal, weil mehr Platz ist
662 if ( nMouseX
<= aTL
.X() + 4 )
667 else if ( nMouseX
>= aBR
.X() - 6 )
670 nHitX
= nPosX
+1; // linker Rand der naechsten Zelle
672 if ( nMouseY
<= aTL
.Y() + 2 )
677 else if ( nMouseY
>= aBR
.Y() - 4 )
680 nHitY
= nPosY
+1; // oberer Rand der naechsten Zelle
683 if ( bHori
|| bVert
)
685 USHORT nCount
= sal::static_int_cast
<USHORT
>( pPageData
->GetCount() );
686 for (USHORT nPos
=0; nPos
<nCount
&& !nFound
; nPos
++)
688 ScPrintRangeData
& rData
= pPageData
->GetData(nPos
);
689 ScRange aRange
= rData
.GetPrintRange();
690 BOOL bLHit
= ( bHori
&& nHitX
== aRange
.aStart
.Col() );
691 BOOL bRHit
= ( bHori
&& nHitX
== aRange
.aEnd
.Col() + 1 );
692 BOOL bTHit
= ( bVert
&& nHitY
== aRange
.aStart
.Row() );
693 BOOL bBHit
= ( bVert
&& nHitY
== aRange
.aEnd
.Row() + 1 );
694 BOOL bInsideH
= ( nPosX
>= aRange
.aStart
.Col() && nPosX
<= aRange
.aEnd
.Col() );
695 BOOL bInsideV
= ( nPosY
>= aRange
.aStart
.Row() && nPosY
<= aRange
.aEnd
.Row() );
700 nFound
= SC_PD_RANGE_TL
;
702 nFound
= SC_PD_RANGE_BL
;
704 nFound
= SC_PD_RANGE_L
;
709 nFound
= SC_PD_RANGE_TR
;
711 nFound
= SC_PD_RANGE_BR
;
713 nFound
= SC_PD_RANGE_R
;
715 else if ( bTHit
&& bInsideH
)
716 nFound
= SC_PD_RANGE_T
;
717 else if ( bBHit
&& bInsideH
)
718 nFound
= SC_PD_RANGE_B
;
724 if ( bVert
&& bInsideH
&& !nFound
)
726 size_t nRowCount
= rData
.GetPagesY();
727 const SCROW
* pRowEnd
= rData
.GetPageEndY();
728 for (size_t nRowPos
=0; nRowPos
+1<nRowCount
; nRowPos
++)
729 if ( pRowEnd
[nRowPos
]+1 == nHitY
)
731 nFound
= SC_PD_BREAK_V
;
735 nPrev
= pRowEnd
[nRowPos
-1]+1;
737 nPrev
= aRange
.aStart
.Row();
740 if ( bHori
&& bInsideV
&& !nFound
)
742 size_t nColCount
= rData
.GetPagesX();
743 const SCCOL
* pColEnd
= rData
.GetPageEndX();
744 for (size_t nColPos
=0; nColPos
+1<nColCount
; nColPos
++)
745 if ( pColEnd
[nColPos
]+1 == nHitX
)
747 nFound
= SC_PD_BREAK_H
;
751 nPrev
= pColEnd
[nColPos
-1]+1;
753 nPrev
= aRange
.aStart
.Col();
761 *pSource
= aSource
; // Druckbereich
763 *pBreak
= nBreak
; // X/Y Position des verchobenen Seitenumbruchs
765 *pPrev
= nPrev
; // X/Y Anfang der Seite, die am Umbruch zuende ist
769 void ScGridWindow::PagebreakMove( const MouseEvent
& rMEvt
, BOOL bUp
)
771 //! Scrolling und Umschalten mit RFMouseMove zusammenfassen !
772 //! (Weginvertieren vor dem Scrolling ist anders)
777 Point aPos
= rMEvt
.GetPosPixel();
780 if ( aPos
.X() < 0 ) nDx
= -1;
781 if ( aPos
.Y() < 0 ) nDy
= -1;
782 Size aSize
= GetOutputSizePixel();
783 if ( aPos
.X() >= aSize
.Width() )
785 if ( aPos
.Y() >= aSize
.Height() )
787 if ( nDx
!= 0 || nDy
!= 0 )
789 if ( bPagebreakDrawn
) // weginvertieren
791 // DrawDragRect( aPagebreakDrag.aStart.Col(), aPagebreakDrag.aStart.Row(),
792 // aPagebreakDrag.aEnd.Col(), aPagebreakDrag.aEnd.Row(), FALSE );
793 bPagebreakDrawn
= FALSE
;
794 UpdateDragRectOverlay();
797 if ( nDx
!= 0 ) pViewData
->GetView()->ScrollX( nDx
, WhichH(eWhich
) );
798 if ( nDy
!= 0 ) pViewData
->GetView()->ScrollY( nDy
, WhichV(eWhich
) );
802 // Umschalten bei Fixierung (damit Scrolling funktioniert)
804 if ( eWhich
== pViewData
->GetActivePart() ) //??
806 if ( pViewData
->GetHSplitMode() == SC_SPLIT_FIX
)
809 if ( eWhich
== SC_SPLIT_TOPLEFT
)
810 pViewData
->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT
);
811 else if ( eWhich
== SC_SPLIT_BOTTOMLEFT
)
812 pViewData
->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT
);
815 if ( pViewData
->GetVSplitMode() == SC_SPLIT_FIX
)
818 if ( eWhich
== SC_SPLIT_TOPLEFT
)
819 pViewData
->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT
);
820 else if ( eWhich
== SC_SPLIT_TOPRIGHT
)
821 pViewData
->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT
);
827 // gesucht wird eine Position zwischen den Zellen (vor nPosX / nPosY)
830 pViewData
->GetPosFromPixel( aPos
.X(), aPos
.Y(), eWhich
, nPosX
, nPosY
);
832 pViewData
->GetMouseQuadrant( aPos
, eWhich
, nPosX
, nPosY
, bLeft
, bTop
);
833 if ( !bLeft
) ++nPosX
;
834 if ( !bTop
) ++nPosY
;
836 BOOL bBreak
= ( nPagebreakMouse
== SC_PD_BREAK_H
|| nPagebreakMouse
== SC_PD_BREAK_V
);
839 ScRange aDrawRange
= aPagebreakSource
;
842 if ( nPagebreakMouse
== SC_PD_BREAK_H
)
844 if ( nPosX
> aPagebreakSource
.aStart
.Col() &&
845 nPosX
<= aPagebreakSource
.aEnd
.Col() + 1 ) // ans Ende ist auch erlaubt
847 bToEnd
= ( nPosX
== aPagebreakSource
.aEnd
.Col() + 1 );
848 aDrawRange
.aStart
.SetCol( nPosX
);
849 aDrawRange
.aEnd
.SetCol( nPosX
- 1 );
856 if ( nPosY
> aPagebreakSource
.aStart
.Row() &&
857 nPosY
<= aPagebreakSource
.aEnd
.Row() + 1 ) // ans Ende ist auch erlaubt
859 bToEnd
= ( nPosY
== aPagebreakSource
.aEnd
.Row() + 1 );
860 aDrawRange
.aStart
.SetRow( nPosY
);
861 aDrawRange
.aEnd
.SetRow( nPosY
- 1 );
869 if ( nPagebreakMouse
& SC_PD_RANGE_L
)
870 aDrawRange
.aStart
.SetCol( nPosX
);
871 if ( nPagebreakMouse
& SC_PD_RANGE_T
)
872 aDrawRange
.aStart
.SetRow( nPosY
);
873 if ( nPagebreakMouse
& SC_PD_RANGE_R
)
876 aDrawRange
.aEnd
.SetCol( nPosX
-1 );
880 if ( nPagebreakMouse
& SC_PD_RANGE_B
)
883 aDrawRange
.aEnd
.SetRow( nPosY
-1 );
887 if ( aDrawRange
.aStart
.Col() > aDrawRange
.aEnd
.Col() ||
888 aDrawRange
.aStart
.Row() > aDrawRange
.aEnd
.Row() )
892 if ( !bPagebreakDrawn
|| bUp
|| aDrawRange
!= aPagebreakDrag
)
896 if ( bPagebreakDrawn
)
899 // DrawDragRect( aPagebreakDrag.aStart.Col(), aPagebreakDrag.aStart.Row(),
900 // aPagebreakDrag.aEnd.Col(), aPagebreakDrag.aEnd.Row(), FALSE );
901 bPagebreakDrawn
= FALSE
;
903 aPagebreakDrag
= aDrawRange
;
904 if ( !bUp
&& !bHide
)
907 // DrawDragRect( aPagebreakDrag.aStart.Col(), aPagebreakDrag.aStart.Row(),
908 // aPagebreakDrag.aEnd.Col(), aPagebreakDrag.aEnd.Row(), FALSE );
909 bPagebreakDrawn
= TRUE
;
911 UpdateDragRectOverlay();
914 // bei ButtonUp die Aenderung ausfuehren
918 ScViewFunc
* pViewFunc
= pViewData
->GetView();
919 ScDocShell
* pDocSh
= pViewData
->GetDocShell();
920 ScDocument
* pDoc
= pDocSh
->GetDocument();
921 SCTAB nTab
= pViewData
->GetTabNo();
922 BOOL
bUndo (pDoc
->IsUndoEnabled());
926 BOOL bColumn
= ( nPagebreakMouse
== SC_PD_BREAK_H
);
927 SCCOLROW nNew
= bColumn
? static_cast<SCCOLROW
>(nPosX
) : static_cast<SCCOLROW
>(nPosY
);
928 if ( nNew
!= nPagebreakBreak
)
932 String aUndo
= ScGlobal::GetRscString( STR_UNDO_DRAG_BREAK
);
933 pDocSh
->GetUndoManager()->EnterListAction( aUndo
, aUndo
);
936 BOOL bGrow
= !bHide
&& nNew
> nPagebreakBreak
;
939 if (pDoc
->HasColBreak(static_cast<SCCOL
>(nPagebreakBreak
), nTab
) & BREAK_MANUAL
)
941 ScAddress
aOldAddr( static_cast<SCCOL
>(nPagebreakBreak
), nPosY
, nTab
);
942 pViewFunc
->DeletePageBreak( TRUE
, TRUE
, &aOldAddr
, FALSE
);
944 if ( !bHide
&& !bToEnd
) // am Ende nicht
946 ScAddress
aNewAddr( static_cast<SCCOL
>(nNew
), nPosY
, nTab
);
947 pViewFunc
->InsertPageBreak( TRUE
, TRUE
, &aNewAddr
, FALSE
);
951 // vorigen Break auf hart, und Skalierung aendern
952 bool bManualBreak
= (pDoc
->HasColBreak(static_cast<SCCOL
>(nPagebreakPrev
), nTab
) & BREAK_MANUAL
);
953 if ( static_cast<SCCOL
>(nPagebreakPrev
) > aPagebreakSource
.aStart
.Col() && !bManualBreak
)
955 ScAddress
aPrev( static_cast<SCCOL
>(nPagebreakPrev
), nPosY
, nTab
);
956 pViewFunc
->InsertPageBreak( TRUE
, TRUE
, &aPrev
, FALSE
);
959 if (!pDocSh
->AdjustPrintZoom( ScRange(
960 static_cast<SCCOL
>(nPagebreakPrev
),0,nTab
, static_cast<SCCOL
>(nNew
-1),0,nTab
) ))
966 if (pDoc
->HasRowBreak(nPagebreakBreak
, nTab
) & BREAK_MANUAL
)
968 ScAddress
aOldAddr( nPosX
, nPagebreakBreak
, nTab
);
969 pViewFunc
->DeletePageBreak( FALSE
, TRUE
, &aOldAddr
, FALSE
);
971 if ( !bHide
&& !bToEnd
) // am Ende nicht
973 ScAddress
aNewAddr( nPosX
, nNew
, nTab
);
974 pViewFunc
->InsertPageBreak( FALSE
, TRUE
, &aNewAddr
, FALSE
);
978 // vorigen Break auf hart, und Skalierung aendern
979 bool bManualBreak
= (pDoc
->HasRowBreak(nPagebreakPrev
, nTab
) & BREAK_MANUAL
);
980 if ( nPagebreakPrev
> aPagebreakSource
.aStart
.Row() && !bManualBreak
)
982 ScAddress
aPrev( nPosX
, nPagebreakPrev
, nTab
);
983 pViewFunc
->InsertPageBreak( FALSE
, TRUE
, &aPrev
, FALSE
);
986 if (!pDocSh
->AdjustPrintZoom( ScRange(
987 0,nPagebreakPrev
,nTab
, 0,nNew
-1,nTab
) ))
994 pDocSh
->GetUndoManager()->LeaveListAction();
997 if (!bGrow
) // sonst in AdjustPrintZoom schon passiert
999 pViewFunc
->UpdatePageBreakData( TRUE
);
1000 pDocSh
->SetDocumentModified();
1004 else if ( bHide
|| aPagebreakDrag
!= aPagebreakSource
)
1006 // Druckbereich setzen
1009 USHORT nOldCount
= pDoc
->GetPrintRangeCount( nTab
);
1012 for (USHORT nPos
=0; nPos
<nOldCount
; nPos
++)
1014 const ScRange
* pOld
= pDoc
->GetPrintRange( nTab
, nPos
);
1018 if ( *pOld
!= aPagebreakSource
)
1019 pOld
->Format( aTemp
, SCA_VALID
);
1021 aPagebreakDrag
.Format( aTemp
, SCA_VALID
);
1024 if ( aNewRanges
.Len() )
1026 aNewRanges
+= aTemp
;
1032 aPagebreakDrag
.Format( aNewRanges
, SCA_VALID
);
1034 pViewFunc
->SetPrintRanges( pDoc
->IsPrintEntireSheet( nTab
), &aNewRanges
, NULL
, NULL
, FALSE
);
1038 // Timer fuer Scrolling
1041 pViewData
->GetView()->SetTimer( this, rMEvt
); // Event wiederholen
1043 pViewData
->GetView()->ResetTimer();