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