xref: /AOO41X/main/sc/source/ui/view/gridwin2.cxx (revision 8809db7a87f97847b57a57f4cd2b0104b2b83182)
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