update ooo310-m15
[ooovba.git] / sc / source / ui / view / gridwin.cxx
blobfacc003be5502a5b67ad351ae6989fe5bc29d146
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: gridwin.cxx,v $
10 * $Revision: 1.96.50.4 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 #include "scitems.hxx"
36 #include <memory> //auto_ptr
37 #include <svx/adjitem.hxx>
38 #include <svx/algitem.hxx>
39 #include <svx/dbexch.hrc>
40 #include <svx/editview.hxx>
41 #include <svx/editstat.hxx>
42 #include <svx/flditem.hxx>
43 #include <svx/svdetc.hxx>
44 #include <svx/editobj.hxx>
45 #include <sfx2/dispatch.hxx>
46 #include <sfx2/viewfrm.hxx>
47 #include <sfx2/docfile.hxx>
48 #include <svtools/stritem.hxx>
49 #include <svtools/svlbox.hxx>
50 #include <svtools/svtabbx.hxx>
51 #include <svtools/urlbmk.hxx>
52 #include <tools/urlobj.hxx>
53 #include <vcl/cursor.hxx>
54 #include <vcl/sound.hxx>
55 #include <vcl/graph.hxx>
56 #include <vcl/hatch.hxx>
57 #include <sot/formats.hxx>
58 #include <sot/clsids.hxx>
60 #include <svx/svdview.hxx> // fuer Command-Handler (COMMAND_INSERTTEXT)
61 #include <svx/outliner.hxx> // fuer Command-Handler (COMMAND_INSERTTEXT)
62 #include <svx/svditer.hxx>
63 #include <svx/svdocapt.hxx>
64 #include <svx/svdpagv.hxx>
66 #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
67 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
68 #include <com/sun/star/sheet/DataPilotTableHeaderData.hpp>
69 #include <com/sun/star/sheet/DataPilotTableResultData.hpp>
70 #include <com/sun/star/sheet/DataPilotTablePositionData.hpp>
71 #include <com/sun/star/sheet/DataPilotTablePositionType.hpp>
72 #include <com/sun/star/sheet/MemberResultFlags.hpp>
73 #include <com/sun/star/awt/KeyModifier.hpp>
74 #include <com/sun/star/awt/MouseButton.hpp>
76 #include "gridwin.hxx"
77 #include "tabvwsh.hxx"
78 #include "docsh.hxx"
79 #include "viewdata.hxx"
80 #include "tabview.hxx"
81 #include "select.hxx"
82 #include "scmod.hxx"
83 #include "document.hxx"
84 #include "attrib.hxx"
85 #include "dbcolect.hxx"
86 #include "stlpool.hxx"
87 #include "printfun.hxx"
88 #include "cbutton.hxx"
89 #include "sc.hrc"
90 #include "globstr.hrc"
91 #include "editutil.hxx"
92 #include "scresid.hxx"
93 #include "inputhdl.hxx"
94 #include "uiitems.hxx" // Filter-Dialog - auslagern !!!
95 #include "filtdlg.hxx"
96 #include "impex.hxx" // Sylk-ID fuer CB
97 #include "cell.hxx" // fuer Edit-Felder
98 #include "patattr.hxx"
99 #include "notemark.hxx"
100 #include "rfindlst.hxx"
101 #include "docpool.hxx"
102 #include "output.hxx"
103 #include "docfunc.hxx"
104 #include "dbdocfun.hxx"
105 #include "dpobject.hxx"
106 #include "dpoutput.hxx"
107 #include "transobj.hxx"
108 #include "drwtrans.hxx"
109 #include "seltrans.hxx"
110 #include "sizedev.hxx"
111 #include "AccessibilityHints.hxx"
112 #include "dpsave.hxx"
113 #include "viewuno.hxx"
114 #include "compiler.hxx"
115 #include "editable.hxx"
116 #include "fillinfo.hxx"
117 #include "scitems.hxx"
118 #include "userdat.hxx"
119 #include "drwlayer.hxx"
120 #include "attrib.hxx"
121 #include "cellsh.hxx"
122 #include "tabprotection.hxx"
123 #include "clipparam.hxx"
124 #include "dpcontrol.hxx"
126 // #114409#
127 #include <vcl/salbtype.hxx> // FRound
128 #include "drawview.hxx"
129 #include <svx/sdrpagewindow.hxx>
130 #include <svx/sdrpaintwindow.hxx>
131 #include <svx/sdr/overlay/overlaymanager.hxx>
132 #include <vcl/svapp.hxx>
134 #include "cellsuno.hxx"
136 #include <com/sun/star/document/XVbaEventsHelper.hpp>
137 #include <com/sun/star/document/VbaEventId.hpp>
139 using namespace com::sun::star;
140 using namespace com::sun::star::document::VbaEventId;
141 using ::com::sun::star::uno::Sequence;
142 using ::com::sun::star::uno::Any;
144 const BYTE SC_NESTEDBUTTON_NONE = 0;
145 const BYTE SC_NESTEDBUTTON_DOWN = 1;
146 const BYTE SC_NESTEDBUTTON_UP = 2;
148 #define SC_AUTOFILTER_ALL 0
149 #define SC_AUTOFILTER_TOP10 1
150 #define SC_AUTOFILTER_CUSTOM 2
151 #define SC_AUTOFILTER_EMPTY 3
152 #define SC_AUTOFILTER_NOTEMPTY 4
154 // Modi fuer die FilterListBox
155 enum ScFilterBoxMode
157 SC_FILTERBOX_FILTER,
158 SC_FILTERBOX_DATASELECT,
159 SC_FILTERBOX_SCENARIO,
160 SC_FILTERBOX_PAGEFIELD
163 extern SfxViewShell* pScActiveViewShell; // global.cxx
164 extern USHORT nScClickMouseModifier; // global.cxx
165 extern USHORT nScFillModeMouseModifier; // global.cxx
167 #define SC_FILTERLISTBOX_LINES 12
169 //==================================================================
171 class ScFilterListBox : public ListBox
173 private:
174 ScGridWindow* pGridWin;
175 SCCOL nCol;
176 SCROW nRow;
177 BOOL bButtonDown;
178 BOOL bInit;
179 BOOL bCancelled;
180 BOOL bInSelect;
181 bool mbListHasDates;
182 ULONG nSel;
183 ScFilterBoxMode eMode;
185 protected:
186 virtual void LoseFocus();
187 void SelectHdl();
189 public:
190 ScFilterListBox( Window* pParent, ScGridWindow* pGrid,
191 SCCOL nNewCol, SCROW nNewRow, ScFilterBoxMode eNewMode );
192 ~ScFilterListBox();
194 virtual long PreNotify( NotifyEvent& rNEvt );
195 virtual void Select();
197 SCCOL GetCol() const { return nCol; }
198 SCROW GetRow() const { return nRow; }
199 ScFilterBoxMode GetMode() const { return eMode; }
200 BOOL IsDataSelect() const { return (eMode == SC_FILTERBOX_DATASELECT); }
201 void EndInit();
202 BOOL IsInInit() const { return bInit; }
203 void SetCancelled() { bCancelled = TRUE; }
204 BOOL IsInSelect() const { return bInSelect; }
205 void SetListHasDates(bool b) { mbListHasDates = b; }
206 bool HasDates() const { return mbListHasDates; }
209 //-------------------------------------------------------------------
211 // ListBox in einem FloatingWindow (pParent)
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( FALSE ),
219 bInit( TRUE ),
220 bCancelled( FALSE ),
221 bInSelect( FALSE ),
222 mbListHasDates(false),
223 nSel( 0 ),
224 eMode( eNewMode )
228 __EXPORT ScFilterListBox::~ScFilterListBox()
230 if (IsMouseCaptured())
231 ReleaseMouse();
234 void ScFilterListBox::EndInit()
236 USHORT nPos = GetSelectEntryPos();
237 if ( LISTBOX_ENTRY_NOTFOUND == nPos )
238 nSel = 0;
239 else
240 nSel = nPos;
242 bInit = FALSE;
245 void __EXPORT ScFilterListBox::LoseFocus()
247 #ifndef UNX
248 Hide();
249 #endif
252 // -----------------------------------------------------------------------
254 long ScFilterListBox::PreNotify( NotifyEvent& rNEvt )
256 long nDone = 0;
257 if ( rNEvt.GetType() == EVENT_KEYINPUT )
259 KeyEvent aKeyEvt = *rNEvt.GetKeyEvent();
260 KeyCode aCode = aKeyEvt.GetKeyCode();
261 if ( !aCode.GetModifier() ) // ohne alle Modifiers
263 USHORT nKey = aCode.GetCode();
264 if ( nKey == KEY_RETURN )
266 SelectHdl(); // auswaehlen
267 nDone = 1;
269 else if ( nKey == KEY_ESCAPE )
271 pGridWin->ClickExtern(); // loescht die List-Box !!!
272 nDone = 1;
277 return nDone ? nDone : ListBox::PreNotify( rNEvt );
280 void __EXPORT ScFilterListBox::Select()
282 ListBox::Select();
283 SelectHdl();
286 void __EXPORT ScFilterListBox::SelectHdl()
288 if ( !IsTravelSelect() && !bInit && !bCancelled )
290 USHORT nPos = GetSelectEntryPos();
291 if ( LISTBOX_ENTRY_NOTFOUND != nPos )
293 nSel = nPos;
294 if (!bButtonDown)
296 // #i81298# set bInSelect flag, so the box isn't deleted from modifications within FilterSelect
297 bInSelect = TRUE;
298 pGridWin->FilterSelect( nSel );
299 bInSelect = FALSE;
305 // ============================================================================
307 // use a System floating window for the above filter listbox
308 class ScFilterFloatingWindow : public FloatingWindow
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();
317 ScFilterFloatingWindow::ScFilterFloatingWindow( Window* pParent, WinBits nStyle ) :
318 FloatingWindow( pParent, nStyle|WB_SYSTEMWINDOW ) // make it a system floater
321 ScFilterFloatingWindow::~ScFilterFloatingWindow()
323 EndPopupMode();
326 Window* ScFilterFloatingWindow::GetPreferredKeyInputWindow()
328 // redirect keyinput in the child window
329 return GetWindow(WINDOW_FIRSTCHILD) ? GetWindow(WINDOW_FIRSTCHILD)->GetPreferredKeyInputWindow() : NULL; // will be the FilterBox
332 // ============================================================================
334 BOOL lcl_IsEditableMatrix( ScDocument* pDoc, const ScRange& rRange )
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 ???
340 if ( !pDoc->IsBlockEditable( rRange.aStart.Tab(), rRange.aStart.Col(),rRange.aStart.Row(),
341 rRange.aEnd.Col(),rRange.aEnd.Row() ) )
342 return FALSE;
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 );
351 void lcl_UnLockComment( ScDrawView* pView, SdrPageView* pPV, SdrModel* pDrDoc, const Point& rPos, ScViewData* pViewData )
353 if (!pView && !pPV && !pDrDoc && !pViewData)
354 return;
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 ) )
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 );
370 sal_Bool lcl_GetHyperlinkCell(ScDocument* pDoc, SCCOL& rPosX, SCROW& rPosY, SCTAB nTab, ScBaseCell*& rpCell )
372 BOOL bFound = FALSE;
375 pDoc->GetCell( rPosX, rPosY, nTab, rpCell );
376 if ( !rpCell || rpCell->GetCellType() == CELLTYPE_NOTE )
378 if ( rPosX <= 0 )
379 return FALSE; // alles leer bis links
380 else
381 --rPosX; // weitersuchen
383 else if ( rpCell->GetCellType() == CELLTYPE_EDIT)
384 bFound = TRUE;
385 else if (rpCell->GetCellType() == CELLTYPE_FORMULA &&
386 static_cast<ScFormulaCell*>(rpCell)->IsHyperLinkCell())
387 bFound = TRUE;
388 else
389 return FALSE; // andere Zelle
391 while ( !bFound );
393 return bFound;
396 // ============================================================================
398 ScGridWindow::VisibleRange::VisibleRange() :
399 mnCol1(0), mnCol2(MAXCOL), mnRow1(0), mnRow2(MAXROW)
403 bool ScGridWindow::VisibleRange::isInside(SCCOL nCol, SCROW nRow) const
405 return mnCol1 <= nCol && nCol <= mnCol2 && mnRow1 <= nRow && nRow <= mnRow2;
408 // ============================================================================
410 // WB_DIALOGCONTROL noetig fuer UNO-Controls
411 ScGridWindow::ScGridWindow( Window* pParent, ScViewData* pData, ScSplitPos eWhichPos )
412 : Window( pParent, WB_CLIPCHILDREN | WB_DIALOGCONTROL ),
413 DropTargetHelper( this ),
414 DragSourceHelper( this ),
415 mpOOCursors( NULL ),
416 mpOOSelection( NULL ),
417 mpOOSelectionBorder( NULL ),
418 mpOOAutoFill( NULL ),
419 mpOODragRect( NULL ),
420 mpOOHeader( NULL ),
421 mpOOShrink( NULL ),
422 mpAutoFillRect(static_cast<Rectangle*>(NULL)),
423 pViewData( pData ),
424 eWhich( eWhichPos ),
425 pNoteMarker( NULL ),
426 pFilterBox( NULL ),
427 pFilterFloat( NULL ),
428 mpDPFieldPopup(NULL),
429 nCursorHideCount( 0 ),
430 bMarking( FALSE ),
431 nButtonDown( 0 ),
432 bEEMouse( FALSE ),
433 nMouseStatus( SC_GM_NONE ),
434 nNestedButtonState( SC_NESTEDBUTTON_NONE ),
435 #if OLD_PIVOT_IMPLEMENTATION
436 bPivotMouse( FALSE ),
437 #endif
438 bDPMouse( FALSE ),
439 bRFMouse( FALSE ),
440 nPagebreakMouse( SC_PD_NONE ),
441 bPagebreakDrawn( FALSE ),
442 nPageScript( 0 ),
443 bDragRect( FALSE ),
444 meDragInsertMode( INS_NONE ),
445 nCurrentPointer( 0 ),
446 bIsInScroll( FALSE ),
447 bIsInPaint( FALSE ),
448 aComboButton( this ),
449 aCurMousePos( 0,0 ),
450 nPaintCount( 0 ),
451 bNeedsRepaint( FALSE ),
452 bAutoMarkVisible( FALSE ),
453 bListValButton( FALSE )
455 switch(eWhich)
457 case SC_SPLIT_TOPLEFT:
458 eHWhich = SC_SPLIT_LEFT;
459 eVWhich = SC_SPLIT_TOP;
460 break;
461 case SC_SPLIT_TOPRIGHT:
462 eHWhich = SC_SPLIT_RIGHT;
463 eVWhich = SC_SPLIT_TOP;
464 break;
465 case SC_SPLIT_BOTTOMLEFT:
466 eHWhich = SC_SPLIT_LEFT;
467 eVWhich = SC_SPLIT_BOTTOM;
468 break;
469 case SC_SPLIT_BOTTOMRIGHT:
470 eHWhich = SC_SPLIT_RIGHT;
471 eVWhich = SC_SPLIT_BOTTOM;
472 break;
473 default:
474 DBG_ERROR("GridWindow: falsche Position");
477 SetBackground();
479 SetMapMode(pViewData->GetLogicMode(eWhich));
480 // EnableDrop();
481 EnableChildTransparentMode();
482 SetDialogControlFlags( WINDOW_DLGCTRL_RETURN | WINDOW_DLGCTRL_WANTFOCUS );
484 SetHelpId( HID_SC_WIN_GRIDWIN );
485 SetUniqueId( HID_SC_WIN_GRIDWIN );
487 SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
488 EnableRTL( FALSE );
491 __EXPORT ScGridWindow::~ScGridWindow()
493 // #114409#
494 ImpDestroyOverlayObjects();
496 delete pFilterBox;
497 delete pFilterFloat;
498 delete pNoteMarker;
501 void __EXPORT ScGridWindow::Resize( const Size& )
503 // gar nix
506 void ScGridWindow::ClickExtern()
508 // #i81298# don't delete the filter box when called from its select handler
509 // (possible through row header size update)
510 // #i84277# when initializing the filter box, a Basic error can deactivate the view
511 if ( pFilterBox && ( pFilterBox->IsInSelect() || pFilterBox->IsInInit() ) )
512 return;
514 DELETEZ(pFilterBox);
515 DELETEZ(pFilterFloat);
518 IMPL_LINK( ScGridWindow, PopupModeEndHdl, FloatingWindow*, EMPTYARG )
520 if (pFilterBox)
521 pFilterBox->SetCancelled(); // nicht mehr auswaehlen
522 GrabFocus();
523 return 0;
526 IMPL_LINK( ScGridWindow, PopupSpellingHdl, SpellCallbackInfo*, pInfo )
528 if( pInfo->nCommand == SPELLCMD_STARTSPELLDLG )
529 pViewData->GetDispatcher().Execute( SID_SPELL_DIALOG, SFX_CALLMODE_ASYNCHRON );
530 return 0;
533 void ScGridWindow::ExecPageFieldSelect( SCCOL nCol, SCROW nRow, BOOL bHasSelection, const String& rStr )
535 //! gridwin2 ?
537 ScDocument* pDoc = pViewData->GetDocument();
538 SCTAB nTab = pViewData->GetTabNo();
539 ScDPObject* pDPObj = pDoc->GetDPAtCursor(nCol, nRow, nTab);
540 if ( pDPObj && nCol > 0 )
542 // look for the dimension header left of the drop-down arrow
543 USHORT nOrient = sheet::DataPilotFieldOrientation_HIDDEN;
544 long nField = pDPObj->GetHeaderDim( ScAddress( nCol-1, nRow, nTab ), nOrient );
545 if ( nField >= 0 && nOrient == sheet::DataPilotFieldOrientation_PAGE )
547 ScDPSaveData aSaveData( *pDPObj->GetSaveData() );
549 BOOL bIsDataLayout;
550 String aDimName = pDPObj->GetDimName( nField, bIsDataLayout );
551 if ( !bIsDataLayout )
553 ScDPSaveDimension* pDim = aSaveData.GetDimensionByName(aDimName);
555 if ( bHasSelection )
556 pDim->SetCurrentPage( &rStr );
557 else
558 pDim->SetCurrentPage( NULL );
560 ScDPObject aNewObj( *pDPObj );
561 aNewObj.SetSaveData( aSaveData );
562 ScDBDocFunc aFunc( *pViewData->GetDocShell() );
563 aFunc.DataPilotUpdate( pDPObj, &aNewObj, TRUE, FALSE );
564 pViewData->GetView()->CursorPosChanged(); // shells may be switched
570 void ScGridWindow::DoPageFieldMenue( SCCOL nCol, SCROW nRow )
572 //! merge position/size handling with DoAutoFilterMenue
574 delete pFilterBox;
575 delete pFilterFloat;
577 USHORT i;
578 ScDocument* pDoc = pViewData->GetDocument();
579 SCTAB nTab = pViewData->GetTabNo();
580 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
582 long nSizeX = 0;
583 long nSizeY = 0;
584 long nHeight = 0;
585 pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
586 Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich );
587 if ( bLayoutRTL )
588 aPos.X() -= nSizeX;
590 Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) );
592 aPos.X() -= 1;
593 aPos.Y() += nSizeY - 1;
595 pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) ); // not resizable etc.
596 pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) );
597 pFilterBox = new ScFilterListBox( pFilterFloat, this, nCol, nRow, SC_FILTERBOX_PAGEFIELD );
598 if ( bLayoutRTL )
599 pFilterBox->EnableMirroring();
601 nSizeX += 1;
604 Font aOldFont = GetFont(); SetFont( pFilterBox->GetFont() );
605 MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL );
607 nHeight = GetTextHeight();
608 nHeight *= SC_FILTERLISTBOX_LINES;
610 SetMapMode( aOldMode );
611 SetFont( aOldFont );
614 // SetSize comes later
616 TypedScStrCollection aStrings( 128, 128 );
618 // get list box entries and selection
619 BOOL bHasCurrentPage = FALSE;
620 String aCurrentPage;
621 ScDPObject* pDPObj = pDoc->GetDPAtCursor(nCol, nRow, nTab);
622 if ( pDPObj && nCol > 0 )
624 // look for the dimension header left of the drop-down arrow
625 USHORT nOrient = sheet::DataPilotFieldOrientation_HIDDEN;
626 long nField = pDPObj->GetHeaderDim( ScAddress( nCol-1, nRow, nTab ), nOrient );
627 if ( nField >= 0 && nOrient == sheet::DataPilotFieldOrientation_PAGE )
629 pDPObj->FillPageList( aStrings, nField );
631 // get current page from SaveData
633 ScDPSaveData* pSaveData = pDPObj->GetSaveData();
634 BOOL bIsDataLayout;
635 String aDimName = pDPObj->GetDimName( nField, bIsDataLayout );
636 if ( pSaveData && !bIsDataLayout )
638 ScDPSaveDimension* pDim = pSaveData->GetExistingDimensionByName(aDimName);
639 if ( pDim && pDim->HasCurrentPage() )
641 aCurrentPage = pDim->GetCurrentPage();
642 bHasCurrentPage = TRUE;
648 // include all entry widths for the size of the drop-down
649 long nMaxText = 0;
650 USHORT nCount = aStrings.GetCount();
651 for (i=0; i<nCount; i++)
653 TypedStrData* pData = aStrings[i];
654 long nTextWidth = pFilterBox->GetTextWidth( pData->GetString() );
655 if ( nTextWidth > nMaxText )
656 nMaxText = nTextWidth;
659 // add scrollbar width if needed (string entries are counted here)
660 // (scrollbar is shown if the box is exactly full?)
661 if ( nCount >= SC_FILTERLISTBOX_LINES )
662 nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize();
664 nMaxText += 4; // for borders
666 if ( nMaxText > nSizeX )
667 nSizeX = nMaxText; // just modify width - starting position is unchanged
669 // adjust position and size to window
671 Size aParentSize = GetParent()->GetOutputSizePixel();
672 Size aSize( nSizeX, nHeight );
674 if ( aSize.Height() > aParentSize.Height() )
675 aSize.Height() = aParentSize.Height();
676 if ( aPos.Y() + aSize.Height() > aParentSize.Height() )
677 aPos.Y() = aParentSize.Height() - aSize.Height();
679 pFilterBox->SetSizePixel( aSize );
680 pFilterBox->Show(); // Show must be called before SetUpdateMode
681 pFilterBox->SetUpdateMode(FALSE);
683 pFilterFloat->SetOutputSizePixel( aSize );
684 pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS);
686 // fill the list box
687 BOOL bWait = ( nCount > 100 );
689 if (bWait)
690 EnterWait();
692 for (i=0; i<nCount; i++)
693 pFilterBox->InsertEntry( aStrings[i]->GetString() );
695 pFilterBox->SetSeparatorPos( 0 );
697 if (bWait)
698 LeaveWait();
700 pFilterBox->SetUpdateMode(TRUE);
702 USHORT nSelPos = LISTBOX_ENTRY_NOTFOUND;
703 if (bHasCurrentPage)
704 nSelPos = pFilterBox->GetEntryPos( aCurrentPage );
706 if ( nSelPos == LISTBOX_ENTRY_NOTFOUND )
707 nSelPos = 0; // first entry
709 pFilterBox->GrabFocus();
711 // call Select after GrabFocus, so the focus rectangle ends up in the right position
712 if ( nSelPos != LISTBOX_ENTRY_NOTFOUND )
713 pFilterBox->SelectEntryPos( nSelPos );
715 pFilterBox->EndInit();
717 nMouseStatus = SC_GM_FILTER;
718 CaptureMouse();
721 void ScGridWindow::DoScenarioMenue( const ScRange& rScenRange )
723 delete pFilterBox;
724 delete pFilterFloat;
726 SCCOL nCol = rScenRange.aEnd.Col(); // Zelle unterhalb des Buttons
727 SCROW nRow = rScenRange.aStart.Row();
728 if (nRow == 0)
730 nRow = rScenRange.aEnd.Row() + 1; // Bereich ganz oben -> Button unterhalb
731 if (nRow>MAXROW) nRow = MAXROW;
732 //! Texthoehe addieren (wenn sie an der View gespeichert ist...)
735 ScDocument* pDoc = pViewData->GetDocument();
736 SCTAB nTab = pViewData->GetTabNo();
737 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
739 long nSizeX = 0;
740 long nSizeY = 0;
741 long nHeight = 0;
742 pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
743 Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich );
744 if ( bLayoutRTL )
745 aPos.X() -= nSizeX;
746 Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) );
747 aCellRect.Top() -= nSizeY;
748 aCellRect.Bottom() -= nSizeY - 1;
749 // Die ListBox direkt unter der schwarzen Linie auf dem Zellgitter
750 // (wenn die Linie verdeckt wird, sieht es komisch aus...)
752 pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) ); // nicht resizable etc.
753 pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) );
754 pFilterBox = new ScFilterListBox( pFilterFloat, this, nCol, nRow, SC_FILTERBOX_SCENARIO );
755 if ( bLayoutRTL )
756 pFilterBox->EnableMirroring();
758 nSizeX += 1;
761 Font aOldFont = GetFont(); SetFont( pFilterBox->GetFont() );
762 MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL );
764 nHeight = GetTextHeight();
765 nHeight *= SC_FILTERLISTBOX_LINES;
767 SetMapMode( aOldMode );
768 SetFont( aOldFont );
771 // SetSize spaeter
773 pFilterBox->SetSelectionMode( SINGLE_SELECTION );
774 pFilterBox->SetTabs( nFilterBoxTabs, MapUnit( MAP_APPFONT ));
775 pFilterBox->SetTabJustify( 1, bLayoutRTL ? AdjustRight : AdjustLeft );
778 // ParentSize Abfrage fehlt
779 Size aSize( nSizeX, nHeight );
780 pFilterBox->SetSizePixel( aSize );
781 pFilterBox->Show(); // Show muss vor SetUpdateMode kommen !!!
782 pFilterBox->SetUpdateMode(FALSE);
784 // SetOutputSizePixel/StartPopupMode erst unten, wenn die Groesse feststeht
786 // Listbox fuellen
788 long nMaxText = 0;
789 String aCurrent;
790 String aTabName;
791 SCTAB nTabCount = pDoc->GetTableCount();
792 SCTAB nEntryCount = 0;
793 for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
795 if (pDoc->HasScenarioRange( i, rScenRange ))
796 if (pDoc->GetName( i, aTabName ))
798 pFilterBox->InsertEntry( aTabName );
799 if (pDoc->IsActiveScenario(i))
800 aCurrent = aTabName;
801 long nTextWidth = pFilterBox->GetTextWidth( aTabName );
802 if ( nTextWidth > nMaxText )
803 nMaxText = nTextWidth;
804 ++nEntryCount;
807 if (nEntryCount > SC_FILTERLISTBOX_LINES)
808 nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize();
809 nMaxText += 4; // fuer Rand
810 if ( nMaxText > 300 )
811 nMaxText = 300; // auch nicht uebertreiben (Pixel)
813 if (nMaxText > nSizeX) // Groesse auf benoetigte Groesse anpassen
815 long nDiff = nMaxText - nSizeX;
816 aSize = Size( nMaxText, nHeight );
817 pFilterBox->SetSizePixel( aSize );
818 pFilterFloat->SetOutputSizePixel( aSize );
820 if ( !bLayoutRTL )
822 // also move popup position
823 long nNewX = aCellRect.Left() - nDiff;
824 if ( nNewX < 0 )
825 nNewX = 0;
826 aCellRect.Left() = nNewX;
830 pFilterFloat->SetOutputSizePixel( aSize );
831 pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS );
833 pFilterBox->SetUpdateMode(TRUE);
834 pFilterBox->GrabFocus();
836 // Select erst nach GrabFocus, damit das Focus-Rechteck richtig landet
837 //! SvLBoxEntry* pSelect = NULL;
838 USHORT nPos = LISTBOX_ENTRY_NOTFOUND;
839 if (aCurrent.Len())
841 nPos = pFilterBox->GetEntryPos( aCurrent );
842 //! pSelect = pFilterBox->GetEntry( nPos );
844 if (/*!pSelect*/ LISTBOX_ENTRY_NOTFOUND == nPos && pFilterBox->GetEntryCount() > 0 )
845 nPos = 0;
846 //! pSelect = pFilterBox->GetEntry(0); // einer sollte immer selektiert sein
847 if (/*pSelect*/ LISTBOX_ENTRY_NOTFOUND != nPos )
848 pFilterBox->SelectEntryPos(nPos);
850 pFilterBox->EndInit();
852 // Szenario-Auswahl kommt aus MouseButtonDown:
853 // der naechste MouseMove auf die Filterbox ist wie ein ButtonDown
855 nMouseStatus = SC_GM_FILTER;
856 CaptureMouse();
859 void ScGridWindow::DoAutoFilterMenue( SCCOL nCol, SCROW nRow, BOOL bDataSelect )
861 delete pFilterBox;
862 delete pFilterFloat;
864 USHORT i;
865 ScDocument* pDoc = pViewData->GetDocument();
866 SCTAB nTab = pViewData->GetTabNo();
867 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
869 long nSizeX = 0;
870 long nSizeY = 0;
871 long nHeight = 0;
872 pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
873 Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich );
874 if ( bLayoutRTL )
875 aPos.X() -= nSizeX;
877 Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) );
879 aPos.X() -= 1;
880 aPos.Y() += nSizeY - 1;
882 pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) ); // nicht resizable etc.
883 pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) );
884 pFilterBox = new ScFilterListBox(
885 pFilterFloat, this, nCol, nRow, bDataSelect ? SC_FILTERBOX_DATASELECT : SC_FILTERBOX_FILTER );
886 if ( bLayoutRTL )
887 pFilterBox->EnableMirroring();
889 nSizeX += 1;
892 Font aOldFont = GetFont(); SetFont( pFilterBox->GetFont() );
893 MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL );
895 nHeight = GetTextHeight();
896 nHeight *= SC_FILTERLISTBOX_LINES;
898 SetMapMode( aOldMode );
899 SetFont( aOldFont );
902 // SetSize spaeter
904 pFilterBox->SetSelectionMode( SINGLE_SELECTION );
905 pFilterBox->SetTabs( nFilterBoxTabs, MapUnit( MAP_APPFONT ));
906 pFilterBox->SetTabJustify( 1, bLayoutRTL ? AdjustRight : AdjustLeft );
909 BOOL bEmpty = FALSE;
910 TypedScStrCollection aStrings( 128, 128 );
911 if ( bDataSelect ) // Auswahl-Liste
913 // Liste fuellen
914 aStrings.SetCaseSensitive( TRUE );
915 pDoc->GetDataEntries( nCol, nRow, nTab, aStrings );
916 if ( aStrings.GetCount() == 0 )
917 bEmpty = TRUE;
919 else // AutoFilter
921 //! wird der Titel ueberhaupt ausgewertet ???
922 String aString;
923 pDoc->GetString( nCol, nRow, nTab, aString );
924 pFilterBox->SetText( aString );
926 long nMaxText = 0;
928 // default entries
929 static const USHORT nDefIDs[] = { SCSTR_ALLFILTER, SCSTR_TOP10FILTER, SCSTR_STDFILTER, SCSTR_EMPTY, SCSTR_NOTEMPTY };
930 const USHORT nDefCount = sizeof(nDefIDs) / sizeof(USHORT);
931 for (i=0; i<nDefCount; i++)
933 String aEntry( (ScResId) nDefIDs[i] );
934 pFilterBox->InsertEntry( aEntry );
935 long nTextWidth = pFilterBox->GetTextWidth( aEntry );
936 if ( nTextWidth > nMaxText )
937 nMaxText = nTextWidth;
939 pFilterBox->SetSeparatorPos( nDefCount - 1 );
941 // get list entries
942 bool bHasDates = false;
943 pDoc->GetFilterEntries( nCol, nRow, nTab, true, aStrings, bHasDates);
944 pFilterBox->SetListHasDates(bHasDates);
946 // check widths of numerical entries (string entries are not included)
947 // so all numbers are completely visible
948 USHORT nCount = aStrings.GetCount();
949 for (i=0; i<nCount; i++)
951 TypedStrData* pData = aStrings[i];
952 if ( !pData->IsStrData() ) // only numerical entries
954 long nTextWidth = pFilterBox->GetTextWidth( pData->GetString() );
955 if ( nTextWidth > nMaxText )
956 nMaxText = nTextWidth;
960 // add scrollbar width if needed (string entries are counted here)
961 // (scrollbar is shown if the box is exactly full?)
962 if ( nCount + nDefCount >= SC_FILTERLISTBOX_LINES )
963 nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize();
965 nMaxText += 4; // for borders
967 if ( nMaxText > nSizeX )
968 nSizeX = nMaxText; // just modify width - starting position is unchanged
971 if (!bEmpty)
973 // Position und Groesse an Fenster anpassen
974 //! vorher Abfrage, ob die Eintraege hineinpassen (Breite)
976 Size aParentSize = GetParent()->GetOutputSizePixel();
977 Size aSize( nSizeX, nHeight );
979 if ( aSize.Height() > aParentSize.Height() )
980 aSize.Height() = aParentSize.Height();
981 if ( aPos.Y() + aSize.Height() > aParentSize.Height() )
982 aPos.Y() = aParentSize.Height() - aSize.Height();
984 pFilterBox->SetSizePixel( aSize );
985 pFilterBox->Show(); // Show muss vor SetUpdateMode kommen !!!
986 pFilterBox->SetUpdateMode(FALSE);
988 pFilterFloat->SetOutputSizePixel( aSize );
989 pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS);
991 // Listbox fuellen
992 USHORT nCount = aStrings.GetCount();
993 BOOL bWait = ( nCount > 100 );
995 if (bWait)
996 EnterWait();
998 for (i=0; i<nCount; i++)
999 pFilterBox->InsertEntry( aStrings[i]->GetString() );
1001 if (bWait)
1002 LeaveWait();
1004 pFilterBox->SetUpdateMode(TRUE);
1007 //! SvLBoxEntry* pSelect = NULL;
1008 USHORT nSelPos = LISTBOX_ENTRY_NOTFOUND;
1010 if (!bDataSelect) // AutoFilter: aktiven Eintrag selektieren
1012 ScDBData* pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab );
1013 if (pDBData)
1015 ScQueryParam aParam;
1016 pDBData->GetQueryParam( aParam ); // kann nur MAXQUERY Eintraege ergeben
1018 BOOL bValid = TRUE;
1019 for (SCSIZE j=0; j<MAXQUERY && bValid; j++) // bisherige Filter-Einstellungen
1020 if (aParam.GetEntry(j).bDoQuery)
1022 //! Abfrage mit DrawButtons zusammenfassen!
1024 ScQueryEntry& rEntry = aParam.GetEntry(j);
1025 if (j>0)
1026 if (rEntry.eConnect != SC_AND)
1027 bValid = FALSE;
1028 if (rEntry.nField == nCol)
1030 if (rEntry.eOp == SC_EQUAL)
1032 String* pStr = rEntry.pStr;
1033 if (pStr)
1035 nSelPos = pFilterBox->GetEntryPos( *pStr );
1036 //! pSelect = pFilterBox->GetEntry( nPos );
1039 else if (rEntry.eOp == SC_TOPVAL && rEntry.pStr &&
1040 rEntry.pStr->EqualsAscii("10"))
1041 nSelPos = SC_AUTOFILTER_TOP10;
1042 else
1043 nSelPos = SC_AUTOFILTER_CUSTOM;
1047 if (!bValid)
1048 nSelPos = SC_AUTOFILTER_CUSTOM;
1052 // neu (309): irgendwas muss immer selektiert sein:
1053 if ( LISTBOX_ENTRY_NOTFOUND == nSelPos && pFilterBox->GetEntryCount() > 0 )
1054 nSelPos = 0;
1056 // keine leere Auswahl-Liste anzeigen:
1058 if ( bEmpty )
1060 DELETEZ(pFilterBox); // war nix
1061 DELETEZ(pFilterFloat);
1062 Sound::Beep(); // bemerkbar machen
1064 else
1066 // pFilterBox->Show(); // schon vorne
1067 pFilterBox->GrabFocus();
1069 // Select erst nach GrabFocus, damit das Focus-Rechteck richtig landet
1070 if ( LISTBOX_ENTRY_NOTFOUND != nSelPos )
1071 pFilterBox->SelectEntryPos( nSelPos );
1073 pFilterBox->EndInit();
1075 if (!bDataSelect)
1077 // AutoFilter (aus MouseButtonDown):
1078 // der naechste MouseMove auf die Filterbox ist wie ein ButtonDown
1080 nMouseStatus = SC_GM_FILTER;
1081 CaptureMouse();
1086 void ScGridWindow::FilterSelect( ULONG nSel )
1088 String aString;
1090 SvLBoxEntry* pEntry = pFilterBox->GetEntry( nSel );
1091 if (pEntry)
1093 SvLBoxString* pStringEntry = (SvLBoxString*) pEntry->GetFirstItem( SV_ITEM_ID_LBOXSTRING );
1094 if ( pStringEntry )
1095 aString = pStringEntry->GetText();
1098 aString = pFilterBox->GetEntry( static_cast< USHORT >( nSel ) );
1100 SCCOL nCol = pFilterBox->GetCol();
1101 SCROW nRow = pFilterBox->GetRow();
1102 switch ( pFilterBox->GetMode() )
1104 case SC_FILTERBOX_DATASELECT:
1105 ExecDataSelect( nCol, nRow, aString );
1106 break;
1107 case SC_FILTERBOX_FILTER:
1108 ExecFilter( nSel, nCol, nRow, aString, pFilterBox->HasDates() );
1109 break;
1110 case SC_FILTERBOX_SCENARIO:
1111 pViewData->GetView()->UseScenario( aString );
1112 break;
1113 case SC_FILTERBOX_PAGEFIELD:
1114 // first entry is "all"
1115 ExecPageFieldSelect( nCol, nRow, (nSel != 0), aString );
1116 break;
1119 if (pFilterFloat)
1120 pFilterFloat->EndPopupMode();
1122 GrabFocus(); // unter OS/2 stimmt der Focus sonst nicht
1125 void ScGridWindow::ExecDataSelect( SCCOL nCol, SCROW nRow, const String& rStr )
1127 if ( rStr.Len() )
1129 SCTAB nTab = pViewData->GetTabNo();
1130 ScViewFunc* pView = pViewData->GetView();
1131 pView->EnterData( nCol, nRow, nTab, rStr );
1133 // #i52307# CellContentChanged is not in EnterData so it isn't called twice
1134 // if the cursor is moved afterwards.
1135 pView->CellContentChanged();
1139 void ScGridWindow::ExecFilter( ULONG nSel,
1140 SCCOL nCol, SCROW nRow,
1141 const String& aValue, bool bCheckForDates )
1143 SCTAB nTab = pViewData->GetTabNo();
1144 ScDocument* pDoc = pViewData->GetDocument();
1146 ScDBData* pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab );
1147 if (pDBData)
1149 ScQueryParam aParam;
1150 pDBData->GetQueryParam( aParam ); // kann nur MAXQUERY Eintraege ergeben
1152 if (SC_AUTOFILTER_CUSTOM == nSel)
1154 pViewData->GetView()->SetCursor(nCol,nRow); //! auch ueber Slot ??
1155 pViewData->GetDispatcher().Execute( SID_FILTER, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD );
1157 else
1159 BOOL bDeleteOld = FALSE;
1160 SCSIZE nQueryPos = 0;
1161 BOOL bFound = FALSE;
1162 if (!aParam.bInplace)
1163 bDeleteOld = TRUE;
1164 if (aParam.bRegExp)
1165 bDeleteOld = TRUE;
1166 for (SCSIZE i=0; i<MAXQUERY && !bDeleteOld; i++) // bisherige Filter-Einstellungen
1167 if (aParam.GetEntry(i).bDoQuery)
1169 //! Abfrage mit DrawButtons zusammenfassen!
1171 ScQueryEntry& rEntry = aParam.GetEntry(i);
1172 if (i>0)
1173 if (rEntry.eConnect != SC_AND)
1174 bDeleteOld = TRUE;
1176 if (rEntry.nField == nCol)
1178 if (bFound) // diese Spalte zweimal?
1179 bDeleteOld = TRUE;
1180 nQueryPos = i;
1181 bFound = TRUE;
1183 if (!bFound)
1184 nQueryPos = i + 1;
1187 if (bDeleteOld)
1189 SCSIZE nEC = aParam.GetEntryCount();
1190 for (SCSIZE i=0; i<nEC; i++)
1191 aParam.GetEntry(i).Clear();
1192 nQueryPos = 0;
1193 aParam.bInplace = TRUE;
1194 aParam.bRegExp = FALSE;
1197 if ( nQueryPos < MAXQUERY || SC_AUTOFILTER_ALL == nSel ) // loeschen geht immer
1199 if (nSel)
1201 ScQueryEntry& rNewEntry = aParam.GetEntry(nQueryPos);
1203 rNewEntry.bDoQuery = TRUE;
1204 rNewEntry.bQueryByString = TRUE;
1205 rNewEntry.nField = nCol;
1206 rNewEntry.bQueryByDate = bCheckForDates;
1207 if ( nSel == SC_AUTOFILTER_TOP10 )
1209 rNewEntry.eOp = SC_TOPVAL;
1210 *rNewEntry.pStr = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("10"));
1212 else if (nSel == SC_AUTOFILTER_EMPTY)
1214 rNewEntry.pStr->Erase();
1215 rNewEntry.bQueryByString = FALSE;
1216 rNewEntry.eOp = SC_EQUAL;
1217 rNewEntry.nVal = SC_EMPTYFIELDS;
1220 else if (nSel == SC_AUTOFILTER_NOTEMPTY)
1222 rNewEntry.pStr->Erase();
1223 rNewEntry.bQueryByString = FALSE;
1224 rNewEntry.eOp = SC_EQUAL;
1225 rNewEntry.nVal = SC_NONEMPTYFIELDS;
1227 else
1229 rNewEntry.eOp = SC_EQUAL;
1230 *rNewEntry.pStr = aValue;
1232 if (nQueryPos > 0)
1233 rNewEntry.eConnect = SC_AND;
1235 else
1237 if (bFound)
1238 aParam.DeleteQuery(nQueryPos);
1241 // #100597# end edit mode - like in ScCellShell::ExecuteDB
1242 if ( pViewData->HasEditView( pViewData->GetActivePart() ) )
1244 SC_MOD()->InputEnterHandler();
1245 pViewData->GetViewShell()->UpdateInputHandler();
1248 aParam.bUseDynamicRange = true;
1249 pViewData->GetView()->Query( aParam, NULL, TRUE );
1250 pDBData->SetQueryParam( aParam ); // speichern
1252 else // "Zuviele Bedingungen"
1253 pViewData->GetView()->ErrorMessage( STR_FILTER_TOOMANY );
1256 else
1258 DBG_ERROR("Wo ist der Datenbankbereich?");
1262 void ScGridWindow::SetPointer( const Pointer& rPointer )
1264 nCurrentPointer = 0;
1265 Window::SetPointer( rPointer );
1268 void ScGridWindow::MoveMouseStatus( ScGridWindow& rDestWin )
1270 if (nButtonDown)
1272 rDestWin.nButtonDown = nButtonDown;
1273 rDestWin.nMouseStatus = nMouseStatus;
1276 if (bRFMouse)
1278 rDestWin.bRFMouse = bRFMouse;
1279 rDestWin.bRFSize = bRFSize;
1280 rDestWin.nRFIndex = nRFIndex;
1281 rDestWin.nRFAddX = nRFAddX;
1282 rDestWin.nRFAddY = nRFAddY;
1283 bRFMouse = FALSE;
1286 if (nPagebreakMouse)
1288 rDestWin.nPagebreakMouse = nPagebreakMouse;
1289 rDestWin.nPagebreakBreak = nPagebreakBreak;
1290 rDestWin.nPagebreakPrev = nPagebreakPrev;
1291 rDestWin.aPagebreakSource = aPagebreakSource;
1292 rDestWin.aPagebreakDrag = aPagebreakDrag;
1293 nPagebreakMouse = SC_PD_NONE;
1297 BOOL ScGridWindow::TestMouse( const MouseEvent& rMEvt, BOOL bAction )
1299 // MouseEvent buttons must only be checked if bAction==TRUE
1300 // to allow changing the mouse pointer in MouseMove,
1301 // but not start AutoFill with right button (#74229#).
1302 // with bAction==TRUE, SetFillMode / SetDragMode is called
1304 if ( bAction && !rMEvt.IsLeft() )
1305 return FALSE;
1307 BOOL bNewPointer = FALSE;
1309 SfxInPlaceClient* pClient = pViewData->GetViewShell()->GetIPClient();
1310 BOOL bOleActive = ( pClient && pClient->IsObjectInPlaceActive() );
1312 if ( pViewData->IsActive() && !bOleActive )
1314 ScDocument* pDoc = pViewData->GetDocument();
1315 SCTAB nTab = pViewData->GetTabNo();
1316 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1317 long nLayoutSign = bLayoutRTL ? -1 : 1;
1319 // Auto-Fill
1321 ScRange aMarkRange;
1322 if (pViewData->GetSimpleArea( aMarkRange ) == SC_MARK_SIMPLE)
1324 if (aMarkRange.aStart.Tab() == pViewData->GetTabNo() && mpAutoFillRect)
1326 Point aMousePos = rMEvt.GetPosPixel();
1327 if (mpAutoFillRect->IsInside(aMousePos))
1329 SetPointer( Pointer( POINTER_CROSS ) ); //! dickeres Kreuz ?
1330 if (bAction)
1332 SCCOL nX = aMarkRange.aEnd.Col();
1333 SCROW nY = aMarkRange.aEnd.Row();
1335 if ( lcl_IsEditableMatrix( pViewData->GetDocument(), aMarkRange ) )
1336 pViewData->SetDragMode(
1337 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nX, nY, SC_FILL_MATRIX );
1338 else
1339 pViewData->SetFillMode(
1340 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nX, nY );
1342 // #108266# The simple selection must also be recognized when dragging,
1343 // where the Marking flag is set and MarkToSimple won't work anymore.
1344 pViewData->GetMarkData().MarkToSimple();
1346 bNewPointer = TRUE;
1351 // Embedded-Rechteck
1353 if (pDoc->IsEmbedded())
1355 ScRange aRange;
1356 pDoc->GetEmbedded( aRange );
1357 if ( pViewData->GetTabNo() == aRange.aStart.Tab() )
1359 Point aStartPos = pViewData->GetScrPos( aRange.aStart.Col(), aRange.aStart.Row(), eWhich );
1360 Point aEndPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aEnd.Row()+1, eWhich );
1361 Point aMousePos = rMEvt.GetPosPixel();
1362 if ( bLayoutRTL )
1364 aStartPos.X() += 2;
1365 aEndPos.X() += 2;
1367 BOOL bTop = ( aMousePos.X() >= aStartPos.X()-3 && aMousePos.X() <= aStartPos.X()+1 &&
1368 aMousePos.Y() >= aStartPos.Y()-3 && aMousePos.Y() <= aStartPos.Y()+1 );
1369 BOOL bBottom = ( aMousePos.X() >= aEndPos.X()-3 && aMousePos.X() <= aEndPos.X()+1 &&
1370 aMousePos.Y() >= aEndPos.Y()-3 && aMousePos.Y() <= aEndPos.Y()+1 );
1371 if ( bTop || bBottom )
1373 SetPointer( Pointer( POINTER_CROSS ) );
1374 if (bAction)
1376 BYTE nMode = bTop ? SC_FILL_EMBED_LT : SC_FILL_EMBED_RB;
1377 pViewData->SetDragMode(
1378 aRange.aStart.Col(), aRange.aStart.Row(),
1379 aRange.aEnd.Col(), aRange.aEnd.Row(), nMode );
1381 bNewPointer = TRUE;
1387 if (!bNewPointer && bAction)
1389 // SetPointer( POINTER_ARROW ); // in Fu...
1390 pViewData->ResetFillMode();
1393 return bNewPointer;
1396 void __EXPORT ScGridWindow::MouseButtonDown( const MouseEvent& rMEvt )
1398 nNestedButtonState = SC_NESTEDBUTTON_DOWN;
1400 HandleMouseButtonDown( rMEvt );
1402 if ( nNestedButtonState == SC_NESTEDBUTTON_UP )
1404 // #i41690# If an object is deactivated from MouseButtonDown, it might reschedule,
1405 // so MouseButtonUp comes before the MouseButtonDown call is finished. In this case,
1406 // simulate another MouseButtonUp call, so the selection state is consistent.
1408 nButtonDown = rMEvt.GetButtons();
1409 FakeButtonUp();
1411 if ( IsTracking() )
1412 EndTracking(); // normally done in VCL as part of MouseButtonUp handling
1414 nNestedButtonState = SC_NESTEDBUTTON_NONE;
1417 void ScGridWindow::HandleMouseButtonDown( const MouseEvent& rMEvt )
1419 // We have to check if a context menu is shown and we have an UI
1420 // active inplace client. In that case we have to ignore the event.
1421 // Otherwise we would crash (context menu has been
1422 // opened by inplace client and we would deactivate the inplace client,
1423 // the contex menu is closed by VCL asynchronously which in the end
1424 // would work on deleted objects or the context menu has no parent anymore)
1425 // See #126086# and #128122#
1426 SfxViewShell* pViewSh = pViewData->GetViewShell();
1427 SfxInPlaceClient* pClient = pViewSh->GetIPClient();
1428 if ( pClient &&
1429 pClient->IsObjectInPlaceActive() &&
1430 PopupMenu::IsInExecute() )
1431 return;
1433 aCurMousePos = rMEvt.GetPosPixel();
1435 // Filter-Popup beendet sich mit eigenem Mausklick, nicht erst beim Klick
1436 // in das GridWindow, darum ist die folgende Abfrage nicht mehr noetig:
1437 #if 0
1438 // merken, dass FilterBox geloescht wird, damit sichergestellt
1439 // ist, dass in diesem Handler nicht an gleicher Stelle wieder
1440 // eine neue geoeffnet wird.
1441 BOOL bWasFilterBox = ( pFilterBox != NULL &&
1442 ((Window*)pFilterBox)->IsVisible() &&
1443 !pFilterBox->IsDataSelect() );
1444 SCCOL nOldColFBox = bWasFilterBox ? pFilterBox->GetCol() : 0;
1445 SCROW nOldRowFBox = bWasFilterBox ? pFilterBox->GetRow() : 0;
1446 #endif
1447 #include "cellsuno.hxx"
1449 ClickExtern(); // loescht FilterBox, wenn vorhanden
1451 HideNoteMarker(); // Notiz-Anzeige
1453 bEEMouse = FALSE;
1455 ScModule* pScMod = SC_MOD();
1456 if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
1458 Sound::Beep();
1459 return;
1462 pScActiveViewShell = pViewData->GetViewShell(); // falls auf Link geklickt wird
1463 nScClickMouseModifier = rMEvt.GetModifier(); // um Control-Klick immer zu erkennen
1465 BOOL bDetective = pViewData->GetViewShell()->IsAuditShell();
1466 BOOL bRefMode = pViewData->IsRefMode(); // Referenz angefangen
1467 BOOL bFormulaMode = pScMod->IsFormulaMode(); // naechster Klick -> Referenz
1468 BOOL bEditMode = pViewData->HasEditView(eWhich); // auch bei Mode==SC_INPUT_TYPE
1469 BOOL bDouble = (rMEvt.GetClicks() == 2);
1471 // DeactivateIP passiert nur noch bei MarkListHasChanged
1473 // im GrabFocus Aufruf kann eine Fehlermeldung hochkommen
1474 // (z.B. beim Umbenennen von Tabellen per Tab-Reiter)
1476 if ( !nButtonDown || !bDouble ) // single (first) click is always valid
1477 nButtonDown = rMEvt.GetButtons(); // set nButtonDown first, so StopMarking works
1479 // pViewData->GetViewShell()->GetViewFrame()->GetWindow().GrabFocus();
1480 if ( ( bEditMode && pViewData->GetActivePart() == eWhich ) || !bFormulaMode )
1481 GrabFocus();
1483 // #i31846# need to cancel a double click if the first click has set the "ignore" state,
1484 // but a single (first) click is always valid
1485 if ( nMouseStatus == SC_GM_IGNORE && bDouble )
1487 nButtonDown = 0;
1488 nMouseStatus = SC_GM_NONE;
1489 return;
1492 if ( bDetective ) // Detektiv-Fuell-Modus
1494 if ( rMEvt.IsLeft() && !rMEvt.GetModifier() )
1496 Point aPos = rMEvt.GetPosPixel();
1497 SCsCOL nPosX;
1498 SCsROW nPosY;
1499 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
1501 SfxInt16Item aPosXItem( SID_RANGE_COL, nPosX );
1502 SfxInt32Item aPosYItem( SID_RANGE_ROW, nPosY );
1503 pViewData->GetDispatcher().Execute( SID_FILL_SELECT, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD,
1504 &aPosXItem, &aPosYItem, (void*)0L );
1507 nButtonDown = 0;
1508 nMouseStatus = SC_GM_NONE;
1509 return;
1512 if (!bDouble)
1513 nMouseStatus = SC_GM_NONE;
1515 if (!bFormulaMode)
1517 if ( pViewData->GetActivePart() != eWhich )
1518 pViewData->GetView()->ActivatePart( eWhich );
1520 else
1522 ScViewSelectionEngine* pSelEng = pViewData->GetView()->GetSelEngine();
1523 pSelEng->SetWindow(this);
1524 pSelEng->SetWhich(eWhich);
1525 pSelEng->SetVisibleArea( Rectangle(Point(), GetOutputSizePixel()) );
1528 if (bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()))
1530 Point aPos = rMEvt.GetPosPixel();
1531 SCsCOL nPosX;
1532 SCsROW nPosY;
1533 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
1535 EditView* pEditView;
1536 SCCOL nEditCol;
1537 SCROW nEditRow;
1538 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
1539 SCCOL nEndCol = pViewData->GetEditEndCol();
1540 SCROW nEndRow = pViewData->GetEditEndRow();
1542 if ( nPosX >= (SCsCOL) nEditCol && nPosX <= (SCsCOL) nEndCol &&
1543 nPosY >= (SCsROW) nEditRow && nPosY <= (SCsROW) nEndRow )
1545 // #53966# beim Klick in die Tabellen-EditView immer den Focus umsetzen
1546 if (bFormulaMode) // sonst ist es oben schon passiert
1547 GrabFocus();
1549 pScMod->SetInputMode( SC_INPUT_TABLE );
1550 bEEMouse = TRUE;
1551 bEditMode = pEditView->MouseButtonDown( rMEvt );
1552 return;
1556 if (pScMod->GetIsWaterCan())
1558 //! was is mit'm Mac ???
1559 if ( rMEvt.GetModifier() + rMEvt.GetButtons() == MOUSE_RIGHT )
1561 nMouseStatus = SC_GM_WATERUNDO;
1562 return;
1566 // Reihenfolge passend zum angezeigten Cursor:
1567 // RangeFinder, AutoFill, PageBreak, Drawing
1569 if ( HitRangeFinder( rMEvt.GetPosPixel(), bRFSize, &nRFIndex, &nRFAddX, &nRFAddY ) )
1571 bRFMouse = TRUE; // die anderen Variablen sind oben initialisiert
1573 if ( pViewData->GetActivePart() != eWhich )
1574 pViewData->GetView()->ActivatePart( eWhich ); //! schon oben immer ???
1576 // CaptureMouse();
1577 StartTracking();
1578 return;
1581 BOOL bCrossPointer = TestMouse( rMEvt, TRUE );
1582 if ( bCrossPointer )
1584 if ( bDouble )
1585 pViewData->GetView()->FillCrossDblClick();
1586 else
1587 pScMod->InputEnterHandler(); // Autofill etc.
1590 if ( !bCrossPointer )
1592 nPagebreakMouse = HitPageBreak( rMEvt.GetPosPixel(), &aPagebreakSource,
1593 &nPagebreakBreak, &nPagebreakPrev );
1594 if (nPagebreakMouse)
1596 bPagebreakDrawn = FALSE;
1597 // CaptureMouse();
1598 StartTracking();
1599 PagebreakMove( rMEvt, FALSE );
1600 return;
1604 if (!bFormulaMode && !bEditMode && rMEvt.IsLeft())
1606 if ( !bCrossPointer && DrawMouseButtonDown(rMEvt) )
1608 //if (DrawHasMarkedObj())
1609 // pViewData->GetViewShell()->SetDrawShellOrSub(); // Draw-Objekt selektiert
1610 return;
1613 pViewData->GetViewShell()->SetDrawShell( FALSE ); // kein Draw-Objekt selektiert
1615 // TestMouse schon oben passiert
1618 Point aPos = rMEvt.GetPosPixel();
1619 SCsCOL nPosX;
1620 SCsROW nPosY;
1621 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
1622 SCTAB nTab = pViewData->GetTabNo();
1623 ScDocument* pDoc = pViewData->GetDocument();
1627 // AutoFilter buttons
1630 if ( !bDouble && !bFormulaMode && rMEvt.IsLeft() )
1632 ScMergeFlagAttr* pAttr = (ScMergeFlagAttr*)
1633 pDoc->GetAttr( nPosX, nPosY, nTab, ATTR_MERGE_FLAG );
1634 if (pAttr->HasAutoFilter())
1636 Point aScrPos = pViewData->GetScrPos(nPosX,nPosY,eWhich);
1637 long nSizeX;
1638 long nSizeY;
1639 Point aDiffPix = aPos;
1641 aDiffPix -= aScrPos;
1642 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1643 if ( bLayoutRTL )
1644 aDiffPix.X() = -aDiffPix.X();
1646 pViewData->GetMergeSizePixel( nPosX, nPosY, nSizeX, nSizeY );
1648 // Breite des Buttons ist nicht von der Zellhoehe abhaengig
1649 Size aButSize = aComboButton.GetSizePixel();
1650 long nButWidth = Min( aButSize.Width(), nSizeX );
1651 long nButHeight = Min( aButSize.Height(), nSizeY );
1653 if ( aDiffPix.X() >= nSizeX - nButWidth &&
1654 aDiffPix.Y() >= nSizeY - nButHeight )
1656 if ( DoPageFieldSelection( nPosX, nPosY ) )
1657 return;
1659 BOOL bFilterActive = IsAutoFilterActive( nPosX, nPosY,
1660 pViewData->GetTabNo() );
1662 aComboButton.SetOptSizePixel();
1663 DrawComboButton( aScrPos, nSizeX, nSizeY, bFilterActive, TRUE );
1665 #if 0
1666 if ( bWasFilterBox
1667 && (SCsCOL)nOldColFBox == nPosX
1668 && (SCsROW)nOldRowFBox == nPosY )
1670 // Verhindern, dass an gleicher Stelle eine
1671 // FilterBox geoeffnet wird, wenn diese gerade
1672 // geloescht wurde
1674 nMouseStatus = SC_GM_FILTER; // fuer ButtonDraw im MouseButtonUp();
1675 return;
1677 #endif
1678 DoAutoFilterMenue( nPosX, nPosY, FALSE );
1680 return;
1683 if (pAttr->HasButton())
1685 DoPushButton( nPosX, nPosY, rMEvt ); // setzt evtl. bPivotMouse / bDPMouse
1686 return;
1689 // List Validity drop-down button
1691 if ( bListValButton )
1693 Rectangle aButtonRect = GetListValButtonRect( aListValPos );
1694 if ( aButtonRect.IsInside( aPos ) )
1696 DoAutoFilterMenue( aListValPos.Col(), aListValPos.Row(), TRUE );
1698 nMouseStatus = SC_GM_FILTER; // not set in DoAutoFilterMenue for bDataSelect
1699 CaptureMouse();
1700 return;
1706 // scenario selection
1709 ScRange aScenRange;
1710 if ( rMEvt.IsLeft() && HasScenarioButton( aPos, aScenRange ) )
1712 DoScenarioMenue( aScenRange );
1713 return;
1717 // Doppelklick angefangen ?
1720 // StopMarking kann aus DrawMouseButtonDown gerufen werden
1722 if ( nMouseStatus != SC_GM_IGNORE && !bRefMode )
1724 if ( bDouble && !bCrossPointer )
1726 if (nMouseStatus == SC_GM_TABDOWN)
1727 nMouseStatus = SC_GM_DBLDOWN;
1729 else
1730 nMouseStatus = SC_GM_TABDOWN;
1734 // Links in Edit-Zellen
1737 BOOL bAlt = rMEvt.IsMod2();
1738 if ( !bAlt && rMEvt.IsLeft() &&
1739 GetEditUrl(rMEvt.GetPosPixel()) ) // Klick auf Link: Cursor nicht bewegen
1741 SetPointer( Pointer( POINTER_REFHAND ) );
1742 nMouseStatus = SC_GM_URLDOWN; // auch nur dann beim ButtonUp ausfuehren
1743 return;
1747 // Gridwin - SelectionEngine
1750 if ( rMEvt.IsLeft() )
1752 ScViewSelectionEngine* pSelEng = pViewData->GetView()->GetSelEngine();
1753 pSelEng->SetWindow(this);
1754 pSelEng->SetWhich(eWhich);
1755 pSelEng->SetVisibleArea( Rectangle(Point(), GetOutputSizePixel()) );
1757 // SelMouseButtonDown an der View setzt noch das bMoveIsShift Flag
1758 if ( pViewData->GetView()->SelMouseButtonDown( rMEvt ) )
1760 if (IsMouseCaptured())
1762 // Tracking statt CaptureMouse, damit sauber abgebrochen werden kann
1763 //! Irgendwann sollte die SelectionEngine selber StartTracking rufen!?!
1764 ReleaseMouse();
1765 StartTracking();
1767 pViewData->GetMarkData().SetMarking(TRUE);
1768 return;
1773 void __EXPORT ScGridWindow::MouseButtonUp( const MouseEvent& rMEvt )
1775 aCurMousePos = rMEvt.GetPosPixel();
1776 ScDocument* pDoc = pViewData->GetDocument();
1777 ScMarkData& rMark = pViewData->GetMarkData();
1779 // #i41690# detect a MouseButtonUp call from within MouseButtonDown
1780 // (possible through Reschedule from storing an OLE object that is deselected)
1782 if ( nNestedButtonState == SC_NESTEDBUTTON_DOWN )
1783 nNestedButtonState = SC_NESTEDBUTTON_UP;
1785 if (nButtonDown != rMEvt.GetButtons())
1786 nMouseStatus = SC_GM_IGNORE; // reset und return
1788 nButtonDown = 0;
1790 if (nMouseStatus == SC_GM_IGNORE)
1792 nMouseStatus = SC_GM_NONE;
1793 // Selection-Engine: Markieren abbrechen
1794 pViewData->GetView()->GetSelEngine()->Reset();
1795 rMark.SetMarking(FALSE);
1796 if (pViewData->IsAnyFillMode())
1798 pViewData->GetView()->StopRefMode();
1799 pViewData->ResetFillMode();
1801 StopMarking();
1802 DrawEndAction(); // Markieren/Verschieben auf Drawing-Layer abbrechen
1803 ReleaseMouse();
1804 return;
1807 if (nMouseStatus == SC_GM_FILTER)
1809 if ( pFilterBox && pFilterBox->GetMode() == SC_FILTERBOX_FILTER )
1811 BOOL bFilterActive = IsAutoFilterActive( pFilterBox->GetCol(), pFilterBox->GetRow(),
1812 pViewData->GetTabNo() );
1813 HideCursor();
1814 aComboButton.Draw( bFilterActive );
1815 ShowCursor();
1817 nMouseStatus = SC_GM_NONE;
1818 ReleaseMouse();
1819 return; // da muss nix mehr passieren
1822 ScModule* pScMod = SC_MOD();
1823 if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
1824 return;
1826 SfxBindings& rBindings = pViewData->GetBindings();
1827 if (bEEMouse && pViewData->HasEditView( eWhich ))
1829 EditView* pEditView;
1830 SCCOL nEditCol;
1831 SCROW nEditRow;
1832 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
1833 pEditView->MouseButtonUp( rMEvt );
1835 if ( rMEvt.IsMiddle() &&
1836 GetSettings().GetMouseSettings().GetMiddleButtonAction() == MOUSE_MIDDLE_PASTESELECTION )
1838 // EditView may have pasted from selection
1839 pScMod->InputChanged( pEditView );
1841 else
1842 pScMod->InputSelection( pEditView ); // parentheses etc.
1844 pViewData->GetView()->InvalidateAttribs();
1845 rBindings.Invalidate( SID_HYPERLINK_GETLINK );
1846 bEEMouse = FALSE;
1847 return;
1850 #if OLD_PIVOT_IMPLEMENTATION
1851 if (bPivotMouse)
1853 PivotMouseButtonUp( rMEvt );
1854 bPivotMouse = FALSE;
1855 return;
1857 #endif
1859 if (bDPMouse)
1861 DPMouseButtonUp( rMEvt ); // resets bDPMouse
1862 return;
1865 if (bRFMouse)
1867 RFMouseMove( rMEvt, TRUE ); // Range wieder richtigherum
1868 bRFMouse = FALSE;
1869 SetPointer( Pointer( POINTER_ARROW ) );
1870 ReleaseMouse();
1871 return;
1874 if (nPagebreakMouse)
1876 PagebreakMove( rMEvt, TRUE );
1877 nPagebreakMouse = SC_PD_NONE;
1878 SetPointer( Pointer( POINTER_ARROW ) );
1879 ReleaseMouse();
1880 return;
1883 if (nMouseStatus == SC_GM_WATERUNDO) // Undo im Giesskannenmodus
1885 SfxUndoManager* pMgr = pViewData->GetDocShell()->GetUndoManager();
1886 if ( pMgr->GetUndoActionCount() && pMgr->GetUndoActionId() == STR_UNDO_APPLYCELLSTYLE )
1887 pMgr->Undo();
1888 else
1889 Sound::Beep();
1890 return;
1893 if (DrawMouseButtonUp(rMEvt)) // includes format paint brush handling for drawing objects
1894 return;
1896 rMark.SetMarking(FALSE);
1898 SetPointer( Pointer( POINTER_ARROW ) );
1900 if (pViewData->IsFillMode() ||
1901 ( pViewData->GetFillMode() == SC_FILL_MATRIX && rMEvt.IsMod1() ))
1903 nScFillModeMouseModifier = rMEvt.GetModifier();
1904 SCCOL nStartCol;
1905 SCROW nStartRow;
1906 SCCOL nEndCol;
1907 SCROW nEndRow;
1908 pViewData->GetFillData( nStartCol, nStartRow, nEndCol, nEndRow );
1909 // DBG_ASSERT( nStartCol==pViewData->GetRefStartX() && nStartRow==pViewData->GetRefStartY(),
1910 // "Block falsch fuer AutoFill" );
1911 ScRange aDelRange;
1912 BOOL bIsDel = pViewData->GetDelMark( aDelRange );
1914 ScViewFunc* pView = pViewData->GetView();
1915 pView->StopRefMode();
1916 pViewData->ResetFillMode();
1917 pView->GetFunctionSet()->SetAnchorFlag( FALSE ); // #i5819# don't use AutoFill anchor flag for selection
1919 if ( bIsDel )
1921 pView->MarkRange( aDelRange, FALSE );
1922 pView->DeleteContents( IDF_CONTENTS );
1923 SCTAB nTab = pViewData->GetTabNo();
1924 ScRange aBlockRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab );
1925 if ( aBlockRange != aDelRange )
1927 if ( aDelRange.aStart.Row() == nStartRow )
1928 aBlockRange.aEnd.SetCol( aDelRange.aStart.Col() - 1 );
1929 else
1930 aBlockRange.aEnd.SetRow( aDelRange.aStart.Row() - 1 );
1931 pView->MarkRange( aBlockRange, FALSE );
1934 else
1935 pViewData->GetDispatcher().Execute( FID_FILL_AUTO, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD );
1937 else if (pViewData->GetFillMode() == SC_FILL_MATRIX)
1939 SCTAB nTab = pViewData->GetTabNo();
1940 SCCOL nStartCol;
1941 SCROW nStartRow;
1942 SCCOL nEndCol;
1943 SCROW nEndRow;
1944 pViewData->GetFillData( nStartCol, nStartRow, nEndCol, nEndRow );
1945 ScRange aBlockRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab );
1946 SCCOL nFillCol = pViewData->GetRefEndX();
1947 SCROW nFillRow = pViewData->GetRefEndY();
1948 ScAddress aEndPos( nFillCol, nFillRow, nTab );
1950 ScTabView* pView = pViewData->GetView();
1951 pView->StopRefMode();
1952 pViewData->ResetFillMode();
1953 pView->GetFunctionSet()->SetAnchorFlag( FALSE );
1955 if ( aEndPos != aBlockRange.aEnd )
1957 pViewData->GetDocShell()->GetDocFunc().ResizeMatrix( aBlockRange, aEndPos, FALSE );
1958 pViewData->GetView()->MarkRange( ScRange( aBlockRange.aStart, aEndPos ) );
1961 else if (pViewData->IsAnyFillMode())
1963 // Embedded-Area has been changed
1964 ScTabView* pView = pViewData->GetView();
1965 pView->StopRefMode();
1966 pViewData->ResetFillMode();
1967 pView->GetFunctionSet()->SetAnchorFlag( FALSE );
1968 pViewData->GetDocShell()->UpdateOle(pViewData);
1971 BOOL bRefMode = pViewData->IsRefMode();
1972 if (bRefMode)
1973 pScMod->EndReference();
1976 // Giesskannen-Modus (Gestalter)
1979 if (pScMod->GetIsWaterCan())
1981 // Abfrage auf Undo schon oben
1983 ScStyleSheetPool* pStylePool = (ScStyleSheetPool*)
1984 (pViewData->GetDocument()->
1985 GetStyleSheetPool());
1986 if ( pStylePool )
1988 SfxStyleSheet* pStyleSheet = (SfxStyleSheet*)
1989 pStylePool->GetActualStyleSheet();
1991 if ( pStyleSheet )
1993 SfxStyleFamily eFamily = pStyleSheet->GetFamily();
1995 switch ( eFamily )
1997 case SFX_STYLE_FAMILY_PARA:
1998 pViewData->GetView()->SetStyleSheetToMarked( pStyleSheet );
1999 pViewData->GetView()->DoneBlockMode();
2000 break;
2002 case SFX_STYLE_FAMILY_PAGE:
2003 pViewData->GetDocument()->SetPageStyle( pViewData->GetTabNo(),
2004 pStyleSheet->GetName() );
2006 ScPrintFunc( pViewData->GetDocShell(),
2007 pViewData->GetViewShell()->GetPrinter(TRUE),
2008 pViewData->GetTabNo() ).UpdatePages();
2010 rBindings.Invalidate( SID_STATUS_PAGESTYLE );
2011 break;
2013 default:
2014 break;
2020 ScDBFunc* pView = pViewData->GetView();
2021 ScDocument* pBrushDoc = pView->GetBrushDocument();
2022 if ( pBrushDoc )
2024 pView->PasteFromClip( IDF_ATTRIB, pBrushDoc );
2025 if ( !pView->IsPaintBrushLocked() )
2026 pView->ResetBrushDocument(); // invalidates pBrushDoc pointer
2030 // double click (only left button)
2033 BOOL bDouble = ( rMEvt.GetClicks() == 2 && rMEvt.IsLeft() );
2034 if ( bDouble && !bRefMode && nMouseStatus == SC_GM_DBLDOWN && !pScMod->IsRefDialogOpen() )
2036 // data pilot table
2037 Point aPos = rMEvt.GetPosPixel();
2038 SCsCOL nPosX;
2039 SCsROW nPosY;
2040 SCTAB nTab = pViewData->GetTabNo();
2041 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
2042 ScDPObject* pDPObj = pDoc->GetDPAtCursor( nPosX, nPosY, nTab );
2043 if ( pDPObj && pDPObj->GetSaveData()->GetDrillDown() )
2045 ScAddress aCellPos( nPosX, nPosY, pViewData->GetTabNo() );
2047 // Check for header drill-down first.
2048 sheet::DataPilotTableHeaderData aData;
2049 pDPObj->GetHeaderPositionData(aCellPos, aData);
2051 if ( ( aData.Flags & sheet::MemberResultFlags::HASMEMBER ) &&
2052 ! ( aData.Flags & sheet::MemberResultFlags::SUBTOTAL ) )
2054 USHORT nDummy;
2055 if ( pView->HasSelectionForDrillDown( nDummy ) )
2057 // execute slot to show dialog
2058 pViewData->GetDispatcher().Execute( SID_OUTLINE_SHOW, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD );
2060 else
2062 // toggle single entry
2063 ScDPObject aNewObj( *pDPObj );
2064 pDPObj->ToggleDetails( aData, &aNewObj );
2065 ScDBDocFunc aFunc( *pViewData->GetDocShell() );
2066 aFunc.DataPilotUpdate( pDPObj, &aNewObj, TRUE, FALSE );
2067 pViewData->GetView()->CursorPosChanged(); // shells may be switched
2070 else
2072 // Check if the data area is double-clicked.
2074 Sequence<sheet::DataPilotFieldFilter> aFilters;
2075 if ( pDPObj->GetDataFieldPositionData(aCellPos, aFilters) )
2076 pViewData->GetView()->ShowDataPilotSourceData( *pDPObj, aFilters );
2077 else
2078 Sound::Beep(); // nothing to expand/collapse/show
2081 return;
2084 // Check for cell protection attribute.
2085 ScTableProtection* pProtect = pDoc->GetTabProtection( nTab );
2086 bool bEditAllowed = true;
2087 if ( pProtect && pProtect->isProtected() )
2089 bool bCellProtected = pDoc->HasAttrib(nPosX, nPosY, nTab, nPosX, nPosY, nTab, HASATTR_PROTECTED);
2090 bool bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
2091 bool bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
2093 if ( bSkipProtected && bSkipUnprotected )
2094 bEditAllowed = false;
2095 else if ( (bCellProtected && bSkipProtected) || (!bCellProtected && bSkipUnprotected) )
2096 bEditAllowed = false;
2099 if ( bEditAllowed )
2101 // edit cell contents
2102 pViewData->GetViewShell()->UpdateInputHandler();
2103 pScMod->SetInputMode( SC_INPUT_TABLE );
2104 if (pViewData->HasEditView(eWhich))
2106 // Text-Cursor gleich an die geklickte Stelle setzen
2107 EditView* pEditView = pViewData->GetEditView( eWhich );
2108 MouseEvent aEditEvt( rMEvt.GetPosPixel(), 1, MOUSE_SYNTHETIC, MOUSE_LEFT, 0 );
2109 pEditView->MouseButtonDown( aEditEvt );
2110 pEditView->MouseButtonUp( aEditEvt );
2113 return;
2117 // Links in edit cells
2120 BOOL bAlt = rMEvt.IsMod2();
2121 if ( !bAlt && !bRefMode && !bDouble && nMouseStatus == SC_GM_URLDOWN )
2123 // beim ButtonUp nur ausfuehren, wenn ButtonDown auch ueber einer URL war
2125 String aName, aUrl, aTarget;
2126 if ( GetEditUrl( rMEvt.GetPosPixel(), &aName, &aUrl, &aTarget ) )
2128 nMouseStatus = SC_GM_NONE; // keinen Doppelklick anfangen
2129 ScGlobal::OpenURL( aUrl, aTarget );
2131 // fire worksheet_followhyperlink event
2132 Point aPos = rMEvt.GetPosPixel();
2133 SCsCOL nPosX;
2134 SCsROW nPosY;
2135 SCTAB nTab = pViewData->GetTabNo();
2136 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
2137 ScBaseCell* pCell = NULL;
2139 BOOL bFound = lcl_GetHyperlinkCell( pDoc, nPosX, nPosY, nTab, pCell );
2140 if( bFound )
2142 ScAddress aCellPos( nPosX, nPosY, nTab );
2143 ScCellObj* pObj = new ScCellObj( pViewData->GetDocShell(), aCellPos );
2144 uno::Sequence< uno::Any > aArgs(1);
2145 aArgs[0] = uno::makeAny(uno::Reference<uno::XInterface>(static_cast<cppu::OWeakObject*>(pObj)));
2146 uno::Reference< document::XVbaEventsHelper > xVbaEventsHelper ( pViewData->GetDocument()->GetVbaEventsHelper(), uno::UNO_QUERY );
2147 if( xVbaEventsHelper.is() )
2148 xVbaEventsHelper->ProcessCompatibleVbaEvent( VBAEVENT_WORKSHEET_FOLLOWHYPERLINK, aArgs );
2150 return;
2155 // Gridwin - SelectionEngine
2158 // SelMouseButtonDown is called only for left button, but SelMouseButtonUp would return
2159 // TRUE for any call, so IsLeft must be checked here, too.
2161 if ( rMEvt.IsLeft() && pViewData->GetView()->GetSelEngine()->SelMouseButtonUp( rMEvt ) )
2163 // rMark.MarkToSimple();
2164 pViewData->GetView()->UpdateAutoFillMark();
2166 SfxDispatcher* pDisp = pViewData->GetViewShell()->GetDispatcher();
2167 BOOL bFormulaMode = pScMod->IsFormulaMode();
2168 DBG_ASSERT( pDisp || bFormulaMode, "Cursor auf nicht aktiver View bewegen ?" );
2170 // #i14927# execute SID_CURRENTCELL (for macro recording) only if there is no
2171 // multiple selection, so the argument string completely describes the selection,
2172 // and executing the slot won't change the existing selection (executing the slot
2173 // here and from a recorded macro is treated equally)
2175 if ( pDisp && !bFormulaMode && !rMark.IsMultiMarked() )
2177 String aAddr; // CurrentCell
2178 if( rMark.IsMarked() )
2180 // BOOL bKeep = rMark.IsMultiMarked(); //! wohin damit ???
2182 ScRange aScRange;
2183 rMark.GetMarkArea( aScRange );
2184 aScRange.Format( aAddr, SCR_ABS );
2185 if ( aScRange.aStart == aScRange.aEnd )
2187 // make sure there is a range selection string even for a single cell
2188 String aSingle = aAddr;
2189 aAddr.Append( (sal_Char) ':' );
2190 aAddr.Append( aSingle );
2193 //! SID_MARKAREA gibts nicht mehr ???
2194 //! was passiert beim Markieren mit dem Cursor ???
2196 else // nur Cursor bewegen
2198 ScAddress aScAddress( pViewData->GetCurX(), pViewData->GetCurY(), 0 );
2199 aScAddress.Format( aAddr, SCA_ABS );
2202 SfxStringItem aPosItem( SID_CURRENTCELL, aAddr );
2203 // We don't want to align to the cursor position because if the
2204 // cell cursor isn't visible after making selection, it would jump
2205 // back to the origin of the selection where the cell cursor is.
2206 SfxBoolItem aAlignCursorItem( FN_PARAM_2, false );
2207 pDisp->Execute( SID_CURRENTCELL, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD,
2208 &aPosItem, &aAlignCursorItem, (void*)0L );
2210 pViewData->GetView()->InvalidateAttribs();
2212 return;
2216 void ScGridWindow::FakeButtonUp()
2218 if ( nButtonDown )
2220 MouseEvent aEvent( aCurMousePos ); // nButtons = 0 -> ignore
2221 MouseButtonUp( aEvent );
2225 void __EXPORT ScGridWindow::MouseMove( const MouseEvent& rMEvt )
2227 aCurMousePos = rMEvt.GetPosPixel();
2229 if ( rMEvt.IsLeaveWindow() && pNoteMarker && !pNoteMarker->IsByKeyboard() )
2230 HideNoteMarker();
2232 ScModule* pScMod = SC_MOD();
2233 if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
2234 return;
2236 // Ob aus dem Edit-Modus Drag&Drop gestartet wurde, bekommt man leider
2237 // nicht anders mit:
2239 if (bEEMouse && nButtonDown && !rMEvt.GetButtons())
2241 bEEMouse = FALSE;
2242 nButtonDown = 0;
2243 nMouseStatus = SC_GM_NONE;
2244 return;
2247 if (nMouseStatus == SC_GM_IGNORE)
2248 return;
2250 if (nMouseStatus == SC_GM_WATERUNDO) // Undo im Giesskannenmodus -> nur auf Up warten
2251 return;
2253 if ( pViewData->GetViewShell()->IsAuditShell() ) // Detektiv-Fuell-Modus
2255 SetPointer( Pointer( POINTER_FILL ) );
2256 return;
2259 if (nMouseStatus == SC_GM_FILTER && pFilterBox)
2261 Point aRelPos = pFilterBox->ScreenToOutputPixel( OutputToScreenPixel( rMEvt.GetPosPixel() ) );
2262 if ( Rectangle(Point(),pFilterBox->GetOutputSizePixel()).IsInside(aRelPos) )
2264 nButtonDown = 0;
2265 nMouseStatus = SC_GM_NONE;
2266 if ( pFilterBox->GetMode() == SC_FILTERBOX_FILTER )
2268 HideCursor();
2269 aComboButton.Draw( FALSE );
2270 ShowCursor();
2272 ReleaseMouse();
2273 pFilterBox->MouseButtonDown( MouseEvent( aRelPos, 1, MOUSE_SIMPLECLICK, MOUSE_LEFT ) );
2274 return;
2278 BOOL bFormulaMode = pScMod->IsFormulaMode(); // naechster Klick -> Referenz
2280 if (bEEMouse && pViewData->HasEditView( eWhich ))
2282 EditView* pEditView;
2283 SCCOL nEditCol;
2284 SCROW nEditRow;
2285 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
2286 pEditView->MouseMove( rMEvt );
2287 return;
2290 #if OLD_PIVOT_IMPLEMENTATION
2291 if (bPivotMouse)
2293 PivotMouseMove( rMEvt );
2294 return;
2296 #endif
2298 if (bDPMouse)
2300 DPMouseMove( rMEvt );
2301 return;
2304 if (bRFMouse)
2306 RFMouseMove( rMEvt, FALSE );
2307 return;
2310 if (nPagebreakMouse)
2312 PagebreakMove( rMEvt, FALSE );
2313 return;
2316 // anderen Mauszeiger anzeigen?
2318 BOOL bEditMode = pViewData->HasEditView(eWhich);
2320 //! Testen ob RefMode-Dragging !!!
2321 if ( bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()) )
2323 Point aPos = rMEvt.GetPosPixel();
2324 SCsCOL nPosX;
2325 SCsROW nPosY;
2326 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
2328 EditView* pEditView;
2329 SCCOL nEditCol;
2330 SCROW nEditRow;
2331 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
2332 SCCOL nEndCol = pViewData->GetEditEndCol();
2333 SCROW nEndRow = pViewData->GetEditEndRow();
2335 if ( nPosX >= (SCsCOL) nEditCol && nPosX <= (SCsCOL) nEndCol &&
2336 nPosY >= (SCsROW) nEditRow && nPosY <= (SCsROW) nEndRow )
2338 // Field can only be URL field
2339 BOOL bAlt = rMEvt.IsMod2();
2340 if ( !bAlt && !nButtonDown && pEditView && pEditView->GetFieldUnderMousePointer() )
2341 SetPointer( Pointer( POINTER_REFHAND ) );
2342 else if ( pEditView && pEditView->GetEditEngine()->IsVertical() )
2343 SetPointer( Pointer( POINTER_TEXT_VERTICAL ) );
2344 else
2345 SetPointer( Pointer( POINTER_TEXT ) );
2346 return;
2350 BOOL bWater = SC_MOD()->GetIsWaterCan() || pViewData->GetView()->HasPaintBrush();
2351 if (bWater)
2352 SetPointer( Pointer(POINTER_FILL) );
2354 if (!bWater)
2356 BOOL bCross = FALSE;
2358 // Range-Finder
2360 BOOL bCorner;
2361 if ( HitRangeFinder( rMEvt.GetPosPixel(), bCorner ) )
2363 if (bCorner)
2364 SetPointer( Pointer( POINTER_CROSS ) );
2365 else
2366 SetPointer( Pointer( POINTER_HAND ) );
2367 bCross = TRUE;
2370 // Page-Break-Modus
2372 USHORT nBreakType;
2373 if ( !nButtonDown && pViewData->IsPagebreakMode() &&
2374 ( nBreakType = HitPageBreak( rMEvt.GetPosPixel() ) ) != 0 )
2376 PointerStyle eNew = POINTER_ARROW;
2377 switch ( nBreakType )
2379 case SC_PD_RANGE_L:
2380 case SC_PD_RANGE_R:
2381 case SC_PD_BREAK_H:
2382 eNew = POINTER_ESIZE;
2383 break;
2384 case SC_PD_RANGE_T:
2385 case SC_PD_RANGE_B:
2386 case SC_PD_BREAK_V:
2387 eNew = POINTER_SSIZE;
2388 break;
2389 case SC_PD_RANGE_TL:
2390 case SC_PD_RANGE_BR:
2391 eNew = POINTER_SESIZE;
2392 break;
2393 case SC_PD_RANGE_TR:
2394 case SC_PD_RANGE_BL:
2395 eNew = POINTER_NESIZE;
2396 break;
2398 SetPointer( Pointer( eNew ) );
2399 bCross = TRUE;
2402 // Fill-Cursor anzeigen ?
2404 if ( !bFormulaMode && !nButtonDown )
2405 if (TestMouse( rMEvt, FALSE ))
2406 bCross = TRUE;
2408 if ( nButtonDown && pViewData->IsAnyFillMode() )
2410 SetPointer( Pointer( POINTER_CROSS ) );
2411 bCross = TRUE;
2412 nScFillModeMouseModifier = rMEvt.GetModifier(); // ausgewertet bei AutoFill und Matrix
2415 if (!bCross)
2417 BOOL bAlt = rMEvt.IsMod2();
2419 if (bEditMode) // Edit-Mode muss zuerst kommen!
2420 SetPointer( Pointer( POINTER_ARROW ) );
2421 else if ( !bAlt && !nButtonDown &&
2422 GetEditUrl(rMEvt.GetPosPixel()) )
2423 SetPointer( Pointer( POINTER_REFHAND ) );
2424 else if ( DrawMouseMove(rMEvt) ) // setzt Pointer um
2425 return;
2429 if ( pViewData->GetView()->GetSelEngine()->SelMouseMove( rMEvt ) )
2430 return;
2433 void lcl_InitMouseEvent( ::com::sun::star::awt::MouseEvent& rEvent, const MouseEvent& rEvt )
2435 rEvent.Modifiers = 0;
2436 if ( rEvt.IsShift() )
2437 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::SHIFT;
2438 if ( rEvt.IsMod1() )
2439 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD1;
2440 if ( rEvt.IsMod2() )
2441 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD2;
2443 rEvent.Buttons = 0;
2444 if ( rEvt.IsLeft() )
2445 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::LEFT;
2446 if ( rEvt.IsRight() )
2447 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::RIGHT;
2448 if ( rEvt.IsMiddle() )
2449 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::MIDDLE;
2451 rEvent.X = rEvt.GetPosPixel().X();
2452 rEvent.Y = rEvt.GetPosPixel().Y();
2453 rEvent.ClickCount = rEvt.GetClicks();
2454 rEvent.PopupTrigger = sal_False;
2457 long ScGridWindow::PreNotify( NotifyEvent& rNEvt )
2459 USHORT nType = rNEvt.GetType();
2460 if ( nType == EVENT_MOUSEBUTTONUP || nType == EVENT_MOUSEBUTTONDOWN )
2462 Window* pWindow = rNEvt.GetWindow();
2463 if (pWindow == this && pViewData)
2465 SfxViewFrame* pViewFrame = pViewData->GetViewShell()->GetViewFrame();
2466 if (pViewFrame)
2468 SfxFrame* pFrame = pViewFrame->GetFrame();
2469 if (pFrame)
2471 com::sun::star::uno::Reference<com::sun::star::frame::XController> xController = pFrame->GetController();
2472 if (xController.is())
2474 ScTabViewObj* pImp = ScTabViewObj::getImplementation( xController );
2475 if (pImp && pImp->IsMouseListening())
2477 ::com::sun::star::awt::MouseEvent aEvent;
2478 lcl_InitMouseEvent( aEvent, *rNEvt.GetMouseEvent() );
2479 if ( rNEvt.GetWindow() )
2480 aEvent.Source = rNEvt.GetWindow()->GetComponentInterface();
2481 if ( nType == EVENT_MOUSEBUTTONDOWN )
2482 pImp->MousePressed( aEvent );
2483 else
2484 pImp->MouseReleased( aEvent );
2492 return Window::PreNotify( rNEvt );
2495 void ScGridWindow::Tracking( const TrackingEvent& rTEvt )
2497 // Weil die SelectionEngine kein Tracking kennt, die Events nur auf
2498 // die verschiedenen MouseHandler verteilen...
2500 const MouseEvent& rMEvt = rTEvt.GetMouseEvent();
2502 if ( rTEvt.IsTrackingCanceled() ) // alles abbrechen...
2504 if (!pViewData->GetView()->IsInActivatePart())
2506 #if OLD_PIVOT_IMPLEMENTATION
2507 if (bPivotMouse)
2508 bPivotMouse = FALSE; // gezeichnet wird per bDragRect
2509 #endif
2510 if (bDPMouse)
2511 bDPMouse = FALSE; // gezeichnet wird per bDragRect
2512 if (bDragRect)
2514 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
2515 bDragRect = FALSE;
2516 UpdateDragRectOverlay();
2518 if (bRFMouse)
2520 RFMouseMove( rMEvt, TRUE ); // richtig abbrechen geht dabei nicht...
2521 bRFMouse = FALSE;
2523 if (nPagebreakMouse)
2525 // if (bPagebreakDrawn)
2526 // DrawDragRect( aPagebreakDrag.aStart.Col(), aPagebreakDrag.aStart.Row(),
2527 // aPagebreakDrag.aEnd.Col(), aPagebreakDrag.aEnd.Row(), FALSE );
2528 bPagebreakDrawn = FALSE;
2529 UpdateDragRectOverlay();
2530 nPagebreakMouse = SC_PD_NONE;
2533 SetPointer( Pointer( POINTER_ARROW ) );
2534 StopMarking();
2535 MouseButtonUp( rMEvt ); // mit Status SC_GM_IGNORE aus StopMarking
2537 BOOL bRefMode = pViewData->IsRefMode();
2538 if (bRefMode)
2539 SC_MOD()->EndReference(); // #63148# Dialog nicht verkleinert lassen
2542 else if ( rTEvt.IsTrackingEnded() )
2544 // MouseButtonUp immer mit passenden Buttons (z.B. wegen Testtool, #63148#)
2545 // Schliesslich behauptet der Tracking-Event ja, dass normal beendet und nicht
2546 // abgebrochen wurde.
2548 MouseEvent aUpEvt( rMEvt.GetPosPixel(), rMEvt.GetClicks(),
2549 rMEvt.GetMode(), nButtonDown, rMEvt.GetModifier() );
2550 MouseButtonUp( aUpEvt );
2552 else
2553 MouseMove( rMEvt );
2556 void ScGridWindow::StartDrag( sal_Int8 /* nAction */, const Point& rPosPixel )
2558 if ( pFilterBox || nPagebreakMouse )
2559 return;
2561 HideNoteMarker();
2563 CommandEvent aDragEvent( rPosPixel, COMMAND_STARTDRAG, TRUE );
2565 if (bEEMouse && pViewData->HasEditView( eWhich ))
2567 EditView* pEditView;
2568 SCCOL nEditCol;
2569 SCROW nEditRow;
2570 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
2572 // #63263# don't remove the edit view while switching views
2573 ScModule* pScMod = SC_MOD();
2574 pScMod->SetInEditCommand( TRUE );
2576 pEditView->Command( aDragEvent );
2578 ScInputHandler* pHdl = pScMod->GetInputHdl();
2579 if (pHdl)
2580 pHdl->DataChanged();
2582 pScMod->SetInEditCommand( FALSE );
2583 if (!pViewData->IsActive()) // dropped to different view?
2585 ScInputHandler* pViewHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
2586 if ( pViewHdl && pViewData->HasEditView( eWhich ) )
2588 pViewHdl->CancelHandler();
2589 ShowCursor(); // missing from KillEditView
2593 else
2594 if ( !DrawCommand(aDragEvent) )
2595 pViewData->GetView()->GetSelEngine()->Command( aDragEvent );
2598 void lcl_SetTextCursorPos( ScViewData* pViewData, ScSplitPos eWhich, Window* pWin )
2600 SCCOL nCol = pViewData->GetCurX();
2601 SCROW nRow = pViewData->GetCurY();
2602 Rectangle aEditArea = pViewData->GetEditArea( eWhich, nCol, nRow, pWin, NULL, TRUE );
2603 aEditArea.Right() = aEditArea.Left();
2604 aEditArea = pWin->PixelToLogic( aEditArea );
2605 pWin->SetCursorRect( &aEditArea );
2608 void __EXPORT ScGridWindow::Command( const CommandEvent& rCEvt )
2610 // The command event is send to the window after a possible context
2611 // menu from an inplace client is closed. Now we have the chance to
2612 // deactivate the inplace client without any problem regarding parent
2613 // windows and code on the stack.
2614 // For more information, see #126086# and #128122#
2615 USHORT nCmd = rCEvt.GetCommand();
2616 ScTabViewShell* pTabViewSh = pViewData->GetViewShell();
2617 SfxInPlaceClient* pClient = pTabViewSh->GetIPClient();
2618 if ( pClient &&
2619 pClient->IsObjectInPlaceActive() &&
2620 nCmd == COMMAND_CONTEXTMENU )
2622 pTabViewSh->DeactivateOle();
2623 return;
2626 ScModule* pScMod = SC_MOD();
2627 DBG_ASSERT( nCmd != COMMAND_STARTDRAG, "ScGridWindow::Command called with COMMAND_STARTDRAG" );
2629 if ( nCmd == COMMAND_STARTEXTTEXTINPUT ||
2630 nCmd == COMMAND_ENDEXTTEXTINPUT ||
2631 nCmd == COMMAND_EXTTEXTINPUT ||
2632 nCmd == COMMAND_CURSORPOS )
2634 BOOL bEditView = pViewData->HasEditView( eWhich );
2635 if (!bEditView)
2637 // only if no cell editview is active, look at drawview
2638 SdrView* pSdrView = pViewData->GetView()->GetSdrView();
2639 if ( pSdrView )
2641 OutlinerView* pOlView = pSdrView->GetTextEditOutlinerView();
2642 if ( pOlView && pOlView->GetWindow() == this )
2644 pOlView->Command( rCEvt );
2645 return; // done
2650 if ( nCmd == COMMAND_CURSORPOS && !bEditView )
2652 // #88458# CURSORPOS may be called without following text input,
2653 // to set the input method window position
2654 // -> input mode must not be started,
2655 // manually calculate text insert position if not in input mode
2657 lcl_SetTextCursorPos( pViewData, eWhich, this );
2658 return;
2661 ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
2662 if ( pHdl )
2664 pHdl->InputCommand( rCEvt, TRUE );
2665 return; // done
2668 Window::Command( rCEvt );
2669 return;
2672 if ( nCmd == COMMAND_VOICE )
2674 // Der Handler wird nur gerufen, wenn ein Text-Cursor aktiv ist,
2675 // also muss es eine EditView oder ein editiertes Zeichenobjekt geben
2677 ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
2678 if ( pHdl && pViewData->HasEditView( eWhich ) )
2680 EditView* pEditView = pViewData->GetEditView( eWhich ); // ist dann nicht 0
2681 pHdl->DataChanging();
2682 pEditView->Command( rCEvt );
2683 pHdl->DataChanged();
2684 return; // erledigt
2686 SdrView* pSdrView = pViewData->GetView()->GetSdrView();
2687 if ( pSdrView )
2689 OutlinerView* pOlView = pSdrView->GetTextEditOutlinerView();
2690 if ( pOlView && pOlView->GetWindow() == this )
2692 pOlView->Command( rCEvt );
2693 return; // erledigt
2696 Window::Command(rCEvt); // sonst soll sich die Basisklasse drum kuemmern...
2697 return;
2700 if ( nCmd == COMMAND_PASTESELECTION )
2702 if ( bEEMouse )
2704 // EditEngine handles selection in MouseButtonUp - no action
2705 // needed in command handler
2707 else
2709 PasteSelection( rCEvt.GetMousePosPixel() );
2711 return;
2714 if ( nCmd == COMMAND_INPUTLANGUAGECHANGE )
2716 // #i55929# Font and font size state depends on input language if nothing is selected,
2717 // so the slots have to be invalidated when the input language is changed.
2719 SfxBindings& rBindings = pViewData->GetBindings();
2720 rBindings.Invalidate( SID_ATTR_CHAR_FONT );
2721 rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT );
2722 return;
2725 if ( nCmd == COMMAND_WHEEL || nCmd == COMMAND_STARTAUTOSCROLL || nCmd == COMMAND_AUTOSCROLL )
2727 BOOL bDone = pViewData->GetView()->ScrollCommand( rCEvt, eWhich );
2728 if (!bDone)
2729 Window::Command(rCEvt);
2730 return;
2732 // #i7560# FormulaMode check is below scrolling - scrolling is allowed during formula input
2733 BOOL bDisable = pScMod->IsFormulaMode() ||
2734 pScMod->IsModalMode(pViewData->GetSfxDocShell());
2735 if (bDisable)
2736 return;
2738 if ( nCmd == COMMAND_CONTEXTMENU && !SC_MOD()->GetIsWaterCan() )
2740 if (pViewData->IsAnyFillMode())
2742 pViewData->GetView()->StopRefMode();
2743 pViewData->ResetFillMode();
2745 ReleaseMouse();
2746 StopMarking();
2748 Point aPosPixel = rCEvt.GetMousePosPixel();
2749 Point aMenuPos = aPosPixel;
2750 BOOL bMouse = rCEvt.IsMouseEvent();
2752 if ( bMouse )
2754 // #i18735# First select the item under the mouse pointer.
2755 // This can change the selection, and the view state (edit mode, etc).
2756 SelectForContextMenu( aPosPixel );
2759 BOOL bDone = FALSE;
2760 BOOL bEdit = pViewData->HasEditView(eWhich);
2761 if ( !bEdit )
2763 // Edit-Zelle mit Spelling-Errors ?
2764 if ( bMouse && GetEditUrlOrError( TRUE, aPosPixel ) )
2766 // GetEditUrlOrError hat den Cursor schon bewegt
2768 pScMod->SetInputMode( SC_INPUT_TABLE );
2769 bEdit = pViewData->HasEditView(eWhich); // hat's geklappt ?
2771 DBG_ASSERT( bEdit, "kann nicht in Edit-Modus schalten" );
2774 if ( bEdit )
2776 EditView* pEditView = pViewData->GetEditView( eWhich ); // ist dann nicht 0
2778 if ( !bMouse )
2780 Cursor* pCur = pEditView->GetCursor();
2781 if ( pCur )
2783 Point aLogicPos = pCur->GetPos();
2784 // use the position right of the cursor (spell popup is opened if
2785 // the cursor is before the word, but not if behind it)
2786 aLogicPos.X() += pCur->GetWidth();
2787 aLogicPos.Y() += pCur->GetHeight() / 2; // center vertically
2788 aMenuPos = LogicToPixel( aLogicPos );
2792 // if edit mode was just started above, online spelling may be incomplete
2793 pEditView->GetEditEngine()->CompleteOnlineSpelling();
2795 // IsCursorAtWrongSpelledWord could be used for !bMouse
2796 // if there was a corresponding ExecuteSpellPopup call
2798 if( pEditView->IsWrongSpelledWordAtPos( aMenuPos ) )
2800 // Wenn man unter OS/2 neben das Popupmenue klickt, kommt MouseButtonDown
2801 // vor dem Ende des Menue-Execute, darum muss SetModified vorher kommen
2802 // (Bug #40968#)
2803 ScInputHandler* pHdl = pScMod->GetInputHdl();
2804 if (pHdl)
2805 pHdl->SetModified();
2807 Link aLink = LINK( this, ScGridWindow, PopupSpellingHdl );
2808 pEditView->ExecuteSpellPopup( aMenuPos, &aLink );
2810 bDone = TRUE;
2813 else if ( !bMouse )
2815 // non-edit menu by keyboard -> use lower right of cell cursor position
2817 SCCOL nCurX = pViewData->GetCurX();
2818 SCROW nCurY = pViewData->GetCurY();
2819 aMenuPos = pViewData->GetScrPos( nCurX, nCurY, eWhich, TRUE );
2820 long nSizeXPix;
2821 long nSizeYPix;
2822 pViewData->GetMergeSizePixel( nCurX, nCurY, nSizeXPix, nSizeYPix );
2823 aMenuPos.X() += nSizeXPix;
2824 aMenuPos.Y() += nSizeYPix;
2826 if (pViewData)
2828 ScTabViewShell* pViewSh = pViewData->GetViewShell();
2829 if (pViewSh)
2831 // Is a draw object selected?
2833 SdrView* pDrawView = pViewSh->GetSdrView();
2834 if (pDrawView && pDrawView->AreObjectsMarked())
2836 // #100442#; the conext menu should open in the middle of the selected objects
2837 Rectangle aSelectRect(LogicToPixel(pDrawView->GetAllMarkedBoundRect()));
2838 aMenuPos = aSelectRect.Center();
2844 if (!bDone)
2846 SfxDispatcher::ExecutePopup( 0, this, &aMenuPos );
2851 void ScGridWindow::SelectForContextMenu( const Point& rPosPixel )
2853 // #i18735# if the click was outside of the current selection,
2854 // the cursor is moved or an object at the click position selected.
2855 // (see SwEditWin::SelectMenuPosition in Writer)
2857 SCsCOL nCellX;
2858 SCsROW nCellY;
2859 pViewData->GetPosFromPixel( rPosPixel.X(), rPosPixel.Y(), eWhich, nCellX, nCellY );
2860 ScTabView* pView = pViewData->GetView();
2861 ScDrawView* pDrawView = pView->GetScDrawView();
2863 // check cell edit mode
2865 if ( pViewData->HasEditView(eWhich) )
2867 ScModule* pScMod = SC_MOD();
2868 SCCOL nEditStartCol = pViewData->GetEditViewCol(); //! change to GetEditStartCol after calcrtl is integrated
2869 SCROW nEditStartRow = pViewData->GetEditViewRow();
2870 SCCOL nEditEndCol = pViewData->GetEditEndCol();
2871 SCROW nEditEndRow = pViewData->GetEditEndRow();
2873 if ( nCellX >= (SCsCOL) nEditStartCol && nCellX <= (SCsCOL) nEditEndCol &&
2874 nCellY >= (SCsROW) nEditStartRow && nCellY <= (SCsROW) nEditEndRow )
2876 // handle selection within the EditView
2878 EditView* pEditView = pViewData->GetEditView( eWhich ); // not NULL (HasEditView)
2879 EditEngine* pEditEngine = pEditView->GetEditEngine();
2880 Rectangle aOutputArea = pEditView->GetOutputArea();
2881 Rectangle aVisArea = pEditView->GetVisArea();
2883 Point aTextPos = PixelToLogic( rPosPixel );
2884 if ( pEditEngine->IsVertical() ) // have to manually transform position
2886 aTextPos -= aOutputArea.TopRight();
2887 long nTemp = -aTextPos.X();
2888 aTextPos.X() = aTextPos.Y();
2889 aTextPos.Y() = nTemp;
2891 else
2892 aTextPos -= aOutputArea.TopLeft();
2893 aTextPos += aVisArea.TopLeft(); // position in the edit document
2895 EPosition aDocPosition = pEditEngine->FindDocPosition(aTextPos);
2896 ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex);
2897 ESelection aSelection = pEditView->GetSelection();
2898 aSelection.Adjust(); // needed for IsLess/IsGreater
2899 if ( aCompare.IsLess(aSelection) || aCompare.IsGreater(aSelection) )
2901 // clicked outside the selected text - deselect and move text cursor
2902 MouseEvent aEvent( rPosPixel );
2903 pEditView->MouseButtonDown( aEvent );
2904 pEditView->MouseButtonUp( aEvent );
2905 pScMod->InputSelection( pEditView );
2908 return; // clicked within the edit view - keep edit mode
2910 else
2912 // outside of the edit view - end edit mode, regardless of cell selection, then continue
2913 pScMod->InputEnterHandler();
2917 // check draw text edit mode
2919 Point aLogicPos = PixelToLogic( rPosPixel ); // after cell edit mode is ended
2920 if ( pDrawView && pDrawView->GetTextEditObject() && pDrawView->GetTextEditOutlinerView() )
2922 OutlinerView* pOlView = pDrawView->GetTextEditOutlinerView();
2923 Rectangle aOutputArea = pOlView->GetOutputArea();
2924 if ( aOutputArea.IsInside( aLogicPos ) )
2926 // handle selection within the OutlinerView
2928 Outliner* pOutliner = pOlView->GetOutliner();
2929 const EditEngine& rEditEngine = pOutliner->GetEditEngine();
2930 Rectangle aVisArea = pOlView->GetVisArea();
2932 Point aTextPos = aLogicPos;
2933 if ( pOutliner->IsVertical() ) // have to manually transform position
2935 aTextPos -= aOutputArea.TopRight();
2936 long nTemp = -aTextPos.X();
2937 aTextPos.X() = aTextPos.Y();
2938 aTextPos.Y() = nTemp;
2940 else
2941 aTextPos -= aOutputArea.TopLeft();
2942 aTextPos += aVisArea.TopLeft(); // position in the edit document
2944 EPosition aDocPosition = rEditEngine.FindDocPosition(aTextPos);
2945 ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex);
2946 ESelection aSelection = pOlView->GetSelection();
2947 aSelection.Adjust(); // needed for IsLess/IsGreater
2948 if ( aCompare.IsLess(aSelection) || aCompare.IsGreater(aSelection) )
2950 // clicked outside the selected text - deselect and move text cursor
2951 // use DrawView to allow extra handling there (none currently)
2952 MouseEvent aEvent( rPosPixel );
2953 pDrawView->MouseButtonDown( aEvent, this );
2954 pDrawView->MouseButtonUp( aEvent, this );
2957 return; // clicked within the edit area - keep edit mode
2959 else
2961 // Outside of the edit area - end text edit mode, then continue.
2962 // DrawDeselectAll also ends text edit mode and updates the shells.
2963 // If the click was on the edited object, it will be selected again below.
2964 pView->DrawDeselectAll();
2968 // look for existing selection
2970 BOOL bHitSelected = FALSE;
2971 if ( pDrawView && pDrawView->IsMarkedObjHit( aLogicPos ) )
2973 // clicked on selected object -> don't change anything
2974 bHitSelected = TRUE;
2976 else if ( pViewData->GetMarkData().IsCellMarked(nCellX, nCellY) )
2978 // clicked on selected cell -> don't change anything
2979 bHitSelected = TRUE;
2982 // select drawing object or move cell cursor
2984 if ( !bHitSelected )
2986 BOOL bWasDraw = ( pDrawView && pDrawView->AreObjectsMarked() );
2987 BOOL bHitDraw = FALSE;
2988 if ( pDrawView )
2990 pDrawView->UnmarkAllObj();
2991 // Unlock the Internal Layer in order to activate the context menu.
2992 // re-lock in ScDrawView::MarkListHasChanged()
2993 lcl_UnLockComment( pDrawView, pDrawView->GetSdrPageView(), pDrawView->GetModel(), aLogicPos ,pViewData);
2994 bHitDraw = pDrawView->MarkObj( aLogicPos );
2995 // draw shell is activated in MarkListHasChanged
2997 if ( !bHitDraw )
2999 pView->Unmark();
3000 pView->SetCursor(nCellX, nCellY);
3001 if ( bWasDraw )
3002 pViewData->GetViewShell()->SetDrawShell( FALSE ); // switch shells
3007 static void ClearSingleSelection( ScViewData* pViewData )
3009 SCCOL nX;
3010 SCROW nY;
3011 ScTransferObj* pTransObj = ScTransferObj::GetOwnClipboard(
3012 pViewData->GetActiveWin() );
3013 if (!pTransObj)
3014 return;
3016 ScDocument* pClipDoc = pTransObj->GetDocument();
3017 pClipDoc->GetClipArea( nX, nY, TRUE );
3018 if (nX == 0 && nY == 0)
3020 ScTabView* pView = pViewData->GetView();
3021 pView->Unmark();
3025 void __EXPORT ScGridWindow::KeyInput(const KeyEvent& rKEvt)
3027 // #96965# Cursor control for ref input dialog
3028 const KeyCode& rKeyCode = rKEvt.GetKeyCode();
3029 if( SC_MOD()->IsRefDialogOpen() )
3031 if( !rKeyCode.GetModifier() && (rKeyCode.GetCode() == KEY_F2) )
3033 SC_MOD()->EndReference();
3034 return;
3036 else if( pViewData->GetViewShell()->MoveCursorKeyInput( rKEvt ) )
3038 ScRange aRef(
3039 pViewData->GetRefStartX(), pViewData->GetRefStartY(), pViewData->GetRefStartZ(),
3040 pViewData->GetRefEndX(), pViewData->GetRefEndY(), pViewData->GetRefEndZ() );
3041 SC_MOD()->SetReference( aRef, pViewData->GetDocument() );
3042 return;
3045 else if( rKeyCode.GetCode() == KEY_RETURN && pViewData->IsPasteMode() )
3047 ScTabViewShell* pTabViewShell = pViewData->GetViewShell();
3049 ScCellShell::PasteFromClipboard( pViewData, pTabViewShell, FALSE );
3050 ClearSingleSelection( pViewData );
3052 uno::Reference<datatransfer::clipboard::XClipboard> xSystemClipboard =
3053 TransferableHelper::GetSystemClipboard();
3054 if (xSystemClipboard.is())
3056 xSystemClipboard->setContents(
3057 uno::Reference<datatransfer::XTransferable>(),
3058 uno::Reference<datatransfer::clipboard::XClipboardOwner>());
3061 // hide the border around the copy source
3062 pViewData->SetPasteMode( SC_PASTE_NONE );
3063 UpdateCursorOverlay();
3064 return;
3066 // wenn semi-Modeless-SfxChildWindow-Dialog oben, keine KeyInputs:
3067 else if( !pViewData->IsAnyFillMode() )
3069 if (rKeyCode.GetCode() == KEY_ESCAPE)
3071 pViewData->SetPasteMode( SC_PASTE_NONE );
3072 UpdateCursorOverlay();
3074 // query for existing note marker before calling ViewShell's keyboard handling
3075 // which may remove the marker
3076 BOOL bHadKeyMarker = ( pNoteMarker && pNoteMarker->IsByKeyboard() );
3077 ScTabViewShell* pViewSh = pViewData->GetViewShell();
3079 if (pViewData->GetDocShell()->GetProgress())
3080 return;
3082 if (DrawKeyInput(rKEvt))
3083 return;
3085 if (!pViewData->GetView()->IsDrawSelMode() && !DrawHasMarkedObj()) // keine Eingaben im Zeichenmodus
3086 { //! DrawShell abfragen !!!
3087 if (pViewSh->TabKeyInput(rKEvt))
3088 return;
3090 else
3091 if (pViewSh->SfxViewShell::KeyInput(rKEvt)) // von SfxViewShell
3092 return;
3094 KeyCode aCode = rKEvt.GetKeyCode();
3095 if ( aCode.GetCode() == KEY_ESCAPE && aCode.GetModifier() == 0 )
3097 if ( bHadKeyMarker )
3098 HideNoteMarker();
3099 else
3100 pViewSh->Escape();
3101 return;
3103 if ( aCode.GetCode() == KEY_F1 && aCode.GetModifier() == KEY_MOD1 )
3105 // ctrl-F1 shows or hides the note or redlining info for the cursor position
3106 // (hard-coded because F1 can't be configured)
3108 if ( bHadKeyMarker )
3109 HideNoteMarker(); // hide when previously visible
3110 else
3111 ShowNoteMarker( pViewData->GetCurX(), pViewData->GetCurY(), TRUE );
3112 return;
3114 if (aCode.GetCode() == KEY_BRACKETLEFT && aCode.GetModifier() == KEY_MOD1)
3116 pViewSh->DetectiveMarkPred();
3117 return;
3119 if (aCode.GetCode() == KEY_BRACKETRIGHT && aCode.GetModifier() == KEY_MOD1)
3121 pViewSh->DetectiveMarkSucc();
3122 return;
3127 Window::KeyInput(rKEvt);
3130 void ScGridWindow::StopMarking()
3132 DrawEndAction(); // Markieren/Verschieben auf Drawing-Layer abbrechen
3134 if (nButtonDown)
3136 pViewData->GetMarkData().SetMarking(FALSE);
3137 nMouseStatus = SC_GM_IGNORE;
3141 void ScGridWindow::UpdateInputContext()
3143 BOOL bReadOnly = pViewData->GetDocShell()->IsReadOnly();
3144 ULONG nOptions = bReadOnly ? 0 : ( INPUTCONTEXT_TEXT | INPUTCONTEXT_EXTTEXTINPUT );
3146 // when font from InputContext is used,
3147 // it must be taken from the cursor position's cell attributes
3149 InputContext aContext;
3150 aContext.SetOptions( nOptions );
3151 SetInputContext( aContext );
3154 //--------------------------------------------------------
3156 // sensitiver Bereich (Pixel)
3157 #define SCROLL_SENSITIVE 20
3159 BOOL ScGridWindow::DropScroll( const Point& rMousePos )
3161 /* doch auch auf nicht aktiven Views...
3162 if ( !pViewData->IsActive() )
3163 return FALSE;
3165 SCsCOL nDx = 0;
3166 SCsROW nDy = 0;
3167 Size aSize = GetOutputSizePixel();
3169 if (aSize.Width() > SCROLL_SENSITIVE * 3)
3171 if ( rMousePos.X() < SCROLL_SENSITIVE && pViewData->GetPosX(WhichH(eWhich)) > 0 )
3172 nDx = -1;
3173 if ( rMousePos.X() >= aSize.Width() - SCROLL_SENSITIVE
3174 && pViewData->GetPosX(WhichH(eWhich)) < MAXCOL )
3175 nDx = 1;
3177 if (aSize.Height() > SCROLL_SENSITIVE * 3)
3179 if ( rMousePos.Y() < SCROLL_SENSITIVE && pViewData->GetPosY(WhichV(eWhich)) > 0 )
3180 nDy = -1;
3181 if ( rMousePos.Y() >= aSize.Height() - SCROLL_SENSITIVE
3182 && pViewData->GetPosY(WhichV(eWhich)) < MAXROW )
3183 nDy = 1;
3186 if ( nDx != 0 || nDy != 0 )
3188 // if (bDragRect)
3189 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3191 if ( nDx != 0 )
3192 pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) );
3193 if ( nDy != 0 )
3194 pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) );
3196 // if (bDragRect)
3197 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3200 return FALSE;
3203 BOOL lcl_TestScenarioRedliningDrop( ScDocument* pDoc, const ScRange& aDragRange)
3205 // Testet, ob bei eingeschalteten RedLining,
3206 // bei einem Drop ein Scenario betroffen ist.
3208 BOOL bReturn = FALSE;
3209 SCTAB nTab = aDragRange.aStart.Tab();
3210 SCTAB nTabCount = pDoc->GetTableCount();
3212 if(pDoc->GetChangeTrack()!=NULL)
3214 if( pDoc->IsScenario(nTab) && pDoc->HasScenarioRange(nTab, aDragRange))
3216 bReturn = TRUE;
3218 else
3220 for(SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
3222 if(pDoc->HasScenarioRange(i, aDragRange))
3224 bReturn = TRUE;
3225 break;
3230 return bReturn;
3233 ScRange lcl_MakeDropRange( SCCOL nPosX, SCROW nPosY, SCTAB nTab, const ScRange& rSource )
3235 SCCOL nCol1 = nPosX;
3236 SCCOL nCol2 = nCol1 + ( rSource.aEnd.Col() - rSource.aStart.Col() );
3237 if ( nCol2 > MAXCOL )
3239 nCol1 -= nCol2 - MAXCOL;
3240 nCol2 = MAXCOL;
3242 SCROW nRow1 = nPosY;
3243 SCROW nRow2 = nRow1 + ( rSource.aEnd.Row() - rSource.aStart.Row() );
3244 if ( nRow2 > MAXROW )
3246 nRow1 -= nRow2 - MAXROW;
3247 nRow2 = MAXROW;
3250 return ScRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab );
3253 //--------------------------------------------------------
3255 extern BOOL bPasteIsDrop; // viewfun4 -> move to header
3256 extern BOOL bPasteIsMove; // viewfun7 -> move to header
3258 //--------------------------------------------------------
3260 sal_Int8 ScGridWindow::AcceptPrivateDrop( const AcceptDropEvent& rEvt )
3262 if ( rEvt.mbLeaving )
3264 // if (bDragRect)
3265 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3266 bDragRect = FALSE;
3267 UpdateDragRectOverlay();
3268 return rEvt.mnAction;
3271 const ScDragData& rData = SC_MOD()->GetDragData();
3272 if ( rData.pCellTransfer )
3274 // Don't move source that would include filtered rows.
3275 if ((rEvt.mnAction & DND_ACTION_MOVE) && rData.pCellTransfer->HasFilteredRows())
3277 if (bDragRect)
3279 bDragRect = FALSE;
3280 UpdateDragRectOverlay();
3282 return DND_ACTION_NONE;
3285 Point aPos = rEvt.maPosPixel;
3287 ScDocument* pSourceDoc = rData.pCellTransfer->GetSourceDocument();
3288 ScDocument* pThisDoc = pViewData->GetDocument();
3289 if (pSourceDoc == pThisDoc)
3291 if ( pThisDoc->HasChartAtPoint(pViewData->GetTabNo(), PixelToLogic(aPos)) )
3293 if (bDragRect) // Rechteck loeschen
3295 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3296 bDragRect = FALSE;
3297 UpdateDragRectOverlay();
3300 //! highlight chart? (selection border?)
3302 sal_Int8 nRet = rEvt.mnAction;
3303 //! if ( rEvt.GetAction() == DROP_LINK )
3304 //! bOk = rEvt.SetAction( DROP_COPY ); // can't link onto chart
3305 return nRet;
3308 //! else
3309 //! if ( rEvt.GetAction() == DROP_MOVE )
3310 //! rEvt.SetAction( DROP_COPY ); // different doc: default=COPY
3313 if ( rData.pCellTransfer->GetDragSourceFlags() & SC_DROP_TABLE ) // whole sheet?
3315 BOOL bOk = pThisDoc->IsDocEditable();
3316 return bOk ? rEvt.mnAction : 0; // don't draw selection frame
3319 SCsCOL nPosX;
3320 SCsROW nPosY;
3321 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
3323 ScRange aSourceRange = rData.pCellTransfer->GetRange();
3324 SCCOL nSourceStartX = aSourceRange.aStart.Col();
3325 SCROW nSourceStartY = aSourceRange.aStart.Row();
3326 SCCOL nSourceEndX = aSourceRange.aEnd.Col();
3327 SCROW nSourceEndY = aSourceRange.aEnd.Row();
3328 SCCOL nSizeX = nSourceEndX - nSourceStartX + 1;
3329 SCROW nSizeY = nSourceEndY - nSourceStartY + 1;
3331 if ( rEvt.mnAction != DND_ACTION_MOVE )
3332 nSizeY = rData.pCellTransfer->GetNonFilteredRows(); // copy/link: no filtered rows
3334 SCsCOL nNewDragX = nPosX - rData.pCellTransfer->GetDragHandleX();
3335 if (nNewDragX<0) nNewDragX=0;
3336 if (nNewDragX+(nSizeX-1) > MAXCOL)
3337 nNewDragX = MAXCOL-(nSizeX-1);
3338 SCsROW nNewDragY = nPosY - rData.pCellTransfer->GetDragHandleY();
3339 if (nNewDragY<0) nNewDragY=0;
3340 if (nNewDragY+(nSizeY-1) > MAXROW)
3341 nNewDragY = MAXROW-(nSizeY-1);
3343 // don't break scenario ranges, don't drop on filtered
3344 SCTAB nTab = pViewData->GetTabNo();
3345 ScRange aDropRange = lcl_MakeDropRange( nNewDragX, nNewDragY, nTab, aSourceRange );
3346 if ( lcl_TestScenarioRedliningDrop( pThisDoc, aDropRange ) ||
3347 lcl_TestScenarioRedliningDrop( pSourceDoc, aSourceRange ) ||
3348 ScViewUtil::HasFiltered( aDropRange, pThisDoc) )
3350 if (bDragRect)
3352 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3353 bDragRect = FALSE;
3354 UpdateDragRectOverlay();
3356 return DND_ACTION_NONE;
3359 InsCellCmd eDragInsertMode = INS_NONE;
3360 Window::PointerState aState = GetPointerState();
3362 // check for datapilot item sorting
3363 ScDPObject* pDPObj = NULL;
3364 if ( pThisDoc == pSourceDoc && ( pDPObj = pThisDoc->GetDPAtCursor( nNewDragX, nNewDragY, nTab ) ) != NULL )
3366 // drop on DataPilot table: sort or nothing
3368 bool bDPSort = false;
3369 if ( pThisDoc->GetDPAtCursor( nSourceStartX, nSourceStartY, aSourceRange.aStart.Tab() ) == pDPObj )
3371 sheet::DataPilotTableHeaderData aDestData;
3372 pDPObj->GetHeaderPositionData( ScAddress(nNewDragX, nNewDragY, nTab), aDestData );
3373 bool bValid = ( aDestData.Dimension >= 0 ); // dropping onto a field
3375 // look through the source range
3376 for (SCROW nRow = aSourceRange.aStart.Row(); bValid && nRow <= aSourceRange.aEnd.Row(); ++nRow )
3377 for (SCCOL nCol = aSourceRange.aStart.Col(); bValid && nCol <= aSourceRange.aEnd.Col(); ++nCol )
3379 sheet::DataPilotTableHeaderData aSourceData;
3380 pDPObj->GetHeaderPositionData( ScAddress( nCol, nRow, aSourceRange.aStart.Tab() ), aSourceData );
3381 if ( aSourceData.Dimension != aDestData.Dimension || !aSourceData.MemberName.getLength() )
3382 bValid = false; // empty (subtotal) or different field
3385 if ( bValid )
3387 BOOL bIsDataLayout;
3388 String aDimName = pDPObj->GetDimName( aDestData.Dimension, bIsDataLayout );
3389 const ScDPSaveDimension* pDim = pDPObj->GetSaveData()->GetExistingDimensionByName( aDimName );
3390 if ( pDim )
3392 ScRange aOutRange = pDPObj->GetOutRange();
3394 USHORT nOrient = pDim->GetOrientation();
3395 if ( nOrient == sheet::DataPilotFieldOrientation_COLUMN )
3397 eDragInsertMode = INS_CELLSRIGHT;
3398 nSizeY = aOutRange.aEnd.Row() - nNewDragY + 1;
3399 bDPSort = true;
3401 else if ( nOrient == sheet::DataPilotFieldOrientation_ROW )
3403 eDragInsertMode = INS_CELLSDOWN;
3404 nSizeX = aOutRange.aEnd.Col() - nNewDragX + 1;
3405 bDPSort = true;
3411 if ( !bDPSort )
3413 // no valid sorting in a DataPilot table -> disallow
3414 if ( bDragRect )
3416 bDragRect = FALSE;
3417 UpdateDragRectOverlay();
3419 return DND_ACTION_NONE;
3422 else if ( aState.mnState & KEY_MOD2 )
3424 if ( pThisDoc == pSourceDoc && nTab == aSourceRange.aStart.Tab() )
3426 long nDeltaX = labs( static_cast< long >( nNewDragX - nSourceStartX ) );
3427 long nDeltaY = labs( static_cast< long >( nNewDragY - nSourceStartY ) );
3428 if ( nDeltaX <= nDeltaY )
3430 eDragInsertMode = INS_CELLSDOWN;
3432 else
3434 eDragInsertMode = INS_CELLSRIGHT;
3437 if ( ( eDragInsertMode == INS_CELLSDOWN && nNewDragY <= nSourceEndY &&
3438 ( nNewDragX + nSizeX - 1 ) >= nSourceStartX && nNewDragX <= nSourceEndX &&
3439 ( nNewDragX != nSourceStartX || nNewDragY >= nSourceStartY ) ) ||
3440 ( eDragInsertMode == INS_CELLSRIGHT && nNewDragX <= nSourceEndX &&
3441 ( nNewDragY + nSizeY - 1 ) >= nSourceStartY && nNewDragY <= nSourceEndY &&
3442 ( nNewDragY != nSourceStartY || nNewDragX >= nSourceStartX ) ) )
3444 if ( bDragRect )
3446 bDragRect = FALSE;
3447 UpdateDragRectOverlay();
3449 return DND_ACTION_NONE;
3452 else
3454 if ( static_cast< long >( nSizeX ) >= static_cast< long >( nSizeY ) )
3456 eDragInsertMode = INS_CELLSDOWN;
3459 else
3461 eDragInsertMode = INS_CELLSRIGHT;
3466 if ( nNewDragX != (SCsCOL) nDragStartX || nNewDragY != (SCsROW) nDragStartY ||
3467 nDragStartX+nSizeX-1 != nDragEndX || nDragStartY+nSizeY-1 != nDragEndY ||
3468 !bDragRect || eDragInsertMode != meDragInsertMode )
3470 // if (bDragRect)
3471 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3473 nDragStartX = nNewDragX;
3474 nDragStartY = nNewDragY;
3475 nDragEndX = nDragStartX+nSizeX-1;
3476 nDragEndY = nDragStartY+nSizeY-1;
3477 bDragRect = TRUE;
3478 meDragInsertMode = eDragInsertMode;
3480 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3482 UpdateDragRectOverlay();
3484 // show target position as tip help
3485 #if 0
3486 if (Help::IsQuickHelpEnabled())
3488 ScRange aRange( nDragStartX, nDragStartY, nTab, nDragEndX, nDragEndY, nTab );
3489 String aHelpStr;
3490 aRange.Format( aHelpStr, SCA_VALID ); // non-3D
3492 Point aPos = Pointer::GetPosPixel();
3493 USHORT nAlign = QUICKHELP_BOTTOM|QUICKHELP_RIGHT;
3494 Rectangle aRect( aPos, aPos );
3495 Help::ShowQuickHelp(aRect, aHelpStr, nAlign);
3497 #endif
3501 return rEvt.mnAction;
3504 sal_Int8 ScGridWindow::AcceptDrop( const AcceptDropEvent& rEvt )
3506 const ScDragData& rData = SC_MOD()->GetDragData();
3507 if ( rEvt.mbLeaving )
3509 DrawMarkDropObj( NULL );
3510 if ( rData.pCellTransfer )
3511 return AcceptPrivateDrop( rEvt ); // hide drop marker for internal D&D
3512 else
3513 return rEvt.mnAction;
3516 if ( pViewData->GetDocShell()->IsReadOnly() )
3517 return DND_ACTION_NONE;
3520 sal_Int8 nRet = DND_ACTION_NONE;
3522 if (rData.pCellTransfer)
3524 ScRange aSource = rData.pCellTransfer->GetRange();
3525 if ( aSource.aStart.Col() != 0 || aSource.aEnd.Col() != MAXCOL ||
3526 aSource.aStart.Row() != 0 || aSource.aEnd.Row() != MAXROW )
3527 DropScroll( rEvt.maPosPixel );
3529 nRet = AcceptPrivateDrop( rEvt );
3531 else
3533 if ( rData.aLinkDoc.Len() )
3535 String aThisName;
3536 ScDocShell* pDocSh = pViewData->GetDocShell();
3537 if (pDocSh && pDocSh->HasName())
3538 aThisName = pDocSh->GetMedium()->GetName();
3540 if ( rData.aLinkDoc != aThisName )
3541 nRet = rEvt.mnAction;
3543 else if (rData.aJumpTarget.Len())
3545 // internal bookmarks (from Navigator)
3546 // local jumps from an unnamed document are possible only within a document
3548 if ( !rData.pJumpLocalDoc || rData.pJumpLocalDoc == pViewData->GetDocument() )
3549 nRet = rEvt.mnAction;
3551 else
3553 sal_Int8 nMyAction = rEvt.mnAction;
3555 if ( !rData.pDrawTransfer ||
3556 !IsMyModel(rData.pDrawTransfer->GetDragSourceView()) ) // drawing within the document
3557 if ( rEvt.mbDefault && nMyAction == DND_ACTION_MOVE )
3558 nMyAction = DND_ACTION_COPY;
3560 ScDocument* pThisDoc = pViewData->GetDocument();
3561 SdrObject* pHitObj = pThisDoc->GetObjectAtPoint(
3562 pViewData->GetTabNo(), PixelToLogic(rEvt.maPosPixel) );
3563 if ( pHitObj && nMyAction == DND_ACTION_LINK && !rData.pDrawTransfer )
3565 if ( IsDropFormatSupported(SOT_FORMATSTR_ID_SVXB)
3566 || IsDropFormatSupported(SOT_FORMAT_GDIMETAFILE)
3567 || IsDropFormatSupported(SOT_FORMAT_BITMAP) )
3569 // graphic dragged onto drawing object
3570 DrawMarkDropObj( pHitObj );
3571 nRet = nMyAction;
3574 if (!nRet)
3575 DrawMarkDropObj( NULL );
3577 if (!nRet)
3579 switch ( nMyAction )
3581 case DND_ACTION_COPY:
3582 case DND_ACTION_MOVE:
3583 case DND_ACTION_COPYMOVE:
3585 BOOL bMove = ( nMyAction == DND_ACTION_MOVE );
3586 if ( IsDropFormatSupported( SOT_FORMATSTR_ID_EMBED_SOURCE ) ||
3587 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE ) ||
3588 IsDropFormatSupported( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) ||
3589 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ||
3590 IsDropFormatSupported( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) ||
3591 IsDropFormatSupported( SOT_FORMAT_STRING ) ||
3592 IsDropFormatSupported( SOT_FORMATSTR_ID_SYLK ) ||
3593 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK ) ||
3594 IsDropFormatSupported( SOT_FORMATSTR_ID_HTML ) ||
3595 IsDropFormatSupported( SOT_FORMATSTR_ID_HTML_SIMPLE ) ||
3596 IsDropFormatSupported( SOT_FORMATSTR_ID_DIF ) ||
3597 IsDropFormatSupported( SOT_FORMATSTR_ID_DRAWING ) ||
3598 IsDropFormatSupported( SOT_FORMATSTR_ID_SVXB ) ||
3599 IsDropFormatSupported( SOT_FORMAT_RTF ) ||
3600 IsDropFormatSupported( SOT_FORMAT_GDIMETAFILE ) ||
3601 IsDropFormatSupported( SOT_FORMAT_BITMAP ) ||
3602 IsDropFormatSupported( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) ||
3603 IsDropFormatSupported( SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE ) ||
3604 ( !bMove && (
3605 IsDropFormatSupported( SOT_FORMAT_FILE_LIST ) ||
3606 IsDropFormatSupported( SOT_FORMAT_FILE ) ||
3607 IsDropFormatSupported( SOT_FORMATSTR_ID_SOLK ) ||
3608 IsDropFormatSupported( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) ||
3609 IsDropFormatSupported( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) ||
3610 IsDropFormatSupported( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) ) ) )
3612 nRet = nMyAction;
3615 break;
3616 case DND_ACTION_LINK:
3617 if ( IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE ) ||
3618 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ||
3619 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK ) ||
3620 IsDropFormatSupported( SOT_FORMAT_FILE_LIST ) ||
3621 IsDropFormatSupported( SOT_FORMAT_FILE ) ||
3622 IsDropFormatSupported( SOT_FORMATSTR_ID_SOLK ) ||
3623 IsDropFormatSupported( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) ||
3624 IsDropFormatSupported( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) ||
3625 IsDropFormatSupported( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
3627 nRet = nMyAction;
3629 break;
3632 if ( nRet )
3634 // Simple check for protection: It's not known here if the drop will result
3635 // in cells or drawing objects (some formats can be both) and how many cells
3636 // the result will be. But if IsFormatEditable for the drop cell position
3637 // is FALSE (ignores matrix formulas), nothing can be pasted, so the drop
3638 // can already be rejected here.
3640 Point aPos = rEvt.maPosPixel;
3641 SCsCOL nPosX;
3642 SCsROW nPosY;
3643 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
3644 SCTAB nTab = pViewData->GetTabNo();
3645 ScDocument* pDoc = pViewData->GetDocument();
3647 ScEditableTester aTester( pDoc, nTab, nPosX,nPosY, nPosX,nPosY );
3648 if ( !aTester.IsFormatEditable() )
3649 nRet = DND_ACTION_NONE; // forbidden
3654 // scroll only for accepted formats
3655 if (nRet)
3656 DropScroll( rEvt.maPosPixel );
3659 return nRet;
3662 ULONG lcl_GetDropFormatId( const uno::Reference<datatransfer::XTransferable>& xTransfer, bool bPreferText = false )
3664 TransferableDataHelper aDataHelper( xTransfer );
3666 if ( !aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) )
3668 // use bookmark formats if no sba is present
3670 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SOLK ) )
3671 return SOT_FORMATSTR_ID_SOLK;
3672 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) )
3673 return SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR;
3674 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) )
3675 return SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK;
3676 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
3677 return SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR;
3680 ULONG nFormatId = 0;
3681 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING ) )
3682 nFormatId = SOT_FORMATSTR_ID_DRAWING;
3683 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ) )
3684 nFormatId = SOT_FORMATSTR_ID_SVXB;
3685 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ) )
3687 // If it's a Writer object, insert RTF instead of OLE
3689 BOOL bDoRtf = FALSE;
3690 SotStorageStreamRef xStm;
3691 TransferableObjectDescriptor aObjDesc;
3692 if( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) &&
3693 aDataHelper.GetSotStorageStream( SOT_FORMATSTR_ID_EMBED_SOURCE, xStm ) )
3695 SotStorageRef xStore( new SotStorage( *xStm ) );
3696 bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) ||
3697 aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) )
3698 && aDataHelper.HasFormat( SOT_FORMAT_RTF ) );
3700 if ( bDoRtf )
3701 nFormatId = FORMAT_RTF;
3702 else
3703 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE;
3705 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) )
3706 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE;
3707 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) )
3708 nFormatId = SOT_FORMATSTR_ID_SBA_DATAEXCHANGE;
3709 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE ) )
3710 nFormatId = SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE;
3711 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_BIFF_8 ) )
3712 nFormatId = SOT_FORMATSTR_ID_BIFF_8;
3713 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_BIFF_5 ) )
3714 nFormatId = SOT_FORMATSTR_ID_BIFF_5;
3715 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) )
3716 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE_OLE;
3717 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) )
3718 nFormatId = SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE;
3719 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) )
3720 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE;
3721 else if ( aDataHelper.HasFormat( SOT_FORMAT_RTF ) )
3722 nFormatId = SOT_FORMAT_RTF;
3723 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_HTML ) )
3724 nFormatId = SOT_FORMATSTR_ID_HTML;
3725 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_HTML_SIMPLE ) )
3726 nFormatId = SOT_FORMATSTR_ID_HTML_SIMPLE;
3727 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SYLK ) )
3728 nFormatId = SOT_FORMATSTR_ID_SYLK;
3729 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK ) )
3730 nFormatId = SOT_FORMATSTR_ID_LINK;
3731 else if ( bPreferText && aDataHelper.HasFormat( SOT_FORMAT_STRING ) ) // #i86734# the behaviour introduced in #i62773# is wrong when pasting
3732 nFormatId = SOT_FORMAT_STRING;
3733 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) )
3734 nFormatId = SOT_FORMAT_FILE_LIST;
3735 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE ) ) // #i62773# FILE_LIST/FILE before STRING (Unix file managers)
3736 nFormatId = SOT_FORMAT_FILE;
3737 else if ( aDataHelper.HasFormat( SOT_FORMAT_STRING ) )
3738 nFormatId = SOT_FORMAT_STRING;
3739 else if ( aDataHelper.HasFormat( SOT_FORMAT_GDIMETAFILE ) )
3740 nFormatId = SOT_FORMAT_GDIMETAFILE;
3741 else if ( aDataHelper.HasFormat( SOT_FORMAT_BITMAP ) )
3742 nFormatId = SOT_FORMAT_BITMAP;
3744 return nFormatId;
3747 ULONG lcl_GetDropLinkId( const uno::Reference<datatransfer::XTransferable>& xTransfer )
3749 TransferableDataHelper aDataHelper( xTransfer );
3751 ULONG nFormatId = 0;
3752 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) )
3753 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE;
3754 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) )
3755 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE;
3756 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK ) )
3757 nFormatId = SOT_FORMATSTR_ID_LINK;
3758 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) )
3759 nFormatId = SOT_FORMAT_FILE_LIST;
3760 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE ) )
3761 nFormatId = SOT_FORMAT_FILE;
3762 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SOLK ) )
3763 nFormatId = SOT_FORMATSTR_ID_SOLK;
3764 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) )
3765 nFormatId = SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR;
3766 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) )
3767 nFormatId = SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK;
3768 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
3769 nFormatId = SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR;
3771 return nFormatId;
3775 sal_Int8 ScGridWindow::ExecutePrivateDrop( const ExecuteDropEvent& rEvt )
3777 // hide drop marker
3778 // if (bDragRect)
3779 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3780 bDragRect = FALSE;
3781 UpdateDragRectOverlay();
3783 ScModule* pScMod = SC_MOD();
3784 const ScDragData& rData = pScMod->GetDragData();
3786 return DropTransferObj( rData.pCellTransfer, nDragStartX, nDragStartY,
3787 PixelToLogic(rEvt.maPosPixel), rEvt.mnAction );
3790 sal_Int8 ScGridWindow::DropTransferObj( ScTransferObj* pTransObj, SCCOL nDestPosX, SCROW nDestPosY,
3791 const Point& rLogicPos, sal_Int8 nDndAction )
3793 if ( !pTransObj )
3794 return 0;
3796 ScDocument* pSourceDoc = pTransObj->GetSourceDocument();
3797 ScDocShell* pDocSh = pViewData->GetDocShell();
3798 ScDocument* pThisDoc = pViewData->GetDocument();
3799 ScViewFunc* pView = pViewData->GetView();
3800 SCTAB nThisTab = pViewData->GetTabNo();
3801 USHORT nFlags = pTransObj->GetDragSourceFlags();
3803 BOOL bIsNavi = ( nFlags & SC_DROP_NAVIGATOR ) != 0;
3804 BOOL bIsMove = ( nDndAction == DND_ACTION_MOVE && !bIsNavi );
3806 // workaround for wrong nDndAction on Windows when pressing solely
3807 // the Alt key during drag and drop;
3808 // can be removed after #i79215# has been fixed
3809 if ( meDragInsertMode != INS_NONE )
3811 bIsMove = ( nDndAction & DND_ACTION_MOVE && !bIsNavi );
3814 BOOL bIsLink = ( nDndAction == DND_ACTION_LINK );
3816 ScRange aSource = pTransObj->GetRange();
3818 // only use visible tab from source range - when dragging within one table,
3819 // all selected tables at the time of dropping are used (handled in MoveBlockTo)
3820 SCTAB nSourceTab = pTransObj->GetVisibleTab();
3821 aSource.aStart.SetTab( nSourceTab );
3822 aSource.aEnd.SetTab( nSourceTab );
3824 SCCOL nSizeX = aSource.aEnd.Col() - aSource.aStart.Col() + 1;
3825 SCROW nSizeY = (bIsMove ? (aSource.aEnd.Row() - aSource.aStart.Row() + 1) :
3826 pTransObj->GetNonFilteredRows()); // copy/link: no filtered rows
3827 ScRange aDest( nDestPosX, nDestPosY, nThisTab,
3828 nDestPosX + nSizeX - 1, nDestPosY + nSizeY - 1, nThisTab );
3831 /* NOTE: AcceptPrivateDrop() already checked for filtered conditions during
3832 * dragging and adapted drawing of the selection frame. We check here
3833 * (again) because this may actually also be called from PasteSelection(),
3834 * we would have to duplicate determination of flags and destination range
3835 * and would lose the context of the "filtered destination is OK" cases
3836 * below, which is already awkward enough as is. */
3838 // Don't move filtered source.
3839 bool bFiltered = (bIsMove && pTransObj->HasFilteredRows());
3840 if (!bFiltered)
3842 if (pSourceDoc != pThisDoc && ((nFlags & SC_DROP_TABLE) ||
3843 (!bIsLink && meDragInsertMode == INS_NONE)))
3845 // Nothing. Either entire sheet to be dropped, or the one case
3846 // where PasteFromClip() is to be called that handles a filtered
3847 // destination itself. Drag-copy from another document without
3848 // inserting cells.
3850 else
3851 // Don't copy or move to filtered destination.
3852 bFiltered = ScViewUtil::HasFiltered( aDest, pThisDoc);
3855 BOOL bDone = FALSE;
3857 if (!bFiltered && pSourceDoc == pThisDoc)
3859 if ( nFlags & SC_DROP_TABLE ) // whole sheet?
3861 if ( pThisDoc->IsDocEditable() )
3863 SCTAB nSrcTab = aSource.aStart.Tab();
3864 pViewData->GetDocShell()->MoveTable( nSrcTab, nThisTab, !bIsMove, TRUE ); // with Undo
3865 pView->SetTabNo( nThisTab, TRUE );
3866 bDone = TRUE;
3869 else // move/copy block
3871 String aChartName;
3872 if (pThisDoc->HasChartAtPoint( nThisTab, rLogicPos, &aChartName ))
3874 String aRangeName;
3875 aSource.Format( aRangeName, SCR_ABS_3D, pThisDoc );
3876 SfxStringItem aNameItem( SID_CHART_NAME, aChartName );
3877 SfxStringItem aRangeItem( SID_CHART_SOURCE, aRangeName );
3878 USHORT nId = bIsMove ? SID_CHART_SOURCE : SID_CHART_ADDSOURCE;
3879 pViewData->GetDispatcher().Execute( nId, SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD,
3880 &aRangeItem, &aNameItem, (void*) NULL );
3881 bDone = TRUE;
3883 else if ( pThisDoc->GetDPAtCursor( nDestPosX, nDestPosY, nThisTab ) )
3885 // drop on DataPilot table: try to sort, fail if that isn't possible
3887 ScAddress aDestPos( nDestPosX, nDestPosY, nThisTab );
3888 if ( aDestPos != aSource.aStart )
3889 bDone = pViewData->GetView()->DataPilotMove( aSource, aDestPos );
3890 else
3891 bDone = TRUE; // same position: nothing
3893 else if ( nDestPosX != aSource.aStart.Col() || nDestPosY != aSource.aStart.Row() ||
3894 nSourceTab != nThisTab )
3896 String aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY );
3897 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
3899 bDone = TRUE;
3900 if ( meDragInsertMode != INS_NONE )
3902 // call with bApi = TRUE to avoid error messages in drop handler
3903 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, TRUE /*bRecord*/, TRUE /*bApi*/, TRUE /*bPartOfPaste*/ );
3904 if ( bDone )
3906 if ( nThisTab == nSourceTab )
3908 if ( meDragInsertMode == INS_CELLSDOWN &&
3909 nDestPosX == aSource.aStart.Col() && nDestPosY < aSource.aStart.Row() )
3911 bDone = aSource.Move( 0, nSizeY, 0, pSourceDoc );
3913 else if ( meDragInsertMode == INS_CELLSRIGHT &&
3914 nDestPosY == aSource.aStart.Row() && nDestPosX < aSource.aStart.Col() )
3916 bDone = aSource.Move( nSizeX, 0, 0, pSourceDoc );
3919 pDocSh->UpdateOle( pViewData );
3920 pView->CellContentChanged();
3924 if ( bDone )
3926 if ( bIsLink )
3928 // call with bApi = TRUE to avoid error messages in drop handler
3929 bDone = pView->LinkBlock( aSource, aDest.aStart, TRUE /*bApi*/ );
3931 else
3933 // call with bApi = TRUE to avoid error messages in drop handler
3934 bDone = pView->MoveBlockTo( aSource, aDest.aStart, bIsMove, TRUE /*bRecord*/, TRUE /*bPaint*/, TRUE /*bApi*/ );
3938 if ( bDone && meDragInsertMode != INS_NONE && bIsMove && nThisTab == nSourceTab )
3940 DelCellCmd eCmd = DEL_NONE;
3941 if ( meDragInsertMode == INS_CELLSDOWN )
3943 eCmd = DEL_CELLSUP;
3945 else if ( meDragInsertMode == INS_CELLSRIGHT )
3947 eCmd = DEL_CELLSLEFT;
3950 if ( ( eCmd == DEL_CELLSUP && nDestPosX == aSource.aStart.Col() ) ||
3951 ( eCmd == DEL_CELLSLEFT && nDestPosY == aSource.aStart.Row() ) )
3953 // call with bApi = TRUE to avoid error messages in drop handler
3954 bDone = pDocSh->GetDocFunc().DeleteCells( aSource, NULL, eCmd, TRUE /*bRecord*/, TRUE /*bApi*/ );
3955 if ( bDone )
3957 if ( eCmd == DEL_CELLSUP && nDestPosY > aSource.aEnd.Row() )
3959 bDone = aDest.Move( 0, -nSizeY, 0, pThisDoc );
3961 else if ( eCmd == DEL_CELLSLEFT && nDestPosX > aSource.aEnd.Col() )
3963 bDone = aDest.Move( -nSizeX, 0, 0, pThisDoc );
3965 pDocSh->UpdateOle( pViewData );
3966 pView->CellContentChanged();
3971 if ( bDone )
3973 pView->MarkRange( aDest, FALSE, FALSE );
3975 SCCOL nDCol = pViewData->GetCurX() - aSource.aStart.Col();
3976 SCROW nDRow = pViewData->GetCurY() - aSource.aStart.Row();
3977 pView->SetCursor( aDest.aStart.Col() + nDCol, aDest.aStart.Row() + nDRow );
3980 pDocSh->GetUndoManager()->LeaveListAction();
3982 if (!bDone)
3983 Sound::Beep(); // instead of error message in drop handler
3985 else
3986 bDone = TRUE; // nothing to do
3989 if (bDone)
3990 pTransObj->SetDragWasInternal(); // don't delete source in DragFinished
3992 else if ( !bFiltered && pSourceDoc ) // between documents
3994 if ( nFlags & SC_DROP_TABLE ) // copy/link sheets between documents
3996 if ( pThisDoc->IsDocEditable() )
3998 ScDocShell* pSrcShell = pTransObj->GetSourceDocShell();
4000 SCTAB nTabs[MAXTABCOUNT];
4002 ScMarkData aMark = pTransObj->GetSourceMarkData();
4003 SCTAB nTabCount = pSourceDoc->GetTableCount();
4004 SCTAB nTabSelCount = 0;
4006 for(SCTAB i=0; i<nTabCount; i++)
4008 if(aMark.GetTableSelect(i))
4010 nTabs[nTabSelCount++]=i;
4011 for(SCTAB j=i+1;j<nTabCount;j++)
4013 if((!pSourceDoc->IsVisible(j))&&(pSourceDoc->IsScenario(j)))
4015 nTabs[nTabSelCount++]=j;
4016 i=j;
4018 else break;
4023 pView->ImportTables( pSrcShell,nTabSelCount, nTabs, bIsLink, nThisTab );
4024 bDone = TRUE;
4027 else if ( bIsLink )
4029 // as in PasteDDE
4030 // (external references might be used instead?)
4032 SfxObjectShell* pSourceSh = pSourceDoc->GetDocumentShell();
4033 DBG_ASSERT(pSourceSh, "drag document has no shell");
4034 if (pSourceSh)
4036 String aUndo = ScGlobal::GetRscString( STR_UNDO_COPY );
4037 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
4039 bDone = TRUE;
4040 if ( meDragInsertMode != INS_NONE )
4042 // call with bApi = TRUE to avoid error messages in drop handler
4043 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, TRUE /*bRecord*/, TRUE /*bApi*/, TRUE /*bPartOfPaste*/ );
4044 if ( bDone )
4046 pDocSh->UpdateOle( pViewData );
4047 pView->CellContentChanged();
4051 if ( bDone )
4053 String aApp = Application::GetAppName();
4054 String aTopic = pSourceSh->GetTitle( SFX_TITLE_FULLNAME );
4055 String aItem;
4056 aSource.Format( aItem, SCA_VALID | SCA_TAB_3D, pSourceDoc );
4058 // TODO: we could define ocQuote for "
4059 const String aQuote( '"' );
4060 const String& sSep = ScCompiler::GetNativeSymbol( ocSep);
4061 String aFormula( '=' );
4062 aFormula += ScCompiler::GetNativeSymbol( ocDde);
4063 aFormula += ScCompiler::GetNativeSymbol( ocOpen);
4064 aFormula += aQuote;
4065 aFormula += aApp;
4066 aFormula += aQuote;
4067 aFormula += sSep;
4068 aFormula += aQuote;
4069 aFormula += aTopic;
4070 aFormula += aQuote;
4071 aFormula += sSep;
4072 aFormula += aQuote;
4073 aFormula += aItem;
4074 aFormula += aQuote;
4075 aFormula += ScCompiler::GetNativeSymbol( ocClose);
4077 pView->DoneBlockMode();
4078 pView->InitBlockMode( nDestPosX, nDestPosY, nThisTab );
4079 pView->MarkCursor( nDestPosX + nSizeX - 1,
4080 nDestPosY + nSizeY - 1, nThisTab );
4082 pView->EnterMatrix( aFormula );
4084 pView->MarkRange( aDest, FALSE, FALSE );
4085 pView->SetCursor( aDest.aStart.Col(), aDest.aStart.Row() );
4088 pDocSh->GetUndoManager()->LeaveListAction();
4091 else
4093 //! HasSelectedBlockMatrixFragment without selected sheet?
4094 //! or don't start dragging on a part of a matrix
4096 String aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY );
4097 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
4099 bDone = TRUE;
4100 if ( meDragInsertMode != INS_NONE )
4102 // call with bApi = TRUE to avoid error messages in drop handler
4103 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, TRUE /*bRecord*/, TRUE /*bApi*/, TRUE /*bPartOfPaste*/ );
4104 if ( bDone )
4106 pDocSh->UpdateOle( pViewData );
4107 pView->CellContentChanged();
4111 if ( bDone )
4113 pView->Unmark(); // before SetCursor, so CheckSelectionTransfer isn't called with a selection
4114 pView->SetCursor( nDestPosX, nDestPosY );
4115 bDone = pView->PasteFromClip( IDF_ALL, pTransObj->GetDocument() ); // clip-doc
4116 if ( bDone )
4118 pView->MarkRange( aDest, FALSE, FALSE );
4119 pView->SetCursor( aDest.aStart.Col(), aDest.aStart.Row() );
4123 pDocSh->GetUndoManager()->LeaveListAction();
4125 // no longer call ResetMark here - the inserted block has been selected
4126 // and may have been copied to primary selection
4130 sal_Int8 nRet = bDone ? nDndAction : DND_ACTION_NONE;
4131 return nRet;
4134 sal_Int8 ScGridWindow::ExecuteDrop( const ExecuteDropEvent& rEvt )
4136 DrawMarkDropObj( NULL ); // drawing layer
4138 ScModule* pScMod = SC_MOD();
4139 const ScDragData& rData = pScMod->GetDragData();
4140 if (rData.pCellTransfer)
4141 return ExecutePrivateDrop( rEvt );
4143 Point aPos = rEvt.maPosPixel;
4145 if ( rData.aLinkDoc.Len() )
4147 // try to insert a link
4149 BOOL bOk = TRUE;
4150 String aThisName;
4151 ScDocShell* pDocSh = pViewData->GetDocShell();
4152 if (pDocSh && pDocSh->HasName())
4153 aThisName = pDocSh->GetMedium()->GetName();
4155 if ( rData.aLinkDoc == aThisName ) // error - no link within a document
4156 bOk = FALSE;
4157 else
4159 ScViewFunc* pView = pViewData->GetView();
4160 if ( rData.aLinkTable.Len() )
4161 pView->InsertTableLink( rData.aLinkDoc, EMPTY_STRING, EMPTY_STRING,
4162 rData.aLinkTable );
4163 else if ( rData.aLinkArea.Len() )
4165 SCsCOL nPosX;
4166 SCsROW nPosY;
4167 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
4168 pView->MoveCursorAbs( nPosX, nPosY, SC_FOLLOW_NONE, FALSE, FALSE );
4170 pView->InsertAreaLink( rData.aLinkDoc, EMPTY_STRING, EMPTY_STRING,
4171 rData.aLinkArea, 0 );
4173 else
4175 DBG_ERROR("drop with link: no sheet nor area");
4176 bOk = FALSE;
4180 return bOk ? rEvt.mnAction : DND_ACTION_NONE; // don't try anything else
4183 Point aLogicPos = PixelToLogic(aPos);
4185 if (rData.pDrawTransfer)
4187 USHORT nFlags = rData.pDrawTransfer->GetDragSourceFlags();
4189 BOOL bIsNavi = ( nFlags & SC_DROP_NAVIGATOR ) != 0;
4190 BOOL bIsMove = ( rEvt.mnAction == DND_ACTION_MOVE && !bIsNavi );
4192 bPasteIsMove = bIsMove;
4194 pViewData->GetView()->PasteDraw( aLogicPos, rData.pDrawTransfer->GetModel() );
4196 if (bPasteIsMove)
4197 rData.pDrawTransfer->SetDragWasInternal();
4198 bPasteIsMove = FALSE;
4200 return rEvt.mnAction;
4204 SCsCOL nPosX;
4205 SCsROW nPosY;
4206 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
4208 if (rData.aJumpTarget.Len())
4210 // internal bookmark (from Navigator)
4211 // bookmark clipboard formats are in PasteScDataObject
4213 if ( !rData.pJumpLocalDoc || rData.pJumpLocalDoc == pViewData->GetDocument() )
4215 pViewData->GetViewShell()->InsertBookmark( rData.aJumpText, rData.aJumpTarget,
4216 nPosX, nPosY );
4217 return rEvt.mnAction;
4221 BOOL bIsLink = ( rEvt.mnAction == DND_ACTION_LINK );
4223 ScDocument* pThisDoc = pViewData->GetDocument();
4224 SdrObject* pHitObj = pThisDoc->GetObjectAtPoint( pViewData->GetTabNo(), PixelToLogic(aPos) );
4225 if ( pHitObj && bIsLink )
4227 // dropped on drawing object
4228 // PasteOnDrawObject checks for valid formats
4229 if ( pViewData->GetView()->PasteOnDrawObject( rEvt.maDropEvent.Transferable, pHitObj, TRUE ) )
4230 return rEvt.mnAction;
4233 BOOL bDone = FALSE;
4235 ULONG nFormatId = bIsLink ?
4236 lcl_GetDropLinkId( rEvt.maDropEvent.Transferable ) :
4237 lcl_GetDropFormatId( rEvt.maDropEvent.Transferable );
4238 if ( nFormatId )
4240 pScMod->SetInExecuteDrop( TRUE ); // #i28468# prevent error messages from PasteDataFormat
4241 bPasteIsDrop = TRUE;
4242 bDone = pViewData->GetView()->PasteDataFormat(
4243 nFormatId, rEvt.maDropEvent.Transferable, nPosX, nPosY, &aLogicPos, bIsLink );
4244 bPasteIsDrop = FALSE;
4245 pScMod->SetInExecuteDrop( FALSE );
4248 sal_Int8 nRet = bDone ? rEvt.mnAction : DND_ACTION_NONE;
4249 return nRet;
4252 //--------------------------------------------------------
4254 void ScGridWindow::PasteSelection( const Point& rPosPixel )
4256 Point aLogicPos = PixelToLogic( rPosPixel );
4258 SCsCOL nPosX;
4259 SCsROW nPosY;
4260 pViewData->GetPosFromPixel( rPosPixel.X(), rPosPixel.Y(), eWhich, nPosX, nPosY );
4262 ScSelectionTransferObj* pOwnSelection = SC_MOD()->GetSelectionTransfer();
4263 if ( pOwnSelection )
4265 // within Calc
4267 ScTransferObj* pCellTransfer = pOwnSelection->GetCellData();
4268 if ( pCellTransfer )
4270 // keep a reference to the data in case the selection is changed during paste
4271 uno::Reference<datatransfer::XTransferable> xRef( pCellTransfer );
4272 DropTransferObj( pCellTransfer, nPosX, nPosY, aLogicPos, DND_ACTION_COPY );
4274 else
4276 ScDrawTransferObj* pDrawTransfer = pOwnSelection->GetDrawData();
4277 if ( pDrawTransfer )
4279 // keep a reference to the data in case the selection is changed during paste
4280 uno::Reference<datatransfer::XTransferable> xRef( pDrawTransfer );
4282 // #96821# bSameDocClipboard argument for PasteDraw is needed
4283 // because only DragData is checked directly inside PasteDraw
4284 pViewData->GetView()->PasteDraw( aLogicPos, pDrawTransfer->GetModel(), FALSE,
4285 pDrawTransfer->GetSourceDocID() == pViewData->GetDocument()->GetDocumentID() );
4289 else
4291 // get selection from system
4293 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSelection( this ) );
4294 uno::Reference<datatransfer::XTransferable> xTransferable = aDataHelper.GetTransferable();
4295 if ( xTransferable.is() )
4297 ULONG nFormatId = lcl_GetDropFormatId( xTransferable, true );
4298 if ( nFormatId )
4300 bPasteIsDrop = TRUE;
4301 pViewData->GetView()->PasteDataFormat( nFormatId, xTransferable, nPosX, nPosY, &aLogicPos );
4302 bPasteIsDrop = FALSE;
4308 //--------------------------------------------------------
4310 void ScGridWindow::UpdateEditViewPos()
4312 if (pViewData->HasEditView(eWhich))
4314 EditView* pView;
4315 SCCOL nCol;
4316 SCROW nRow;
4317 pViewData->GetEditView( eWhich, pView, nCol, nRow );
4318 SCCOL nEndCol = pViewData->GetEditEndCol();
4319 SCROW nEndRow = pViewData->GetEditEndRow();
4321 // hide EditView?
4323 BOOL bHide = ( nEndCol<pViewData->GetPosX(eHWhich) || nEndRow<pViewData->GetPosY(eVWhich) );
4324 if ( SC_MOD()->IsFormulaMode() )
4325 if ( pViewData->GetTabNo() != pViewData->GetRefTabNo() )
4326 bHide = TRUE;
4328 if (bHide)
4330 Rectangle aRect = pView->GetOutputArea();
4331 long nHeight = aRect.Bottom() - aRect.Top();
4332 aRect.Top() = PixelToLogic(GetOutputSizePixel(), pViewData->GetLogicMode()).
4333 Height() * 2;
4334 aRect.Bottom() = aRect.Top() + nHeight;
4335 pView->SetOutputArea( aRect );
4336 pView->HideCursor();
4338 else
4340 // bForceToTop = TRUE for editing
4341 Rectangle aPixRect = pViewData->GetEditArea( eWhich, nCol, nRow, this, NULL, TRUE );
4342 Point aScrPos = PixelToLogic( aPixRect.TopLeft(), pViewData->GetLogicMode() );
4344 Rectangle aRect = pView->GetOutputArea();
4345 aRect.SetPos( aScrPos );
4346 pView->SetOutputArea( aRect );
4347 pView->ShowCursor();
4352 void ScGridWindow::ScrollPixel( long nDifX, long nDifY )
4354 ClickExtern();
4355 HideNoteMarker();
4357 bIsInScroll = TRUE;
4358 //BOOL bXor=DrawBeforeScroll();
4360 SetMapMode(MAP_PIXEL);
4361 Scroll( nDifX, nDifY, SCROLL_CHILDREN );
4362 SetMapMode( GetDrawMapMode() ); // verschobenen MapMode erzeugen
4364 UpdateEditViewPos();
4366 DrawAfterScroll(); //bXor);
4367 bIsInScroll = FALSE;
4370 // Formeln neu zeichnen -------------------------------------------------
4372 void ScGridWindow::UpdateFormulas()
4374 if (pViewData->GetView()->IsMinimized())
4375 return;
4377 if ( nPaintCount )
4379 // nicht anfangen, verschachtelt zu painten
4380 // (dann wuerde zumindest der MapMode nicht mehr stimmen)
4382 bNeedsRepaint = TRUE; // -> am Ende vom Paint nochmal Invalidate auf alles
4383 aRepaintPixel = Rectangle(); // alles
4384 return;
4387 SCCOL nX1 = pViewData->GetPosX( eHWhich );
4388 SCROW nY1 = pViewData->GetPosY( eVWhich );
4389 SCCOL nX2 = nX1 + pViewData->VisibleCellsX( eHWhich );
4390 SCROW nY2 = nY1 + pViewData->VisibleCellsY( eVWhich );
4392 if (nX2 > MAXCOL) nX2 = MAXCOL;
4393 if (nY2 > MAXROW) nY2 = MAXROW;
4395 // Draw( nX1, nY1, nX2, nY2, SC_UPDATE_CHANGED );
4397 // don't draw directly - instead use OutputData to find changed area and invalidate
4399 SCROW nPosY = nY1;
4401 ScDocShell* pDocSh = pViewData->GetDocShell();
4402 ScDocument* pDoc = pDocSh->GetDocument();
4403 SCTAB nTab = pViewData->GetTabNo();
4405 pDoc->ExtendHidden( nX1, nY1, nX2, nY2, nTab );
4407 Point aScrPos = pViewData->GetScrPos( nX1, nY1, eWhich );
4408 long nMirrorWidth = GetSizePixel().Width();
4409 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
4410 // unused variable long nLayoutSign = bLayoutRTL ? -1 : 1;
4411 if ( bLayoutRTL )
4413 long nEndPixel = pViewData->GetScrPos( nX2+1, nPosY, eWhich ).X();
4414 nMirrorWidth = aScrPos.X() - nEndPixel;
4415 aScrPos.X() = nEndPixel + 1;
4418 long nScrX = aScrPos.X();
4419 long nScrY = aScrPos.Y();
4421 double nPPTX = pViewData->GetPPTX();
4422 double nPPTY = pViewData->GetPPTY();
4424 ScTableInfo aTabInfo;
4425 pDoc->FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nTab, nPPTX, nPPTY, FALSE, FALSE );
4427 Fraction aZoomX = pViewData->GetZoomX();
4428 Fraction aZoomY = pViewData->GetZoomY();
4429 ScOutputData aOutputData( this, OUTTYPE_WINDOW, aTabInfo, pDoc, nTab,
4430 nScrX, nScrY, nX1, nY1, nX2, nY2, nPPTX, nPPTY,
4431 &aZoomX, &aZoomY );
4432 aOutputData.SetMirrorWidth( nMirrorWidth );
4434 aOutputData.FindChanged();
4436 PolyPolygon aChangedPoly( aOutputData.GetChangedArea() ); // logic (PixelToLogic)
4437 if ( aChangedPoly.Count() )
4439 Invalidate( aChangedPoly );
4442 CheckNeedsRepaint(); // #i90362# used to be called via Draw() - still needed here
4445 void ScGridWindow::UpdateAutoFillMark(BOOL bMarked, const ScRange& rMarkRange)
4447 if ( bMarked != bAutoMarkVisible || ( bMarked && rMarkRange.aEnd != aAutoMarkPos ) )
4449 HideCursor();
4450 bAutoMarkVisible = bMarked;
4451 if ( bMarked )
4452 aAutoMarkPos = rMarkRange.aEnd;
4453 ShowCursor();
4455 UpdateAutoFillOverlay();
4459 void ScGridWindow::UpdateListValPos( BOOL bVisible, const ScAddress& rPos )
4461 BOOL bOldButton = bListValButton;
4462 ScAddress aOldPos = aListValPos;
4464 bListValButton = bVisible;
4465 aListValPos = rPos;
4467 if ( bListValButton )
4469 if ( !bOldButton || aListValPos != aOldPos )
4471 // paint area of new button
4472 Invalidate( PixelToLogic( GetListValButtonRect( aListValPos ) ) );
4475 if ( bOldButton )
4477 if ( !bListValButton || aListValPos != aOldPos )
4479 // paint area of old button
4480 Invalidate( PixelToLogic( GetListValButtonRect( aOldPos ) ) );
4485 void ScGridWindow::HideCursor()
4487 ++nCursorHideCount;
4488 if (nCursorHideCount==1)
4490 DrawCursor();
4491 DrawAutoFillMark();
4495 void ScGridWindow::ShowCursor()
4497 if (nCursorHideCount==0)
4499 DBG_ERROR("zuviel ShowCursor");
4500 return;
4503 if (nCursorHideCount==1)
4505 // #i57745# Draw the cursor before setting the variable, in case the
4506 // GetSizePixel call from drawing causes a repaint (resize handler is called)
4507 DrawAutoFillMark();
4508 DrawCursor();
4511 --nCursorHideCount;
4514 void __EXPORT ScGridWindow::GetFocus()
4516 ScTabViewShell* pViewShell = pViewData->GetViewShell();
4517 pViewShell->GotFocus();
4518 pViewShell->SetFormShellAtTop( FALSE ); // focus in GridWindow -> FormShell no longer on top
4520 if (pViewShell->HasAccessibilityObjects())
4521 pViewShell->BroadcastAccessibility(ScAccGridWinFocusGotHint(eWhich, GetAccessible()));
4524 if ( !SC_MOD()->IsFormulaMode() )
4526 pViewShell->UpdateInputHandler();
4527 // StopMarking(); // falls Dialog (Fehler), weil dann kein ButtonUp
4528 // MO: nur wenn nicht im RefInput-Modus
4529 // -> GetFocus/MouseButtonDown-Reihenfolge
4530 // auf dem Mac
4533 Window::GetFocus();
4536 void __EXPORT ScGridWindow::LoseFocus()
4538 ScTabViewShell* pViewShell = pViewData->GetViewShell();
4539 pViewShell->LostFocus();
4541 if (pViewShell->HasAccessibilityObjects())
4542 pViewShell->BroadcastAccessibility(ScAccGridWinFocusLostHint(eWhich, GetAccessible()));
4544 Window::LoseFocus();
4547 Point ScGridWindow::GetMousePosPixel() const { return aCurMousePos; }
4549 //------------------------------------------------------------------------
4551 BOOL ScGridWindow::HitRangeFinder( const Point& rMouse, BOOL& rCorner,
4552 USHORT* pIndex, SCsCOL* pAddX, SCsROW* pAddY )
4554 BOOL bFound = FALSE;
4555 ScInputHandler* pHdl = SC_MOD()->GetInputHdl( pViewData->GetViewShell() );
4556 if (pHdl)
4558 ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList();
4559 if ( pRangeFinder && !pRangeFinder->IsHidden() &&
4560 pRangeFinder->GetDocName() == pViewData->GetDocShell()->GetTitle() )
4562 ScDocument* pDoc = pViewData->GetDocument();
4563 SCTAB nTab = pViewData->GetTabNo();
4564 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
4565 long nLayoutSign = bLayoutRTL ? -1 : 1;
4567 SCsCOL nPosX;
4568 SCsROW nPosY;
4569 pViewData->GetPosFromPixel( rMouse.X(), rMouse.Y(), eWhich, nPosX, nPosY );
4570 // zusammengefasste (einzeln/Bereich) ???
4571 ScAddress aAddr( nPosX, nPosY, nTab );
4573 // Point aNext = pViewData->GetScrPos( nPosX+1, nPosY+1, eWhich );
4575 Point aNext = pViewData->GetScrPos( nPosX, nPosY, eWhich, TRUE );
4576 long nSizeXPix;
4577 long nSizeYPix;
4578 pViewData->GetMergeSizePixel( nPosX, nPosY, nSizeXPix, nSizeYPix );
4579 aNext.X() += nSizeXPix * nLayoutSign;
4580 aNext.Y() += nSizeYPix;
4582 BOOL bCornerHor;
4583 if ( bLayoutRTL )
4584 bCornerHor = ( rMouse.X() >= aNext.X() && rMouse.X() <= aNext.X() + 8 );
4585 else
4586 bCornerHor = ( rMouse.X() >= aNext.X() - 8 && rMouse.X() <= aNext.X() );
4588 BOOL bCellCorner = ( bCornerHor &&
4589 rMouse.Y() >= aNext.Y() - 8 && rMouse.Y() <= aNext.Y() );
4590 // corner is hit only if the mouse is within the cell
4592 USHORT nCount = (USHORT)pRangeFinder->Count();
4593 for (USHORT i=nCount; i;)
4595 // rueckwaerts suchen, damit der zuletzt gepaintete Rahmen gefunden wird
4596 --i;
4597 ScRangeFindData* pData = pRangeFinder->GetObject(i);
4598 if ( pData && pData->aRef.In(aAddr) )
4600 if (pIndex) *pIndex = i;
4601 if (pAddX) *pAddX = nPosX - pData->aRef.aStart.Col();
4602 if (pAddY) *pAddY = nPosY - pData->aRef.aStart.Row();
4603 bFound = TRUE;
4604 rCorner = ( bCellCorner && aAddr == pData->aRef.aEnd );
4605 break;
4610 return bFound;
4613 #define SCE_TOP 1
4614 #define SCE_BOTTOM 2
4615 #define SCE_LEFT 4
4616 #define SCE_RIGHT 8
4617 #define SCE_ALL 15
4619 void lcl_PaintOneRange( ScDocShell* pDocSh, const ScRange& rRange, USHORT nEdges )
4621 // der Range ist immer richtigherum
4623 SCCOL nCol1 = rRange.aStart.Col();
4624 SCROW nRow1 = rRange.aStart.Row();
4625 SCTAB nTab1 = rRange.aStart.Tab();
4626 SCCOL nCol2 = rRange.aEnd.Col();
4627 SCROW nRow2 = rRange.aEnd.Row();
4628 SCTAB nTab2 = rRange.aEnd.Tab();
4629 BOOL bHiddenEdge = FALSE;
4630 SCROW nTmp;
4632 ScDocument* pDoc = pDocSh->GetDocument();
4633 while ( nCol1 > 0 && pDoc->ColHidden(nCol1, nTab1) )
4635 --nCol1;
4636 bHiddenEdge = TRUE;
4638 while ( nCol2 < MAXCOL && pDoc->ColHidden(nCol2, nTab1) )
4640 ++nCol2;
4641 bHiddenEdge = TRUE;
4643 nTmp = pDoc->FirstVisibleRow(0, nRow1, nTab1);
4644 if (!ValidRow(nTmp))
4645 nTmp = 0;
4646 if (nTmp < nRow1)
4648 nRow1 = nTmp;
4649 bHiddenEdge = TRUE;
4651 nTmp = pDoc->FirstVisibleRow(nRow2, MAXROW, nTab1);
4652 if (!ValidRow(nTmp))
4653 nTmp = MAXROW;
4654 if (nTmp > nRow2)
4656 nRow2 = nTmp;
4657 bHiddenEdge = TRUE;
4660 if ( nCol2 > nCol1 + 1 && nRow2 > nRow1 + 1 && !bHiddenEdge )
4662 // nur an den Raendern entlang
4663 // (die Ecken werden evtl. zweimal getroffen)
4665 if ( nEdges & SCE_TOP )
4666 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol2, nRow1, nTab2, PAINT_MARKS );
4667 if ( nEdges & SCE_LEFT )
4668 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol1, nRow2, nTab2, PAINT_MARKS );
4669 if ( nEdges & SCE_RIGHT )
4670 pDocSh->PostPaint( nCol2, nRow1, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
4671 if ( nEdges & SCE_BOTTOM )
4672 pDocSh->PostPaint( nCol1, nRow2, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
4674 else // everything in one call
4675 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
4678 void lcl_PaintRefChanged( ScDocShell* pDocSh, const ScRange& rOldUn, const ScRange& rNewUn )
4680 // Repaint fuer die Teile des Rahmens in Old, die bei New nicht mehr da sind
4682 ScRange aOld = rOldUn;
4683 ScRange aNew = rNewUn;
4684 aOld.Justify();
4685 aNew.Justify();
4687 if ( aOld.aStart == aOld.aEnd ) //! Tab ignorieren?
4688 pDocSh->GetDocument()->ExtendMerge(aOld);
4689 if ( aNew.aStart == aNew.aEnd ) //! Tab ignorieren?
4690 pDocSh->GetDocument()->ExtendMerge(aNew);
4692 SCCOL nOldCol1 = aOld.aStart.Col();
4693 SCROW nOldRow1 = aOld.aStart.Row();
4694 SCCOL nOldCol2 = aOld.aEnd.Col();
4695 SCROW nOldRow2 = aOld.aEnd.Row();
4696 SCCOL nNewCol1 = aNew.aStart.Col();
4697 SCROW nNewRow1 = aNew.aStart.Row();
4698 SCCOL nNewCol2 = aNew.aEnd.Col();
4699 SCROW nNewRow2 = aNew.aEnd.Row();
4700 SCTAB nTab1 = aOld.aStart.Tab(); // Tab aendert sich nicht
4701 SCTAB nTab2 = aOld.aEnd.Tab();
4703 if ( nNewRow2 < nOldRow1 || nNewRow1 > nOldRow2 ||
4704 nNewCol2 < nOldCol1 || nNewCol1 > nOldCol2 ||
4705 ( nNewCol1 != nOldCol1 && nNewRow1 != nOldRow1 &&
4706 nNewCol2 != nOldCol2 && nNewRow2 != nOldRow2 ) )
4708 // komplett weggeschoben oder alle Seiten veraendert
4709 // (Abfrage <= statt < geht schief bei einzelnen Zeilen/Spalten)
4711 lcl_PaintOneRange( pDocSh, aOld, SCE_ALL );
4713 else // alle vier Kanten einzeln testen
4715 // oberer Teil
4716 if ( nNewRow1 < nOldRow1 ) // nur obere Linie loeschen
4717 lcl_PaintOneRange( pDocSh, ScRange(
4718 nOldCol1, nOldRow1, nTab1, nOldCol2, nOldRow1, nTab2 ), SCE_ALL );
4719 else if ( nNewRow1 > nOldRow1 ) // den Teil, der oben wegkommt
4720 lcl_PaintOneRange( pDocSh, ScRange(
4721 nOldCol1, nOldRow1, nTab1, nOldCol2, nNewRow1-1, nTab2 ),
4722 SCE_ALL &~ SCE_BOTTOM );
4724 // unterer Teil
4725 if ( nNewRow2 > nOldRow2 ) // nur untere Linie loeschen
4726 lcl_PaintOneRange( pDocSh, ScRange(
4727 nOldCol1, nOldRow2, nTab1, nOldCol2, nOldRow2, nTab2 ), SCE_ALL );
4728 else if ( nNewRow2 < nOldRow2 ) // den Teil, der unten wegkommt
4729 lcl_PaintOneRange( pDocSh, ScRange(
4730 nOldCol1, nNewRow2+1, nTab1, nOldCol2, nOldRow2, nTab2 ),
4731 SCE_ALL &~ SCE_TOP );
4733 // linker Teil
4734 if ( nNewCol1 < nOldCol1 ) // nur linke Linie loeschen
4735 lcl_PaintOneRange( pDocSh, ScRange(
4736 nOldCol1, nOldRow1, nTab1, nOldCol1, nOldRow2, nTab2 ), SCE_ALL );
4737 else if ( nNewCol1 > nOldCol1 ) // den Teil, der links wegkommt
4738 lcl_PaintOneRange( pDocSh, ScRange(
4739 nOldCol1, nOldRow1, nTab1, nNewCol1-1, nOldRow2, nTab2 ),
4740 SCE_ALL &~ SCE_RIGHT );
4742 // rechter Teil
4743 if ( nNewCol2 > nOldCol2 ) // nur rechte Linie loeschen
4744 lcl_PaintOneRange( pDocSh, ScRange(
4745 nOldCol2, nOldRow1, nTab1, nOldCol2, nOldRow2, nTab2 ), SCE_ALL );
4746 else if ( nNewCol2 < nOldCol2 ) // den Teil, der rechts wegkommt
4747 lcl_PaintOneRange( pDocSh, ScRange(
4748 nNewCol2+1, nOldRow1, nTab1, nOldCol2, nOldRow2, nTab2 ),
4749 SCE_ALL &~ SCE_LEFT );
4753 void ScGridWindow::RFMouseMove( const MouseEvent& rMEvt, BOOL bUp )
4755 ScInputHandler* pHdl = SC_MOD()->GetInputHdl( pViewData->GetViewShell() );
4756 if (!pHdl)
4757 return;
4758 ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList();
4759 if (!pRangeFinder || nRFIndex >= pRangeFinder->Count())
4760 return;
4761 ScRangeFindData* pData = pRangeFinder->GetObject( nRFIndex );
4762 if (!pData)
4763 return;
4765 // Mauszeiger
4767 if (bRFSize)
4768 SetPointer( Pointer( POINTER_CROSS ) );
4769 else
4770 SetPointer( Pointer( POINTER_HAND ) );
4772 // Scrolling
4774 BOOL bTimer = FALSE;
4775 Point aPos = rMEvt.GetPosPixel();
4776 SCsCOL nDx = 0;
4777 SCsROW nDy = 0;
4778 if ( aPos.X() < 0 ) nDx = -1;
4779 if ( aPos.Y() < 0 ) nDy = -1;
4780 Size aSize = GetOutputSizePixel();
4781 if ( aPos.X() >= aSize.Width() )
4782 nDx = 1;
4783 if ( aPos.Y() >= aSize.Height() )
4784 nDy = 1;
4785 if ( nDx != 0 || nDy != 0 )
4787 if ( nDx != 0) pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) );
4788 if ( nDy != 0 ) pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) );
4789 bTimer = TRUE;
4792 // Umschalten bei Fixierung (damit Scrolling funktioniert)
4794 if ( eWhich == pViewData->GetActivePart() ) //??
4796 if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX )
4797 if ( nDx > 0 )
4799 if ( eWhich == SC_SPLIT_TOPLEFT )
4800 pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT );
4801 else if ( eWhich == SC_SPLIT_BOTTOMLEFT )
4802 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT );
4805 if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX )
4806 if ( nDy > 0 )
4808 if ( eWhich == SC_SPLIT_TOPLEFT )
4809 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT );
4810 else if ( eWhich == SC_SPLIT_TOPRIGHT )
4811 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT );
4815 // Verschieben
4817 SCsCOL nPosX;
4818 SCsROW nPosY;
4819 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
4821 ScRange aOld = pData->aRef;
4822 ScRange aNew = aOld;
4823 if ( bRFSize )
4825 aNew.aEnd.SetCol((SCCOL)nPosX);
4826 aNew.aEnd.SetRow((SCROW)nPosY);
4828 else
4830 long nStartX = nPosX - nRFAddX;
4831 if ( nStartX < 0 ) nStartX = 0;
4832 long nStartY = nPosY - nRFAddY;
4833 if ( nStartY < 0 ) nStartY = 0;
4834 long nEndX = nStartX + aOld.aEnd.Col() - aOld.aStart.Col();
4835 if ( nEndX > MAXCOL )
4837 nStartX -= ( nEndX - MAXROW );
4838 nEndX = MAXCOL;
4840 long nEndY = nStartY + aOld.aEnd.Row() - aOld.aStart.Row();
4841 if ( nEndY > MAXROW )
4843 nStartY -= ( nEndY - MAXROW );
4844 nEndY = MAXROW;
4847 aNew.aStart.SetCol((SCCOL)nStartX);
4848 aNew.aStart.SetRow((SCROW)nStartY);
4849 aNew.aEnd.SetCol((SCCOL)nEndX);
4850 aNew.aEnd.SetRow((SCROW)nEndY);
4853 if ( bUp )
4854 aNew.Justify(); // beim ButtonUp wieder richtigherum
4856 if ( aNew != aOld )
4858 pHdl->UpdateRange( nRFIndex, aNew );
4860 ScDocShell* pDocSh = pViewData->GetDocShell();
4862 // nur das neuzeichnen, was sich veraendert hat...
4863 lcl_PaintRefChanged( pDocSh, aOld, aNew );
4865 // neuen Rahmen nur drueberzeichnen (synchron)
4866 pDocSh->Broadcast( ScIndexHint( SC_HINT_SHOWRANGEFINDER, nRFIndex ) );
4868 Update(); // was man bewegt, will man auch sofort sehen
4871 // Timer fuer Scrolling
4873 if (bTimer)
4874 pViewData->GetView()->SetTimer( this, rMEvt ); // Event wiederholen
4875 else
4876 pViewData->GetView()->ResetTimer();
4879 //------------------------------------------------------------------------
4881 BOOL ScGridWindow::GetEditUrl( const Point& rPos,
4882 String* pName, String* pUrl, String* pTarget )
4884 return GetEditUrlOrError( FALSE, rPos, pName, pUrl, pTarget );
4887 BOOL ScGridWindow::GetEditUrlOrError( BOOL bSpellErr, const Point& rPos,
4888 String* pName, String* pUrl, String* pTarget )
4890 //! nPosX/Y mit uebergeben?
4891 SCsCOL nPosX;
4892 SCsROW nPosY;
4893 pViewData->GetPosFromPixel( rPos.X(), rPos.Y(), eWhich, nPosX, nPosY );
4895 SCTAB nTab = pViewData->GetTabNo();
4896 ScDocShell* pDocSh = pViewData->GetDocShell();
4897 ScDocument* pDoc = pDocSh->GetDocument();
4898 ScBaseCell* pCell = NULL;
4900 BOOL bFound = lcl_GetHyperlinkCell( pDoc, nPosX, nPosY, nTab, pCell );
4901 if( !bFound )
4902 return FALSE;
4904 ScHideTextCursor aHideCursor( pViewData, eWhich ); // before GetEditArea (MapMode is changed)
4906 const ScPatternAttr* pPattern = pDoc->GetPattern( nPosX, nPosY, nTab );
4907 // bForceToTop = FALSE, use the cell's real position
4908 Rectangle aEditRect = pViewData->GetEditArea( eWhich, nPosX, nPosY, this, pPattern, FALSE );
4909 if (rPos.Y() < aEditRect.Top())
4910 return FALSE;
4912 // vertikal kann (noch) nicht angeklickt werden:
4914 if (pPattern->GetCellOrientation() != SVX_ORIENTATION_STANDARD)
4915 return FALSE;
4917 BOOL bBreak = ((SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK)).GetValue() ||
4918 ((SvxCellHorJustify)((const SvxHorJustifyItem&)pPattern->
4919 GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_BLOCK);
4920 SvxCellHorJustify eHorJust = (SvxCellHorJustify)((SvxHorJustifyItem&)pPattern->
4921 GetItem(ATTR_HOR_JUSTIFY)).GetValue();
4923 // EditEngine
4925 ScFieldEditEngine aEngine( pDoc->GetEditPool() );
4926 ScSizeDeviceProvider aProv(pDocSh);
4927 aEngine.SetRefDevice( aProv.GetDevice() );
4928 aEngine.SetRefMapMode( MAP_100TH_MM );
4929 SfxItemSet aDefault( aEngine.GetEmptyItemSet() );
4930 pPattern->FillEditItemSet( &aDefault );
4931 SvxAdjust eSvxAdjust = SVX_ADJUST_LEFT;
4932 switch (eHorJust)
4934 case SVX_HOR_JUSTIFY_LEFT:
4935 case SVX_HOR_JUSTIFY_REPEAT: // nicht implementiert
4936 case SVX_HOR_JUSTIFY_STANDARD: // always Text if an EditCell type
4937 eSvxAdjust = SVX_ADJUST_LEFT;
4938 break;
4939 case SVX_HOR_JUSTIFY_RIGHT:
4940 eSvxAdjust = SVX_ADJUST_RIGHT;
4941 break;
4942 case SVX_HOR_JUSTIFY_CENTER:
4943 eSvxAdjust = SVX_ADJUST_CENTER;
4944 break;
4945 case SVX_HOR_JUSTIFY_BLOCK:
4946 eSvxAdjust = SVX_ADJUST_BLOCK;
4947 break;
4949 aDefault.Put( SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) );
4950 aEngine.SetDefaults( aDefault );
4951 if (bSpellErr)
4952 aEngine.SetControlWord( aEngine.GetControlWord() | EE_CNTRL_ONLINESPELLING );
4954 MapMode aEditMode = pViewData->GetLogicMode(eWhich); // ohne Drawing-Skalierung
4955 Rectangle aLogicEdit = PixelToLogic( aEditRect, aEditMode );
4956 long nThisColLogic = aLogicEdit.Right() - aLogicEdit.Left() + 1;
4958 Size aPaperSize = Size( 1000000, 1000000 );
4959 if(pCell->GetCellType() == CELLTYPE_FORMULA)
4961 long nSizeX = 0;
4962 long nSizeY = 0;
4963 pViewData->GetMergeSizePixel( nPosX, nPosY, nSizeX, nSizeY );
4964 aPaperSize = Size(nSizeX, nSizeY );
4965 aPaperSize = PixelToLogic(aPaperSize);
4968 if (bBreak)
4969 aPaperSize.Width() = nThisColLogic;
4970 aEngine.SetPaperSize( aPaperSize );
4972 ::std::auto_ptr< EditTextObject > pTextObj;
4973 const EditTextObject* pData;
4974 if(pCell->GetCellType() == CELLTYPE_EDIT)
4976 ((ScEditCell*)pCell)->GetData(pData);
4977 if (pData)
4978 aEngine.SetText(*pData);
4980 else // HyperLink Formula cell
4982 pTextObj.reset((static_cast<ScFormulaCell*>(pCell))->CreateURLObject());
4983 if (pTextObj.get())
4984 aEngine.SetText(*pTextObj);
4987 long nStartX = aLogicEdit.Left();
4989 long nTextWidth = aEngine.CalcTextWidth();
4990 long nTextHeight = aEngine.GetTextHeight();
4991 if ( nTextWidth < nThisColLogic )
4993 if (eHorJust == SVX_HOR_JUSTIFY_RIGHT)
4994 nStartX += nThisColLogic - nTextWidth;
4995 else if (eHorJust == SVX_HOR_JUSTIFY_CENTER)
4996 nStartX += (nThisColLogic - nTextWidth) / 2;
4999 aLogicEdit.Left() = nStartX;
5000 if (!bBreak)
5001 aLogicEdit.Right() = nStartX + nTextWidth;
5003 // There is one glitch when dealing with a hyperlink cell and
5004 // the cell content is NUMERIC. This defaults to right aligned and
5005 // we need to adjust accordingly.
5006 if(pCell->GetCellType() == CELLTYPE_FORMULA &&
5007 static_cast<ScFormulaCell*>(pCell)->IsValue() &&
5008 eHorJust == SVX_HOR_JUSTIFY_STANDARD)
5010 aLogicEdit.Right() = aLogicEdit.Left() + nThisColLogic - 1;
5011 aLogicEdit.Left() = aLogicEdit.Right() - nTextWidth;
5013 aLogicEdit.Bottom() = aLogicEdit.Top() + nTextHeight;
5016 Point aLogicClick = PixelToLogic(rPos,aEditMode);
5017 if ( aLogicEdit.IsInside(aLogicClick) )
5019 // aEngine.SetUpdateMode(FALSE);
5020 EditView aTempView( &aEngine, this );
5021 aTempView.SetOutputArea( aLogicEdit );
5023 BOOL bRet = FALSE;
5024 MapMode aOld = GetMapMode();
5025 SetMapMode(aEditMode); // kein return mehr
5027 if (bSpellErr) // Spelling-Fehler suchen
5029 bRet = aTempView.IsWrongSpelledWordAtPos( rPos );
5030 if ( bRet )
5031 pViewData->GetView()->SetCursor( nPosX, nPosY ); // Cursor setzen
5033 else // URL suchen
5035 const SvxFieldItem* pFieldItem = aTempView.GetFieldUnderMousePointer();
5037 if (pFieldItem)
5039 const SvxFieldData* pField = pFieldItem->GetField();
5040 if ( pField && pField->ISA(SvxURLField) )
5042 if ( pName || pUrl || pTarget )
5044 const SvxURLField* pURLField = (const SvxURLField*)pField;
5045 if (pName)
5046 *pName = pURLField->GetRepresentation();
5047 if (pUrl)
5048 *pUrl = pURLField->GetURL();
5049 if (pTarget)
5050 *pTarget = pURLField->GetTargetFrame();
5052 bRet = TRUE;
5057 SetMapMode(aOld);
5059 // text cursor is restored in ScHideTextCursor dtor
5061 return bRet;
5063 return FALSE;
5066 BOOL ScGridWindow::HasScenarioButton( const Point& rPosPixel, ScRange& rScenRange )
5068 ScDocument* pDoc = pViewData->GetDocument();
5069 SCTAB nTab = pViewData->GetTabNo();
5070 SCTAB nTabCount = pDoc->GetTableCount();
5071 if ( nTab+1<nTabCount && pDoc->IsScenario(nTab+1) && !pDoc->IsScenario(nTab) )
5073 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5075 Size aButSize = pViewData->GetScenButSize();
5076 long nBWidth = aButSize.Width();
5077 if (!nBWidth)
5078 return FALSE; // noch kein Button gezeichnet -> da ist auch keiner
5079 long nBHeight = aButSize.Height();
5080 long nHSpace = (long)( SC_SCENARIO_HSPACE * pViewData->GetPPTX() );
5082 //! Ranges an der Table cachen!!!!
5084 ScMarkData aMarks;
5085 for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
5086 pDoc->MarkScenario( i, nTab, aMarks, FALSE, SC_SCENARIO_SHOWFRAME );
5087 ScRangeList aRanges;
5088 aMarks.FillRangeListWithMarks( &aRanges, FALSE );
5091 ULONG nRangeCount = aRanges.Count();
5092 for (ULONG j=0; j<nRangeCount; j++)
5094 ScRange aRange = *aRanges.GetObject(j);
5095 // Szenario-Rahmen immer dann auf zusammengefasste Zellen erweitern, wenn
5096 // dadurch keine neuen nicht-ueberdeckten Zellen mit umrandet werden
5097 pDoc->ExtendTotalMerge( aRange );
5099 BOOL bTextBelow = ( aRange.aStart.Row() == 0 );
5101 Point aButtonPos;
5102 if ( bTextBelow )
5104 aButtonPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aEnd.Row()+1,
5105 eWhich, TRUE );
5107 else
5109 aButtonPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aStart.Row(),
5110 eWhich, TRUE );
5111 aButtonPos.Y() -= nBHeight;
5113 if ( bLayoutRTL )
5114 aButtonPos.X() -= nHSpace - 1;
5115 else
5116 aButtonPos.X() -= nBWidth - nHSpace; // same for top or bottom
5118 Rectangle aButRect( aButtonPos, Size(nBWidth,nBHeight) );
5119 if ( aButRect.IsInside( rPosPixel ) )
5121 rScenRange = aRange;
5122 return TRUE;
5127 return FALSE;
5130 // #114409#
5131 void ScGridWindow::DrawLayerCreated()
5133 SetMapMode( GetDrawMapMode() );
5135 // initially create overlay objects
5136 ImpCreateOverlayObjects();
5139 // #114409#
5140 void ScGridWindow::CursorChanged()
5142 // here the created OverlayObjects may be transformed in later versions. For
5143 // now, just re-create them
5145 UpdateCursorOverlay();
5148 // #114409#
5149 void ScGridWindow::ImpCreateOverlayObjects()
5151 UpdateCursorOverlay();
5152 UpdateSelectionOverlay();
5153 UpdateAutoFillOverlay();
5154 UpdateDragRectOverlay();
5155 UpdateHeaderOverlay();
5156 UpdateShrinkOverlay();
5159 // #114409#
5160 void ScGridWindow::ImpDestroyOverlayObjects()
5162 DeleteCursorOverlay();
5163 DeleteSelectionOverlay();
5164 DeleteAutoFillOverlay();
5165 DeleteDragRectOverlay();
5166 DeleteHeaderOverlay();
5167 DeleteShrinkOverlay();
5170 void ScGridWindow::UpdateAllOverlays()
5172 // delete and re-allocate all overlay objects
5174 ImpDestroyOverlayObjects();
5175 ImpCreateOverlayObjects();
5178 void ScGridWindow::DeleteCursorOverlay()
5180 DELETEZ( mpOOCursors );
5181 DELETEZ( mpOOSelectionBorder );
5184 void ScGridWindow::ConvertPixelRectsToRangeVector( const ::std::vector< Rectangle >& rPixelRects,
5185 sdr::overlay::OverlayObjectCell::RangeVector* pRanges,
5186 const MapMode& rDrawMode,
5187 const ScGridWindow::RectangleConverter* pConverter )
5189 std::vector<Rectangle>::const_iterator aPixelEnd( rPixelRects.end() );
5190 for ( std::vector<Rectangle>::const_iterator aPixelIter( rPixelRects.begin() );
5191 aPixelIter != aPixelEnd; ++aPixelIter )
5193 Rectangle aLogic( PixelToLogic(
5194 (pConverter == NULL ? *aPixelIter : pConverter->Convert (*aPixelIter)),
5195 rDrawMode ) );
5197 const basegfx::B2DPoint aTopLeft(aLogic.Left(), aLogic.Top());
5198 const basegfx::B2DPoint aBottomRight(aLogic.Right(), aLogic.Bottom());
5199 const basegfx::B2DRange a2DRange(aTopLeft, aBottomRight);
5201 pRanges->push_back( a2DRange );
5205 void ScGridWindow::UpdateCopySourceOverlay( const MapMode& rDrawMode )
5207 if (!pViewData->ShowPasteSource())
5208 return;
5209 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5210 if (!pOverlayManager)
5211 return;
5212 ScTransferObj* pTransObj = ScTransferObj::GetOwnClipboard( pViewData->GetActiveWin() );
5213 if (!pTransObj)
5214 return;
5215 ScDocument* pClipDoc = pTransObj->GetDocument();
5216 if (!pClipDoc)
5217 return;
5219 SCTAB nCurTab = pViewData->GetCurPos().Tab();
5221 ScClipParam& rClipParam = pClipDoc->GetClipParam();
5222 mpOOSelectionBorder = new ::sdr::overlay::OverlayObjectList;
5223 for (ScRange* p = rClipParam.maRanges.First(); p; p = rClipParam.maRanges.Next())
5225 if (p->aStart.Tab() != nCurTab)
5226 continue;
5228 SCCOL nClipStartX = p->aStart.Col();
5229 SCROW nClipStartY = p->aStart.Row();
5230 SCCOL nClipEndX = p->aEnd.Col();
5231 SCROW nClipEndY = p->aEnd.Row();
5233 Point aClipStartScrPos = pViewData->GetScrPos( nClipStartX, nClipStartY, eWhich );
5234 Point aClipEndScrPos = pViewData->GetScrPos( nClipEndX + 1, nClipEndY + 1, eWhich );
5236 long nSizeXPix = aClipEndScrPos.X() - aClipStartScrPos.X();
5237 long nSizeYPix = aClipEndScrPos.Y() - aClipStartScrPos.Y();
5239 aClipStartScrPos.X() -= 2;
5240 aClipStartScrPos.Y() -= 2;
5242 Rectangle aRect( aClipStartScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) );
5244 std::vector<Rectangle> aPixelRects;
5246 aPixelRects.push_back(Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() ));
5247 aPixelRects.push_back(Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() ));
5248 aPixelRects.push_back(Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 ));
5249 aPixelRects.push_back(Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() ));
5251 sdr::overlay::OverlayObjectCell::RangeVector aRanges;
5252 ConvertPixelRectsToRangeVector( aPixelRects, &aRanges, rDrawMode );
5254 ScOverlayType eType = SC_OVERLAY_BORDER_TRANSPARENT;
5256 Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
5257 sdr::overlay::OverlayObjectCell* pOverlay = new sdr::overlay::OverlayObjectCell( eType, aHighlight, aRanges );
5259 pOverlayManager->add(*pOverlay);
5260 mpOOSelectionBorder->append(*pOverlay);
5264 void ScGridWindow::UpdateCursorOverlay()
5266 MapMode aDrawMode = GetDrawMapMode();
5267 MapMode aOldMode = GetMapMode();
5268 if ( aOldMode != aDrawMode )
5269 SetMapMode( aDrawMode );
5271 // Existing OverlayObjects may be transformed in later versions.
5272 // For now, just re-create them.
5274 DeleteCursorOverlay();
5276 UpdateCopySourceOverlay( aDrawMode );
5278 std::vector<Rectangle> aPixelRects;
5281 // determine the cursor rectangles in pixels (moved from ScGridWindow::DrawCursor)
5284 SCTAB nTab = pViewData->GetTabNo();
5285 SCCOL nX = pViewData->GetCurX();
5286 SCROW nY = pViewData->GetCurY();
5288 if (!maVisibleRange.isInside(nX, nY))
5289 return;
5291 // don't show the cursor in overlapped cells
5293 ScDocument* pDoc = pViewData->GetDocument();
5294 const ScPatternAttr* pPattern = pDoc->GetPattern(nX,nY,nTab);
5295 const ScMergeFlagAttr& rMergeFlag = (const ScMergeFlagAttr&) pPattern->GetItem(ATTR_MERGE_FLAG);
5296 BOOL bOverlapped = rMergeFlag.IsOverlapped();
5298 // left or above of the screen?
5300 BOOL bVis = ( nX>=pViewData->GetPosX(eHWhich) && nY>=pViewData->GetPosY(eVWhich) );
5301 if (!bVis)
5303 SCCOL nEndX = nX;
5304 SCROW nEndY = nY;
5305 const ScMergeAttr& rMerge = (const ScMergeAttr&) pPattern->GetItem(ATTR_MERGE);
5306 if (rMerge.GetColMerge() > 1)
5307 nEndX += rMerge.GetColMerge()-1;
5308 if (rMerge.GetRowMerge() > 1)
5309 nEndY += rMerge.GetRowMerge()-1;
5310 bVis = ( nEndX>=pViewData->GetPosX(eHWhich) && nEndY>=pViewData->GetPosY(eVWhich) );
5313 if ( bVis && !bOverlapped && !pViewData->HasEditView(eWhich) && pViewData->IsActive() )
5315 Point aScrPos = pViewData->GetScrPos( nX, nY, eWhich, TRUE );
5316 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5318 // completely right of/below the screen?
5319 // (test with logical start position in aScrPos)
5320 BOOL bMaybeVisible;
5321 if ( bLayoutRTL )
5322 bMaybeVisible = ( aScrPos.X() >= -2 && aScrPos.Y() >= -2 );
5323 else
5325 Size aOutSize = GetOutputSizePixel();
5326 bMaybeVisible = ( aScrPos.X() <= aOutSize.Width() + 2 && aScrPos.Y() <= aOutSize.Height() + 2 );
5328 if ( bMaybeVisible )
5330 long nSizeXPix;
5331 long nSizeYPix;
5332 pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix );
5334 if ( bLayoutRTL )
5335 aScrPos.X() -= nSizeXPix - 2; // move instead of mirroring
5337 // Now, draw the cursor.
5339 aScrPos.X() -= 2;
5340 aScrPos.Y() -= 2;
5341 Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) );
5343 aPixelRects.push_back(Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() ));
5344 aPixelRects.push_back(Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() ));
5345 aPixelRects.push_back(Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 ));
5346 aPixelRects.push_back(Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() ));
5351 // convert into logic units and create overlay object
5354 if ( aPixelRects.size() )
5356 sdr::overlay::OverlayObjectCell::RangeVector aRanges;
5357 ConvertPixelRectsToRangeVector( aPixelRects, &aRanges, aDrawMode );
5359 // #i70788# get the OverlayManager safely
5360 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5362 if(pOverlayManager)
5364 BOOL bOld = pViewData->GetView()->IsOldSelection();
5366 ScOverlayType eType = bOld ? SC_OVERLAY_INVERT : SC_OVERLAY_SOLID;
5367 Color aCursorColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
5368 if (pViewData->GetActivePart() != eWhich)
5369 // non-active pane uses a different color.
5370 aCursorColor = SC_MOD()->GetColorConfig().GetColorValue(svtools::CALCPAGEBREAKAUTOMATIC).nColor;
5372 sdr::overlay::OverlayObjectCell* pOverlay = new sdr::overlay::OverlayObjectCell( eType, aCursorColor, aRanges );
5374 pOverlayManager->add(*pOverlay);
5375 mpOOCursors = new ::sdr::overlay::OverlayObjectList;
5376 mpOOCursors->append(*pOverlay);
5380 if ( aOldMode != aDrawMode )
5381 SetMapMode( aOldMode );
5384 void ScGridWindow::DeleteSelectionOverlay()
5386 DELETEZ( mpOOSelection );
5389 void ScGridWindow::UpdateSelectionOverlay()
5391 MapMode aDrawMode = GetDrawMapMode();
5392 MapMode aOldMode = GetMapMode();
5393 if ( aOldMode != aDrawMode )
5394 SetMapMode( aDrawMode );
5396 DeleteSelectionOverlay();
5398 std::vector<Rectangle> aPixelRects;
5399 GetSelectionRects( aPixelRects );
5401 if ( aPixelRects.size() && pViewData->IsActive() )
5403 struct SelectionConverter : RectangleConverter {
5404 SCTAB nTab;
5405 BOOL bLayoutRTL;
5406 BOOL bOld;
5408 SelectionConverter (ScViewData* pViewData)
5409 : nTab (pViewData->GetTabNo())
5410 , bLayoutRTL (pViewData->GetDocument()->IsLayoutRTL( nTab ))
5411 , bOld (pViewData->GetView()->IsOldSelection())
5415 Rectangle Convert (const Rectangle& rRect) const
5417 if ( bOld )
5418 return rRect;
5419 // for transparent selection, add a pixel so the border is on the grid on all edges
5420 Rectangle aPixel (rRect);
5421 if ( bLayoutRTL )
5422 aPixel.Right() += 1;
5423 else
5424 aPixel.Left() -= 1;
5425 aPixel.Top() -= 1;
5426 return aPixel;
5429 SelectionConverter aConverter (pViewData);
5431 sdr::overlay::OverlayObjectCell::RangeVector aRanges;
5432 ConvertPixelRectsToRangeVector( aPixelRects, &aRanges, aDrawMode, &aConverter );
5434 // #i70788# get the OverlayManager safely
5435 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5437 if(pOverlayManager)
5439 ScOverlayType eType = aConverter.bOld ? SC_OVERLAY_INVERT : SC_OVERLAY_BORDER_TRANSPARENT;
5440 Color aHighlight( GetSettings().GetStyleSettings().GetHighlightColor() );
5441 sdr::overlay::OverlayObjectCell* pOverlay =
5442 new sdr::overlay::OverlayObjectCell( eType, aHighlight, aRanges );
5444 pOverlayManager->add(*pOverlay);
5445 mpOOSelection = new ::sdr::overlay::OverlayObjectList;
5446 mpOOSelection->append(*pOverlay);
5450 if ( aOldMode != aDrawMode )
5451 SetMapMode( aOldMode );
5454 void ScGridWindow::DeleteAutoFillOverlay()
5456 DELETEZ( mpOOAutoFill );
5457 mpAutoFillRect.reset();
5460 void ScGridWindow::UpdateAutoFillOverlay()
5462 MapMode aDrawMode = GetDrawMapMode();
5463 MapMode aOldMode = GetMapMode();
5464 if ( aOldMode != aDrawMode )
5465 SetMapMode( aDrawMode );
5467 DeleteAutoFillOverlay();
5470 // get the AutoFill handle rectangle in pixels (moved from ScGridWindow::DrawAutoFillMark)
5473 if ( bAutoMarkVisible && aAutoMarkPos.Tab() == pViewData->GetTabNo() &&
5474 !pViewData->HasEditView(eWhich) && pViewData->IsActive() )
5476 SCCOL nX = aAutoMarkPos.Col();
5477 SCROW nY = aAutoMarkPos.Row();
5479 if (!maVisibleRange.isInside(nX, nY))
5480 // Autofill mark is not visible. Bail out.
5481 return;
5483 SCTAB nTab = pViewData->GetTabNo();
5484 ScDocument* pDoc = pViewData->GetDocument();
5485 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5487 Point aFillPos = pViewData->GetScrPos( nX, nY, eWhich, TRUE );
5488 long nSizeXPix;
5489 long nSizeYPix;
5490 pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix );
5491 if ( bLayoutRTL )
5492 aFillPos.X() -= nSizeXPix + 3;
5493 else
5494 aFillPos.X() += nSizeXPix - 2;
5496 aFillPos.Y() += nSizeYPix;
5497 aFillPos.Y() -= 2;
5498 mpAutoFillRect.reset(new Rectangle(aFillPos, Size(6, 6)));
5501 // convert into logic units
5504 sdr::overlay::OverlayObjectCell::RangeVector aRanges;
5506 Rectangle aLogic( PixelToLogic( *mpAutoFillRect, aDrawMode ) );
5508 const basegfx::B2DPoint aTopLeft(aLogic.Left(), aLogic.Top());
5509 const basegfx::B2DPoint aBottomRight(aLogic.Right(), aLogic.Bottom());
5510 const basegfx::B2DRange a2DRange(aTopLeft, aBottomRight);
5512 aRanges.push_back( a2DRange );
5514 // #i70788# get the OverlayManager safely
5515 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5517 if(pOverlayManager)
5519 BOOL bOld = pViewData->GetView()->IsOldSelection();
5521 ScOverlayType eType = bOld ? SC_OVERLAY_INVERT : SC_OVERLAY_SOLID;
5522 Color aHandleColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
5523 if (pViewData->GetActivePart() != eWhich)
5524 // non-active pane uses a different color.
5525 aHandleColor = SC_MOD()->GetColorConfig().GetColorValue(svtools::CALCPAGEBREAKAUTOMATIC).nColor;
5527 sdr::overlay::OverlayObjectCell* pOverlay =
5528 new sdr::overlay::OverlayObjectCell( eType, aHandleColor, aRanges );
5530 pOverlayManager->add(*pOverlay);
5531 mpOOAutoFill = new ::sdr::overlay::OverlayObjectList;
5532 mpOOAutoFill->append(*pOverlay);
5535 if ( aOldMode != aDrawMode )
5536 SetMapMode( aOldMode );
5540 void ScGridWindow::DeleteDragRectOverlay()
5542 DELETEZ( mpOODragRect );
5545 void ScGridWindow::UpdateDragRectOverlay()
5547 MapMode aDrawMode = GetDrawMapMode();
5548 MapMode aOldMode = GetMapMode();
5549 if ( aOldMode != aDrawMode )
5550 SetMapMode( aDrawMode );
5552 DeleteDragRectOverlay();
5555 // get the rectangles in pixels (moved from DrawDragRect)
5558 if ( bDragRect || bPagebreakDrawn )
5560 std::vector<Rectangle> aPixelRects;
5562 SCCOL nX1 = bDragRect ? nDragStartX : aPagebreakDrag.aStart.Col();
5563 SCROW nY1 = bDragRect ? nDragStartY : aPagebreakDrag.aStart.Row();
5564 SCCOL nX2 = bDragRect ? nDragEndX : aPagebreakDrag.aEnd.Col();
5565 SCROW nY2 = bDragRect ? nDragEndY : aPagebreakDrag.aEnd.Row();
5567 SCTAB nTab = pViewData->GetTabNo();
5569 SCCOL nPosX = pViewData->GetPosX(WhichH(eWhich));
5570 SCROW nPosY = pViewData->GetPosY(WhichV(eWhich));
5571 if (nX1 < nPosX) nX1 = nPosX;
5572 if (nX2 < nPosX) nX2 = nPosX;
5573 if (nY1 < nPosY) nY1 = nPosY;
5574 if (nY2 < nPosY) nY2 = nPosY;
5576 Point aScrPos( pViewData->GetScrPos( nX1, nY1, eWhich ) );
5578 long nSizeXPix=0;
5579 long nSizeYPix=0;
5580 ScDocument* pDoc = pViewData->GetDocument();
5581 double nPPTX = pViewData->GetPPTX();
5582 double nPPTY = pViewData->GetPPTY();
5583 SCCOLROW i;
5585 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5586 long nLayoutSign = bLayoutRTL ? -1 : 1;
5588 if (ValidCol(nX2) && nX2>=nX1)
5589 for (i=nX1; i<=nX2; i++)
5590 nSizeXPix += ScViewData::ToPixel( pDoc->GetColWidth( static_cast<SCCOL>(i), nTab ), nPPTX );
5591 else
5593 aScrPos.X() -= nLayoutSign;
5594 nSizeXPix += 2;
5597 if (ValidRow(nY2) && nY2>=nY1)
5598 for (i=nY1; i<=nY2; i++)
5599 nSizeYPix += ScViewData::ToPixel( pDoc->GetRowHeight( i, nTab ), nPPTY );
5600 else
5602 aScrPos.Y() -= 1;
5603 nSizeYPix += 2;
5606 aScrPos.X() -= 2 * nLayoutSign;
5607 aScrPos.Y() -= 2;
5608 // Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) );
5609 Rectangle aRect( aScrPos.X(), aScrPos.Y(),
5610 aScrPos.X() + ( nSizeXPix + 2 ) * nLayoutSign, aScrPos.Y() + nSizeYPix + 2 );
5611 if ( bLayoutRTL )
5613 aRect.Left() = aRect.Right(); // end position is left
5614 aRect.Right() = aScrPos.X();
5617 if ( meDragInsertMode == INS_CELLSDOWN )
5619 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Top()+3, aRect.Left()+1, aRect.Bottom()-2 ) );
5620 aPixelRects.push_back( Rectangle( aRect.Right()-1, aRect.Top()+3, aRect.Right()-1, aRect.Bottom()-2 ) );
5621 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Top(), aRect.Right()-1, aRect.Top()+2 ) );
5622 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Bottom()-1, aRect.Right()-1, aRect.Bottom()-1 ) );
5624 else if ( meDragInsertMode == INS_CELLSRIGHT )
5626 aPixelRects.push_back( Rectangle( aRect.Left(), aRect.Top()+1, aRect.Left()+2, aRect.Bottom()-1 ) );
5627 aPixelRects.push_back( Rectangle( aRect.Right()-1, aRect.Top()+1, aRect.Right()-1, aRect.Bottom()-1 ) );
5628 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Top()+1, aRect.Right()-2, aRect.Top()+1 ) );
5629 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Bottom()-1, aRect.Right()-2, aRect.Bottom()-1 ) );
5631 else
5633 aPixelRects.push_back( Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() ) );
5634 aPixelRects.push_back( Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() ) );
5635 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 ) );
5636 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() ) );
5640 // convert into logic units and create overlay object
5643 sdr::overlay::OverlayObjectCell::RangeVector aRanges;
5644 ConvertPixelRectsToRangeVector( aPixelRects, &aRanges, aDrawMode );
5646 // #i70788# get the OverlayManager safely
5647 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5649 if(pOverlayManager)
5651 ScOverlayType eType = SC_OVERLAY_INVERT;
5652 Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
5653 sdr::overlay::OverlayObjectCell* pOverlay =
5654 new sdr::overlay::OverlayObjectCell( eType, aHighlight, aRanges );
5656 pOverlayManager->add(*pOverlay);
5657 mpOODragRect = new ::sdr::overlay::OverlayObjectList;
5658 mpOODragRect->append(*pOverlay);
5662 if ( aOldMode != aDrawMode )
5663 SetMapMode( aOldMode );
5666 void ScGridWindow::DeleteHeaderOverlay()
5668 DELETEZ( mpOOHeader );
5671 void ScGridWindow::UpdateHeaderOverlay()
5673 MapMode aDrawMode = GetDrawMapMode();
5674 MapMode aOldMode = GetMapMode();
5675 if ( aOldMode != aDrawMode )
5676 SetMapMode( aDrawMode );
5678 DeleteHeaderOverlay();
5680 // Pixel rectangle is in aInvertRect
5683 // convert into logic units and create overlay object
5686 if ( !aInvertRect.IsEmpty() )
5688 Rectangle aLogic( PixelToLogic( aInvertRect, aDrawMode ) );
5690 const basegfx::B2DPoint aTopLeft(aLogic.Left(), aLogic.Top());
5691 const basegfx::B2DPoint aBottomRight(aLogic.Right(), aLogic.Bottom());
5692 const basegfx::B2DRange a2DRange(aTopLeft, aBottomRight);
5694 sdr::overlay::OverlayObjectCell::RangeVector aRanges;
5695 aRanges.push_back( a2DRange );
5697 // #i70788# get the OverlayManager safely
5698 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5700 if(pOverlayManager)
5702 ScOverlayType eType = SC_OVERLAY_INVERT;
5703 Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
5704 sdr::overlay::OverlayObjectCell* pOverlay =
5705 new sdr::overlay::OverlayObjectCell( eType, aHighlight, aRanges );
5707 pOverlayManager->add(*pOverlay);
5708 mpOOHeader = new ::sdr::overlay::OverlayObjectList;
5709 mpOOHeader->append(*pOverlay);
5713 if ( aOldMode != aDrawMode )
5714 SetMapMode( aOldMode );
5717 void ScGridWindow::DeleteShrinkOverlay()
5719 DELETEZ( mpOOShrink );
5722 void ScGridWindow::UpdateShrinkOverlay()
5724 MapMode aDrawMode = GetDrawMapMode();
5725 MapMode aOldMode = GetMapMode();
5726 if ( aOldMode != aDrawMode )
5727 SetMapMode( aDrawMode );
5729 DeleteShrinkOverlay();
5732 // get the rectangle in pixels
5735 Rectangle aPixRect;
5736 ScRange aRange;
5737 SCTAB nTab = pViewData->GetTabNo();
5738 if ( pViewData->IsRefMode() && nTab >= pViewData->GetRefStartZ() && nTab <= pViewData->GetRefEndZ() &&
5739 pViewData->GetDelMark( aRange ) )
5741 //! limit to visible area
5742 if ( aRange.aStart.Col() <= aRange.aEnd.Col() &&
5743 aRange.aStart.Row() <= aRange.aEnd.Row() )
5745 Point aStart = pViewData->GetScrPos( aRange.aStart.Col(),
5746 aRange.aStart.Row(), eWhich );
5747 Point aEnd = pViewData->GetScrPos( aRange.aEnd.Col()+1,
5748 aRange.aEnd.Row()+1, eWhich );
5749 aEnd.X() -= 1;
5750 aEnd.Y() -= 1;
5752 aPixRect = Rectangle( aStart,aEnd );
5757 // convert into logic units and create overlay object
5760 if ( !aPixRect.IsEmpty() )
5762 Rectangle aLogic( PixelToLogic( aPixRect, aDrawMode ) );
5764 const basegfx::B2DPoint aTopLeft(aLogic.Left(), aLogic.Top());
5765 const basegfx::B2DPoint aBottomRight(aLogic.Right(), aLogic.Bottom());
5766 const basegfx::B2DRange a2DRange(aTopLeft, aBottomRight);
5768 sdr::overlay::OverlayObjectCell::RangeVector aRanges;
5769 aRanges.push_back( a2DRange );
5771 // #i70788# get the OverlayManager safely
5772 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5774 if(pOverlayManager)
5776 ScOverlayType eType = SC_OVERLAY_INVERT;
5777 Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
5778 sdr::overlay::OverlayObjectCell* pOverlay =
5779 new sdr::overlay::OverlayObjectCell( eType, aHighlight, aRanges );
5781 pOverlayManager->add(*pOverlay);
5782 mpOOShrink = new ::sdr::overlay::OverlayObjectList;
5783 mpOOShrink->append(*pOverlay);
5787 if ( aOldMode != aDrawMode )
5788 SetMapMode( aOldMode );
5791 // #i70788# central method to get the OverlayManager safely
5792 ::sdr::overlay::OverlayManager* ScGridWindow::getOverlayManager()
5794 SdrPageView* pPV = pViewData->GetView()->GetScDrawView()->GetSdrPageView();
5796 if(pPV)
5798 SdrPageWindow* pPageWin = pPV->FindPageWindow( *this );
5800 if ( pPageWin )
5802 return (pPageWin->GetOverlayManager());
5806 return 0L;
5809 void ScGridWindow::flushOverlayManager()
5811 // #i70788# get the OverlayManager safely
5812 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5814 if(pOverlayManager)
5816 pOverlayManager->flush();
5820 // ---------------------------------------------------------------------------
5822 // #114409#
5823 namespace sdr
5825 namespace overlay
5827 OverlayObjectCell::OverlayObjectCell( ScOverlayType eType, const Color& rColor, const RangeVector& rRects )
5828 : OverlayObject( rColor ),
5829 mePaintType( eType ),
5830 maRectangles( rRects )
5834 OverlayObjectCell::~OverlayObjectCell()
5838 void OverlayObjectCell::drawGeometry(OutputDevice& rOutputDevice)
5840 // safe original AA and switch off for selection
5841 const sal_uInt16 nOriginalAA(rOutputDevice.GetAntialiasing());
5842 rOutputDevice.SetAntialiasing(0);
5844 // set colors
5845 rOutputDevice.SetLineColor();
5846 rOutputDevice.SetFillColor(getBaseColor());
5848 if ( mePaintType == SC_OVERLAY_BORDER_TRANSPARENT )
5850 // to draw the border, all rectangles have to be collected into a PolyPolygon
5852 PolyPolygon aPolyPoly;
5853 sal_uInt32 nRectCount = maRectangles.size();
5854 for(sal_uInt32 nRect=0; nRect < nRectCount; ++nRect)
5856 const basegfx::B2DRange& rRange(maRectangles[nRect]);
5857 Rectangle aRectangle(FRound(rRange.getMinX()), FRound(rRange.getMinY()), FRound(rRange.getMaxX()), FRound(rRange.getMaxY()));
5858 if ( nRectCount == 1 || nRect+1 < nRectCount )
5860 // simply add for all except the last rect
5861 aPolyPoly.Insert( Polygon( aRectangle ) );
5863 else
5865 PolyPolygon aTemp( aPolyPoly );
5866 aTemp.GetUnion( PolyPolygon( Polygon( aRectangle ) ), aPolyPoly );
5870 rOutputDevice.DrawTransparent(aPolyPoly, 75);
5872 rOutputDevice.SetLineColor(getBaseColor());
5873 rOutputDevice.SetFillColor();
5875 rOutputDevice.DrawPolyPolygon(aPolyPoly);
5877 else
5879 if ( mePaintType == SC_OVERLAY_INVERT )
5881 rOutputDevice.Push();
5882 rOutputDevice.SetRasterOp( ROP_XOR );
5883 rOutputDevice.SetFillColor( COL_WHITE );
5886 for(sal_uInt32 a(0L);a < maRectangles.size(); a++)
5888 const basegfx::B2DRange& rRange(maRectangles[a]);
5889 const Rectangle aRectangle(FRound(rRange.getMinX()), FRound(rRange.getMinY()), FRound(rRange.getMaxX()), FRound(rRange.getMaxY()));
5891 switch(mePaintType)
5893 case SC_OVERLAY_INVERT :
5895 rOutputDevice.DrawRect( aRectangle );
5896 break;
5898 case SC_OVERLAY_SOLID :
5900 rOutputDevice.DrawRect(aRectangle);
5901 break;
5903 default:
5905 // SC_OVERLAY_BORDER_TRANSPARENT is handled separately
5910 if ( mePaintType == SC_OVERLAY_INVERT )
5912 rOutputDevice.Pop();
5916 // restore original AA
5917 rOutputDevice.SetAntialiasing(nOriginalAA);
5920 void OverlayObjectCell::createBaseRange(OutputDevice& /* rOutputDevice */)
5922 maBaseRange.reset();
5924 for(sal_uInt32 a(0L); a < maRectangles.size(); a++)
5926 maBaseRange.expand(maRectangles[a]);
5930 void OverlayObjectCell::transform(const basegfx::B2DHomMatrix& rMatrix)
5932 for(sal_uInt32 a(0L); a < maRectangles.size(); a++)
5934 maRectangles[a].transform(rMatrix);
5938 } // end of namespace overlay
5939 } // end of namespace sdr
5941 // ---------------------------------------------------------------------------
5943 // eof