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 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_sc.hxx"
24
25 #include "scitems.hxx"
26
27 #include <memory> //auto_ptr
28 #include <editeng/adjitem.hxx>
29 #include <svx/algitem.hxx>
30 #include <svx/dbexch.hrc>
31 #include <editeng/editview.hxx>
32 #include <editeng/editstat.hxx>
33 #include <editeng/flditem.hxx>
34 #include <svx/svdetc.hxx>
35 #include <editeng/editobj.hxx>
36 #include <sfx2/dispatch.hxx>
37 #include <sfx2/viewfrm.hxx>
38 #include <sfx2/docfile.hxx>
39 #include <svl/stritem.hxx>
40 #include <svtools/svlbox.hxx>
41 #include <svtools/svtabbx.hxx>
42 #include <svl/urlbmk.hxx>
43 #include <tools/urlobj.hxx>
44 #include <vcl/cursor.hxx>
45 #include <vcl/sound.hxx>
46 #include <vcl/graph.hxx>
47 #include <vcl/hatch.hxx>
48 #include <sot/formats.hxx>
49 #include <sot/clsids.hxx>
50
51 #include <svx/svdview.hxx> // for Command-Handler (COMMAND_INSERTTEXT)
52 #include <editeng/outliner.hxx> // for Command-Handler (COMMAND_INSERTTEXT)
53 #include <svx/svditer.hxx>
54 #include <svx/svdocapt.hxx>
55 #include <svx/svdpagv.hxx>
56
57 #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
58 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
59 #include <com/sun/star/sheet/DataPilotTableHeaderData.hpp>
60 #include <com/sun/star/sheet/DataPilotTableResultData.hpp>
61 #include <com/sun/star/sheet/DataPilotTablePositionData.hpp>
62 #include <com/sun/star/sheet/DataPilotTablePositionType.hpp>
63 #include <com/sun/star/sheet/MemberResultFlags.hpp>
64 #include <com/sun/star/awt/KeyModifier.hpp>
65 #include <com/sun/star/awt/MouseButton.hpp>
66 #include <com/sun/star/script/vba/VBAEventId.hpp>
67 #include <com/sun/star/script/vba/XVBAEventProcessor.hpp>
68
69 #include "gridwin.hxx"
70 #include "tabvwsh.hxx"
71 #include "docsh.hxx"
72 #include "viewdata.hxx"
73 #include "tabview.hxx"
74 #include "select.hxx"
75 #include "scmod.hxx"
76 #include "document.hxx"
77 #include "attrib.hxx"
78 #include "dbcolect.hxx"
79 #include "stlpool.hxx"
80 #include "printfun.hxx"
81 #include "cbutton.hxx"
82 #include "sc.hrc"
83 #include "globstr.hrc"
84 #include "editutil.hxx"
85 #include "scresid.hxx"
86 #include "inputhdl.hxx"
87 #include "uiitems.hxx" // Filter-Dialog - auslagern !!!
88 #include "filtdlg.hxx"
89 #include "impex.hxx" // Sylk-ID for CB
90 #include "cell.hxx" // für Edit-Felder
91 #include "patattr.hxx"
92 #include "notemark.hxx"
93 #include "rfindlst.hxx"
94 #include "docpool.hxx"
95 #include "output.hxx"
96 #include "docfunc.hxx"
97 #include "dbdocfun.hxx"
98 #include "dpobject.hxx"
99 #include "dpoutput.hxx"
100 #include "transobj.hxx"
101 #include "drwtrans.hxx"
102 #include "seltrans.hxx"
103 #include "sizedev.hxx"
104 #include "AccessibilityHints.hxx"
105 #include "dpsave.hxx"
106 #include "viewuno.hxx"
107 #include "compiler.hxx"
108 #include "editable.hxx"
109 #include "fillinfo.hxx"
110 #include "scitems.hxx"
111 #include "userdat.hxx"
112 #include "drwlayer.hxx"
113 #include "attrib.hxx"
114 #include "validat.hxx"
115 #include "tabprotection.hxx"
116 #include "postit.hxx"
117 #include "dpcontrol.hxx"
118 #include "cellsuno.hxx"
119
120 #include "drawview.hxx"
121 #include <svx/sdrpagewindow.hxx>
122 #include <svx/sdr/overlay/overlaymanager.hxx>
123 #include <vcl/svapp.hxx>
124 #include <svx/sdr/overlay/overlayselection.hxx>
125
126 using namespace com::sun::star;
127 using ::com::sun::star::uno::Sequence;
128 using ::com::sun::star::uno::Any;
129
130 const sal_uInt8 SC_NESTEDBUTTON_NONE = 0;
131 const sal_uInt8 SC_NESTEDBUTTON_DOWN = 1;
132 const sal_uInt8 SC_NESTEDBUTTON_UP = 2;
133
134 #define SC_AUTOFILTER_ALL 0
135 #define SC_AUTOFILTER_TOP10 1
136 #define SC_AUTOFILTER_CUSTOM 2
137 #define SC_AUTOFILTER_EMPTY 3
138 #define SC_AUTOFILTER_NOTEMPTY 4
139
140 // Modi für die FilterListBox
141 enum ScFilterBoxMode
142 {
143 SC_FILTERBOX_FILTER,
144 SC_FILTERBOX_DATASELECT,
145 SC_FILTERBOX_SCENARIO,
146 SC_FILTERBOX_PAGEFIELD
147 };
148
149 extern SfxViewShell* pScActiveViewShell; // global.cxx
150 extern sal_uInt16 nScClickMouseModifier; // global.cxx
151 extern sal_uInt16 nScFillModeMouseModifier; // global.cxx
152
153 #define SC_FILTERLISTBOX_LINES 12
154
155 // ============================================================================
156
VisibleRange()157 ScGridWindow::VisibleRange::VisibleRange() :
158 mnCol1(0), mnCol2(MAXCOL), mnRow1(0), mnRow2(MAXROW)
159 {
160 }
161
isInside(SCCOL nCol,SCROW nRow) const162 bool ScGridWindow::VisibleRange::isInside(SCCOL nCol, SCROW nRow) const
163 {
164 return mnCol1 <= nCol && nCol <= mnCol2 && mnRow1 <= nRow && nRow <= mnRow2;
165 }
166
167 // ============================================================================
168
169 class ScFilterListBox : public ListBox
170 {
171 private:
172 ScGridWindow* pGridWin;
173 SCCOL nCol;
174 SCROW nRow;
175 sal_Bool bButtonDown;
176 sal_Bool bInit;
177 sal_Bool bCancelled;
178 sal_Bool bInSelect;
179 bool mbListHasDates;
180 sal_uLong nSel;
181 ScFilterBoxMode eMode;
182
183 protected:
184 virtual void LoseFocus();
185 void SelectHdl();
186
187 public:
188 ScFilterListBox( Window* pParent, ScGridWindow* pGrid,
189 SCCOL nNewCol, SCROW nNewRow, ScFilterBoxMode eNewMode );
190 ~ScFilterListBox();
191
192 virtual long PreNotify( NotifyEvent& rNEvt );
193 virtual void Select();
194
GetCol() const195 SCCOL GetCol() const { return nCol; }
GetRow() const196 SCROW GetRow() const { return nRow; }
GetMode() const197 ScFilterBoxMode GetMode() const { return eMode; }
IsDataSelect() const198 sal_Bool IsDataSelect() const { return (eMode == SC_FILTERBOX_DATASELECT); }
199 void EndInit();
IsInInit() const200 sal_Bool IsInInit() const { return bInit; }
SetCancelled()201 void SetCancelled() { bCancelled = sal_True; }
IsInSelect() const202 sal_Bool IsInSelect() const { return bInSelect; }
SetListHasDates(bool b)203 void SetListHasDates(bool b) { mbListHasDates = b; }
HasDates() const204 bool HasDates() const { return mbListHasDates; }
205 };
206
207 //-------------------------------------------------------------------
208
209 // ListBox in einem FloatingWindow (pParent)
ScFilterListBox(Window * pParent,ScGridWindow * pGrid,SCCOL nNewCol,SCROW nNewRow,ScFilterBoxMode eNewMode)210 ScFilterListBox::ScFilterListBox( Window* pParent, ScGridWindow* pGrid,
211 SCCOL nNewCol, SCROW nNewRow, ScFilterBoxMode eNewMode ) :
212 ListBox( pParent, WB_AUTOHSCROLL ),
213 pGridWin( pGrid ),
214 nCol( nNewCol ),
215 nRow( nNewRow ),
216 bButtonDown( sal_False ),
217 bInit( sal_True ),
218 bCancelled( sal_False ),
219 bInSelect( sal_False ),
220 mbListHasDates(false),
221 nSel( 0 ),
222 eMode( eNewMode )
223 {
224 }
225
~ScFilterListBox()226 __EXPORT ScFilterListBox::~ScFilterListBox()
227 {
228 if (IsMouseCaptured())
229 ReleaseMouse();
230 }
231
EndInit()232 void ScFilterListBox::EndInit()
233 {
234 sal_uInt16 nPos = GetSelectEntryPos();
235 if ( LISTBOX_ENTRY_NOTFOUND == nPos )
236 nSel = 0;
237 else
238 nSel = nPos;
239
240 bInit = sal_False;
241 }
242
LoseFocus()243 void __EXPORT ScFilterListBox::LoseFocus()
244 {
245 #ifndef UNX
246 Hide();
247 #endif
248 }
249
250 // -----------------------------------------------------------------------
251
PreNotify(NotifyEvent & rNEvt)252 long ScFilterListBox::PreNotify( NotifyEvent& rNEvt )
253 {
254 long nDone = 0;
255 if ( rNEvt.GetType() == EVENT_KEYINPUT )
256 {
257 KeyEvent aKeyEvt = *rNEvt.GetKeyEvent();
258 KeyCode aCode = aKeyEvt.GetKeyCode();
259 if ( !aCode.GetModifier() ) // ohne alle Modifiers
260 {
261 sal_uInt16 nKey = aCode.GetCode();
262 if ( nKey == KEY_RETURN )
263 {
264 SelectHdl(); // auswählen
265 nDone = 1;
266 }
267 else if ( nKey == KEY_ESCAPE )
268 {
269 pGridWin->ClickExtern(); // löscht die List-Box !!!
270 nDone = 1;
271 }
272 }
273 }
274
275 return nDone ? nDone : ListBox::PreNotify( rNEvt );
276 }
277
Select()278 void __EXPORT ScFilterListBox::Select()
279 {
280 ListBox::Select();
281 SelectHdl();
282 }
283
SelectHdl()284 void __EXPORT ScFilterListBox::SelectHdl()
285 {
286 if ( !IsTravelSelect() && !bInit && !bCancelled )
287 {
288 sal_uInt16 nPos = GetSelectEntryPos();
289 if ( LISTBOX_ENTRY_NOTFOUND != nPos )
290 {
291 nSel = nPos;
292 if (!bButtonDown)
293 {
294 // #i81298# set bInSelect flag, so the box isn't deleted from modifications within FilterSelect
295 bInSelect = sal_True;
296 pGridWin->FilterSelect( nSel );
297 bInSelect = sal_False;
298 }
299 }
300 }
301 }
302
303 // ============================================================================
304
305 // use a System floating window for the above filter listbox
306 class ScFilterFloatingWindow : public FloatingWindow
307 {
308 public:
309 ScFilterFloatingWindow( Window* pParent, WinBits nStyle = WB_STDFLOATWIN );
310 virtual ~ScFilterFloatingWindow();
311 // required for System FloatingWindows that will not process KeyInput by themselves
312 virtual Window* GetPreferredKeyInputWindow();
313 };
314
ScFilterFloatingWindow(Window * pParent,WinBits nStyle)315 ScFilterFloatingWindow::ScFilterFloatingWindow( Window* pParent, WinBits nStyle ) :
316 FloatingWindow( pParent, nStyle|WB_SYSTEMWINDOW ) // make it a system floater
317 {}
318
~ScFilterFloatingWindow()319 ScFilterFloatingWindow::~ScFilterFloatingWindow()
320 {
321 EndPopupMode();
322 }
323
GetPreferredKeyInputWindow()324 Window* ScFilterFloatingWindow::GetPreferredKeyInputWindow()
325 {
326 // redirect keyinput in the child window
327 return GetWindow(WINDOW_FIRSTCHILD) ? GetWindow(WINDOW_FIRSTCHILD)->GetPreferredKeyInputWindow() : NULL; // will be the FilterBox
328 }
329
330 // ============================================================================
331
lcl_IsEditableMatrix(ScDocument * pDoc,const ScRange & rRange)332 sal_Bool lcl_IsEditableMatrix( ScDocument* pDoc, const ScRange& rRange )
333 {
334 // Wenn es ein editierbarer Bereich ist, und rechts unten eine Matrix-Zelle
335 // mit Origin links oben liegt, enthält der Bereich genau die Matrix.
336 //! Direkt die MatrixEdges Funktionen von der Column herausreichen ???
337
338 if ( !pDoc->IsBlockEditable( rRange.aStart.Tab(), rRange.aStart.Col(),rRange.aStart.Row(),
339 rRange.aEnd.Col(),rRange.aEnd.Row() ) )
340 return sal_False;
341
342 ScAddress aPos;
343 const ScBaseCell* pCell = pDoc->GetCell( rRange.aEnd );
344 return ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA &&
345 ((ScFormulaCell*)pCell)->GetMatrixOrigin(aPos) && aPos == rRange.aStart );
346
347 }
348
lcl_UnLockComment(ScDrawView * pView,SdrPageView * pPV,SdrModel * pDrDoc,const Point & rPos,ScViewData * pViewData)349 void lcl_UnLockComment( ScDrawView* pView, SdrPageView* pPV, SdrModel* pDrDoc, const Point& rPos, ScViewData* pViewData )
350 {
351 if (!pView && !pPV && !pDrDoc && !pViewData)
352 return;
353
354 ScDocument& rDoc = *pViewData->GetDocument();
355 ScAddress aCellPos( pViewData->GetCurX(), pViewData->GetCurY(), pViewData->GetTabNo() );
356 ScPostIt* pNote = rDoc.GetNote( aCellPos );
357 SdrObject* pObj = pNote ? pNote->GetCaption() : 0;
358 if( pObj && pObj->GetLogicRect().IsInside( rPos ) && ScDrawLayer::IsNoteCaption( pObj ) )
359 {
360 const ScProtectionAttr* pProtAttr = static_cast< const ScProtectionAttr* > (rDoc.GetAttr( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab(), ATTR_PROTECTION ) );
361 bool bProtectAttr = pProtAttr->GetProtection() || pProtAttr->GetHideCell() ;
362 bool bProtectDoc = rDoc.IsTabProtected( aCellPos.Tab() ) || pViewData->GetSfxDocShell()->IsReadOnly() ;
363 // unlock internal layer (if not protected), will be relocked in ScDrawView::MarkListHasChanged()
364 pView->LockInternalLayer( bProtectDoc && bProtectAttr );
365 }
366 }
367
lcl_GetHyperlinkCell(ScDocument * pDoc,SCCOL & rPosX,SCROW & rPosY,SCTAB nTab,ScBaseCell * & rpCell)368 sal_Bool lcl_GetHyperlinkCell(ScDocument* pDoc, SCCOL& rPosX, SCROW& rPosY, SCTAB nTab, ScBaseCell*& rpCell )
369 {
370 sal_Bool bFound = sal_False;
371 do
372 {
373 pDoc->GetCell( rPosX, rPosY, nTab, rpCell );
374 if ( !rpCell || rpCell->GetCellType() == CELLTYPE_NOTE )
375 {
376 if ( rPosX <= 0 )
377 return sal_False; // alles leer bis links
378 else
379 --rPosX; // weitersuchen
380 }
381 else if ( rpCell->GetCellType() == CELLTYPE_EDIT)
382 bFound = sal_True;
383 else if (rpCell->GetCellType() == CELLTYPE_FORMULA &&
384 static_cast<ScFormulaCell*>(rpCell)->IsHyperLinkCell())
385 bFound = sal_True;
386 else
387 return sal_False; // andere Zelle
388 }
389 while ( !bFound );
390
391 return bFound;
392 }
393
394 // ---------------------------------------------------------------------------
395 // WB_DIALOGCONTROL nötig für UNO-Controls
ScGridWindow(Window * pParent,ScViewData * pData,ScSplitPos eWhichPos)396 ScGridWindow::ScGridWindow( Window* pParent, ScViewData* pData, ScSplitPos eWhichPos )
397 : Window( pParent, WB_CLIPCHILDREN | WB_DIALOGCONTROL ),
398 DropTargetHelper( this ),
399 DragSourceHelper( this ),
400 mpOOCursors( NULL ),
401 mpOOSelection( NULL ),
402 mpOOAutoFill( NULL ),
403 mpOODragRect( NULL ),
404 mpOOHeader( NULL ),
405 mpOOShrink( NULL ),
406 mpAutoFillRect(static_cast<Rectangle*>(NULL)),
407 pViewData( pData ),
408 eWhich( eWhichPos ),
409 pNoteMarker( NULL ),
410 pFilterBox( NULL ),
411 pFilterFloat( NULL ),
412 mpDPFieldPopup(NULL),
413 mpFilterButton(NULL),
414 nCursorHideCount( 0 ),
415 bMarking( sal_False ),
416 nButtonDown( 0 ),
417 bEEMouse( sal_False ),
418 nMouseStatus( SC_GM_NONE ),
419 nNestedButtonState( SC_NESTEDBUTTON_NONE ),
420 bDPMouse( sal_False ),
421 bRFMouse( sal_False ),
422 nPagebreakMouse( SC_PD_NONE ),
423 bPagebreakDrawn( sal_False ),
424 nPageScript( 0 ),
425 bDragRect( sal_False ),
426 meDragInsertMode( INS_NONE ),
427 nCurrentPointer( 0 ),
428 bIsInScroll( sal_False ),
429 bIsInPaint( sal_False ),
430 aComboButton( this ),
431 aCurMousePos( 0,0 ),
432 nPaintCount( 0 ),
433 bNeedsRepaint( sal_False ),
434 bAutoMarkVisible( sal_False ),
435 bListValButton( sal_False )
436 {
437 switch(eWhich)
438 {
439 case SC_SPLIT_TOPLEFT:
440 eHWhich = SC_SPLIT_LEFT;
441 eVWhich = SC_SPLIT_TOP;
442 break;
443 case SC_SPLIT_TOPRIGHT:
444 eHWhich = SC_SPLIT_RIGHT;
445 eVWhich = SC_SPLIT_TOP;
446 break;
447 case SC_SPLIT_BOTTOMLEFT:
448 eHWhich = SC_SPLIT_LEFT;
449 eVWhich = SC_SPLIT_BOTTOM;
450 break;
451 case SC_SPLIT_BOTTOMRIGHT:
452 eHWhich = SC_SPLIT_RIGHT;
453 eVWhich = SC_SPLIT_BOTTOM;
454 break;
455 default:
456 DBG_ERROR("GridWindow: wrong position");
457 }
458
459 SetBackground();
460
461 SetMapMode(pViewData->GetLogicMode(eWhich));
462 // EnableDrop();
463 EnableChildTransparentMode();
464 SetDialogControlFlags( WINDOW_DLGCTRL_RETURN | WINDOW_DLGCTRL_WANTFOCUS );
465
466 SetHelpId( HID_SC_WIN_GRIDWIN );
467 SetUniqueId( HID_SC_WIN_GRIDWIN );
468
469 SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
470 EnableRTL( sal_False );
471 }
472
~ScGridWindow()473 __EXPORT ScGridWindow::~ScGridWindow()
474 {
475 // #114409#
476 ImpDestroyOverlayObjects();
477
478 delete pFilterBox;
479 delete pFilterFloat;
480 delete pNoteMarker;
481 }
482
Resize(const Size &)483 void __EXPORT ScGridWindow::Resize( const Size& )
484 {
485 // gar nix
486 }
487
ClickExtern()488 void ScGridWindow::ClickExtern()
489 {
490 do
491 {
492 // #i81298# don't delete the filter box when called from its select handler
493 // (possible through row header size update)
494 // #i84277# when initializing the filter box, a Basic error can deactivate the view
495 if ( pFilterBox && ( pFilterBox->IsInSelect() || pFilterBox->IsInInit() ) )
496 {
497 break;
498 }
499
500 DELETEZ(pFilterBox);
501 DELETEZ(pFilterFloat);
502 }
503 while (false);
504
505 if (mpDPFieldPopup.get())
506 {
507 mpDPFieldPopup->close(false);
508 mpDPFieldPopup.reset();
509 }
510 }
511
IMPL_LINK(ScGridWindow,PopupModeEndHdl,FloatingWindow *,EMPTYARG)512 IMPL_LINK( ScGridWindow, PopupModeEndHdl, FloatingWindow*, EMPTYARG )
513 {
514 if (pFilterBox)
515 pFilterBox->SetCancelled(); // nicht mehr auswählen
516 GrabFocus();
517 return 0;
518 }
519
IMPL_LINK(ScGridWindow,PopupSpellingHdl,SpellCallbackInfo *,pInfo)520 IMPL_LINK( ScGridWindow, PopupSpellingHdl, SpellCallbackInfo*, pInfo )
521 {
522 if( pInfo->nCommand == SPELLCMD_STARTSPELLDLG )
523 pViewData->GetDispatcher().Execute( SID_SPELL_DIALOG, SFX_CALLMODE_ASYNCHRON );
524 return 0;
525 }
526
ExecPageFieldSelect(SCCOL nCol,SCROW nRow,sal_Bool bHasSelection,const String & rStr)527 void ScGridWindow::ExecPageFieldSelect( SCCOL nCol, SCROW nRow, sal_Bool bHasSelection, const String& rStr )
528 {
529 //! gridwin2 ?
530
531 ScDocument* pDoc = pViewData->GetDocument();
532 SCTAB nTab = pViewData->GetTabNo();
533 ScDPObject* pDPObj = pDoc->GetDPAtCursor(nCol, nRow, nTab);
534 if ( pDPObj && nCol > 0 )
535 {
536 // look for the dimension header left of the drop-down arrow
537 sal_uInt16 nOrient = sheet::DataPilotFieldOrientation_HIDDEN;
538 long nField = pDPObj->GetHeaderDim( ScAddress( nCol-1, nRow, nTab ), nOrient );
539 if ( nField >= 0 && nOrient == sheet::DataPilotFieldOrientation_PAGE )
540 {
541 ScDPSaveData aSaveData( *pDPObj->GetSaveData() );
542
543 sal_Bool bIsDataLayout;
544 String aDimName = pDPObj->GetDimName( nField, bIsDataLayout );
545 if ( !bIsDataLayout )
546 {
547 ScDPSaveDimension* pDim = aSaveData.GetDimensionByName(aDimName);
548
549 if ( bHasSelection )
550 pDim->SetCurrentPage( &rStr );
551 else
552 pDim->SetCurrentPage( NULL );
553
554 ScDPObject aNewObj( *pDPObj );
555 aNewObj.SetSaveData( aSaveData );
556 ScDBDocFunc aFunc( *pViewData->GetDocShell() );
557 aFunc.DataPilotUpdate( pDPObj, &aNewObj, sal_True, sal_False );
558 pViewData->GetView()->CursorPosChanged(); // shells may be switched
559 }
560 }
561 }
562 }
563
LaunchPageFieldMenu(SCCOL nCol,SCROW nRow)564 void ScGridWindow::LaunchPageFieldMenu( SCCOL nCol, SCROW nRow )
565 {
566 //! merge position/size handling with DoAutoFilterMenue
567
568 delete pFilterBox;
569 delete pFilterFloat;
570
571 sal_uInt16 i;
572 ScDocument* pDoc = pViewData->GetDocument();
573 SCTAB nTab = pViewData->GetTabNo();
574 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
575
576 long nSizeX = 0;
577 long nSizeY = 0;
578 long nHeight = 0;
579 pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
580 Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich );
581 if ( bLayoutRTL )
582 aPos.X() -= nSizeX;
583
584 Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) );
585
586 aPos.X() -= 1;
587 aPos.Y() += nSizeY - 1;
588
589 pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) ); // not resizable etc.
590 pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) );
591 pFilterBox = new ScFilterListBox( pFilterFloat, this, nCol, nRow, SC_FILTERBOX_PAGEFIELD );
592 if ( bLayoutRTL )
593 pFilterBox->EnableMirroring();
594
595 nSizeX += 1;
596
597 {
598 Font aOldFont = GetFont(); SetFont( pFilterBox->GetFont() );
599 MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL );
600
601 nHeight = GetTextHeight();
602 nHeight *= SC_FILTERLISTBOX_LINES;
603
604 SetMapMode( aOldMode );
605 SetFont( aOldFont );
606 }
607
608 // SetSize comes later
609
610 TypedScStrCollection aStrings( 128, 128 );
611
612 // get list box entries and selection
613 sal_Bool bHasCurrentPage = sal_False;
614 String aCurrentPage;
615 ScDPObject* pDPObj = pDoc->GetDPAtCursor(nCol, nRow, nTab);
616 if ( pDPObj && nCol > 0 )
617 {
618 // look for the dimension header left of the drop-down arrow
619 sal_uInt16 nOrient = sheet::DataPilotFieldOrientation_HIDDEN;
620 long nField = pDPObj->GetHeaderDim( ScAddress( nCol-1, nRow, nTab ), nOrient );
621 if ( nField >= 0 && nOrient == sheet::DataPilotFieldOrientation_PAGE )
622 {
623 pDPObj->FillPageList( aStrings, nField );
624
625 // get current page from SaveData
626
627 ScDPSaveData* pSaveData = pDPObj->GetSaveData();
628 sal_Bool bIsDataLayout;
629 String aDimName = pDPObj->GetDimName( nField, bIsDataLayout );
630 if ( pSaveData && !bIsDataLayout )
631 {
632 ScDPSaveDimension* pDim = pSaveData->GetExistingDimensionByName(aDimName);
633 if ( pDim && pDim->HasCurrentPage() )
634 {
635 aCurrentPage = pDim->GetCurrentPage();
636 bHasCurrentPage = sal_True;
637 }
638 }
639 }
640 }
641
642 // include all entry widths for the size of the drop-down
643 long nMaxText = 0;
644 sal_uInt16 nCount = aStrings.GetCount();
645 for (i=0; i<nCount; i++)
646 {
647 TypedStrData* pData = aStrings[i];
648 long nTextWidth = pFilterBox->GetTextWidth( pData->GetString() );
649 if ( nTextWidth > nMaxText )
650 nMaxText = nTextWidth;
651 }
652
653 // add scrollbar width if needed (string entries are counted here)
654 // (scrollbar is shown if the box is exactly full?)
655 if ( nCount >= SC_FILTERLISTBOX_LINES )
656 nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize();
657
658 nMaxText += 4; // for borders
659
660 if ( nMaxText > nSizeX )
661 nSizeX = nMaxText; // just modify width - starting position is unchanged
662
663 // adjust position and size to window
664
665 Size aParentSize = GetParent()->GetOutputSizePixel();
666 Size aSize( nSizeX, nHeight );
667
668 if ( aSize.Height() > aParentSize.Height() )
669 aSize.Height() = aParentSize.Height();
670 if ( aPos.Y() + aSize.Height() > aParentSize.Height() )
671 aPos.Y() = aParentSize.Height() - aSize.Height();
672
673 pFilterBox->SetSizePixel( aSize );
674 pFilterBox->Show(); // Show must be called before SetUpdateMode
675 pFilterBox->SetUpdateMode(sal_False);
676
677 pFilterFloat->SetOutputSizePixel( aSize );
678 pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS);
679
680 // fill the list box
681 sal_Bool bWait = ( nCount > 100 );
682
683 if (bWait)
684 EnterWait();
685
686 for (i=0; i<nCount; i++)
687 pFilterBox->InsertEntry( aStrings[i]->GetString() );
688
689 pFilterBox->SetSeparatorPos( 0 );
690
691 if (bWait)
692 LeaveWait();
693
694 pFilterBox->SetUpdateMode(sal_True);
695
696 sal_uInt16 nSelPos = LISTBOX_ENTRY_NOTFOUND;
697 if (bHasCurrentPage)
698 nSelPos = pFilterBox->GetEntryPos( aCurrentPage );
699
700 if ( nSelPos == LISTBOX_ENTRY_NOTFOUND )
701 nSelPos = 0; // first entry
702
703 pFilterBox->GrabFocus();
704
705 // call Select after GrabFocus, so the focus rectangle ends up in the right position
706 if ( nSelPos != LISTBOX_ENTRY_NOTFOUND )
707 pFilterBox->SelectEntryPos( nSelPos );
708
709 pFilterBox->EndInit();
710
711 nMouseStatus = SC_GM_FILTER;
712 CaptureMouse();
713 }
714
LaunchDPFieldMenu(SCCOL nCol,SCROW nRow)715 void ScGridWindow::LaunchDPFieldMenu( SCCOL nCol, SCROW nRow )
716 {
717 SCTAB nTab = pViewData->GetTabNo();
718 ScDPObject* pDPObj = pViewData->GetDocument()->GetDPAtCursor(nCol, nRow, nTab);
719 if (!pDPObj)
720 return;
721
722 // Get the geometry of the cell.
723 Point aScrPos = pViewData->GetScrPos(nCol, nRow, eWhich);
724 long nSizeX, nSizeY;
725 pViewData->GetMergeSizePixel(nCol, nRow, nSizeX, nSizeY);
726 Size aScrSize(nSizeX-1, nSizeY-1);
727
728 DPLaunchFieldPopupMenu(OutputToScreenPixel(aScrPos), aScrSize, ScAddress(nCol, nRow, nTab), pDPObj);
729 }
730
DoScenarioMenue(const ScRange & rScenRange)731 void ScGridWindow::DoScenarioMenue( const ScRange& rScenRange )
732 {
733 delete pFilterBox;
734 delete pFilterFloat;
735
736 SCCOL nCol = rScenRange.aEnd.Col(); // Zelle unterhalb des Buttons
737 SCROW nRow = rScenRange.aStart.Row();
738 if (nRow == 0)
739 {
740 nRow = rScenRange.aEnd.Row() + 1; // Bereich ganz oben -> Button unterhalb
741 if (nRow>MAXROW) nRow = MAXROW;
742 //! Texthöhe addieren (wenn sie an der View gespeichert ist...)
743 }
744
745 ScDocument* pDoc = pViewData->GetDocument();
746 SCTAB nTab = pViewData->GetTabNo();
747 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
748
749 long nSizeX = 0;
750 long nSizeY = 0;
751 long nHeight = 0;
752 pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
753 Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich );
754 if ( bLayoutRTL )
755 aPos.X() -= nSizeX;
756 Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) );
757 aCellRect.Top() -= nSizeY;
758 aCellRect.Bottom() -= nSizeY - 1;
759 // Die ListBox direkt unter der schwarzen Linie auf dem Zellgitter
760 // (wenn die Linie verdeckt wird, sieht es komisch aus...)
761
762 pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) ); // nicht resizable etc.
763 pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) );
764 pFilterBox = new ScFilterListBox( pFilterFloat, this, nCol, nRow, SC_FILTERBOX_SCENARIO );
765 if ( bLayoutRTL )
766 pFilterBox->EnableMirroring();
767
768 nSizeX += 1;
769
770 {
771 Font aOldFont = GetFont(); SetFont( pFilterBox->GetFont() );
772 MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL );
773
774 nHeight = GetTextHeight();
775 nHeight *= SC_FILTERLISTBOX_LINES;
776
777 SetMapMode( aOldMode );
778 SetFont( aOldFont );
779 }
780
781 // SetSize später
782 /*
783 pFilterBox->SetSelectionMode( SINGLE_SELECTION );
784 pFilterBox->SetTabs( nFilterBoxTabs, MapUnit( MAP_APPFONT ));
785 pFilterBox->SetTabJustify( 1, bLayoutRTL ? AdjustRight : AdjustLeft );
786 */
787
788 // ParentSize Abfrage fehlt
789 Size aSize( nSizeX, nHeight );
790 pFilterBox->SetSizePixel( aSize );
791 pFilterBox->Show(); // Show muss vor SetUpdateMode kommen !!!
792 pFilterBox->SetUpdateMode(sal_False);
793
794 // SetOutputSizePixel/StartPopupMode erst unten, wenn die Größe feststeht
795
796 // Listbox füllen
797
798 long nMaxText = 0;
799 String aCurrent;
800 String aTabName;
801 SCTAB nTabCount = pDoc->GetTableCount();
802 SCTAB nEntryCount = 0;
803 for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
804 {
805 if (pDoc->HasScenarioRange( i, rScenRange ))
806 if (pDoc->GetName( i, aTabName ))
807 {
808 pFilterBox->InsertEntry( aTabName );
809 if (pDoc->IsActiveScenario(i))
810 aCurrent = aTabName;
811 long nTextWidth = pFilterBox->GetTextWidth( aTabName );
812 if ( nTextWidth > nMaxText )
813 nMaxText = nTextWidth;
814 ++nEntryCount;
815 }
816 }
817 if (nEntryCount > SC_FILTERLISTBOX_LINES)
818 nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize();
819 nMaxText += 4; // für Rand
820 if ( nMaxText > 300 )
821 nMaxText = 300; // auch nicht uebertreiben (Pixel)
822
823 if (nMaxText > nSizeX) // Größe auf benötigte Größe anpassen
824 {
825 long nDiff = nMaxText - nSizeX;
826 aSize = Size( nMaxText, nHeight );
827 pFilterBox->SetSizePixel( aSize );
828 pFilterFloat->SetOutputSizePixel( aSize );
829
830 if ( !bLayoutRTL )
831 {
832 // also move popup position
833 long nNewX = aCellRect.Left() - nDiff;
834 if ( nNewX < 0 )
835 nNewX = 0;
836 aCellRect.Left() = nNewX;
837 }
838 }
839
840 pFilterFloat->SetOutputSizePixel( aSize );
841 pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS );
842
843 pFilterBox->SetUpdateMode(sal_True);
844 pFilterBox->GrabFocus();
845
846 // Select erst nach GrabFocus, damit das Focus-Rechteck richtig landet
847 //! SvLBoxEntry* pSelect = NULL;
848 sal_uInt16 nPos = LISTBOX_ENTRY_NOTFOUND;
849 if (aCurrent.Len())
850 {
851 nPos = pFilterBox->GetEntryPos( aCurrent );
852 //! pSelect = pFilterBox->GetEntry( nPos );
853 }
854 if (/*!pSelect*/ LISTBOX_ENTRY_NOTFOUND == nPos && pFilterBox->GetEntryCount() > 0 )
855 nPos = 0;
856 //! pSelect = pFilterBox->GetEntry(0); // einer sollte immer selektiert sein
857 if (/*pSelect*/ LISTBOX_ENTRY_NOTFOUND != nPos )
858 pFilterBox->SelectEntryPos(nPos);
859
860 pFilterBox->EndInit();
861
862 // Szenario-Auswahl kommt aus MouseButtonDown:
863 // der nächste MouseMove auf die Filterbox ist wie ein ButtonDown
864
865 nMouseStatus = SC_GM_FILTER;
866 CaptureMouse();
867 }
868
HasScenarioRange(sal_uInt16 nCol,sal_Int32 nRow,ScRange & rScenRange)869 sal_Bool ScGridWindow::HasScenarioRange( sal_uInt16 nCol, sal_Int32 nRow, ScRange& rScenRange )
870 {
871 ScDocument* pDoc = pViewData->GetDocument();
872 sal_uInt16 nTab = pViewData->GetTabNo();
873 sal_uInt16 nTabCount = pDoc->GetTableCount();
874 if ( nTab+1<nTabCount && pDoc->IsScenario(nTab+1) && !pDoc->IsScenario(nTab) )
875 {
876 sal_uInt16 i;
877 ScMarkData aMarks;
878 for (i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
879 pDoc->MarkScenario( i, nTab, aMarks, sal_False, SC_SCENARIO_SHOWFRAME );
880 ScRangeList aRanges;
881 aMarks.FillRangeListWithMarks( &aRanges, sal_False );
882 sal_uInt16 nRangeCount = (sal_uInt16)aRanges.Count();
883 for (i=0; i<nRangeCount; i++)
884 {
885 ScRange aRange = *aRanges.GetObject(i);
886 pDoc->ExtendTotalMerge( aRange );
887 sal_Bool bTextBelow = ( aRange.aStart.Row() == 0 );
888 sal_Bool bIsInScen = sal_False;
889 if ( bTextBelow )
890 {
891 bIsInScen = (aRange.aStart.Col() == nCol && aRange.aEnd.Row() == nRow-1);
892 }
893 else
894 {
895 bIsInScen = (aRange.aStart.Col() == nCol && aRange.aStart.Row() == nRow+1);
896 }
897 if (bIsInScen)
898 {
899 rScenRange = aRange;
900 return sal_True;
901 }
902 }
903 }
904 return sal_False;
905 }
DoAutoFilterMenue(SCCOL nCol,SCROW nRow,sal_Bool bDataSelect)906 void ScGridWindow::DoAutoFilterMenue( SCCOL nCol, SCROW nRow, sal_Bool bDataSelect )
907 {
908 delete pFilterBox;
909 delete pFilterFloat;
910
911 sal_uInt16 i;
912 ScDocument* pDoc = pViewData->GetDocument();
913 SCTAB nTab = pViewData->GetTabNo();
914 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
915
916 long nSizeX = 0;
917 long nSizeY = 0;
918 long nHeight = 0;
919 pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
920 // The button height should not use the merged cell height, should still use single row height
921 nSizeY = pViewData->ToPixel(pDoc->GetRowHeight(nRow, nTab), pViewData->GetPPTY());
922 Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich );
923 if ( bLayoutRTL )
924 aPos.X() -= nSizeX;
925
926 Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) );
927
928 aPos.X() -= 1;
929 aPos.Y() += nSizeY - 1;
930
931 pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) ); // nicht resizable etc.
932 pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) );
933 pFilterBox = new ScFilterListBox(
934 pFilterFloat, this, nCol, nRow, bDataSelect ? SC_FILTERBOX_DATASELECT : SC_FILTERBOX_FILTER );
935 if ( bLayoutRTL )
936 pFilterBox->EnableMirroring();
937
938 nSizeX += 1;
939
940 {
941 Font aOldFont = GetFont(); SetFont( pFilterBox->GetFont() );
942 MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL );
943
944 nHeight = GetTextHeight();
945 nHeight *= SC_FILTERLISTBOX_LINES;
946
947 SetMapMode( aOldMode );
948 SetFont( aOldFont );
949 }
950
951 // SetSize später
952 /*
953 pFilterBox->SetSelectionMode( SINGLE_SELECTION );
954 pFilterBox->SetTabs( nFilterBoxTabs, MapUnit( MAP_APPFONT ));
955 pFilterBox->SetTabJustify( 1, bLayoutRTL ? AdjustRight : AdjustLeft );
956 */
957
958 sal_Bool bEmpty = sal_False;
959 TypedScStrCollection aStrings( 128, 128 );
960 if ( bDataSelect ) // Auswahl-Liste
961 {
962 // Liste fuellen
963 aStrings.SetCaseSensitive( sal_True );
964 pDoc->GetDataEntries( nCol, nRow, nTab, aStrings );
965 if ( aStrings.GetCount() == 0 )
966 bEmpty = sal_True;
967 }
968 else // AutoFilter
969 {
970 //! wird der Titel ueberhaupt ausgewertet ???
971 String aString;
972 pDoc->GetString( nCol, nRow, nTab, aString );
973 pFilterBox->SetText( aString );
974
975 long nMaxText = 0;
976
977 // default entries
978 static const sal_uInt16 nDefIDs[] = { SCSTR_ALLFILTER, SCSTR_TOP10FILTER, SCSTR_STDFILTER, SCSTR_EMPTY, SCSTR_NOTEMPTY };
979 const sal_uInt16 nDefCount = sizeof(nDefIDs) / sizeof(sal_uInt16);
980 for (i=0; i<nDefCount; i++)
981 {
982 String aEntry( (ScResId) nDefIDs[i] );
983 pFilterBox->InsertEntry( aEntry );
984 long nTextWidth = pFilterBox->GetTextWidth( aEntry );
985 if ( nTextWidth > nMaxText )
986 nMaxText = nTextWidth;
987 }
988 pFilterBox->SetSeparatorPos( nDefCount - 1 );
989
990 // get list entries
991 bool bHasDates = false;
992 pDoc->GetFilterEntries( nCol, nRow, nTab, true, aStrings, bHasDates);
993 pFilterBox->SetListHasDates(bHasDates);
994
995 // check widths of numerical entries (string entries are not included)
996 // so all numbers are completely visible
997 sal_uInt16 nCount = aStrings.GetCount();
998 for (i=0; i<nCount; i++)
999 {
1000 TypedStrData* pData = aStrings[i];
1001 if ( !pData->IsStrData() ) // only numerical entries
1002 {
1003 long nTextWidth = pFilterBox->GetTextWidth( pData->GetString() );
1004 if ( nTextWidth > nMaxText )
1005 nMaxText = nTextWidth;
1006 }
1007 }
1008
1009 // add scrollbar width if needed (string entries are counted here)
1010 // (scrollbar is shown if the box is exactly full?)
1011 if ( nCount + nDefCount >= SC_FILTERLISTBOX_LINES )
1012 nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize();
1013
1014 nMaxText += 4; // for borders
1015
1016 if ( nMaxText > nSizeX )
1017 nSizeX = nMaxText; // just modify width - starting position is unchanged
1018 }
1019
1020 if (!bEmpty)
1021 {
1022 // Position und Größe an Fenster anpassen
1023 //! vorher Abfrage, ob die Einträge hineinpassen (Breite)
1024
1025 Size aParentSize = GetParent()->GetOutputSizePixel();
1026 Size aSize( nSizeX, nHeight );
1027
1028 if ( aSize.Height() > aParentSize.Height() )
1029 aSize.Height() = aParentSize.Height();
1030 if ( aPos.Y() + aSize.Height() > aParentSize.Height() )
1031 aPos.Y() = aParentSize.Height() - aSize.Height();
1032
1033 pFilterBox->SetSizePixel( aSize );
1034 pFilterBox->Show(); // Show muss vor SetUpdateMode kommen !!!
1035 pFilterBox->SetUpdateMode(sal_False);
1036
1037 pFilterFloat->SetOutputSizePixel( aSize );
1038 pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS);
1039
1040 // Listbox fuellen
1041 sal_uInt16 nCount = aStrings.GetCount();
1042 sal_Bool bWait = ( nCount > 100 );
1043
1044 if (bWait)
1045 EnterWait();
1046
1047 for (i=0; i<nCount; i++)
1048 pFilterBox->InsertEntry( aStrings[i]->GetString() );
1049
1050 if (bWait)
1051 LeaveWait();
1052
1053 pFilterBox->SetUpdateMode(sal_True);
1054 }
1055
1056 //! SvLBoxEntry* pSelect = NULL;
1057 sal_uInt16 nSelPos = LISTBOX_ENTRY_NOTFOUND;
1058
1059 if (!bDataSelect) // AutoFilter: aktiven Eintrag selektieren
1060 {
1061 ScDBData* pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab );
1062 if (pDBData)
1063 {
1064 ScQueryParam aParam;
1065 pDBData->GetQueryParam( aParam ); // kann nur MAXQUERY Einträge ergeben
1066
1067 sal_Bool bValid = sal_True;
1068 for (SCSIZE j=0; j<MAXQUERY && bValid; j++) // bisherige Filter-Einstellungen
1069 if (aParam.GetEntry(j).bDoQuery)
1070 {
1071 //! Abfrage mit DrawButtons zusammenfassen!
1072
1073 ScQueryEntry& rEntry = aParam.GetEntry(j);
1074 if (j>0)
1075 if (rEntry.eConnect != SC_AND)
1076 bValid = sal_False;
1077 if (rEntry.nField == nCol)
1078 {
1079 if (rEntry.eOp == SC_EQUAL)
1080 {
1081 String* pStr = rEntry.pStr;
1082 if (pStr)
1083 {
1084 nSelPos = pFilterBox->GetEntryPos( *pStr );
1085 //! pSelect = pFilterBox->GetEntry( nPos );
1086 }
1087 }
1088 else if (rEntry.eOp == SC_TOPVAL && rEntry.pStr &&
1089 rEntry.pStr->EqualsAscii("10"))
1090 nSelPos = SC_AUTOFILTER_TOP10;
1091 else
1092 nSelPos = SC_AUTOFILTER_CUSTOM;
1093 }
1094 }
1095
1096 if (!bValid)
1097 nSelPos = SC_AUTOFILTER_CUSTOM;
1098 }
1099 }
1100 else
1101 {
1102
1103 sal_uLong nIndex = ((SfxUInt32Item*)pDoc->GetAttr(
1104 nCol, nRow, nTab, ATTR_VALIDDATA ))->GetValue();
1105 if ( nIndex )
1106 {
1107 const ScValidationData* pData = pDoc->GetValidationEntry( nIndex );
1108 if (pData)
1109 {
1110 TypedStrData* pNew = NULL;
1111 String aDocStr;
1112 pDoc->GetString( nCol, nRow, nTab, aDocStr );
1113 if ( pDoc->HasValueData( nCol, nRow, nTab ) )
1114 {
1115 double fVal = pDoc->GetValue(ScAddress(nCol, nRow, nTab));
1116 pNew = new TypedStrData( aDocStr, fVal, SC_STRTYPE_VALUE );
1117 }
1118 else
1119 pNew = new TypedStrData( aDocStr, 0.0, SC_STRTYPE_STANDARD );
1120
1121 bool bSortList = ( pData->GetListType() == ValidListType::SORTEDASCENDING);
1122 if ( bSortList )
1123 {
1124 sal_uInt16 nStrIndex;
1125 if (aStrings.Search(pNew,nStrIndex))
1126 nSelPos = nStrIndex;
1127 }
1128 else
1129 {
1130 sal_uInt16 nCount = aStrings.GetCount();
1131 for (i = 0; ((i < nCount) && ( LISTBOX_ENTRY_NOTFOUND == nSelPos)); i++)
1132 {
1133 if ( aStrings.Compare(aStrings[i], pNew)==0 )
1134 nSelPos = i;
1135 }
1136 }
1137 delete pNew;
1138 }
1139 }
1140 }
1141
1142 // neu (309): irgendwas muss immer selektiert sein:
1143 if ( LISTBOX_ENTRY_NOTFOUND == nSelPos && pFilterBox->GetEntryCount() > 0 && !bDataSelect)
1144 nSelPos = 0;
1145
1146 // keine leere Auswahl-Liste anzeigen:
1147
1148 if ( bEmpty )
1149 {
1150 DELETEZ(pFilterBox); // war nix
1151 DELETEZ(pFilterFloat);
1152 Sound::Beep(); // bemerkbar machen
1153 }
1154 else
1155 {
1156 // pFilterBox->Show(); // schon vorne
1157 pFilterBox->GrabFocus();
1158
1159 // Select erst nach GrabFocus, damit das Focus-Rechteck richtig landet
1160 if ( LISTBOX_ENTRY_NOTFOUND != nSelPos )
1161 pFilterBox->SelectEntryPos( nSelPos );
1162 else
1163 {
1164 if (bDataSelect)
1165 pFilterBox->SetNoSelection();
1166 }
1167
1168 pFilterBox->EndInit();
1169
1170 if (!bDataSelect)
1171 {
1172 // AutoFilter (aus MouseButtonDown):
1173 // der nächste MouseMove auf die Filterbox ist wie ein ButtonDown
1174
1175 nMouseStatus = SC_GM_FILTER;
1176 CaptureMouse();
1177 }
1178 }
1179 }
1180
FilterSelect(sal_uLong nSel)1181 void ScGridWindow::FilterSelect( sal_uLong nSel )
1182 {
1183 String aString;
1184 /*
1185 SvLBoxEntry* pEntry = pFilterBox->GetEntry( nSel );
1186 if (pEntry)
1187 {
1188 SvLBoxString* pStringEntry = (SvLBoxString*) pEntry->GetFirstItem( SV_ITEM_ID_LBOXSTRING );
1189 if ( pStringEntry )
1190 aString = pStringEntry->GetText();
1191 }
1192 */
1193 aString = pFilterBox->GetEntry( static_cast< sal_uInt16 >( nSel ) );
1194
1195 SCCOL nCol = pFilterBox->GetCol();
1196 SCROW nRow = pFilterBox->GetRow();
1197 switch ( pFilterBox->GetMode() )
1198 {
1199 case SC_FILTERBOX_DATASELECT:
1200 ExecDataSelect( nCol, nRow, aString );
1201 break;
1202 case SC_FILTERBOX_FILTER:
1203 ExecFilter( nSel, nCol, nRow, aString, pFilterBox->HasDates() );
1204 break;
1205 case SC_FILTERBOX_SCENARIO:
1206 pViewData->GetView()->UseScenario( aString );
1207 break;
1208 case SC_FILTERBOX_PAGEFIELD:
1209 // first entry is "all"
1210 ExecPageFieldSelect( nCol, nRow, (nSel != 0), aString );
1211 break;
1212 }
1213
1214 if (pFilterFloat)
1215 pFilterFloat->EndPopupMode();
1216
1217 GrabFocus(); // unter OS/2 stimmt der Focus sonst nicht
1218 }
1219
ExecDataSelect(SCCOL nCol,SCROW nRow,const String & rStr)1220 void ScGridWindow::ExecDataSelect( SCCOL nCol, SCROW nRow, const String& rStr )
1221 {
1222 if ( rStr.Len() )
1223 {
1224 SCTAB nTab = pViewData->GetTabNo();
1225 ScViewFunc* pView = pViewData->GetView();
1226 pView->EnterData( nCol, nRow, nTab, rStr );
1227
1228 // #i52307# CellContentChanged is not in EnterData so it isn't called twice
1229 // if the cursor is moved afterwards.
1230 pView->CellContentChanged();
1231 }
1232 }
1233
ExecFilter(sal_uLong nSel,SCCOL nCol,SCROW nRow,const String & aValue,bool bCheckForDates)1234 void ScGridWindow::ExecFilter( sal_uLong nSel,
1235 SCCOL nCol, SCROW nRow,
1236 const String& aValue, bool bCheckForDates )
1237 {
1238 SCTAB nTab = pViewData->GetTabNo();
1239 ScDocument* pDoc = pViewData->GetDocument();
1240
1241 ScDBData* pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab );
1242 if (pDBData)
1243 {
1244 ScQueryParam aParam;
1245 pDBData->GetQueryParam( aParam ); // kann nur MAXQUERY Einträge ergeben
1246
1247 if (SC_AUTOFILTER_CUSTOM == nSel)
1248 {
1249 SCTAB nAreaTab;
1250 SCCOL nStartCol;
1251 SCROW nStartRow;
1252 SCCOL nEndCol;
1253 SCROW nEndRow;
1254 pDBData->GetArea( nAreaTab, nStartCol,nStartRow,nEndCol,nEndRow );
1255 pViewData->GetView()->MarkRange( ScRange( nStartCol,nStartRow,nAreaTab,nEndCol,nEndRow,nAreaTab));
1256 pViewData->GetView()->SetCursor(nCol,nRow); //! auch ueber Slot ??
1257 pViewData->GetDispatcher().Execute( SID_FILTER, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD );
1258 }
1259 else
1260 {
1261 sal_Bool bDeleteOld = sal_False;
1262 SCSIZE nQueryPos = 0;
1263 sal_Bool bFound = sal_False;
1264 if (!aParam.bInplace)
1265 bDeleteOld = sal_True;
1266 if (aParam.bRegExp)
1267 bDeleteOld = sal_True;
1268 for (SCSIZE i=0; i<MAXQUERY && !bDeleteOld; i++) // bisherige Filter-Einstellungen
1269 if (aParam.GetEntry(i).bDoQuery)
1270 {
1271 //! Abfrage mit DrawButtons zusammenfassen!
1272
1273 ScQueryEntry& rEntry = aParam.GetEntry(i);
1274 if (i>0)
1275 if (rEntry.eConnect != SC_AND)
1276 bDeleteOld = sal_True;
1277
1278 if (rEntry.nField == nCol)
1279 {
1280 if (bFound) // diese Spalte zweimal?
1281 bDeleteOld = sal_True;
1282 nQueryPos = i;
1283 bFound = sal_True;
1284 }
1285 if (!bFound)
1286 nQueryPos = i + 1;
1287 }
1288
1289 if (bDeleteOld)
1290 {
1291 SCSIZE nEC = aParam.GetEntryCount();
1292 for (SCSIZE i=0; i<nEC; i++)
1293 aParam.GetEntry(i).Clear();
1294 nQueryPos = 0;
1295 aParam.bInplace = sal_True;
1296 aParam.bRegExp = sal_False;
1297 }
1298
1299 if ( nQueryPos < MAXQUERY || SC_AUTOFILTER_ALL == nSel ) // löschen geht immer
1300 {
1301 if (nSel)
1302 {
1303 ScQueryEntry& rNewEntry = aParam.GetEntry(nQueryPos);
1304
1305 rNewEntry.bDoQuery = sal_True;
1306 rNewEntry.bQueryByString = sal_True;
1307 rNewEntry.nField = nCol;
1308 rNewEntry.bQueryByDate = bCheckForDates;
1309 if ( nSel == SC_AUTOFILTER_TOP10 )
1310 {
1311 rNewEntry.eOp = SC_TOPVAL;
1312 *rNewEntry.pStr = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("10"));
1313 }
1314 else if ( nSel == SC_AUTOFILTER_EMPTY) {
1315 rNewEntry.pStr->Erase();
1316 rNewEntry.bQueryByString = sal_False;
1317 rNewEntry.eOp = SC_EQUAL;
1318 rNewEntry.nVal = SC_EMPTYFIELDS;
1319 }
1320 else if (nSel == SC_AUTOFILTER_NOTEMPTY)
1321 {
1322 rNewEntry.pStr->Erase();
1323 rNewEntry.bQueryByString = sal_False;
1324 rNewEntry.eOp = SC_EQUAL;
1325 rNewEntry.nVal = SC_NONEMPTYFIELDS;
1326 }
1327 else
1328 {
1329 rNewEntry.eOp = SC_EQUAL;
1330 *rNewEntry.pStr = aValue;
1331 }
1332 if (nQueryPos > 0)
1333 rNewEntry.eConnect = SC_AND;
1334 }
1335 else
1336 {
1337 if (bFound)
1338 aParam.DeleteQuery(nQueryPos);
1339 }
1340
1341 // #100597# end edit mode - like in ScCellShell::ExecuteDB
1342 if ( pViewData->HasEditView( pViewData->GetActivePart() ) )
1343 {
1344 SC_MOD()->InputEnterHandler();
1345 pViewData->GetViewShell()->UpdateInputHandler();
1346 }
1347
1348 pViewData->GetView()->Query( aParam, NULL, sal_True );
1349 pDBData->SetQueryParam( aParam ); // speichern
1350 }
1351 else // "Zuviele Bedingungen"
1352 pViewData->GetView()->ErrorMessage( STR_FILTER_TOOMANY );
1353 }
1354 }
1355 else
1356 {
1357 DBG_ERROR("Wo ist der Datenbankbereich?");
1358 }
1359 }
1360
SetPointer(const Pointer & rPointer)1361 void ScGridWindow::SetPointer( const Pointer& rPointer )
1362 {
1363 nCurrentPointer = 0;
1364 Window::SetPointer( rPointer );
1365 }
1366
MoveMouseStatus(ScGridWindow & rDestWin)1367 void ScGridWindow::MoveMouseStatus( ScGridWindow& rDestWin )
1368 {
1369 if (nButtonDown)
1370 {
1371 rDestWin.nButtonDown = nButtonDown;
1372 rDestWin.nMouseStatus = nMouseStatus;
1373 }
1374
1375 if (bRFMouse)
1376 {
1377 rDestWin.bRFMouse = bRFMouse;
1378 rDestWin.bRFSize = bRFSize;
1379 rDestWin.nRFIndex = nRFIndex;
1380 rDestWin.nRFAddX = nRFAddX;
1381 rDestWin.nRFAddY = nRFAddY;
1382 bRFMouse = sal_False;
1383 }
1384
1385 if (nPagebreakMouse)
1386 {
1387 rDestWin.nPagebreakMouse = nPagebreakMouse;
1388 rDestWin.nPagebreakBreak = nPagebreakBreak;
1389 rDestWin.nPagebreakPrev = nPagebreakPrev;
1390 rDestWin.aPagebreakSource = aPagebreakSource;
1391 rDestWin.aPagebreakDrag = aPagebreakDrag;
1392 nPagebreakMouse = SC_PD_NONE;
1393 }
1394 }
1395
TestMouse(const MouseEvent & rMEvt,sal_Bool bAction)1396 sal_Bool ScGridWindow::TestMouse( const MouseEvent& rMEvt, sal_Bool bAction )
1397 {
1398 // MouseEvent buttons must only be checked if bAction==TRUE
1399 // to allow changing the mouse pointer in MouseMove,
1400 // but not start AutoFill with right button (#74229#).
1401 // with bAction==sal_True, SetFillMode / SetDragMode is called
1402
1403 if ( bAction && !rMEvt.IsLeft() )
1404 return sal_False;
1405
1406 sal_Bool bNewPointer = sal_False;
1407
1408 SfxInPlaceClient* pClient = pViewData->GetViewShell()->GetIPClient();
1409 sal_Bool bOleActive = ( pClient && pClient->IsObjectInPlaceActive() );
1410
1411 if ( pViewData->IsActive() && !bOleActive )
1412 {
1413 ScDocument* pDoc = pViewData->GetDocument();
1414 SCTAB nTab = pViewData->GetTabNo();
1415 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1416
1417 // Auto-Fill
1418
1419 ScRange aMarkRange;
1420 if (pViewData->GetSimpleArea( aMarkRange ) == SC_MARK_SIMPLE)
1421 {
1422 if (aMarkRange.aStart.Tab() == pViewData->GetTabNo() && mpAutoFillRect)
1423 {
1424 Point aMousePos = rMEvt.GetPosPixel();
1425 if (mpAutoFillRect->IsInside(aMousePos))
1426 {
1427 SetPointer( Pointer( POINTER_CROSS ) ); //! dickeres Kreuz ?
1428 if (bAction)
1429 {
1430 SCCOL nX = aMarkRange.aEnd.Col();
1431 SCROW nY = aMarkRange.aEnd.Row();
1432
1433 if ( lcl_IsEditableMatrix( pViewData->GetDocument(), aMarkRange ) )
1434 pViewData->SetDragMode(
1435 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nX, nY, SC_FILL_MATRIX );
1436 else
1437 pViewData->SetFillMode(
1438 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nX, nY );
1439
1440 // #108266# The simple selection must also be recognized when dragging,
1441 // where the Marking flag is set and MarkToSimple won't work anymore.
1442 pViewData->GetMarkData().MarkToSimple();
1443 }
1444 bNewPointer = sal_True;
1445 }
1446 }
1447 }
1448
1449 // Embedded-Rechteck
1450
1451 if (pDoc->IsEmbedded())
1452 {
1453 ScRange aRange;
1454 pDoc->GetEmbedded( aRange );
1455 if ( pViewData->GetTabNo() == aRange.aStart.Tab() )
1456 {
1457 Point aStartPos = pViewData->GetScrPos( aRange.aStart.Col(), aRange.aStart.Row(), eWhich );
1458 Point aEndPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aEnd.Row()+1, eWhich );
1459 Point aMousePos = rMEvt.GetPosPixel();
1460 if ( bLayoutRTL )
1461 {
1462 aStartPos.X() += 2;
1463 aEndPos.X() += 2;
1464 }
1465 sal_Bool bTop = ( aMousePos.X() >= aStartPos.X()-3 && aMousePos.X() <= aStartPos.X()+1 &&
1466 aMousePos.Y() >= aStartPos.Y()-3 && aMousePos.Y() <= aStartPos.Y()+1 );
1467 sal_Bool bBottom = ( aMousePos.X() >= aEndPos.X()-3 && aMousePos.X() <= aEndPos.X()+1 &&
1468 aMousePos.Y() >= aEndPos.Y()-3 && aMousePos.Y() <= aEndPos.Y()+1 );
1469 if ( bTop || bBottom )
1470 {
1471 SetPointer( Pointer( POINTER_CROSS ) );
1472 if (bAction)
1473 {
1474 sal_uInt8 nMode = bTop ? SC_FILL_EMBED_LT : SC_FILL_EMBED_RB;
1475 pViewData->SetDragMode(
1476 aRange.aStart.Col(), aRange.aStart.Row(),
1477 aRange.aEnd.Col(), aRange.aEnd.Row(), nMode );
1478 }
1479 bNewPointer = sal_True;
1480 }
1481 }
1482 }
1483 }
1484
1485 if (!bNewPointer && bAction)
1486 {
1487 // SetPointer( POINTER_ARROW ); // in Fu...
1488 pViewData->ResetFillMode();
1489 }
1490
1491 return bNewPointer;
1492 }
1493
MouseButtonDown(const MouseEvent & rMEvt)1494 void __EXPORT ScGridWindow::MouseButtonDown( const MouseEvent& rMEvt )
1495 {
1496 nNestedButtonState = SC_NESTEDBUTTON_DOWN;
1497
1498 HandleMouseButtonDown( rMEvt );
1499
1500 if ( nNestedButtonState == SC_NESTEDBUTTON_UP )
1501 {
1502 // #i41690# If an object is deactivated from MouseButtonDown, it might reschedule,
1503 // so MouseButtonUp comes before the MouseButtonDown call is finished. In this case,
1504 // simulate another MouseButtonUp call, so the selection state is consistent.
1505
1506 nButtonDown = rMEvt.GetButtons();
1507 FakeButtonUp();
1508
1509 if ( IsTracking() )
1510 EndTracking(); // normally done in VCL as part of MouseButtonUp handling
1511 }
1512 nNestedButtonState = SC_NESTEDBUTTON_NONE;
1513 }
1514
HandleMouseButtonDown(const MouseEvent & rMEvt)1515 void ScGridWindow::HandleMouseButtonDown( const MouseEvent& rMEvt )
1516 {
1517 // We have to check if a context menu is shown and we have an UI
1518 // active inplace client. In that case we have to ignore the event.
1519 // Otherwise we would crash (context menu has been
1520 // opened by inplace client and we would deactivate the inplace client,
1521 // the context menu is closed by VCL asynchronously which in the end
1522 // would work on deleted objects or the context menu has no parent anymore)
1523 // See #126086# and #128122#
1524 SfxViewShell* pViewSh = pViewData->GetViewShell();
1525 SfxInPlaceClient* pClient = pViewSh->GetIPClient();
1526 if ( pClient &&
1527 pClient->IsObjectInPlaceActive() &&
1528 PopupMenu::IsInExecute() )
1529 return;
1530
1531 aCurMousePos = rMEvt.GetPosPixel();
1532
1533 // Filter-Popup beendet sich mit eigenem Mausklick, nicht erst beim Klick
1534 // in das GridWindow, darum ist die folgende Abfrage nicht mehr nötig:
1535 #if 0
1536 // merken, dass FilterBox gelöscht wird, damit sichergestellt
1537 // ist, dass in diesem Handler nicht an gleicher Stelle wieder
1538 // eine neue geöffnet wird.
1539 sal_Bool bWasFilterBox = ( pFilterBox != NULL &&
1540 ((Window*)pFilterBox)->IsVisible() &&
1541 !pFilterBox->IsDataSelect() );
1542 SCCOL nOldColFBox = bWasFilterBox ? pFilterBox->GetCol() : 0;
1543 SCROW nOldRowFBox = bWasFilterBox ? pFilterBox->GetRow() : 0;
1544 #endif
1545
1546 ClickExtern(); // löscht FilterBox, wenn vorhanden
1547
1548 HideNoteMarker(); // Notiz-Anzeige
1549
1550 bEEMouse = sal_False;
1551
1552 ScModule* pScMod = SC_MOD();
1553 if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
1554 {
1555 Sound::Beep();
1556 return;
1557 }
1558
1559 pScActiveViewShell = pViewData->GetViewShell(); // falls auf Link geklickt wird
1560 nScClickMouseModifier = rMEvt.GetModifier(); // um Control-Klick immer zu erkennen
1561
1562 sal_Bool bDetective = pViewData->GetViewShell()->IsAuditShell();
1563 sal_Bool bRefMode = pViewData->IsRefMode(); // Referenz angefangen
1564 sal_Bool bFormulaMode = pScMod->IsFormulaMode(); // nächster Klick -> Referenz
1565 sal_Bool bEditMode = pViewData->HasEditView(eWhich); // auch bei Mode==SC_INPUT_TYPE
1566 sal_Bool bDouble = (rMEvt.GetClicks() == 2);
1567
1568 // DeactivateIP passiert nur noch bei MarkListHasChanged
1569
1570 // im GrabFocus Aufruf kann eine Fehlermeldung hochkommen
1571 // (z.B. beim Umbenennen von Tabellen per Tab-Reiter)
1572
1573 if ( !nButtonDown || !bDouble ) // single (first) click is always valid
1574 nButtonDown = rMEvt.GetButtons(); // set nButtonDown first, so StopMarking works
1575
1576 // pViewData->GetViewShell()->GetViewFrame()->GetWindow().GrabFocus();
1577 if ( ( bEditMode && pViewData->GetActivePart() == eWhich ) || !bFormulaMode )
1578 GrabFocus();
1579
1580 // #i31846# need to cancel a double click if the first click has set the "ignore" state,
1581 // but a single (first) click is always valid
1582 if ( nMouseStatus == SC_GM_IGNORE && bDouble )
1583 {
1584 nButtonDown = 0;
1585 nMouseStatus = SC_GM_NONE;
1586 return;
1587 }
1588
1589 if ( bDetective ) // Detektiv-Fuell-Modus
1590 {
1591 if ( rMEvt.IsLeft() && !rMEvt.GetModifier() )
1592 {
1593 Point aPos = rMEvt.GetPosPixel();
1594 SCsCOL nPosX;
1595 SCsROW nPosY;
1596 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
1597
1598 SfxInt16Item aPosXItem( SID_RANGE_COL, nPosX );
1599 SfxInt32Item aPosYItem( SID_RANGE_ROW, nPosY );
1600 pViewData->GetDispatcher().Execute( SID_FILL_SELECT, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD,
1601 &aPosXItem, &aPosYItem, (void*)0L );
1602
1603 }
1604 nButtonDown = 0;
1605 nMouseStatus = SC_GM_NONE;
1606 return;
1607 }
1608
1609 if (!bDouble)
1610 nMouseStatus = SC_GM_NONE;
1611
1612 if (!bFormulaMode)
1613 {
1614 if ( pViewData->GetActivePart() != eWhich )
1615 pViewData->GetView()->ActivatePart( eWhich );
1616 }
1617 else
1618 {
1619 ScViewSelectionEngine* pSelEng = pViewData->GetView()->GetSelEngine();
1620 pSelEng->SetWindow(this);
1621 pSelEng->SetWhich(eWhich);
1622 pSelEng->SetVisibleArea( Rectangle(Point(), GetOutputSizePixel()) );
1623 }
1624
1625 if (bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()))
1626 {
1627 Point aPos = rMEvt.GetPosPixel();
1628 SCsCOL nPosX;
1629 SCsROW nPosY;
1630 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
1631
1632 EditView* pEditView;
1633 SCCOL nEditCol;
1634 SCROW nEditRow;
1635 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
1636 SCCOL nEndCol = pViewData->GetEditEndCol();
1637 SCROW nEndRow = pViewData->GetEditEndRow();
1638
1639 if ( nPosX >= (SCsCOL) nEditCol && nPosX <= (SCsCOL) nEndCol &&
1640 nPosY >= (SCsROW) nEditRow && nPosY <= (SCsROW) nEndRow )
1641 {
1642 // #53966# beim Klick in die Tabellen-EditView immer den Focus umsetzen
1643 if (bFormulaMode) // sonst ist es oben schon passiert
1644 GrabFocus();
1645
1646 pScMod->SetInputMode( SC_INPUT_TABLE );
1647 bEEMouse = sal_True;
1648 bEditMode = pEditView->MouseButtonDown( rMEvt );
1649 return;
1650 }
1651 }
1652
1653 if (pScMod->GetIsWaterCan())
1654 {
1655 //! was is mit'm Mac ???
1656 if ( rMEvt.GetModifier() + rMEvt.GetButtons() == MOUSE_RIGHT )
1657 {
1658 nMouseStatus = SC_GM_WATERUNDO;
1659 return;
1660 }
1661 }
1662
1663 // Reihenfolge passend zum angezeigten Cursor:
1664 // RangeFinder, AutoFill, PageBreak, Drawing
1665
1666 if ( HitRangeFinder( rMEvt.GetPosPixel(), bRFSize, &nRFIndex, &nRFAddX, &nRFAddY ) )
1667 {
1668 bRFMouse = sal_True; // die anderen Variablen sind oben initialisiert
1669
1670 if ( pViewData->GetActivePart() != eWhich )
1671 pViewData->GetView()->ActivatePart( eWhich ); //! schon oben immer ???
1672
1673 // CaptureMouse();
1674 StartTracking();
1675 return;
1676 }
1677
1678 sal_Bool bCrossPointer = TestMouse( rMEvt, sal_True );
1679 if ( bCrossPointer )
1680 {
1681 if ( bDouble )
1682 pViewData->GetView()->FillCrossDblClick();
1683 else
1684 pScMod->InputEnterHandler(); // Autofill etc.
1685 }
1686
1687 if ( !bCrossPointer )
1688 {
1689 nPagebreakMouse = HitPageBreak( rMEvt.GetPosPixel(), &aPagebreakSource,
1690 &nPagebreakBreak, &nPagebreakPrev );
1691 if (nPagebreakMouse)
1692 {
1693 bPagebreakDrawn = sal_False;
1694 // CaptureMouse();
1695 StartTracking();
1696 PagebreakMove( rMEvt, sal_False );
1697 return;
1698 }
1699 }
1700
1701 if (!bFormulaMode && !bEditMode && rMEvt.IsLeft())
1702 {
1703 if ( !bCrossPointer && DrawMouseButtonDown(rMEvt) )
1704 {
1705 //if (DrawHasMarkedObj())
1706 // pViewData->GetViewShell()->SetDrawShellOrSub(); // Draw-Objekt selektiert
1707 return;
1708 }
1709
1710 pViewData->GetViewShell()->SetDrawShell( sal_False ); // kein Draw-Objekt selektiert
1711
1712 // TestMouse schon oben passiert
1713 }
1714
1715 Point aPos = rMEvt.GetPosPixel();
1716 SCsCOL nPosX;
1717 SCsROW nPosY;
1718 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
1719 SCTAB nTab = pViewData->GetTabNo();
1720 ScDocument* pDoc = pViewData->GetDocument();
1721
1722 // AutoFilter buttons
1723
1724 if ( !bDouble && !bFormulaMode && rMEvt.IsLeft() )
1725 {
1726 SCsCOL nRealPosX;
1727 SCsROW nRealPosY;
1728 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nRealPosX, nRealPosY, false );//the real row/col
1729 ScMergeFlagAttr* pRealPosAttr = (ScMergeFlagAttr*)
1730 pDoc->GetAttr( nRealPosX, nRealPosY, nTab, ATTR_MERGE_FLAG );
1731 ScMergeFlagAttr* pAttr = (ScMergeFlagAttr*)
1732 pDoc->GetAttr( nPosX, nPosY, nTab, ATTR_MERGE_FLAG );
1733 if( pRealPosAttr->HasAutoFilter() )
1734 {
1735 SC_MOD()->InputEnterHandler();
1736 if (DoAutoFilterButton( nRealPosX, nRealPosY, rMEvt))
1737 return;
1738 }
1739 if( pAttr->HasAutoFilter() )
1740 {
1741 SC_MOD()->InputEnterHandler(); //Add for i85305
1742 if (DoAutoFilterButton( nPosX, nPosY, rMEvt))
1743 return;
1744 }
1745 if (pAttr->HasButton())
1746 {
1747 DoPushButton( nPosX, nPosY, rMEvt ); // setzt evtl. bPivotMouse / bDPMouse
1748 return;
1749 }
1750
1751 // List Validity drop-down button
1752
1753 if ( bListValButton )
1754 {
1755 Rectangle aButtonRect = GetListValButtonRect( aListValPos );
1756 if ( aButtonRect.IsInside( aPos ) )
1757 {
1758 DoAutoFilterMenue( aListValPos.Col(), aListValPos.Row(), sal_True );
1759
1760 nMouseStatus = SC_GM_FILTER; // not set in DoAutoFilterMenue for bDataSelect
1761 CaptureMouse();
1762 return;
1763 }
1764 }
1765 }
1766
1767 // scenario selection
1768
1769 ScRange aScenRange;
1770 if ( rMEvt.IsLeft() && HasScenarioButton( aPos, aScenRange ) )
1771 {
1772 DoScenarioMenue( aScenRange );
1773 return;
1774 }
1775
1776 // Doppelklick angefangen ?
1777
1778 // StopMarking kann aus DrawMouseButtonDown gerufen werden
1779
1780 if ( nMouseStatus != SC_GM_IGNORE && !bRefMode )
1781 {
1782 if ( bDouble && !bCrossPointer )
1783 {
1784 if (nMouseStatus == SC_GM_TABDOWN)
1785 nMouseStatus = SC_GM_DBLDOWN;
1786 }
1787 else
1788 nMouseStatus = SC_GM_TABDOWN;
1789 }
1790
1791 // Links in Edit-Zellen
1792
1793 sal_Bool bAlt = rMEvt.IsMod2();
1794 if ( !bAlt && rMEvt.IsLeft() &&
1795 GetEditUrl(rMEvt.GetPosPixel()) ) // Klick auf Link: Cursor nicht bewegen
1796 {
1797 SetPointer( Pointer( POINTER_REFHAND ) );
1798 nMouseStatus = SC_GM_URLDOWN; // auch nur dann beim ButtonUp ausfuehren
1799 return;
1800 }
1801
1802 // Gridwin - SelectionEngine
1803
1804 if ( rMEvt.IsLeft() )
1805 {
1806 ScViewSelectionEngine* pSelEng = pViewData->GetView()->GetSelEngine();
1807 pSelEng->SetWindow(this);
1808 pSelEng->SetWhich(eWhich);
1809 pSelEng->SetVisibleArea( Rectangle(Point(), GetOutputSizePixel()) );
1810
1811 // SelMouseButtonDown an der View setzt noch das bMoveIsShift Flag
1812 if ( pViewData->GetView()->SelMouseButtonDown( rMEvt ) )
1813 {
1814 if (IsMouseCaptured())
1815 {
1816 // Tracking statt CaptureMouse, damit sauber abgebrochen werden kann
1817 //! Irgendwann sollte die SelectionEngine selber StartTracking rufen!?!
1818 ReleaseMouse();
1819 StartTracking();
1820 }
1821 pViewData->GetMarkData().SetMarking(sal_True);
1822 return;
1823 }
1824 }
1825 }
1826
MouseButtonUp(const MouseEvent & rMEvt)1827 void __EXPORT ScGridWindow::MouseButtonUp( const MouseEvent& rMEvt )
1828 {
1829 aCurMousePos = rMEvt.GetPosPixel();
1830 ScDocument* pDoc = pViewData->GetDocument();
1831 ScMarkData& rMark = pViewData->GetMarkData();
1832
1833 // #i41690# detect a MouseButtonUp call from within MouseButtonDown
1834 // (possible through Reschedule from storing an OLE object that is deselected)
1835
1836 if ( nNestedButtonState == SC_NESTEDBUTTON_DOWN )
1837 nNestedButtonState = SC_NESTEDBUTTON_UP;
1838
1839 if (nButtonDown != rMEvt.GetButtons())
1840 nMouseStatus = SC_GM_IGNORE; // reset und return
1841
1842 nButtonDown = 0;
1843
1844 if (nMouseStatus == SC_GM_IGNORE)
1845 {
1846 nMouseStatus = SC_GM_NONE;
1847 // Selection-Engine: Markieren abbrechen
1848 pViewData->GetView()->GetSelEngine()->Reset();
1849 rMark.SetMarking(sal_False);
1850 if (pViewData->IsAnyFillMode())
1851 {
1852 pViewData->GetView()->StopRefMode();
1853 pViewData->ResetFillMode();
1854 }
1855 StopMarking();
1856 DrawEndAction(); // Markieren/Verschieben auf Drawing-Layer abbrechen
1857 ReleaseMouse();
1858 return;
1859 }
1860
1861 if (nMouseStatus == SC_GM_FILTER)
1862 {
1863 if ( pFilterBox && pFilterBox->GetMode() == SC_FILTERBOX_FILTER )
1864 {
1865 if (mpFilterButton.get())
1866 {
1867 bool bFilterActive = IsAutoFilterActive(
1868 pFilterBox->GetCol(), pFilterBox->GetRow(), pViewData->GetTabNo() );
1869
1870 mpFilterButton->setHasHiddenMember(bFilterActive);
1871 mpFilterButton->setPopupPressed(false);
1872 HideCursor();
1873 mpFilterButton->draw();
1874 ShowCursor();
1875 }
1876 }
1877 nMouseStatus = SC_GM_NONE;
1878 ReleaseMouse();
1879 return; // da muss nix mehr passieren
1880 }
1881
1882 ScModule* pScMod = SC_MOD();
1883 if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
1884 return;
1885
1886 SfxBindings& rBindings = pViewData->GetBindings();
1887 if (bEEMouse && pViewData->HasEditView( eWhich ))
1888 {
1889 EditView* pEditView;
1890 SCCOL nEditCol;
1891 SCROW nEditRow;
1892 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
1893 pEditView->MouseButtonUp( rMEvt );
1894
1895 if ( rMEvt.IsMiddle() &&
1896 GetSettings().GetMouseSettings().GetMiddleButtonAction() == MOUSE_MIDDLE_PASTESELECTION )
1897 {
1898 // EditView may have pasted from selection
1899 pScMod->InputChanged( pEditView );
1900 }
1901 else
1902 pScMod->InputSelection( pEditView ); // parentheses etc.
1903
1904 pViewData->GetView()->InvalidateAttribs();
1905 rBindings.Invalidate( SID_HYPERLINK_GETLINK );
1906 bEEMouse = sal_False;
1907 return;
1908 }
1909
1910 if (bDPMouse)
1911 {
1912 DPMouseButtonUp( rMEvt ); // resets bDPMouse
1913 return;
1914 }
1915
1916 if (bRFMouse)
1917 {
1918 RFMouseMove( rMEvt, sal_True ); // Range wieder richtig herum
1919 bRFMouse = sal_False;
1920 SetPointer( Pointer( POINTER_ARROW ) );
1921 ReleaseMouse();
1922 return;
1923 }
1924
1925 if (nPagebreakMouse)
1926 {
1927 PagebreakMove( rMEvt, sal_True );
1928 nPagebreakMouse = SC_PD_NONE;
1929 SetPointer( Pointer( POINTER_ARROW ) );
1930 ReleaseMouse();
1931 return;
1932 }
1933
1934 if (nMouseStatus == SC_GM_WATERUNDO) // Undo im Giesskannenmodus
1935 {
1936 ::svl::IUndoManager* pMgr = pViewData->GetDocShell()->GetUndoManager();
1937 if ( pMgr->GetUndoActionCount() && pMgr->GetUndoActionId() == STR_UNDO_APPLYCELLSTYLE )
1938 pMgr->Undo();
1939 else
1940 Sound::Beep();
1941 return;
1942 }
1943
1944 if (DrawMouseButtonUp(rMEvt)) // includes format paint brush handling for drawing objects
1945 {
1946 ScTabViewShell* pViewShell = pViewData->GetViewShell();
1947 SfxBindings& rBindings=pViewShell->GetViewFrame()->GetBindings();
1948 rBindings.Invalidate(SID_ATTR_TRANSFORM_WIDTH);
1949 rBindings.Invalidate(SID_ATTR_TRANSFORM_HEIGHT);
1950 rBindings.Invalidate(SID_ATTR_TRANSFORM_POS_X);
1951 rBindings.Invalidate(SID_ATTR_TRANSFORM_POS_Y);
1952 rBindings.Invalidate(SID_ATTR_TRANSFORM_ANGLE);
1953 rBindings.Invalidate(SID_ATTR_TRANSFORM_ROT_X);
1954 rBindings.Invalidate(SID_ATTR_TRANSFORM_ROT_Y);
1955 rBindings.Invalidate(SID_ATTR_TRANSFORM_AUTOWIDTH);
1956 rBindings.Invalidate(SID_ATTR_TRANSFORM_AUTOHEIGHT);
1957 return;
1958 }
1959
1960 rMark.SetMarking(sal_False);
1961
1962 SetPointer( Pointer( POINTER_ARROW ) );
1963
1964 if (pViewData->IsFillMode() ||
1965 ( pViewData->GetFillMode() == SC_FILL_MATRIX && rMEvt.IsMod1() ))
1966 {
1967 nScFillModeMouseModifier = rMEvt.GetModifier();
1968 SCCOL nStartCol;
1969 SCROW nStartRow;
1970 SCCOL nEndCol;
1971 SCROW nEndRow;
1972 pViewData->GetFillData( nStartCol, nStartRow, nEndCol, nEndRow );
1973 // DBG_ASSERT( nStartCol==pViewData->GetRefStartX() && nStartRow==pViewData->GetRefStartY(),
1974 // "Block wrong for AutoFill" );
1975 ScRange aDelRange;
1976 sal_Bool bIsDel = pViewData->GetDelMark( aDelRange );
1977
1978 ScViewFunc* pView = pViewData->GetView();
1979 pView->StopRefMode();
1980 pViewData->ResetFillMode();
1981 pView->GetFunctionSet()->SetAnchorFlag( sal_False ); // #i5819# don't use AutoFill anchor flag for selection
1982
1983 if ( bIsDel )
1984 {
1985 pView->MarkRange( aDelRange, sal_False );
1986 pView->DeleteContents( IDF_CONTENTS );
1987 SCTAB nTab = pViewData->GetTabNo();
1988 ScRange aBlockRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab );
1989 if ( aBlockRange != aDelRange )
1990 {
1991 if ( aDelRange.aStart.Row() == nStartRow )
1992 aBlockRange.aEnd.SetCol( aDelRange.aStart.Col() - 1 );
1993 else
1994 aBlockRange.aEnd.SetRow( aDelRange.aStart.Row() - 1 );
1995 pView->MarkRange( aBlockRange, sal_False );
1996 }
1997 }
1998 else
1999 pViewData->GetDispatcher().Execute( FID_FILL_AUTO, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD );
2000 }
2001 else if (pViewData->GetFillMode() == SC_FILL_MATRIX)
2002 {
2003 SCTAB nTab = pViewData->GetTabNo();
2004 SCCOL nStartCol;
2005 SCROW nStartRow;
2006 SCCOL nEndCol;
2007 SCROW nEndRow;
2008 pViewData->GetFillData( nStartCol, nStartRow, nEndCol, nEndRow );
2009 ScRange aBlockRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab );
2010 SCCOL nFillCol = pViewData->GetRefEndX();
2011 SCROW nFillRow = pViewData->GetRefEndY();
2012 ScAddress aEndPos( nFillCol, nFillRow, nTab );
2013
2014 ScTabView* pView = pViewData->GetView();
2015 pView->StopRefMode();
2016 pViewData->ResetFillMode();
2017 pView->GetFunctionSet()->SetAnchorFlag( sal_False );
2018
2019 if ( aEndPos != aBlockRange.aEnd )
2020 {
2021 pViewData->GetDocShell()->GetDocFunc().ResizeMatrix( aBlockRange, aEndPos, sal_False );
2022 pViewData->GetView()->MarkRange( ScRange( aBlockRange.aStart, aEndPos ) );
2023 }
2024 }
2025 else if (pViewData->IsAnyFillMode())
2026 {
2027 // Embedded-Area has been changed
2028 ScTabView* pView = pViewData->GetView();
2029 pView->StopRefMode();
2030 pViewData->ResetFillMode();
2031 pView->GetFunctionSet()->SetAnchorFlag( sal_False );
2032 pViewData->GetDocShell()->UpdateOle(pViewData);
2033 }
2034
2035 sal_Bool bRefMode = pViewData->IsRefMode();
2036 if (bRefMode)
2037 pScMod->EndReference();
2038
2039 // Giesskannen-Modus (Gestalter)
2040
2041 if (pScMod->GetIsWaterCan())
2042 {
2043 // Abfrage auf Undo schon oben
2044
2045 ScStyleSheetPool* pStylePool = (ScStyleSheetPool*)
2046 (pViewData->GetDocument()->
2047 GetStyleSheetPool());
2048 if ( pStylePool )
2049 {
2050 SfxStyleSheet* pStyleSheet = (SfxStyleSheet*)
2051 pStylePool->GetActualStyleSheet();
2052
2053 if ( pStyleSheet )
2054 {
2055 SfxStyleFamily eFamily = pStyleSheet->GetFamily();
2056
2057 switch ( eFamily )
2058 {
2059 case SFX_STYLE_FAMILY_PARA:
2060 pViewData->GetView()->SetStyleSheetToMarked( pStyleSheet );
2061 pViewData->GetView()->DoneBlockMode();
2062 break;
2063
2064 case SFX_STYLE_FAMILY_PAGE:
2065 pViewData->GetDocument()->SetPageStyle( pViewData->GetTabNo(),
2066 pStyleSheet->GetName() );
2067
2068 ScPrintFunc( pViewData->GetDocShell(),
2069 pViewData->GetViewShell()->GetPrinter(sal_True),
2070 pViewData->GetTabNo() ).UpdatePages();
2071
2072 rBindings.Invalidate( SID_STATUS_PAGESTYLE );
2073 break;
2074
2075 default:
2076 break;
2077 }
2078 }
2079 }
2080 }
2081
2082 ScDBFunc* pView = pViewData->GetView();
2083 ScDocument* pBrushDoc = pView->GetBrushDocument();
2084 if ( pBrushDoc )
2085 {
2086 pView->PasteFromClip( IDF_ATTRIB, pBrushDoc );
2087 if ( !pView->IsPaintBrushLocked() )
2088 pView->ResetBrushDocument(); // invalidates pBrushDoc pointer
2089 }
2090
2091 //
2092 // double click (only left button)
2093 //
2094
2095 sal_Bool bDouble = ( rMEvt.GetClicks() == 2 && rMEvt.IsLeft() );
2096 if ( bDouble && !bRefMode && nMouseStatus == SC_GM_DBLDOWN && !pScMod->IsRefDialogOpen() )
2097 {
2098 // data pilot table
2099 Point aPos = rMEvt.GetPosPixel();
2100 SCsCOL nPosX;
2101 SCsROW nPosY;
2102 SCTAB nTab = pViewData->GetTabNo();
2103 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
2104 ScDPObject* pDPObj = pDoc->GetDPAtCursor( nPosX, nPosY, nTab );
2105 if ( pDPObj && pDPObj->GetSaveData()->GetDrillDown() )
2106 {
2107 ScAddress aCellPos( nPosX, nPosY, pViewData->GetTabNo() );
2108
2109 // Check for header drill-down first.
2110 sheet::DataPilotTableHeaderData aData;
2111 pDPObj->GetHeaderPositionData(aCellPos, aData);
2112
2113 if ( ( aData.Flags & sheet::MemberResultFlags::HASMEMBER ) &&
2114 ! ( aData.Flags & sheet::MemberResultFlags::SUBTOTAL ) )
2115 {
2116 sal_uInt16 nDummy;
2117 if ( pView->HasSelectionForDrillDown( nDummy ) )
2118 {
2119 // execute slot to show dialog
2120 pViewData->GetDispatcher().Execute( SID_OUTLINE_SHOW, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD );
2121 }
2122 else
2123 {
2124 // toggle single entry
2125 ScDPObject aNewObj( *pDPObj );
2126 pDPObj->ToggleDetails( aData, &aNewObj );
2127 ScDBDocFunc aFunc( *pViewData->GetDocShell() );
2128 aFunc.DataPilotUpdate( pDPObj, &aNewObj, sal_True, sal_False );
2129 pViewData->GetView()->CursorPosChanged(); // shells may be switched
2130 }
2131 }
2132 else
2133 {
2134 // Check if the data area is double-clicked.
2135
2136 Sequence<sheet::DataPilotFieldFilter> aFilters;
2137 if ( pDPObj->GetDataFieldPositionData(aCellPos, aFilters) )
2138 pViewData->GetView()->ShowDataPilotSourceData( *pDPObj, aFilters );
2139 else
2140 Sound::Beep(); // nothing to expand/collapse/show
2141 }
2142
2143 return;
2144 }
2145
2146 // Check for cell protection attribute.
2147 ScTableProtection* pProtect = pDoc->GetTabProtection( nTab );
2148 bool bEditAllowed = true;
2149 if ( pProtect && pProtect->isProtected() )
2150 {
2151 bool bCellProtected = pDoc->HasAttrib(nPosX, nPosY, nTab, nPosX, nPosY, nTab, HASATTR_PROTECTED);
2152 bool bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
2153 bool bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
2154
2155 if ( bSkipProtected && bSkipUnprotected )
2156 bEditAllowed = false;
2157 else if ( (bCellProtected && bSkipProtected) || (!bCellProtected && bSkipUnprotected) )
2158 bEditAllowed = false;
2159 }
2160
2161 if ( bEditAllowed )
2162 {
2163 // edit cell contents
2164 pViewData->GetViewShell()->UpdateInputHandler();
2165 pScMod->SetInputMode( SC_INPUT_TABLE );
2166 if (pViewData->HasEditView(eWhich))
2167 {
2168 // Text-Cursor gleich an die geklickte Stelle setzen
2169 EditView* pEditView = pViewData->GetEditView( eWhich );
2170 MouseEvent aEditEvt( rMEvt.GetPosPixel(), 1, MOUSE_SYNTHETIC, MOUSE_LEFT, 0 );
2171 pEditView->MouseButtonDown( aEditEvt );
2172 pEditView->MouseButtonUp( aEditEvt );
2173 }
2174 }
2175 return;
2176 }
2177
2178 // Links in edit cells
2179
2180 sal_Bool bAlt = rMEvt.IsMod2();
2181 if ( !bAlt && !bRefMode && !bDouble && nMouseStatus == SC_GM_URLDOWN )
2182 {
2183 // beim ButtonUp nur ausfuehren, wenn ButtonDown auch ueber einer URL war
2184
2185 String aName, aUrl, aTarget;
2186 if ( GetEditUrl( rMEvt.GetPosPixel(), &aName, &aUrl, &aTarget ) )
2187 {
2188 nMouseStatus = SC_GM_NONE; // keinen Doppelklick anfangen
2189 ScGlobal::OpenURL( aUrl, aTarget );
2190
2191 // fire worksheet_followhyperlink event
2192 uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents = pDoc->GetVbaEventProcessor();
2193 if( xVbaEvents.is() ) try
2194 {
2195 Point aPos = rMEvt.GetPosPixel();
2196 SCsCOL nPosX;
2197 SCsROW nPosY;
2198 SCTAB nTab = pViewData->GetTabNo();
2199 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
2200 ScBaseCell* pCell = NULL;
2201 if( lcl_GetHyperlinkCell( pDoc, nPosX, nPosY, nTab, pCell ) )
2202 {
2203 ScAddress aCellPos( nPosX, nPosY, nTab );
2204 uno::Reference< table::XCell > xCell( new ScCellObj( pViewData->GetDocShell(), aCellPos ) );
2205 uno::Sequence< uno::Any > aArgs(1);
2206 aArgs[0] <<= xCell;
2207 xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKSHEET_FOLLOWHYPERLINK, aArgs );
2208 }
2209 }
2210 catch( uno::Exception& )
2211 {
2212 }
2213
2214 return;
2215 }
2216 }
2217
2218 // Gridwin - SelectionEngine
2219
2220 // SelMouseButtonDown is called only for left button, but SelMouseButtonUp would return
2221 // sal_True for any call, so IsLeft must be checked here, too.
2222
2223 if ( rMEvt.IsLeft() && pViewData->GetView()->GetSelEngine()->SelMouseButtonUp( rMEvt ) )
2224 {
2225 // rMark.MarkToSimple();
2226 pViewData->GetView()->UpdateAutoFillMark();
2227
2228 SfxDispatcher* pDisp = pViewData->GetViewShell()->GetDispatcher();
2229 sal_Bool bFormulaMode = pScMod->IsFormulaMode();
2230 DBG_ASSERT( pDisp || bFormulaMode, "Cursor auf nicht aktiver View bewegen ?" );
2231
2232 // #i14927# execute SID_CURRENTCELL (for macro recording) only if there is no
2233 // multiple selection, so the argument string completely describes the selection,
2234 // and executing the slot won't change the existing selection (executing the slot
2235 // here and from a recorded macro is treated equally)
2236
2237 if ( pDisp && !bFormulaMode && !rMark.IsMultiMarked() )
2238 {
2239 String aAddr; // CurrentCell
2240 if( rMark.IsMarked() )
2241 {
2242 // sal_Bool bKeep = rMark.IsMultiMarked(); //! wohin damit ???
2243
2244 ScRange aScRange;
2245 rMark.GetMarkArea( aScRange );
2246 aScRange.Format( aAddr, SCR_ABS );
2247 if ( aScRange.aStart == aScRange.aEnd )
2248 {
2249 // make sure there is a range selection string even for a single cell
2250 String aSingle = aAddr;
2251 aAddr.Append( (sal_Char) ':' );
2252 aAddr.Append( aSingle );
2253 }
2254
2255 //! SID_MARKAREA gibts nicht mehr ???
2256 //! was passiert beim Markieren mit dem Cursor ???
2257 }
2258 else // nur Cursor bewegen
2259 {
2260 ScAddress aScAddress( pViewData->GetCurX(), pViewData->GetCurY(), 0 );
2261 aScAddress.Format( aAddr, SCA_ABS );
2262 }
2263
2264 SfxStringItem aPosItem( SID_CURRENTCELL, aAddr );
2265 pDisp->Execute( SID_CURRENTCELL, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD,
2266 &aPosItem, (void*)0L );
2267
2268 pViewData->GetView()->InvalidateAttribs();
2269 }
2270 pViewData->GetViewShell()->SelectionChanged();
2271 return;
2272 }
2273 }
2274
FakeButtonUp()2275 void ScGridWindow::FakeButtonUp()
2276 {
2277 if ( nButtonDown )
2278 {
2279 MouseEvent aEvent( aCurMousePos ); // nButtons = 0 -> ignore
2280 MouseButtonUp( aEvent );
2281 }
2282 }
2283
MouseMove(const MouseEvent & rMEvt)2284 void __EXPORT ScGridWindow::MouseMove( const MouseEvent& rMEvt )
2285 {
2286 aCurMousePos = rMEvt.GetPosPixel();
2287
2288 if ( rMEvt.IsLeaveWindow() && pNoteMarker && !pNoteMarker->IsByKeyboard() )
2289 HideNoteMarker();
2290
2291 ScModule* pScMod = SC_MOD();
2292 if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
2293 return;
2294
2295 // Ob aus dem Edit-Modus Drag&Drop gestartet wurde, bekommt man leider
2296 // nicht anders mit:
2297
2298 if (bEEMouse && nButtonDown && !rMEvt.GetButtons())
2299 {
2300 bEEMouse = sal_False;
2301 nButtonDown = 0;
2302 nMouseStatus = SC_GM_NONE;
2303 return;
2304 }
2305
2306 if (nMouseStatus == SC_GM_IGNORE)
2307 return;
2308
2309 if (nMouseStatus == SC_GM_WATERUNDO) // Undo im Giesskannenmodus -> nur auf Up warten
2310 return;
2311
2312 if ( pViewData->GetViewShell()->IsAuditShell() ) // Detektiv-Füll-Modus
2313 {
2314 SetPointer( Pointer( POINTER_FILL ) );
2315 return;
2316 }
2317
2318 if (nMouseStatus == SC_GM_FILTER && pFilterBox)
2319 {
2320 Point aRelPos = pFilterBox->ScreenToOutputPixel( OutputToScreenPixel( rMEvt.GetPosPixel() ) );
2321 if ( Rectangle(Point(),pFilterBox->GetOutputSizePixel()).IsInside(aRelPos) )
2322 {
2323 nButtonDown = 0;
2324 nMouseStatus = SC_GM_NONE;
2325 if ( pFilterBox->GetMode() == SC_FILTERBOX_FILTER )
2326 {
2327 if (mpFilterButton.get())
2328 {
2329 mpFilterButton->setHasHiddenMember(false);
2330 mpFilterButton->setPopupPressed(false);
2331 HideCursor();
2332 mpFilterButton->draw();
2333 ShowCursor();
2334 }
2335 }
2336 ReleaseMouse();
2337 pFilterBox->MouseButtonDown( MouseEvent( aRelPos, 1, MOUSE_SIMPLECLICK, MOUSE_LEFT ) );
2338 return;
2339 }
2340 }
2341
2342 sal_Bool bFormulaMode = pScMod->IsFormulaMode(); // nächster Klick -> Referenz
2343
2344 if (bEEMouse && pViewData->HasEditView( eWhich ))
2345 {
2346 EditView* pEditView;
2347 SCCOL nEditCol;
2348 SCROW nEditRow;
2349 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
2350 pEditView->MouseMove( rMEvt );
2351 return;
2352 }
2353
2354 if (bDPMouse)
2355 {
2356 DPMouseMove( rMEvt );
2357 return;
2358 }
2359
2360 if (bRFMouse)
2361 {
2362 RFMouseMove( rMEvt, sal_False );
2363 return;
2364 }
2365
2366 if (nPagebreakMouse)
2367 {
2368 PagebreakMove( rMEvt, sal_False );
2369 return;
2370 }
2371
2372 // anderen Mauszeiger anzeigen?
2373
2374 sal_Bool bEditMode = pViewData->HasEditView(eWhich);
2375
2376 //! Testen ob RefMode-Dragging !!!
2377 if ( bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()) )
2378 {
2379 Point aPos = rMEvt.GetPosPixel();
2380 SCsCOL nPosX;
2381 SCsROW nPosY;
2382 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
2383
2384 EditView* pEditView;
2385 SCCOL nEditCol;
2386 SCROW nEditRow;
2387 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
2388 SCCOL nEndCol = pViewData->GetEditEndCol();
2389 SCROW nEndRow = pViewData->GetEditEndRow();
2390
2391 if ( nPosX >= (SCsCOL) nEditCol && nPosX <= (SCsCOL) nEndCol &&
2392 nPosY >= (SCsROW) nEditRow && nPosY <= (SCsROW) nEndRow )
2393 {
2394 // Field can only be URL field
2395 sal_Bool bAlt = rMEvt.IsMod2();
2396 if ( !bAlt && !nButtonDown && pEditView && pEditView->GetFieldUnderMousePointer() )
2397 SetPointer( Pointer( POINTER_REFHAND ) );
2398 else if ( pEditView && pEditView->GetEditEngine()->IsVertical() )
2399 SetPointer( Pointer( POINTER_TEXT_VERTICAL ) );
2400 else
2401 SetPointer( Pointer( POINTER_TEXT ) );
2402 return;
2403 }
2404 }
2405
2406 sal_Bool bWater = SC_MOD()->GetIsWaterCan() || pViewData->GetView()->HasPaintBrush();
2407 if (bWater)
2408 SetPointer( Pointer(POINTER_FILL) );
2409
2410 if (!bWater)
2411 {
2412 sal_Bool bCross = sal_False;
2413
2414 // Range-Finder
2415
2416 sal_Bool bCorner;
2417 if ( HitRangeFinder( rMEvt.GetPosPixel(), bCorner ) )
2418 {
2419 if (bCorner)
2420 SetPointer( Pointer( POINTER_CROSS ) );
2421 else
2422 SetPointer( Pointer( POINTER_HAND ) );
2423 bCross = sal_True;
2424 }
2425
2426 // Page-Break-Modus
2427
2428 sal_uInt16 nBreakType;
2429 if ( !nButtonDown && pViewData->IsPagebreakMode() &&
2430 ( nBreakType = HitPageBreak( rMEvt.GetPosPixel() ) ) != 0 )
2431 {
2432 PointerStyle eNew = POINTER_ARROW;
2433 switch ( nBreakType )
2434 {
2435 case SC_PD_RANGE_L:
2436 case SC_PD_RANGE_R:
2437 case SC_PD_BREAK_H:
2438 eNew = POINTER_ESIZE;
2439 break;
2440 case SC_PD_RANGE_T:
2441 case SC_PD_RANGE_B:
2442 case SC_PD_BREAK_V:
2443 eNew = POINTER_SSIZE;
2444 break;
2445 case SC_PD_RANGE_TL:
2446 case SC_PD_RANGE_BR:
2447 eNew = POINTER_SESIZE;
2448 break;
2449 case SC_PD_RANGE_TR:
2450 case SC_PD_RANGE_BL:
2451 eNew = POINTER_NESIZE;
2452 break;
2453 }
2454 SetPointer( Pointer( eNew ) );
2455 bCross = sal_True;
2456 }
2457
2458 // Fill-Cursor anzeigen ?
2459
2460 if ( !bFormulaMode && !nButtonDown )
2461 if (TestMouse( rMEvt, sal_False ))
2462 bCross = sal_True;
2463
2464 if ( nButtonDown && pViewData->IsAnyFillMode() )
2465 {
2466 SetPointer( Pointer( POINTER_CROSS ) );
2467 bCross = sal_True;
2468 nScFillModeMouseModifier = rMEvt.GetModifier(); // ausgewertet bei AutoFill und Matrix
2469 }
2470
2471 if (!bCross)
2472 {
2473 sal_Bool bAlt = rMEvt.IsMod2();
2474
2475 if (bEditMode) // Edit-Mode muss zuerst kommen!
2476 SetPointer( Pointer( POINTER_ARROW ) );
2477 else if ( !bAlt && !nButtonDown &&
2478 GetEditUrl(rMEvt.GetPosPixel()) )
2479 SetPointer( Pointer( POINTER_REFHAND ) );
2480 else if ( DrawMouseMove(rMEvt) ) // setzt Pointer um
2481 return;
2482 }
2483 }
2484
2485 if ( pViewData->GetView()->GetSelEngine()->SelMouseMove( rMEvt ) )
2486 return;
2487 }
2488
lcl_InitMouseEvent(::com::sun::star::awt::MouseEvent & rEvent,const MouseEvent & rEvt)2489 void lcl_InitMouseEvent( ::com::sun::star::awt::MouseEvent& rEvent, const MouseEvent& rEvt )
2490 {
2491 rEvent.Modifiers = 0;
2492 if ( rEvt.IsShift() )
2493 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::SHIFT;
2494 if ( rEvt.IsMod1() )
2495 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD1;
2496 if ( rEvt.IsMod2() )
2497 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD2;
2498 if ( rEvt.IsMod3() )
2499 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD3;
2500
2501 rEvent.Buttons = 0;
2502 if ( rEvt.IsLeft() )
2503 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::LEFT;
2504 if ( rEvt.IsRight() )
2505 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::RIGHT;
2506 if ( rEvt.IsMiddle() )
2507 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::MIDDLE;
2508
2509 rEvent.X = rEvt.GetPosPixel().X();
2510 rEvent.Y = rEvt.GetPosPixel().Y();
2511 rEvent.ClickCount = rEvt.GetClicks();
2512 rEvent.PopupTrigger = sal_False;
2513 }
2514
PreNotify(NotifyEvent & rNEvt)2515 long ScGridWindow::PreNotify( NotifyEvent& rNEvt )
2516 {
2517 bool bDone = false;
2518 sal_uInt16 nType = rNEvt.GetType();
2519 if ( nType == EVENT_MOUSEBUTTONUP || nType == EVENT_MOUSEBUTTONDOWN )
2520 {
2521 Window* pWindow = rNEvt.GetWindow();
2522 if (pWindow == this && pViewData)
2523 {
2524 SfxViewFrame* pViewFrame = pViewData->GetViewShell()->GetViewFrame();
2525 if (pViewFrame)
2526 {
2527 com::sun::star::uno::Reference<com::sun::star::frame::XController> xController = pViewFrame->GetFrame().GetController();
2528 if (xController.is())
2529 {
2530 ScTabViewObj* pImp = ScTabViewObj::getImplementation( xController );
2531 if (pImp && pImp->IsMouseListening())
2532 {
2533 ::com::sun::star::awt::MouseEvent aEvent;
2534 lcl_InitMouseEvent( aEvent, *rNEvt.GetMouseEvent() );
2535 if ( rNEvt.GetWindow() )
2536 aEvent.Source = rNEvt.GetWindow()->GetComponentInterface();
2537 if ( nType == EVENT_MOUSEBUTTONDOWN)
2538 bDone = pImp->MousePressed( aEvent );
2539 else
2540 bDone = pImp->MouseReleased( aEvent );
2541 }
2542 }
2543 }
2544 }
2545 }
2546 if (bDone) // event consumed by a listener
2547 {
2548 if ( nType == EVENT_MOUSEBUTTONDOWN )
2549 {
2550 const MouseEvent* pMouseEvent = rNEvt.GetMouseEvent();
2551 if ( pMouseEvent->IsRight() && pMouseEvent->GetClicks() == 1 )
2552 {
2553 // If a listener returned true for a right-click call, also prevent opening the context menu
2554 // (this works only if the context menu is opened on mouse-down)
2555 nMouseStatus = SC_GM_IGNORE;
2556 }
2557 }
2558
2559 return 1;
2560 }
2561 else
2562 return Window::PreNotify( rNEvt );
2563 }
2564
Tracking(const TrackingEvent & rTEvt)2565 void ScGridWindow::Tracking( const TrackingEvent& rTEvt )
2566 {
2567 // Weil die SelectionEngine kein Tracking kennt, die Events nur auf
2568 // die verschiedenen MouseHandler verteilen...
2569
2570 const MouseEvent& rMEvt = rTEvt.GetMouseEvent();
2571
2572 if ( rTEvt.IsTrackingCanceled() ) // alles abbrechen...
2573 {
2574 if (!pViewData->GetView()->IsInActivatePart())
2575 {
2576 if (bDPMouse)
2577 bDPMouse = sal_False; // gezeichnet wird per bDragRect
2578 if (bDragRect)
2579 {
2580 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
2581 bDragRect = sal_False;
2582 UpdateDragRectOverlay();
2583 }
2584 if (bRFMouse)
2585 {
2586 RFMouseMove( rMEvt, sal_True ); // richtig abbrechen geht dabei nicht...
2587 bRFMouse = sal_False;
2588 }
2589 if (nPagebreakMouse)
2590 {
2591 // if (bPagebreakDrawn)
2592 // DrawDragRect( aPagebreakDrag.aStart.Col(), aPagebreakDrag.aStart.Row(),
2593 // aPagebreakDrag.aEnd.Col(), aPagebreakDrag.aEnd.Row(), sal_False );
2594 bPagebreakDrawn = sal_False;
2595 UpdateDragRectOverlay();
2596 nPagebreakMouse = SC_PD_NONE;
2597 }
2598
2599 SetPointer( Pointer( POINTER_ARROW ) );
2600 StopMarking();
2601 MouseButtonUp( rMEvt ); // mit Status SC_GM_IGNORE aus StopMarking
2602
2603 sal_Bool bRefMode = pViewData->IsRefMode();
2604 if (bRefMode)
2605 SC_MOD()->EndReference(); // #63148# Dialog nicht verkleinert lassen
2606 }
2607 }
2608 else if ( rTEvt.IsTrackingEnded() )
2609 {
2610 // MouseButtonUp immer mit passenden Buttons (z.B. wegen Testtool, #63148#)
2611 // Schliesslich behauptet der Tracking-Event ja, dass normal beendet und nicht
2612 // abgebrochen wurde.
2613
2614 MouseEvent aUpEvt( rMEvt.GetPosPixel(), rMEvt.GetClicks(),
2615 rMEvt.GetMode(), nButtonDown, rMEvt.GetModifier() );
2616 MouseButtonUp( aUpEvt );
2617 }
2618 else
2619 MouseMove( rMEvt );
2620 }
2621
StartDrag(sal_Int8,const Point & rPosPixel)2622 void ScGridWindow::StartDrag( sal_Int8 /* nAction */, const Point& rPosPixel )
2623 {
2624 if ( pFilterBox || nPagebreakMouse )
2625 return;
2626
2627 HideNoteMarker();
2628
2629 CommandEvent aDragEvent( rPosPixel, COMMAND_STARTDRAG, sal_True );
2630
2631 if (bEEMouse && pViewData->HasEditView( eWhich ))
2632 {
2633 EditView* pEditView;
2634 SCCOL nEditCol;
2635 SCROW nEditRow;
2636 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
2637
2638 // #63263# don't remove the edit view while switching views
2639 ScModule* pScMod = SC_MOD();
2640 pScMod->SetInEditCommand( sal_True );
2641
2642 pEditView->Command( aDragEvent );
2643
2644 ScInputHandler* pHdl = pScMod->GetInputHdl();
2645 if (pHdl)
2646 pHdl->DataChanged();
2647
2648 pScMod->SetInEditCommand( sal_False );
2649 if (!pViewData->IsActive()) // dropped to different view?
2650 {
2651 ScInputHandler* pViewHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
2652 if ( pViewHdl && pViewData->HasEditView( eWhich ) )
2653 {
2654 pViewHdl->CancelHandler();
2655 ShowCursor(); // missing from KillEditView
2656 }
2657 }
2658 }
2659 else
2660 if ( !DrawCommand(aDragEvent) )
2661 pViewData->GetView()->GetSelEngine()->Command( aDragEvent );
2662 }
2663
lcl_SetTextCursorPos(ScViewData * pViewData,ScSplitPos eWhich,Window * pWin)2664 void lcl_SetTextCursorPos( ScViewData* pViewData, ScSplitPos eWhich, Window* pWin )
2665 {
2666 SCCOL nCol = pViewData->GetCurX();
2667 SCROW nRow = pViewData->GetCurY();
2668 Rectangle aEditArea = pViewData->GetEditArea( eWhich, nCol, nRow, pWin, NULL, sal_True );
2669 aEditArea.Right() = aEditArea.Left();
2670 aEditArea = pWin->PixelToLogic( aEditArea );
2671 pWin->SetCursorRect( &aEditArea );
2672 }
2673
Command(const CommandEvent & rCEvt)2674 void __EXPORT ScGridWindow::Command( const CommandEvent& rCEvt )
2675 {
2676 // The command event is send to the window after a possible context
2677 // menu from an inplace client is closed. Now we have the chance to
2678 // deactivate the inplace client without any problem regarding parent
2679 // windows and code on the stack.
2680 // For more information, see #126086# and #128122#
2681 sal_uInt16 nCmd = rCEvt.GetCommand();
2682 ScTabViewShell* pTabViewSh = pViewData->GetViewShell();
2683 SfxInPlaceClient* pClient = pTabViewSh->GetIPClient();
2684 if ( pClient &&
2685 pClient->IsObjectInPlaceActive() &&
2686 nCmd == COMMAND_CONTEXTMENU )
2687 {
2688 pTabViewSh->DeactivateOle();
2689 return;
2690 }
2691
2692 ScModule* pScMod = SC_MOD();
2693 DBG_ASSERT( nCmd != COMMAND_STARTDRAG, "ScGridWindow::Command called with COMMAND_STARTDRAG" );
2694
2695 if ( nCmd == COMMAND_STARTEXTTEXTINPUT ||
2696 nCmd == COMMAND_ENDEXTTEXTINPUT ||
2697 nCmd == COMMAND_EXTTEXTINPUT ||
2698 nCmd == COMMAND_CURSORPOS )
2699 {
2700 sal_Bool bEditView = pViewData->HasEditView( eWhich );
2701 if (!bEditView)
2702 {
2703 // only if no cell editview is active, look at drawview
2704 SdrView* pSdrView = pViewData->GetView()->GetSdrView();
2705 if ( pSdrView )
2706 {
2707 OutlinerView* pOlView = pSdrView->GetTextEditOutlinerView();
2708 if ( pOlView && pOlView->GetWindow() == this )
2709 {
2710 pOlView->Command( rCEvt );
2711 return; // done
2712 }
2713 }
2714 }
2715
2716 if ( nCmd == COMMAND_CURSORPOS && !bEditView )
2717 {
2718 // #88458# CURSORPOS may be called without following text input,
2719 // to set the input method window position
2720 // -> input mode must not be started,
2721 // manually calculate text insert position if not in input mode
2722
2723 lcl_SetTextCursorPos( pViewData, eWhich, this );
2724 return;
2725 }
2726
2727 ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
2728 if ( pHdl )
2729 {
2730 pHdl->InputCommand( rCEvt, sal_True );
2731 return; // done
2732 }
2733
2734 Window::Command( rCEvt );
2735 return;
2736 }
2737
2738 if ( nCmd == COMMAND_VOICE )
2739 {
2740 // Der Handler wird nur gerufen, wenn ein Text-Cursor aktiv ist,
2741 // also muss es eine EditView oder ein editiertes Zeichenobjekt geben
2742
2743 ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
2744 if ( pHdl && pViewData->HasEditView( eWhich ) )
2745 {
2746 EditView* pEditView = pViewData->GetEditView( eWhich ); // ist dann nicht 0
2747 pHdl->DataChanging();
2748 pEditView->Command( rCEvt );
2749 pHdl->DataChanged();
2750 return; // erledigt
2751 }
2752 SdrView* pSdrView = pViewData->GetView()->GetSdrView();
2753 if ( pSdrView )
2754 {
2755 OutlinerView* pOlView = pSdrView->GetTextEditOutlinerView();
2756 if ( pOlView && pOlView->GetWindow() == this )
2757 {
2758 pOlView->Command( rCEvt );
2759 return; // erledigt
2760 }
2761 }
2762 Window::Command(rCEvt); // sonst soll sich die Basisklasse drum kümmern...
2763 return;
2764 }
2765
2766 if ( nCmd == COMMAND_PASTESELECTION )
2767 {
2768 if ( bEEMouse )
2769 {
2770 // EditEngine handles selection in MouseButtonUp - no action
2771 // needed in command handler
2772 }
2773 else
2774 {
2775 PasteSelection( rCEvt.GetMousePosPixel() );
2776 }
2777 return;
2778 }
2779
2780 if ( nCmd == COMMAND_INPUTLANGUAGECHANGE )
2781 {
2782 // #i55929# Font and font size state depends on input language if nothing is selected,
2783 // so the slots have to be invalidated when the input language is changed.
2784
2785 SfxBindings& rBindings = pViewData->GetBindings();
2786 rBindings.Invalidate( SID_ATTR_CHAR_FONT );
2787 rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT );
2788 return;
2789 }
2790
2791 if ( nCmd == COMMAND_WHEEL || nCmd == COMMAND_STARTAUTOSCROLL || nCmd == COMMAND_AUTOSCROLL )
2792 {
2793 sal_Bool bDone = pViewData->GetView()->ScrollCommand( rCEvt, eWhich );
2794 if (!bDone)
2795 Window::Command(rCEvt);
2796 return;
2797 }
2798 // #i7560# FormulaMode check is below scrolling - scrolling is allowed during formula input
2799 sal_Bool bDisable = pScMod->IsFormulaMode() ||
2800 pScMod->IsModalMode(pViewData->GetSfxDocShell());
2801 if (bDisable)
2802 return;
2803
2804 if ( nCmd == COMMAND_CONTEXTMENU && !SC_MOD()->GetIsWaterCan() )
2805 {
2806 sal_Bool bMouse = rCEvt.IsMouseEvent();
2807 if ( bMouse && nMouseStatus == SC_GM_IGNORE )
2808 return;
2809
2810 if (pViewData->IsAnyFillMode())
2811 {
2812 pViewData->GetView()->StopRefMode();
2813 pViewData->ResetFillMode();
2814 }
2815 ReleaseMouse();
2816 StopMarking();
2817
2818 Point aPosPixel = rCEvt.GetMousePosPixel();
2819 Point aMenuPos = aPosPixel;
2820
2821 if ( bMouse )
2822 {
2823 SCsCOL nCellX = -1;
2824 SCsROW nCellY = -1;
2825 pViewData->GetPosFromPixel(aPosPixel.X(), aPosPixel.Y(), eWhich, nCellX, nCellY);
2826 ScDocument* pDoc = pViewData->GetDocument();
2827 SCTAB nTab = pViewData->GetTabNo();
2828 const ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
2829 bool bSelectAllowed = true;
2830 if ( pProtect && pProtect->isProtected() )
2831 {
2832 // This sheet is protected. Check if a context menu is allowed on this cell.
2833 bool bCellProtected = pDoc->HasAttrib(nCellX, nCellY, nTab, nCellX, nCellY, nTab, HASATTR_PROTECTED);
2834 bool bSelProtected = pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
2835 bool bSelUnprotected = pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
2836
2837 if (bCellProtected)
2838 bSelectAllowed = bSelProtected;
2839 else
2840 bSelectAllowed = bSelUnprotected;
2841 }
2842 if (!bSelectAllowed)
2843 // Selecting this cell is not allowed, neither is context menu.
2844 return;
2845
2846 // #i18735# First select the item under the mouse pointer.
2847 // This can change the selection, and the view state (edit mode, etc).
2848 SelectForContextMenu( aPosPixel, nCellX, nCellY );
2849 }
2850
2851 sal_Bool bDone = sal_False;
2852 sal_Bool bEdit = pViewData->HasEditView(eWhich);
2853 if ( !bEdit )
2854 {
2855 // Edit-Zelle mit Spelling-Errors ?
2856 if ( bMouse && GetEditUrlOrError( sal_True, aPosPixel ) )
2857 {
2858 // GetEditUrlOrError hat den Cursor schon bewegt
2859
2860 pScMod->SetInputMode( SC_INPUT_TABLE );
2861 bEdit = pViewData->HasEditView(eWhich); // hat's geklappt ?
2862
2863 DBG_ASSERT( bEdit, "kann nicht in Edit-Modus schalten" );
2864 }
2865 }
2866 if ( bEdit )
2867 {
2868 EditView* pEditView = pViewData->GetEditView( eWhich ); // ist dann nicht 0
2869
2870 if ( !bMouse )
2871 {
2872 Cursor* pCur = pEditView->GetCursor();
2873 if ( pCur )
2874 {
2875 Point aLogicPos = pCur->GetPos();
2876 // use the position right of the cursor (spell popup is opened if
2877 // the cursor is before the word, but not if behind it)
2878 aLogicPos.X() += pCur->GetWidth();
2879 aLogicPos.Y() += pCur->GetHeight() / 2; // center vertically
2880 aMenuPos = LogicToPixel( aLogicPos );
2881 }
2882 }
2883
2884 // if edit mode was just started above, online spelling may be incomplete
2885 pEditView->GetEditEngine()->CompleteOnlineSpelling();
2886
2887 // IsCursorAtWrongSpelledWord could be used for !bMouse
2888 // if there was a corresponding ExecuteSpellPopup call
2889
2890 if( pEditView->IsWrongSpelledWordAtPos( aMenuPos ) )
2891 {
2892 // Wenn man unter OS/2 neben das Popupmenü klickt, kommt MouseButtonDown
2893 // vor dem Ende des Menue-Execute, darum muss SetModified vorher kommen
2894 // (Bug #40968#)
2895 ScInputHandler* pHdl = pScMod->GetInputHdl();
2896 if (pHdl)
2897 pHdl->SetModified();
2898
2899 Link aLink = LINK( this, ScGridWindow, PopupSpellingHdl );
2900 pEditView->ExecuteSpellPopup( aMenuPos, &aLink );
2901
2902 bDone = sal_True;
2903 }
2904 }
2905 else if ( !bMouse )
2906 {
2907 // non-edit menu by keyboard -> use lower right of cell cursor position
2908
2909 SCCOL nCurX = pViewData->GetCurX();
2910 SCROW nCurY = pViewData->GetCurY();
2911 aMenuPos = pViewData->GetScrPos( nCurX, nCurY, eWhich, sal_True );
2912 long nSizeXPix;
2913 long nSizeYPix;
2914 pViewData->GetMergeSizePixel( nCurX, nCurY, nSizeXPix, nSizeYPix );
2915 aMenuPos.X() += nSizeXPix;
2916 aMenuPos.Y() += nSizeYPix;
2917
2918 if (pViewData)
2919 {
2920 ScTabViewShell* pViewSh = pViewData->GetViewShell();
2921 if (pViewSh)
2922 {
2923 // Is a draw object selected?
2924
2925 SdrView* pDrawView = pViewSh->GetSdrView();
2926 if (pDrawView && pDrawView->AreObjectsMarked())
2927 {
2928 // #100442#; the conext menu should open in the middle of the selected objects
2929 Rectangle aSelectRect(LogicToPixel(pDrawView->GetAllMarkedBoundRect()));
2930 aMenuPos = aSelectRect.Center();
2931 }
2932 }
2933 }
2934 }
2935
2936 if (!bDone)
2937 {
2938 SfxDispatcher::ExecutePopup( 0, this, &aMenuPos );
2939 }
2940 }
2941 }
2942
SelectForContextMenu(const Point & rPosPixel,SCsCOL nCellX,SCsROW nCellY)2943 void ScGridWindow::SelectForContextMenu( const Point& rPosPixel, SCsCOL nCellX, SCsROW nCellY )
2944 {
2945 // #i18735# if the click was outside of the current selection,
2946 // the cursor is moved or an object at the click position selected.
2947 // (see SwEditWin::SelectMenuPosition in Writer)
2948
2949 ScTabView* pView = pViewData->GetView();
2950 ScDrawView* pDrawView = pView->GetScDrawView();
2951
2952 // check cell edit mode
2953
2954 if ( pViewData->HasEditView(eWhich) )
2955 {
2956 ScModule* pScMod = SC_MOD();
2957 SCCOL nEditStartCol = pViewData->GetEditViewCol(); //! change to GetEditStartCol after calcrtl is integrated
2958 SCROW nEditStartRow = pViewData->GetEditViewRow();
2959 SCCOL nEditEndCol = pViewData->GetEditEndCol();
2960 SCROW nEditEndRow = pViewData->GetEditEndRow();
2961
2962 if ( nCellX >= (SCsCOL) nEditStartCol && nCellX <= (SCsCOL) nEditEndCol &&
2963 nCellY >= (SCsROW) nEditStartRow && nCellY <= (SCsROW) nEditEndRow )
2964 {
2965 // handle selection within the EditView
2966
2967 EditView* pEditView = pViewData->GetEditView( eWhich ); // not NULL (HasEditView)
2968 EditEngine* pEditEngine = pEditView->GetEditEngine();
2969 Rectangle aOutputArea = pEditView->GetOutputArea();
2970 Rectangle aVisArea = pEditView->GetVisArea();
2971
2972 Point aTextPos = PixelToLogic( rPosPixel );
2973 if ( pEditEngine->IsVertical() ) // have to manually transform position
2974 {
2975 aTextPos -= aOutputArea.TopRight();
2976 long nTemp = -aTextPos.X();
2977 aTextPos.X() = aTextPos.Y();
2978 aTextPos.Y() = nTemp;
2979 }
2980 else
2981 aTextPos -= aOutputArea.TopLeft();
2982 aTextPos += aVisArea.TopLeft(); // position in the edit document
2983
2984 EPosition aDocPosition = pEditEngine->FindDocPosition(aTextPos);
2985 ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex);
2986 ESelection aSelection = pEditView->GetSelection();
2987 aSelection.Adjust(); // needed for IsLess/IsGreater
2988 if ( aCompare.IsLess(aSelection) || aCompare.IsGreater(aSelection) )
2989 {
2990 // clicked outside the selected text - deselect and move text cursor
2991 MouseEvent aEvent( rPosPixel );
2992 pEditView->MouseButtonDown( aEvent );
2993 pEditView->MouseButtonUp( aEvent );
2994 pScMod->InputSelection( pEditView );
2995 }
2996
2997 return; // clicked within the edit view - keep edit mode
2998 }
2999 else
3000 {
3001 // outside of the edit view - end edit mode, regardless of cell selection, then continue
3002 pScMod->InputEnterHandler();
3003 }
3004 }
3005
3006 // check draw text edit mode
3007
3008 Point aLogicPos = PixelToLogic( rPosPixel ); // after cell edit mode is ended
3009 if ( pDrawView && pDrawView->GetTextEditObject() && pDrawView->GetTextEditOutlinerView() )
3010 {
3011 OutlinerView* pOlView = pDrawView->GetTextEditOutlinerView();
3012 Rectangle aOutputArea = pOlView->GetOutputArea();
3013 if ( aOutputArea.IsInside( aLogicPos ) )
3014 {
3015 // handle selection within the OutlinerView
3016
3017 Outliner* pOutliner = pOlView->GetOutliner();
3018 const EditEngine& rEditEngine = pOutliner->GetEditEngine();
3019 Rectangle aVisArea = pOlView->GetVisArea();
3020
3021 Point aTextPos = aLogicPos;
3022 if ( pOutliner->IsVertical() ) // have to manually transform position
3023 {
3024 aTextPos -= aOutputArea.TopRight();
3025 long nTemp = -aTextPos.X();
3026 aTextPos.X() = aTextPos.Y();
3027 aTextPos.Y() = nTemp;
3028 }
3029 else
3030 aTextPos -= aOutputArea.TopLeft();
3031 aTextPos += aVisArea.TopLeft(); // position in the edit document
3032
3033 EPosition aDocPosition = rEditEngine.FindDocPosition(aTextPos);
3034 ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex);
3035 ESelection aSelection = pOlView->GetSelection();
3036 aSelection.Adjust(); // needed for IsLess/IsGreater
3037 if ( aCompare.IsLess(aSelection) || aCompare.IsGreater(aSelection) )
3038 {
3039 // clicked outside the selected text - deselect and move text cursor
3040 // use DrawView to allow extra handling there (none currently)
3041 MouseEvent aEvent( rPosPixel );
3042 pDrawView->MouseButtonDown( aEvent, this );
3043 pDrawView->MouseButtonUp( aEvent, this );
3044 }
3045
3046 return; // clicked within the edit area - keep edit mode
3047 }
3048 else
3049 {
3050 // Outside of the edit area - end text edit mode, then continue.
3051 // DrawDeselectAll also ends text edit mode and updates the shells.
3052 // If the click was on the edited object, it will be selected again below.
3053 pView->DrawDeselectAll();
3054 }
3055 }
3056
3057 // look for existing selection
3058
3059 sal_Bool bHitSelected = sal_False;
3060 if ( pDrawView && pDrawView->IsMarkedObjHit( aLogicPos ) )
3061 {
3062 // clicked on selected object -> don't change anything
3063 bHitSelected = sal_True;
3064 }
3065 else if ( pViewData->GetMarkData().IsCellMarked(nCellX, nCellY) )
3066 {
3067 // clicked on selected cell -> don't change anything
3068 bHitSelected = sal_True;
3069 }
3070
3071 // select drawing object or move cell cursor
3072
3073 if ( !bHitSelected )
3074 {
3075 sal_Bool bWasDraw = ( pDrawView && pDrawView->AreObjectsMarked() );
3076 sal_Bool bHitDraw = sal_False;
3077 if ( pDrawView )
3078 {
3079 pDrawView->UnmarkAllObj();
3080 // Unlock the Internal Layer in order to activate the context menu.
3081 // re-lock in ScDrawView::MarkListHasChanged()
3082 lcl_UnLockComment( pDrawView, pDrawView->GetSdrPageView(), pDrawView->GetModel(), aLogicPos ,pViewData);
3083 bHitDraw = pDrawView->MarkObj( aLogicPos );
3084 // draw shell is activated in MarkListHasChanged
3085 }
3086 if ( !bHitDraw )
3087 {
3088 pView->Unmark();
3089 pView->SetCursor(nCellX, nCellY);
3090 if ( bWasDraw )
3091 pViewData->GetViewShell()->SetDrawShell( sal_False ); // switch shells
3092 }
3093 }
3094 }
3095
KeyInput(const KeyEvent & rKEvt)3096 void __EXPORT ScGridWindow::KeyInput(const KeyEvent& rKEvt)
3097 {
3098 // #96965# Cursor control for ref input dialog
3099 if( SC_MOD()->IsRefDialogOpen() )
3100 {
3101 const KeyCode& rKeyCode = rKEvt.GetKeyCode();
3102 if( !rKeyCode.GetModifier() && (rKeyCode.GetCode() == KEY_F2) )
3103 {
3104 SC_MOD()->EndReference();
3105 }
3106 else if( pViewData->GetViewShell()->MoveCursorKeyInput( rKEvt ) )
3107 {
3108 ScRange aRef(
3109 pViewData->GetRefStartX(), pViewData->GetRefStartY(), pViewData->GetRefStartZ(),
3110 pViewData->GetRefEndX(), pViewData->GetRefEndY(), pViewData->GetRefEndZ() );
3111 SC_MOD()->SetReference( aRef, pViewData->GetDocument() );
3112 }
3113 pViewData->GetViewShell()->SelectionChanged();
3114 return ;
3115 }
3116 // wenn semi-Modeless-SfxChildWindow-Dialog oben, keine KeyInputs:
3117 else if( !pViewData->IsAnyFillMode() )
3118 {
3119 // query for existing note marker before calling ViewShell's keyboard handling
3120 // which may remove the marker
3121 sal_Bool bHadKeyMarker = ( pNoteMarker && pNoteMarker->IsByKeyboard() );
3122 ScTabViewShell* pViewSh = pViewData->GetViewShell();
3123
3124 if (pViewData->GetDocShell()->GetProgress())
3125 return;
3126
3127 if (DrawKeyInput(rKEvt))
3128 {
3129 const KeyCode& rKeyCode = rKEvt.GetKeyCode();
3130 if (rKeyCode.GetCode() == KEY_DOWN
3131 || rKeyCode.GetCode() == KEY_UP
3132 || rKeyCode.GetCode() == KEY_LEFT
3133 || rKeyCode.GetCode() == KEY_RIGHT)
3134 {
3135 ScTabViewShell* pViewShell = pViewData->GetViewShell();
3136 SfxBindings& rBindings = pViewShell->GetViewFrame()->GetBindings();
3137 rBindings.Invalidate(SID_ATTR_TRANSFORM_POS_X);
3138 rBindings.Invalidate(SID_ATTR_TRANSFORM_POS_Y);
3139 }
3140 return;
3141 }
3142
3143 if (!pViewData->GetView()->IsDrawSelMode() && !DrawHasMarkedObj()) // keine Eingaben im Zeichenmodus
3144 { //! DrawShell abfragen !!!
3145 if (pViewSh->TabKeyInput(rKEvt))
3146 return;
3147 }
3148 else
3149 if (pViewSh->SfxViewShell::KeyInput(rKEvt)) // von SfxViewShell
3150 return;
3151
3152 KeyCode aCode = rKEvt.GetKeyCode();
3153 if ( aCode.GetCode() == KEY_ESCAPE && aCode.GetModifier() == 0 )
3154 {
3155 if ( bHadKeyMarker )
3156 HideNoteMarker();
3157 else
3158 pViewSh->Escape();
3159 return;
3160 }
3161 if ( aCode.GetCode() == KEY_F1 && aCode.GetModifier() == KEY_MOD1 )
3162 {
3163 // ctrl-F1 shows or hides the note or redlining info for the cursor position
3164 // (hard-coded because F1 can't be configured)
3165
3166 if ( bHadKeyMarker )
3167 HideNoteMarker(); // hide when previously visible
3168 else
3169 ShowNoteMarker( pViewData->GetCurX(), pViewData->GetCurY(), sal_True );
3170 return;
3171 }
3172 }
3173
3174 Window::KeyInput(rKEvt);
3175 }
3176
StopMarking()3177 void ScGridWindow::StopMarking()
3178 {
3179 DrawEndAction(); // Markieren/Verschieben auf Drawing-Layer abbrechen
3180
3181 if (nButtonDown)
3182 {
3183 pViewData->GetMarkData().SetMarking(sal_False);
3184 nMouseStatus = SC_GM_IGNORE;
3185 }
3186 }
3187
UpdateInputContext()3188 void ScGridWindow::UpdateInputContext()
3189 {
3190 sal_Bool bReadOnly = pViewData->GetDocShell()->IsReadOnly();
3191 sal_uLong nOptions = bReadOnly ? 0 : ( INPUTCONTEXT_TEXT | INPUTCONTEXT_EXTTEXTINPUT );
3192
3193 // when font from InputContext is used,
3194 // it must be taken from the cursor position's cell attributes
3195
3196 InputContext aContext;
3197 aContext.SetOptions( nOptions );
3198 SetInputContext( aContext );
3199 }
3200
3201 //--------------------------------------------------------
3202
3203 // sensitiver Bereich (Pixel)
3204 #define SCROLL_SENSITIVE 20
3205
DropScroll(const Point & rMousePos)3206 sal_Bool ScGridWindow::DropScroll( const Point& rMousePos )
3207 {
3208 /* doch auch auf nicht aktiven Views...
3209 if ( !pViewData->IsActive() )
3210 return sal_False;
3211 */
3212 SCsCOL nDx = 0;
3213 SCsROW nDy = 0;
3214 Size aSize = GetOutputSizePixel();
3215
3216 if (aSize.Width() > SCROLL_SENSITIVE * 3)
3217 {
3218 if ( rMousePos.X() < SCROLL_SENSITIVE && pViewData->GetPosX(WhichH(eWhich)) > 0 )
3219 nDx = -1;
3220 if ( rMousePos.X() >= aSize.Width() - SCROLL_SENSITIVE
3221 && pViewData->GetPosX(WhichH(eWhich)) < MAXCOL )
3222 nDx = 1;
3223 }
3224 if (aSize.Height() > SCROLL_SENSITIVE * 3)
3225 {
3226 if ( rMousePos.Y() < SCROLL_SENSITIVE && pViewData->GetPosY(WhichV(eWhich)) > 0 )
3227 nDy = -1;
3228 if ( rMousePos.Y() >= aSize.Height() - SCROLL_SENSITIVE
3229 && pViewData->GetPosY(WhichV(eWhich)) < MAXROW )
3230 nDy = 1;
3231 }
3232
3233 if ( nDx != 0 || nDy != 0 )
3234 {
3235 // if (bDragRect)
3236 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3237
3238 if ( nDx != 0 )
3239 pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) );
3240 if ( nDy != 0 )
3241 pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) );
3242
3243 // if (bDragRect)
3244 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3245 }
3246
3247 return sal_False;
3248 }
3249
lcl_TestScenarioRedliningDrop(ScDocument * pDoc,const ScRange & aDragRange)3250 sal_Bool lcl_TestScenarioRedliningDrop( ScDocument* pDoc, const ScRange& aDragRange)
3251 {
3252 // Testet, ob bei eingeschalteten RedLining,
3253 // bei einem Drop ein Scenario betroffen ist.
3254
3255 sal_Bool bReturn = sal_False;
3256 SCTAB nTab = aDragRange.aStart.Tab();
3257 SCTAB nTabCount = pDoc->GetTableCount();
3258
3259 if(pDoc->GetChangeTrack()!=NULL)
3260 {
3261 if( pDoc->IsScenario(nTab) && pDoc->HasScenarioRange(nTab, aDragRange))
3262 {
3263 bReturn = sal_True;
3264 }
3265 else
3266 {
3267 for(SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
3268 {
3269 if(pDoc->HasScenarioRange(i, aDragRange))
3270 {
3271 bReturn = sal_True;
3272 break;
3273 }
3274 }
3275 }
3276 }
3277 return bReturn;
3278 }
3279
lcl_MakeDropRange(SCCOL nPosX,SCROW nPosY,SCTAB nTab,const ScRange & rSource)3280 ScRange lcl_MakeDropRange( SCCOL nPosX, SCROW nPosY, SCTAB nTab, const ScRange& rSource )
3281 {
3282 SCCOL nCol1 = nPosX;
3283 SCCOL nCol2 = nCol1 + ( rSource.aEnd.Col() - rSource.aStart.Col() );
3284 if ( nCol2 > MAXCOL )
3285 {
3286 nCol1 -= nCol2 - MAXCOL;
3287 nCol2 = MAXCOL;
3288 }
3289 SCROW nRow1 = nPosY;
3290 SCROW nRow2 = nRow1 + ( rSource.aEnd.Row() - rSource.aStart.Row() );
3291 if ( nRow2 > MAXROW )
3292 {
3293 nRow1 -= nRow2 - MAXROW;
3294 nRow2 = MAXROW;
3295 }
3296
3297 return ScRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab );
3298 }
3299
3300 //--------------------------------------------------------
3301
3302 extern sal_Bool bPasteIsDrop; // viewfun4 -> move to header
3303 extern sal_Bool bPasteIsMove; // viewfun7 -> move to header
3304
3305 //--------------------------------------------------------
3306
AcceptPrivateDrop(const AcceptDropEvent & rEvt)3307 sal_Int8 ScGridWindow::AcceptPrivateDrop( const AcceptDropEvent& rEvt )
3308 {
3309 if ( rEvt.mbLeaving )
3310 {
3311 // if (bDragRect)
3312 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3313 bDragRect = sal_False;
3314 UpdateDragRectOverlay();
3315 return rEvt.mnAction;
3316 }
3317
3318 const ScDragData& rData = SC_MOD()->GetDragData();
3319 if ( rData.pCellTransfer )
3320 {
3321 // Don't move source that would include filtered rows.
3322 if ((rEvt.mnAction & DND_ACTION_MOVE) && rData.pCellTransfer->HasFilteredRows())
3323 {
3324 if (bDragRect)
3325 {
3326 bDragRect = sal_False;
3327 UpdateDragRectOverlay();
3328 }
3329 return DND_ACTION_NONE;
3330 }
3331
3332 Point aPos = rEvt.maPosPixel;
3333
3334 ScDocument* pSourceDoc = rData.pCellTransfer->GetSourceDocument();
3335 ScDocument* pThisDoc = pViewData->GetDocument();
3336 if (pSourceDoc == pThisDoc)
3337 {
3338 if ( pThisDoc->HasChartAtPoint(pViewData->GetTabNo(), PixelToLogic(aPos)) )
3339 {
3340 if (bDragRect) // Rechteck löschen
3341 {
3342 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3343 bDragRect = sal_False;
3344 UpdateDragRectOverlay();
3345 }
3346
3347 //! highlight chart? (selection border?)
3348
3349 sal_Int8 nRet = rEvt.mnAction;
3350 //! if ( rEvt.GetAction() == DROP_LINK )
3351 //! bOk = rEvt.SetAction( DROP_COPY ); // can't link onto chart
3352 return nRet;
3353 }
3354 }
3355 //! else
3356 //! if ( rEvt.GetAction() == DROP_MOVE )
3357 //! rEvt.SetAction( DROP_COPY ); // different doc: default=COPY
3358
3359 if ( rData.pCellTransfer->GetDragSourceFlags() & SC_DROP_TABLE ) // whole sheet?
3360 {
3361 sal_Bool bOk = pThisDoc->IsDocEditable();
3362 return bOk ? rEvt.mnAction : 0; // don't draw selection frame
3363 }
3364
3365 SCsCOL nPosX;
3366 SCsROW nPosY;
3367 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
3368
3369 ScRange aSourceRange = rData.pCellTransfer->GetRange();
3370 SCCOL nSourceStartX = aSourceRange.aStart.Col();
3371 SCROW nSourceStartY = aSourceRange.aStart.Row();
3372 SCCOL nSourceEndX = aSourceRange.aEnd.Col();
3373 SCROW nSourceEndY = aSourceRange.aEnd.Row();
3374 SCCOL nSizeX = nSourceEndX - nSourceStartX + 1;
3375 SCROW nSizeY = nSourceEndY - nSourceStartY + 1;
3376
3377 if ( rEvt.mnAction != DND_ACTION_MOVE )
3378 nSizeY = rData.pCellTransfer->GetNonFilteredRows(); // copy/link: no filtered rows
3379
3380 SCsCOL nNewDragX = nPosX - rData.pCellTransfer->GetDragHandleX();
3381 if (nNewDragX<0) nNewDragX=0;
3382 if (nNewDragX+(nSizeX-1) > MAXCOL)
3383 nNewDragX = MAXCOL-(nSizeX-1);
3384 SCsROW nNewDragY = nPosY - rData.pCellTransfer->GetDragHandleY();
3385 if (nNewDragY<0) nNewDragY=0;
3386 if (nNewDragY+(nSizeY-1) > MAXROW)
3387 nNewDragY = MAXROW-(nSizeY-1);
3388
3389 // don't break scenario ranges, don't drop on filtered
3390 SCTAB nTab = pViewData->GetTabNo();
3391 ScRange aDropRange = lcl_MakeDropRange( nNewDragX, nNewDragY, nTab, aSourceRange );
3392 if ( lcl_TestScenarioRedliningDrop( pThisDoc, aDropRange ) ||
3393 lcl_TestScenarioRedliningDrop( pSourceDoc, aSourceRange ) ||
3394 ScViewUtil::HasFiltered( aDropRange, pThisDoc) )
3395 {
3396 if (bDragRect)
3397 {
3398 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3399 bDragRect = sal_False;
3400 UpdateDragRectOverlay();
3401 }
3402 return DND_ACTION_NONE;
3403 }
3404
3405 InsCellCmd eDragInsertMode = INS_NONE;
3406 Window::PointerState aState = GetPointerState();
3407
3408 // check for datapilot item sorting
3409 ScDPObject* pDPObj = NULL;
3410 if ( pThisDoc == pSourceDoc && ( pDPObj = pThisDoc->GetDPAtCursor( nNewDragX, nNewDragY, nTab ) ) != NULL )
3411 {
3412 // drop on DataPilot table: sort or nothing
3413
3414 bool bDPSort = false;
3415 if ( pThisDoc->GetDPAtCursor( nSourceStartX, nSourceStartY, aSourceRange.aStart.Tab() ) == pDPObj )
3416 {
3417 sheet::DataPilotTableHeaderData aDestData;
3418 pDPObj->GetHeaderPositionData( ScAddress(nNewDragX, nNewDragY, nTab), aDestData );
3419 bool bValid = ( aDestData.Dimension >= 0 ); // dropping onto a field
3420
3421 // look through the source range
3422 for (SCROW nRow = aSourceRange.aStart.Row(); bValid && nRow <= aSourceRange.aEnd.Row(); ++nRow )
3423 for (SCCOL nCol = aSourceRange.aStart.Col(); bValid && nCol <= aSourceRange.aEnd.Col(); ++nCol )
3424 {
3425 sheet::DataPilotTableHeaderData aSourceData;
3426 pDPObj->GetHeaderPositionData( ScAddress( nCol, nRow, aSourceRange.aStart.Tab() ), aSourceData );
3427 if ( aSourceData.Dimension != aDestData.Dimension || !aSourceData.MemberName.getLength() )
3428 bValid = false; // empty (subtotal) or different field
3429 }
3430
3431 if ( bValid )
3432 {
3433 sal_Bool bIsDataLayout;
3434 String aDimName = pDPObj->GetDimName( aDestData.Dimension, bIsDataLayout );
3435 const ScDPSaveDimension* pDim = pDPObj->GetSaveData()->GetExistingDimensionByName( aDimName );
3436 if ( pDim )
3437 {
3438 ScRange aOutRange = pDPObj->GetOutRange();
3439
3440 sal_uInt16 nOrient = pDim->GetOrientation();
3441 if ( nOrient == sheet::DataPilotFieldOrientation_COLUMN )
3442 {
3443 eDragInsertMode = INS_CELLSRIGHT;
3444 nSizeY = aOutRange.aEnd.Row() - nNewDragY + 1;
3445 bDPSort = true;
3446 }
3447 else if ( nOrient == sheet::DataPilotFieldOrientation_ROW )
3448 {
3449 eDragInsertMode = INS_CELLSDOWN;
3450 nSizeX = aOutRange.aEnd.Col() - nNewDragX + 1;
3451 bDPSort = true;
3452 }
3453 }
3454 }
3455 }
3456
3457 if ( !bDPSort )
3458 {
3459 // no valid sorting in a DataPilot table -> disallow
3460 if ( bDragRect )
3461 {
3462 bDragRect = sal_False;
3463 UpdateDragRectOverlay();
3464 }
3465 return DND_ACTION_NONE;
3466 }
3467 }
3468 else if ( aState.mnState & KEY_MOD2 )
3469 {
3470 if ( pThisDoc == pSourceDoc && nTab == aSourceRange.aStart.Tab() )
3471 {
3472 long nDeltaX = labs( static_cast< long >( nNewDragX - nSourceStartX ) );
3473 long nDeltaY = labs( static_cast< long >( nNewDragY - nSourceStartY ) );
3474 if ( nDeltaX <= nDeltaY )
3475 {
3476 eDragInsertMode = INS_CELLSDOWN;
3477 }
3478 else
3479 {
3480 eDragInsertMode = INS_CELLSRIGHT;
3481 }
3482
3483 if ( ( eDragInsertMode == INS_CELLSDOWN && nNewDragY <= nSourceEndY &&
3484 ( nNewDragX + nSizeX - 1 ) >= nSourceStartX && nNewDragX <= nSourceEndX &&
3485 ( nNewDragX != nSourceStartX || nNewDragY >= nSourceStartY ) ) ||
3486 ( eDragInsertMode == INS_CELLSRIGHT && nNewDragX <= nSourceEndX &&
3487 ( nNewDragY + nSizeY - 1 ) >= nSourceStartY && nNewDragY <= nSourceEndY &&
3488 ( nNewDragY != nSourceStartY || nNewDragX >= nSourceStartX ) ) )
3489 {
3490 if ( bDragRect )
3491 {
3492 bDragRect = sal_False;
3493 UpdateDragRectOverlay();
3494 }
3495 return DND_ACTION_NONE;
3496 }
3497 }
3498 else
3499 {
3500 if ( static_cast< long >( nSizeX ) >= static_cast< long >( nSizeY ) )
3501 {
3502 eDragInsertMode = INS_CELLSDOWN;
3503
3504 }
3505 else
3506 {
3507 eDragInsertMode = INS_CELLSRIGHT;
3508 }
3509 }
3510 }
3511
3512 if ( nNewDragX != (SCsCOL) nDragStartX || nNewDragY != (SCsROW) nDragStartY ||
3513 nDragStartX+nSizeX-1 != nDragEndX || nDragStartY+nSizeY-1 != nDragEndY ||
3514 !bDragRect || eDragInsertMode != meDragInsertMode )
3515 {
3516 // if (bDragRect)
3517 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3518
3519 nDragStartX = nNewDragX;
3520 nDragStartY = nNewDragY;
3521 nDragEndX = nDragStartX+nSizeX-1;
3522 nDragEndY = nDragStartY+nSizeY-1;
3523 bDragRect = sal_True;
3524 meDragInsertMode = eDragInsertMode;
3525
3526 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3527
3528 UpdateDragRectOverlay();
3529
3530 // show target position as tip help
3531 #if 0
3532 if (Help::IsQuickHelpEnabled())
3533 {
3534 ScRange aRange( nDragStartX, nDragStartY, nTab, nDragEndX, nDragEndY, nTab );
3535 String aHelpStr;
3536 aRange.Format( aHelpStr, SCA_VALID ); // non-3D
3537
3538 Point aPos = Pointer::GetPosPixel();
3539 sal_uInt16 nAlign = QUICKHELP_BOTTOM|QUICKHELP_RIGHT;
3540 Rectangle aRect( aPos, aPos );
3541 Help::ShowQuickHelp(aRect, aHelpStr, nAlign);
3542 }
3543 #endif
3544 }
3545 }
3546
3547 return rEvt.mnAction;
3548 }
3549
AcceptDrop(const AcceptDropEvent & rEvt)3550 sal_Int8 ScGridWindow::AcceptDrop( const AcceptDropEvent& rEvt )
3551 {
3552 const ScDragData& rData = SC_MOD()->GetDragData();
3553 if ( rEvt.mbLeaving )
3554 {
3555 DrawMarkDropObj( NULL );
3556 if ( rData.pCellTransfer )
3557 return AcceptPrivateDrop( rEvt ); // hide drop marker for internal D&D
3558 else
3559 return rEvt.mnAction;
3560 }
3561
3562 if ( pViewData->GetDocShell()->IsReadOnly() )
3563 return DND_ACTION_NONE;
3564
3565 sal_Int8 nRet = DND_ACTION_NONE;
3566
3567 if (rData.pCellTransfer)
3568 {
3569 ScRange aSource = rData.pCellTransfer->GetRange();
3570 if ( aSource.aStart.Col() != 0 || aSource.aEnd.Col() != MAXCOL ||
3571 aSource.aStart.Row() != 0 || aSource.aEnd.Row() != MAXROW )
3572 DropScroll( rEvt.maPosPixel );
3573
3574 nRet = AcceptPrivateDrop( rEvt );
3575 }
3576 else
3577 {
3578 if ( rData.aLinkDoc.Len() )
3579 {
3580 String aThisName;
3581 ScDocShell* pDocSh = pViewData->GetDocShell();
3582 if (pDocSh && pDocSh->HasName())
3583 aThisName = pDocSh->GetMedium()->GetName();
3584
3585 if ( rData.aLinkDoc != aThisName )
3586 nRet = rEvt.mnAction;
3587 }
3588 else if (rData.aJumpTarget.Len())
3589 {
3590 // internal bookmarks (from Navigator)
3591 // local jumps from an unnamed document are possible only within a document
3592
3593 if ( !rData.pJumpLocalDoc || rData.pJumpLocalDoc == pViewData->GetDocument() )
3594 nRet = rEvt.mnAction;
3595 }
3596 else
3597 {
3598 sal_Int8 nMyAction = rEvt.mnAction;
3599
3600 // clear DND_ACTION_LINK when other actions are set. The usage below cannot handle
3601 // multiple set values
3602 if((nMyAction & DND_ACTION_LINK) && (nMyAction & (DND_ACTION_COPYMOVE)))
3603 {
3604 nMyAction &= ~DND_ACTION_LINK;
3605 }
3606
3607 if ( !rData.pDrawTransfer ||
3608 !IsMyModel(rData.pDrawTransfer->GetDragSourceView()) ) // drawing within the document
3609 if ( rEvt.mbDefault && nMyAction == DND_ACTION_MOVE )
3610 nMyAction = DND_ACTION_COPY;
3611
3612 ScDocument* pThisDoc = pViewData->GetDocument();
3613 SdrObject* pHitObj = pThisDoc->GetObjectAtPoint(
3614 pViewData->GetTabNo(), PixelToLogic(rEvt.maPosPixel) );
3615 if ( pHitObj && nMyAction == DND_ACTION_LINK ) // && !rData.pDrawTransfer )
3616 {
3617 if ( IsDropFormatSupported(SOT_FORMATSTR_ID_SVXB)
3618 || IsDropFormatSupported(SOT_FORMAT_GDIMETAFILE)
3619 || IsDropFormatSupported(SOT_FORMATSTR_ID_PNG)
3620 || IsDropFormatSupported(SOT_FORMAT_BITMAP) )
3621 {
3622 // graphic dragged onto drawing object
3623 DrawMarkDropObj( pHitObj );
3624 nRet = nMyAction;
3625 }
3626 }
3627 if (!nRet)
3628 DrawMarkDropObj( NULL );
3629
3630 if (!nRet)
3631 {
3632 switch ( nMyAction )
3633 {
3634 case DND_ACTION_COPY:
3635 case DND_ACTION_MOVE:
3636 case DND_ACTION_COPYMOVE:
3637 {
3638 sal_Bool bMove = ( nMyAction == DND_ACTION_MOVE );
3639 if ( IsDropFormatSupported( SOT_FORMATSTR_ID_EMBED_SOURCE ) ||
3640 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE ) ||
3641 IsDropFormatSupported( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) ||
3642 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ||
3643 IsDropFormatSupported( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) ||
3644 IsDropFormatSupported( SOT_FORMAT_STRING ) ||
3645 IsDropFormatSupported( SOT_FORMATSTR_ID_SYLK ) ||
3646 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK ) ||
3647 IsDropFormatSupported( SOT_FORMATSTR_ID_HTML ) ||
3648 IsDropFormatSupported( SOT_FORMATSTR_ID_HTML_SIMPLE ) ||
3649 IsDropFormatSupported( SOT_FORMATSTR_ID_DIF ) ||
3650 IsDropFormatSupported( SOT_FORMATSTR_ID_DRAWING ) ||
3651 IsDropFormatSupported( SOT_FORMATSTR_ID_SVXB ) ||
3652 IsDropFormatSupported( SOT_FORMAT_RTF ) ||
3653 IsDropFormatSupported( SOT_FORMAT_GDIMETAFILE ) ||
3654 IsDropFormatSupported( SOT_FORMATSTR_ID_PNG ) ||
3655 IsDropFormatSupported( SOT_FORMAT_BITMAP ) ||
3656 IsDropFormatSupported( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) ||
3657 IsDropFormatSupported( SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE ) ||
3658 ( !bMove && (
3659 IsDropFormatSupported( SOT_FORMAT_FILE_LIST ) ||
3660 IsDropFormatSupported( SOT_FORMAT_FILE ) ||
3661 IsDropFormatSupported( SOT_FORMATSTR_ID_SOLK ) ||
3662 IsDropFormatSupported( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) ||
3663 IsDropFormatSupported( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) ||
3664 IsDropFormatSupported( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) ) ) )
3665 {
3666 nRet = nMyAction;
3667 }
3668 }
3669 break;
3670 case DND_ACTION_LINK:
3671 if ( IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE ) ||
3672 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ||
3673 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK ) ||
3674 IsDropFormatSupported( SOT_FORMAT_FILE_LIST ) ||
3675 IsDropFormatSupported( SOT_FORMAT_FILE ) ||
3676 IsDropFormatSupported( SOT_FORMATSTR_ID_SOLK ) ||
3677 IsDropFormatSupported( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) ||
3678 IsDropFormatSupported( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) ||
3679 IsDropFormatSupported( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
3680 {
3681 nRet = nMyAction;
3682 }
3683 break;
3684 }
3685
3686 if ( nRet )
3687 {
3688 // Simple check for protection: It's not known here if the drop will result
3689 // in cells or drawing objects (some formats can be both) and how many cells
3690 // the result will be. But if IsFormatEditable for the drop cell position
3691 // is sal_False (ignores matrix formulas), nothing can be pasted, so the drop
3692 // can already be rejected here.
3693
3694 Point aPos = rEvt.maPosPixel;
3695 SCsCOL nPosX;
3696 SCsROW nPosY;
3697 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
3698 SCTAB nTab = pViewData->GetTabNo();
3699 ScDocument* pDoc = pViewData->GetDocument();
3700
3701 ScEditableTester aTester( pDoc, nTab, nPosX,nPosY, nPosX,nPosY );
3702 if ( !aTester.IsFormatEditable() )
3703 nRet = DND_ACTION_NONE; // forbidden
3704 }
3705 }
3706 }
3707
3708 // scroll only for accepted formats
3709 if (nRet)
3710 DropScroll( rEvt.maPosPixel );
3711 }
3712
3713 return nRet;
3714 }
3715
lcl_GetDropFormatId(const uno::Reference<datatransfer::XTransferable> & xTransfer,bool bPreferText=false)3716 sal_uLong lcl_GetDropFormatId( const uno::Reference<datatransfer::XTransferable>& xTransfer, bool bPreferText = false )
3717 {
3718 TransferableDataHelper aDataHelper( xTransfer );
3719
3720 if ( !aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) )
3721 {
3722 // use bookmark formats if no sba is present
3723
3724 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SOLK ) )
3725 return SOT_FORMATSTR_ID_SOLK;
3726 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) )
3727 return SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR;
3728 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) )
3729 return SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK;
3730 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
3731 return SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR;
3732 }
3733
3734 sal_uLong nFormatId = 0;
3735 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING ) )
3736 nFormatId = SOT_FORMATSTR_ID_DRAWING;
3737 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ) )
3738 nFormatId = SOT_FORMATSTR_ID_SVXB;
3739 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ) )
3740 {
3741 // If it's a Writer object, insert RTF instead of OLE
3742
3743 sal_Bool bDoRtf = sal_False;
3744 SotStorageStreamRef xStm;
3745 TransferableObjectDescriptor aObjDesc;
3746 if( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) &&
3747 aDataHelper.GetSotStorageStream( SOT_FORMATSTR_ID_EMBED_SOURCE, xStm ) )
3748 {
3749 SotStorageRef xStore( new SotStorage( *xStm ) );
3750 bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) ||
3751 aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) )
3752 && aDataHelper.HasFormat( SOT_FORMAT_RTF ) );
3753 }
3754 if ( bDoRtf )
3755 nFormatId = FORMAT_RTF;
3756 else
3757 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE;
3758 }
3759 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) )
3760 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE;
3761 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) )
3762 nFormatId = SOT_FORMATSTR_ID_SBA_DATAEXCHANGE;
3763 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE ) )
3764 nFormatId = SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE;
3765 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_BIFF_8 ) )
3766 nFormatId = SOT_FORMATSTR_ID_BIFF_8;
3767 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_BIFF_5 ) )
3768 nFormatId = SOT_FORMATSTR_ID_BIFF_5;
3769 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) )
3770 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE_OLE;
3771 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) )
3772 nFormatId = SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE;
3773 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) )
3774 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE;
3775 else if ( aDataHelper.HasFormat( SOT_FORMAT_RTF ) )
3776 nFormatId = SOT_FORMAT_RTF;
3777 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_HTML ) )
3778 nFormatId = SOT_FORMATSTR_ID_HTML;
3779 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_HTML_SIMPLE ) )
3780 nFormatId = SOT_FORMATSTR_ID_HTML_SIMPLE;
3781 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SYLK ) )
3782 nFormatId = SOT_FORMATSTR_ID_SYLK;
3783 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK ) )
3784 nFormatId = SOT_FORMATSTR_ID_LINK;
3785 else if ( bPreferText && aDataHelper.HasFormat( SOT_FORMAT_STRING ) ) // #i86734# the behaviour introduced in #i62773# is wrong when pasting
3786 nFormatId = SOT_FORMAT_STRING;
3787 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) )
3788 nFormatId = SOT_FORMAT_FILE_LIST;
3789 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE ) ) // #i62773# FILE_LIST/FILE before STRING (Unix file managers)
3790 nFormatId = SOT_FORMAT_FILE;
3791 else if ( aDataHelper.HasFormat( SOT_FORMAT_STRING ) )
3792 nFormatId = SOT_FORMAT_STRING;
3793 else if ( aDataHelper.HasFormat( SOT_FORMAT_GDIMETAFILE ) )
3794 nFormatId = SOT_FORMAT_GDIMETAFILE;
3795 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_PNG ) )
3796 nFormatId = SOT_FORMATSTR_ID_PNG;
3797 else if ( aDataHelper.HasFormat( SOT_FORMAT_BITMAP ) )
3798 nFormatId = SOT_FORMAT_BITMAP;
3799
3800 return nFormatId;
3801 }
3802
lcl_GetDropLinkId(const uno::Reference<datatransfer::XTransferable> & xTransfer)3803 sal_uLong lcl_GetDropLinkId( const uno::Reference<datatransfer::XTransferable>& xTransfer )
3804 {
3805 TransferableDataHelper aDataHelper( xTransfer );
3806
3807 sal_uLong nFormatId = 0;
3808 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) )
3809 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE;
3810 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) )
3811 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE;
3812 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK ) )
3813 nFormatId = SOT_FORMATSTR_ID_LINK;
3814 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) )
3815 nFormatId = SOT_FORMAT_FILE_LIST;
3816 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE ) )
3817 nFormatId = SOT_FORMAT_FILE;
3818 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SOLK ) )
3819 nFormatId = SOT_FORMATSTR_ID_SOLK;
3820 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) )
3821 nFormatId = SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR;
3822 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) )
3823 nFormatId = SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK;
3824 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
3825 nFormatId = SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR;
3826
3827 return nFormatId;
3828 }
3829
ExecutePrivateDrop(const ExecuteDropEvent & rEvt)3830 sal_Int8 ScGridWindow::ExecutePrivateDrop( const ExecuteDropEvent& rEvt )
3831 {
3832 // hide drop marker
3833 // if (bDragRect)
3834 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3835 bDragRect = sal_False;
3836 UpdateDragRectOverlay();
3837
3838 ScModule* pScMod = SC_MOD();
3839 const ScDragData& rData = pScMod->GetDragData();
3840
3841 return DropTransferObj( rData.pCellTransfer, nDragStartX, nDragStartY,
3842 PixelToLogic(rEvt.maPosPixel), rEvt.mnAction );
3843 }
3844
DropTransferObj(ScTransferObj * pTransObj,SCCOL nDestPosX,SCROW nDestPosY,const Point & rLogicPos,sal_Int8 nDndAction)3845 sal_Int8 ScGridWindow::DropTransferObj( ScTransferObj* pTransObj, SCCOL nDestPosX, SCROW nDestPosY,
3846 const Point& rLogicPos, sal_Int8 nDndAction )
3847 {
3848 if ( !pTransObj )
3849 return 0;
3850
3851 ScDocument* pSourceDoc = pTransObj->GetSourceDocument();
3852 ScDocShell* pDocSh = pViewData->GetDocShell();
3853 ScDocument* pThisDoc = pViewData->GetDocument();
3854 ScViewFunc* pView = pViewData->GetView();
3855 SCTAB nThisTab = pViewData->GetTabNo();
3856 sal_uInt16 nFlags = pTransObj->GetDragSourceFlags();
3857
3858 sal_Bool bIsNavi = ( nFlags & SC_DROP_NAVIGATOR ) != 0;
3859 sal_Bool bIsMove = ( nDndAction == DND_ACTION_MOVE && !bIsNavi );
3860
3861 // workaround for wrong nDndAction on Windows when pressing solely
3862 // the Alt key during drag and drop;
3863 // can be removed after #i79215# has been fixed
3864 if ( meDragInsertMode != INS_NONE )
3865 {
3866 bIsMove = ( nDndAction & DND_ACTION_MOVE && !bIsNavi );
3867 }
3868
3869 sal_Bool bIsLink = ( nDndAction == DND_ACTION_LINK );
3870
3871 ScRange aSource = pTransObj->GetRange();
3872
3873 // only use visible tab from source range - when dragging within one table,
3874 // all selected tables at the time of dropping are used (handled in MoveBlockTo)
3875 SCTAB nSourceTab = pTransObj->GetVisibleTab();
3876 aSource.aStart.SetTab( nSourceTab );
3877 aSource.aEnd.SetTab( nSourceTab );
3878
3879 SCCOL nSizeX = aSource.aEnd.Col() - aSource.aStart.Col() + 1;
3880 SCROW nSizeY = (bIsMove ? (aSource.aEnd.Row() - aSource.aStart.Row() + 1) :
3881 pTransObj->GetNonFilteredRows()); // copy/link: no filtered rows
3882 ScRange aDest( nDestPosX, nDestPosY, nThisTab,
3883 nDestPosX + nSizeX - 1, nDestPosY + nSizeY - 1, nThisTab );
3884
3885 /* NOTE: AcceptPrivateDrop() already checked for filtered conditions during
3886 * dragging and adapted drawing of the selection frame. We check here
3887 * (again) because this may actually also be called from PasteSelection(),
3888 * we would have to duplicate determination of flags and destination range
3889 * and would lose the context of the "filtered destination is OK" cases
3890 * below, which is already awkward enough as is. */
3891
3892 // Don't move filtered source.
3893 bool bFiltered = (bIsMove && pTransObj->HasFilteredRows());
3894 if (!bFiltered)
3895 {
3896 if (pSourceDoc != pThisDoc && ((nFlags & SC_DROP_TABLE) ||
3897 (!bIsLink && meDragInsertMode == INS_NONE)))
3898 {
3899 // Nothing. Either entire sheet to be dropped, or the one case
3900 // where PasteFromClip() is to be called that handles a filtered
3901 // destination itself. Drag-copy from another document without
3902 // inserting cells.
3903 }
3904 else
3905 // Don't copy or move to filtered destination.
3906 bFiltered = ScViewUtil::HasFiltered( aDest, pThisDoc);
3907 }
3908
3909 sal_Bool bDone = sal_False;
3910
3911 if (!bFiltered && pSourceDoc == pThisDoc)
3912 {
3913 if ( nFlags & SC_DROP_TABLE ) // whole sheet?
3914 {
3915 if ( pThisDoc->IsDocEditable() )
3916 {
3917 SCTAB nSrcTab = aSource.aStart.Tab();
3918 pViewData->GetDocShell()->MoveTable( nSrcTab, nThisTab, !bIsMove, sal_True ); // with Undo
3919 pView->SetTabNo( nThisTab, sal_True );
3920 bDone = sal_True;
3921 }
3922 }
3923 else // move/copy block
3924 {
3925 String aChartName;
3926 if (pThisDoc->HasChartAtPoint( nThisTab, rLogicPos, &aChartName ))
3927 {
3928 String aRangeName;
3929 aSource.Format( aRangeName, SCR_ABS_3D, pThisDoc );
3930 SfxStringItem aNameItem( SID_CHART_NAME, aChartName );
3931 SfxStringItem aRangeItem( SID_CHART_SOURCE, aRangeName );
3932 sal_uInt16 nId = bIsMove ? SID_CHART_SOURCE : SID_CHART_ADDSOURCE;
3933 pViewData->GetDispatcher().Execute( nId, SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD,
3934 &aRangeItem, &aNameItem, (void*) NULL );
3935 bDone = sal_True;
3936 }
3937 else if ( pThisDoc->GetDPAtCursor( nDestPosX, nDestPosY, nThisTab ) )
3938 {
3939 // drop on DataPilot table: try to sort, fail if that isn't possible
3940
3941 ScAddress aDestPos( nDestPosX, nDestPosY, nThisTab );
3942 if ( aDestPos != aSource.aStart )
3943 bDone = pViewData->GetView()->DataPilotMove( aSource, aDestPos );
3944 else
3945 bDone = sal_True; // same position: nothing
3946 }
3947 else if ( nDestPosX != aSource.aStart.Col() || nDestPosY != aSource.aStart.Row() ||
3948 nSourceTab != nThisTab )
3949 {
3950 String aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY );
3951 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
3952
3953 bDone = sal_True;
3954 if ( meDragInsertMode != INS_NONE )
3955 {
3956 // call with bApi = sal_True to avoid error messages in drop handler
3957 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, sal_True /*bRecord*/, sal_True /*bApi*/, sal_True /*bPartOfPaste*/ );
3958 if ( bDone )
3959 {
3960 if ( nThisTab == nSourceTab )
3961 {
3962 if ( meDragInsertMode == INS_CELLSDOWN &&
3963 nDestPosX == aSource.aStart.Col() && nDestPosY < aSource.aStart.Row() )
3964 {
3965 bDone = aSource.Move( 0, nSizeY, 0, pSourceDoc );
3966 }
3967 else if ( meDragInsertMode == INS_CELLSRIGHT &&
3968 nDestPosY == aSource.aStart.Row() && nDestPosX < aSource.aStart.Col() )
3969 {
3970 bDone = aSource.Move( nSizeX, 0, 0, pSourceDoc );
3971 }
3972 }
3973 pDocSh->UpdateOle( pViewData );
3974 pView->CellContentChanged();
3975 }
3976 }
3977
3978 if ( bDone )
3979 {
3980 if ( bIsLink )
3981 {
3982 // call with bApi = sal_True to avoid error messages in drop handler
3983 bDone = pView->LinkBlock( aSource, aDest.aStart, sal_True /*bApi*/ );
3984 }
3985 else
3986 {
3987 // call with bApi = sal_True to avoid error messages in drop handler
3988 bDone = pView->MoveBlockTo( aSource, aDest.aStart, bIsMove, sal_True /*bRecord*/, sal_True /*bPaint*/, sal_True /*bApi*/ );
3989 }
3990 }
3991
3992 if ( bDone && meDragInsertMode != INS_NONE && bIsMove && nThisTab == nSourceTab )
3993 {
3994 DelCellCmd eCmd = DEL_NONE;
3995 if ( meDragInsertMode == INS_CELLSDOWN )
3996 {
3997 eCmd = DEL_CELLSUP;
3998 }
3999 else if ( meDragInsertMode == INS_CELLSRIGHT )
4000 {
4001 eCmd = DEL_CELLSLEFT;
4002 }
4003
4004 if ( ( eCmd == DEL_CELLSUP && nDestPosX == aSource.aStart.Col() ) ||
4005 ( eCmd == DEL_CELLSLEFT && nDestPosY == aSource.aStart.Row() ) )
4006 {
4007 // call with bApi = sal_True to avoid error messages in drop handler
4008 bDone = pDocSh->GetDocFunc().DeleteCells( aSource, NULL, eCmd, sal_True /*bRecord*/, sal_True /*bApi*/ );
4009 if ( bDone )
4010 {
4011 if ( eCmd == DEL_CELLSUP && nDestPosY > aSource.aEnd.Row() )
4012 {
4013 bDone = aDest.Move( 0, -nSizeY, 0, pThisDoc );
4014 }
4015 else if ( eCmd == DEL_CELLSLEFT && nDestPosX > aSource.aEnd.Col() )
4016 {
4017 bDone = aDest.Move( -nSizeX, 0, 0, pThisDoc );
4018 }
4019 pDocSh->UpdateOle( pViewData );
4020 pView->CellContentChanged();
4021 }
4022 }
4023 }
4024
4025 if ( bDone )
4026 {
4027 pView->MarkRange( aDest, sal_False, sal_False );
4028 pView->SetCursor( aDest.aEnd.Col(), aDest.aEnd.Row() );
4029 }
4030
4031 pDocSh->GetUndoManager()->LeaveListAction();
4032
4033 if (!bDone)
4034 Sound::Beep(); // instead of error message in drop handler
4035 }
4036 else
4037 bDone = sal_True; // nothing to do
4038 }
4039
4040 if (bDone)
4041 pTransObj->SetDragWasInternal(); // don't delete source in DragFinished
4042 }
4043 else if ( !bFiltered && pSourceDoc ) // between documents
4044 {
4045 if ( nFlags & SC_DROP_TABLE ) // copy/link sheets between documents
4046 {
4047 if ( pThisDoc->IsDocEditable() )
4048 {
4049 ScDocShell* pSrcShell = pTransObj->GetSourceDocShell();
4050
4051 SCTAB nTabs[MAXTABCOUNT];
4052
4053 ScMarkData aMark = pTransObj->GetSourceMarkData();
4054 SCTAB nTabCount = pSourceDoc->GetTableCount();
4055 SCTAB nTabSelCount = 0;
4056
4057 for(SCTAB i=0; i<nTabCount; i++)
4058 {
4059 if(aMark.GetTableSelect(i))
4060 {
4061 nTabs[nTabSelCount++]=i;
4062 for(SCTAB j=i+1;j<nTabCount;j++)
4063 {
4064 if((!pSourceDoc->IsVisible(j))&&(pSourceDoc->IsScenario(j)))
4065 {
4066 nTabs[nTabSelCount++]=j;
4067 i=j;
4068 }
4069 else break;
4070 }
4071 }
4072 }
4073
4074 pView->ImportTables( pSrcShell,nTabSelCount, nTabs, bIsLink, nThisTab );
4075 bDone = sal_True;
4076 }
4077 }
4078 else if ( bIsLink )
4079 {
4080 // as in PasteDDE
4081 // (external references might be used instead?)
4082
4083 SfxObjectShell* pSourceSh = pSourceDoc->GetDocumentShell();
4084 DBG_ASSERT(pSourceSh, "drag document has no shell");
4085 if (pSourceSh)
4086 {
4087 String aUndo = ScGlobal::GetRscString( STR_UNDO_COPY );
4088 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
4089
4090 bDone = sal_True;
4091 if ( meDragInsertMode != INS_NONE )
4092 {
4093 // call with bApi = sal_True to avoid error messages in drop handler
4094 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, sal_True /*bRecord*/, sal_True /*bApi*/, sal_True /*bPartOfPaste*/ );
4095 if ( bDone )
4096 {
4097 pDocSh->UpdateOle( pViewData );
4098 pView->CellContentChanged();
4099 }
4100 }
4101
4102 if ( bDone )
4103 {
4104 String aApp = Application::GetAppName();
4105 String aTopic = pSourceSh->GetTitle( SFX_TITLE_FULLNAME );
4106 String aItem;
4107 aSource.Format( aItem, SCA_VALID | SCA_TAB_3D, pSourceDoc );
4108
4109 // TODO: we could define ocQuote for "
4110 const String aQuote( '"' );
4111 const String& sSep = ScCompiler::GetNativeSymbol( ocSep);
4112 String aFormula( '=' );
4113 aFormula += ScCompiler::GetNativeSymbol( ocDde);
4114 aFormula += ScCompiler::GetNativeSymbol( ocOpen);
4115 aFormula += aQuote;
4116 aFormula += aApp;
4117 aFormula += aQuote;
4118 aFormula += sSep;
4119 aFormula += aQuote;
4120 aFormula += aTopic;
4121 aFormula += aQuote;
4122 aFormula += sSep;
4123 aFormula += aQuote;
4124 aFormula += aItem;
4125 aFormula += aQuote;
4126 aFormula += ScCompiler::GetNativeSymbol( ocClose);
4127
4128 pView->DoneBlockMode();
4129 pView->InitBlockMode( nDestPosX, nDestPosY, nThisTab );
4130 pView->MarkCursor( nDestPosX + nSizeX - 1,
4131 nDestPosY + nSizeY - 1, nThisTab );
4132
4133 pView->EnterMatrix( aFormula );
4134
4135 pView->MarkRange( aDest, sal_False, sal_False );
4136 pView->SetCursor( aDest.aEnd.Col(), aDest.aEnd.Row() );
4137 }
4138
4139 pDocSh->GetUndoManager()->LeaveListAction();
4140 }
4141 }
4142 else
4143 {
4144 //! HasSelectedBlockMatrixFragment without selected sheet?
4145 //! or don't start dragging on a part of a matrix
4146
4147 String aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY );
4148 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
4149
4150 bDone = sal_True;
4151 if ( meDragInsertMode != INS_NONE )
4152 {
4153 // call with bApi = sal_True to avoid error messages in drop handler
4154 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, sal_True /*bRecord*/, sal_True /*bApi*/, sal_True /*bPartOfPaste*/ );
4155 if ( bDone )
4156 {
4157 pDocSh->UpdateOle( pViewData );
4158 pView->CellContentChanged();
4159 }
4160 }
4161
4162 if ( bDone )
4163 {
4164 pView->Unmark(); // before SetCursor, so CheckSelectionTransfer isn't called with a selection
4165 pView->SetCursor( nDestPosX, nDestPosY );
4166 bDone = pView->PasteFromClip( IDF_ALL, pTransObj->GetDocument() ); // clip-doc
4167 if ( bDone )
4168 {
4169 pView->MarkRange( aDest, sal_False, sal_False );
4170 pView->SetCursor( aDest.aEnd.Col(), aDest.aEnd.Row() );
4171 }
4172 }
4173
4174 pDocSh->GetUndoManager()->LeaveListAction();
4175
4176 // no longer call ResetMark here - the inserted block has been selected
4177 // and may have been copied to primary selection
4178 }
4179 }
4180
4181 sal_Int8 nRet = bDone ? nDndAction : DND_ACTION_NONE;
4182 return nRet;
4183 }
4184
ExecuteDrop(const ExecuteDropEvent & rEvt)4185 sal_Int8 ScGridWindow::ExecuteDrop( const ExecuteDropEvent& rEvt )
4186 {
4187 DrawMarkDropObj( NULL ); // drawing layer
4188
4189 ScModule* pScMod = SC_MOD();
4190 const ScDragData& rData = pScMod->GetDragData();
4191 if (rData.pCellTransfer)
4192 return ExecutePrivateDrop( rEvt );
4193
4194 Point aPos = rEvt.maPosPixel;
4195
4196 if ( rData.aLinkDoc.Len() )
4197 {
4198 // try to insert a link
4199
4200 sal_Bool bOk = sal_True;
4201 String aThisName;
4202 ScDocShell* pDocSh = pViewData->GetDocShell();
4203 if (pDocSh && pDocSh->HasName())
4204 aThisName = pDocSh->GetMedium()->GetName();
4205
4206 if ( rData.aLinkDoc == aThisName ) // error - no link within a document
4207 bOk = sal_False;
4208 else
4209 {
4210 ScViewFunc* pView = pViewData->GetView();
4211 if ( rData.aLinkTable.Len() )
4212 pView->InsertTableLink( rData.aLinkDoc, EMPTY_STRING, EMPTY_STRING,
4213 rData.aLinkTable );
4214 else if ( rData.aLinkArea.Len() )
4215 {
4216 SCsCOL nPosX;
4217 SCsROW nPosY;
4218 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
4219 pView->MoveCursorAbs( nPosX, nPosY, SC_FOLLOW_NONE, sal_False, sal_False );
4220
4221 pView->InsertAreaLink( rData.aLinkDoc, EMPTY_STRING, EMPTY_STRING,
4222 rData.aLinkArea, 0 );
4223 }
4224 else
4225 {
4226 DBG_ERROR("drop with link: no sheet nor area");
4227 bOk = sal_False;
4228 }
4229 }
4230
4231 return bOk ? rEvt.mnAction : DND_ACTION_NONE; // don't try anything else
4232 }
4233
4234 Point aLogicPos = PixelToLogic(aPos);
4235 sal_Bool bIsLink = ( rEvt.mnAction == DND_ACTION_LINK );
4236
4237 if (!bIsLink && rData.pDrawTransfer)
4238 {
4239 sal_uInt16 nFlags = rData.pDrawTransfer->GetDragSourceFlags();
4240
4241 sal_Bool bIsNavi = ( nFlags & SC_DROP_NAVIGATOR ) != 0;
4242 sal_Bool bIsMove = ( rEvt.mnAction == DND_ACTION_MOVE && !bIsNavi );
4243
4244 bPasteIsMove = bIsMove;
4245
4246 pViewData->GetView()->PasteDraw( aLogicPos, rData.pDrawTransfer->GetModel() );
4247
4248 if (bPasteIsMove)
4249 rData.pDrawTransfer->SetDragWasInternal();
4250 bPasteIsMove = sal_False;
4251
4252 return rEvt.mnAction;
4253 }
4254
4255 SCsCOL nPosX;
4256 SCsROW nPosY;
4257 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
4258
4259 if (rData.aJumpTarget.Len())
4260 {
4261 // internal bookmark (from Navigator)
4262 // bookmark clipboard formats are in PasteScDataObject
4263
4264 if ( !rData.pJumpLocalDoc || rData.pJumpLocalDoc == pViewData->GetDocument() )
4265 {
4266 pViewData->GetViewShell()->InsertBookmark( rData.aJumpText, rData.aJumpTarget,
4267 nPosX, nPosY );
4268 return rEvt.mnAction;
4269 }
4270 }
4271
4272 ScDocument* pThisDoc = pViewData->GetDocument();
4273 SdrObject* pHitObj = pThisDoc->GetObjectAtPoint( pViewData->GetTabNo(), PixelToLogic(aPos) );
4274 if ( pHitObj && bIsLink )
4275 {
4276 // dropped on drawing object
4277 // PasteOnDrawObjectLinked checks for valid formats
4278 if ( pViewData->GetView()->PasteOnDrawObjectLinked( rEvt.maDropEvent.Transferable, *pHitObj ) )
4279 return rEvt.mnAction;
4280 }
4281
4282 sal_Bool bDone = sal_False;
4283
4284 sal_uLong nFormatId = bIsLink ?
4285 lcl_GetDropLinkId( rEvt.maDropEvent.Transferable ) :
4286 lcl_GetDropFormatId( rEvt.maDropEvent.Transferable );
4287 if ( nFormatId )
4288 {
4289 pScMod->SetInExecuteDrop( sal_True ); // #i28468# prevent error messages from PasteDataFormat
4290 bPasteIsDrop = sal_True;
4291 bDone = pViewData->GetView()->PasteDataFormat(
4292 nFormatId, rEvt.maDropEvent.Transferable, nPosX, nPosY, &aLogicPos, bIsLink );
4293 bPasteIsDrop = sal_False;
4294 pScMod->SetInExecuteDrop( sal_False );
4295 }
4296
4297 sal_Int8 nRet = bDone ? rEvt.mnAction : DND_ACTION_NONE;
4298 return nRet;
4299 }
4300
4301 //--------------------------------------------------------
4302
PasteSelection(const Point & rPosPixel)4303 void ScGridWindow::PasteSelection( const Point& rPosPixel )
4304 {
4305 Point aLogicPos = PixelToLogic( rPosPixel );
4306
4307 SCsCOL nPosX;
4308 SCsROW nPosY;
4309 pViewData->GetPosFromPixel( rPosPixel.X(), rPosPixel.Y(), eWhich, nPosX, nPosY );
4310
4311 ScSelectionTransferObj* pOwnSelection = SC_MOD()->GetSelectionTransfer();
4312 if ( pOwnSelection )
4313 {
4314 // within Calc
4315
4316 ScTransferObj* pCellTransfer = pOwnSelection->GetCellData();
4317 if ( pCellTransfer )
4318 {
4319 // keep a reference to the data in case the selection is changed during paste
4320 uno::Reference<datatransfer::XTransferable> xRef( pCellTransfer );
4321 DropTransferObj( pCellTransfer, nPosX, nPosY, aLogicPos, DND_ACTION_COPY );
4322 }
4323 else
4324 {
4325 ScDrawTransferObj* pDrawTransfer = pOwnSelection->GetDrawData();
4326 if ( pDrawTransfer )
4327 {
4328 // keep a reference to the data in case the selection is changed during paste
4329 uno::Reference<datatransfer::XTransferable> xRef( pDrawTransfer );
4330
4331 // #96821# bSameDocClipboard argument for PasteDraw is needed
4332 // because only DragData is checked directly inside PasteDraw
4333 pViewData->GetView()->PasteDraw( aLogicPos, pDrawTransfer->GetModel(), sal_False,
4334 pDrawTransfer->GetSourceDocID() == pViewData->GetDocument()->GetDocumentID() );
4335 }
4336 }
4337 }
4338 else
4339 {
4340 // get selection from system
4341
4342 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSelection( this ) );
4343 uno::Reference<datatransfer::XTransferable> xTransferable = aDataHelper.GetTransferable();
4344 if ( xTransferable.is() )
4345 {
4346 sal_uLong nFormatId = lcl_GetDropFormatId( xTransferable, true );
4347 if ( nFormatId )
4348 {
4349 bPasteIsDrop = sal_True;
4350 pViewData->GetView()->PasteDataFormat( nFormatId, xTransferable, nPosX, nPosY, &aLogicPos );
4351 bPasteIsDrop = sal_False;
4352 }
4353 }
4354 }
4355 }
4356
4357 //--------------------------------------------------------
4358
UpdateEditViewPos()4359 void ScGridWindow::UpdateEditViewPos()
4360 {
4361 if (pViewData->HasEditView(eWhich))
4362 {
4363 EditView* pView;
4364 SCCOL nCol;
4365 SCROW nRow;
4366 pViewData->GetEditView( eWhich, pView, nCol, nRow );
4367 SCCOL nEndCol = pViewData->GetEditEndCol();
4368 SCROW nEndRow = pViewData->GetEditEndRow();
4369
4370 // hide EditView?
4371
4372 sal_Bool bHide = ( nEndCol<pViewData->GetPosX(eHWhich) || nEndRow<pViewData->GetPosY(eVWhich) );
4373 if ( SC_MOD()->IsFormulaMode() )
4374 if ( pViewData->GetTabNo() != pViewData->GetRefTabNo() )
4375 bHide = sal_True;
4376
4377 if (bHide)
4378 {
4379 Rectangle aRect = pView->GetOutputArea();
4380 long nHeight = aRect.Bottom() - aRect.Top();
4381 aRect.Top() = PixelToLogic(GetOutputSizePixel(), pViewData->GetLogicMode()).
4382 Height() * 2;
4383 aRect.Bottom() = aRect.Top() + nHeight;
4384 pView->SetOutputArea( aRect );
4385 pView->HideCursor();
4386 }
4387 else
4388 {
4389 // bForceToTop = sal_True for editing
4390 Rectangle aPixRect = pViewData->GetEditArea( eWhich, nCol, nRow, this, NULL, sal_True );
4391 Point aScrPos = PixelToLogic( aPixRect.TopLeft(), pViewData->GetLogicMode() );
4392
4393 Rectangle aRect = pView->GetOutputArea();
4394 aRect.SetPos( aScrPos );
4395 pView->SetOutputArea( aRect );
4396 pView->ShowCursor();
4397 }
4398 }
4399 }
4400
ScrollPixel(long nDifX,long nDifY)4401 void ScGridWindow::ScrollPixel( long nDifX, long nDifY )
4402 {
4403 ClickExtern();
4404 HideNoteMarker();
4405
4406 bIsInScroll = sal_True;
4407 //sal_Bool bXor=DrawBeforeScroll();
4408
4409 SetMapMode(MAP_PIXEL);
4410 Scroll( nDifX, nDifY, SCROLL_CHILDREN );
4411 SetMapMode( GetDrawMapMode() ); // verschobenen MapMode erzeugen
4412
4413 UpdateEditViewPos();
4414
4415 DrawAfterScroll(); //bXor);
4416 bIsInScroll = sal_False;
4417 }
4418
4419 // Formeln neu zeichnen -------------------------------------------------
4420
UpdateFormulas()4421 void ScGridWindow::UpdateFormulas()
4422 {
4423 if (pViewData->GetView()->IsMinimized())
4424 return;
4425
4426 if ( nPaintCount )
4427 {
4428 // nicht anfangen, verschachtelt zu painten
4429 // (dann würde zumindest der MapMode nicht mehr stimmen)
4430
4431 bNeedsRepaint = sal_True; // -> am Ende vom Paint nochmal Invalidate auf alles
4432 aRepaintPixel = Rectangle(); // alles
4433 return;
4434 }
4435
4436 SCCOL nX1 = pViewData->GetPosX( eHWhich );
4437 SCROW nY1 = pViewData->GetPosY( eVWhich );
4438 SCCOL nX2 = nX1 + pViewData->VisibleCellsX( eHWhich );
4439 SCROW nY2 = nY1 + pViewData->VisibleCellsY( eVWhich );
4440
4441 if (nX2 > MAXCOL) nX2 = MAXCOL;
4442 if (nY2 > MAXROW) nY2 = MAXROW;
4443
4444 // Draw( nX1, nY1, nX2, nY2, SC_UPDATE_CHANGED );
4445
4446 // don't draw directly - instead use OutputData to find changed area and invalidate
4447
4448 SCROW nPosY = nY1;
4449
4450 ScDocShell* pDocSh = pViewData->GetDocShell();
4451 ScDocument* pDoc = pDocSh->GetDocument();
4452 SCTAB nTab = pViewData->GetTabNo();
4453
4454 pDoc->ExtendHidden( nX1, nY1, nX2, nY2, nTab );
4455
4456 Point aScrPos = pViewData->GetScrPos( nX1, nY1, eWhich );
4457 long nMirrorWidth = GetSizePixel().Width();
4458 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
4459 // unused variable long nLayoutSign = bLayoutRTL ? -1 : 1;
4460 if ( bLayoutRTL )
4461 {
4462 long nEndPixel = pViewData->GetScrPos( nX2+1, nPosY, eWhich ).X();
4463 nMirrorWidth = aScrPos.X() - nEndPixel;
4464 aScrPos.X() = nEndPixel + 1;
4465 }
4466
4467 long nScrX = aScrPos.X();
4468 long nScrY = aScrPos.Y();
4469
4470 double nPPTX = pViewData->GetPPTX();
4471 double nPPTY = pViewData->GetPPTY();
4472
4473 ScTableInfo aTabInfo;
4474 pDoc->FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nTab, nPPTX, nPPTY, sal_False, sal_False );
4475
4476 Fraction aZoomX = pViewData->GetZoomX();
4477 Fraction aZoomY = pViewData->GetZoomY();
4478 ScOutputData aOutputData( this, OUTTYPE_WINDOW, aTabInfo, pDoc, nTab,
4479 nScrX, nScrY, nX1, nY1, nX2, nY2, nPPTX, nPPTY,
4480 &aZoomX, &aZoomY );
4481 aOutputData.SetMirrorWidth( nMirrorWidth );
4482
4483 aOutputData.FindChanged();
4484
4485 // #122149# do not use old GetChangedArea() which used polygon-based Regions, but use
4486 // the region-band based new version; anyways, only rectangles are added
4487 Region aChangedRegion( aOutputData.GetChangedAreaRegion() ); // logic (PixelToLogic)
4488 if(!aChangedRegion.IsEmpty())
4489 {
4490 Invalidate(aChangedRegion);
4491 }
4492
4493 CheckNeedsRepaint(); // #i90362# used to be called via Draw() - still needed here
4494 }
4495
UpdateAutoFillMark(sal_Bool bMarked,const ScRange & rMarkRange)4496 void ScGridWindow::UpdateAutoFillMark(sal_Bool bMarked, const ScRange& rMarkRange)
4497 {
4498 if ( bMarked != bAutoMarkVisible || ( bMarked && rMarkRange.aEnd != aAutoMarkPos ) )
4499 {
4500 HideCursor();
4501 bAutoMarkVisible = bMarked;
4502 if ( bMarked )
4503 aAutoMarkPos = rMarkRange.aEnd;
4504 ShowCursor();
4505
4506 UpdateAutoFillOverlay();
4507 }
4508 }
4509
UpdateListValPos(sal_Bool bVisible,const ScAddress & rPos)4510 void ScGridWindow::UpdateListValPos( sal_Bool bVisible, const ScAddress& rPos )
4511 {
4512 sal_Bool bOldButton = bListValButton;
4513 ScAddress aOldPos = aListValPos;
4514
4515 bListValButton = bVisible;
4516 aListValPos = rPos;
4517
4518 if ( bListValButton )
4519 {
4520 if ( !bOldButton || aListValPos != aOldPos )
4521 {
4522 // paint area of new button
4523 Invalidate( PixelToLogic( GetListValButtonRect( aListValPos ) ) );
4524 }
4525 }
4526 if ( bOldButton )
4527 {
4528 if ( !bListValButton || aListValPos != aOldPos )
4529 {
4530 // paint area of old button
4531 Invalidate( PixelToLogic( GetListValButtonRect( aOldPos ) ) );
4532 }
4533 }
4534 }
4535
HideCursor()4536 void ScGridWindow::HideCursor()
4537 {
4538 ++nCursorHideCount;
4539 if (nCursorHideCount==1)
4540 {
4541 DrawCursor();
4542 DrawAutoFillMark();
4543 }
4544 }
4545
ShowCursor()4546 void ScGridWindow::ShowCursor()
4547 {
4548 if (nCursorHideCount==0)
4549 {
4550 DBG_ERROR("zuviel ShowCursor");
4551 return;
4552 }
4553
4554 if (nCursorHideCount==1)
4555 {
4556 // #i57745# Draw the cursor before setting the variable, in case the
4557 // GetSizePixel call from drawing causes a repaint (resize handler is called)
4558 DrawAutoFillMark();
4559 DrawCursor();
4560 }
4561
4562 --nCursorHideCount;
4563 }
4564
GetFocus()4565 void __EXPORT ScGridWindow::GetFocus()
4566 {
4567 ScTabViewShell* pViewShell = pViewData->GetViewShell();
4568 pViewShell->GotFocus();
4569 pViewShell->SetFormShellAtTop( sal_False ); // focus in GridWindow -> FormShell no longer on top
4570
4571 if (pViewShell->HasAccessibilityObjects())
4572 pViewShell->BroadcastAccessibility(ScAccGridWinFocusGotHint(eWhich, GetAccessible()));
4573
4574 if ( !SC_MOD()->IsFormulaMode() )
4575 {
4576 pViewShell->UpdateInputHandler();
4577 // StopMarking(); // falls Dialog (Fehler), weil dann kein ButtonUp
4578 // MO: nur wenn nicht im RefInput-Modus
4579 // -> GetFocus/MouseButtonDown-Reihenfolge
4580 // auf dem Mac
4581 }
4582
4583 Window::GetFocus();
4584 }
4585
LoseFocus()4586 void __EXPORT ScGridWindow::LoseFocus()
4587 {
4588 ScTabViewShell* pViewShell = pViewData->GetViewShell();
4589 pViewShell->LostFocus();
4590
4591 if (pViewShell->HasAccessibilityObjects())
4592 pViewShell->BroadcastAccessibility(ScAccGridWinFocusLostHint(eWhich, GetAccessible()));
4593
4594 Window::LoseFocus();
4595 }
4596
GetMousePosPixel() const4597 Point ScGridWindow::GetMousePosPixel() const { return aCurMousePos; }
4598
4599 //------------------------------------------------------------------------
4600
HitRangeFinder(const Point & rMouse,sal_Bool & rCorner,sal_uInt16 * pIndex,SCsCOL * pAddX,SCsROW * pAddY)4601 sal_Bool ScGridWindow::HitRangeFinder( const Point& rMouse, sal_Bool& rCorner,
4602 sal_uInt16* pIndex, SCsCOL* pAddX, SCsROW* pAddY )
4603 {
4604 sal_Bool bFound = sal_False;
4605 ScInputHandler* pHdl = SC_MOD()->GetInputHdl( pViewData->GetViewShell() );
4606 if (pHdl)
4607 {
4608 ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList();
4609 if ( pRangeFinder && !pRangeFinder->IsHidden() &&
4610 pRangeFinder->GetDocName() == pViewData->GetDocShell()->GetTitle() )
4611 {
4612 ScDocument* pDoc = pViewData->GetDocument();
4613 SCTAB nTab = pViewData->GetTabNo();
4614 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
4615 long nLayoutSign = bLayoutRTL ? -1 : 1;
4616
4617 SCsCOL nPosX;
4618 SCsROW nPosY;
4619 pViewData->GetPosFromPixel( rMouse.X(), rMouse.Y(), eWhich, nPosX, nPosY );
4620 // zusammengefasste (einzeln/Bereich) ???
4621 ScAddress aAddr( nPosX, nPosY, nTab );
4622
4623 // Point aNext = pViewData->GetScrPos( nPosX+1, nPosY+1, eWhich );
4624
4625 Point aNext = pViewData->GetScrPos( nPosX, nPosY, eWhich, sal_True );
4626 long nSizeXPix;
4627 long nSizeYPix;
4628 pViewData->GetMergeSizePixel( nPosX, nPosY, nSizeXPix, nSizeYPix );
4629 aNext.X() += nSizeXPix * nLayoutSign;
4630 aNext.Y() += nSizeYPix;
4631
4632 sal_Bool bCornerHor;
4633 if ( bLayoutRTL )
4634 bCornerHor = ( rMouse.X() >= aNext.X() && rMouse.X() <= aNext.X() + 8 );
4635 else
4636 bCornerHor = ( rMouse.X() >= aNext.X() - 8 && rMouse.X() <= aNext.X() );
4637
4638 sal_Bool bCellCorner = ( bCornerHor &&
4639 rMouse.Y() >= aNext.Y() - 8 && rMouse.Y() <= aNext.Y() );
4640 // corner is hit only if the mouse is within the cell
4641
4642 sal_uInt16 nCount = (sal_uInt16)pRangeFinder->Count();
4643 for (sal_uInt16 i=nCount; i;)
4644 {
4645 // rückwärts suchen, damit der zuletzt gepaintete Rahmen gefunden wird
4646 --i;
4647 ScRangeFindData* pData = pRangeFinder->GetObject(i);
4648 if ( pData && pData->aRef.In(aAddr) )
4649 {
4650 if (pIndex) *pIndex = i;
4651 if (pAddX) *pAddX = nPosX - pData->aRef.aStart.Col();
4652 if (pAddY) *pAddY = nPosY - pData->aRef.aStart.Row();
4653 bFound = sal_True;
4654 rCorner = ( bCellCorner && aAddr == pData->aRef.aEnd );
4655 break;
4656 }
4657 }
4658 }
4659 }
4660 return bFound;
4661 }
4662
4663 #define SCE_TOP 1
4664 #define SCE_BOTTOM 2
4665 #define SCE_LEFT 4
4666 #define SCE_RIGHT 8
4667 #define SCE_ALL 15
4668
lcl_PaintOneRange(ScDocShell * pDocSh,const ScRange & rRange,sal_uInt16 nEdges)4669 void lcl_PaintOneRange( ScDocShell* pDocSh, const ScRange& rRange, sal_uInt16 nEdges )
4670 {
4671 // der Range ist immer richtigherum
4672
4673 SCCOL nCol1 = rRange.aStart.Col();
4674 SCROW nRow1 = rRange.aStart.Row();
4675 SCTAB nTab1 = rRange.aStart.Tab();
4676 SCCOL nCol2 = rRange.aEnd.Col();
4677 SCROW nRow2 = rRange.aEnd.Row();
4678 SCTAB nTab2 = rRange.aEnd.Tab();
4679 sal_Bool bHiddenEdge = sal_False;
4680 SCROW nTmp;
4681
4682 ScDocument* pDoc = pDocSh->GetDocument();
4683 while ( nCol1 > 0 && pDoc->ColHidden(nCol1, nTab1) )
4684 {
4685 --nCol1;
4686 bHiddenEdge = sal_True;
4687 }
4688 while ( nCol2 < MAXCOL && pDoc->ColHidden(nCol2, nTab1) )
4689 {
4690 ++nCol2;
4691 bHiddenEdge = sal_True;
4692 }
4693 nTmp = pDoc->FirstVisibleRow(0, nRow1, nTab1);
4694 if (!ValidRow(nTmp))
4695 nTmp = 0;
4696 if (nTmp < nRow1)
4697 {
4698 nRow1 = nTmp;
4699 bHiddenEdge = sal_True;
4700 }
4701 nTmp = pDoc->FirstVisibleRow(nRow2, MAXROW, nTab1);
4702 if (!ValidRow(nTmp))
4703 nTmp = MAXROW;
4704 if (nTmp > nRow2)
4705 {
4706 nRow2 = nTmp;
4707 bHiddenEdge = sal_True;
4708 }
4709
4710 if ( nCol2 > nCol1 + 1 && nRow2 > nRow1 + 1 && !bHiddenEdge )
4711 {
4712 // nur an den Rändern entlang
4713 // (die Ecken werden evtl. zweimal getroffen)
4714
4715 if ( nEdges & SCE_TOP )
4716 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol2, nRow1, nTab2, PAINT_MARKS );
4717 if ( nEdges & SCE_LEFT )
4718 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol1, nRow2, nTab2, PAINT_MARKS );
4719 if ( nEdges & SCE_RIGHT )
4720 pDocSh->PostPaint( nCol2, nRow1, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
4721 if ( nEdges & SCE_BOTTOM )
4722 pDocSh->PostPaint( nCol1, nRow2, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
4723 }
4724 else // everything in one call
4725 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
4726 }
4727
lcl_PaintRefChanged(ScDocShell * pDocSh,const ScRange & rOldUn,const ScRange & rNewUn)4728 void lcl_PaintRefChanged( ScDocShell* pDocSh, const ScRange& rOldUn, const ScRange& rNewUn )
4729 {
4730 // Repaint für die Teile des Rahmens in Old, die bei New nicht mehr da sind
4731
4732 ScRange aOld = rOldUn;
4733 ScRange aNew = rNewUn;
4734 aOld.Justify();
4735 aNew.Justify();
4736
4737 if ( aOld.aStart == aOld.aEnd ) //! Tab ignorieren?
4738 pDocSh->GetDocument()->ExtendMerge(aOld);
4739 if ( aNew.aStart == aNew.aEnd ) //! Tab ignorieren?
4740 pDocSh->GetDocument()->ExtendMerge(aNew);
4741
4742 SCCOL nOldCol1 = aOld.aStart.Col();
4743 SCROW nOldRow1 = aOld.aStart.Row();
4744 SCCOL nOldCol2 = aOld.aEnd.Col();
4745 SCROW nOldRow2 = aOld.aEnd.Row();
4746 SCCOL nNewCol1 = aNew.aStart.Col();
4747 SCROW nNewRow1 = aNew.aStart.Row();
4748 SCCOL nNewCol2 = aNew.aEnd.Col();
4749 SCROW nNewRow2 = aNew.aEnd.Row();
4750 SCTAB nTab1 = aOld.aStart.Tab(); // Tab ändert sich nicht
4751 SCTAB nTab2 = aOld.aEnd.Tab();
4752
4753 if ( nNewRow2 < nOldRow1 || nNewRow1 > nOldRow2 ||
4754 nNewCol2 < nOldCol1 || nNewCol1 > nOldCol2 ||
4755 ( nNewCol1 != nOldCol1 && nNewRow1 != nOldRow1 &&
4756 nNewCol2 != nOldCol2 && nNewRow2 != nOldRow2 ) )
4757 {
4758 // komplett weggeschoben oder alle Seiten verändert
4759 // (Abfrage <= statt < geht schief bei einzelnen Zeilen/Spalten)
4760
4761 lcl_PaintOneRange( pDocSh, aOld, SCE_ALL );
4762 }
4763 else // alle vier Kanten einzeln testen
4764 {
4765 // oberer Teil
4766 if ( nNewRow1 < nOldRow1 ) // nur obere Linie löschen
4767 lcl_PaintOneRange( pDocSh, ScRange(
4768 nOldCol1, nOldRow1, nTab1, nOldCol2, nOldRow1, nTab2 ), SCE_ALL );
4769 else if ( nNewRow1 > nOldRow1 ) // den Teil, der oben wegkommt
4770 lcl_PaintOneRange( pDocSh, ScRange(
4771 nOldCol1, nOldRow1, nTab1, nOldCol2, nNewRow1-1, nTab2 ),
4772 SCE_ALL &~ SCE_BOTTOM );
4773
4774 // unterer Teil
4775 if ( nNewRow2 > nOldRow2 ) // nur untere Linie löschen
4776 lcl_PaintOneRange( pDocSh, ScRange(
4777 nOldCol1, nOldRow2, nTab1, nOldCol2, nOldRow2, nTab2 ), SCE_ALL );
4778 else if ( nNewRow2 < nOldRow2 ) // den Teil, der unten wegkommt
4779 lcl_PaintOneRange( pDocSh, ScRange(
4780 nOldCol1, nNewRow2+1, nTab1, nOldCol2, nOldRow2, nTab2 ),
4781 SCE_ALL &~ SCE_TOP );
4782
4783 // linker Teil
4784 if ( nNewCol1 < nOldCol1 ) // nur linke Linie löschen
4785 lcl_PaintOneRange( pDocSh, ScRange(
4786 nOldCol1, nOldRow1, nTab1, nOldCol1, nOldRow2, nTab2 ), SCE_ALL );
4787 else if ( nNewCol1 > nOldCol1 ) // den Teil, der links wegkommt
4788 lcl_PaintOneRange( pDocSh, ScRange(
4789 nOldCol1, nOldRow1, nTab1, nNewCol1-1, nOldRow2, nTab2 ),
4790 SCE_ALL &~ SCE_RIGHT );
4791
4792 // rechter Teil
4793 if ( nNewCol2 > nOldCol2 ) // nur rechte Linie löschen
4794 lcl_PaintOneRange( pDocSh, ScRange(
4795 nOldCol2, nOldRow1, nTab1, nOldCol2, nOldRow2, nTab2 ), SCE_ALL );
4796 else if ( nNewCol2 < nOldCol2 ) // den Teil, der rechts wegkommt
4797 lcl_PaintOneRange( pDocSh, ScRange(
4798 nNewCol2+1, nOldRow1, nTab1, nOldCol2, nOldRow2, nTab2 ),
4799 SCE_ALL &~ SCE_LEFT );
4800 }
4801 }
4802
RFMouseMove(const MouseEvent & rMEvt,sal_Bool bUp)4803 void ScGridWindow::RFMouseMove( const MouseEvent& rMEvt, sal_Bool bUp )
4804 {
4805 ScInputHandler* pHdl = SC_MOD()->GetInputHdl( pViewData->GetViewShell() );
4806 if (!pHdl)
4807 return;
4808 ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList();
4809 if (!pRangeFinder || nRFIndex >= pRangeFinder->Count())
4810 return;
4811 ScRangeFindData* pData = pRangeFinder->GetObject( nRFIndex );
4812 if (!pData)
4813 return;
4814
4815 // Mauszeiger
4816
4817 if (bRFSize)
4818 SetPointer( Pointer( POINTER_CROSS ) );
4819 else
4820 SetPointer( Pointer( POINTER_HAND ) );
4821
4822 // Scrolling
4823
4824 sal_Bool bTimer = sal_False;
4825 Point aPos = rMEvt.GetPosPixel();
4826 SCsCOL nDx = 0;
4827 SCsROW nDy = 0;
4828 if ( aPos.X() < 0 ) nDx = -1;
4829 if ( aPos.Y() < 0 ) nDy = -1;
4830 Size aSize = GetOutputSizePixel();
4831 if ( aPos.X() >= aSize.Width() )
4832 nDx = 1;
4833 if ( aPos.Y() >= aSize.Height() )
4834 nDy = 1;
4835 if ( nDx != 0 || nDy != 0 )
4836 {
4837 if ( nDx != 0) pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) );
4838 if ( nDy != 0 ) pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) );
4839 bTimer = sal_True;
4840 }
4841
4842 // Umschalten bei Fixierung (damit Scrolling funktioniert)
4843
4844 if ( eWhich == pViewData->GetActivePart() ) //??
4845 {
4846 if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX )
4847 if ( nDx > 0 )
4848 {
4849 if ( eWhich == SC_SPLIT_TOPLEFT )
4850 pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT );
4851 else if ( eWhich == SC_SPLIT_BOTTOMLEFT )
4852 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT );
4853 }
4854
4855 if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX )
4856 if ( nDy > 0 )
4857 {
4858 if ( eWhich == SC_SPLIT_TOPLEFT )
4859 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT );
4860 else if ( eWhich == SC_SPLIT_TOPRIGHT )
4861 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT );
4862 }
4863 }
4864
4865 // Verschieben
4866
4867 SCsCOL nPosX;
4868 SCsROW nPosY;
4869 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
4870
4871 ScRange aOld = pData->aRef;
4872 ScRange aNew = aOld;
4873 if ( bRFSize )
4874 {
4875 aNew.aEnd.SetCol((SCCOL)nPosX);
4876 aNew.aEnd.SetRow((SCROW)nPosY);
4877 }
4878 else
4879 {
4880 long nStartX = nPosX - nRFAddX;
4881 if ( nStartX < 0 ) nStartX = 0;
4882 long nStartY = nPosY - nRFAddY;
4883 if ( nStartY < 0 ) nStartY = 0;
4884 long nEndX = nStartX + aOld.aEnd.Col() - aOld.aStart.Col();
4885 if ( nEndX > MAXCOL )
4886 {
4887 nStartX -= ( nEndX - MAXROW );
4888 nEndX = MAXCOL;
4889 }
4890 long nEndY = nStartY + aOld.aEnd.Row() - aOld.aStart.Row();
4891 if ( nEndY > MAXROW )
4892 {
4893 nStartY -= ( nEndY - MAXROW );
4894 nEndY = MAXROW;
4895 }
4896
4897 aNew.aStart.SetCol((SCCOL)nStartX);
4898 aNew.aStart.SetRow((SCROW)nStartY);
4899 aNew.aEnd.SetCol((SCCOL)nEndX);
4900 aNew.aEnd.SetRow((SCROW)nEndY);
4901 }
4902
4903 if ( bUp )
4904 aNew.Justify(); // beim ButtonUp wieder richtigherum
4905
4906 if ( aNew != aOld )
4907 {
4908 pHdl->UpdateRange( nRFIndex, aNew );
4909
4910 ScDocShell* pDocSh = pViewData->GetDocShell();
4911
4912 // nur das neuzeichnen, was sich verändert hat...
4913 lcl_PaintRefChanged( pDocSh, aOld, aNew );
4914
4915 // neuen Rahmen nur drüberzeichnen (synchron)
4916 pDocSh->Broadcast( ScIndexHint( SC_HINT_SHOWRANGEFINDER, nRFIndex ) );
4917
4918 Update(); // was man bewegt, will man auch sofort sehen
4919 }
4920
4921 // Timer für Scrolling
4922
4923 if (bTimer)
4924 pViewData->GetView()->SetTimer( this, rMEvt ); // Event wiederholen
4925 else
4926 pViewData->GetView()->ResetTimer();
4927 }
4928
4929 //------------------------------------------------------------------------
4930
GetEditUrl(const Point & rPos,String * pName,String * pUrl,String * pTarget)4931 sal_Bool ScGridWindow::GetEditUrl( const Point& rPos,
4932 String* pName, String* pUrl, String* pTarget )
4933 {
4934 return GetEditUrlOrError( sal_False, rPos, pName, pUrl, pTarget );
4935 }
4936
GetEditUrlOrError(sal_Bool bSpellErr,const Point & rPos,String * pName,String * pUrl,String * pTarget)4937 sal_Bool ScGridWindow::GetEditUrlOrError( sal_Bool bSpellErr, const Point& rPos,
4938 String* pName, String* pUrl, String* pTarget )
4939 {
4940 //! nPosX/Y mit übergeben?
4941 SCsCOL nPosX;
4942 SCsROW nPosY;
4943 pViewData->GetPosFromPixel( rPos.X(), rPos.Y(), eWhich, nPosX, nPosY );
4944
4945 SCTAB nTab = pViewData->GetTabNo();
4946 ScDocShell* pDocSh = pViewData->GetDocShell();
4947 ScDocument* pDoc = pDocSh->GetDocument();
4948 ScBaseCell* pCell = NULL;
4949
4950 sal_Bool bFound = lcl_GetHyperlinkCell( pDoc, nPosX, nPosY, nTab, pCell );
4951 if( !bFound )
4952 return sal_False;
4953
4954 ScHideTextCursor aHideCursor( pViewData, eWhich ); // before GetEditArea (MapMode is changed)
4955
4956 const ScPatternAttr* pPattern = pDoc->GetPattern( nPosX, nPosY, nTab );
4957 // bForceToTop = sal_False, use the cell's real position
4958 Rectangle aEditRect = pViewData->GetEditArea( eWhich, nPosX, nPosY, this, pPattern, sal_False );
4959 if (rPos.Y() < aEditRect.Top())
4960 return sal_False;
4961
4962 // vertikal kann (noch) nicht angeklickt werden:
4963
4964 if (pPattern->GetCellOrientation() != SVX_ORIENTATION_STANDARD)
4965 return sal_False;
4966
4967 sal_Bool bBreak = ((SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK)).GetValue() ||
4968 ((SvxCellHorJustify)((const SvxHorJustifyItem&)pPattern->
4969 GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_BLOCK);
4970 SvxCellHorJustify eHorJust = (SvxCellHorJustify)((SvxHorJustifyItem&)pPattern->
4971 GetItem(ATTR_HOR_JUSTIFY)).GetValue();
4972
4973 // EditEngine
4974
4975 ScFieldEditEngine aEngine( pDoc->GetEditPool() );
4976 ScSizeDeviceProvider aProv(pDocSh);
4977 aEngine.SetRefDevice( aProv.GetDevice() );
4978 aEngine.SetRefMapMode( MAP_100TH_MM );
4979 SfxItemSet aDefault( aEngine.GetEmptyItemSet() );
4980 pPattern->FillEditItemSet( &aDefault );
4981 SvxAdjust eSvxAdjust = SVX_ADJUST_LEFT;
4982 switch (eHorJust)
4983 {
4984 case SVX_HOR_JUSTIFY_LEFT:
4985 case SVX_HOR_JUSTIFY_REPEAT: // nicht implementiert
4986 case SVX_HOR_JUSTIFY_STANDARD: // always Text if an EditCell type
4987 eSvxAdjust = SVX_ADJUST_LEFT;
4988 break;
4989 case SVX_HOR_JUSTIFY_RIGHT:
4990 eSvxAdjust = SVX_ADJUST_RIGHT;
4991 break;
4992 case SVX_HOR_JUSTIFY_CENTER:
4993 eSvxAdjust = SVX_ADJUST_CENTER;
4994 break;
4995 case SVX_HOR_JUSTIFY_BLOCK:
4996 eSvxAdjust = SVX_ADJUST_BLOCK;
4997 break;
4998 }
4999 aDefault.Put( SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) );
5000 aEngine.SetDefaults( aDefault );
5001 if (bSpellErr)
5002 aEngine.SetControlWord( aEngine.GetControlWord() | EE_CNTRL_ONLINESPELLING );
5003
5004 MapMode aEditMode = pViewData->GetLogicMode(eWhich); // ohne Drawing-Skalierung
5005 Rectangle aLogicEdit = PixelToLogic( aEditRect, aEditMode );
5006 long nThisColLogic = aLogicEdit.Right() - aLogicEdit.Left() + 1;
5007 Size aPaperSize = Size( 1000000, 1000000 );
5008 if(pCell->GetCellType() == CELLTYPE_FORMULA)
5009 {
5010 long nSizeX = 0;
5011 long nSizeY = 0;
5012 pViewData->GetMergeSizePixel( nPosX, nPosY, nSizeX, nSizeY );
5013 aPaperSize = Size(nSizeX, nSizeY );
5014 aPaperSize = PixelToLogic(aPaperSize);
5015 }
5016
5017 if (bBreak)
5018 aPaperSize.Width() = nThisColLogic;
5019 aEngine.SetPaperSize( aPaperSize );
5020
5021 ::std::auto_ptr< EditTextObject > pTextObj;
5022 const EditTextObject* pData;
5023 if(pCell->GetCellType() == CELLTYPE_EDIT)
5024 {
5025 ((ScEditCell*)pCell)->GetData(pData);
5026 if (pData)
5027 aEngine.SetText(*pData);
5028 }
5029 else // HyperLink Formula cell
5030 {
5031 pTextObj.reset((static_cast<ScFormulaCell*>(pCell))->CreateURLObject());
5032 if (pTextObj.get())
5033 aEngine.SetText(*pTextObj);
5034 }
5035
5036 long nStartX = aLogicEdit.Left();
5037
5038 long nTextWidth = aEngine.CalcTextWidth();
5039 long nTextHeight = aEngine.GetTextHeight();
5040 if ( nTextWidth < nThisColLogic )
5041 {
5042 if (eHorJust == SVX_HOR_JUSTIFY_RIGHT)
5043 nStartX += nThisColLogic - nTextWidth;
5044 else if (eHorJust == SVX_HOR_JUSTIFY_CENTER)
5045 nStartX += (nThisColLogic - nTextWidth) / 2;
5046 }
5047
5048 aLogicEdit.Left() = nStartX;
5049 if (!bBreak)
5050 aLogicEdit.Right() = nStartX + nTextWidth;
5051
5052 // There is one glitch when dealing with a hyperlink cell and
5053 // the cell content is NUMERIC. This defaults to right aligned and
5054 // we need to adjust accordingly.
5055 if(pCell->GetCellType() == CELLTYPE_FORMULA &&
5056 static_cast<ScFormulaCell*>(pCell)->IsValue() &&
5057 eHorJust == SVX_HOR_JUSTIFY_STANDARD)
5058 {
5059 aLogicEdit.Right() = aLogicEdit.Left() + nThisColLogic - 1;
5060 aLogicEdit.Left() = aLogicEdit.Right() - nTextWidth;
5061 }
5062 aLogicEdit.Bottom() = aLogicEdit.Top() + nTextHeight;
5063
5064 Point aLogicClick = PixelToLogic(rPos,aEditMode);
5065 if ( aLogicEdit.IsInside(aLogicClick) )
5066 {
5067 // aEngine.SetUpdateMode(sal_False);
5068 EditView aTempView( &aEngine, this );
5069 aTempView.SetOutputArea( aLogicEdit );
5070
5071 sal_Bool bRet = sal_False;
5072 MapMode aOld = GetMapMode();
5073 SetMapMode(aEditMode); // kein return mehr
5074
5075 if (bSpellErr) // Spelling-Fehler suchen
5076 {
5077 bRet = aTempView.IsWrongSpelledWordAtPos( rPos );
5078 if ( bRet )
5079 pViewData->GetView()->SetCursor( nPosX, nPosY ); // Cursor setzen
5080 }
5081 else // URL suchen
5082 {
5083 const SvxFieldItem* pFieldItem = aTempView.GetFieldUnderMousePointer();
5084
5085 if (pFieldItem)
5086 {
5087 const SvxFieldData* pField = pFieldItem->GetField();
5088 if ( pField && pField->ISA(SvxURLField) )
5089 {
5090 if ( pName || pUrl || pTarget )
5091 {
5092 const SvxURLField* pURLField = (const SvxURLField*)pField;
5093 if (pName)
5094 *pName = pURLField->GetRepresentation();
5095 if (pUrl)
5096 *pUrl = pURLField->GetURL();
5097 if (pTarget)
5098 *pTarget = pURLField->GetTargetFrame();
5099 }
5100 bRet = sal_True;
5101 }
5102 }
5103 }
5104
5105 SetMapMode(aOld);
5106
5107 // text cursor is restored in ScHideTextCursor dtor
5108
5109 return bRet;
5110 }
5111 return sal_False;
5112 }
5113
HasScenarioButton(const Point & rPosPixel,ScRange & rScenRange)5114 sal_Bool ScGridWindow::HasScenarioButton( const Point& rPosPixel, ScRange& rScenRange )
5115 {
5116 ScDocument* pDoc = pViewData->GetDocument();
5117 SCTAB nTab = pViewData->GetTabNo();
5118 SCTAB nTabCount = pDoc->GetTableCount();
5119 if ( nTab+1<nTabCount && pDoc->IsScenario(nTab+1) && !pDoc->IsScenario(nTab) )
5120 {
5121 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5122
5123 Size aButSize = pViewData->GetScenButSize();
5124 long nBWidth = aButSize.Width();
5125 if (!nBWidth)
5126 return sal_False; // noch kein Button gezeichnet -> da ist auch keiner
5127 long nBHeight = aButSize.Height();
5128 long nHSpace = (long)( SC_SCENARIO_HSPACE * pViewData->GetPPTX() );
5129
5130 //! Ranges an der Table cachen!!!!
5131
5132 ScMarkData aMarks;
5133 for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
5134 pDoc->MarkScenario( i, nTab, aMarks, sal_False, SC_SCENARIO_SHOWFRAME );
5135 ScRangeList aRanges;
5136 aMarks.FillRangeListWithMarks( &aRanges, sal_False );
5137
5138 sal_uLong nRangeCount = aRanges.Count();
5139 for (sal_uLong j=0; j<nRangeCount; j++)
5140 {
5141 ScRange aRange = *aRanges.GetObject(j);
5142 // Szenario-Rahmen immer dann auf zusammengefasste Zellen erweitern, wenn
5143 // dadurch keine neuen nicht-überdeckten Zellen mit umrandet werden
5144 pDoc->ExtendTotalMerge( aRange );
5145
5146 sal_Bool bTextBelow = ( aRange.aStart.Row() == 0 );
5147
5148 Point aButtonPos;
5149 if ( bTextBelow )
5150 {
5151 aButtonPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aEnd.Row()+1,
5152 eWhich, sal_True );
5153 }
5154 else
5155 {
5156 aButtonPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aStart.Row(),
5157 eWhich, sal_True );
5158 aButtonPos.Y() -= nBHeight;
5159 }
5160 if ( bLayoutRTL )
5161 aButtonPos.X() -= nHSpace - 1;
5162 else
5163 aButtonPos.X() -= nBWidth - nHSpace; // same for top or bottom
5164
5165 Rectangle aButRect( aButtonPos, Size(nBWidth,nBHeight) );
5166 if ( aButRect.IsInside( rPosPixel ) )
5167 {
5168 rScenRange = aRange;
5169 return sal_True;
5170 }
5171 }
5172 }
5173
5174 return sal_False;
5175 }
5176
UpdateVisibleRange()5177 void ScGridWindow::UpdateVisibleRange()
5178 {
5179 // #163911# Update the visible range outside of paint (called when switching sheets).
5180 // Use the same logic here as in ScGridWindow::Draw.
5181
5182 SCCOL nPosX = pViewData->GetPosX( eHWhich );
5183 SCROW nPosY = pViewData->GetPosY( eVWhich );
5184
5185 SCCOL nXRight = nPosX + pViewData->VisibleCellsX(eHWhich);
5186 if (nXRight > MAXCOL) nXRight = MAXCOL;
5187 SCROW nYBottom = nPosY + pViewData->VisibleCellsY(eVWhich);
5188 if (nYBottom > MAXROW) nYBottom = MAXROW;
5189
5190 // Store the current visible range.
5191 maVisibleRange.mnCol1 = nPosX;
5192 maVisibleRange.mnCol2 = nXRight;
5193 maVisibleRange.mnRow1 = nPosY;
5194 maVisibleRange.mnRow2 = nYBottom;
5195 }
5196
5197 // #114409#
DrawLayerCreated()5198 void ScGridWindow::DrawLayerCreated()
5199 {
5200 SetMapMode( GetDrawMapMode() );
5201
5202 // initially create overlay objects
5203 ImpCreateOverlayObjects();
5204 }
5205
5206 // #114409#
CursorChanged()5207 void ScGridWindow::CursorChanged()
5208 {
5209 // here the created OverlayObjects may be transformed in later versions. For
5210 // now, just re-create them
5211
5212 UpdateCursorOverlay();
5213 }
5214
5215 // #114409#
ImpCreateOverlayObjects()5216 void ScGridWindow::ImpCreateOverlayObjects()
5217 {
5218 UpdateCursorOverlay();
5219 UpdateSelectionOverlay();
5220 UpdateAutoFillOverlay();
5221 UpdateDragRectOverlay();
5222 UpdateHeaderOverlay();
5223 UpdateShrinkOverlay();
5224 }
5225
5226 // #114409#
ImpDestroyOverlayObjects()5227 void ScGridWindow::ImpDestroyOverlayObjects()
5228 {
5229 DeleteCursorOverlay();
5230 DeleteSelectionOverlay();
5231 DeleteAutoFillOverlay();
5232 DeleteDragRectOverlay();
5233 DeleteHeaderOverlay();
5234 DeleteShrinkOverlay();
5235 }
5236
UpdateAllOverlays()5237 void ScGridWindow::UpdateAllOverlays()
5238 {
5239 // delete and re-allocate all overlay objects
5240
5241 ImpDestroyOverlayObjects();
5242 ImpCreateOverlayObjects();
5243 }
5244
DeleteCursorOverlay()5245 void ScGridWindow::DeleteCursorOverlay()
5246 {
5247 DELETEZ( mpOOCursors );
5248 }
5249
UpdateCursorOverlay()5250 void ScGridWindow::UpdateCursorOverlay()
5251 {
5252 MapMode aDrawMode = GetDrawMapMode();
5253 MapMode aOldMode = GetMapMode();
5254 if ( aOldMode != aDrawMode )
5255 SetMapMode( aDrawMode );
5256
5257 // Existing OverlayObjects may be transformed in later versions.
5258 // For now, just re-create them.
5259
5260 DeleteCursorOverlay();
5261
5262 std::vector<Rectangle> aPixelRects;
5263
5264 // determine the cursor rectangles in pixels (moved from ScGridWindow::DrawCursor)
5265
5266 SCTAB nTab = pViewData->GetTabNo();
5267 SCCOL nX = pViewData->GetCurX();
5268 SCROW nY = pViewData->GetCurY();
5269
5270 if (!maVisibleRange.isInside(nX, nY))
5271 return;
5272
5273 // don't show the cursor in overlapped cells
5274
5275 ScDocument* pDoc = pViewData->GetDocument();
5276 const ScPatternAttr* pPattern = pDoc->GetPattern(nX,nY,nTab);
5277 const ScMergeFlagAttr& rMergeFlag = (const ScMergeFlagAttr&) pPattern->GetItem(ATTR_MERGE_FLAG);
5278 sal_Bool bOverlapped = rMergeFlag.IsOverlapped();
5279
5280 // left or above of the screen?
5281
5282 sal_Bool bVis = ( nX>=pViewData->GetPosX(eHWhich) && nY>=pViewData->GetPosY(eVWhich) );
5283 if (!bVis)
5284 {
5285 SCCOL nEndX = nX;
5286 SCROW nEndY = nY;
5287 const ScMergeAttr& rMerge = (const ScMergeAttr&) pPattern->GetItem(ATTR_MERGE);
5288 if (rMerge.GetColMerge() > 1)
5289 nEndX += rMerge.GetColMerge()-1;
5290 if (rMerge.GetRowMerge() > 1)
5291 nEndY += rMerge.GetRowMerge()-1;
5292 bVis = ( nEndX>=pViewData->GetPosX(eHWhich) && nEndY>=pViewData->GetPosY(eVWhich) );
5293 }
5294
5295 if ( bVis && !bOverlapped && !pViewData->HasEditView(eWhich) && pViewData->IsActive() )
5296 {
5297 Point aScrPos = pViewData->GetScrPos( nX, nY, eWhich, sal_True );
5298 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5299
5300 // completely right of/below the screen?
5301 // (test with logical start position in aScrPos)
5302 sal_Bool bMaybeVisible;
5303 if ( bLayoutRTL )
5304 bMaybeVisible = ( aScrPos.X() >= -2 && aScrPos.Y() >= -2 );
5305 else
5306 {
5307 Size aOutSize = GetOutputSizePixel();
5308 bMaybeVisible = ( aScrPos.X() <= aOutSize.Width() + 2 && aScrPos.Y() <= aOutSize.Height() + 2 );
5309 }
5310 if ( bMaybeVisible )
5311 {
5312 long nSizeXPix;
5313 long nSizeYPix;
5314 pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix );
5315
5316 if ( bLayoutRTL )
5317 aScrPos.X() -= nSizeXPix - 2; // move instead of mirroring
5318
5319 sal_Bool bFix = ( pViewData->GetHSplitMode() == SC_SPLIT_FIX ||
5320 pViewData->GetVSplitMode() == SC_SPLIT_FIX );
5321 if ( pViewData->GetActivePart()==eWhich || bFix )
5322 {
5323 aScrPos.X() -= 2;
5324 aScrPos.Y() -= 2;
5325 Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) );
5326
5327 aPixelRects.push_back(Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() ));
5328 aPixelRects.push_back(Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() ));
5329 aPixelRects.push_back(Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 ));
5330 aPixelRects.push_back(Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() ));
5331 }
5332 else
5333 {
5334 Rectangle aRect( aScrPos, Size( nSizeXPix - 1, nSizeYPix - 1 ) );
5335 aPixelRects.push_back( aRect );
5336 }
5337 }
5338 }
5339
5340 if ( aPixelRects.size() )
5341 {
5342 // #i70788# get the OverlayManager safely
5343 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5344
5345 if(pOverlayManager)
5346 {
5347 const Color aCursorColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
5348 std::vector< basegfx::B2DRange > aRanges;
5349 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5350
5351 for(sal_uInt32 a(0); a < aPixelRects.size(); a++)
5352 {
5353 const Rectangle aRA(aPixelRects[a]);
5354 basegfx::B2DRange aRB(aRA.Left(), aRA.Top(), aRA.Right() + 1, aRA.Bottom() + 1);
5355 aRB.transform(aTransform);
5356 aRanges.push_back(aRB);
5357 }
5358
5359 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5360 sdr::overlay::OVERLAY_SOLID,
5361 aCursorColor,
5362 aRanges,
5363 false);
5364
5365 pOverlayManager->add(*pOverlay);
5366 mpOOCursors = new ::sdr::overlay::OverlayObjectList;
5367 mpOOCursors->append(*pOverlay);
5368 }
5369 }
5370
5371 if ( aOldMode != aDrawMode )
5372 SetMapMode( aOldMode );
5373 }
5374
DeleteSelectionOverlay()5375 void ScGridWindow::DeleteSelectionOverlay()
5376 {
5377 DELETEZ( mpOOSelection );
5378 }
5379
UpdateSelectionOverlay()5380 void ScGridWindow::UpdateSelectionOverlay()
5381 {
5382 MapMode aDrawMode = GetDrawMapMode();
5383 MapMode aOldMode = GetMapMode();
5384 if ( aOldMode != aDrawMode )
5385 SetMapMode( aDrawMode );
5386
5387 DeleteSelectionOverlay();
5388 std::vector<Rectangle> aPixelRects;
5389 GetSelectionRects( aPixelRects );
5390
5391 if ( aPixelRects.size() && pViewData->IsActive() )
5392 {
5393 // #i70788# get the OverlayManager safely
5394 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5395
5396 if(pOverlayManager)
5397 {
5398 std::vector< basegfx::B2DRange > aRanges;
5399 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5400
5401 for(sal_uInt32 a(0); a < aPixelRects.size(); a++)
5402 {
5403 const Rectangle aRA(aPixelRects[a]);
5404 basegfx::B2DRange aRB(aRA.Left() - 1, aRA.Top() - 1, aRA.Right(), aRA.Bottom());
5405 aRB.transform(aTransform);
5406 aRanges.push_back(aRB);
5407 }
5408
5409 // get the system's hilight color
5410 const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
5411 const Color aHighlight(aSvtOptionsDrawinglayer.getHilightColor());
5412
5413 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5414 sdr::overlay::OVERLAY_TRANSPARENT,
5415 aHighlight,
5416 aRanges,
5417 true);
5418
5419 pOverlayManager->add(*pOverlay);
5420 mpOOSelection = new ::sdr::overlay::OverlayObjectList;
5421 mpOOSelection->append(*pOverlay);
5422 }
5423 }
5424
5425 if ( aOldMode != aDrawMode )
5426 SetMapMode( aOldMode );
5427 }
5428
DeleteAutoFillOverlay()5429 void ScGridWindow::DeleteAutoFillOverlay()
5430 {
5431 DELETEZ( mpOOAutoFill );
5432 mpAutoFillRect.reset();
5433 }
5434
UpdateAutoFillOverlay()5435 void ScGridWindow::UpdateAutoFillOverlay()
5436 {
5437 MapMode aDrawMode = GetDrawMapMode();
5438 MapMode aOldMode = GetMapMode();
5439 if ( aOldMode != aDrawMode )
5440 SetMapMode( aDrawMode );
5441
5442 DeleteAutoFillOverlay();
5443
5444 // get the AutoFill handle rectangle in pixels (moved from ScGridWindow::DrawAutoFillMark)
5445
5446 if ( bAutoMarkVisible && aAutoMarkPos.Tab() == pViewData->GetTabNo() &&
5447 !pViewData->HasEditView(eWhich) && pViewData->IsActive() )
5448 {
5449 SCCOL nX = aAutoMarkPos.Col();
5450 SCROW nY = aAutoMarkPos.Row();
5451
5452 if (!maVisibleRange.isInside(nX, nY))
5453 // Autofill mark is not visible. Bail out.
5454 return;
5455
5456 SCTAB nTab = pViewData->GetTabNo();
5457 ScDocument* pDoc = pViewData->GetDocument();
5458 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5459
5460 Point aFillPos = pViewData->GetScrPos( nX, nY, eWhich, sal_True );
5461 long nSizeXPix;
5462 long nSizeYPix;
5463 pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix );
5464 if ( bLayoutRTL )
5465 aFillPos.X() -= nSizeXPix + 3;
5466 else
5467 aFillPos.X() += nSizeXPix - 2;
5468
5469 aFillPos.Y() += nSizeYPix;
5470 aFillPos.Y() -= 2;
5471 mpAutoFillRect.reset(new Rectangle(aFillPos, Size(6, 6)));
5472
5473 // #i70788# get the OverlayManager safely
5474 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5475
5476 if(pOverlayManager)
5477 {
5478 const Color aHandleColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
5479 std::vector< basegfx::B2DRange > aRanges;
5480 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5481 basegfx::B2DRange aRB(mpAutoFillRect->Left(), mpAutoFillRect->Top(), mpAutoFillRect->Right() + 1, mpAutoFillRect->Bottom() + 1);
5482
5483 aRB.transform(aTransform);
5484 aRanges.push_back(aRB);
5485
5486 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5487 sdr::overlay::OVERLAY_SOLID,
5488 aHandleColor,
5489 aRanges,
5490 false);
5491
5492 pOverlayManager->add(*pOverlay);
5493 mpOOAutoFill = new ::sdr::overlay::OverlayObjectList;
5494 mpOOAutoFill->append(*pOverlay);
5495 }
5496
5497 if ( aOldMode != aDrawMode )
5498 SetMapMode( aOldMode );
5499 }
5500 }
5501
DeleteDragRectOverlay()5502 void ScGridWindow::DeleteDragRectOverlay()
5503 {
5504 DELETEZ( mpOODragRect );
5505 }
5506
UpdateDragRectOverlay()5507 void ScGridWindow::UpdateDragRectOverlay()
5508 {
5509 MapMode aDrawMode = GetDrawMapMode();
5510 MapMode aOldMode = GetMapMode();
5511 if ( aOldMode != aDrawMode )
5512 SetMapMode( aDrawMode );
5513
5514 DeleteDragRectOverlay();
5515
5516 // get the rectangles in pixels (moved from DrawDragRect)
5517
5518 if ( bDragRect || bPagebreakDrawn )
5519 {
5520 std::vector<Rectangle> aPixelRects;
5521
5522 SCCOL nX1 = bDragRect ? nDragStartX : aPagebreakDrag.aStart.Col();
5523 SCROW nY1 = bDragRect ? nDragStartY : aPagebreakDrag.aStart.Row();
5524 SCCOL nX2 = bDragRect ? nDragEndX : aPagebreakDrag.aEnd.Col();
5525 SCROW nY2 = bDragRect ? nDragEndY : aPagebreakDrag.aEnd.Row();
5526
5527 SCTAB nTab = pViewData->GetTabNo();
5528
5529 SCCOL nPosX = pViewData->GetPosX(WhichH(eWhich));
5530 SCROW nPosY = pViewData->GetPosY(WhichV(eWhich));
5531 if (nX1 < nPosX) nX1 = nPosX;
5532 if (nX2 < nPosX) nX2 = nPosX;
5533 if (nY1 < nPosY) nY1 = nPosY;
5534 if (nY2 < nPosY) nY2 = nPosY;
5535
5536 Point aScrPos( pViewData->GetScrPos( nX1, nY1, eWhich ) );
5537
5538 long nSizeXPix=0;
5539 long nSizeYPix=0;
5540 ScDocument* pDoc = pViewData->GetDocument();
5541 double nPPTX = pViewData->GetPPTX();
5542 double nPPTY = pViewData->GetPPTY();
5543 SCCOLROW i;
5544
5545 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5546 long nLayoutSign = bLayoutRTL ? -1 : 1;
5547
5548 if (ValidCol(nX2) && nX2>=nX1)
5549 for (i=nX1; i<=nX2; i++)
5550 nSizeXPix += ScViewData::ToPixel( pDoc->GetColWidth( static_cast<SCCOL>(i), nTab ), nPPTX );
5551 else
5552 {
5553 aScrPos.X() -= nLayoutSign;
5554 nSizeXPix += 2;
5555 }
5556
5557 if (ValidRow(nY2) && nY2>=nY1)
5558 for (i=nY1; i<=nY2; i++)
5559 nSizeYPix += ScViewData::ToPixel( pDoc->GetRowHeight( i, nTab ), nPPTY );
5560 else
5561 {
5562 aScrPos.Y() -= 1;
5563 nSizeYPix += 2;
5564 }
5565
5566 aScrPos.X() -= 2 * nLayoutSign;
5567 aScrPos.Y() -= 2;
5568 // Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) );
5569 Rectangle aRect( aScrPos.X(), aScrPos.Y(),
5570 aScrPos.X() + ( nSizeXPix + 2 ) * nLayoutSign, aScrPos.Y() + nSizeYPix + 2 );
5571 if ( bLayoutRTL )
5572 {
5573 aRect.Left() = aRect.Right(); // end position is left
5574 aRect.Right() = aScrPos.X();
5575 }
5576
5577 if ( meDragInsertMode == INS_CELLSDOWN )
5578 {
5579 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Top()+3, aRect.Left()+1, aRect.Bottom()-2 ) );
5580 aPixelRects.push_back( Rectangle( aRect.Right()-1, aRect.Top()+3, aRect.Right()-1, aRect.Bottom()-2 ) );
5581 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Top(), aRect.Right()-1, aRect.Top()+2 ) );
5582 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Bottom()-1, aRect.Right()-1, aRect.Bottom()-1 ) );
5583 }
5584 else if ( meDragInsertMode == INS_CELLSRIGHT )
5585 {
5586 aPixelRects.push_back( Rectangle( aRect.Left(), aRect.Top()+1, aRect.Left()+2, aRect.Bottom()-1 ) );
5587 aPixelRects.push_back( Rectangle( aRect.Right()-1, aRect.Top()+1, aRect.Right()-1, aRect.Bottom()-1 ) );
5588 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Top()+1, aRect.Right()-2, aRect.Top()+1 ) );
5589 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Bottom()-1, aRect.Right()-2, aRect.Bottom()-1 ) );
5590 }
5591 else
5592 {
5593 aPixelRects.push_back( Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() ) );
5594 aPixelRects.push_back( Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() ) );
5595 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 ) );
5596 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() ) );
5597 }
5598
5599 // #i70788# get the OverlayManager safely
5600 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5601
5602 if(pOverlayManager)
5603 {
5604 // Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
5605 std::vector< basegfx::B2DRange > aRanges;
5606 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5607
5608 for(sal_uInt32 a(0); a < aPixelRects.size(); a++)
5609 {
5610 const Rectangle aRA(aPixelRects[a]);
5611 basegfx::B2DRange aRB(aRA.Left(), aRA.Top(), aRA.Right() + 1, aRA.Bottom() + 1);
5612 aRB.transform(aTransform);
5613 aRanges.push_back(aRB);
5614 }
5615
5616 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5617 sdr::overlay::OVERLAY_INVERT,
5618 Color(COL_BLACK),
5619 aRanges,
5620 false);
5621
5622 pOverlayManager->add(*pOverlay);
5623 mpOODragRect = new ::sdr::overlay::OverlayObjectList;
5624 mpOODragRect->append(*pOverlay);
5625 }
5626 }
5627
5628 if ( aOldMode != aDrawMode )
5629 SetMapMode( aOldMode );
5630 }
5631
DeleteHeaderOverlay()5632 void ScGridWindow::DeleteHeaderOverlay()
5633 {
5634 DELETEZ( mpOOHeader );
5635 }
5636
UpdateHeaderOverlay()5637 void ScGridWindow::UpdateHeaderOverlay()
5638 {
5639 MapMode aDrawMode = GetDrawMapMode();
5640 MapMode aOldMode = GetMapMode();
5641 if ( aOldMode != aDrawMode )
5642 SetMapMode( aDrawMode );
5643
5644 DeleteHeaderOverlay();
5645
5646 // Pixel rectangle is in aInvertRect
5647 if ( !aInvertRect.IsEmpty() )
5648 {
5649 // #i70788# get the OverlayManager safely
5650 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5651
5652 if(pOverlayManager)
5653 {
5654 // Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
5655 std::vector< basegfx::B2DRange > aRanges;
5656 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5657 basegfx::B2DRange aRB(aInvertRect.Left(), aInvertRect.Top(), aInvertRect.Right() + 1, aInvertRect.Bottom() + 1);
5658
5659 aRB.transform(aTransform);
5660 aRanges.push_back(aRB);
5661
5662 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5663 sdr::overlay::OVERLAY_INVERT,
5664 Color(COL_BLACK),
5665 aRanges,
5666 false);
5667
5668 pOverlayManager->add(*pOverlay);
5669 mpOOHeader = new ::sdr::overlay::OverlayObjectList;
5670 mpOOHeader->append(*pOverlay);
5671 }
5672 }
5673
5674 if ( aOldMode != aDrawMode )
5675 SetMapMode( aOldMode );
5676 }
5677
DeleteShrinkOverlay()5678 void ScGridWindow::DeleteShrinkOverlay()
5679 {
5680 DELETEZ( mpOOShrink );
5681 }
5682
UpdateShrinkOverlay()5683 void ScGridWindow::UpdateShrinkOverlay()
5684 {
5685 MapMode aDrawMode = GetDrawMapMode();
5686 MapMode aOldMode = GetMapMode();
5687 if ( aOldMode != aDrawMode )
5688 SetMapMode( aDrawMode );
5689
5690 DeleteShrinkOverlay();
5691
5692 // get the rectangle in pixels
5693
5694 Rectangle aPixRect;
5695 ScRange aRange;
5696 SCTAB nTab = pViewData->GetTabNo();
5697 if ( pViewData->IsRefMode() && nTab >= pViewData->GetRefStartZ() && nTab <= pViewData->GetRefEndZ() &&
5698 pViewData->GetDelMark( aRange ) )
5699 {
5700 //! limit to visible area
5701 if ( aRange.aStart.Col() <= aRange.aEnd.Col() &&
5702 aRange.aStart.Row() <= aRange.aEnd.Row() )
5703 {
5704 Point aStart = pViewData->GetScrPos( aRange.aStart.Col(),
5705 aRange.aStart.Row(), eWhich );
5706 Point aEnd = pViewData->GetScrPos( aRange.aEnd.Col()+1,
5707 aRange.aEnd.Row()+1, eWhich );
5708 aEnd.X() -= 1;
5709 aEnd.Y() -= 1;
5710
5711 aPixRect = Rectangle( aStart,aEnd );
5712 }
5713 }
5714
5715 if ( !aPixRect.IsEmpty() )
5716 {
5717 // #i70788# get the OverlayManager safely
5718 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5719
5720 if(pOverlayManager)
5721 {
5722 // Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
5723 std::vector< basegfx::B2DRange > aRanges;
5724 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5725 basegfx::B2DRange aRB(aPixRect.Left(), aPixRect.Top(), aPixRect.Right() + 1, aPixRect.Bottom() + 1);
5726
5727 aRB.transform(aTransform);
5728 aRanges.push_back(aRB);
5729
5730 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5731 sdr::overlay::OVERLAY_INVERT,
5732 Color(COL_BLACK),
5733 aRanges,
5734 false);
5735
5736 pOverlayManager->add(*pOverlay);
5737 mpOOShrink = new ::sdr::overlay::OverlayObjectList;
5738 mpOOShrink->append(*pOverlay);
5739 }
5740 }
5741
5742 if ( aOldMode != aDrawMode )
5743 SetMapMode( aOldMode );
5744 }
5745
5746 // #i70788# central method to get the OverlayManager safely
getOverlayManager()5747 ::sdr::overlay::OverlayManager* ScGridWindow::getOverlayManager()
5748 {
5749 SdrPageView* pPV = pViewData->GetView()->GetScDrawView()->GetSdrPageView();
5750
5751 if(pPV)
5752 {
5753 SdrPageWindow* pPageWin = pPV->FindPageWindow( *this );
5754
5755 if ( pPageWin )
5756 {
5757 return (pPageWin->GetOverlayManager());
5758 }
5759 }
5760
5761 return 0L;
5762 }
5763
flushOverlayManager()5764 void ScGridWindow::flushOverlayManager()
5765 {
5766 // #i70788# get the OverlayManager safely
5767 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5768
5769 if(pOverlayManager)
5770 {
5771 pOverlayManager->flush();
5772 }
5773 }
5774
5775 /* vim: set noet sw=4 ts=4: */
5776