1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26
27 #include "scitems.hxx"
28
29 #include <memory> //auto_ptr
30 #include <editeng/adjitem.hxx>
31 #include <svx/algitem.hxx>
32 #include <svx/dbexch.hrc>
33 #include <editeng/editview.hxx>
34 #include <editeng/editstat.hxx>
35 #include <editeng/flditem.hxx>
36 #include <svx/svdetc.hxx>
37 #include <editeng/editobj.hxx>
38 #include <sfx2/dispatch.hxx>
39 #include <sfx2/viewfrm.hxx>
40 #include <sfx2/docfile.hxx>
41 #include <svl/stritem.hxx>
42 #include <svtools/svlbox.hxx>
43 #include <svtools/svtabbx.hxx>
44 #include <svl/urlbmk.hxx>
45 #include <tools/urlobj.hxx>
46 #include <vcl/cursor.hxx>
47 #include <vcl/sound.hxx>
48 #include <vcl/graph.hxx>
49 #include <vcl/hatch.hxx>
50 #include <sot/formats.hxx>
51 #include <sot/clsids.hxx>
52
53 #include <svx/svdview.hxx> // fuer Command-Handler (COMMAND_INSERTTEXT)
54 #include <editeng/outliner.hxx> // fuer Command-Handler (COMMAND_INSERTTEXT)
55 #include <svx/svditer.hxx>
56 #include <svx/svdocapt.hxx>
57 #include <svx/svdpagv.hxx>
58
59 #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
60 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
61 #include <com/sun/star/sheet/DataPilotTableHeaderData.hpp>
62 #include <com/sun/star/sheet/DataPilotTableResultData.hpp>
63 #include <com/sun/star/sheet/DataPilotTablePositionData.hpp>
64 #include <com/sun/star/sheet/DataPilotTablePositionType.hpp>
65 #include <com/sun/star/sheet/MemberResultFlags.hpp>
66 #include <com/sun/star/awt/KeyModifier.hpp>
67 #include <com/sun/star/awt/MouseButton.hpp>
68 #include <com/sun/star/script/vba/VBAEventId.hpp>
69 #include <com/sun/star/script/vba/XVBAEventProcessor.hpp>
70
71 #include "gridwin.hxx"
72 #include "tabvwsh.hxx"
73 #include "docsh.hxx"
74 #include "viewdata.hxx"
75 #include "tabview.hxx"
76 #include "select.hxx"
77 #include "scmod.hxx"
78 #include "document.hxx"
79 #include "attrib.hxx"
80 #include "dbcolect.hxx"
81 #include "stlpool.hxx"
82 #include "printfun.hxx"
83 #include "cbutton.hxx"
84 #include "sc.hrc"
85 #include "globstr.hrc"
86 #include "editutil.hxx"
87 #include "scresid.hxx"
88 #include "inputhdl.hxx"
89 #include "uiitems.hxx" // Filter-Dialog - auslagern !!!
90 #include "filtdlg.hxx"
91 #include "impex.hxx" // Sylk-ID fuer CB
92 #include "cell.hxx" // fuer Edit-Felder
93 #include "patattr.hxx"
94 #include "notemark.hxx"
95 #include "rfindlst.hxx"
96 #include "docpool.hxx"
97 #include "output.hxx"
98 #include "docfunc.hxx"
99 #include "dbdocfun.hxx"
100 #include "dpobject.hxx"
101 #include "dpoutput.hxx"
102 #include "transobj.hxx"
103 #include "drwtrans.hxx"
104 #include "seltrans.hxx"
105 #include "sizedev.hxx"
106 #include "AccessibilityHints.hxx"
107 #include "dpsave.hxx"
108 #include "viewuno.hxx"
109 #include "compiler.hxx"
110 #include "editable.hxx"
111 #include "fillinfo.hxx"
112 #include "scitems.hxx"
113 #include "userdat.hxx"
114 #include "drwlayer.hxx"
115 #include "attrib.hxx"
116 #include "validat.hxx"
117 #include "tabprotection.hxx"
118 #include "postit.hxx"
119 #include "dpcontrol.hxx"
120 #include "cellsuno.hxx"
121
122 #include "drawview.hxx"
123 #include <svx/sdrpagewindow.hxx>
124 #include <svx/sdr/overlay/overlaymanager.hxx>
125 #include <vcl/svapp.hxx>
126 #include <svx/sdr/overlay/overlayselection.hxx>
127
128 using namespace com::sun::star;
129 using ::com::sun::star::uno::Sequence;
130 using ::com::sun::star::uno::Any;
131
132 const sal_uInt8 SC_NESTEDBUTTON_NONE = 0;
133 const sal_uInt8 SC_NESTEDBUTTON_DOWN = 1;
134 const sal_uInt8 SC_NESTEDBUTTON_UP = 2;
135
136 #define SC_AUTOFILTER_ALL 0
137 #define SC_AUTOFILTER_TOP10 1
138 #define SC_AUTOFILTER_CUSTOM 2
139
140 // Modi fuer 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(); // auswaehlen
265 nDone = 1;
266 }
267 else if ( nKey == KEY_ESCAPE )
268 {
269 pGridWin->ClickExtern(); // loescht 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, enthaelt 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 noetig fuer 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: falsche 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 auswaehlen
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 //! Texthoehe 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 spaeter
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 Groesse feststeht
795
796 // Listbox fuellen
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; // fuer Rand
820 if ( nMaxText > 300 )
821 nMaxText = 300; // auch nicht uebertreiben (Pixel)
822
823 if (nMaxText > nSizeX) // Groesse auf benoetigte Groesse 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 naechste 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 spaeter
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 };
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 Groesse an Fenster anpassen
1023 //! vorher Abfrage, ob die Eintraege 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 Eintraege 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 naechste 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 Eintraege 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 ) // loeschen 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
1315 {
1316 rNewEntry.eOp = SC_EQUAL;
1317 *rNewEntry.pStr = aValue;
1318 }
1319 if (nQueryPos > 0)
1320 rNewEntry.eConnect = SC_AND;
1321 }
1322 else
1323 {
1324 if (bFound)
1325 aParam.DeleteQuery(nQueryPos);
1326 }
1327
1328 // #100597# end edit mode - like in ScCellShell::ExecuteDB
1329 if ( pViewData->HasEditView( pViewData->GetActivePart() ) )
1330 {
1331 SC_MOD()->InputEnterHandler();
1332 pViewData->GetViewShell()->UpdateInputHandler();
1333 }
1334
1335 pViewData->GetView()->Query( aParam, NULL, sal_True );
1336 pDBData->SetQueryParam( aParam ); // speichern
1337 }
1338 else // "Zuviele Bedingungen"
1339 pViewData->GetView()->ErrorMessage( STR_FILTER_TOOMANY );
1340 }
1341 }
1342 else
1343 {
1344 DBG_ERROR("Wo ist der Datenbankbereich?");
1345 }
1346 }
1347
SetPointer(const Pointer & rPointer)1348 void ScGridWindow::SetPointer( const Pointer& rPointer )
1349 {
1350 nCurrentPointer = 0;
1351 Window::SetPointer( rPointer );
1352 }
1353
MoveMouseStatus(ScGridWindow & rDestWin)1354 void ScGridWindow::MoveMouseStatus( ScGridWindow& rDestWin )
1355 {
1356 if (nButtonDown)
1357 {
1358 rDestWin.nButtonDown = nButtonDown;
1359 rDestWin.nMouseStatus = nMouseStatus;
1360 }
1361
1362 if (bRFMouse)
1363 {
1364 rDestWin.bRFMouse = bRFMouse;
1365 rDestWin.bRFSize = bRFSize;
1366 rDestWin.nRFIndex = nRFIndex;
1367 rDestWin.nRFAddX = nRFAddX;
1368 rDestWin.nRFAddY = nRFAddY;
1369 bRFMouse = sal_False;
1370 }
1371
1372 if (nPagebreakMouse)
1373 {
1374 rDestWin.nPagebreakMouse = nPagebreakMouse;
1375 rDestWin.nPagebreakBreak = nPagebreakBreak;
1376 rDestWin.nPagebreakPrev = nPagebreakPrev;
1377 rDestWin.aPagebreakSource = aPagebreakSource;
1378 rDestWin.aPagebreakDrag = aPagebreakDrag;
1379 nPagebreakMouse = SC_PD_NONE;
1380 }
1381 }
1382
TestMouse(const MouseEvent & rMEvt,sal_Bool bAction)1383 sal_Bool ScGridWindow::TestMouse( const MouseEvent& rMEvt, sal_Bool bAction )
1384 {
1385 // MouseEvent buttons must only be checked if bAction==TRUE
1386 // to allow changing the mouse pointer in MouseMove,
1387 // but not start AutoFill with right button (#74229#).
1388 // with bAction==sal_True, SetFillMode / SetDragMode is called
1389
1390 if ( bAction && !rMEvt.IsLeft() )
1391 return sal_False;
1392
1393 sal_Bool bNewPointer = sal_False;
1394
1395 SfxInPlaceClient* pClient = pViewData->GetViewShell()->GetIPClient();
1396 sal_Bool bOleActive = ( pClient && pClient->IsObjectInPlaceActive() );
1397
1398 if ( pViewData->IsActive() && !bOleActive )
1399 {
1400 ScDocument* pDoc = pViewData->GetDocument();
1401 SCTAB nTab = pViewData->GetTabNo();
1402 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1403
1404 // Auto-Fill
1405
1406 ScRange aMarkRange;
1407 if (pViewData->GetSimpleArea( aMarkRange ) == SC_MARK_SIMPLE)
1408 {
1409 if (aMarkRange.aStart.Tab() == pViewData->GetTabNo() && mpAutoFillRect)
1410 {
1411 Point aMousePos = rMEvt.GetPosPixel();
1412 if (mpAutoFillRect->IsInside(aMousePos))
1413 {
1414 SetPointer( Pointer( POINTER_CROSS ) ); //! dickeres Kreuz ?
1415 if (bAction)
1416 {
1417 SCCOL nX = aMarkRange.aEnd.Col();
1418 SCROW nY = aMarkRange.aEnd.Row();
1419
1420 if ( lcl_IsEditableMatrix( pViewData->GetDocument(), aMarkRange ) )
1421 pViewData->SetDragMode(
1422 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nX, nY, SC_FILL_MATRIX );
1423 else
1424 pViewData->SetFillMode(
1425 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nX, nY );
1426
1427 // #108266# The simple selection must also be recognized when dragging,
1428 // where the Marking flag is set and MarkToSimple won't work anymore.
1429 pViewData->GetMarkData().MarkToSimple();
1430 }
1431 bNewPointer = sal_True;
1432 }
1433 }
1434 }
1435
1436 // Embedded-Rechteck
1437
1438 if (pDoc->IsEmbedded())
1439 {
1440 ScRange aRange;
1441 pDoc->GetEmbedded( aRange );
1442 if ( pViewData->GetTabNo() == aRange.aStart.Tab() )
1443 {
1444 Point aStartPos = pViewData->GetScrPos( aRange.aStart.Col(), aRange.aStart.Row(), eWhich );
1445 Point aEndPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aEnd.Row()+1, eWhich );
1446 Point aMousePos = rMEvt.GetPosPixel();
1447 if ( bLayoutRTL )
1448 {
1449 aStartPos.X() += 2;
1450 aEndPos.X() += 2;
1451 }
1452 sal_Bool bTop = ( aMousePos.X() >= aStartPos.X()-3 && aMousePos.X() <= aStartPos.X()+1 &&
1453 aMousePos.Y() >= aStartPos.Y()-3 && aMousePos.Y() <= aStartPos.Y()+1 );
1454 sal_Bool bBottom = ( aMousePos.X() >= aEndPos.X()-3 && aMousePos.X() <= aEndPos.X()+1 &&
1455 aMousePos.Y() >= aEndPos.Y()-3 && aMousePos.Y() <= aEndPos.Y()+1 );
1456 if ( bTop || bBottom )
1457 {
1458 SetPointer( Pointer( POINTER_CROSS ) );
1459 if (bAction)
1460 {
1461 sal_uInt8 nMode = bTop ? SC_FILL_EMBED_LT : SC_FILL_EMBED_RB;
1462 pViewData->SetDragMode(
1463 aRange.aStart.Col(), aRange.aStart.Row(),
1464 aRange.aEnd.Col(), aRange.aEnd.Row(), nMode );
1465 }
1466 bNewPointer = sal_True;
1467 }
1468 }
1469 }
1470 }
1471
1472 if (!bNewPointer && bAction)
1473 {
1474 // SetPointer( POINTER_ARROW ); // in Fu...
1475 pViewData->ResetFillMode();
1476 }
1477
1478 return bNewPointer;
1479 }
1480
MouseButtonDown(const MouseEvent & rMEvt)1481 void __EXPORT ScGridWindow::MouseButtonDown( const MouseEvent& rMEvt )
1482 {
1483 nNestedButtonState = SC_NESTEDBUTTON_DOWN;
1484
1485 HandleMouseButtonDown( rMEvt );
1486
1487 if ( nNestedButtonState == SC_NESTEDBUTTON_UP )
1488 {
1489 // #i41690# If an object is deactivated from MouseButtonDown, it might reschedule,
1490 // so MouseButtonUp comes before the MouseButtonDown call is finished. In this case,
1491 // simulate another MouseButtonUp call, so the selection state is consistent.
1492
1493 nButtonDown = rMEvt.GetButtons();
1494 FakeButtonUp();
1495
1496 if ( IsTracking() )
1497 EndTracking(); // normally done in VCL as part of MouseButtonUp handling
1498 }
1499 nNestedButtonState = SC_NESTEDBUTTON_NONE;
1500 }
1501
HandleMouseButtonDown(const MouseEvent & rMEvt)1502 void ScGridWindow::HandleMouseButtonDown( const MouseEvent& rMEvt )
1503 {
1504 // We have to check if a context menu is shown and we have an UI
1505 // active inplace client. In that case we have to ignore the event.
1506 // Otherwise we would crash (context menu has been
1507 // opened by inplace client and we would deactivate the inplace client,
1508 // the contex menu is closed by VCL asynchronously which in the end
1509 // would work on deleted objects or the context menu has no parent anymore)
1510 // See #126086# and #128122#
1511 SfxViewShell* pViewSh = pViewData->GetViewShell();
1512 SfxInPlaceClient* pClient = pViewSh->GetIPClient();
1513 if ( pClient &&
1514 pClient->IsObjectInPlaceActive() &&
1515 PopupMenu::IsInExecute() )
1516 return;
1517
1518 aCurMousePos = rMEvt.GetPosPixel();
1519
1520 // Filter-Popup beendet sich mit eigenem Mausklick, nicht erst beim Klick
1521 // in das GridWindow, darum ist die folgende Abfrage nicht mehr noetig:
1522 #if 0
1523 // merken, dass FilterBox geloescht wird, damit sichergestellt
1524 // ist, dass in diesem Handler nicht an gleicher Stelle wieder
1525 // eine neue geoeffnet wird.
1526 sal_Bool bWasFilterBox = ( pFilterBox != NULL &&
1527 ((Window*)pFilterBox)->IsVisible() &&
1528 !pFilterBox->IsDataSelect() );
1529 SCCOL nOldColFBox = bWasFilterBox ? pFilterBox->GetCol() : 0;
1530 SCROW nOldRowFBox = bWasFilterBox ? pFilterBox->GetRow() : 0;
1531 #endif
1532
1533 ClickExtern(); // loescht FilterBox, wenn vorhanden
1534
1535 HideNoteMarker(); // Notiz-Anzeige
1536
1537 bEEMouse = sal_False;
1538
1539 ScModule* pScMod = SC_MOD();
1540 if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
1541 {
1542 Sound::Beep();
1543 return;
1544 }
1545
1546 pScActiveViewShell = pViewData->GetViewShell(); // falls auf Link geklickt wird
1547 nScClickMouseModifier = rMEvt.GetModifier(); // um Control-Klick immer zu erkennen
1548
1549 sal_Bool bDetective = pViewData->GetViewShell()->IsAuditShell();
1550 sal_Bool bRefMode = pViewData->IsRefMode(); // Referenz angefangen
1551 sal_Bool bFormulaMode = pScMod->IsFormulaMode(); // naechster Klick -> Referenz
1552 sal_Bool bEditMode = pViewData->HasEditView(eWhich); // auch bei Mode==SC_INPUT_TYPE
1553 sal_Bool bDouble = (rMEvt.GetClicks() == 2);
1554
1555 // DeactivateIP passiert nur noch bei MarkListHasChanged
1556
1557 // im GrabFocus Aufruf kann eine Fehlermeldung hochkommen
1558 // (z.B. beim Umbenennen von Tabellen per Tab-Reiter)
1559
1560 if ( !nButtonDown || !bDouble ) // single (first) click is always valid
1561 nButtonDown = rMEvt.GetButtons(); // set nButtonDown first, so StopMarking works
1562
1563 // pViewData->GetViewShell()->GetViewFrame()->GetWindow().GrabFocus();
1564 if ( ( bEditMode && pViewData->GetActivePart() == eWhich ) || !bFormulaMode )
1565 GrabFocus();
1566
1567 // #i31846# need to cancel a double click if the first click has set the "ignore" state,
1568 // but a single (first) click is always valid
1569 if ( nMouseStatus == SC_GM_IGNORE && bDouble )
1570 {
1571 nButtonDown = 0;
1572 nMouseStatus = SC_GM_NONE;
1573 return;
1574 }
1575
1576 if ( bDetective ) // Detektiv-Fuell-Modus
1577 {
1578 if ( rMEvt.IsLeft() && !rMEvt.GetModifier() )
1579 {
1580 Point aPos = rMEvt.GetPosPixel();
1581 SCsCOL nPosX;
1582 SCsROW nPosY;
1583 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
1584
1585 SfxInt16Item aPosXItem( SID_RANGE_COL, nPosX );
1586 SfxInt32Item aPosYItem( SID_RANGE_ROW, nPosY );
1587 pViewData->GetDispatcher().Execute( SID_FILL_SELECT, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD,
1588 &aPosXItem, &aPosYItem, (void*)0L );
1589
1590 }
1591 nButtonDown = 0;
1592 nMouseStatus = SC_GM_NONE;
1593 return;
1594 }
1595
1596 if (!bDouble)
1597 nMouseStatus = SC_GM_NONE;
1598
1599 if (!bFormulaMode)
1600 {
1601 if ( pViewData->GetActivePart() != eWhich )
1602 pViewData->GetView()->ActivatePart( eWhich );
1603 }
1604 else
1605 {
1606 ScViewSelectionEngine* pSelEng = pViewData->GetView()->GetSelEngine();
1607 pSelEng->SetWindow(this);
1608 pSelEng->SetWhich(eWhich);
1609 pSelEng->SetVisibleArea( Rectangle(Point(), GetOutputSizePixel()) );
1610 }
1611
1612 if (bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()))
1613 {
1614 Point aPos = rMEvt.GetPosPixel();
1615 SCsCOL nPosX;
1616 SCsROW nPosY;
1617 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
1618
1619 EditView* pEditView;
1620 SCCOL nEditCol;
1621 SCROW nEditRow;
1622 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
1623 SCCOL nEndCol = pViewData->GetEditEndCol();
1624 SCROW nEndRow = pViewData->GetEditEndRow();
1625
1626 if ( nPosX >= (SCsCOL) nEditCol && nPosX <= (SCsCOL) nEndCol &&
1627 nPosY >= (SCsROW) nEditRow && nPosY <= (SCsROW) nEndRow )
1628 {
1629 // #53966# beim Klick in die Tabellen-EditView immer den Focus umsetzen
1630 if (bFormulaMode) // sonst ist es oben schon passiert
1631 GrabFocus();
1632
1633 pScMod->SetInputMode( SC_INPUT_TABLE );
1634 bEEMouse = sal_True;
1635 bEditMode = pEditView->MouseButtonDown( rMEvt );
1636 return;
1637 }
1638 }
1639
1640 if (pScMod->GetIsWaterCan())
1641 {
1642 //! was is mit'm Mac ???
1643 if ( rMEvt.GetModifier() + rMEvt.GetButtons() == MOUSE_RIGHT )
1644 {
1645 nMouseStatus = SC_GM_WATERUNDO;
1646 return;
1647 }
1648 }
1649
1650 // Reihenfolge passend zum angezeigten Cursor:
1651 // RangeFinder, AutoFill, PageBreak, Drawing
1652
1653 if ( HitRangeFinder( rMEvt.GetPosPixel(), bRFSize, &nRFIndex, &nRFAddX, &nRFAddY ) )
1654 {
1655 bRFMouse = sal_True; // die anderen Variablen sind oben initialisiert
1656
1657 if ( pViewData->GetActivePart() != eWhich )
1658 pViewData->GetView()->ActivatePart( eWhich ); //! schon oben immer ???
1659
1660 // CaptureMouse();
1661 StartTracking();
1662 return;
1663 }
1664
1665 sal_Bool bCrossPointer = TestMouse( rMEvt, sal_True );
1666 if ( bCrossPointer )
1667 {
1668 if ( bDouble )
1669 pViewData->GetView()->FillCrossDblClick();
1670 else
1671 pScMod->InputEnterHandler(); // Autofill etc.
1672 }
1673
1674 if ( !bCrossPointer )
1675 {
1676 nPagebreakMouse = HitPageBreak( rMEvt.GetPosPixel(), &aPagebreakSource,
1677 &nPagebreakBreak, &nPagebreakPrev );
1678 if (nPagebreakMouse)
1679 {
1680 bPagebreakDrawn = sal_False;
1681 // CaptureMouse();
1682 StartTracking();
1683 PagebreakMove( rMEvt, sal_False );
1684 return;
1685 }
1686 }
1687
1688 if (!bFormulaMode && !bEditMode && rMEvt.IsLeft())
1689 {
1690 if ( !bCrossPointer && DrawMouseButtonDown(rMEvt) )
1691 {
1692 //if (DrawHasMarkedObj())
1693 // pViewData->GetViewShell()->SetDrawShellOrSub(); // Draw-Objekt selektiert
1694 return;
1695 }
1696
1697 pViewData->GetViewShell()->SetDrawShell( sal_False ); // kein Draw-Objekt selektiert
1698
1699 // TestMouse schon oben passiert
1700 }
1701
1702 Point aPos = rMEvt.GetPosPixel();
1703 SCsCOL nPosX;
1704 SCsROW nPosY;
1705 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
1706 SCTAB nTab = pViewData->GetTabNo();
1707 ScDocument* pDoc = pViewData->GetDocument();
1708
1709
1710 //
1711 // AutoFilter buttons
1712 //
1713
1714 if ( !bDouble && !bFormulaMode && rMEvt.IsLeft() )
1715 {
1716 SCsCOL nRealPosX;
1717 SCsROW nRealPosY;
1718 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nRealPosX, nRealPosY, false );//the real row/col
1719 ScMergeFlagAttr* pRealPosAttr = (ScMergeFlagAttr*)
1720 pDoc->GetAttr( nRealPosX, nRealPosY, nTab, ATTR_MERGE_FLAG );
1721 ScMergeFlagAttr* pAttr = (ScMergeFlagAttr*)
1722 pDoc->GetAttr( nPosX, nPosY, nTab, ATTR_MERGE_FLAG );
1723 if( pRealPosAttr->HasAutoFilter() )
1724 {
1725 SC_MOD()->InputEnterHandler();
1726 if (DoAutoFilterButton( nRealPosX, nRealPosY, rMEvt))
1727 return;
1728 }
1729 if( pAttr->HasAutoFilter() )
1730 {
1731 SC_MOD()->InputEnterHandler(); //Add for i85305
1732 if (DoAutoFilterButton( nPosX, nPosY, rMEvt))
1733 return;
1734 }
1735 if (pAttr->HasButton())
1736 {
1737 DoPushButton( nPosX, nPosY, rMEvt ); // setzt evtl. bPivotMouse / bDPMouse
1738 return;
1739 }
1740
1741 // List Validity drop-down button
1742
1743 if ( bListValButton )
1744 {
1745 Rectangle aButtonRect = GetListValButtonRect( aListValPos );
1746 if ( aButtonRect.IsInside( aPos ) )
1747 {
1748 DoAutoFilterMenue( aListValPos.Col(), aListValPos.Row(), sal_True );
1749
1750 nMouseStatus = SC_GM_FILTER; // not set in DoAutoFilterMenue for bDataSelect
1751 CaptureMouse();
1752 return;
1753 }
1754 }
1755 }
1756
1757 //
1758 // scenario selection
1759 //
1760
1761 ScRange aScenRange;
1762 if ( rMEvt.IsLeft() && HasScenarioButton( aPos, aScenRange ) )
1763 {
1764 DoScenarioMenue( aScenRange );
1765 return;
1766 }
1767
1768 //
1769 // Doppelklick angefangen ?
1770 //
1771
1772 // StopMarking kann aus DrawMouseButtonDown gerufen werden
1773
1774 if ( nMouseStatus != SC_GM_IGNORE && !bRefMode )
1775 {
1776 if ( bDouble && !bCrossPointer )
1777 {
1778 if (nMouseStatus == SC_GM_TABDOWN)
1779 nMouseStatus = SC_GM_DBLDOWN;
1780 }
1781 else
1782 nMouseStatus = SC_GM_TABDOWN;
1783 }
1784
1785 //
1786 // Links in Edit-Zellen
1787 //
1788
1789 sal_Bool bAlt = rMEvt.IsMod2();
1790 if ( !bAlt && rMEvt.IsLeft() &&
1791 GetEditUrl(rMEvt.GetPosPixel()) ) // Klick auf Link: Cursor nicht bewegen
1792 {
1793 SetPointer( Pointer( POINTER_REFHAND ) );
1794 nMouseStatus = SC_GM_URLDOWN; // auch nur dann beim ButtonUp ausfuehren
1795 return;
1796 }
1797
1798 //
1799 // Gridwin - SelectionEngine
1800 //
1801
1802 if ( rMEvt.IsLeft() )
1803 {
1804 ScViewSelectionEngine* pSelEng = pViewData->GetView()->GetSelEngine();
1805 pSelEng->SetWindow(this);
1806 pSelEng->SetWhich(eWhich);
1807 pSelEng->SetVisibleArea( Rectangle(Point(), GetOutputSizePixel()) );
1808
1809 // SelMouseButtonDown an der View setzt noch das bMoveIsShift Flag
1810 if ( pViewData->GetView()->SelMouseButtonDown( rMEvt ) )
1811 {
1812 if (IsMouseCaptured())
1813 {
1814 // Tracking statt CaptureMouse, damit sauber abgebrochen werden kann
1815 //! Irgendwann sollte die SelectionEngine selber StartTracking rufen!?!
1816 ReleaseMouse();
1817 StartTracking();
1818 }
1819 pViewData->GetMarkData().SetMarking(sal_True);
1820 return;
1821 }
1822 }
1823 }
1824
MouseButtonUp(const MouseEvent & rMEvt)1825 void __EXPORT ScGridWindow::MouseButtonUp( const MouseEvent& rMEvt )
1826 {
1827 aCurMousePos = rMEvt.GetPosPixel();
1828 ScDocument* pDoc = pViewData->GetDocument();
1829 ScMarkData& rMark = pViewData->GetMarkData();
1830
1831 // #i41690# detect a MouseButtonUp call from within MouseButtonDown
1832 // (possible through Reschedule from storing an OLE object that is deselected)
1833
1834 if ( nNestedButtonState == SC_NESTEDBUTTON_DOWN )
1835 nNestedButtonState = SC_NESTEDBUTTON_UP;
1836
1837 if (nButtonDown != rMEvt.GetButtons())
1838 nMouseStatus = SC_GM_IGNORE; // reset und return
1839
1840 nButtonDown = 0;
1841
1842 if (nMouseStatus == SC_GM_IGNORE)
1843 {
1844 nMouseStatus = SC_GM_NONE;
1845 // Selection-Engine: Markieren abbrechen
1846 pViewData->GetView()->GetSelEngine()->Reset();
1847 rMark.SetMarking(sal_False);
1848 if (pViewData->IsAnyFillMode())
1849 {
1850 pViewData->GetView()->StopRefMode();
1851 pViewData->ResetFillMode();
1852 }
1853 StopMarking();
1854 DrawEndAction(); // Markieren/Verschieben auf Drawing-Layer abbrechen
1855 ReleaseMouse();
1856 return;
1857 }
1858
1859 if (nMouseStatus == SC_GM_FILTER)
1860 {
1861 if ( pFilterBox && pFilterBox->GetMode() == SC_FILTERBOX_FILTER )
1862 {
1863 if (mpFilterButton.get())
1864 {
1865 bool bFilterActive = IsAutoFilterActive(
1866 pFilterBox->GetCol(), pFilterBox->GetRow(), pViewData->GetTabNo() );
1867
1868 mpFilterButton->setHasHiddenMember(bFilterActive);
1869 mpFilterButton->setPopupPressed(false);
1870 HideCursor();
1871 mpFilterButton->draw();
1872 ShowCursor();
1873 }
1874 }
1875 nMouseStatus = SC_GM_NONE;
1876 ReleaseMouse();
1877 return; // da muss nix mehr passieren
1878 }
1879
1880 ScModule* pScMod = SC_MOD();
1881 if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
1882 return;
1883
1884 SfxBindings& rBindings = pViewData->GetBindings();
1885 if (bEEMouse && pViewData->HasEditView( eWhich ))
1886 {
1887 EditView* pEditView;
1888 SCCOL nEditCol;
1889 SCROW nEditRow;
1890 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
1891 pEditView->MouseButtonUp( rMEvt );
1892
1893 if ( rMEvt.IsMiddle() &&
1894 GetSettings().GetMouseSettings().GetMiddleButtonAction() == MOUSE_MIDDLE_PASTESELECTION )
1895 {
1896 // EditView may have pasted from selection
1897 pScMod->InputChanged( pEditView );
1898 }
1899 else
1900 pScMod->InputSelection( pEditView ); // parentheses etc.
1901
1902 pViewData->GetView()->InvalidateAttribs();
1903 rBindings.Invalidate( SID_HYPERLINK_GETLINK );
1904 bEEMouse = sal_False;
1905 return;
1906 }
1907
1908 if (bDPMouse)
1909 {
1910 DPMouseButtonUp( rMEvt ); // resets bDPMouse
1911 return;
1912 }
1913
1914 if (bRFMouse)
1915 {
1916 RFMouseMove( rMEvt, sal_True ); // Range wieder richtigherum
1917 bRFMouse = sal_False;
1918 SetPointer( Pointer( POINTER_ARROW ) );
1919 ReleaseMouse();
1920 return;
1921 }
1922
1923 if (nPagebreakMouse)
1924 {
1925 PagebreakMove( rMEvt, sal_True );
1926 nPagebreakMouse = SC_PD_NONE;
1927 SetPointer( Pointer( POINTER_ARROW ) );
1928 ReleaseMouse();
1929 return;
1930 }
1931
1932 if (nMouseStatus == SC_GM_WATERUNDO) // Undo im Giesskannenmodus
1933 {
1934 ::svl::IUndoManager* pMgr = pViewData->GetDocShell()->GetUndoManager();
1935 if ( pMgr->GetUndoActionCount() && pMgr->GetUndoActionId() == STR_UNDO_APPLYCELLSTYLE )
1936 pMgr->Undo();
1937 else
1938 Sound::Beep();
1939 return;
1940 }
1941
1942 if (DrawMouseButtonUp(rMEvt)) // includes format paint brush handling for drawing objects
1943 {
1944 ScTabViewShell* pViewShell = pViewData->GetViewShell();
1945 SfxBindings& rBindings=pViewShell->GetViewFrame()->GetBindings();
1946 rBindings.Invalidate(SID_ATTR_TRANSFORM_WIDTH);
1947 rBindings.Invalidate(SID_ATTR_TRANSFORM_HEIGHT);
1948 rBindings.Invalidate(SID_ATTR_TRANSFORM_POS_X);
1949 rBindings.Invalidate(SID_ATTR_TRANSFORM_POS_Y);
1950 rBindings.Invalidate(SID_ATTR_TRANSFORM_ANGLE);
1951 rBindings.Invalidate(SID_ATTR_TRANSFORM_ROT_X);
1952 rBindings.Invalidate(SID_ATTR_TRANSFORM_ROT_Y);
1953 rBindings.Invalidate(SID_ATTR_TRANSFORM_AUTOWIDTH);
1954 rBindings.Invalidate(SID_ATTR_TRANSFORM_AUTOHEIGHT);
1955 return;
1956 }
1957
1958 rMark.SetMarking(sal_False);
1959
1960 SetPointer( Pointer( POINTER_ARROW ) );
1961
1962 if (pViewData->IsFillMode() ||
1963 ( pViewData->GetFillMode() == SC_FILL_MATRIX && rMEvt.IsMod1() ))
1964 {
1965 nScFillModeMouseModifier = rMEvt.GetModifier();
1966 SCCOL nStartCol;
1967 SCROW nStartRow;
1968 SCCOL nEndCol;
1969 SCROW nEndRow;
1970 pViewData->GetFillData( nStartCol, nStartRow, nEndCol, nEndRow );
1971 // DBG_ASSERT( nStartCol==pViewData->GetRefStartX() && nStartRow==pViewData->GetRefStartY(),
1972 // "Block falsch fuer AutoFill" );
1973 ScRange aDelRange;
1974 sal_Bool bIsDel = pViewData->GetDelMark( aDelRange );
1975
1976 ScViewFunc* pView = pViewData->GetView();
1977 pView->StopRefMode();
1978 pViewData->ResetFillMode();
1979 pView->GetFunctionSet()->SetAnchorFlag( sal_False ); // #i5819# don't use AutoFill anchor flag for selection
1980
1981 if ( bIsDel )
1982 {
1983 pView->MarkRange( aDelRange, sal_False );
1984 pView->DeleteContents( IDF_CONTENTS );
1985 SCTAB nTab = pViewData->GetTabNo();
1986 ScRange aBlockRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab );
1987 if ( aBlockRange != aDelRange )
1988 {
1989 if ( aDelRange.aStart.Row() == nStartRow )
1990 aBlockRange.aEnd.SetCol( aDelRange.aStart.Col() - 1 );
1991 else
1992 aBlockRange.aEnd.SetRow( aDelRange.aStart.Row() - 1 );
1993 pView->MarkRange( aBlockRange, sal_False );
1994 }
1995 }
1996 else
1997 pViewData->GetDispatcher().Execute( FID_FILL_AUTO, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD );
1998 }
1999 else if (pViewData->GetFillMode() == SC_FILL_MATRIX)
2000 {
2001 SCTAB nTab = pViewData->GetTabNo();
2002 SCCOL nStartCol;
2003 SCROW nStartRow;
2004 SCCOL nEndCol;
2005 SCROW nEndRow;
2006 pViewData->GetFillData( nStartCol, nStartRow, nEndCol, nEndRow );
2007 ScRange aBlockRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab );
2008 SCCOL nFillCol = pViewData->GetRefEndX();
2009 SCROW nFillRow = pViewData->GetRefEndY();
2010 ScAddress aEndPos( nFillCol, nFillRow, nTab );
2011
2012 ScTabView* pView = pViewData->GetView();
2013 pView->StopRefMode();
2014 pViewData->ResetFillMode();
2015 pView->GetFunctionSet()->SetAnchorFlag( sal_False );
2016
2017 if ( aEndPos != aBlockRange.aEnd )
2018 {
2019 pViewData->GetDocShell()->GetDocFunc().ResizeMatrix( aBlockRange, aEndPos, sal_False );
2020 pViewData->GetView()->MarkRange( ScRange( aBlockRange.aStart, aEndPos ) );
2021 }
2022 }
2023 else if (pViewData->IsAnyFillMode())
2024 {
2025 // Embedded-Area has been changed
2026 ScTabView* pView = pViewData->GetView();
2027 pView->StopRefMode();
2028 pViewData->ResetFillMode();
2029 pView->GetFunctionSet()->SetAnchorFlag( sal_False );
2030 pViewData->GetDocShell()->UpdateOle(pViewData);
2031 }
2032
2033 sal_Bool bRefMode = pViewData->IsRefMode();
2034 if (bRefMode)
2035 pScMod->EndReference();
2036
2037 //
2038 // Giesskannen-Modus (Gestalter)
2039 //
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 //
2179 // Links in edit cells
2180 //
2181
2182 sal_Bool bAlt = rMEvt.IsMod2();
2183 if ( !bAlt && !bRefMode && !bDouble && nMouseStatus == SC_GM_URLDOWN )
2184 {
2185 // beim ButtonUp nur ausfuehren, wenn ButtonDown auch ueber einer URL war
2186
2187 String aName, aUrl, aTarget;
2188 if ( GetEditUrl( rMEvt.GetPosPixel(), &aName, &aUrl, &aTarget ) )
2189 {
2190 nMouseStatus = SC_GM_NONE; // keinen Doppelklick anfangen
2191 ScGlobal::OpenURL( aUrl, aTarget );
2192
2193 // fire worksheet_followhyperlink event
2194 uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents = pDoc->GetVbaEventProcessor();
2195 if( xVbaEvents.is() ) try
2196 {
2197 Point aPos = rMEvt.GetPosPixel();
2198 SCsCOL nPosX;
2199 SCsROW nPosY;
2200 SCTAB nTab = pViewData->GetTabNo();
2201 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
2202 ScBaseCell* pCell = NULL;
2203 if( lcl_GetHyperlinkCell( pDoc, nPosX, nPosY, nTab, pCell ) )
2204 {
2205 ScAddress aCellPos( nPosX, nPosY, nTab );
2206 uno::Reference< table::XCell > xCell( new ScCellObj( pViewData->GetDocShell(), aCellPos ) );
2207 uno::Sequence< uno::Any > aArgs(1);
2208 aArgs[0] <<= xCell;
2209 xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKSHEET_FOLLOWHYPERLINK, aArgs );
2210 }
2211 }
2212 catch( uno::Exception& )
2213 {
2214 }
2215
2216 return;
2217 }
2218 }
2219
2220 //
2221 // Gridwin - SelectionEngine
2222 //
2223
2224 // SelMouseButtonDown is called only for left button, but SelMouseButtonUp would return
2225 // sal_True for any call, so IsLeft must be checked here, too.
2226
2227 if ( rMEvt.IsLeft() && pViewData->GetView()->GetSelEngine()->SelMouseButtonUp( rMEvt ) )
2228 {
2229 // rMark.MarkToSimple();
2230 pViewData->GetView()->UpdateAutoFillMark();
2231
2232 SfxDispatcher* pDisp = pViewData->GetViewShell()->GetDispatcher();
2233 sal_Bool bFormulaMode = pScMod->IsFormulaMode();
2234 DBG_ASSERT( pDisp || bFormulaMode, "Cursor auf nicht aktiver View bewegen ?" );
2235
2236 // #i14927# execute SID_CURRENTCELL (for macro recording) only if there is no
2237 // multiple selection, so the argument string completely describes the selection,
2238 // and executing the slot won't change the existing selection (executing the slot
2239 // here and from a recorded macro is treated equally)
2240
2241 if ( pDisp && !bFormulaMode && !rMark.IsMultiMarked() )
2242 {
2243 String aAddr; // CurrentCell
2244 if( rMark.IsMarked() )
2245 {
2246 // sal_Bool bKeep = rMark.IsMultiMarked(); //! wohin damit ???
2247
2248 ScRange aScRange;
2249 rMark.GetMarkArea( aScRange );
2250 aScRange.Format( aAddr, SCR_ABS );
2251 if ( aScRange.aStart == aScRange.aEnd )
2252 {
2253 // make sure there is a range selection string even for a single cell
2254 String aSingle = aAddr;
2255 aAddr.Append( (sal_Char) ':' );
2256 aAddr.Append( aSingle );
2257 }
2258
2259 //! SID_MARKAREA gibts nicht mehr ???
2260 //! was passiert beim Markieren mit dem Cursor ???
2261 }
2262 else // nur Cursor bewegen
2263 {
2264 ScAddress aScAddress( pViewData->GetCurX(), pViewData->GetCurY(), 0 );
2265 aScAddress.Format( aAddr, SCA_ABS );
2266 }
2267
2268 SfxStringItem aPosItem( SID_CURRENTCELL, aAddr );
2269 pDisp->Execute( SID_CURRENTCELL, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD,
2270 &aPosItem, (void*)0L );
2271
2272 pViewData->GetView()->InvalidateAttribs();
2273 }
2274 pViewData->GetViewShell()->SelectionChanged();
2275 return;
2276 }
2277 }
2278
FakeButtonUp()2279 void ScGridWindow::FakeButtonUp()
2280 {
2281 if ( nButtonDown )
2282 {
2283 MouseEvent aEvent( aCurMousePos ); // nButtons = 0 -> ignore
2284 MouseButtonUp( aEvent );
2285 }
2286 }
2287
MouseMove(const MouseEvent & rMEvt)2288 void __EXPORT ScGridWindow::MouseMove( const MouseEvent& rMEvt )
2289 {
2290 aCurMousePos = rMEvt.GetPosPixel();
2291
2292 if ( rMEvt.IsLeaveWindow() && pNoteMarker && !pNoteMarker->IsByKeyboard() )
2293 HideNoteMarker();
2294
2295 ScModule* pScMod = SC_MOD();
2296 if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
2297 return;
2298
2299 // Ob aus dem Edit-Modus Drag&Drop gestartet wurde, bekommt man leider
2300 // nicht anders mit:
2301
2302 if (bEEMouse && nButtonDown && !rMEvt.GetButtons())
2303 {
2304 bEEMouse = sal_False;
2305 nButtonDown = 0;
2306 nMouseStatus = SC_GM_NONE;
2307 return;
2308 }
2309
2310 if (nMouseStatus == SC_GM_IGNORE)
2311 return;
2312
2313 if (nMouseStatus == SC_GM_WATERUNDO) // Undo im Giesskannenmodus -> nur auf Up warten
2314 return;
2315
2316 if ( pViewData->GetViewShell()->IsAuditShell() ) // Detektiv-Fuell-Modus
2317 {
2318 SetPointer( Pointer( POINTER_FILL ) );
2319 return;
2320 }
2321
2322 if (nMouseStatus == SC_GM_FILTER && pFilterBox)
2323 {
2324 Point aRelPos = pFilterBox->ScreenToOutputPixel( OutputToScreenPixel( rMEvt.GetPosPixel() ) );
2325 if ( Rectangle(Point(),pFilterBox->GetOutputSizePixel()).IsInside(aRelPos) )
2326 {
2327 nButtonDown = 0;
2328 nMouseStatus = SC_GM_NONE;
2329 if ( pFilterBox->GetMode() == SC_FILTERBOX_FILTER )
2330 {
2331 if (mpFilterButton.get())
2332 {
2333 mpFilterButton->setHasHiddenMember(false);
2334 mpFilterButton->setPopupPressed(false);
2335 HideCursor();
2336 mpFilterButton->draw();
2337 ShowCursor();
2338 }
2339 }
2340 ReleaseMouse();
2341 pFilterBox->MouseButtonDown( MouseEvent( aRelPos, 1, MOUSE_SIMPLECLICK, MOUSE_LEFT ) );
2342 return;
2343 }
2344 }
2345
2346 sal_Bool bFormulaMode = pScMod->IsFormulaMode(); // naechster Klick -> Referenz
2347
2348 if (bEEMouse && pViewData->HasEditView( eWhich ))
2349 {
2350 EditView* pEditView;
2351 SCCOL nEditCol;
2352 SCROW nEditRow;
2353 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
2354 pEditView->MouseMove( rMEvt );
2355 return;
2356 }
2357
2358 if (bDPMouse)
2359 {
2360 DPMouseMove( rMEvt );
2361 return;
2362 }
2363
2364 if (bRFMouse)
2365 {
2366 RFMouseMove( rMEvt, sal_False );
2367 return;
2368 }
2369
2370 if (nPagebreakMouse)
2371 {
2372 PagebreakMove( rMEvt, sal_False );
2373 return;
2374 }
2375
2376 // anderen Mauszeiger anzeigen?
2377
2378 sal_Bool bEditMode = pViewData->HasEditView(eWhich);
2379
2380 //! Testen ob RefMode-Dragging !!!
2381 if ( bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()) )
2382 {
2383 Point aPos = rMEvt.GetPosPixel();
2384 SCsCOL nPosX;
2385 SCsROW nPosY;
2386 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
2387
2388 EditView* pEditView;
2389 SCCOL nEditCol;
2390 SCROW nEditRow;
2391 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
2392 SCCOL nEndCol = pViewData->GetEditEndCol();
2393 SCROW nEndRow = pViewData->GetEditEndRow();
2394
2395 if ( nPosX >= (SCsCOL) nEditCol && nPosX <= (SCsCOL) nEndCol &&
2396 nPosY >= (SCsROW) nEditRow && nPosY <= (SCsROW) nEndRow )
2397 {
2398 // Field can only be URL field
2399 sal_Bool bAlt = rMEvt.IsMod2();
2400 if ( !bAlt && !nButtonDown && pEditView && pEditView->GetFieldUnderMousePointer() )
2401 SetPointer( Pointer( POINTER_REFHAND ) );
2402 else if ( pEditView && pEditView->GetEditEngine()->IsVertical() )
2403 SetPointer( Pointer( POINTER_TEXT_VERTICAL ) );
2404 else
2405 SetPointer( Pointer( POINTER_TEXT ) );
2406 return;
2407 }
2408 }
2409
2410 sal_Bool bWater = SC_MOD()->GetIsWaterCan() || pViewData->GetView()->HasPaintBrush();
2411 if (bWater)
2412 SetPointer( Pointer(POINTER_FILL) );
2413
2414 if (!bWater)
2415 {
2416 sal_Bool bCross = sal_False;
2417
2418 // Range-Finder
2419
2420 sal_Bool bCorner;
2421 if ( HitRangeFinder( rMEvt.GetPosPixel(), bCorner ) )
2422 {
2423 if (bCorner)
2424 SetPointer( Pointer( POINTER_CROSS ) );
2425 else
2426 SetPointer( Pointer( POINTER_HAND ) );
2427 bCross = sal_True;
2428 }
2429
2430 // Page-Break-Modus
2431
2432 sal_uInt16 nBreakType;
2433 if ( !nButtonDown && pViewData->IsPagebreakMode() &&
2434 ( nBreakType = HitPageBreak( rMEvt.GetPosPixel() ) ) != 0 )
2435 {
2436 PointerStyle eNew = POINTER_ARROW;
2437 switch ( nBreakType )
2438 {
2439 case SC_PD_RANGE_L:
2440 case SC_PD_RANGE_R:
2441 case SC_PD_BREAK_H:
2442 eNew = POINTER_ESIZE;
2443 break;
2444 case SC_PD_RANGE_T:
2445 case SC_PD_RANGE_B:
2446 case SC_PD_BREAK_V:
2447 eNew = POINTER_SSIZE;
2448 break;
2449 case SC_PD_RANGE_TL:
2450 case SC_PD_RANGE_BR:
2451 eNew = POINTER_SESIZE;
2452 break;
2453 case SC_PD_RANGE_TR:
2454 case SC_PD_RANGE_BL:
2455 eNew = POINTER_NESIZE;
2456 break;
2457 }
2458 SetPointer( Pointer( eNew ) );
2459 bCross = sal_True;
2460 }
2461
2462 // Fill-Cursor anzeigen ?
2463
2464 if ( !bFormulaMode && !nButtonDown )
2465 if (TestMouse( rMEvt, sal_False ))
2466 bCross = sal_True;
2467
2468 if ( nButtonDown && pViewData->IsAnyFillMode() )
2469 {
2470 SetPointer( Pointer( POINTER_CROSS ) );
2471 bCross = sal_True;
2472 nScFillModeMouseModifier = rMEvt.GetModifier(); // ausgewertet bei AutoFill und Matrix
2473 }
2474
2475 if (!bCross)
2476 {
2477 sal_Bool bAlt = rMEvt.IsMod2();
2478
2479 if (bEditMode) // Edit-Mode muss zuerst kommen!
2480 SetPointer( Pointer( POINTER_ARROW ) );
2481 else if ( !bAlt && !nButtonDown &&
2482 GetEditUrl(rMEvt.GetPosPixel()) )
2483 SetPointer( Pointer( POINTER_REFHAND ) );
2484 else if ( DrawMouseMove(rMEvt) ) // setzt Pointer um
2485 return;
2486 }
2487 }
2488
2489 if ( pViewData->GetView()->GetSelEngine()->SelMouseMove( rMEvt ) )
2490 return;
2491 }
2492
lcl_InitMouseEvent(::com::sun::star::awt::MouseEvent & rEvent,const MouseEvent & rEvt)2493 void lcl_InitMouseEvent( ::com::sun::star::awt::MouseEvent& rEvent, const MouseEvent& rEvt )
2494 {
2495 rEvent.Modifiers = 0;
2496 if ( rEvt.IsShift() )
2497 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::SHIFT;
2498 if ( rEvt.IsMod1() )
2499 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD1;
2500 if ( rEvt.IsMod2() )
2501 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD2;
2502 if ( rEvt.IsMod3() )
2503 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD3;
2504
2505 rEvent.Buttons = 0;
2506 if ( rEvt.IsLeft() )
2507 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::LEFT;
2508 if ( rEvt.IsRight() )
2509 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::RIGHT;
2510 if ( rEvt.IsMiddle() )
2511 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::MIDDLE;
2512
2513 rEvent.X = rEvt.GetPosPixel().X();
2514 rEvent.Y = rEvt.GetPosPixel().Y();
2515 rEvent.ClickCount = rEvt.GetClicks();
2516 rEvent.PopupTrigger = sal_False;
2517 }
2518
PreNotify(NotifyEvent & rNEvt)2519 long ScGridWindow::PreNotify( NotifyEvent& rNEvt )
2520 {
2521 bool bDone = false;
2522 sal_uInt16 nType = rNEvt.GetType();
2523 if ( nType == EVENT_MOUSEBUTTONUP || nType == EVENT_MOUSEBUTTONDOWN )
2524 {
2525 Window* pWindow = rNEvt.GetWindow();
2526 if (pWindow == this && pViewData)
2527 {
2528 SfxViewFrame* pViewFrame = pViewData->GetViewShell()->GetViewFrame();
2529 if (pViewFrame)
2530 {
2531 com::sun::star::uno::Reference<com::sun::star::frame::XController> xController = pViewFrame->GetFrame().GetController();
2532 if (xController.is())
2533 {
2534 ScTabViewObj* pImp = ScTabViewObj::getImplementation( xController );
2535 if (pImp && pImp->IsMouseListening())
2536 {
2537 ::com::sun::star::awt::MouseEvent aEvent;
2538 lcl_InitMouseEvent( aEvent, *rNEvt.GetMouseEvent() );
2539 if ( rNEvt.GetWindow() )
2540 aEvent.Source = rNEvt.GetWindow()->GetComponentInterface();
2541 if ( nType == EVENT_MOUSEBUTTONDOWN)
2542 bDone = pImp->MousePressed( aEvent );
2543 else
2544 bDone = pImp->MouseReleased( aEvent );
2545 }
2546 }
2547 }
2548 }
2549 }
2550 if (bDone) // event consumed by a listener
2551 {
2552 if ( nType == EVENT_MOUSEBUTTONDOWN )
2553 {
2554 const MouseEvent* pMouseEvent = rNEvt.GetMouseEvent();
2555 if ( pMouseEvent->IsRight() && pMouseEvent->GetClicks() == 1 )
2556 {
2557 // If a listener returned true for a right-click call, also prevent opening the context menu
2558 // (this works only if the context menu is opened on mouse-down)
2559 nMouseStatus = SC_GM_IGNORE;
2560 }
2561 }
2562
2563 return 1;
2564 }
2565 else
2566 return Window::PreNotify( rNEvt );
2567 }
2568
Tracking(const TrackingEvent & rTEvt)2569 void ScGridWindow::Tracking( const TrackingEvent& rTEvt )
2570 {
2571 // Weil die SelectionEngine kein Tracking kennt, die Events nur auf
2572 // die verschiedenen MouseHandler verteilen...
2573
2574 const MouseEvent& rMEvt = rTEvt.GetMouseEvent();
2575
2576 if ( rTEvt.IsTrackingCanceled() ) // alles abbrechen...
2577 {
2578 if (!pViewData->GetView()->IsInActivatePart())
2579 {
2580 if (bDPMouse)
2581 bDPMouse = sal_False; // gezeichnet wird per bDragRect
2582 if (bDragRect)
2583 {
2584 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
2585 bDragRect = sal_False;
2586 UpdateDragRectOverlay();
2587 }
2588 if (bRFMouse)
2589 {
2590 RFMouseMove( rMEvt, sal_True ); // richtig abbrechen geht dabei nicht...
2591 bRFMouse = sal_False;
2592 }
2593 if (nPagebreakMouse)
2594 {
2595 // if (bPagebreakDrawn)
2596 // DrawDragRect( aPagebreakDrag.aStart.Col(), aPagebreakDrag.aStart.Row(),
2597 // aPagebreakDrag.aEnd.Col(), aPagebreakDrag.aEnd.Row(), sal_False );
2598 bPagebreakDrawn = sal_False;
2599 UpdateDragRectOverlay();
2600 nPagebreakMouse = SC_PD_NONE;
2601 }
2602
2603 SetPointer( Pointer( POINTER_ARROW ) );
2604 StopMarking();
2605 MouseButtonUp( rMEvt ); // mit Status SC_GM_IGNORE aus StopMarking
2606
2607 sal_Bool bRefMode = pViewData->IsRefMode();
2608 if (bRefMode)
2609 SC_MOD()->EndReference(); // #63148# Dialog nicht verkleinert lassen
2610 }
2611 }
2612 else if ( rTEvt.IsTrackingEnded() )
2613 {
2614 // MouseButtonUp immer mit passenden Buttons (z.B. wegen Testtool, #63148#)
2615 // Schliesslich behauptet der Tracking-Event ja, dass normal beendet und nicht
2616 // abgebrochen wurde.
2617
2618 MouseEvent aUpEvt( rMEvt.GetPosPixel(), rMEvt.GetClicks(),
2619 rMEvt.GetMode(), nButtonDown, rMEvt.GetModifier() );
2620 MouseButtonUp( aUpEvt );
2621 }
2622 else
2623 MouseMove( rMEvt );
2624 }
2625
StartDrag(sal_Int8,const Point & rPosPixel)2626 void ScGridWindow::StartDrag( sal_Int8 /* nAction */, const Point& rPosPixel )
2627 {
2628 if ( pFilterBox || nPagebreakMouse )
2629 return;
2630
2631 HideNoteMarker();
2632
2633 CommandEvent aDragEvent( rPosPixel, COMMAND_STARTDRAG, sal_True );
2634
2635 if (bEEMouse && pViewData->HasEditView( eWhich ))
2636 {
2637 EditView* pEditView;
2638 SCCOL nEditCol;
2639 SCROW nEditRow;
2640 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
2641
2642 // #63263# don't remove the edit view while switching views
2643 ScModule* pScMod = SC_MOD();
2644 pScMod->SetInEditCommand( sal_True );
2645
2646 pEditView->Command( aDragEvent );
2647
2648 ScInputHandler* pHdl = pScMod->GetInputHdl();
2649 if (pHdl)
2650 pHdl->DataChanged();
2651
2652 pScMod->SetInEditCommand( sal_False );
2653 if (!pViewData->IsActive()) // dropped to different view?
2654 {
2655 ScInputHandler* pViewHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
2656 if ( pViewHdl && pViewData->HasEditView( eWhich ) )
2657 {
2658 pViewHdl->CancelHandler();
2659 ShowCursor(); // missing from KillEditView
2660 }
2661 }
2662 }
2663 else
2664 if ( !DrawCommand(aDragEvent) )
2665 pViewData->GetView()->GetSelEngine()->Command( aDragEvent );
2666 }
2667
lcl_SetTextCursorPos(ScViewData * pViewData,ScSplitPos eWhich,Window * pWin)2668 void lcl_SetTextCursorPos( ScViewData* pViewData, ScSplitPos eWhich, Window* pWin )
2669 {
2670 SCCOL nCol = pViewData->GetCurX();
2671 SCROW nRow = pViewData->GetCurY();
2672 Rectangle aEditArea = pViewData->GetEditArea( eWhich, nCol, nRow, pWin, NULL, sal_True );
2673 aEditArea.Right() = aEditArea.Left();
2674 aEditArea = pWin->PixelToLogic( aEditArea );
2675 pWin->SetCursorRect( &aEditArea );
2676 }
2677
Command(const CommandEvent & rCEvt)2678 void __EXPORT ScGridWindow::Command( const CommandEvent& rCEvt )
2679 {
2680 // The command event is send to the window after a possible context
2681 // menu from an inplace client is closed. Now we have the chance to
2682 // deactivate the inplace client without any problem regarding parent
2683 // windows and code on the stack.
2684 // For more information, see #126086# and #128122#
2685 sal_uInt16 nCmd = rCEvt.GetCommand();
2686 ScTabViewShell* pTabViewSh = pViewData->GetViewShell();
2687 SfxInPlaceClient* pClient = pTabViewSh->GetIPClient();
2688 if ( pClient &&
2689 pClient->IsObjectInPlaceActive() &&
2690 nCmd == COMMAND_CONTEXTMENU )
2691 {
2692 pTabViewSh->DeactivateOle();
2693 return;
2694 }
2695
2696 ScModule* pScMod = SC_MOD();
2697 DBG_ASSERT( nCmd != COMMAND_STARTDRAG, "ScGridWindow::Command called with COMMAND_STARTDRAG" );
2698
2699 if ( nCmd == COMMAND_STARTEXTTEXTINPUT ||
2700 nCmd == COMMAND_ENDEXTTEXTINPUT ||
2701 nCmd == COMMAND_EXTTEXTINPUT ||
2702 nCmd == COMMAND_CURSORPOS )
2703 {
2704 sal_Bool bEditView = pViewData->HasEditView( eWhich );
2705 if (!bEditView)
2706 {
2707 // only if no cell editview is active, look at drawview
2708 SdrView* pSdrView = pViewData->GetView()->GetSdrView();
2709 if ( pSdrView )
2710 {
2711 OutlinerView* pOlView = pSdrView->GetTextEditOutlinerView();
2712 if ( pOlView && pOlView->GetWindow() == this )
2713 {
2714 pOlView->Command( rCEvt );
2715 return; // done
2716 }
2717 }
2718 }
2719
2720 if ( nCmd == COMMAND_CURSORPOS && !bEditView )
2721 {
2722 // #88458# CURSORPOS may be called without following text input,
2723 // to set the input method window position
2724 // -> input mode must not be started,
2725 // manually calculate text insert position if not in input mode
2726
2727 lcl_SetTextCursorPos( pViewData, eWhich, this );
2728 return;
2729 }
2730
2731 ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
2732 if ( pHdl )
2733 {
2734 pHdl->InputCommand( rCEvt, sal_True );
2735 return; // done
2736 }
2737
2738 Window::Command( rCEvt );
2739 return;
2740 }
2741
2742 if ( nCmd == COMMAND_VOICE )
2743 {
2744 // Der Handler wird nur gerufen, wenn ein Text-Cursor aktiv ist,
2745 // also muss es eine EditView oder ein editiertes Zeichenobjekt geben
2746
2747 ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
2748 if ( pHdl && pViewData->HasEditView( eWhich ) )
2749 {
2750 EditView* pEditView = pViewData->GetEditView( eWhich ); // ist dann nicht 0
2751 pHdl->DataChanging();
2752 pEditView->Command( rCEvt );
2753 pHdl->DataChanged();
2754 return; // erledigt
2755 }
2756 SdrView* pSdrView = pViewData->GetView()->GetSdrView();
2757 if ( pSdrView )
2758 {
2759 OutlinerView* pOlView = pSdrView->GetTextEditOutlinerView();
2760 if ( pOlView && pOlView->GetWindow() == this )
2761 {
2762 pOlView->Command( rCEvt );
2763 return; // erledigt
2764 }
2765 }
2766 Window::Command(rCEvt); // sonst soll sich die Basisklasse drum kuemmern...
2767 return;
2768 }
2769
2770 if ( nCmd == COMMAND_PASTESELECTION )
2771 {
2772 if ( bEEMouse )
2773 {
2774 // EditEngine handles selection in MouseButtonUp - no action
2775 // needed in command handler
2776 }
2777 else
2778 {
2779 PasteSelection( rCEvt.GetMousePosPixel() );
2780 }
2781 return;
2782 }
2783
2784 if ( nCmd == COMMAND_INPUTLANGUAGECHANGE )
2785 {
2786 // #i55929# Font and font size state depends on input language if nothing is selected,
2787 // so the slots have to be invalidated when the input language is changed.
2788
2789 SfxBindings& rBindings = pViewData->GetBindings();
2790 rBindings.Invalidate( SID_ATTR_CHAR_FONT );
2791 rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT );
2792 return;
2793 }
2794
2795 if ( nCmd == COMMAND_WHEEL || nCmd == COMMAND_STARTAUTOSCROLL || nCmd == COMMAND_AUTOSCROLL )
2796 {
2797 sal_Bool bDone = pViewData->GetView()->ScrollCommand( rCEvt, eWhich );
2798 if (!bDone)
2799 Window::Command(rCEvt);
2800 return;
2801 }
2802 // #i7560# FormulaMode check is below scrolling - scrolling is allowed during formula input
2803 sal_Bool bDisable = pScMod->IsFormulaMode() ||
2804 pScMod->IsModalMode(pViewData->GetSfxDocShell());
2805 if (bDisable)
2806 return;
2807
2808 if ( nCmd == COMMAND_CONTEXTMENU && !SC_MOD()->GetIsWaterCan() )
2809 {
2810 sal_Bool bMouse = rCEvt.IsMouseEvent();
2811 if ( bMouse && nMouseStatus == SC_GM_IGNORE )
2812 return;
2813
2814 if (pViewData->IsAnyFillMode())
2815 {
2816 pViewData->GetView()->StopRefMode();
2817 pViewData->ResetFillMode();
2818 }
2819 ReleaseMouse();
2820 StopMarking();
2821
2822 Point aPosPixel = rCEvt.GetMousePosPixel();
2823 Point aMenuPos = aPosPixel;
2824
2825 if ( bMouse )
2826 {
2827 SCsCOL nCellX = -1;
2828 SCsROW nCellY = -1;
2829 pViewData->GetPosFromPixel(aPosPixel.X(), aPosPixel.Y(), eWhich, nCellX, nCellY);
2830 ScDocument* pDoc = pViewData->GetDocument();
2831 SCTAB nTab = pViewData->GetTabNo();
2832 const ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
2833 bool bSelectAllowed = true;
2834 if ( pProtect && pProtect->isProtected() )
2835 {
2836 // This sheet is protected. Check if a context menu is allowed on this cell.
2837 bool bCellProtected = pDoc->HasAttrib(nCellX, nCellY, nTab, nCellX, nCellY, nTab, HASATTR_PROTECTED);
2838 bool bSelProtected = pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
2839 bool bSelUnprotected = pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
2840
2841 if (bCellProtected)
2842 bSelectAllowed = bSelProtected;
2843 else
2844 bSelectAllowed = bSelUnprotected;
2845 }
2846 if (!bSelectAllowed)
2847 // Selecting this cell is not allowed, neither is context menu.
2848 return;
2849
2850 // #i18735# First select the item under the mouse pointer.
2851 // This can change the selection, and the view state (edit mode, etc).
2852 SelectForContextMenu( aPosPixel, nCellX, nCellY );
2853 }
2854
2855 sal_Bool bDone = sal_False;
2856 sal_Bool bEdit = pViewData->HasEditView(eWhich);
2857 if ( !bEdit )
2858 {
2859 // Edit-Zelle mit Spelling-Errors ?
2860 if ( bMouse && GetEditUrlOrError( sal_True, aPosPixel ) )
2861 {
2862 // GetEditUrlOrError hat den Cursor schon bewegt
2863
2864 pScMod->SetInputMode( SC_INPUT_TABLE );
2865 bEdit = pViewData->HasEditView(eWhich); // hat's geklappt ?
2866
2867 DBG_ASSERT( bEdit, "kann nicht in Edit-Modus schalten" );
2868 }
2869 }
2870 if ( bEdit )
2871 {
2872 EditView* pEditView = pViewData->GetEditView( eWhich ); // ist dann nicht 0
2873
2874 if ( !bMouse )
2875 {
2876 Cursor* pCur = pEditView->GetCursor();
2877 if ( pCur )
2878 {
2879 Point aLogicPos = pCur->GetPos();
2880 // use the position right of the cursor (spell popup is opened if
2881 // the cursor is before the word, but not if behind it)
2882 aLogicPos.X() += pCur->GetWidth();
2883 aLogicPos.Y() += pCur->GetHeight() / 2; // center vertically
2884 aMenuPos = LogicToPixel( aLogicPos );
2885 }
2886 }
2887
2888 // if edit mode was just started above, online spelling may be incomplete
2889 pEditView->GetEditEngine()->CompleteOnlineSpelling();
2890
2891 // IsCursorAtWrongSpelledWord could be used for !bMouse
2892 // if there was a corresponding ExecuteSpellPopup call
2893
2894 if( pEditView->IsWrongSpelledWordAtPos( aMenuPos ) )
2895 {
2896 // Wenn man unter OS/2 neben das Popupmenue klickt, kommt MouseButtonDown
2897 // vor dem Ende des Menue-Execute, darum muss SetModified vorher kommen
2898 // (Bug #40968#)
2899 ScInputHandler* pHdl = pScMod->GetInputHdl();
2900 if (pHdl)
2901 pHdl->SetModified();
2902
2903 Link aLink = LINK( this, ScGridWindow, PopupSpellingHdl );
2904 pEditView->ExecuteSpellPopup( aMenuPos, &aLink );
2905
2906 bDone = sal_True;
2907 }
2908 }
2909 else if ( !bMouse )
2910 {
2911 // non-edit menu by keyboard -> use lower right of cell cursor position
2912
2913 SCCOL nCurX = pViewData->GetCurX();
2914 SCROW nCurY = pViewData->GetCurY();
2915 aMenuPos = pViewData->GetScrPos( nCurX, nCurY, eWhich, sal_True );
2916 long nSizeXPix;
2917 long nSizeYPix;
2918 pViewData->GetMergeSizePixel( nCurX, nCurY, nSizeXPix, nSizeYPix );
2919 aMenuPos.X() += nSizeXPix;
2920 aMenuPos.Y() += nSizeYPix;
2921
2922 if (pViewData)
2923 {
2924 ScTabViewShell* pViewSh = pViewData->GetViewShell();
2925 if (pViewSh)
2926 {
2927 // Is a draw object selected?
2928
2929 SdrView* pDrawView = pViewSh->GetSdrView();
2930 if (pDrawView && pDrawView->AreObjectsMarked())
2931 {
2932 // #100442#; the conext menu should open in the middle of the selected objects
2933 Rectangle aSelectRect(LogicToPixel(pDrawView->GetAllMarkedBoundRect()));
2934 aMenuPos = aSelectRect.Center();
2935 }
2936 }
2937 }
2938 }
2939
2940 if (!bDone)
2941 {
2942 SfxDispatcher::ExecutePopup( 0, this, &aMenuPos );
2943 }
2944 }
2945 }
2946
SelectForContextMenu(const Point & rPosPixel,SCsCOL nCellX,SCsROW nCellY)2947 void ScGridWindow::SelectForContextMenu( const Point& rPosPixel, SCsCOL nCellX, SCsROW nCellY )
2948 {
2949 // #i18735# if the click was outside of the current selection,
2950 // the cursor is moved or an object at the click position selected.
2951 // (see SwEditWin::SelectMenuPosition in Writer)
2952
2953 ScTabView* pView = pViewData->GetView();
2954 ScDrawView* pDrawView = pView->GetScDrawView();
2955
2956 // check cell edit mode
2957
2958 if ( pViewData->HasEditView(eWhich) )
2959 {
2960 ScModule* pScMod = SC_MOD();
2961 SCCOL nEditStartCol = pViewData->GetEditViewCol(); //! change to GetEditStartCol after calcrtl is integrated
2962 SCROW nEditStartRow = pViewData->GetEditViewRow();
2963 SCCOL nEditEndCol = pViewData->GetEditEndCol();
2964 SCROW nEditEndRow = pViewData->GetEditEndRow();
2965
2966 if ( nCellX >= (SCsCOL) nEditStartCol && nCellX <= (SCsCOL) nEditEndCol &&
2967 nCellY >= (SCsROW) nEditStartRow && nCellY <= (SCsROW) nEditEndRow )
2968 {
2969 // handle selection within the EditView
2970
2971 EditView* pEditView = pViewData->GetEditView( eWhich ); // not NULL (HasEditView)
2972 EditEngine* pEditEngine = pEditView->GetEditEngine();
2973 Rectangle aOutputArea = pEditView->GetOutputArea();
2974 Rectangle aVisArea = pEditView->GetVisArea();
2975
2976 Point aTextPos = PixelToLogic( rPosPixel );
2977 if ( pEditEngine->IsVertical() ) // have to manually transform position
2978 {
2979 aTextPos -= aOutputArea.TopRight();
2980 long nTemp = -aTextPos.X();
2981 aTextPos.X() = aTextPos.Y();
2982 aTextPos.Y() = nTemp;
2983 }
2984 else
2985 aTextPos -= aOutputArea.TopLeft();
2986 aTextPos += aVisArea.TopLeft(); // position in the edit document
2987
2988 EPosition aDocPosition = pEditEngine->FindDocPosition(aTextPos);
2989 ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex);
2990 ESelection aSelection = pEditView->GetSelection();
2991 aSelection.Adjust(); // needed for IsLess/IsGreater
2992 if ( aCompare.IsLess(aSelection) || aCompare.IsGreater(aSelection) )
2993 {
2994 // clicked outside the selected text - deselect and move text cursor
2995 MouseEvent aEvent( rPosPixel );
2996 pEditView->MouseButtonDown( aEvent );
2997 pEditView->MouseButtonUp( aEvent );
2998 pScMod->InputSelection( pEditView );
2999 }
3000
3001 return; // clicked within the edit view - keep edit mode
3002 }
3003 else
3004 {
3005 // outside of the edit view - end edit mode, regardless of cell selection, then continue
3006 pScMod->InputEnterHandler();
3007 }
3008 }
3009
3010 // check draw text edit mode
3011
3012 Point aLogicPos = PixelToLogic( rPosPixel ); // after cell edit mode is ended
3013 if ( pDrawView && pDrawView->GetTextEditObject() && pDrawView->GetTextEditOutlinerView() )
3014 {
3015 OutlinerView* pOlView = pDrawView->GetTextEditOutlinerView();
3016 Rectangle aOutputArea = pOlView->GetOutputArea();
3017 if ( aOutputArea.IsInside( aLogicPos ) )
3018 {
3019 // handle selection within the OutlinerView
3020
3021 Outliner* pOutliner = pOlView->GetOutliner();
3022 const EditEngine& rEditEngine = pOutliner->GetEditEngine();
3023 Rectangle aVisArea = pOlView->GetVisArea();
3024
3025 Point aTextPos = aLogicPos;
3026 if ( pOutliner->IsVertical() ) // have to manually transform position
3027 {
3028 aTextPos -= aOutputArea.TopRight();
3029 long nTemp = -aTextPos.X();
3030 aTextPos.X() = aTextPos.Y();
3031 aTextPos.Y() = nTemp;
3032 }
3033 else
3034 aTextPos -= aOutputArea.TopLeft();
3035 aTextPos += aVisArea.TopLeft(); // position in the edit document
3036
3037 EPosition aDocPosition = rEditEngine.FindDocPosition(aTextPos);
3038 ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex);
3039 ESelection aSelection = pOlView->GetSelection();
3040 aSelection.Adjust(); // needed for IsLess/IsGreater
3041 if ( aCompare.IsLess(aSelection) || aCompare.IsGreater(aSelection) )
3042 {
3043 // clicked outside the selected text - deselect and move text cursor
3044 // use DrawView to allow extra handling there (none currently)
3045 MouseEvent aEvent( rPosPixel );
3046 pDrawView->MouseButtonDown( aEvent, this );
3047 pDrawView->MouseButtonUp( aEvent, this );
3048 }
3049
3050 return; // clicked within the edit area - keep edit mode
3051 }
3052 else
3053 {
3054 // Outside of the edit area - end text edit mode, then continue.
3055 // DrawDeselectAll also ends text edit mode and updates the shells.
3056 // If the click was on the edited object, it will be selected again below.
3057 pView->DrawDeselectAll();
3058 }
3059 }
3060
3061 // look for existing selection
3062
3063 sal_Bool bHitSelected = sal_False;
3064 if ( pDrawView && pDrawView->IsMarkedObjHit( aLogicPos ) )
3065 {
3066 // clicked on selected object -> don't change anything
3067 bHitSelected = sal_True;
3068 }
3069 else if ( pViewData->GetMarkData().IsCellMarked(nCellX, nCellY) )
3070 {
3071 // clicked on selected cell -> don't change anything
3072 bHitSelected = sal_True;
3073 }
3074
3075 // select drawing object or move cell cursor
3076
3077 if ( !bHitSelected )
3078 {
3079 sal_Bool bWasDraw = ( pDrawView && pDrawView->AreObjectsMarked() );
3080 sal_Bool bHitDraw = sal_False;
3081 if ( pDrawView )
3082 {
3083 pDrawView->UnmarkAllObj();
3084 // Unlock the Internal Layer in order to activate the context menu.
3085 // re-lock in ScDrawView::MarkListHasChanged()
3086 lcl_UnLockComment( pDrawView, pDrawView->GetSdrPageView(), pDrawView->GetModel(), aLogicPos ,pViewData);
3087 bHitDraw = pDrawView->MarkObj( aLogicPos );
3088 // draw shell is activated in MarkListHasChanged
3089 }
3090 if ( !bHitDraw )
3091 {
3092 pView->Unmark();
3093 pView->SetCursor(nCellX, nCellY);
3094 if ( bWasDraw )
3095 pViewData->GetViewShell()->SetDrawShell( sal_False ); // switch shells
3096 }
3097 }
3098 }
3099
KeyInput(const KeyEvent & rKEvt)3100 void __EXPORT ScGridWindow::KeyInput(const KeyEvent& rKEvt)
3101 {
3102 // #96965# Cursor control for ref input dialog
3103 if( SC_MOD()->IsRefDialogOpen() )
3104 {
3105 const KeyCode& rKeyCode = rKEvt.GetKeyCode();
3106 if( !rKeyCode.GetModifier() && (rKeyCode.GetCode() == KEY_F2) )
3107 {
3108 SC_MOD()->EndReference();
3109 }
3110 else if( pViewData->GetViewShell()->MoveCursorKeyInput( rKEvt ) )
3111 {
3112 ScRange aRef(
3113 pViewData->GetRefStartX(), pViewData->GetRefStartY(), pViewData->GetRefStartZ(),
3114 pViewData->GetRefEndX(), pViewData->GetRefEndY(), pViewData->GetRefEndZ() );
3115 SC_MOD()->SetReference( aRef, pViewData->GetDocument() );
3116 }
3117 pViewData->GetViewShell()->SelectionChanged();
3118 return ;
3119 }
3120 // wenn semi-Modeless-SfxChildWindow-Dialog oben, keine KeyInputs:
3121 else if( !pViewData->IsAnyFillMode() )
3122 {
3123 // query for existing note marker before calling ViewShell's keyboard handling
3124 // which may remove the marker
3125 sal_Bool bHadKeyMarker = ( pNoteMarker && pNoteMarker->IsByKeyboard() );
3126 ScTabViewShell* pViewSh = pViewData->GetViewShell();
3127
3128 if (pViewData->GetDocShell()->GetProgress())
3129 return;
3130
3131 if (DrawKeyInput(rKEvt))
3132 {
3133 const KeyCode& rKeyCode = rKEvt.GetKeyCode();
3134 if (rKeyCode.GetCode() == KEY_DOWN
3135 || rKeyCode.GetCode() == KEY_UP
3136 || rKeyCode.GetCode() == KEY_LEFT
3137 || rKeyCode.GetCode() == KEY_RIGHT)
3138 {
3139 ScTabViewShell* pViewShell = pViewData->GetViewShell();
3140 SfxBindings& rBindings = pViewShell->GetViewFrame()->GetBindings();
3141 rBindings.Invalidate(SID_ATTR_TRANSFORM_POS_X);
3142 rBindings.Invalidate(SID_ATTR_TRANSFORM_POS_Y);
3143 }
3144 return;
3145 }
3146
3147 if (!pViewData->GetView()->IsDrawSelMode() && !DrawHasMarkedObj()) // keine Eingaben im Zeichenmodus
3148 { //! DrawShell abfragen !!!
3149 if (pViewSh->TabKeyInput(rKEvt))
3150 return;
3151 }
3152 else
3153 if (pViewSh->SfxViewShell::KeyInput(rKEvt)) // von SfxViewShell
3154 return;
3155
3156 KeyCode aCode = rKEvt.GetKeyCode();
3157 if ( aCode.GetCode() == KEY_ESCAPE && aCode.GetModifier() == 0 )
3158 {
3159 if ( bHadKeyMarker )
3160 HideNoteMarker();
3161 else
3162 pViewSh->Escape();
3163 return;
3164 }
3165 if ( aCode.GetCode() == KEY_F1 && aCode.GetModifier() == KEY_MOD1 )
3166 {
3167 // ctrl-F1 shows or hides the note or redlining info for the cursor position
3168 // (hard-coded because F1 can't be configured)
3169
3170 if ( bHadKeyMarker )
3171 HideNoteMarker(); // hide when previously visible
3172 else
3173 ShowNoteMarker( pViewData->GetCurX(), pViewData->GetCurY(), sal_True );
3174 return;
3175 }
3176 }
3177
3178 Window::KeyInput(rKEvt);
3179 }
3180
StopMarking()3181 void ScGridWindow::StopMarking()
3182 {
3183 DrawEndAction(); // Markieren/Verschieben auf Drawing-Layer abbrechen
3184
3185 if (nButtonDown)
3186 {
3187 pViewData->GetMarkData().SetMarking(sal_False);
3188 nMouseStatus = SC_GM_IGNORE;
3189 }
3190 }
3191
UpdateInputContext()3192 void ScGridWindow::UpdateInputContext()
3193 {
3194 sal_Bool bReadOnly = pViewData->GetDocShell()->IsReadOnly();
3195 sal_uLong nOptions = bReadOnly ? 0 : ( INPUTCONTEXT_TEXT | INPUTCONTEXT_EXTTEXTINPUT );
3196
3197 // when font from InputContext is used,
3198 // it must be taken from the cursor position's cell attributes
3199
3200 InputContext aContext;
3201 aContext.SetOptions( nOptions );
3202 SetInputContext( aContext );
3203 }
3204
3205 //--------------------------------------------------------
3206
3207 // sensitiver Bereich (Pixel)
3208 #define SCROLL_SENSITIVE 20
3209
DropScroll(const Point & rMousePos)3210 sal_Bool ScGridWindow::DropScroll( const Point& rMousePos )
3211 {
3212 /* doch auch auf nicht aktiven Views...
3213 if ( !pViewData->IsActive() )
3214 return sal_False;
3215 */
3216 SCsCOL nDx = 0;
3217 SCsROW nDy = 0;
3218 Size aSize = GetOutputSizePixel();
3219
3220 if (aSize.Width() > SCROLL_SENSITIVE * 3)
3221 {
3222 if ( rMousePos.X() < SCROLL_SENSITIVE && pViewData->GetPosX(WhichH(eWhich)) > 0 )
3223 nDx = -1;
3224 if ( rMousePos.X() >= aSize.Width() - SCROLL_SENSITIVE
3225 && pViewData->GetPosX(WhichH(eWhich)) < MAXCOL )
3226 nDx = 1;
3227 }
3228 if (aSize.Height() > SCROLL_SENSITIVE * 3)
3229 {
3230 if ( rMousePos.Y() < SCROLL_SENSITIVE && pViewData->GetPosY(WhichV(eWhich)) > 0 )
3231 nDy = -1;
3232 if ( rMousePos.Y() >= aSize.Height() - SCROLL_SENSITIVE
3233 && pViewData->GetPosY(WhichV(eWhich)) < MAXROW )
3234 nDy = 1;
3235 }
3236
3237 if ( nDx != 0 || nDy != 0 )
3238 {
3239 // if (bDragRect)
3240 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3241
3242 if ( nDx != 0 )
3243 pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) );
3244 if ( nDy != 0 )
3245 pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) );
3246
3247 // if (bDragRect)
3248 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3249 }
3250
3251 return sal_False;
3252 }
3253
lcl_TestScenarioRedliningDrop(ScDocument * pDoc,const ScRange & aDragRange)3254 sal_Bool lcl_TestScenarioRedliningDrop( ScDocument* pDoc, const ScRange& aDragRange)
3255 {
3256 // Testet, ob bei eingeschalteten RedLining,
3257 // bei einem Drop ein Scenario betroffen ist.
3258
3259 sal_Bool bReturn = sal_False;
3260 SCTAB nTab = aDragRange.aStart.Tab();
3261 SCTAB nTabCount = pDoc->GetTableCount();
3262
3263 if(pDoc->GetChangeTrack()!=NULL)
3264 {
3265 if( pDoc->IsScenario(nTab) && pDoc->HasScenarioRange(nTab, aDragRange))
3266 {
3267 bReturn = sal_True;
3268 }
3269 else
3270 {
3271 for(SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
3272 {
3273 if(pDoc->HasScenarioRange(i, aDragRange))
3274 {
3275 bReturn = sal_True;
3276 break;
3277 }
3278 }
3279 }
3280 }
3281 return bReturn;
3282 }
3283
lcl_MakeDropRange(SCCOL nPosX,SCROW nPosY,SCTAB nTab,const ScRange & rSource)3284 ScRange lcl_MakeDropRange( SCCOL nPosX, SCROW nPosY, SCTAB nTab, const ScRange& rSource )
3285 {
3286 SCCOL nCol1 = nPosX;
3287 SCCOL nCol2 = nCol1 + ( rSource.aEnd.Col() - rSource.aStart.Col() );
3288 if ( nCol2 > MAXCOL )
3289 {
3290 nCol1 -= nCol2 - MAXCOL;
3291 nCol2 = MAXCOL;
3292 }
3293 SCROW nRow1 = nPosY;
3294 SCROW nRow2 = nRow1 + ( rSource.aEnd.Row() - rSource.aStart.Row() );
3295 if ( nRow2 > MAXROW )
3296 {
3297 nRow1 -= nRow2 - MAXROW;
3298 nRow2 = MAXROW;
3299 }
3300
3301 return ScRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab );
3302 }
3303
3304 //--------------------------------------------------------
3305
3306 extern sal_Bool bPasteIsDrop; // viewfun4 -> move to header
3307 extern sal_Bool bPasteIsMove; // viewfun7 -> move to header
3308
3309 //--------------------------------------------------------
3310
AcceptPrivateDrop(const AcceptDropEvent & rEvt)3311 sal_Int8 ScGridWindow::AcceptPrivateDrop( const AcceptDropEvent& rEvt )
3312 {
3313 if ( rEvt.mbLeaving )
3314 {
3315 // if (bDragRect)
3316 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3317 bDragRect = sal_False;
3318 UpdateDragRectOverlay();
3319 return rEvt.mnAction;
3320 }
3321
3322 const ScDragData& rData = SC_MOD()->GetDragData();
3323 if ( rData.pCellTransfer )
3324 {
3325 // Don't move source that would include filtered rows.
3326 if ((rEvt.mnAction & DND_ACTION_MOVE) && rData.pCellTransfer->HasFilteredRows())
3327 {
3328 if (bDragRect)
3329 {
3330 bDragRect = sal_False;
3331 UpdateDragRectOverlay();
3332 }
3333 return DND_ACTION_NONE;
3334 }
3335
3336 Point aPos = rEvt.maPosPixel;
3337
3338 ScDocument* pSourceDoc = rData.pCellTransfer->GetSourceDocument();
3339 ScDocument* pThisDoc = pViewData->GetDocument();
3340 if (pSourceDoc == pThisDoc)
3341 {
3342 if ( pThisDoc->HasChartAtPoint(pViewData->GetTabNo(), PixelToLogic(aPos)) )
3343 {
3344 if (bDragRect) // Rechteck loeschen
3345 {
3346 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3347 bDragRect = sal_False;
3348 UpdateDragRectOverlay();
3349 }
3350
3351 //! highlight chart? (selection border?)
3352
3353 sal_Int8 nRet = rEvt.mnAction;
3354 //! if ( rEvt.GetAction() == DROP_LINK )
3355 //! bOk = rEvt.SetAction( DROP_COPY ); // can't link onto chart
3356 return nRet;
3357 }
3358 }
3359 //! else
3360 //! if ( rEvt.GetAction() == DROP_MOVE )
3361 //! rEvt.SetAction( DROP_COPY ); // different doc: default=COPY
3362
3363
3364 if ( rData.pCellTransfer->GetDragSourceFlags() & SC_DROP_TABLE ) // whole sheet?
3365 {
3366 sal_Bool bOk = pThisDoc->IsDocEditable();
3367 return bOk ? rEvt.mnAction : 0; // don't draw selection frame
3368 }
3369
3370 SCsCOL nPosX;
3371 SCsROW nPosY;
3372 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
3373
3374 ScRange aSourceRange = rData.pCellTransfer->GetRange();
3375 SCCOL nSourceStartX = aSourceRange.aStart.Col();
3376 SCROW nSourceStartY = aSourceRange.aStart.Row();
3377 SCCOL nSourceEndX = aSourceRange.aEnd.Col();
3378 SCROW nSourceEndY = aSourceRange.aEnd.Row();
3379 SCCOL nSizeX = nSourceEndX - nSourceStartX + 1;
3380 SCROW nSizeY = nSourceEndY - nSourceStartY + 1;
3381
3382 if ( rEvt.mnAction != DND_ACTION_MOVE )
3383 nSizeY = rData.pCellTransfer->GetNonFilteredRows(); // copy/link: no filtered rows
3384
3385 SCsCOL nNewDragX = nPosX - rData.pCellTransfer->GetDragHandleX();
3386 if (nNewDragX<0) nNewDragX=0;
3387 if (nNewDragX+(nSizeX-1) > MAXCOL)
3388 nNewDragX = MAXCOL-(nSizeX-1);
3389 SCsROW nNewDragY = nPosY - rData.pCellTransfer->GetDragHandleY();
3390 if (nNewDragY<0) nNewDragY=0;
3391 if (nNewDragY+(nSizeY-1) > MAXROW)
3392 nNewDragY = MAXROW-(nSizeY-1);
3393
3394 // don't break scenario ranges, don't drop on filtered
3395 SCTAB nTab = pViewData->GetTabNo();
3396 ScRange aDropRange = lcl_MakeDropRange( nNewDragX, nNewDragY, nTab, aSourceRange );
3397 if ( lcl_TestScenarioRedliningDrop( pThisDoc, aDropRange ) ||
3398 lcl_TestScenarioRedliningDrop( pSourceDoc, aSourceRange ) ||
3399 ScViewUtil::HasFiltered( aDropRange, pThisDoc) )
3400 {
3401 if (bDragRect)
3402 {
3403 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3404 bDragRect = sal_False;
3405 UpdateDragRectOverlay();
3406 }
3407 return DND_ACTION_NONE;
3408 }
3409
3410 InsCellCmd eDragInsertMode = INS_NONE;
3411 Window::PointerState aState = GetPointerState();
3412
3413 // check for datapilot item sorting
3414 ScDPObject* pDPObj = NULL;
3415 if ( pThisDoc == pSourceDoc && ( pDPObj = pThisDoc->GetDPAtCursor( nNewDragX, nNewDragY, nTab ) ) != NULL )
3416 {
3417 // drop on DataPilot table: sort or nothing
3418
3419 bool bDPSort = false;
3420 if ( pThisDoc->GetDPAtCursor( nSourceStartX, nSourceStartY, aSourceRange.aStart.Tab() ) == pDPObj )
3421 {
3422 sheet::DataPilotTableHeaderData aDestData;
3423 pDPObj->GetHeaderPositionData( ScAddress(nNewDragX, nNewDragY, nTab), aDestData );
3424 bool bValid = ( aDestData.Dimension >= 0 ); // dropping onto a field
3425
3426 // look through the source range
3427 for (SCROW nRow = aSourceRange.aStart.Row(); bValid && nRow <= aSourceRange.aEnd.Row(); ++nRow )
3428 for (SCCOL nCol = aSourceRange.aStart.Col(); bValid && nCol <= aSourceRange.aEnd.Col(); ++nCol )
3429 {
3430 sheet::DataPilotTableHeaderData aSourceData;
3431 pDPObj->GetHeaderPositionData( ScAddress( nCol, nRow, aSourceRange.aStart.Tab() ), aSourceData );
3432 if ( aSourceData.Dimension != aDestData.Dimension || !aSourceData.MemberName.getLength() )
3433 bValid = false; // empty (subtotal) or different field
3434 }
3435
3436 if ( bValid )
3437 {
3438 sal_Bool bIsDataLayout;
3439 String aDimName = pDPObj->GetDimName( aDestData.Dimension, bIsDataLayout );
3440 const ScDPSaveDimension* pDim = pDPObj->GetSaveData()->GetExistingDimensionByName( aDimName );
3441 if ( pDim )
3442 {
3443 ScRange aOutRange = pDPObj->GetOutRange();
3444
3445 sal_uInt16 nOrient = pDim->GetOrientation();
3446 if ( nOrient == sheet::DataPilotFieldOrientation_COLUMN )
3447 {
3448 eDragInsertMode = INS_CELLSRIGHT;
3449 nSizeY = aOutRange.aEnd.Row() - nNewDragY + 1;
3450 bDPSort = true;
3451 }
3452 else if ( nOrient == sheet::DataPilotFieldOrientation_ROW )
3453 {
3454 eDragInsertMode = INS_CELLSDOWN;
3455 nSizeX = aOutRange.aEnd.Col() - nNewDragX + 1;
3456 bDPSort = true;
3457 }
3458 }
3459 }
3460 }
3461
3462 if ( !bDPSort )
3463 {
3464 // no valid sorting in a DataPilot table -> disallow
3465 if ( bDragRect )
3466 {
3467 bDragRect = sal_False;
3468 UpdateDragRectOverlay();
3469 }
3470 return DND_ACTION_NONE;
3471 }
3472 }
3473 else if ( aState.mnState & KEY_MOD2 )
3474 {
3475 if ( pThisDoc == pSourceDoc && nTab == aSourceRange.aStart.Tab() )
3476 {
3477 long nDeltaX = labs( static_cast< long >( nNewDragX - nSourceStartX ) );
3478 long nDeltaY = labs( static_cast< long >( nNewDragY - nSourceStartY ) );
3479 if ( nDeltaX <= nDeltaY )
3480 {
3481 eDragInsertMode = INS_CELLSDOWN;
3482 }
3483 else
3484 {
3485 eDragInsertMode = INS_CELLSRIGHT;
3486 }
3487
3488 if ( ( eDragInsertMode == INS_CELLSDOWN && nNewDragY <= nSourceEndY &&
3489 ( nNewDragX + nSizeX - 1 ) >= nSourceStartX && nNewDragX <= nSourceEndX &&
3490 ( nNewDragX != nSourceStartX || nNewDragY >= nSourceStartY ) ) ||
3491 ( eDragInsertMode == INS_CELLSRIGHT && nNewDragX <= nSourceEndX &&
3492 ( nNewDragY + nSizeY - 1 ) >= nSourceStartY && nNewDragY <= nSourceEndY &&
3493 ( nNewDragY != nSourceStartY || nNewDragX >= nSourceStartX ) ) )
3494 {
3495 if ( bDragRect )
3496 {
3497 bDragRect = sal_False;
3498 UpdateDragRectOverlay();
3499 }
3500 return DND_ACTION_NONE;
3501 }
3502 }
3503 else
3504 {
3505 if ( static_cast< long >( nSizeX ) >= static_cast< long >( nSizeY ) )
3506 {
3507 eDragInsertMode = INS_CELLSDOWN;
3508
3509 }
3510 else
3511 {
3512 eDragInsertMode = INS_CELLSRIGHT;
3513 }
3514 }
3515 }
3516
3517 if ( nNewDragX != (SCsCOL) nDragStartX || nNewDragY != (SCsROW) nDragStartY ||
3518 nDragStartX+nSizeX-1 != nDragEndX || nDragStartY+nSizeY-1 != nDragEndY ||
3519 !bDragRect || eDragInsertMode != meDragInsertMode )
3520 {
3521 // if (bDragRect)
3522 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3523
3524 nDragStartX = nNewDragX;
3525 nDragStartY = nNewDragY;
3526 nDragEndX = nDragStartX+nSizeX-1;
3527 nDragEndY = nDragStartY+nSizeY-1;
3528 bDragRect = sal_True;
3529 meDragInsertMode = eDragInsertMode;
3530
3531 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3532
3533 UpdateDragRectOverlay();
3534
3535 // show target position as tip help
3536 #if 0
3537 if (Help::IsQuickHelpEnabled())
3538 {
3539 ScRange aRange( nDragStartX, nDragStartY, nTab, nDragEndX, nDragEndY, nTab );
3540 String aHelpStr;
3541 aRange.Format( aHelpStr, SCA_VALID ); // non-3D
3542
3543 Point aPos = Pointer::GetPosPixel();
3544 sal_uInt16 nAlign = QUICKHELP_BOTTOM|QUICKHELP_RIGHT;
3545 Rectangle aRect( aPos, aPos );
3546 Help::ShowQuickHelp(aRect, aHelpStr, nAlign);
3547 }
3548 #endif
3549 }
3550 }
3551
3552 return rEvt.mnAction;
3553 }
3554
AcceptDrop(const AcceptDropEvent & rEvt)3555 sal_Int8 ScGridWindow::AcceptDrop( const AcceptDropEvent& rEvt )
3556 {
3557 const ScDragData& rData = SC_MOD()->GetDragData();
3558 if ( rEvt.mbLeaving )
3559 {
3560 DrawMarkDropObj( NULL );
3561 if ( rData.pCellTransfer )
3562 return AcceptPrivateDrop( rEvt ); // hide drop marker for internal D&D
3563 else
3564 return rEvt.mnAction;
3565 }
3566
3567 if ( pViewData->GetDocShell()->IsReadOnly() )
3568 return DND_ACTION_NONE;
3569
3570
3571 sal_Int8 nRet = DND_ACTION_NONE;
3572
3573 if (rData.pCellTransfer)
3574 {
3575 ScRange aSource = rData.pCellTransfer->GetRange();
3576 if ( aSource.aStart.Col() != 0 || aSource.aEnd.Col() != MAXCOL ||
3577 aSource.aStart.Row() != 0 || aSource.aEnd.Row() != MAXROW )
3578 DropScroll( rEvt.maPosPixel );
3579
3580 nRet = AcceptPrivateDrop( rEvt );
3581 }
3582 else
3583 {
3584 if ( rData.aLinkDoc.Len() )
3585 {
3586 String aThisName;
3587 ScDocShell* pDocSh = pViewData->GetDocShell();
3588 if (pDocSh && pDocSh->HasName())
3589 aThisName = pDocSh->GetMedium()->GetName();
3590
3591 if ( rData.aLinkDoc != aThisName )
3592 nRet = rEvt.mnAction;
3593 }
3594 else if (rData.aJumpTarget.Len())
3595 {
3596 // internal bookmarks (from Navigator)
3597 // local jumps from an unnamed document are possible only within a document
3598
3599 if ( !rData.pJumpLocalDoc || rData.pJumpLocalDoc == pViewData->GetDocument() )
3600 nRet = rEvt.mnAction;
3601 }
3602 else
3603 {
3604 sal_Int8 nMyAction = rEvt.mnAction;
3605
3606 // clear DND_ACTION_LINK when other actions are set. The usage below cannot handle
3607 // multiple set values
3608 if((nMyAction & DND_ACTION_LINK) && (nMyAction & (DND_ACTION_COPYMOVE)))
3609 {
3610 nMyAction &= ~DND_ACTION_LINK;
3611 }
3612
3613 if ( !rData.pDrawTransfer ||
3614 !IsMyModel(rData.pDrawTransfer->GetDragSourceView()) ) // drawing within the document
3615 if ( rEvt.mbDefault && nMyAction == DND_ACTION_MOVE )
3616 nMyAction = DND_ACTION_COPY;
3617
3618 ScDocument* pThisDoc = pViewData->GetDocument();
3619 SdrObject* pHitObj = pThisDoc->GetObjectAtPoint(
3620 pViewData->GetTabNo(), PixelToLogic(rEvt.maPosPixel) );
3621 if ( pHitObj && nMyAction == DND_ACTION_LINK ) // && !rData.pDrawTransfer )
3622 {
3623 if ( IsDropFormatSupported(SOT_FORMATSTR_ID_SVXB)
3624 || IsDropFormatSupported(SOT_FORMAT_GDIMETAFILE)
3625 || IsDropFormatSupported(SOT_FORMATSTR_ID_PNG)
3626 || IsDropFormatSupported(SOT_FORMAT_BITMAP) )
3627 {
3628 // graphic dragged onto drawing object
3629 DrawMarkDropObj( pHitObj );
3630 nRet = nMyAction;
3631 }
3632 }
3633 if (!nRet)
3634 DrawMarkDropObj( NULL );
3635
3636 if (!nRet)
3637 {
3638 switch ( nMyAction )
3639 {
3640 case DND_ACTION_COPY:
3641 case DND_ACTION_MOVE:
3642 case DND_ACTION_COPYMOVE:
3643 {
3644 sal_Bool bMove = ( nMyAction == DND_ACTION_MOVE );
3645 if ( IsDropFormatSupported( SOT_FORMATSTR_ID_EMBED_SOURCE ) ||
3646 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE ) ||
3647 IsDropFormatSupported( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) ||
3648 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ||
3649 IsDropFormatSupported( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) ||
3650 IsDropFormatSupported( SOT_FORMAT_STRING ) ||
3651 IsDropFormatSupported( SOT_FORMATSTR_ID_SYLK ) ||
3652 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK ) ||
3653 IsDropFormatSupported( SOT_FORMATSTR_ID_HTML ) ||
3654 IsDropFormatSupported( SOT_FORMATSTR_ID_HTML_SIMPLE ) ||
3655 IsDropFormatSupported( SOT_FORMATSTR_ID_DIF ) ||
3656 IsDropFormatSupported( SOT_FORMATSTR_ID_DRAWING ) ||
3657 IsDropFormatSupported( SOT_FORMATSTR_ID_SVXB ) ||
3658 IsDropFormatSupported( SOT_FORMAT_RTF ) ||
3659 IsDropFormatSupported( SOT_FORMAT_GDIMETAFILE ) ||
3660 IsDropFormatSupported( SOT_FORMATSTR_ID_PNG ) ||
3661 IsDropFormatSupported( SOT_FORMAT_BITMAP ) ||
3662 IsDropFormatSupported( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) ||
3663 IsDropFormatSupported( SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE ) ||
3664 ( !bMove && (
3665 IsDropFormatSupported( SOT_FORMAT_FILE_LIST ) ||
3666 IsDropFormatSupported( SOT_FORMAT_FILE ) ||
3667 IsDropFormatSupported( SOT_FORMATSTR_ID_SOLK ) ||
3668 IsDropFormatSupported( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) ||
3669 IsDropFormatSupported( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) ||
3670 IsDropFormatSupported( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) ) ) )
3671 {
3672 nRet = nMyAction;
3673 }
3674 }
3675 break;
3676 case DND_ACTION_LINK:
3677 if ( IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE ) ||
3678 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ||
3679 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK ) ||
3680 IsDropFormatSupported( SOT_FORMAT_FILE_LIST ) ||
3681 IsDropFormatSupported( SOT_FORMAT_FILE ) ||
3682 IsDropFormatSupported( SOT_FORMATSTR_ID_SOLK ) ||
3683 IsDropFormatSupported( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) ||
3684 IsDropFormatSupported( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) ||
3685 IsDropFormatSupported( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
3686 {
3687 nRet = nMyAction;
3688 }
3689 break;
3690 }
3691
3692 if ( nRet )
3693 {
3694 // Simple check for protection: It's not known here if the drop will result
3695 // in cells or drawing objects (some formats can be both) and how many cells
3696 // the result will be. But if IsFormatEditable for the drop cell position
3697 // is sal_False (ignores matrix formulas), nothing can be pasted, so the drop
3698 // can already be rejected here.
3699
3700 Point aPos = rEvt.maPosPixel;
3701 SCsCOL nPosX;
3702 SCsROW nPosY;
3703 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
3704 SCTAB nTab = pViewData->GetTabNo();
3705 ScDocument* pDoc = pViewData->GetDocument();
3706
3707 ScEditableTester aTester( pDoc, nTab, nPosX,nPosY, nPosX,nPosY );
3708 if ( !aTester.IsFormatEditable() )
3709 nRet = DND_ACTION_NONE; // forbidden
3710 }
3711 }
3712 }
3713
3714 // scroll only for accepted formats
3715 if (nRet)
3716 DropScroll( rEvt.maPosPixel );
3717 }
3718
3719 return nRet;
3720 }
3721
lcl_GetDropFormatId(const uno::Reference<datatransfer::XTransferable> & xTransfer,bool bPreferText=false)3722 sal_uLong lcl_GetDropFormatId( const uno::Reference<datatransfer::XTransferable>& xTransfer, bool bPreferText = false )
3723 {
3724 TransferableDataHelper aDataHelper( xTransfer );
3725
3726 if ( !aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) )
3727 {
3728 // use bookmark formats if no sba is present
3729
3730 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SOLK ) )
3731 return SOT_FORMATSTR_ID_SOLK;
3732 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) )
3733 return SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR;
3734 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) )
3735 return SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK;
3736 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
3737 return SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR;
3738 }
3739
3740 sal_uLong nFormatId = 0;
3741 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING ) )
3742 nFormatId = SOT_FORMATSTR_ID_DRAWING;
3743 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ) )
3744 nFormatId = SOT_FORMATSTR_ID_SVXB;
3745 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ) )
3746 {
3747 // If it's a Writer object, insert RTF instead of OLE
3748
3749 sal_Bool bDoRtf = sal_False;
3750 SotStorageStreamRef xStm;
3751 TransferableObjectDescriptor aObjDesc;
3752 if( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) &&
3753 aDataHelper.GetSotStorageStream( SOT_FORMATSTR_ID_EMBED_SOURCE, xStm ) )
3754 {
3755 SotStorageRef xStore( new SotStorage( *xStm ) );
3756 bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) ||
3757 aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) )
3758 && aDataHelper.HasFormat( SOT_FORMAT_RTF ) );
3759 }
3760 if ( bDoRtf )
3761 nFormatId = FORMAT_RTF;
3762 else
3763 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE;
3764 }
3765 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) )
3766 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE;
3767 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) )
3768 nFormatId = SOT_FORMATSTR_ID_SBA_DATAEXCHANGE;
3769 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE ) )
3770 nFormatId = SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE;
3771 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_BIFF_8 ) )
3772 nFormatId = SOT_FORMATSTR_ID_BIFF_8;
3773 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_BIFF_5 ) )
3774 nFormatId = SOT_FORMATSTR_ID_BIFF_5;
3775 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) )
3776 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE_OLE;
3777 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) )
3778 nFormatId = SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE;
3779 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) )
3780 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE;
3781 else if ( aDataHelper.HasFormat( SOT_FORMAT_RTF ) )
3782 nFormatId = SOT_FORMAT_RTF;
3783 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_HTML ) )
3784 nFormatId = SOT_FORMATSTR_ID_HTML;
3785 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_HTML_SIMPLE ) )
3786 nFormatId = SOT_FORMATSTR_ID_HTML_SIMPLE;
3787 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SYLK ) )
3788 nFormatId = SOT_FORMATSTR_ID_SYLK;
3789 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK ) )
3790 nFormatId = SOT_FORMATSTR_ID_LINK;
3791 else if ( bPreferText && aDataHelper.HasFormat( SOT_FORMAT_STRING ) ) // #i86734# the behaviour introduced in #i62773# is wrong when pasting
3792 nFormatId = SOT_FORMAT_STRING;
3793 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) )
3794 nFormatId = SOT_FORMAT_FILE_LIST;
3795 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE ) ) // #i62773# FILE_LIST/FILE before STRING (Unix file managers)
3796 nFormatId = SOT_FORMAT_FILE;
3797 else if ( aDataHelper.HasFormat( SOT_FORMAT_STRING ) )
3798 nFormatId = SOT_FORMAT_STRING;
3799 else if ( aDataHelper.HasFormat( SOT_FORMAT_GDIMETAFILE ) )
3800 nFormatId = SOT_FORMAT_GDIMETAFILE;
3801 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_PNG ) )
3802 nFormatId = SOT_FORMATSTR_ID_PNG;
3803 else if ( aDataHelper.HasFormat( SOT_FORMAT_BITMAP ) )
3804 nFormatId = SOT_FORMAT_BITMAP;
3805
3806 return nFormatId;
3807 }
3808
lcl_GetDropLinkId(const uno::Reference<datatransfer::XTransferable> & xTransfer)3809 sal_uLong lcl_GetDropLinkId( const uno::Reference<datatransfer::XTransferable>& xTransfer )
3810 {
3811 TransferableDataHelper aDataHelper( xTransfer );
3812
3813 sal_uLong nFormatId = 0;
3814 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) )
3815 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE;
3816 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) )
3817 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE;
3818 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK ) )
3819 nFormatId = SOT_FORMATSTR_ID_LINK;
3820 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) )
3821 nFormatId = SOT_FORMAT_FILE_LIST;
3822 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE ) )
3823 nFormatId = SOT_FORMAT_FILE;
3824 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SOLK ) )
3825 nFormatId = SOT_FORMATSTR_ID_SOLK;
3826 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) )
3827 nFormatId = SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR;
3828 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) )
3829 nFormatId = SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK;
3830 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
3831 nFormatId = SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR;
3832
3833 return nFormatId;
3834 }
3835
3836
ExecutePrivateDrop(const ExecuteDropEvent & rEvt)3837 sal_Int8 ScGridWindow::ExecutePrivateDrop( const ExecuteDropEvent& rEvt )
3838 {
3839 // hide drop marker
3840 // if (bDragRect)
3841 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3842 bDragRect = sal_False;
3843 UpdateDragRectOverlay();
3844
3845 ScModule* pScMod = SC_MOD();
3846 const ScDragData& rData = pScMod->GetDragData();
3847
3848 return DropTransferObj( rData.pCellTransfer, nDragStartX, nDragStartY,
3849 PixelToLogic(rEvt.maPosPixel), rEvt.mnAction );
3850 }
3851
DropTransferObj(ScTransferObj * pTransObj,SCCOL nDestPosX,SCROW nDestPosY,const Point & rLogicPos,sal_Int8 nDndAction)3852 sal_Int8 ScGridWindow::DropTransferObj( ScTransferObj* pTransObj, SCCOL nDestPosX, SCROW nDestPosY,
3853 const Point& rLogicPos, sal_Int8 nDndAction )
3854 {
3855 if ( !pTransObj )
3856 return 0;
3857
3858 ScDocument* pSourceDoc = pTransObj->GetSourceDocument();
3859 ScDocShell* pDocSh = pViewData->GetDocShell();
3860 ScDocument* pThisDoc = pViewData->GetDocument();
3861 ScViewFunc* pView = pViewData->GetView();
3862 SCTAB nThisTab = pViewData->GetTabNo();
3863 sal_uInt16 nFlags = pTransObj->GetDragSourceFlags();
3864
3865 sal_Bool bIsNavi = ( nFlags & SC_DROP_NAVIGATOR ) != 0;
3866 sal_Bool bIsMove = ( nDndAction == DND_ACTION_MOVE && !bIsNavi );
3867
3868 // workaround for wrong nDndAction on Windows when pressing solely
3869 // the Alt key during drag and drop;
3870 // can be removed after #i79215# has been fixed
3871 if ( meDragInsertMode != INS_NONE )
3872 {
3873 bIsMove = ( nDndAction & DND_ACTION_MOVE && !bIsNavi );
3874 }
3875
3876 sal_Bool bIsLink = ( nDndAction == DND_ACTION_LINK );
3877
3878 ScRange aSource = pTransObj->GetRange();
3879
3880 // only use visible tab from source range - when dragging within one table,
3881 // all selected tables at the time of dropping are used (handled in MoveBlockTo)
3882 SCTAB nSourceTab = pTransObj->GetVisibleTab();
3883 aSource.aStart.SetTab( nSourceTab );
3884 aSource.aEnd.SetTab( nSourceTab );
3885
3886 SCCOL nSizeX = aSource.aEnd.Col() - aSource.aStart.Col() + 1;
3887 SCROW nSizeY = (bIsMove ? (aSource.aEnd.Row() - aSource.aStart.Row() + 1) :
3888 pTransObj->GetNonFilteredRows()); // copy/link: no filtered rows
3889 ScRange aDest( nDestPosX, nDestPosY, nThisTab,
3890 nDestPosX + nSizeX - 1, nDestPosY + nSizeY - 1, nThisTab );
3891
3892
3893 /* NOTE: AcceptPrivateDrop() already checked for filtered conditions during
3894 * dragging and adapted drawing of the selection frame. We check here
3895 * (again) because this may actually also be called from PasteSelection(),
3896 * we would have to duplicate determination of flags and destination range
3897 * and would lose the context of the "filtered destination is OK" cases
3898 * below, which is already awkward enough as is. */
3899
3900 // Don't move filtered source.
3901 bool bFiltered = (bIsMove && pTransObj->HasFilteredRows());
3902 if (!bFiltered)
3903 {
3904 if (pSourceDoc != pThisDoc && ((nFlags & SC_DROP_TABLE) ||
3905 (!bIsLink && meDragInsertMode == INS_NONE)))
3906 {
3907 // Nothing. Either entire sheet to be dropped, or the one case
3908 // where PasteFromClip() is to be called that handles a filtered
3909 // destination itself. Drag-copy from another document without
3910 // inserting cells.
3911 }
3912 else
3913 // Don't copy or move to filtered destination.
3914 bFiltered = ScViewUtil::HasFiltered( aDest, pThisDoc);
3915 }
3916
3917 sal_Bool bDone = sal_False;
3918
3919 if (!bFiltered && pSourceDoc == pThisDoc)
3920 {
3921 if ( nFlags & SC_DROP_TABLE ) // whole sheet?
3922 {
3923 if ( pThisDoc->IsDocEditable() )
3924 {
3925 SCTAB nSrcTab = aSource.aStart.Tab();
3926 pViewData->GetDocShell()->MoveTable( nSrcTab, nThisTab, !bIsMove, sal_True ); // with Undo
3927 pView->SetTabNo( nThisTab, sal_True );
3928 bDone = sal_True;
3929 }
3930 }
3931 else // move/copy block
3932 {
3933 String aChartName;
3934 if (pThisDoc->HasChartAtPoint( nThisTab, rLogicPos, &aChartName ))
3935 {
3936 String aRangeName;
3937 aSource.Format( aRangeName, SCR_ABS_3D, pThisDoc );
3938 SfxStringItem aNameItem( SID_CHART_NAME, aChartName );
3939 SfxStringItem aRangeItem( SID_CHART_SOURCE, aRangeName );
3940 sal_uInt16 nId = bIsMove ? SID_CHART_SOURCE : SID_CHART_ADDSOURCE;
3941 pViewData->GetDispatcher().Execute( nId, SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD,
3942 &aRangeItem, &aNameItem, (void*) NULL );
3943 bDone = sal_True;
3944 }
3945 else if ( pThisDoc->GetDPAtCursor( nDestPosX, nDestPosY, nThisTab ) )
3946 {
3947 // drop on DataPilot table: try to sort, fail if that isn't possible
3948
3949 ScAddress aDestPos( nDestPosX, nDestPosY, nThisTab );
3950 if ( aDestPos != aSource.aStart )
3951 bDone = pViewData->GetView()->DataPilotMove( aSource, aDestPos );
3952 else
3953 bDone = sal_True; // same position: nothing
3954 }
3955 else if ( nDestPosX != aSource.aStart.Col() || nDestPosY != aSource.aStart.Row() ||
3956 nSourceTab != nThisTab )
3957 {
3958 String aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY );
3959 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
3960
3961 bDone = sal_True;
3962 if ( meDragInsertMode != INS_NONE )
3963 {
3964 // call with bApi = sal_True to avoid error messages in drop handler
3965 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, sal_True /*bRecord*/, sal_True /*bApi*/, sal_True /*bPartOfPaste*/ );
3966 if ( bDone )
3967 {
3968 if ( nThisTab == nSourceTab )
3969 {
3970 if ( meDragInsertMode == INS_CELLSDOWN &&
3971 nDestPosX == aSource.aStart.Col() && nDestPosY < aSource.aStart.Row() )
3972 {
3973 bDone = aSource.Move( 0, nSizeY, 0, pSourceDoc );
3974 }
3975 else if ( meDragInsertMode == INS_CELLSRIGHT &&
3976 nDestPosY == aSource.aStart.Row() && nDestPosX < aSource.aStart.Col() )
3977 {
3978 bDone = aSource.Move( nSizeX, 0, 0, pSourceDoc );
3979 }
3980 }
3981 pDocSh->UpdateOle( pViewData );
3982 pView->CellContentChanged();
3983 }
3984 }
3985
3986 if ( bDone )
3987 {
3988 if ( bIsLink )
3989 {
3990 // call with bApi = sal_True to avoid error messages in drop handler
3991 bDone = pView->LinkBlock( aSource, aDest.aStart, sal_True /*bApi*/ );
3992 }
3993 else
3994 {
3995 // call with bApi = sal_True to avoid error messages in drop handler
3996 bDone = pView->MoveBlockTo( aSource, aDest.aStart, bIsMove, sal_True /*bRecord*/, sal_True /*bPaint*/, sal_True /*bApi*/ );
3997 }
3998 }
3999
4000 if ( bDone && meDragInsertMode != INS_NONE && bIsMove && nThisTab == nSourceTab )
4001 {
4002 DelCellCmd eCmd = DEL_NONE;
4003 if ( meDragInsertMode == INS_CELLSDOWN )
4004 {
4005 eCmd = DEL_CELLSUP;
4006 }
4007 else if ( meDragInsertMode == INS_CELLSRIGHT )
4008 {
4009 eCmd = DEL_CELLSLEFT;
4010 }
4011
4012 if ( ( eCmd == DEL_CELLSUP && nDestPosX == aSource.aStart.Col() ) ||
4013 ( eCmd == DEL_CELLSLEFT && nDestPosY == aSource.aStart.Row() ) )
4014 {
4015 // call with bApi = sal_True to avoid error messages in drop handler
4016 bDone = pDocSh->GetDocFunc().DeleteCells( aSource, NULL, eCmd, sal_True /*bRecord*/, sal_True /*bApi*/ );
4017 if ( bDone )
4018 {
4019 if ( eCmd == DEL_CELLSUP && nDestPosY > aSource.aEnd.Row() )
4020 {
4021 bDone = aDest.Move( 0, -nSizeY, 0, pThisDoc );
4022 }
4023 else if ( eCmd == DEL_CELLSLEFT && nDestPosX > aSource.aEnd.Col() )
4024 {
4025 bDone = aDest.Move( -nSizeX, 0, 0, pThisDoc );
4026 }
4027 pDocSh->UpdateOle( pViewData );
4028 pView->CellContentChanged();
4029 }
4030 }
4031 }
4032
4033 if ( bDone )
4034 {
4035 pView->MarkRange( aDest, sal_False, sal_False );
4036 pView->SetCursor( aDest.aEnd.Col(), aDest.aEnd.Row() );
4037 }
4038
4039 pDocSh->GetUndoManager()->LeaveListAction();
4040
4041 if (!bDone)
4042 Sound::Beep(); // instead of error message in drop handler
4043 }
4044 else
4045 bDone = sal_True; // nothing to do
4046 }
4047
4048 if (bDone)
4049 pTransObj->SetDragWasInternal(); // don't delete source in DragFinished
4050 }
4051 else if ( !bFiltered && pSourceDoc ) // between documents
4052 {
4053 if ( nFlags & SC_DROP_TABLE ) // copy/link sheets between documents
4054 {
4055 if ( pThisDoc->IsDocEditable() )
4056 {
4057 ScDocShell* pSrcShell = pTransObj->GetSourceDocShell();
4058
4059 SCTAB nTabs[MAXTABCOUNT];
4060
4061 ScMarkData aMark = pTransObj->GetSourceMarkData();
4062 SCTAB nTabCount = pSourceDoc->GetTableCount();
4063 SCTAB nTabSelCount = 0;
4064
4065 for(SCTAB i=0; i<nTabCount; i++)
4066 {
4067 if(aMark.GetTableSelect(i))
4068 {
4069 nTabs[nTabSelCount++]=i;
4070 for(SCTAB j=i+1;j<nTabCount;j++)
4071 {
4072 if((!pSourceDoc->IsVisible(j))&&(pSourceDoc->IsScenario(j)))
4073 {
4074 nTabs[nTabSelCount++]=j;
4075 i=j;
4076 }
4077 else break;
4078 }
4079 }
4080 }
4081
4082 pView->ImportTables( pSrcShell,nTabSelCount, nTabs, bIsLink, nThisTab );
4083 bDone = sal_True;
4084 }
4085 }
4086 else if ( bIsLink )
4087 {
4088 // as in PasteDDE
4089 // (external references might be used instead?)
4090
4091 SfxObjectShell* pSourceSh = pSourceDoc->GetDocumentShell();
4092 DBG_ASSERT(pSourceSh, "drag document has no shell");
4093 if (pSourceSh)
4094 {
4095 String aUndo = ScGlobal::GetRscString( STR_UNDO_COPY );
4096 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
4097
4098 bDone = sal_True;
4099 if ( meDragInsertMode != INS_NONE )
4100 {
4101 // call with bApi = sal_True to avoid error messages in drop handler
4102 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, sal_True /*bRecord*/, sal_True /*bApi*/, sal_True /*bPartOfPaste*/ );
4103 if ( bDone )
4104 {
4105 pDocSh->UpdateOle( pViewData );
4106 pView->CellContentChanged();
4107 }
4108 }
4109
4110 if ( bDone )
4111 {
4112 String aApp = Application::GetAppName();
4113 String aTopic = pSourceSh->GetTitle( SFX_TITLE_FULLNAME );
4114 String aItem;
4115 aSource.Format( aItem, SCA_VALID | SCA_TAB_3D, pSourceDoc );
4116
4117 // TODO: we could define ocQuote for "
4118 const String aQuote( '"' );
4119 const String& sSep = ScCompiler::GetNativeSymbol( ocSep);
4120 String aFormula( '=' );
4121 aFormula += ScCompiler::GetNativeSymbol( ocDde);
4122 aFormula += ScCompiler::GetNativeSymbol( ocOpen);
4123 aFormula += aQuote;
4124 aFormula += aApp;
4125 aFormula += aQuote;
4126 aFormula += sSep;
4127 aFormula += aQuote;
4128 aFormula += aTopic;
4129 aFormula += aQuote;
4130 aFormula += sSep;
4131 aFormula += aQuote;
4132 aFormula += aItem;
4133 aFormula += aQuote;
4134 aFormula += ScCompiler::GetNativeSymbol( ocClose);
4135
4136 pView->DoneBlockMode();
4137 pView->InitBlockMode( nDestPosX, nDestPosY, nThisTab );
4138 pView->MarkCursor( nDestPosX + nSizeX - 1,
4139 nDestPosY + nSizeY - 1, nThisTab );
4140
4141 pView->EnterMatrix( aFormula );
4142
4143 pView->MarkRange( aDest, sal_False, sal_False );
4144 pView->SetCursor( aDest.aEnd.Col(), aDest.aEnd.Row() );
4145 }
4146
4147 pDocSh->GetUndoManager()->LeaveListAction();
4148 }
4149 }
4150 else
4151 {
4152 //! HasSelectedBlockMatrixFragment without selected sheet?
4153 //! or don't start dragging on a part of a matrix
4154
4155 String aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY );
4156 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
4157
4158 bDone = sal_True;
4159 if ( meDragInsertMode != INS_NONE )
4160 {
4161 // call with bApi = sal_True to avoid error messages in drop handler
4162 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, sal_True /*bRecord*/, sal_True /*bApi*/, sal_True /*bPartOfPaste*/ );
4163 if ( bDone )
4164 {
4165 pDocSh->UpdateOle( pViewData );
4166 pView->CellContentChanged();
4167 }
4168 }
4169
4170 if ( bDone )
4171 {
4172 pView->Unmark(); // before SetCursor, so CheckSelectionTransfer isn't called with a selection
4173 pView->SetCursor( nDestPosX, nDestPosY );
4174 bDone = pView->PasteFromClip( IDF_ALL, pTransObj->GetDocument() ); // clip-doc
4175 if ( bDone )
4176 {
4177 pView->MarkRange( aDest, sal_False, sal_False );
4178 pView->SetCursor( aDest.aEnd.Col(), aDest.aEnd.Row() );
4179 }
4180 }
4181
4182 pDocSh->GetUndoManager()->LeaveListAction();
4183
4184 // no longer call ResetMark here - the inserted block has been selected
4185 // and may have been copied to primary selection
4186 }
4187 }
4188
4189 sal_Int8 nRet = bDone ? nDndAction : DND_ACTION_NONE;
4190 return nRet;
4191 }
4192
ExecuteDrop(const ExecuteDropEvent & rEvt)4193 sal_Int8 ScGridWindow::ExecuteDrop( const ExecuteDropEvent& rEvt )
4194 {
4195 DrawMarkDropObj( NULL ); // drawing layer
4196
4197 ScModule* pScMod = SC_MOD();
4198 const ScDragData& rData = pScMod->GetDragData();
4199 if (rData.pCellTransfer)
4200 return ExecutePrivateDrop( rEvt );
4201
4202 Point aPos = rEvt.maPosPixel;
4203
4204 if ( rData.aLinkDoc.Len() )
4205 {
4206 // try to insert a link
4207
4208 sal_Bool bOk = sal_True;
4209 String aThisName;
4210 ScDocShell* pDocSh = pViewData->GetDocShell();
4211 if (pDocSh && pDocSh->HasName())
4212 aThisName = pDocSh->GetMedium()->GetName();
4213
4214 if ( rData.aLinkDoc == aThisName ) // error - no link within a document
4215 bOk = sal_False;
4216 else
4217 {
4218 ScViewFunc* pView = pViewData->GetView();
4219 if ( rData.aLinkTable.Len() )
4220 pView->InsertTableLink( rData.aLinkDoc, EMPTY_STRING, EMPTY_STRING,
4221 rData.aLinkTable );
4222 else if ( rData.aLinkArea.Len() )
4223 {
4224 SCsCOL nPosX;
4225 SCsROW nPosY;
4226 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
4227 pView->MoveCursorAbs( nPosX, nPosY, SC_FOLLOW_NONE, sal_False, sal_False );
4228
4229 pView->InsertAreaLink( rData.aLinkDoc, EMPTY_STRING, EMPTY_STRING,
4230 rData.aLinkArea, 0 );
4231 }
4232 else
4233 {
4234 DBG_ERROR("drop with link: no sheet nor area");
4235 bOk = sal_False;
4236 }
4237 }
4238
4239 return bOk ? rEvt.mnAction : DND_ACTION_NONE; // don't try anything else
4240 }
4241
4242 Point aLogicPos = PixelToLogic(aPos);
4243 sal_Bool bIsLink = ( rEvt.mnAction == DND_ACTION_LINK );
4244
4245 if (!bIsLink && rData.pDrawTransfer)
4246 {
4247 sal_uInt16 nFlags = rData.pDrawTransfer->GetDragSourceFlags();
4248
4249 sal_Bool bIsNavi = ( nFlags & SC_DROP_NAVIGATOR ) != 0;
4250 sal_Bool bIsMove = ( rEvt.mnAction == DND_ACTION_MOVE && !bIsNavi );
4251
4252 bPasteIsMove = bIsMove;
4253
4254 pViewData->GetView()->PasteDraw( aLogicPos, rData.pDrawTransfer->GetModel() );
4255
4256 if (bPasteIsMove)
4257 rData.pDrawTransfer->SetDragWasInternal();
4258 bPasteIsMove = sal_False;
4259
4260 return rEvt.mnAction;
4261 }
4262
4263
4264 SCsCOL nPosX;
4265 SCsROW nPosY;
4266 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
4267
4268 if (rData.aJumpTarget.Len())
4269 {
4270 // internal bookmark (from Navigator)
4271 // bookmark clipboard formats are in PasteScDataObject
4272
4273 if ( !rData.pJumpLocalDoc || rData.pJumpLocalDoc == pViewData->GetDocument() )
4274 {
4275 pViewData->GetViewShell()->InsertBookmark( rData.aJumpText, rData.aJumpTarget,
4276 nPosX, nPosY );
4277 return rEvt.mnAction;
4278 }
4279 }
4280
4281 ScDocument* pThisDoc = pViewData->GetDocument();
4282 SdrObject* pHitObj = pThisDoc->GetObjectAtPoint( pViewData->GetTabNo(), PixelToLogic(aPos) );
4283 if ( pHitObj && bIsLink )
4284 {
4285 // dropped on drawing object
4286 // PasteOnDrawObjectLinked checks for valid formats
4287 if ( pViewData->GetView()->PasteOnDrawObjectLinked( rEvt.maDropEvent.Transferable, *pHitObj ) )
4288 return rEvt.mnAction;
4289 }
4290
4291 sal_Bool bDone = sal_False;
4292
4293 sal_uLong nFormatId = bIsLink ?
4294 lcl_GetDropLinkId( rEvt.maDropEvent.Transferable ) :
4295 lcl_GetDropFormatId( rEvt.maDropEvent.Transferable );
4296 if ( nFormatId )
4297 {
4298 pScMod->SetInExecuteDrop( sal_True ); // #i28468# prevent error messages from PasteDataFormat
4299 bPasteIsDrop = sal_True;
4300 bDone = pViewData->GetView()->PasteDataFormat(
4301 nFormatId, rEvt.maDropEvent.Transferable, nPosX, nPosY, &aLogicPos, bIsLink );
4302 bPasteIsDrop = sal_False;
4303 pScMod->SetInExecuteDrop( sal_False );
4304 }
4305
4306 sal_Int8 nRet = bDone ? rEvt.mnAction : DND_ACTION_NONE;
4307 return nRet;
4308 }
4309
4310 //--------------------------------------------------------
4311
PasteSelection(const Point & rPosPixel)4312 void ScGridWindow::PasteSelection( const Point& rPosPixel )
4313 {
4314 Point aLogicPos = PixelToLogic( rPosPixel );
4315
4316 SCsCOL nPosX;
4317 SCsROW nPosY;
4318 pViewData->GetPosFromPixel( rPosPixel.X(), rPosPixel.Y(), eWhich, nPosX, nPosY );
4319
4320 ScSelectionTransferObj* pOwnSelection = SC_MOD()->GetSelectionTransfer();
4321 if ( pOwnSelection )
4322 {
4323 // within Calc
4324
4325 ScTransferObj* pCellTransfer = pOwnSelection->GetCellData();
4326 if ( pCellTransfer )
4327 {
4328 // keep a reference to the data in case the selection is changed during paste
4329 uno::Reference<datatransfer::XTransferable> xRef( pCellTransfer );
4330 DropTransferObj( pCellTransfer, nPosX, nPosY, aLogicPos, DND_ACTION_COPY );
4331 }
4332 else
4333 {
4334 ScDrawTransferObj* pDrawTransfer = pOwnSelection->GetDrawData();
4335 if ( pDrawTransfer )
4336 {
4337 // keep a reference to the data in case the selection is changed during paste
4338 uno::Reference<datatransfer::XTransferable> xRef( pDrawTransfer );
4339
4340 // #96821# bSameDocClipboard argument for PasteDraw is needed
4341 // because only DragData is checked directly inside PasteDraw
4342 pViewData->GetView()->PasteDraw( aLogicPos, pDrawTransfer->GetModel(), sal_False,
4343 pDrawTransfer->GetSourceDocID() == pViewData->GetDocument()->GetDocumentID() );
4344 }
4345 }
4346 }
4347 else
4348 {
4349 // get selection from system
4350
4351 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSelection( this ) );
4352 uno::Reference<datatransfer::XTransferable> xTransferable = aDataHelper.GetTransferable();
4353 if ( xTransferable.is() )
4354 {
4355 sal_uLong nFormatId = lcl_GetDropFormatId( xTransferable, true );
4356 if ( nFormatId )
4357 {
4358 bPasteIsDrop = sal_True;
4359 pViewData->GetView()->PasteDataFormat( nFormatId, xTransferable, nPosX, nPosY, &aLogicPos );
4360 bPasteIsDrop = sal_False;
4361 }
4362 }
4363 }
4364 }
4365
4366 //--------------------------------------------------------
4367
UpdateEditViewPos()4368 void ScGridWindow::UpdateEditViewPos()
4369 {
4370 if (pViewData->HasEditView(eWhich))
4371 {
4372 EditView* pView;
4373 SCCOL nCol;
4374 SCROW nRow;
4375 pViewData->GetEditView( eWhich, pView, nCol, nRow );
4376 SCCOL nEndCol = pViewData->GetEditEndCol();
4377 SCROW nEndRow = pViewData->GetEditEndRow();
4378
4379 // hide EditView?
4380
4381 sal_Bool bHide = ( nEndCol<pViewData->GetPosX(eHWhich) || nEndRow<pViewData->GetPosY(eVWhich) );
4382 if ( SC_MOD()->IsFormulaMode() )
4383 if ( pViewData->GetTabNo() != pViewData->GetRefTabNo() )
4384 bHide = sal_True;
4385
4386 if (bHide)
4387 {
4388 Rectangle aRect = pView->GetOutputArea();
4389 long nHeight = aRect.Bottom() - aRect.Top();
4390 aRect.Top() = PixelToLogic(GetOutputSizePixel(), pViewData->GetLogicMode()).
4391 Height() * 2;
4392 aRect.Bottom() = aRect.Top() + nHeight;
4393 pView->SetOutputArea( aRect );
4394 pView->HideCursor();
4395 }
4396 else
4397 {
4398 // bForceToTop = sal_True for editing
4399 Rectangle aPixRect = pViewData->GetEditArea( eWhich, nCol, nRow, this, NULL, sal_True );
4400 Point aScrPos = PixelToLogic( aPixRect.TopLeft(), pViewData->GetLogicMode() );
4401
4402 Rectangle aRect = pView->GetOutputArea();
4403 aRect.SetPos( aScrPos );
4404 pView->SetOutputArea( aRect );
4405 pView->ShowCursor();
4406 }
4407 }
4408 }
4409
ScrollPixel(long nDifX,long nDifY)4410 void ScGridWindow::ScrollPixel( long nDifX, long nDifY )
4411 {
4412 ClickExtern();
4413 HideNoteMarker();
4414
4415 bIsInScroll = sal_True;
4416 //sal_Bool bXor=DrawBeforeScroll();
4417
4418 SetMapMode(MAP_PIXEL);
4419 Scroll( nDifX, nDifY, SCROLL_CHILDREN );
4420 SetMapMode( GetDrawMapMode() ); // verschobenen MapMode erzeugen
4421
4422 UpdateEditViewPos();
4423
4424 DrawAfterScroll(); //bXor);
4425 bIsInScroll = sal_False;
4426 }
4427
4428 // Formeln neu zeichnen -------------------------------------------------
4429
UpdateFormulas()4430 void ScGridWindow::UpdateFormulas()
4431 {
4432 if (pViewData->GetView()->IsMinimized())
4433 return;
4434
4435 if ( nPaintCount )
4436 {
4437 // nicht anfangen, verschachtelt zu painten
4438 // (dann wuerde zumindest der MapMode nicht mehr stimmen)
4439
4440 bNeedsRepaint = sal_True; // -> am Ende vom Paint nochmal Invalidate auf alles
4441 aRepaintPixel = Rectangle(); // alles
4442 return;
4443 }
4444
4445 SCCOL nX1 = pViewData->GetPosX( eHWhich );
4446 SCROW nY1 = pViewData->GetPosY( eVWhich );
4447 SCCOL nX2 = nX1 + pViewData->VisibleCellsX( eHWhich );
4448 SCROW nY2 = nY1 + pViewData->VisibleCellsY( eVWhich );
4449
4450 if (nX2 > MAXCOL) nX2 = MAXCOL;
4451 if (nY2 > MAXROW) nY2 = MAXROW;
4452
4453 // Draw( nX1, nY1, nX2, nY2, SC_UPDATE_CHANGED );
4454
4455 // don't draw directly - instead use OutputData to find changed area and invalidate
4456
4457 SCROW nPosY = nY1;
4458
4459 ScDocShell* pDocSh = pViewData->GetDocShell();
4460 ScDocument* pDoc = pDocSh->GetDocument();
4461 SCTAB nTab = pViewData->GetTabNo();
4462
4463 pDoc->ExtendHidden( nX1, nY1, nX2, nY2, nTab );
4464
4465 Point aScrPos = pViewData->GetScrPos( nX1, nY1, eWhich );
4466 long nMirrorWidth = GetSizePixel().Width();
4467 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
4468 // unused variable long nLayoutSign = bLayoutRTL ? -1 : 1;
4469 if ( bLayoutRTL )
4470 {
4471 long nEndPixel = pViewData->GetScrPos( nX2+1, nPosY, eWhich ).X();
4472 nMirrorWidth = aScrPos.X() - nEndPixel;
4473 aScrPos.X() = nEndPixel + 1;
4474 }
4475
4476 long nScrX = aScrPos.X();
4477 long nScrY = aScrPos.Y();
4478
4479 double nPPTX = pViewData->GetPPTX();
4480 double nPPTY = pViewData->GetPPTY();
4481
4482 ScTableInfo aTabInfo;
4483 pDoc->FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nTab, nPPTX, nPPTY, sal_False, sal_False );
4484
4485 Fraction aZoomX = pViewData->GetZoomX();
4486 Fraction aZoomY = pViewData->GetZoomY();
4487 ScOutputData aOutputData( this, OUTTYPE_WINDOW, aTabInfo, pDoc, nTab,
4488 nScrX, nScrY, nX1, nY1, nX2, nY2, nPPTX, nPPTY,
4489 &aZoomX, &aZoomY );
4490 aOutputData.SetMirrorWidth( nMirrorWidth );
4491
4492 aOutputData.FindChanged();
4493
4494 // #122149# do not use old GetChangedArea() which used polygon-based Regions, but use
4495 // the region-band based new version; anyways, only rectangles are added
4496 Region aChangedRegion( aOutputData.GetChangedAreaRegion() ); // logic (PixelToLogic)
4497 if(!aChangedRegion.IsEmpty())
4498 {
4499 Invalidate(aChangedRegion);
4500 }
4501
4502 CheckNeedsRepaint(); // #i90362# used to be called via Draw() - still needed here
4503 }
4504
UpdateAutoFillMark(sal_Bool bMarked,const ScRange & rMarkRange)4505 void ScGridWindow::UpdateAutoFillMark(sal_Bool bMarked, const ScRange& rMarkRange)
4506 {
4507 if ( bMarked != bAutoMarkVisible || ( bMarked && rMarkRange.aEnd != aAutoMarkPos ) )
4508 {
4509 HideCursor();
4510 bAutoMarkVisible = bMarked;
4511 if ( bMarked )
4512 aAutoMarkPos = rMarkRange.aEnd;
4513 ShowCursor();
4514
4515 UpdateAutoFillOverlay();
4516 }
4517 }
4518
UpdateListValPos(sal_Bool bVisible,const ScAddress & rPos)4519 void ScGridWindow::UpdateListValPos( sal_Bool bVisible, const ScAddress& rPos )
4520 {
4521 sal_Bool bOldButton = bListValButton;
4522 ScAddress aOldPos = aListValPos;
4523
4524 bListValButton = bVisible;
4525 aListValPos = rPos;
4526
4527 if ( bListValButton )
4528 {
4529 if ( !bOldButton || aListValPos != aOldPos )
4530 {
4531 // paint area of new button
4532 Invalidate( PixelToLogic( GetListValButtonRect( aListValPos ) ) );
4533 }
4534 }
4535 if ( bOldButton )
4536 {
4537 if ( !bListValButton || aListValPos != aOldPos )
4538 {
4539 // paint area of old button
4540 Invalidate( PixelToLogic( GetListValButtonRect( aOldPos ) ) );
4541 }
4542 }
4543 }
4544
HideCursor()4545 void ScGridWindow::HideCursor()
4546 {
4547 ++nCursorHideCount;
4548 if (nCursorHideCount==1)
4549 {
4550 DrawCursor();
4551 DrawAutoFillMark();
4552 }
4553 }
4554
ShowCursor()4555 void ScGridWindow::ShowCursor()
4556 {
4557 if (nCursorHideCount==0)
4558 {
4559 DBG_ERROR("zuviel ShowCursor");
4560 return;
4561 }
4562
4563 if (nCursorHideCount==1)
4564 {
4565 // #i57745# Draw the cursor before setting the variable, in case the
4566 // GetSizePixel call from drawing causes a repaint (resize handler is called)
4567 DrawAutoFillMark();
4568 DrawCursor();
4569 }
4570
4571 --nCursorHideCount;
4572 }
4573
GetFocus()4574 void __EXPORT ScGridWindow::GetFocus()
4575 {
4576 ScTabViewShell* pViewShell = pViewData->GetViewShell();
4577 pViewShell->GotFocus();
4578 pViewShell->SetFormShellAtTop( sal_False ); // focus in GridWindow -> FormShell no longer on top
4579
4580 if (pViewShell->HasAccessibilityObjects())
4581 pViewShell->BroadcastAccessibility(ScAccGridWinFocusGotHint(eWhich, GetAccessible()));
4582
4583
4584 if ( !SC_MOD()->IsFormulaMode() )
4585 {
4586 pViewShell->UpdateInputHandler();
4587 // StopMarking(); // falls Dialog (Fehler), weil dann kein ButtonUp
4588 // MO: nur wenn nicht im RefInput-Modus
4589 // -> GetFocus/MouseButtonDown-Reihenfolge
4590 // auf dem Mac
4591 }
4592
4593 Window::GetFocus();
4594 }
4595
LoseFocus()4596 void __EXPORT ScGridWindow::LoseFocus()
4597 {
4598 ScTabViewShell* pViewShell = pViewData->GetViewShell();
4599 pViewShell->LostFocus();
4600
4601 if (pViewShell->HasAccessibilityObjects())
4602 pViewShell->BroadcastAccessibility(ScAccGridWinFocusLostHint(eWhich, GetAccessible()));
4603
4604 Window::LoseFocus();
4605 }
4606
GetMousePosPixel() const4607 Point ScGridWindow::GetMousePosPixel() const { return aCurMousePos; }
4608
4609 //------------------------------------------------------------------------
4610
HitRangeFinder(const Point & rMouse,sal_Bool & rCorner,sal_uInt16 * pIndex,SCsCOL * pAddX,SCsROW * pAddY)4611 sal_Bool ScGridWindow::HitRangeFinder( const Point& rMouse, sal_Bool& rCorner,
4612 sal_uInt16* pIndex, SCsCOL* pAddX, SCsROW* pAddY )
4613 {
4614 sal_Bool bFound = sal_False;
4615 ScInputHandler* pHdl = SC_MOD()->GetInputHdl( pViewData->GetViewShell() );
4616 if (pHdl)
4617 {
4618 ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList();
4619 if ( pRangeFinder && !pRangeFinder->IsHidden() &&
4620 pRangeFinder->GetDocName() == pViewData->GetDocShell()->GetTitle() )
4621 {
4622 ScDocument* pDoc = pViewData->GetDocument();
4623 SCTAB nTab = pViewData->GetTabNo();
4624 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
4625 long nLayoutSign = bLayoutRTL ? -1 : 1;
4626
4627 SCsCOL nPosX;
4628 SCsROW nPosY;
4629 pViewData->GetPosFromPixel( rMouse.X(), rMouse.Y(), eWhich, nPosX, nPosY );
4630 // zusammengefasste (einzeln/Bereich) ???
4631 ScAddress aAddr( nPosX, nPosY, nTab );
4632
4633 // Point aNext = pViewData->GetScrPos( nPosX+1, nPosY+1, eWhich );
4634
4635 Point aNext = pViewData->GetScrPos( nPosX, nPosY, eWhich, sal_True );
4636 long nSizeXPix;
4637 long nSizeYPix;
4638 pViewData->GetMergeSizePixel( nPosX, nPosY, nSizeXPix, nSizeYPix );
4639 aNext.X() += nSizeXPix * nLayoutSign;
4640 aNext.Y() += nSizeYPix;
4641
4642 sal_Bool bCornerHor;
4643 if ( bLayoutRTL )
4644 bCornerHor = ( rMouse.X() >= aNext.X() && rMouse.X() <= aNext.X() + 8 );
4645 else
4646 bCornerHor = ( rMouse.X() >= aNext.X() - 8 && rMouse.X() <= aNext.X() );
4647
4648 sal_Bool bCellCorner = ( bCornerHor &&
4649 rMouse.Y() >= aNext.Y() - 8 && rMouse.Y() <= aNext.Y() );
4650 // corner is hit only if the mouse is within the cell
4651
4652 sal_uInt16 nCount = (sal_uInt16)pRangeFinder->Count();
4653 for (sal_uInt16 i=nCount; i;)
4654 {
4655 // rueckwaerts suchen, damit der zuletzt gepaintete Rahmen gefunden wird
4656 --i;
4657 ScRangeFindData* pData = pRangeFinder->GetObject(i);
4658 if ( pData && pData->aRef.In(aAddr) )
4659 {
4660 if (pIndex) *pIndex = i;
4661 if (pAddX) *pAddX = nPosX - pData->aRef.aStart.Col();
4662 if (pAddY) *pAddY = nPosY - pData->aRef.aStart.Row();
4663 bFound = sal_True;
4664 rCorner = ( bCellCorner && aAddr == pData->aRef.aEnd );
4665 break;
4666 }
4667 }
4668 }
4669 }
4670 return bFound;
4671 }
4672
4673 #define SCE_TOP 1
4674 #define SCE_BOTTOM 2
4675 #define SCE_LEFT 4
4676 #define SCE_RIGHT 8
4677 #define SCE_ALL 15
4678
lcl_PaintOneRange(ScDocShell * pDocSh,const ScRange & rRange,sal_uInt16 nEdges)4679 void lcl_PaintOneRange( ScDocShell* pDocSh, const ScRange& rRange, sal_uInt16 nEdges )
4680 {
4681 // der Range ist immer richtigherum
4682
4683 SCCOL nCol1 = rRange.aStart.Col();
4684 SCROW nRow1 = rRange.aStart.Row();
4685 SCTAB nTab1 = rRange.aStart.Tab();
4686 SCCOL nCol2 = rRange.aEnd.Col();
4687 SCROW nRow2 = rRange.aEnd.Row();
4688 SCTAB nTab2 = rRange.aEnd.Tab();
4689 sal_Bool bHiddenEdge = sal_False;
4690 SCROW nTmp;
4691
4692 ScDocument* pDoc = pDocSh->GetDocument();
4693 while ( nCol1 > 0 && pDoc->ColHidden(nCol1, nTab1) )
4694 {
4695 --nCol1;
4696 bHiddenEdge = sal_True;
4697 }
4698 while ( nCol2 < MAXCOL && pDoc->ColHidden(nCol2, nTab1) )
4699 {
4700 ++nCol2;
4701 bHiddenEdge = sal_True;
4702 }
4703 nTmp = pDoc->FirstVisibleRow(0, nRow1, nTab1);
4704 if (!ValidRow(nTmp))
4705 nTmp = 0;
4706 if (nTmp < nRow1)
4707 {
4708 nRow1 = nTmp;
4709 bHiddenEdge = sal_True;
4710 }
4711 nTmp = pDoc->FirstVisibleRow(nRow2, MAXROW, nTab1);
4712 if (!ValidRow(nTmp))
4713 nTmp = MAXROW;
4714 if (nTmp > nRow2)
4715 {
4716 nRow2 = nTmp;
4717 bHiddenEdge = sal_True;
4718 }
4719
4720 if ( nCol2 > nCol1 + 1 && nRow2 > nRow1 + 1 && !bHiddenEdge )
4721 {
4722 // nur an den Raendern entlang
4723 // (die Ecken werden evtl. zweimal getroffen)
4724
4725 if ( nEdges & SCE_TOP )
4726 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol2, nRow1, nTab2, PAINT_MARKS );
4727 if ( nEdges & SCE_LEFT )
4728 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol1, nRow2, nTab2, PAINT_MARKS );
4729 if ( nEdges & SCE_RIGHT )
4730 pDocSh->PostPaint( nCol2, nRow1, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
4731 if ( nEdges & SCE_BOTTOM )
4732 pDocSh->PostPaint( nCol1, nRow2, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
4733 }
4734 else // everything in one call
4735 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
4736 }
4737
lcl_PaintRefChanged(ScDocShell * pDocSh,const ScRange & rOldUn,const ScRange & rNewUn)4738 void lcl_PaintRefChanged( ScDocShell* pDocSh, const ScRange& rOldUn, const ScRange& rNewUn )
4739 {
4740 // Repaint fuer die Teile des Rahmens in Old, die bei New nicht mehr da sind
4741
4742 ScRange aOld = rOldUn;
4743 ScRange aNew = rNewUn;
4744 aOld.Justify();
4745 aNew.Justify();
4746
4747 if ( aOld.aStart == aOld.aEnd ) //! Tab ignorieren?
4748 pDocSh->GetDocument()->ExtendMerge(aOld);
4749 if ( aNew.aStart == aNew.aEnd ) //! Tab ignorieren?
4750 pDocSh->GetDocument()->ExtendMerge(aNew);
4751
4752 SCCOL nOldCol1 = aOld.aStart.Col();
4753 SCROW nOldRow1 = aOld.aStart.Row();
4754 SCCOL nOldCol2 = aOld.aEnd.Col();
4755 SCROW nOldRow2 = aOld.aEnd.Row();
4756 SCCOL nNewCol1 = aNew.aStart.Col();
4757 SCROW nNewRow1 = aNew.aStart.Row();
4758 SCCOL nNewCol2 = aNew.aEnd.Col();
4759 SCROW nNewRow2 = aNew.aEnd.Row();
4760 SCTAB nTab1 = aOld.aStart.Tab(); // Tab aendert sich nicht
4761 SCTAB nTab2 = aOld.aEnd.Tab();
4762
4763 if ( nNewRow2 < nOldRow1 || nNewRow1 > nOldRow2 ||
4764 nNewCol2 < nOldCol1 || nNewCol1 > nOldCol2 ||
4765 ( nNewCol1 != nOldCol1 && nNewRow1 != nOldRow1 &&
4766 nNewCol2 != nOldCol2 && nNewRow2 != nOldRow2 ) )
4767 {
4768 // komplett weggeschoben oder alle Seiten veraendert
4769 // (Abfrage <= statt < geht schief bei einzelnen Zeilen/Spalten)
4770
4771 lcl_PaintOneRange( pDocSh, aOld, SCE_ALL );
4772 }
4773 else // alle vier Kanten einzeln testen
4774 {
4775 // oberer Teil
4776 if ( nNewRow1 < nOldRow1 ) // nur obere Linie loeschen
4777 lcl_PaintOneRange( pDocSh, ScRange(
4778 nOldCol1, nOldRow1, nTab1, nOldCol2, nOldRow1, nTab2 ), SCE_ALL );
4779 else if ( nNewRow1 > nOldRow1 ) // den Teil, der oben wegkommt
4780 lcl_PaintOneRange( pDocSh, ScRange(
4781 nOldCol1, nOldRow1, nTab1, nOldCol2, nNewRow1-1, nTab2 ),
4782 SCE_ALL &~ SCE_BOTTOM );
4783
4784 // unterer Teil
4785 if ( nNewRow2 > nOldRow2 ) // nur untere Linie loeschen
4786 lcl_PaintOneRange( pDocSh, ScRange(
4787 nOldCol1, nOldRow2, nTab1, nOldCol2, nOldRow2, nTab2 ), SCE_ALL );
4788 else if ( nNewRow2 < nOldRow2 ) // den Teil, der unten wegkommt
4789 lcl_PaintOneRange( pDocSh, ScRange(
4790 nOldCol1, nNewRow2+1, nTab1, nOldCol2, nOldRow2, nTab2 ),
4791 SCE_ALL &~ SCE_TOP );
4792
4793 // linker Teil
4794 if ( nNewCol1 < nOldCol1 ) // nur linke Linie loeschen
4795 lcl_PaintOneRange( pDocSh, ScRange(
4796 nOldCol1, nOldRow1, nTab1, nOldCol1, nOldRow2, nTab2 ), SCE_ALL );
4797 else if ( nNewCol1 > nOldCol1 ) // den Teil, der links wegkommt
4798 lcl_PaintOneRange( pDocSh, ScRange(
4799 nOldCol1, nOldRow1, nTab1, nNewCol1-1, nOldRow2, nTab2 ),
4800 SCE_ALL &~ SCE_RIGHT );
4801
4802 // rechter Teil
4803 if ( nNewCol2 > nOldCol2 ) // nur rechte Linie loeschen
4804 lcl_PaintOneRange( pDocSh, ScRange(
4805 nOldCol2, nOldRow1, nTab1, nOldCol2, nOldRow2, nTab2 ), SCE_ALL );
4806 else if ( nNewCol2 < nOldCol2 ) // den Teil, der rechts wegkommt
4807 lcl_PaintOneRange( pDocSh, ScRange(
4808 nNewCol2+1, nOldRow1, nTab1, nOldCol2, nOldRow2, nTab2 ),
4809 SCE_ALL &~ SCE_LEFT );
4810 }
4811 }
4812
RFMouseMove(const MouseEvent & rMEvt,sal_Bool bUp)4813 void ScGridWindow::RFMouseMove( const MouseEvent& rMEvt, sal_Bool bUp )
4814 {
4815 ScInputHandler* pHdl = SC_MOD()->GetInputHdl( pViewData->GetViewShell() );
4816 if (!pHdl)
4817 return;
4818 ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList();
4819 if (!pRangeFinder || nRFIndex >= pRangeFinder->Count())
4820 return;
4821 ScRangeFindData* pData = pRangeFinder->GetObject( nRFIndex );
4822 if (!pData)
4823 return;
4824
4825 // Mauszeiger
4826
4827 if (bRFSize)
4828 SetPointer( Pointer( POINTER_CROSS ) );
4829 else
4830 SetPointer( Pointer( POINTER_HAND ) );
4831
4832 // Scrolling
4833
4834 sal_Bool bTimer = sal_False;
4835 Point aPos = rMEvt.GetPosPixel();
4836 SCsCOL nDx = 0;
4837 SCsROW nDy = 0;
4838 if ( aPos.X() < 0 ) nDx = -1;
4839 if ( aPos.Y() < 0 ) nDy = -1;
4840 Size aSize = GetOutputSizePixel();
4841 if ( aPos.X() >= aSize.Width() )
4842 nDx = 1;
4843 if ( aPos.Y() >= aSize.Height() )
4844 nDy = 1;
4845 if ( nDx != 0 || nDy != 0 )
4846 {
4847 if ( nDx != 0) pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) );
4848 if ( nDy != 0 ) pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) );
4849 bTimer = sal_True;
4850 }
4851
4852 // Umschalten bei Fixierung (damit Scrolling funktioniert)
4853
4854 if ( eWhich == pViewData->GetActivePart() ) //??
4855 {
4856 if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX )
4857 if ( nDx > 0 )
4858 {
4859 if ( eWhich == SC_SPLIT_TOPLEFT )
4860 pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT );
4861 else if ( eWhich == SC_SPLIT_BOTTOMLEFT )
4862 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT );
4863 }
4864
4865 if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX )
4866 if ( nDy > 0 )
4867 {
4868 if ( eWhich == SC_SPLIT_TOPLEFT )
4869 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT );
4870 else if ( eWhich == SC_SPLIT_TOPRIGHT )
4871 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT );
4872 }
4873 }
4874
4875 // Verschieben
4876
4877 SCsCOL nPosX;
4878 SCsROW nPosY;
4879 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
4880
4881 ScRange aOld = pData->aRef;
4882 ScRange aNew = aOld;
4883 if ( bRFSize )
4884 {
4885 aNew.aEnd.SetCol((SCCOL)nPosX);
4886 aNew.aEnd.SetRow((SCROW)nPosY);
4887 }
4888 else
4889 {
4890 long nStartX = nPosX - nRFAddX;
4891 if ( nStartX < 0 ) nStartX = 0;
4892 long nStartY = nPosY - nRFAddY;
4893 if ( nStartY < 0 ) nStartY = 0;
4894 long nEndX = nStartX + aOld.aEnd.Col() - aOld.aStart.Col();
4895 if ( nEndX > MAXCOL )
4896 {
4897 nStartX -= ( nEndX - MAXROW );
4898 nEndX = MAXCOL;
4899 }
4900 long nEndY = nStartY + aOld.aEnd.Row() - aOld.aStart.Row();
4901 if ( nEndY > MAXROW )
4902 {
4903 nStartY -= ( nEndY - MAXROW );
4904 nEndY = MAXROW;
4905 }
4906
4907 aNew.aStart.SetCol((SCCOL)nStartX);
4908 aNew.aStart.SetRow((SCROW)nStartY);
4909 aNew.aEnd.SetCol((SCCOL)nEndX);
4910 aNew.aEnd.SetRow((SCROW)nEndY);
4911 }
4912
4913 if ( bUp )
4914 aNew.Justify(); // beim ButtonUp wieder richtigherum
4915
4916 if ( aNew != aOld )
4917 {
4918 pHdl->UpdateRange( nRFIndex, aNew );
4919
4920 ScDocShell* pDocSh = pViewData->GetDocShell();
4921
4922 // nur das neuzeichnen, was sich veraendert hat...
4923 lcl_PaintRefChanged( pDocSh, aOld, aNew );
4924
4925 // neuen Rahmen nur drueberzeichnen (synchron)
4926 pDocSh->Broadcast( ScIndexHint( SC_HINT_SHOWRANGEFINDER, nRFIndex ) );
4927
4928 Update(); // was man bewegt, will man auch sofort sehen
4929 }
4930
4931 // Timer fuer Scrolling
4932
4933 if (bTimer)
4934 pViewData->GetView()->SetTimer( this, rMEvt ); // Event wiederholen
4935 else
4936 pViewData->GetView()->ResetTimer();
4937 }
4938
4939 //------------------------------------------------------------------------
4940
GetEditUrl(const Point & rPos,String * pName,String * pUrl,String * pTarget)4941 sal_Bool ScGridWindow::GetEditUrl( const Point& rPos,
4942 String* pName, String* pUrl, String* pTarget )
4943 {
4944 return GetEditUrlOrError( sal_False, rPos, pName, pUrl, pTarget );
4945 }
4946
GetEditUrlOrError(sal_Bool bSpellErr,const Point & rPos,String * pName,String * pUrl,String * pTarget)4947 sal_Bool ScGridWindow::GetEditUrlOrError( sal_Bool bSpellErr, const Point& rPos,
4948 String* pName, String* pUrl, String* pTarget )
4949 {
4950 //! nPosX/Y mit uebergeben?
4951 SCsCOL nPosX;
4952 SCsROW nPosY;
4953 pViewData->GetPosFromPixel( rPos.X(), rPos.Y(), eWhich, nPosX, nPosY );
4954
4955 SCTAB nTab = pViewData->GetTabNo();
4956 ScDocShell* pDocSh = pViewData->GetDocShell();
4957 ScDocument* pDoc = pDocSh->GetDocument();
4958 ScBaseCell* pCell = NULL;
4959
4960 sal_Bool bFound = lcl_GetHyperlinkCell( pDoc, nPosX, nPosY, nTab, pCell );
4961 if( !bFound )
4962 return sal_False;
4963
4964 ScHideTextCursor aHideCursor( pViewData, eWhich ); // before GetEditArea (MapMode is changed)
4965
4966 const ScPatternAttr* pPattern = pDoc->GetPattern( nPosX, nPosY, nTab );
4967 // bForceToTop = sal_False, use the cell's real position
4968 Rectangle aEditRect = pViewData->GetEditArea( eWhich, nPosX, nPosY, this, pPattern, sal_False );
4969 if (rPos.Y() < aEditRect.Top())
4970 return sal_False;
4971
4972 // vertikal kann (noch) nicht angeklickt werden:
4973
4974 if (pPattern->GetCellOrientation() != SVX_ORIENTATION_STANDARD)
4975 return sal_False;
4976
4977 sal_Bool bBreak = ((SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK)).GetValue() ||
4978 ((SvxCellHorJustify)((const SvxHorJustifyItem&)pPattern->
4979 GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_BLOCK);
4980 SvxCellHorJustify eHorJust = (SvxCellHorJustify)((SvxHorJustifyItem&)pPattern->
4981 GetItem(ATTR_HOR_JUSTIFY)).GetValue();
4982
4983 // EditEngine
4984
4985 ScFieldEditEngine aEngine( pDoc->GetEditPool() );
4986 ScSizeDeviceProvider aProv(pDocSh);
4987 aEngine.SetRefDevice( aProv.GetDevice() );
4988 aEngine.SetRefMapMode( MAP_100TH_MM );
4989 SfxItemSet aDefault( aEngine.GetEmptyItemSet() );
4990 pPattern->FillEditItemSet( &aDefault );
4991 SvxAdjust eSvxAdjust = SVX_ADJUST_LEFT;
4992 switch (eHorJust)
4993 {
4994 case SVX_HOR_JUSTIFY_LEFT:
4995 case SVX_HOR_JUSTIFY_REPEAT: // nicht implementiert
4996 case SVX_HOR_JUSTIFY_STANDARD: // always Text if an EditCell type
4997 eSvxAdjust = SVX_ADJUST_LEFT;
4998 break;
4999 case SVX_HOR_JUSTIFY_RIGHT:
5000 eSvxAdjust = SVX_ADJUST_RIGHT;
5001 break;
5002 case SVX_HOR_JUSTIFY_CENTER:
5003 eSvxAdjust = SVX_ADJUST_CENTER;
5004 break;
5005 case SVX_HOR_JUSTIFY_BLOCK:
5006 eSvxAdjust = SVX_ADJUST_BLOCK;
5007 break;
5008 }
5009 aDefault.Put( SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) );
5010 aEngine.SetDefaults( aDefault );
5011 if (bSpellErr)
5012 aEngine.SetControlWord( aEngine.GetControlWord() | EE_CNTRL_ONLINESPELLING );
5013
5014 MapMode aEditMode = pViewData->GetLogicMode(eWhich); // ohne Drawing-Skalierung
5015 Rectangle aLogicEdit = PixelToLogic( aEditRect, aEditMode );
5016 long nThisColLogic = aLogicEdit.Right() - aLogicEdit.Left() + 1;
5017 Size aPaperSize = Size( 1000000, 1000000 );
5018 if(pCell->GetCellType() == CELLTYPE_FORMULA)
5019 {
5020 long nSizeX = 0;
5021 long nSizeY = 0;
5022 pViewData->GetMergeSizePixel( nPosX, nPosY, nSizeX, nSizeY );
5023 aPaperSize = Size(nSizeX, nSizeY );
5024 aPaperSize = PixelToLogic(aPaperSize);
5025 }
5026
5027 if (bBreak)
5028 aPaperSize.Width() = nThisColLogic;
5029 aEngine.SetPaperSize( aPaperSize );
5030
5031 ::std::auto_ptr< EditTextObject > pTextObj;
5032 const EditTextObject* pData;
5033 if(pCell->GetCellType() == CELLTYPE_EDIT)
5034 {
5035 ((ScEditCell*)pCell)->GetData(pData);
5036 if (pData)
5037 aEngine.SetText(*pData);
5038 }
5039 else // HyperLink Formula cell
5040 {
5041 pTextObj.reset((static_cast<ScFormulaCell*>(pCell))->CreateURLObject());
5042 if (pTextObj.get())
5043 aEngine.SetText(*pTextObj);
5044 }
5045
5046 long nStartX = aLogicEdit.Left();
5047
5048 long nTextWidth = aEngine.CalcTextWidth();
5049 long nTextHeight = aEngine.GetTextHeight();
5050 if ( nTextWidth < nThisColLogic )
5051 {
5052 if (eHorJust == SVX_HOR_JUSTIFY_RIGHT)
5053 nStartX += nThisColLogic - nTextWidth;
5054 else if (eHorJust == SVX_HOR_JUSTIFY_CENTER)
5055 nStartX += (nThisColLogic - nTextWidth) / 2;
5056 }
5057
5058 aLogicEdit.Left() = nStartX;
5059 if (!bBreak)
5060 aLogicEdit.Right() = nStartX + nTextWidth;
5061
5062 // There is one glitch when dealing with a hyperlink cell and
5063 // the cell content is NUMERIC. This defaults to right aligned and
5064 // we need to adjust accordingly.
5065 if(pCell->GetCellType() == CELLTYPE_FORMULA &&
5066 static_cast<ScFormulaCell*>(pCell)->IsValue() &&
5067 eHorJust == SVX_HOR_JUSTIFY_STANDARD)
5068 {
5069 aLogicEdit.Right() = aLogicEdit.Left() + nThisColLogic - 1;
5070 aLogicEdit.Left() = aLogicEdit.Right() - nTextWidth;
5071 }
5072 aLogicEdit.Bottom() = aLogicEdit.Top() + nTextHeight;
5073
5074
5075 Point aLogicClick = PixelToLogic(rPos,aEditMode);
5076 if ( aLogicEdit.IsInside(aLogicClick) )
5077 {
5078 // aEngine.SetUpdateMode(sal_False);
5079 EditView aTempView( &aEngine, this );
5080 aTempView.SetOutputArea( aLogicEdit );
5081
5082 sal_Bool bRet = sal_False;
5083 MapMode aOld = GetMapMode();
5084 SetMapMode(aEditMode); // kein return mehr
5085
5086 if (bSpellErr) // Spelling-Fehler suchen
5087 {
5088 bRet = aTempView.IsWrongSpelledWordAtPos( rPos );
5089 if ( bRet )
5090 pViewData->GetView()->SetCursor( nPosX, nPosY ); // Cursor setzen
5091 }
5092 else // URL suchen
5093 {
5094 const SvxFieldItem* pFieldItem = aTempView.GetFieldUnderMousePointer();
5095
5096 if (pFieldItem)
5097 {
5098 const SvxFieldData* pField = pFieldItem->GetField();
5099 if ( pField && pField->ISA(SvxURLField) )
5100 {
5101 if ( pName || pUrl || pTarget )
5102 {
5103 const SvxURLField* pURLField = (const SvxURLField*)pField;
5104 if (pName)
5105 *pName = pURLField->GetRepresentation();
5106 if (pUrl)
5107 *pUrl = pURLField->GetURL();
5108 if (pTarget)
5109 *pTarget = pURLField->GetTargetFrame();
5110 }
5111 bRet = sal_True;
5112 }
5113 }
5114 }
5115
5116 SetMapMode(aOld);
5117
5118 // text cursor is restored in ScHideTextCursor dtor
5119
5120 return bRet;
5121 }
5122 return sal_False;
5123 }
5124
HasScenarioButton(const Point & rPosPixel,ScRange & rScenRange)5125 sal_Bool ScGridWindow::HasScenarioButton( const Point& rPosPixel, ScRange& rScenRange )
5126 {
5127 ScDocument* pDoc = pViewData->GetDocument();
5128 SCTAB nTab = pViewData->GetTabNo();
5129 SCTAB nTabCount = pDoc->GetTableCount();
5130 if ( nTab+1<nTabCount && pDoc->IsScenario(nTab+1) && !pDoc->IsScenario(nTab) )
5131 {
5132 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5133
5134 Size aButSize = pViewData->GetScenButSize();
5135 long nBWidth = aButSize.Width();
5136 if (!nBWidth)
5137 return sal_False; // noch kein Button gezeichnet -> da ist auch keiner
5138 long nBHeight = aButSize.Height();
5139 long nHSpace = (long)( SC_SCENARIO_HSPACE * pViewData->GetPPTX() );
5140
5141 //! Ranges an der Table cachen!!!!
5142
5143 ScMarkData aMarks;
5144 for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
5145 pDoc->MarkScenario( i, nTab, aMarks, sal_False, SC_SCENARIO_SHOWFRAME );
5146 ScRangeList aRanges;
5147 aMarks.FillRangeListWithMarks( &aRanges, sal_False );
5148
5149
5150 sal_uLong nRangeCount = aRanges.Count();
5151 for (sal_uLong j=0; j<nRangeCount; j++)
5152 {
5153 ScRange aRange = *aRanges.GetObject(j);
5154 // Szenario-Rahmen immer dann auf zusammengefasste Zellen erweitern, wenn
5155 // dadurch keine neuen nicht-ueberdeckten Zellen mit umrandet werden
5156 pDoc->ExtendTotalMerge( aRange );
5157
5158 sal_Bool bTextBelow = ( aRange.aStart.Row() == 0 );
5159
5160 Point aButtonPos;
5161 if ( bTextBelow )
5162 {
5163 aButtonPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aEnd.Row()+1,
5164 eWhich, sal_True );
5165 }
5166 else
5167 {
5168 aButtonPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aStart.Row(),
5169 eWhich, sal_True );
5170 aButtonPos.Y() -= nBHeight;
5171 }
5172 if ( bLayoutRTL )
5173 aButtonPos.X() -= nHSpace - 1;
5174 else
5175 aButtonPos.X() -= nBWidth - nHSpace; // same for top or bottom
5176
5177 Rectangle aButRect( aButtonPos, Size(nBWidth,nBHeight) );
5178 if ( aButRect.IsInside( rPosPixel ) )
5179 {
5180 rScenRange = aRange;
5181 return sal_True;
5182 }
5183 }
5184 }
5185
5186 return sal_False;
5187 }
5188
UpdateVisibleRange()5189 void ScGridWindow::UpdateVisibleRange()
5190 {
5191 // #163911# Update the visible range outside of paint (called when switching sheets).
5192 // Use the same logic here as in ScGridWindow::Draw.
5193
5194 SCCOL nPosX = pViewData->GetPosX( eHWhich );
5195 SCROW nPosY = pViewData->GetPosY( eVWhich );
5196
5197 SCCOL nXRight = nPosX + pViewData->VisibleCellsX(eHWhich);
5198 if (nXRight > MAXCOL) nXRight = MAXCOL;
5199 SCROW nYBottom = nPosY + pViewData->VisibleCellsY(eVWhich);
5200 if (nYBottom > MAXROW) nYBottom = MAXROW;
5201
5202 // Store the current visible range.
5203 maVisibleRange.mnCol1 = nPosX;
5204 maVisibleRange.mnCol2 = nXRight;
5205 maVisibleRange.mnRow1 = nPosY;
5206 maVisibleRange.mnRow2 = nYBottom;
5207 }
5208
5209 // #114409#
DrawLayerCreated()5210 void ScGridWindow::DrawLayerCreated()
5211 {
5212 SetMapMode( GetDrawMapMode() );
5213
5214 // initially create overlay objects
5215 ImpCreateOverlayObjects();
5216 }
5217
5218 // #114409#
CursorChanged()5219 void ScGridWindow::CursorChanged()
5220 {
5221 // here the created OverlayObjects may be transformed in later versions. For
5222 // now, just re-create them
5223
5224 UpdateCursorOverlay();
5225 }
5226
5227 // #114409#
ImpCreateOverlayObjects()5228 void ScGridWindow::ImpCreateOverlayObjects()
5229 {
5230 UpdateCursorOverlay();
5231 UpdateSelectionOverlay();
5232 UpdateAutoFillOverlay();
5233 UpdateDragRectOverlay();
5234 UpdateHeaderOverlay();
5235 UpdateShrinkOverlay();
5236 }
5237
5238 // #114409#
ImpDestroyOverlayObjects()5239 void ScGridWindow::ImpDestroyOverlayObjects()
5240 {
5241 DeleteCursorOverlay();
5242 DeleteSelectionOverlay();
5243 DeleteAutoFillOverlay();
5244 DeleteDragRectOverlay();
5245 DeleteHeaderOverlay();
5246 DeleteShrinkOverlay();
5247 }
5248
UpdateAllOverlays()5249 void ScGridWindow::UpdateAllOverlays()
5250 {
5251 // delete and re-allocate all overlay objects
5252
5253 ImpDestroyOverlayObjects();
5254 ImpCreateOverlayObjects();
5255 }
5256
DeleteCursorOverlay()5257 void ScGridWindow::DeleteCursorOverlay()
5258 {
5259 DELETEZ( mpOOCursors );
5260 }
5261
UpdateCursorOverlay()5262 void ScGridWindow::UpdateCursorOverlay()
5263 {
5264 MapMode aDrawMode = GetDrawMapMode();
5265 MapMode aOldMode = GetMapMode();
5266 if ( aOldMode != aDrawMode )
5267 SetMapMode( aDrawMode );
5268
5269 // Existing OverlayObjects may be transformed in later versions.
5270 // For now, just re-create them.
5271
5272 DeleteCursorOverlay();
5273
5274 std::vector<Rectangle> aPixelRects;
5275
5276 //
5277 // determine the cursor rectangles in pixels (moved from ScGridWindow::DrawCursor)
5278 //
5279
5280 SCTAB nTab = pViewData->GetTabNo();
5281 SCCOL nX = pViewData->GetCurX();
5282 SCROW nY = pViewData->GetCurY();
5283
5284 if (!maVisibleRange.isInside(nX, nY))
5285 return;
5286
5287 // don't show the cursor in overlapped cells
5288
5289 ScDocument* pDoc = pViewData->GetDocument();
5290 const ScPatternAttr* pPattern = pDoc->GetPattern(nX,nY,nTab);
5291 const ScMergeFlagAttr& rMergeFlag = (const ScMergeFlagAttr&) pPattern->GetItem(ATTR_MERGE_FLAG);
5292 sal_Bool bOverlapped = rMergeFlag.IsOverlapped();
5293
5294 // left or above of the screen?
5295
5296 sal_Bool bVis = ( nX>=pViewData->GetPosX(eHWhich) && nY>=pViewData->GetPosY(eVWhich) );
5297 if (!bVis)
5298 {
5299 SCCOL nEndX = nX;
5300 SCROW nEndY = nY;
5301 const ScMergeAttr& rMerge = (const ScMergeAttr&) pPattern->GetItem(ATTR_MERGE);
5302 if (rMerge.GetColMerge() > 1)
5303 nEndX += rMerge.GetColMerge()-1;
5304 if (rMerge.GetRowMerge() > 1)
5305 nEndY += rMerge.GetRowMerge()-1;
5306 bVis = ( nEndX>=pViewData->GetPosX(eHWhich) && nEndY>=pViewData->GetPosY(eVWhich) );
5307 }
5308
5309 if ( bVis && !bOverlapped && !pViewData->HasEditView(eWhich) && pViewData->IsActive() )
5310 {
5311 Point aScrPos = pViewData->GetScrPos( nX, nY, eWhich, sal_True );
5312 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5313
5314 // completely right of/below the screen?
5315 // (test with logical start position in aScrPos)
5316 sal_Bool bMaybeVisible;
5317 if ( bLayoutRTL )
5318 bMaybeVisible = ( aScrPos.X() >= -2 && aScrPos.Y() >= -2 );
5319 else
5320 {
5321 Size aOutSize = GetOutputSizePixel();
5322 bMaybeVisible = ( aScrPos.X() <= aOutSize.Width() + 2 && aScrPos.Y() <= aOutSize.Height() + 2 );
5323 }
5324 if ( bMaybeVisible )
5325 {
5326 long nSizeXPix;
5327 long nSizeYPix;
5328 pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix );
5329
5330 if ( bLayoutRTL )
5331 aScrPos.X() -= nSizeXPix - 2; // move instead of mirroring
5332
5333 sal_Bool bFix = ( pViewData->GetHSplitMode() == SC_SPLIT_FIX ||
5334 pViewData->GetVSplitMode() == SC_SPLIT_FIX );
5335 if ( pViewData->GetActivePart()==eWhich || bFix )
5336 {
5337 aScrPos.X() -= 2;
5338 aScrPos.Y() -= 2;
5339 Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) );
5340
5341 aPixelRects.push_back(Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() ));
5342 aPixelRects.push_back(Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() ));
5343 aPixelRects.push_back(Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 ));
5344 aPixelRects.push_back(Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() ));
5345 }
5346 else
5347 {
5348 Rectangle aRect( aScrPos, Size( nSizeXPix - 1, nSizeYPix - 1 ) );
5349 aPixelRects.push_back( aRect );
5350 }
5351 }
5352 }
5353
5354 if ( aPixelRects.size() )
5355 {
5356 // #i70788# get the OverlayManager safely
5357 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5358
5359 if(pOverlayManager)
5360 {
5361 const Color aCursorColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
5362 std::vector< basegfx::B2DRange > aRanges;
5363 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5364
5365 for(sal_uInt32 a(0); a < aPixelRects.size(); a++)
5366 {
5367 const Rectangle aRA(aPixelRects[a]);
5368 basegfx::B2DRange aRB(aRA.Left(), aRA.Top(), aRA.Right() + 1, aRA.Bottom() + 1);
5369 aRB.transform(aTransform);
5370 aRanges.push_back(aRB);
5371 }
5372
5373 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5374 sdr::overlay::OVERLAY_SOLID,
5375 aCursorColor,
5376 aRanges,
5377 false);
5378
5379 pOverlayManager->add(*pOverlay);
5380 mpOOCursors = new ::sdr::overlay::OverlayObjectList;
5381 mpOOCursors->append(*pOverlay);
5382 }
5383 }
5384
5385 if ( aOldMode != aDrawMode )
5386 SetMapMode( aOldMode );
5387 }
5388
DeleteSelectionOverlay()5389 void ScGridWindow::DeleteSelectionOverlay()
5390 {
5391 DELETEZ( mpOOSelection );
5392 }
5393
UpdateSelectionOverlay()5394 void ScGridWindow::UpdateSelectionOverlay()
5395 {
5396 MapMode aDrawMode = GetDrawMapMode();
5397 MapMode aOldMode = GetMapMode();
5398 if ( aOldMode != aDrawMode )
5399 SetMapMode( aDrawMode );
5400
5401 DeleteSelectionOverlay();
5402 std::vector<Rectangle> aPixelRects;
5403 GetSelectionRects( aPixelRects );
5404
5405 if ( aPixelRects.size() && pViewData->IsActive() )
5406 {
5407 // #i70788# get the OverlayManager safely
5408 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5409
5410 if(pOverlayManager)
5411 {
5412 std::vector< basegfx::B2DRange > aRanges;
5413 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5414
5415 for(sal_uInt32 a(0); a < aPixelRects.size(); a++)
5416 {
5417 const Rectangle aRA(aPixelRects[a]);
5418 basegfx::B2DRange aRB(aRA.Left() - 1, aRA.Top() - 1, aRA.Right(), aRA.Bottom());
5419 aRB.transform(aTransform);
5420 aRanges.push_back(aRB);
5421 }
5422
5423 // get the system's hilight color
5424 const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
5425 const Color aHighlight(aSvtOptionsDrawinglayer.getHilightColor());
5426
5427 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5428 sdr::overlay::OVERLAY_TRANSPARENT,
5429 aHighlight,
5430 aRanges,
5431 true);
5432
5433 pOverlayManager->add(*pOverlay);
5434 mpOOSelection = new ::sdr::overlay::OverlayObjectList;
5435 mpOOSelection->append(*pOverlay);
5436 }
5437 }
5438
5439 if ( aOldMode != aDrawMode )
5440 SetMapMode( aOldMode );
5441 }
5442
DeleteAutoFillOverlay()5443 void ScGridWindow::DeleteAutoFillOverlay()
5444 {
5445 DELETEZ( mpOOAutoFill );
5446 mpAutoFillRect.reset();
5447 }
5448
UpdateAutoFillOverlay()5449 void ScGridWindow::UpdateAutoFillOverlay()
5450 {
5451 MapMode aDrawMode = GetDrawMapMode();
5452 MapMode aOldMode = GetMapMode();
5453 if ( aOldMode != aDrawMode )
5454 SetMapMode( aDrawMode );
5455
5456 DeleteAutoFillOverlay();
5457
5458 //
5459 // get the AutoFill handle rectangle in pixels (moved from ScGridWindow::DrawAutoFillMark)
5460 //
5461
5462 if ( bAutoMarkVisible && aAutoMarkPos.Tab() == pViewData->GetTabNo() &&
5463 !pViewData->HasEditView(eWhich) && pViewData->IsActive() )
5464 {
5465 SCCOL nX = aAutoMarkPos.Col();
5466 SCROW nY = aAutoMarkPos.Row();
5467
5468 if (!maVisibleRange.isInside(nX, nY))
5469 // Autofill mark is not visible. Bail out.
5470 return;
5471
5472 SCTAB nTab = pViewData->GetTabNo();
5473 ScDocument* pDoc = pViewData->GetDocument();
5474 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5475
5476 Point aFillPos = pViewData->GetScrPos( nX, nY, eWhich, sal_True );
5477 long nSizeXPix;
5478 long nSizeYPix;
5479 pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix );
5480 if ( bLayoutRTL )
5481 aFillPos.X() -= nSizeXPix + 3;
5482 else
5483 aFillPos.X() += nSizeXPix - 2;
5484
5485 aFillPos.Y() += nSizeYPix;
5486 aFillPos.Y() -= 2;
5487 mpAutoFillRect.reset(new Rectangle(aFillPos, Size(6, 6)));
5488
5489 // #i70788# get the OverlayManager safely
5490 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5491
5492 if(pOverlayManager)
5493 {
5494 const Color aHandleColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
5495 std::vector< basegfx::B2DRange > aRanges;
5496 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5497 basegfx::B2DRange aRB(mpAutoFillRect->Left(), mpAutoFillRect->Top(), mpAutoFillRect->Right() + 1, mpAutoFillRect->Bottom() + 1);
5498
5499 aRB.transform(aTransform);
5500 aRanges.push_back(aRB);
5501
5502 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5503 sdr::overlay::OVERLAY_SOLID,
5504 aHandleColor,
5505 aRanges,
5506 false);
5507
5508 pOverlayManager->add(*pOverlay);
5509 mpOOAutoFill = new ::sdr::overlay::OverlayObjectList;
5510 mpOOAutoFill->append(*pOverlay);
5511 }
5512
5513 if ( aOldMode != aDrawMode )
5514 SetMapMode( aOldMode );
5515 }
5516 }
5517
DeleteDragRectOverlay()5518 void ScGridWindow::DeleteDragRectOverlay()
5519 {
5520 DELETEZ( mpOODragRect );
5521 }
5522
UpdateDragRectOverlay()5523 void ScGridWindow::UpdateDragRectOverlay()
5524 {
5525 MapMode aDrawMode = GetDrawMapMode();
5526 MapMode aOldMode = GetMapMode();
5527 if ( aOldMode != aDrawMode )
5528 SetMapMode( aDrawMode );
5529
5530 DeleteDragRectOverlay();
5531
5532 //
5533 // get the rectangles in pixels (moved from DrawDragRect)
5534 //
5535
5536 if ( bDragRect || bPagebreakDrawn )
5537 {
5538 std::vector<Rectangle> aPixelRects;
5539
5540 SCCOL nX1 = bDragRect ? nDragStartX : aPagebreakDrag.aStart.Col();
5541 SCROW nY1 = bDragRect ? nDragStartY : aPagebreakDrag.aStart.Row();
5542 SCCOL nX2 = bDragRect ? nDragEndX : aPagebreakDrag.aEnd.Col();
5543 SCROW nY2 = bDragRect ? nDragEndY : aPagebreakDrag.aEnd.Row();
5544
5545 SCTAB nTab = pViewData->GetTabNo();
5546
5547 SCCOL nPosX = pViewData->GetPosX(WhichH(eWhich));
5548 SCROW nPosY = pViewData->GetPosY(WhichV(eWhich));
5549 if (nX1 < nPosX) nX1 = nPosX;
5550 if (nX2 < nPosX) nX2 = nPosX;
5551 if (nY1 < nPosY) nY1 = nPosY;
5552 if (nY2 < nPosY) nY2 = nPosY;
5553
5554 Point aScrPos( pViewData->GetScrPos( nX1, nY1, eWhich ) );
5555
5556 long nSizeXPix=0;
5557 long nSizeYPix=0;
5558 ScDocument* pDoc = pViewData->GetDocument();
5559 double nPPTX = pViewData->GetPPTX();
5560 double nPPTY = pViewData->GetPPTY();
5561 SCCOLROW i;
5562
5563 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5564 long nLayoutSign = bLayoutRTL ? -1 : 1;
5565
5566 if (ValidCol(nX2) && nX2>=nX1)
5567 for (i=nX1; i<=nX2; i++)
5568 nSizeXPix += ScViewData::ToPixel( pDoc->GetColWidth( static_cast<SCCOL>(i), nTab ), nPPTX );
5569 else
5570 {
5571 aScrPos.X() -= nLayoutSign;
5572 nSizeXPix += 2;
5573 }
5574
5575 if (ValidRow(nY2) && nY2>=nY1)
5576 for (i=nY1; i<=nY2; i++)
5577 nSizeYPix += ScViewData::ToPixel( pDoc->GetRowHeight( i, nTab ), nPPTY );
5578 else
5579 {
5580 aScrPos.Y() -= 1;
5581 nSizeYPix += 2;
5582 }
5583
5584 aScrPos.X() -= 2 * nLayoutSign;
5585 aScrPos.Y() -= 2;
5586 // Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) );
5587 Rectangle aRect( aScrPos.X(), aScrPos.Y(),
5588 aScrPos.X() + ( nSizeXPix + 2 ) * nLayoutSign, aScrPos.Y() + nSizeYPix + 2 );
5589 if ( bLayoutRTL )
5590 {
5591 aRect.Left() = aRect.Right(); // end position is left
5592 aRect.Right() = aScrPos.X();
5593 }
5594
5595 if ( meDragInsertMode == INS_CELLSDOWN )
5596 {
5597 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Top()+3, aRect.Left()+1, aRect.Bottom()-2 ) );
5598 aPixelRects.push_back( Rectangle( aRect.Right()-1, aRect.Top()+3, aRect.Right()-1, aRect.Bottom()-2 ) );
5599 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Top(), aRect.Right()-1, aRect.Top()+2 ) );
5600 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Bottom()-1, aRect.Right()-1, aRect.Bottom()-1 ) );
5601 }
5602 else if ( meDragInsertMode == INS_CELLSRIGHT )
5603 {
5604 aPixelRects.push_back( Rectangle( aRect.Left(), aRect.Top()+1, aRect.Left()+2, aRect.Bottom()-1 ) );
5605 aPixelRects.push_back( Rectangle( aRect.Right()-1, aRect.Top()+1, aRect.Right()-1, aRect.Bottom()-1 ) );
5606 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Top()+1, aRect.Right()-2, aRect.Top()+1 ) );
5607 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Bottom()-1, aRect.Right()-2, aRect.Bottom()-1 ) );
5608 }
5609 else
5610 {
5611 aPixelRects.push_back( Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() ) );
5612 aPixelRects.push_back( Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() ) );
5613 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 ) );
5614 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() ) );
5615 }
5616
5617 // #i70788# get the OverlayManager safely
5618 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5619
5620 if(pOverlayManager)
5621 {
5622 // Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
5623 std::vector< basegfx::B2DRange > aRanges;
5624 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5625
5626 for(sal_uInt32 a(0); a < aPixelRects.size(); a++)
5627 {
5628 const Rectangle aRA(aPixelRects[a]);
5629 basegfx::B2DRange aRB(aRA.Left(), aRA.Top(), aRA.Right() + 1, aRA.Bottom() + 1);
5630 aRB.transform(aTransform);
5631 aRanges.push_back(aRB);
5632 }
5633
5634 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5635 sdr::overlay::OVERLAY_INVERT,
5636 Color(COL_BLACK),
5637 aRanges,
5638 false);
5639
5640 pOverlayManager->add(*pOverlay);
5641 mpOODragRect = new ::sdr::overlay::OverlayObjectList;
5642 mpOODragRect->append(*pOverlay);
5643 }
5644 }
5645
5646 if ( aOldMode != aDrawMode )
5647 SetMapMode( aOldMode );
5648 }
5649
DeleteHeaderOverlay()5650 void ScGridWindow::DeleteHeaderOverlay()
5651 {
5652 DELETEZ( mpOOHeader );
5653 }
5654
UpdateHeaderOverlay()5655 void ScGridWindow::UpdateHeaderOverlay()
5656 {
5657 MapMode aDrawMode = GetDrawMapMode();
5658 MapMode aOldMode = GetMapMode();
5659 if ( aOldMode != aDrawMode )
5660 SetMapMode( aDrawMode );
5661
5662 DeleteHeaderOverlay();
5663
5664 // Pixel rectangle is in aInvertRect
5665 if ( !aInvertRect.IsEmpty() )
5666 {
5667 // #i70788# get the OverlayManager safely
5668 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5669
5670 if(pOverlayManager)
5671 {
5672 // Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
5673 std::vector< basegfx::B2DRange > aRanges;
5674 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5675 basegfx::B2DRange aRB(aInvertRect.Left(), aInvertRect.Top(), aInvertRect.Right() + 1, aInvertRect.Bottom() + 1);
5676
5677 aRB.transform(aTransform);
5678 aRanges.push_back(aRB);
5679
5680 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5681 sdr::overlay::OVERLAY_INVERT,
5682 Color(COL_BLACK),
5683 aRanges,
5684 false);
5685
5686 pOverlayManager->add(*pOverlay);
5687 mpOOHeader = new ::sdr::overlay::OverlayObjectList;
5688 mpOOHeader->append(*pOverlay);
5689 }
5690 }
5691
5692 if ( aOldMode != aDrawMode )
5693 SetMapMode( aOldMode );
5694 }
5695
DeleteShrinkOverlay()5696 void ScGridWindow::DeleteShrinkOverlay()
5697 {
5698 DELETEZ( mpOOShrink );
5699 }
5700
UpdateShrinkOverlay()5701 void ScGridWindow::UpdateShrinkOverlay()
5702 {
5703 MapMode aDrawMode = GetDrawMapMode();
5704 MapMode aOldMode = GetMapMode();
5705 if ( aOldMode != aDrawMode )
5706 SetMapMode( aDrawMode );
5707
5708 DeleteShrinkOverlay();
5709
5710 //
5711 // get the rectangle in pixels
5712 //
5713
5714 Rectangle aPixRect;
5715 ScRange aRange;
5716 SCTAB nTab = pViewData->GetTabNo();
5717 if ( pViewData->IsRefMode() && nTab >= pViewData->GetRefStartZ() && nTab <= pViewData->GetRefEndZ() &&
5718 pViewData->GetDelMark( aRange ) )
5719 {
5720 //! limit to visible area
5721 if ( aRange.aStart.Col() <= aRange.aEnd.Col() &&
5722 aRange.aStart.Row() <= aRange.aEnd.Row() )
5723 {
5724 Point aStart = pViewData->GetScrPos( aRange.aStart.Col(),
5725 aRange.aStart.Row(), eWhich );
5726 Point aEnd = pViewData->GetScrPos( aRange.aEnd.Col()+1,
5727 aRange.aEnd.Row()+1, eWhich );
5728 aEnd.X() -= 1;
5729 aEnd.Y() -= 1;
5730
5731 aPixRect = Rectangle( aStart,aEnd );
5732 }
5733 }
5734
5735 if ( !aPixRect.IsEmpty() )
5736 {
5737 // #i70788# get the OverlayManager safely
5738 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5739
5740 if(pOverlayManager)
5741 {
5742 // Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
5743 std::vector< basegfx::B2DRange > aRanges;
5744 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5745 basegfx::B2DRange aRB(aPixRect.Left(), aPixRect.Top(), aPixRect.Right() + 1, aPixRect.Bottom() + 1);
5746
5747 aRB.transform(aTransform);
5748 aRanges.push_back(aRB);
5749
5750 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5751 sdr::overlay::OVERLAY_INVERT,
5752 Color(COL_BLACK),
5753 aRanges,
5754 false);
5755
5756 pOverlayManager->add(*pOverlay);
5757 mpOOShrink = new ::sdr::overlay::OverlayObjectList;
5758 mpOOShrink->append(*pOverlay);
5759 }
5760 }
5761
5762 if ( aOldMode != aDrawMode )
5763 SetMapMode( aOldMode );
5764 }
5765
5766 // #i70788# central method to get the OverlayManager safely
getOverlayManager()5767 ::sdr::overlay::OverlayManager* ScGridWindow::getOverlayManager()
5768 {
5769 SdrPageView* pPV = pViewData->GetView()->GetScDrawView()->GetSdrPageView();
5770
5771 if(pPV)
5772 {
5773 SdrPageWindow* pPageWin = pPV->FindPageWindow( *this );
5774
5775 if ( pPageWin )
5776 {
5777 return (pPageWin->GetOverlayManager());
5778 }
5779 }
5780
5781 return 0L;
5782 }
5783
flushOverlayManager()5784 void ScGridWindow::flushOverlayManager()
5785 {
5786 // #i70788# get the OverlayManager safely
5787 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5788
5789 if(pOverlayManager)
5790 {
5791 pOverlayManager->flush();
5792 }
5793 }
5794
5795 // ---------------------------------------------------------------------------
5796 // eof
5797