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