xref: /aoo41x/main/sc/source/ui/view/gridwin2.cxx (revision b3f79822)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 
27 
28 
29 // INCLUDE ---------------------------------------------------------------
30 
31 #include "scitems.hxx"
32 #include <vcl/msgbox.hxx>
33 #include <vcl/sound.hxx>
34 
35 #include "gridwin.hxx"
36 #include "tabvwsh.hxx"
37 #include "docsh.hxx"
38 #include "viewdata.hxx"
39 #include "pivot.hxx"
40 //CHINA001 #include "pfiltdlg.hxx"
41 #include "uiitems.hxx"
42 #include "scresid.hxx"
43 #include "sc.hrc"
44 #include "globstr.hrc"
45 #include "pagedata.hxx"
46 #include "dpobject.hxx"
47 #include "dpsave.hxx"
48 #include "dpoutput.hxx"		// ScDPPositionData
49 #include "dpshttab.hxx"
50 #include "dbdocfun.hxx"
51 #include "dpcontrol.hxx"
52 #include "dpcontrol.hrc"
53 #include "strload.hxx"
54 #include "userlist.hxx"
55 
56 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
57 #include "scabstdlg.hxx" //CHINA001
58 
59 #include <vector>
60 #include <hash_map>
61 
62 using namespace com::sun::star;
63 using ::com::sun::star::sheet::DataPilotFieldOrientation;
64 using ::std::vector;
65 using ::std::auto_ptr;
66 using ::std::hash_map;
67 using ::rtl::OUString;
68 using ::rtl::OUStringHash;
69 
70 // STATIC DATA -----------------------------------------------------------
71 
72 // -----------------------------------------------------------------------
73 
74 DataPilotFieldOrientation ScGridWindow::GetDPFieldOrientation( SCCOL nCol, SCROW nRow ) const
75 {
76     using namespace ::com::sun::star::sheet;
77 
78     ScDocument* pDoc = pViewData->GetDocument();
79     SCTAB nTab = pViewData->GetTabNo();
80     ScDPObject* pDPObj = pDoc->GetDPAtCursor(nCol, nRow, nTab);
81     if (!pDPObj)
82         return DataPilotFieldOrientation_HIDDEN;
83 
84     sal_uInt16 nOrient = DataPilotFieldOrientation_HIDDEN;
85 
86     // Check for page field first.
87     if (nCol > 0)
88     {
89         // look for the dimension header left of the drop-down arrow
90         long nField = pDPObj->GetHeaderDim( ScAddress( nCol-1, nRow, nTab ), nOrient );
91         if ( nField >= 0 && nOrient == DataPilotFieldOrientation_PAGE )
92         {
93             sal_Bool bIsDataLayout = sal_False;
94             String aFieldName = pDPObj->GetDimName( nField, bIsDataLayout );
95             if ( aFieldName.Len() && !bIsDataLayout )
96                 return DataPilotFieldOrientation_PAGE;
97         }
98     }
99 
100     nOrient = sheet::DataPilotFieldOrientation_HIDDEN;
101 
102     // Now, check for row/column field.
103     long nField = pDPObj->GetHeaderDim(ScAddress(nCol, nRow, nTab), nOrient);
104     if (nField >= 0 && (nOrient == DataPilotFieldOrientation_COLUMN || nOrient == DataPilotFieldOrientation_ROW) )
105     {
106         sal_Bool bIsDataLayout = sal_False;
107         String aFieldName = pDPObj->GetDimName(nField, bIsDataLayout);
108         if (aFieldName.Len() && !bIsDataLayout)
109             return static_cast<DataPilotFieldOrientation>(nOrient);
110     }
111 
112     return DataPilotFieldOrientation_HIDDEN;
113 }
114 
115 // private method for mouse button handling
116 sal_Bool ScGridWindow::DoPageFieldSelection( SCCOL nCol, SCROW nRow )
117 {
118     if (GetDPFieldOrientation( nCol, nRow ) == sheet::DataPilotFieldOrientation_PAGE)
119     {
120         LaunchPageFieldMenu( nCol, nRow );
121         return sal_True;
122     }
123 	return sal_False;
124 }
125 
126 bool ScGridWindow::DoAutoFilterButton( SCCOL nCol, SCROW nRow, const MouseEvent& rMEvt )
127 {
128     ScDocument* pDoc = pViewData->GetDocument();
129     SCTAB nTab = pViewData->GetTabNo();
130     Point aScrPos  = pViewData->GetScrPos(nCol, nRow, eWhich);
131     Point aDiffPix = rMEvt.GetPosPixel();
132 
133     aDiffPix -= aScrPos;
134     sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
135     if ( bLayoutRTL )
136         aDiffPix.X() = -aDiffPix.X();
137 
138     long nSizeX, nSizeY;
139     pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
140     Size aScrSize(nSizeX-1, nSizeY-1);
141 
142     // Check if the mouse cursor is clicking on the popup arrow box.
143     mpFilterButton.reset(new ScDPFieldButton(this, &GetSettings().GetStyleSettings(), &pViewData->GetZoomX(), &pViewData->GetZoomY(), pDoc));
144     mpFilterButton->setBoundingBox(aScrPos, aScrSize, bLayoutRTL);
145     mpFilterButton->setPopupLeft(bLayoutRTL);   // #i114944# AutoFilter button is left-aligned in RTL
146     Point aPopupPos;
147     Size aPopupSize;
148     mpFilterButton->getPopupBoundingBox(aPopupPos, aPopupSize);
149     Rectangle aRec(aPopupPos, aPopupSize);
150     if (aRec.IsInside(rMEvt.GetPosPixel()))
151     {
152         if ( DoPageFieldSelection( nCol, nRow ) )
153             return true;
154 
155         bool bFilterActive = IsAutoFilterActive(nCol, nRow, nTab);
156         mpFilterButton->setHasHiddenMember(bFilterActive);
157         mpFilterButton->setDrawBaseButton(false);
158         mpFilterButton->setDrawPopupButton(true);
159         mpFilterButton->setPopupPressed(true);
160         HideCursor();
161         mpFilterButton->draw();
162         ShowCursor();
163         DoAutoFilterMenue(nCol, nRow, false);
164         return true;
165     }
166 
167     return false;
168 }
169 
170 void ScGridWindow::DoPushButton( SCCOL nCol, SCROW nRow, const MouseEvent& rMEvt )
171 {
172 	ScDocument* pDoc = pViewData->GetDocument();
173 	SCTAB nTab = pViewData->GetTabNo();
174 
175 	ScDPObject*	pDPObj	= pDoc->GetDPAtCursor(nCol, nRow, nTab);
176 
177 	if (pDPObj)
178 	{
179 		sal_uInt16 nOrient = sheet::DataPilotFieldOrientation_HIDDEN;
180 		ScAddress aPos( nCol, nRow, nTab );
181 		long nField = pDPObj->GetHeaderDim( aPos, nOrient );
182 		if ( nField >= 0 )
183 		{
184 			bDPMouse   = sal_True;
185 			nDPField   = nField;
186 			pDragDPObj = pDPObj;
187 
188             if (DPTestFieldPopupArrow(rMEvt, aPos, pDPObj))
189             {
190                 // field name pop up menu has been launched.  Don't activate
191                 // field move.
192                 bDPMouse = false;
193                 return;
194             }
195 
196 			DPTestMouse( rMEvt, sal_True );
197 			StartTracking();
198 		}
199 		else if ( pDPObj->IsFilterButton(aPos) )
200 		{
201 			ReleaseMouse();			// may have been captured in ButtonDown
202 
203 			ScQueryParam aQueryParam;
204 			SCTAB nSrcTab = 0;
205 			const ScSheetSourceDesc* pDesc = pDPObj->GetSheetDesc();
206 			DBG_ASSERT(pDesc, "no sheet source for filter button");
207 			if (pDesc)
208 			{
209 				aQueryParam = pDesc->aQueryParam;
210 				nSrcTab = pDesc->aSourceRange.aStart.Tab();
211 			}
212 
213 			SfxItemSet aArgSet( pViewData->GetViewShell()->GetPool(),
214 										SCITEM_QUERYDATA, SCITEM_QUERYDATA );
215 			aArgSet.Put( ScQueryItem( SCITEM_QUERYDATA, pViewData, &aQueryParam ) );
216 
217 //CHINA001			ScPivotFilterDlg* pDlg = new ScPivotFilterDlg(
218 //CHINA001			pViewData->GetViewShell()->GetDialogParent(),
219 //CHINA001			aArgSet, nSrcTab );
220 			ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
221 			DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001
222 
223 			AbstractScPivotFilterDlg* pDlg = pFact->CreateScPivotFilterDlg( pViewData->GetViewShell()->GetDialogParent(),
224 																			aArgSet, nSrcTab,
225 																			RID_SCDLG_PIVOTFILTER);
226 			DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001
227 			if ( pDlg->Execute() == RET_OK )
228 			{
229 				ScSheetSourceDesc aNewDesc;
230 				if (pDesc)
231 					aNewDesc = *pDesc;
232 
233 				const ScQueryItem& rQueryItem = pDlg->GetOutputItem();
234 				aNewDesc.aQueryParam = rQueryItem.GetQueryData();
235 
236 				ScDPObject aNewObj( *pDPObj );
237 				aNewObj.SetSheetDesc( aNewDesc );
238 				ScDBDocFunc aFunc( *pViewData->GetDocShell() );
239 				aFunc.DataPilotUpdate( pDPObj, &aNewObj, sal_True, sal_False );
240 				pViewData->GetView()->CursorPosChanged();		// shells may be switched
241 			}
242 			delete pDlg;
243 		}
244 		else
245 			Sound::Beep();
246 	}
247 	else
248 	{
249 		DBG_ERROR("Da is ja garnix");
250 	}
251 }
252 
253 // -----------------------------------------------------------------------
254 //
255 //	Data Pilot interaction
256 //
257 
258 void ScGridWindow::DPTestMouse( const MouseEvent& rMEvt, sal_Bool bMove )
259 {
260 	DBG_ASSERT(pDragDPObj, "pDragDPObj missing");
261 
262 	//	scroll window if at edges
263 	//!	move this to separate method
264 
265 	sal_Bool bTimer = sal_False;
266 	Point aPixel = rMEvt.GetPosPixel();
267 
268 	SCsCOL nDx = 0;
269 	SCsROW nDy = 0;
270 	if ( aPixel.X() < 0 )
271 		nDx = -1;
272 	if ( aPixel.Y() < 0 )
273 		nDy = -1;
274 	Size aSize = GetOutputSizePixel();
275 	if ( aPixel.X() >= aSize.Width() )
276 		nDx = 1;
277 	if ( aPixel.Y() >= aSize.Height() )
278 		nDy = 1;
279 	if ( nDx != 0 || nDy != 0 )
280 	{
281 		UpdateDragRect( sal_False, Rectangle() );
282 
283 		if ( nDx  != 0)
284 			pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) );
285 		if ( nDy != 0 )
286 			pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) );
287 
288 		bTimer = sal_True;
289 	}
290 
291 	//	---
292 
293 	SCsCOL	nPosX;
294 	SCsROW	nPosY;
295 	pViewData->GetPosFromPixel( aPixel.X(), aPixel.Y(), eWhich, nPosX, nPosY );
296 	sal_Bool	bMouseLeft;
297 	sal_Bool	bMouseTop;
298 	pViewData->GetMouseQuadrant( aPixel, eWhich, nPosX, nPosY, bMouseLeft, bMouseTop );
299 
300 	ScAddress aPos( nPosX, nPosY, pViewData->GetTabNo() );
301 
302 	Rectangle aPosRect;
303 	sal_uInt16 nOrient;
304 	long nDimPos;
305 	sal_Bool bHasRange = pDragDPObj->GetHeaderDrag( aPos, bMouseLeft, bMouseTop, nDPField,
306 												aPosRect, nOrient, nDimPos );
307 	UpdateDragRect( bHasRange && bMove, aPosRect );
308 
309     sal_Bool bIsDataLayout;
310     sal_Int32 nDimFlags = 0;
311     String aDimName = pDragDPObj->GetDimName( nDPField, bIsDataLayout, &nDimFlags );
312     bool bAllowed = !bHasRange || ScDPObject::IsOrientationAllowed( nOrient, nDimFlags );
313 
314 	if (bMove)			// set mouse pointer
315 	{
316         PointerStyle ePointer = POINTER_PIVOT_DELETE;
317         if ( !bAllowed )
318             ePointer = POINTER_NOTALLOWED;
319         else if ( bHasRange )
320 			switch (nOrient)
321 			{
322 				case sheet::DataPilotFieldOrientation_COLUMN: ePointer = POINTER_PIVOT_COL;	break;
323 				case sheet::DataPilotFieldOrientation_ROW:	  ePointer = POINTER_PIVOT_ROW;	break;
324 				case sheet::DataPilotFieldOrientation_PAGE:
325 				case sheet::DataPilotFieldOrientation_DATA:	  ePointer = POINTER_PIVOT_FIELD;	break;
326 			}
327 		SetPointer( ePointer );
328 	}
329 	else				// execute change
330 	{
331 		if (!bHasRange)
332 			nOrient = sheet::DataPilotFieldOrientation_HIDDEN;
333 
334         if ( bIsDataLayout && ( nOrient != sheet::DataPilotFieldOrientation_COLUMN &&
335                                 nOrient != sheet::DataPilotFieldOrientation_ROW ) )
336 		{
337 			//	removing data layout is not allowed
338 			pViewData->GetView()->ErrorMessage(STR_PIVOT_MOVENOTALLOWED);
339 		}
340         else if ( bAllowed )
341 		{
342 			ScDPSaveData aSaveData( *pDragDPObj->GetSaveData() );
343 
344 			ScDPSaveDimension* pDim;
345 			if ( bIsDataLayout )
346 				pDim = aSaveData.GetDataLayoutDimension();
347 			else
348 				pDim = aSaveData.GetDimensionByName(aDimName);
349 			pDim->SetOrientation( nOrient );
350 			aSaveData.SetPosition( pDim, nDimPos );
351 
352 			//!	docfunc method with ScDPSaveData as argument?
353 
354 			ScDPObject aNewObj( *pDragDPObj );
355 			aNewObj.SetSaveData( aSaveData );
356 			ScDBDocFunc aFunc( *pViewData->GetDocShell() );
357 			// when dragging fields, allow re-positioning (bAllowMove)
358 			aFunc.DataPilotUpdate( pDragDPObj, &aNewObj, sal_True, sal_False, sal_True );
359 			pViewData->GetView()->CursorPosChanged();		// shells may be switched
360 		}
361 	}
362 
363 	if (bTimer && bMove)
364 		pViewData->GetView()->SetTimer( this, rMEvt );			// repeat event
365 	else
366 		pViewData->GetView()->ResetTimer();
367 }
368 
369 bool ScGridWindow::DPTestFieldPopupArrow(const MouseEvent& rMEvt, const ScAddress& rPos, ScDPObject* pDPObj)
370 {
371     sal_Bool bLayoutRTL = pViewData->GetDocument()->IsLayoutRTL( pViewData->GetTabNo() );
372 
373     // Get the geometry of the cell.
374     Point aScrPos = pViewData->GetScrPos(rPos.Col(), rPos.Row(), eWhich);
375     long nSizeX, nSizeY;
376     pViewData->GetMergeSizePixel(rPos.Col(), rPos.Row(), nSizeX, nSizeY);
377     Size aScrSize(nSizeX-1, nSizeY-1);
378 
379     // Check if the mouse cursor is clicking on the popup arrow box.
380     ScDPFieldButton aBtn(this, &GetSettings().GetStyleSettings());
381     aBtn.setBoundingBox(aScrPos, aScrSize, bLayoutRTL);
382     aBtn.setPopupLeft(false);   // DataPilot popup is always right-aligned for now
383     Point aPopupPos;
384     Size aPopupSize;
385     aBtn.getPopupBoundingBox(aPopupPos, aPopupSize);
386     Rectangle aRec(aPopupPos, aPopupSize);
387     if (aRec.IsInside(rMEvt.GetPosPixel()))
388     {
389         // Mouse cursor inside the popup arrow box.  Launch the field menu.
390         DPLaunchFieldPopupMenu(OutputToScreenPixel(aScrPos), aScrSize, rPos, pDPObj);
391         return true;
392     }
393 
394     return false;
395 }
396 
397 namespace {
398 
399 struct DPFieldPopupData : public ScDPFieldPopupWindow::ExtendedData
400 {
401     ScPivotParam    maDPParam;
402     ScDPObject*     mpDPObj;
403     long            mnDim;
404 };
405 
406 class DPFieldPopupOKAction : public ScMenuFloatingWindow::Action
407 {
408 public:
409     explicit DPFieldPopupOKAction(ScGridWindow* p) :
410         mpGridWindow(p) {}
411 
412     virtual void execute()
413     {
414         mpGridWindow->UpdateDPFromFieldPopupMenu();
415     }
416 private:
417     ScGridWindow* mpGridWindow;
418 };
419 
420 class PopupSortAction : public ScMenuFloatingWindow::Action
421 {
422 public:
423     enum SortType { ASCENDING, DESCENDING, CUSTOM };
424 
425     explicit PopupSortAction(const ScAddress& rPos, SortType eType, sal_uInt16 nUserListIndex, ScTabViewShell* pViewShell) :
426         maPos(rPos), meType(eType), mnUserListIndex(nUserListIndex), mpViewShell(pViewShell) {}
427 
428     virtual void execute()
429     {
430         switch (meType)
431         {
432             case ASCENDING:
433                 mpViewShell->DataPilotSort(maPos, true);
434             break;
435             case DESCENDING:
436                 mpViewShell->DataPilotSort(maPos, false);
437             break;
438             case CUSTOM:
439                 mpViewShell->DataPilotSort(maPos, true, &mnUserListIndex);
440             break;
441             default:
442                 ;
443         }
444     }
445 
446 private:
447     ScAddress       maPos;
448     SortType        meType;
449     sal_uInt16      mnUserListIndex;
450     ScTabViewShell* mpViewShell;
451 };
452 
453 }
454 
455 bool lcl_GetLabelIndex( size_t& rLabelIndex, long nDimension, const ScDPLabelDataVector& rLabelArray )
456 {
457     size_t n = rLabelArray.size();
458     for (size_t i = 0; i < n; ++i)
459         if (static_cast<long>(rLabelArray[i].mnCol) == nDimension)
460         {
461             rLabelIndex = i;
462             return true;
463         }
464     return false;
465 }
466 
467 void ScGridWindow::DPLaunchFieldPopupMenu(
468     const Point& rScrPos, const Size& rScrSize, const ScAddress& rPos, ScDPObject* pDPObj)
469 {
470     // We need to get the list of field members.
471     auto_ptr<DPFieldPopupData> pDPData(new DPFieldPopupData);
472     pDPObj->FillLabelData(pDPData->maDPParam);
473     pDPData->mpDPObj = pDPObj;
474 
475     sal_uInt16 nOrient;
476     pDPData->mnDim = pDPObj->GetHeaderDim(rPos, nOrient);
477 
478     // #i116457# FillLabelData skips empty column names, so mnDim can't be used directly as index into maLabelArray.
479     size_t nLabelIndex = 0;
480     if (!lcl_GetLabelIndex( nLabelIndex, pDPData->mnDim, pDPData->maDPParam.maLabelArray ))
481         return;
482 
483     const ScDPLabelData& rLabelData = pDPData->maDPParam.maLabelArray[nLabelIndex];
484 
485     mpDPFieldPopup.reset(new ScDPFieldPopupWindow(this, pViewData->GetDocument()));
486     mpDPFieldPopup->setName(OUString::createFromAscii("Pivot table field member popup"));
487     mpDPFieldPopup->setExtendedData(pDPData.release());
488     mpDPFieldPopup->setOKAction(new DPFieldPopupOKAction(this));
489     {
490         // Populate field members.
491         size_t n = rLabelData.maMembers.size();
492         mpDPFieldPopup->setMemberSize(n);
493         for (size_t i = 0; i < n; ++i)
494         {
495             const ScDPLabelData::Member& rMem = rLabelData.maMembers[i];
496             mpDPFieldPopup->addMember(rMem.getDisplayName(), rMem.mbVisible);
497         }
498         mpDPFieldPopup->initMembers();
499     }
500 
501     vector<OUString> aUserSortNames;
502     ScUserList* pUserList = ScGlobal::GetUserList();
503     if (pUserList)
504     {
505         sal_uInt16 n = pUserList->GetCount();
506         aUserSortNames.reserve(n);
507         for (sal_uInt16 i = 0; i < n; ++i)
508         {
509             ScUserListData* pData = static_cast<ScUserListData*>((*pUserList)[i]);
510             aUserSortNames.push_back(pData->GetString());
511         }
512     }
513 
514     // Populate the menus.
515     ScTabViewShell* pViewShell = pViewData->GetViewShell();
516     mpDPFieldPopup->addMenuItem(
517         ScRscStrLoader(RID_POPUP_FILTER, STR_MENU_SORT_ASC).GetString(), true,
518         new PopupSortAction(rPos, PopupSortAction::ASCENDING, 0, pViewShell));
519     mpDPFieldPopup->addMenuItem(
520         ScRscStrLoader(RID_POPUP_FILTER, STR_MENU_SORT_DESC).GetString(), true,
521         new PopupSortAction(rPos, PopupSortAction::DESCENDING, 0, pViewShell));
522     ScMenuFloatingWindow* pSubMenu = mpDPFieldPopup->addSubMenuItem(
523         ScRscStrLoader(RID_POPUP_FILTER, STR_MENU_SORT_CUSTOM).GetString(), !aUserSortNames.empty());
524 
525     if (pSubMenu && !aUserSortNames.empty())
526     {
527         size_t n = aUserSortNames.size();
528         for (size_t i = 0; i < n; ++i)
529         {
530             pSubMenu->addMenuItem(
531                 aUserSortNames[i], true,
532                 new PopupSortAction(rPos, PopupSortAction::CUSTOM, static_cast<sal_uInt16>(i), pViewShell));
533         }
534     }
535 
536     sal_Bool bLayoutRTL = pViewData->GetDocument()->IsLayoutRTL( pViewData->GetTabNo() );
537 
538     Rectangle aCellRect(rScrPos, rScrSize);
539     const Size& rPopupSize = mpDPFieldPopup->getWindowSize();
540     if (bLayoutRTL)
541     {
542         // RTL: rScrPos is logical-left (visual right) position, always right-align with that
543         aCellRect.SetPos(Point(rScrPos.X() - rPopupSize.Width() + 1, rScrPos.Y()));
544     }
545     else if (rScrSize.getWidth() > rPopupSize.getWidth())
546     {
547         // If the cell width is larger than the popup window width, launch it
548         // right-aligned with the cell.
549         long nXOffset = rScrSize.getWidth() - rPopupSize.getWidth();
550         aCellRect.SetPos(Point(rScrPos.X() + nXOffset, rScrPos.Y()));
551     }
552     mpDPFieldPopup->SetPopupModeEndHdl( LINK(this, ScGridWindow, PopupModeEndHdl) );
553     mpDPFieldPopup->StartPopupMode(aCellRect, (FLOATWIN_POPUPMODE_DOWN | FLOATWIN_POPUPMODE_GRABFOCUS));
554 }
555 
556 void ScGridWindow::UpdateDPFromFieldPopupMenu()
557 {
558     typedef hash_map<OUString, OUString, OUStringHash> MemNameMapType;
559     typedef hash_map<OUString, bool, OUStringHash> MemVisibilityType;
560 
561     if (!mpDPFieldPopup.get())
562         return;
563 
564     DPFieldPopupData* pDPData = static_cast<DPFieldPopupData*>(mpDPFieldPopup->getExtendedData());
565     if (!pDPData)
566         return;
567 
568     ScDPObject* pDPObj = pDPData->mpDPObj;
569     ScDPObject aNewDPObj(*pDPObj);
570     aNewDPObj.BuildAllDimensionMembers();
571     ScDPSaveData* pSaveData = aNewDPObj.GetSaveData();
572 
573     sal_Bool bIsDataLayout;
574     String aDimName = pDPObj->GetDimName(pDPData->mnDim, bIsDataLayout);
575     ScDPSaveDimension* pDim = pSaveData->GetDimensionByName(aDimName);
576     if (!pDim)
577         return;
578 
579     size_t nLabelIndex = 0;
580     lcl_GetLabelIndex( nLabelIndex, pDPData->mnDim, pDPData->maDPParam.maLabelArray );
581 
582     // Build a map of layout names to original names.
583     const ScDPLabelData& rLabelData = pDPData->maDPParam.maLabelArray[nLabelIndex];
584     MemNameMapType aMemNameMap;
585     for (vector<ScDPLabelData::Member>::const_iterator itr = rLabelData.maMembers.begin(), itrEnd = rLabelData.maMembers.end();
586            itr != itrEnd; ++itr)
587         aMemNameMap.insert(MemNameMapType::value_type(itr->maLayoutName, itr->maName));
588 
589     // The raw result may contain a mixture of layout names and original names.
590     MemVisibilityType aRawResult;
591     mpDPFieldPopup->getResult(aRawResult);
592 
593     MemVisibilityType aResult;
594     for (MemVisibilityType::const_iterator itr = aRawResult.begin(), itrEnd = aRawResult.end(); itr != itrEnd; ++itr)
595     {
596         MemNameMapType::const_iterator itrNameMap = aMemNameMap.find(itr->first);
597         if (itrNameMap == aMemNameMap.end())
598             // This is an original member name.  Use it as-is.
599             aResult.insert(MemVisibilityType::value_type(itr->first, itr->second));
600         else
601         {
602             // This is a layout name.  Get the original member name and use it.
603             aResult.insert(MemVisibilityType::value_type(itrNameMap->second, itr->second));
604         }
605     }
606     pDim->UpdateMemberVisibility(aResult);
607 
608     ScDBDocFunc aFunc(*pViewData->GetDocShell());
609     aFunc.DataPilotUpdate(pDPObj, &aNewDPObj, true, false);
610 }
611 
612 void ScGridWindow::DPMouseMove( const MouseEvent& rMEvt )
613 {
614 	DPTestMouse( rMEvt, sal_True );
615 }
616 
617 void ScGridWindow::DPMouseButtonUp( const MouseEvent& rMEvt )
618 {
619 	bDPMouse = sal_False;
620 	ReleaseMouse();
621 
622 	DPTestMouse( rMEvt, sal_False );
623 	SetPointer( Pointer( POINTER_ARROW ) );
624 }
625 
626 // -----------------------------------------------------------------------
627 
628 void ScGridWindow::UpdateDragRect( sal_Bool bShowRange, const Rectangle& rPosRect )
629 {
630 	SCCOL nStartX = ( rPosRect.Left()   >= 0 ) ? static_cast<SCCOL>(rPosRect.Left())   : SCCOL_MAX;
631 	SCROW nStartY = ( rPosRect.Top()    >= 0 ) ? static_cast<SCROW>(rPosRect.Top())    : SCROW_MAX;
632 	SCCOL nEndX   = ( rPosRect.Right()  >= 0 ) ? static_cast<SCCOL>(rPosRect.Right())  : SCCOL_MAX;
633 	SCROW nEndY   = ( rPosRect.Bottom() >= 0 ) ? static_cast<SCROW>(rPosRect.Bottom()) : SCROW_MAX;
634 
635 	if ( bShowRange == bDragRect && nDragStartX == nStartX && nDragEndX == nEndX &&
636 									nDragStartY == nStartY && nDragEndY == nEndY )
637 	{
638 		return;			// everything unchanged
639 	}
640 
641 	// if ( bDragRect )
642 	//	DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, sal_False );
643 	if ( bShowRange )
644 	{
645 		nDragStartX = nStartX;
646 		nDragStartY = nStartY;
647 		nDragEndX = nEndX;
648 		nDragEndY = nEndY;
649 		bDragRect = sal_True;
650 		// DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, sal_False );
651 	}
652 	else
653 		bDragRect = sal_False;
654 
655     UpdateDragRectOverlay();
656 }
657 
658 // -----------------------------------------------------------------------
659 
660 //	Page-Break-Modus
661 
662 sal_uInt16 ScGridWindow::HitPageBreak( const Point& rMouse, ScRange* pSource,
663 									SCCOLROW* pBreak, SCCOLROW* pPrev )
664 {
665 	sal_uInt16 nFound = SC_PD_NONE;		// 0
666 	ScRange aSource;
667 	SCCOLROW nBreak = 0;
668 	SCCOLROW nPrev = 0;
669 
670 	ScPageBreakData* pPageData = pViewData->GetView()->GetPageBreakData();
671 	if ( pPageData )
672 	{
673 		sal_Bool bHori = sal_False;
674 		sal_Bool bVert = sal_False;
675         SCCOL nHitX = 0;
676         SCROW nHitY = 0;
677 
678 		long nMouseX = rMouse.X();
679 		long nMouseY = rMouse.Y();
680         SCsCOL nPosX;
681         SCsROW nPosY;
682         pViewData->GetPosFromPixel( nMouseX, nMouseY, eWhich, nPosX, nPosY );
683 		Point aTL = pViewData->GetScrPos( nPosX, nPosY, eWhich );
684 		Point aBR = pViewData->GetScrPos( nPosX+1, nPosY+1, eWhich );
685 
686 		//	Horizontal mehr Toleranz als vertikal, weil mehr Platz ist
687 		if ( nMouseX <= aTL.X() + 4 )
688 		{
689 			bHori = sal_True;
690 			nHitX = nPosX;
691 		}
692 		else if ( nMouseX >= aBR.X() - 6 )
693 		{
694 			bHori = sal_True;
695 			nHitX = nPosX+1;					// linker Rand der naechsten Zelle
696 		}
697 		if ( nMouseY <= aTL.Y() + 2 )
698 		{
699 			bVert = sal_True;
700 			nHitY = nPosY;
701 		}
702 		else if ( nMouseY >= aBR.Y() - 4 )
703 		{
704 			bVert = sal_True;
705 			nHitY = nPosY+1;					// oberer Rand der naechsten Zelle
706 		}
707 
708 		if ( bHori || bVert )
709 		{
710             sal_uInt16 nCount = sal::static_int_cast<sal_uInt16>( pPageData->GetCount() );
711 			for (sal_uInt16 nPos=0; nPos<nCount && !nFound; nPos++)
712 			{
713 				ScPrintRangeData& rData = pPageData->GetData(nPos);
714 				ScRange aRange = rData.GetPrintRange();
715 				sal_Bool bLHit = ( bHori && nHitX == aRange.aStart.Col() );
716 				sal_Bool bRHit = ( bHori && nHitX == aRange.aEnd.Col() + 1 );
717 				sal_Bool bTHit = ( bVert && nHitY == aRange.aStart.Row() );
718 				sal_Bool bBHit = ( bVert && nHitY == aRange.aEnd.Row() + 1 );
719 				sal_Bool bInsideH = ( nPosX >= aRange.aStart.Col() && nPosX <= aRange.aEnd.Col() );
720 				sal_Bool bInsideV = ( nPosY >= aRange.aStart.Row() && nPosY <= aRange.aEnd.Row() );
721 
722 				if ( bLHit )
723 				{
724 					if ( bTHit )
725 						nFound = SC_PD_RANGE_TL;
726 					else if ( bBHit )
727 						nFound = SC_PD_RANGE_BL;
728 					else if ( bInsideV )
729 						nFound = SC_PD_RANGE_L;
730 				}
731 				else if ( bRHit )
732 				{
733 					if ( bTHit )
734 						nFound = SC_PD_RANGE_TR;
735 					else if ( bBHit )
736 						nFound = SC_PD_RANGE_BR;
737 					else if ( bInsideV )
738 						nFound = SC_PD_RANGE_R;
739 				}
740 				else if ( bTHit && bInsideH )
741 					nFound = SC_PD_RANGE_T;
742 				else if ( bBHit && bInsideH )
743 					nFound = SC_PD_RANGE_B;
744 				if (nFound)
745 					aSource = aRange;
746 
747 				//	Umbrueche
748 
749 				if ( bVert && bInsideH && !nFound )
750 				{
751 					size_t nRowCount = rData.GetPagesY();
752 					const SCROW* pRowEnd = rData.GetPageEndY();
753 					for (size_t nRowPos=0; nRowPos+1<nRowCount; nRowPos++)
754 						if ( pRowEnd[nRowPos]+1 == nHitY )
755 						{
756 							nFound = SC_PD_BREAK_V;
757 							aSource = aRange;
758 							nBreak = nHitY;
759 							if ( nRowPos )
760 								nPrev = pRowEnd[nRowPos-1]+1;
761 							else
762 								nPrev = aRange.aStart.Row();
763 						}
764 				}
765 				if ( bHori && bInsideV && !nFound )
766 				{
767 					size_t nColCount = rData.GetPagesX();
768 					const SCCOL* pColEnd = rData.GetPageEndX();
769 					for (size_t nColPos=0; nColPos+1<nColCount; nColPos++)
770 						if ( pColEnd[nColPos]+1 == nHitX )
771 						{
772 							nFound = SC_PD_BREAK_H;
773 							aSource = aRange;
774 							nBreak = nHitX;
775 							if ( nColPos )
776 								nPrev = pColEnd[nColPos-1]+1;
777 							else
778 								nPrev = aRange.aStart.Col();
779 						}
780 				}
781 			}
782 		}
783 	}
784 
785 	if (pSource)
786 		*pSource = aSource;		// Druckbereich
787 	if (pBreak)
788 		*pBreak = nBreak;		// X/Y Position des verchobenen Seitenumbruchs
789 	if (pPrev)
790 		*pPrev = nPrev;			// X/Y Anfang der Seite, die am Umbruch zuende ist
791 	return nFound;
792 }
793 
794 void ScGridWindow::PagebreakMove( const MouseEvent& rMEvt, sal_Bool bUp )
795 {
796 	//!	Scrolling und Umschalten mit RFMouseMove zusammenfassen !
797 	//!	(Weginvertieren vor dem Scrolling ist anders)
798 
799 	//	Scrolling
800 
801 	sal_Bool bTimer = sal_False;
802 	Point aPos = rMEvt.GetPosPixel();
803 	SCsCOL nDx = 0;
804 	SCsROW nDy = 0;
805 	if ( aPos.X() < 0 ) nDx = -1;
806 	if ( aPos.Y() < 0 ) nDy = -1;
807 	Size aSize = GetOutputSizePixel();
808 	if ( aPos.X() >= aSize.Width() )
809 		nDx = 1;
810 	if ( aPos.Y() >= aSize.Height() )
811 		nDy = 1;
812 	if ( nDx != 0 || nDy != 0 )
813 	{
814 		if ( bPagebreakDrawn )			// weginvertieren
815 		{
816 			// DrawDragRect( aPagebreakDrag.aStart.Col(), aPagebreakDrag.aStart.Row(),
817 			//				aPagebreakDrag.aEnd.Col(), aPagebreakDrag.aEnd.Row(), sal_False );
818 			bPagebreakDrawn = sal_False;
819             UpdateDragRectOverlay();
820 		}
821 
822 		if ( nDx != 0 ) pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) );
823 		if ( nDy != 0 ) pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) );
824 		bTimer = sal_True;
825 	}
826 
827 	//	Umschalten bei Fixierung (damit Scrolling funktioniert)
828 
829 	if ( eWhich == pViewData->GetActivePart() )		//??
830 	{
831 		if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX )
832 			if ( nDx > 0 )
833 			{
834 				if ( eWhich == SC_SPLIT_TOPLEFT )
835 					pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT );
836 				else if ( eWhich == SC_SPLIT_BOTTOMLEFT )
837 					pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT );
838 			}
839 
840 		if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX )
841 			if ( nDy > 0 )
842 			{
843 				if ( eWhich == SC_SPLIT_TOPLEFT )
844 					pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT );
845 				else if ( eWhich == SC_SPLIT_TOPRIGHT )
846 					pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT );
847 			}
848 	}
849 
850 	//	ab hier neu
851 
852 	//	gesucht wird eine Position zwischen den Zellen (vor nPosX / nPosY)
853 	SCsCOL nPosX;
854 	SCsROW nPosY;
855 	pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
856 	sal_Bool bLeft, bTop;
857 	pViewData->GetMouseQuadrant( aPos, eWhich, nPosX, nPosY, bLeft, bTop );
858 	if ( !bLeft ) ++nPosX;
859 	if ( !bTop )  ++nPosY;
860 
861 	sal_Bool bBreak = ( nPagebreakMouse == SC_PD_BREAK_H || nPagebreakMouse == SC_PD_BREAK_V );
862 	sal_Bool bHide = sal_False;
863 	sal_Bool bToEnd = sal_False;
864 	ScRange aDrawRange = aPagebreakSource;
865 	if ( bBreak )
866 	{
867 		if ( nPagebreakMouse == SC_PD_BREAK_H )
868 		{
869 			if ( nPosX > aPagebreakSource.aStart.Col() &&
870 				 nPosX <= aPagebreakSource.aEnd.Col() + 1 )		// ans Ende ist auch erlaubt
871 			{
872 				bToEnd = ( nPosX == aPagebreakSource.aEnd.Col() + 1 );
873 				aDrawRange.aStart.SetCol( nPosX );
874 				aDrawRange.aEnd.SetCol( nPosX - 1 );
875 			}
876 			else
877 				bHide = sal_True;
878 		}
879 		else
880 		{
881 			if ( nPosY > aPagebreakSource.aStart.Row() &&
882 				 nPosY <= aPagebreakSource.aEnd.Row() + 1 )		// ans Ende ist auch erlaubt
883 			{
884 				bToEnd = ( nPosY == aPagebreakSource.aEnd.Row() + 1 );
885 				aDrawRange.aStart.SetRow( nPosY );
886 				aDrawRange.aEnd.SetRow( nPosY - 1 );
887 			}
888 			else
889 				bHide = sal_True;
890 		}
891 	}
892 	else
893 	{
894 		if ( nPagebreakMouse & SC_PD_RANGE_L )
895 			aDrawRange.aStart.SetCol( nPosX );
896 		if ( nPagebreakMouse & SC_PD_RANGE_T )
897 			aDrawRange.aStart.SetRow( nPosY );
898 		if ( nPagebreakMouse & SC_PD_RANGE_R )
899 		{
900 			if ( nPosX > 0 )
901 				aDrawRange.aEnd.SetCol( nPosX-1 );
902 			else
903 				bHide = sal_True;
904 		}
905 		if ( nPagebreakMouse & SC_PD_RANGE_B )
906 		{
907 			if ( nPosY > 0 )
908 				aDrawRange.aEnd.SetRow( nPosY-1 );
909 			else
910 				bHide = sal_True;
911 		}
912 		if ( aDrawRange.aStart.Col() > aDrawRange.aEnd.Col() ||
913 			 aDrawRange.aStart.Row() > aDrawRange.aEnd.Row() )
914 			bHide = sal_True;
915 	}
916 
917 	if ( !bPagebreakDrawn || bUp || aDrawRange != aPagebreakDrag )
918 	{
919 		//	zeichnen...
920 
921 		if ( bPagebreakDrawn )
922 		{
923 			// weginvertieren
924 			// DrawDragRect( aPagebreakDrag.aStart.Col(), aPagebreakDrag.aStart.Row(),
925 			//				aPagebreakDrag.aEnd.Col(), aPagebreakDrag.aEnd.Row(), sal_False );
926 			bPagebreakDrawn = sal_False;
927 		}
928 		aPagebreakDrag = aDrawRange;
929 		if ( !bUp && !bHide )
930 		{
931 			// hininvertieren
932 			// DrawDragRect( aPagebreakDrag.aStart.Col(), aPagebreakDrag.aStart.Row(),
933 			//				aPagebreakDrag.aEnd.Col(), aPagebreakDrag.aEnd.Row(), sal_False );
934 			bPagebreakDrawn = sal_True;
935 		}
936         UpdateDragRectOverlay();
937 	}
938 
939 	//	bei ButtonUp die Aenderung ausfuehren
940 
941 	if ( bUp )
942 	{
943 		ScViewFunc* pViewFunc = pViewData->GetView();
944 		ScDocShell* pDocSh = pViewData->GetDocShell();
945 		ScDocument* pDoc = pDocSh->GetDocument();
946 		SCTAB nTab = pViewData->GetTabNo();
947 		sal_Bool bUndo (pDoc->IsUndoEnabled());
948 
949 		if ( bBreak )
950 		{
951 			sal_Bool bColumn = ( nPagebreakMouse == SC_PD_BREAK_H );
952 			SCCOLROW nNew = bColumn ? static_cast<SCCOLROW>(nPosX) : static_cast<SCCOLROW>(nPosY);
953 			if ( nNew != nPagebreakBreak )
954 			{
955 				if (bUndo)
956 				{
957 					String aUndo = ScGlobal::GetRscString( STR_UNDO_DRAG_BREAK );
958 					pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
959 				}
960 
961 				sal_Bool bGrow = !bHide && nNew > nPagebreakBreak;
962 				if ( bColumn )
963 				{
964                     if (pDoc->HasColBreak(static_cast<SCCOL>(nPagebreakBreak), nTab) & BREAK_MANUAL)
965 					{
966 						ScAddress aOldAddr( static_cast<SCCOL>(nPagebreakBreak), nPosY, nTab );
967 						pViewFunc->DeletePageBreak( sal_True, sal_True, &aOldAddr, sal_False );
968 					}
969 					if ( !bHide && !bToEnd )	// am Ende nicht
970 					{
971 						ScAddress aNewAddr( static_cast<SCCOL>(nNew), nPosY, nTab );
972 						pViewFunc->InsertPageBreak( sal_True, sal_True, &aNewAddr, sal_False );
973 					}
974 					if ( bGrow )
975 					{
976 						//	vorigen Break auf hart, und Skalierung aendern
977                         bool bManualBreak = (pDoc->HasColBreak(static_cast<SCCOL>(nPagebreakPrev), nTab) & BREAK_MANUAL);
978                         if ( static_cast<SCCOL>(nPagebreakPrev) > aPagebreakSource.aStart.Col() && !bManualBreak )
979 						{
980 							ScAddress aPrev( static_cast<SCCOL>(nPagebreakPrev), nPosY, nTab );
981 							pViewFunc->InsertPageBreak( sal_True, sal_True, &aPrev, sal_False );
982 						}
983 
984 						if (!pDocSh->AdjustPrintZoom( ScRange(
985 									  static_cast<SCCOL>(nPagebreakPrev),0,nTab, static_cast<SCCOL>(nNew-1),0,nTab ) ))
986 							bGrow = sal_False;
987 					}
988 				}
989 				else
990 				{
991                     if (pDoc->HasRowBreak(nPagebreakBreak, nTab) & BREAK_MANUAL)
992 					{
993 						ScAddress aOldAddr( nPosX, nPagebreakBreak, nTab );
994 						pViewFunc->DeletePageBreak( sal_False, sal_True, &aOldAddr, sal_False );
995 					}
996 					if ( !bHide && !bToEnd )	// am Ende nicht
997 					{
998 						ScAddress aNewAddr( nPosX, nNew, nTab );
999 						pViewFunc->InsertPageBreak( sal_False, sal_True, &aNewAddr, sal_False );
1000 					}
1001 					if ( bGrow )
1002 					{
1003 						//	vorigen Break auf hart, und Skalierung aendern
1004                         bool bManualBreak = (pDoc->HasRowBreak(nPagebreakPrev, nTab) & BREAK_MANUAL);
1005                         if ( nPagebreakPrev > aPagebreakSource.aStart.Row() && !bManualBreak )
1006 						{
1007 							ScAddress aPrev( nPosX, nPagebreakPrev, nTab );
1008 							pViewFunc->InsertPageBreak( sal_False, sal_True, &aPrev, sal_False );
1009 						}
1010 
1011 						if (!pDocSh->AdjustPrintZoom( ScRange(
1012 									  0,nPagebreakPrev,nTab, 0,nNew-1,nTab ) ))
1013 							bGrow = sal_False;
1014 					}
1015 				}
1016 
1017 				if (bUndo)
1018 				{
1019 					pDocSh->GetUndoManager()->LeaveListAction();
1020 				}
1021 
1022 				if (!bGrow)		// sonst in AdjustPrintZoom schon passiert
1023 				{
1024 					pViewFunc->UpdatePageBreakData( sal_True );
1025 					pDocSh->SetDocumentModified();
1026 				}
1027 			}
1028 		}
1029 		else if ( bHide || aPagebreakDrag != aPagebreakSource )
1030 		{
1031 			//	Druckbereich setzen
1032 
1033 			String aNewRanges;
1034 			sal_uInt16 nOldCount = pDoc->GetPrintRangeCount( nTab );
1035 			if ( nOldCount )
1036 			{
1037 				for (sal_uInt16 nPos=0; nPos<nOldCount; nPos++)
1038 				{
1039 					const ScRange* pOld = pDoc->GetPrintRange( nTab, nPos );
1040 					if ( pOld )
1041 					{
1042 						String aTemp;
1043 						if ( *pOld != aPagebreakSource )
1044 							pOld->Format( aTemp, SCA_VALID );
1045 						else if ( !bHide )
1046 							aPagebreakDrag.Format( aTemp, SCA_VALID );
1047 						if (aTemp.Len())
1048 						{
1049 							if ( aNewRanges.Len() )
1050 								aNewRanges += ';';
1051 							aNewRanges += aTemp;
1052 						}
1053 					}
1054 				}
1055 			}
1056 			else if (!bHide)
1057 				aPagebreakDrag.Format( aNewRanges, SCA_VALID );
1058 
1059             pViewFunc->SetPrintRanges( pDoc->IsPrintEntireSheet( nTab ), &aNewRanges, NULL, NULL, sal_False );
1060 		}
1061 	}
1062 
1063 	//	Timer fuer Scrolling
1064 
1065 	if (bTimer && !bUp)
1066 		pViewData->GetView()->SetTimer( this, rMEvt );			// Event wiederholen
1067 	else
1068 		pViewData->GetView()->ResetTimer();
1069 }
1070 
1071 
1072 
1073 
1074