merge the formfield patch from ooo-build
[ooovba.git] / sc / source / ui / view / gridwin.cxx
blobd02bd3110906610ecdb436412a02fa1dee54b8aa
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 "validat.hxx"
122 #include "tabprotection.hxx"
123 #include "postit.hxx"
124 #include "dpcontrol.hxx"
125 #include "clipparam.hxx"
126 #include "cellsh.hxx"
127 #include "overlayobject.hxx"
129 #include "drawview.hxx"
130 #include <svx/sdrpagewindow.hxx>
131 #include <svx/sdr/overlay/overlaymanager.hxx>
132 #include <vcl/svapp.hxx>
133 #include <svx/sdr/overlay/overlayselection.hxx>
135 #include "cellsuno.hxx"
137 #include <com/sun/star/document/XVbaEventsHelper.hpp>
138 #include <com/sun/star/document/VbaEventId.hpp>
140 using namespace com::sun::star;
141 using namespace com::sun::star::document::VbaEventId;
142 using ::com::sun::star::uno::Sequence;
143 using ::com::sun::star::uno::Any;
145 const BYTE SC_NESTEDBUTTON_NONE = 0;
146 const BYTE SC_NESTEDBUTTON_DOWN = 1;
147 const BYTE SC_NESTEDBUTTON_UP = 2;
149 #define SC_AUTOFILTER_ALL 0
150 #define SC_AUTOFILTER_TOP10 1
151 #define SC_AUTOFILTER_CUSTOM 2
152 #define SC_AUTOFILTER_EMPTY 3
153 #define SC_AUTOFILTER_NOTEMPTY 4
155 // Modi fuer die FilterListBox
156 enum ScFilterBoxMode
158 SC_FILTERBOX_FILTER,
159 SC_FILTERBOX_DATASELECT,
160 SC_FILTERBOX_SCENARIO,
161 SC_FILTERBOX_PAGEFIELD
164 extern SfxViewShell* pScActiveViewShell; // global.cxx
165 extern USHORT nScClickMouseModifier; // global.cxx
166 extern USHORT nScFillModeMouseModifier; // global.cxx
168 #define SC_FILTERLISTBOX_LINES 12
170 // ============================================================================
172 ScGridWindow::VisibleRange::VisibleRange() :
173 mnCol1(0), mnCol2(MAXCOL), mnRow1(0), mnRow2(MAXROW)
177 bool ScGridWindow::VisibleRange::isInside(SCCOL nCol, SCROW nRow) const
179 return mnCol1 <= nCol && nCol <= mnCol2 && mnRow1 <= nRow && nRow <= mnRow2;
182 // ============================================================================
184 class ScFilterListBox : public ListBox
186 private:
187 ScGridWindow* pGridWin;
188 SCCOL nCol;
189 SCROW nRow;
190 BOOL bButtonDown;
191 BOOL bInit;
192 BOOL bCancelled;
193 BOOL bInSelect;
194 bool mbListHasDates;
195 ULONG nSel;
196 ScFilterBoxMode eMode;
198 protected:
199 virtual void LoseFocus();
200 void SelectHdl();
202 public:
203 ScFilterListBox( Window* pParent, ScGridWindow* pGrid,
204 SCCOL nNewCol, SCROW nNewRow, ScFilterBoxMode eNewMode );
205 ~ScFilterListBox();
207 virtual long PreNotify( NotifyEvent& rNEvt );
208 virtual void Select();
210 SCCOL GetCol() const { return nCol; }
211 SCROW GetRow() const { return nRow; }
212 ScFilterBoxMode GetMode() const { return eMode; }
213 BOOL IsDataSelect() const { return (eMode == SC_FILTERBOX_DATASELECT); }
214 void EndInit();
215 BOOL IsInInit() const { return bInit; }
216 void SetCancelled() { bCancelled = TRUE; }
217 BOOL IsInSelect() const { return bInSelect; }
218 void SetListHasDates(bool b) { mbListHasDates = b; }
219 bool HasDates() const { return mbListHasDates; }
222 //-------------------------------------------------------------------
224 // ListBox in einem FloatingWindow (pParent)
225 ScFilterListBox::ScFilterListBox( Window* pParent, ScGridWindow* pGrid,
226 SCCOL nNewCol, SCROW nNewRow, ScFilterBoxMode eNewMode ) :
227 ListBox( pParent, WB_AUTOHSCROLL ),
228 pGridWin( pGrid ),
229 nCol( nNewCol ),
230 nRow( nNewRow ),
231 bButtonDown( FALSE ),
232 bInit( TRUE ),
233 bCancelled( FALSE ),
234 bInSelect( FALSE ),
235 mbListHasDates(false),
236 nSel( 0 ),
237 eMode( eNewMode )
241 __EXPORT ScFilterListBox::~ScFilterListBox()
243 if (IsMouseCaptured())
244 ReleaseMouse();
247 void ScFilterListBox::EndInit()
249 USHORT nPos = GetSelectEntryPos();
250 if ( LISTBOX_ENTRY_NOTFOUND == nPos )
251 nSel = 0;
252 else
253 nSel = nPos;
255 bInit = FALSE;
258 void __EXPORT ScFilterListBox::LoseFocus()
260 #ifndef UNX
261 Hide();
262 #endif
265 // -----------------------------------------------------------------------
267 long ScFilterListBox::PreNotify( NotifyEvent& rNEvt )
269 long nDone = 0;
270 if ( rNEvt.GetType() == EVENT_KEYINPUT )
272 KeyEvent aKeyEvt = *rNEvt.GetKeyEvent();
273 KeyCode aCode = aKeyEvt.GetKeyCode();
274 if ( !aCode.GetModifier() ) // ohne alle Modifiers
276 USHORT nKey = aCode.GetCode();
277 if ( nKey == KEY_RETURN )
279 SelectHdl(); // auswaehlen
280 nDone = 1;
282 else if ( nKey == KEY_ESCAPE )
284 pGridWin->ClickExtern(); // loescht die List-Box !!!
285 nDone = 1;
290 return nDone ? nDone : ListBox::PreNotify( rNEvt );
293 void __EXPORT ScFilterListBox::Select()
295 ListBox::Select();
296 SelectHdl();
299 void __EXPORT ScFilterListBox::SelectHdl()
301 if ( !IsTravelSelect() && !bInit && !bCancelled )
303 USHORT nPos = GetSelectEntryPos();
304 if ( LISTBOX_ENTRY_NOTFOUND != nPos )
306 nSel = nPos;
307 if (!bButtonDown)
309 // #i81298# set bInSelect flag, so the box isn't deleted from modifications within FilterSelect
310 bInSelect = TRUE;
311 pGridWin->FilterSelect( nSel );
312 bInSelect = FALSE;
318 // ============================================================================
320 // use a System floating window for the above filter listbox
321 class ScFilterFloatingWindow : public FloatingWindow
323 public:
324 ScFilterFloatingWindow( Window* pParent, WinBits nStyle = WB_STDFLOATWIN );
325 virtual ~ScFilterFloatingWindow();
326 // required for System FloatingWindows that will not process KeyInput by themselves
327 virtual Window* GetPreferredKeyInputWindow();
330 ScFilterFloatingWindow::ScFilterFloatingWindow( Window* pParent, WinBits nStyle ) :
331 FloatingWindow( pParent, nStyle|WB_SYSTEMWINDOW ) // make it a system floater
334 ScFilterFloatingWindow::~ScFilterFloatingWindow()
336 EndPopupMode();
339 Window* ScFilterFloatingWindow::GetPreferredKeyInputWindow()
341 // redirect keyinput in the child window
342 return GetWindow(WINDOW_FIRSTCHILD) ? GetWindow(WINDOW_FIRSTCHILD)->GetPreferredKeyInputWindow() : NULL; // will be the FilterBox
345 // ============================================================================
347 BOOL lcl_IsEditableMatrix( ScDocument* pDoc, const ScRange& rRange )
349 // wenn es ein editierbarer Bereich ist, und rechts unten eine Matrix-Zelle
350 // mit Origin links oben liegt, enthaelt der Bereich genau die Matrix.
351 //! Direkt die MatrixEdges Funktionen von der Column herausreichen ???
353 if ( !pDoc->IsBlockEditable( rRange.aStart.Tab(), rRange.aStart.Col(),rRange.aStart.Row(),
354 rRange.aEnd.Col(),rRange.aEnd.Row() ) )
355 return FALSE;
357 ScAddress aPos;
358 const ScBaseCell* pCell = pDoc->GetCell( rRange.aEnd );
359 return ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA &&
360 ((ScFormulaCell*)pCell)->GetMatrixOrigin(aPos) && aPos == rRange.aStart );
364 void lcl_UnLockComment( ScDrawView* pView, SdrPageView* pPV, SdrModel* pDrDoc, const Point& rPos, ScViewData* pViewData )
366 if (!pView && !pPV && !pDrDoc && !pViewData)
367 return;
369 ScDocument& rDoc = *pViewData->GetDocument();
370 ScAddress aCellPos( pViewData->GetCurX(), pViewData->GetCurY(), pViewData->GetTabNo() );
371 ScPostIt* pNote = rDoc.GetNote( aCellPos );
372 SdrObject* pObj = pNote ? pNote->GetCaption() : 0;
373 if( pObj && pObj->GetLogicRect().IsInside( rPos ) && ScDrawLayer::IsNoteCaption( pObj ) )
375 const ScProtectionAttr* pProtAttr = static_cast< const ScProtectionAttr* > (rDoc.GetAttr( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab(), ATTR_PROTECTION ) );
376 bool bProtectAttr = pProtAttr->GetProtection() || pProtAttr->GetHideCell() ;
377 bool bProtectDoc = rDoc.IsTabProtected( aCellPos.Tab() ) || pViewData->GetSfxDocShell()->IsReadOnly() ;
378 // unlock internal layer (if not protected), will be relocked in ScDrawView::MarkListHasChanged()
379 pView->LockInternalLayer( bProtectDoc && bProtectAttr );
383 sal_Bool lcl_GetHyperlinkCell(ScDocument* pDoc, SCCOL& rPosX, SCROW& rPosY, SCTAB nTab, ScBaseCell*& rpCell )
385 BOOL bFound = FALSE;
388 pDoc->GetCell( rPosX, rPosY, nTab, rpCell );
389 if ( !rpCell || rpCell->GetCellType() == CELLTYPE_NOTE )
391 if ( rPosX <= 0 )
392 return FALSE; // alles leer bis links
393 else
394 --rPosX; // weitersuchen
396 else if ( rpCell->GetCellType() == CELLTYPE_EDIT)
397 bFound = TRUE;
398 else if (rpCell->GetCellType() == CELLTYPE_FORMULA &&
399 static_cast<ScFormulaCell*>(rpCell)->IsHyperLinkCell())
400 bFound = TRUE;
401 else
402 return FALSE; // andere Zelle
404 while ( !bFound );
406 return bFound;
409 // ---------------------------------------------------------------------------
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 mpFilterButton(NULL),
430 nCursorHideCount( 0 ),
431 bMarking( FALSE ),
432 nButtonDown( 0 ),
433 bEEMouse( FALSE ),
434 nMouseStatus( SC_GM_NONE ),
435 nNestedButtonState( SC_NESTEDBUTTON_NONE ),
436 bDPMouse( FALSE ),
437 bRFMouse( FALSE ),
438 nPagebreakMouse( SC_PD_NONE ),
439 bPagebreakDrawn( FALSE ),
440 nPageScript( 0 ),
441 bDragRect( FALSE ),
442 meDragInsertMode( INS_NONE ),
443 nCurrentPointer( 0 ),
444 bIsInScroll( FALSE ),
445 bIsInPaint( FALSE ),
446 aComboButton( this ),
447 aCurMousePos( 0,0 ),
448 nPaintCount( 0 ),
449 bNeedsRepaint( FALSE ),
450 bAutoMarkVisible( FALSE ),
451 bListValButton( FALSE )
453 switch(eWhich)
455 case SC_SPLIT_TOPLEFT:
456 eHWhich = SC_SPLIT_LEFT;
457 eVWhich = SC_SPLIT_TOP;
458 break;
459 case SC_SPLIT_TOPRIGHT:
460 eHWhich = SC_SPLIT_RIGHT;
461 eVWhich = SC_SPLIT_TOP;
462 break;
463 case SC_SPLIT_BOTTOMLEFT:
464 eHWhich = SC_SPLIT_LEFT;
465 eVWhich = SC_SPLIT_BOTTOM;
466 break;
467 case SC_SPLIT_BOTTOMRIGHT:
468 eHWhich = SC_SPLIT_RIGHT;
469 eVWhich = SC_SPLIT_BOTTOM;
470 break;
471 default:
472 DBG_ERROR("GridWindow: falsche Position");
475 SetBackground();
477 SetMapMode(pViewData->GetLogicMode(eWhich));
478 // EnableDrop();
479 EnableChildTransparentMode();
480 SetDialogControlFlags( WINDOW_DLGCTRL_RETURN | WINDOW_DLGCTRL_WANTFOCUS );
482 SetHelpId( HID_SC_WIN_GRIDWIN );
483 SetUniqueId( HID_SC_WIN_GRIDWIN );
485 SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
486 EnableRTL( FALSE );
489 __EXPORT ScGridWindow::~ScGridWindow()
491 // #114409#
492 ImpDestroyOverlayObjects();
494 delete pFilterBox;
495 delete pFilterFloat;
496 delete pNoteMarker;
499 void __EXPORT ScGridWindow::Resize( const Size& )
501 // gar nix
504 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() ) )
513 break;
516 DELETEZ(pFilterBox);
517 DELETEZ(pFilterFloat);
519 while (false);
521 if (mpDPFieldPopup.get())
523 mpDPFieldPopup->close(false);
524 mpDPFieldPopup.reset();
528 IMPL_LINK( ScGridWindow, PopupModeEndHdl, FloatingWindow*, EMPTYARG )
530 if (pFilterBox)
531 pFilterBox->SetCancelled(); // nicht mehr auswaehlen
532 GrabFocus();
533 return 0;
536 IMPL_LINK( ScGridWindow, PopupSpellingHdl, SpellCallbackInfo*, pInfo )
538 if( pInfo->nCommand == SPELLCMD_STARTSPELLDLG )
539 pViewData->GetDispatcher().Execute( SID_SPELL_DIALOG, SFX_CALLMODE_ASYNCHRON );
540 return 0;
543 void ScGridWindow::ExecPageFieldSelect( SCCOL nCol, SCROW nRow, BOOL bHasSelection, const String& rStr )
545 //! gridwin2 ?
547 ScDocument* pDoc = pViewData->GetDocument();
548 SCTAB nTab = pViewData->GetTabNo();
549 ScDPObject* pDPObj = pDoc->GetDPAtCursor(nCol, nRow, nTab);
550 if ( pDPObj && nCol > 0 )
552 // look for the dimension header left of the drop-down arrow
553 USHORT nOrient = sheet::DataPilotFieldOrientation_HIDDEN;
554 long nField = pDPObj->GetHeaderDim( ScAddress( nCol-1, nRow, nTab ), nOrient );
555 if ( nField >= 0 && nOrient == sheet::DataPilotFieldOrientation_PAGE )
557 ScDPSaveData aSaveData( *pDPObj->GetSaveData() );
559 BOOL bIsDataLayout;
560 String aDimName = pDPObj->GetDimName( nField, bIsDataLayout );
561 if ( !bIsDataLayout )
563 ScDPSaveDimension* pDim = aSaveData.GetDimensionByName(aDimName);
565 if ( bHasSelection )
566 pDim->SetCurrentPage( &rStr );
567 else
568 pDim->SetCurrentPage( NULL );
570 ScDPObject aNewObj( *pDPObj );
571 aNewObj.SetSaveData( aSaveData );
572 ScDBDocFunc aFunc( *pViewData->GetDocShell() );
573 aFunc.DataPilotUpdate( pDPObj, &aNewObj, TRUE, FALSE );
574 pViewData->GetView()->CursorPosChanged(); // shells may be switched
580 void ScGridWindow::LaunchPageFieldMenu( SCCOL nCol, SCROW nRow )
582 //! merge position/size handling with DoAutoFilterMenue
584 delete pFilterBox;
585 delete pFilterFloat;
587 USHORT i;
588 ScDocument* pDoc = pViewData->GetDocument();
589 SCTAB nTab = pViewData->GetTabNo();
590 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
592 long nSizeX = 0;
593 long nSizeY = 0;
594 long nHeight = 0;
595 pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
596 Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich );
597 if ( bLayoutRTL )
598 aPos.X() -= nSizeX;
600 Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) );
602 aPos.X() -= 1;
603 aPos.Y() += nSizeY - 1;
605 pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) ); // not resizable etc.
606 pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) );
607 pFilterBox = new ScFilterListBox( pFilterFloat, this, nCol, nRow, SC_FILTERBOX_PAGEFIELD );
608 if ( bLayoutRTL )
609 pFilterBox->EnableMirroring();
611 nSizeX += 1;
614 Font aOldFont = GetFont(); SetFont( pFilterBox->GetFont() );
615 MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL );
617 nHeight = GetTextHeight();
618 nHeight *= SC_FILTERLISTBOX_LINES;
620 SetMapMode( aOldMode );
621 SetFont( aOldFont );
624 // SetSize comes later
626 TypedScStrCollection aStrings( 128, 128 );
628 // get list box entries and selection
629 BOOL bHasCurrentPage = FALSE;
630 String aCurrentPage;
631 ScDPObject* pDPObj = pDoc->GetDPAtCursor(nCol, nRow, nTab);
632 if ( pDPObj && nCol > 0 )
634 // look for the dimension header left of the drop-down arrow
635 USHORT nOrient = sheet::DataPilotFieldOrientation_HIDDEN;
636 long nField = pDPObj->GetHeaderDim( ScAddress( nCol-1, nRow, nTab ), nOrient );
637 if ( nField >= 0 && nOrient == sheet::DataPilotFieldOrientation_PAGE )
639 pDPObj->FillPageList( aStrings, nField );
641 // get current page from SaveData
643 ScDPSaveData* pSaveData = pDPObj->GetSaveData();
644 BOOL bIsDataLayout;
645 String aDimName = pDPObj->GetDimName( nField, bIsDataLayout );
646 if ( pSaveData && !bIsDataLayout )
648 ScDPSaveDimension* pDim = pSaveData->GetExistingDimensionByName(aDimName);
649 if ( pDim && pDim->HasCurrentPage() )
651 aCurrentPage = pDim->GetCurrentPage();
652 bHasCurrentPage = TRUE;
658 // include all entry widths for the size of the drop-down
659 long nMaxText = 0;
660 USHORT nCount = aStrings.GetCount();
661 for (i=0; i<nCount; i++)
663 TypedStrData* pData = aStrings[i];
664 long nTextWidth = pFilterBox->GetTextWidth( pData->GetString() );
665 if ( nTextWidth > nMaxText )
666 nMaxText = nTextWidth;
669 // add scrollbar width if needed (string entries are counted here)
670 // (scrollbar is shown if the box is exactly full?)
671 if ( nCount >= SC_FILTERLISTBOX_LINES )
672 nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize();
674 nMaxText += 4; // for borders
676 if ( nMaxText > nSizeX )
677 nSizeX = nMaxText; // just modify width - starting position is unchanged
679 // adjust position and size to window
681 Size aParentSize = GetParent()->GetOutputSizePixel();
682 Size aSize( nSizeX, nHeight );
684 if ( aSize.Height() > aParentSize.Height() )
685 aSize.Height() = aParentSize.Height();
686 if ( aPos.Y() + aSize.Height() > aParentSize.Height() )
687 aPos.Y() = aParentSize.Height() - aSize.Height();
689 pFilterBox->SetSizePixel( aSize );
690 pFilterBox->Show(); // Show must be called before SetUpdateMode
691 pFilterBox->SetUpdateMode(FALSE);
693 pFilterFloat->SetOutputSizePixel( aSize );
694 pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS);
696 // fill the list box
697 BOOL bWait = ( nCount > 100 );
699 if (bWait)
700 EnterWait();
702 for (i=0; i<nCount; i++)
703 pFilterBox->InsertEntry( aStrings[i]->GetString() );
705 pFilterBox->SetSeparatorPos( 0 );
707 if (bWait)
708 LeaveWait();
710 pFilterBox->SetUpdateMode(TRUE);
712 USHORT nSelPos = LISTBOX_ENTRY_NOTFOUND;
713 if (bHasCurrentPage)
714 nSelPos = pFilterBox->GetEntryPos( aCurrentPage );
716 if ( nSelPos == LISTBOX_ENTRY_NOTFOUND )
717 nSelPos = 0; // first entry
719 pFilterBox->GrabFocus();
721 // call Select after GrabFocus, so the focus rectangle ends up in the right position
722 if ( nSelPos != LISTBOX_ENTRY_NOTFOUND )
723 pFilterBox->SelectEntryPos( nSelPos );
725 pFilterBox->EndInit();
727 nMouseStatus = SC_GM_FILTER;
728 CaptureMouse();
731 void ScGridWindow::LaunchDPFieldMenu( SCCOL nCol, SCROW nRow )
733 SCTAB nTab = pViewData->GetTabNo();
734 ScDPObject* pDPObj = pViewData->GetDocument()->GetDPAtCursor(nCol, nRow, nTab);
735 if (!pDPObj)
736 return;
738 // Get the geometry of the cell.
739 Point aScrPos = pViewData->GetScrPos(nCol, nRow, eWhich);
740 long nSizeX, nSizeY;
741 pViewData->GetMergeSizePixel(nCol, nRow, nSizeX, nSizeY);
742 Size aScrSize(nSizeX-1, nSizeY-1);
744 DPLaunchFieldPopupMenu(OutputToScreenPixel(aScrPos), aScrSize, ScAddress(nCol, nRow, nTab), pDPObj);
747 void ScGridWindow::DoScenarioMenue( const ScRange& rScenRange )
749 delete pFilterBox;
750 delete pFilterFloat;
752 SCCOL nCol = rScenRange.aEnd.Col(); // Zelle unterhalb des Buttons
753 SCROW nRow = rScenRange.aStart.Row();
754 if (nRow == 0)
756 nRow = rScenRange.aEnd.Row() + 1; // Bereich ganz oben -> Button unterhalb
757 if (nRow>MAXROW) nRow = MAXROW;
758 //! Texthoehe addieren (wenn sie an der View gespeichert ist...)
761 ScDocument* pDoc = pViewData->GetDocument();
762 SCTAB nTab = pViewData->GetTabNo();
763 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
765 long nSizeX = 0;
766 long nSizeY = 0;
767 long nHeight = 0;
768 pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
769 Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich );
770 if ( bLayoutRTL )
771 aPos.X() -= nSizeX;
772 Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) );
773 aCellRect.Top() -= nSizeY;
774 aCellRect.Bottom() -= nSizeY - 1;
775 // Die ListBox direkt unter der schwarzen Linie auf dem Zellgitter
776 // (wenn die Linie verdeckt wird, sieht es komisch aus...)
778 pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) ); // nicht resizable etc.
779 pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) );
780 pFilterBox = new ScFilterListBox( pFilterFloat, this, nCol, nRow, SC_FILTERBOX_SCENARIO );
781 if ( bLayoutRTL )
782 pFilterBox->EnableMirroring();
784 nSizeX += 1;
787 Font aOldFont = GetFont(); SetFont( pFilterBox->GetFont() );
788 MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL );
790 nHeight = GetTextHeight();
791 nHeight *= SC_FILTERLISTBOX_LINES;
793 SetMapMode( aOldMode );
794 SetFont( aOldFont );
797 // SetSize spaeter
799 pFilterBox->SetSelectionMode( SINGLE_SELECTION );
800 pFilterBox->SetTabs( nFilterBoxTabs, MapUnit( MAP_APPFONT ));
801 pFilterBox->SetTabJustify( 1, bLayoutRTL ? AdjustRight : AdjustLeft );
804 // ParentSize Abfrage fehlt
805 Size aSize( nSizeX, nHeight );
806 pFilterBox->SetSizePixel( aSize );
807 pFilterBox->Show(); // Show muss vor SetUpdateMode kommen !!!
808 pFilterBox->SetUpdateMode(FALSE);
810 // SetOutputSizePixel/StartPopupMode erst unten, wenn die Groesse feststeht
812 // Listbox fuellen
814 long nMaxText = 0;
815 String aCurrent;
816 String aTabName;
817 SCTAB nTabCount = pDoc->GetTableCount();
818 SCTAB nEntryCount = 0;
819 for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
821 if (pDoc->HasScenarioRange( i, rScenRange ))
822 if (pDoc->GetName( i, aTabName ))
824 pFilterBox->InsertEntry( aTabName );
825 if (pDoc->IsActiveScenario(i))
826 aCurrent = aTabName;
827 long nTextWidth = pFilterBox->GetTextWidth( aTabName );
828 if ( nTextWidth > nMaxText )
829 nMaxText = nTextWidth;
830 ++nEntryCount;
833 if (nEntryCount > SC_FILTERLISTBOX_LINES)
834 nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize();
835 nMaxText += 4; // fuer Rand
836 if ( nMaxText > 300 )
837 nMaxText = 300; // auch nicht uebertreiben (Pixel)
839 if (nMaxText > nSizeX) // Groesse auf benoetigte Groesse anpassen
841 long nDiff = nMaxText - nSizeX;
842 aSize = Size( nMaxText, nHeight );
843 pFilterBox->SetSizePixel( aSize );
844 pFilterFloat->SetOutputSizePixel( aSize );
846 if ( !bLayoutRTL )
848 // also move popup position
849 long nNewX = aCellRect.Left() - nDiff;
850 if ( nNewX < 0 )
851 nNewX = 0;
852 aCellRect.Left() = nNewX;
856 pFilterFloat->SetOutputSizePixel( aSize );
857 pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS );
859 pFilterBox->SetUpdateMode(TRUE);
860 pFilterBox->GrabFocus();
862 // Select erst nach GrabFocus, damit das Focus-Rechteck richtig landet
863 //! SvLBoxEntry* pSelect = NULL;
864 USHORT nPos = LISTBOX_ENTRY_NOTFOUND;
865 if (aCurrent.Len())
867 nPos = pFilterBox->GetEntryPos( aCurrent );
868 //! pSelect = pFilterBox->GetEntry( nPos );
870 if (/*!pSelect*/ LISTBOX_ENTRY_NOTFOUND == nPos && pFilterBox->GetEntryCount() > 0 )
871 nPos = 0;
872 //! pSelect = pFilterBox->GetEntry(0); // einer sollte immer selektiert sein
873 if (/*pSelect*/ LISTBOX_ENTRY_NOTFOUND != nPos )
874 pFilterBox->SelectEntryPos(nPos);
876 pFilterBox->EndInit();
878 // Szenario-Auswahl kommt aus MouseButtonDown:
879 // der naechste MouseMove auf die Filterbox ist wie ein ButtonDown
881 nMouseStatus = SC_GM_FILTER;
882 CaptureMouse();
885 void ScGridWindow::DoAutoFilterMenue( SCCOL nCol, SCROW nRow, BOOL bDataSelect )
887 delete pFilterBox;
888 delete pFilterFloat;
890 USHORT i;
891 ScDocument* pDoc = pViewData->GetDocument();
892 SCTAB nTab = pViewData->GetTabNo();
893 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
895 long nSizeX = 0;
896 long nSizeY = 0;
897 long nHeight = 0;
898 pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
899 Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich );
900 if ( bLayoutRTL )
901 aPos.X() -= nSizeX;
903 Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) );
905 aPos.X() -= 1;
906 aPos.Y() += nSizeY - 1;
908 pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) ); // nicht resizable etc.
909 pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) );
910 pFilterBox = new ScFilterListBox(
911 pFilterFloat, this, nCol, nRow, bDataSelect ? SC_FILTERBOX_DATASELECT : SC_FILTERBOX_FILTER );
912 if ( bLayoutRTL )
913 pFilterBox->EnableMirroring();
915 nSizeX += 1;
918 Font aOldFont = GetFont(); SetFont( pFilterBox->GetFont() );
919 MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL );
921 nHeight = GetTextHeight();
922 nHeight *= SC_FILTERLISTBOX_LINES;
924 SetMapMode( aOldMode );
925 SetFont( aOldFont );
928 // SetSize spaeter
930 pFilterBox->SetSelectionMode( SINGLE_SELECTION );
931 pFilterBox->SetTabs( nFilterBoxTabs, MapUnit( MAP_APPFONT ));
932 pFilterBox->SetTabJustify( 1, bLayoutRTL ? AdjustRight : AdjustLeft );
935 BOOL bEmpty = FALSE;
936 TypedScStrCollection aStrings( 128, 128 );
937 if ( bDataSelect ) // Auswahl-Liste
939 // Liste fuellen
940 aStrings.SetCaseSensitive( TRUE );
941 pDoc->GetDataEntries( nCol, nRow, nTab, aStrings );
942 if ( aStrings.GetCount() == 0 )
943 bEmpty = TRUE;
945 else // AutoFilter
947 //! wird der Titel ueberhaupt ausgewertet ???
948 String aString;
949 pDoc->GetString( nCol, nRow, nTab, aString );
950 pFilterBox->SetText( aString );
952 long nMaxText = 0;
954 // default entries
955 static const USHORT nDefIDs[] = { SCSTR_ALLFILTER, SCSTR_TOP10FILTER, SCSTR_STDFILTER, SCSTR_EMPTY, SCSTR_NOTEMPTY };
956 const USHORT nDefCount = sizeof(nDefIDs) / sizeof(USHORT);
957 for (i=0; i<nDefCount; i++)
959 String aEntry( (ScResId) nDefIDs[i] );
960 pFilterBox->InsertEntry( aEntry );
961 long nTextWidth = pFilterBox->GetTextWidth( aEntry );
962 if ( nTextWidth > nMaxText )
963 nMaxText = nTextWidth;
965 pFilterBox->SetSeparatorPos( nDefCount - 1 );
967 // get list entries
968 bool bHasDates = false;
969 pDoc->GetFilterEntries( nCol, nRow, nTab, true, aStrings, bHasDates);
970 pFilterBox->SetListHasDates(bHasDates);
972 // check widths of numerical entries (string entries are not included)
973 // so all numbers are completely visible
974 USHORT nCount = aStrings.GetCount();
975 for (i=0; i<nCount; i++)
977 TypedStrData* pData = aStrings[i];
978 if ( !pData->IsStrData() ) // only numerical entries
980 long nTextWidth = pFilterBox->GetTextWidth( pData->GetString() );
981 if ( nTextWidth > nMaxText )
982 nMaxText = nTextWidth;
986 // add scrollbar width if needed (string entries are counted here)
987 // (scrollbar is shown if the box is exactly full?)
988 if ( nCount + nDefCount >= SC_FILTERLISTBOX_LINES )
989 nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize();
991 nMaxText += 4; // for borders
993 if ( nMaxText > nSizeX )
994 nSizeX = nMaxText; // just modify width - starting position is unchanged
997 if (!bEmpty)
999 // Position und Groesse an Fenster anpassen
1000 //! vorher Abfrage, ob die Eintraege hineinpassen (Breite)
1002 Size aParentSize = GetParent()->GetOutputSizePixel();
1003 Size aSize( nSizeX, nHeight );
1005 if ( aSize.Height() > aParentSize.Height() )
1006 aSize.Height() = aParentSize.Height();
1007 if ( aPos.Y() + aSize.Height() > aParentSize.Height() )
1008 aPos.Y() = aParentSize.Height() - aSize.Height();
1010 pFilterBox->SetSizePixel( aSize );
1011 pFilterBox->Show(); // Show muss vor SetUpdateMode kommen !!!
1012 pFilterBox->SetUpdateMode(FALSE);
1014 pFilterFloat->SetOutputSizePixel( aSize );
1015 pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS);
1017 // Listbox fuellen
1018 USHORT nCount = aStrings.GetCount();
1019 BOOL bWait = ( nCount > 100 );
1021 if (bWait)
1022 EnterWait();
1024 for (i=0; i<nCount; i++)
1025 pFilterBox->InsertEntry( aStrings[i]->GetString() );
1027 if (bWait)
1028 LeaveWait();
1030 pFilterBox->SetUpdateMode(TRUE);
1033 //! SvLBoxEntry* pSelect = NULL;
1034 USHORT nSelPos = LISTBOX_ENTRY_NOTFOUND;
1036 if (!bDataSelect) // AutoFilter: aktiven Eintrag selektieren
1038 ScDBData* pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab );
1039 if (pDBData)
1041 ScQueryParam aParam;
1042 pDBData->GetQueryParam( aParam ); // kann nur MAXQUERY Eintraege ergeben
1044 BOOL bValid = TRUE;
1045 for (SCSIZE j=0; j<MAXQUERY && bValid; j++) // bisherige Filter-Einstellungen
1046 if (aParam.GetEntry(j).bDoQuery)
1048 //! Abfrage mit DrawButtons zusammenfassen!
1050 ScQueryEntry& rEntry = aParam.GetEntry(j);
1051 if (j>0)
1052 if (rEntry.eConnect != SC_AND)
1053 bValid = FALSE;
1054 if (rEntry.nField == nCol)
1056 if (rEntry.eOp == SC_EQUAL)
1058 String* pStr = rEntry.pStr;
1059 if (pStr)
1061 nSelPos = pFilterBox->GetEntryPos( *pStr );
1062 //! pSelect = pFilterBox->GetEntry( nPos );
1065 else if (rEntry.eOp == SC_TOPVAL && rEntry.pStr &&
1066 rEntry.pStr->EqualsAscii("10"))
1067 nSelPos = SC_AUTOFILTER_TOP10;
1068 else
1069 nSelPos = SC_AUTOFILTER_CUSTOM;
1073 if (!bValid)
1074 nSelPos = SC_AUTOFILTER_CUSTOM;
1077 else
1080 ULONG nIndex = ((SfxUInt32Item*)pDoc->GetAttr(
1081 nCol, nRow, nTab, ATTR_VALIDDATA ))->GetValue();
1082 if ( nIndex )
1084 const ScValidationData* pData = pDoc->GetValidationEntry( nIndex );
1085 if (pData)
1087 TypedStrData* pNew = NULL;
1088 String aDocStr;
1089 pDoc->GetString( nCol, nRow, nTab, aDocStr );
1090 if ( pDoc->HasValueData( nCol, nRow, nTab ) )
1092 double fVal = pDoc->GetValue(ScAddress(nCol, nRow, nTab));
1093 pNew = new TypedStrData( aDocStr, fVal, SC_STRTYPE_VALUE );
1095 else
1096 pNew = new TypedStrData( aDocStr, 0.0, SC_STRTYPE_STANDARD );
1098 bool bSortList = ( pData->GetListType() == ValidListType::SORTEDASCENDING);
1099 if ( bSortList )
1101 USHORT nStrIndex;
1102 if (aStrings.Search(pNew,nStrIndex))
1103 nSelPos = nStrIndex;
1105 else
1107 USHORT nCount = aStrings.GetCount();
1108 for (i = 0; ((i < nCount) && ( LISTBOX_ENTRY_NOTFOUND == nSelPos)); i++)
1110 if ( aStrings.Compare(aStrings[i], pNew)==0 )
1111 nSelPos = i;
1114 delete pNew;
1119 // neu (309): irgendwas muss immer selektiert sein:
1120 if ( LISTBOX_ENTRY_NOTFOUND == nSelPos && pFilterBox->GetEntryCount() > 0 && !bDataSelect)
1121 nSelPos = 0;
1123 // keine leere Auswahl-Liste anzeigen:
1125 if ( bEmpty )
1127 DELETEZ(pFilterBox); // war nix
1128 DELETEZ(pFilterFloat);
1129 Sound::Beep(); // bemerkbar machen
1131 else
1133 // pFilterBox->Show(); // schon vorne
1134 pFilterBox->GrabFocus();
1136 // Select erst nach GrabFocus, damit das Focus-Rechteck richtig landet
1137 if ( LISTBOX_ENTRY_NOTFOUND != nSelPos )
1138 pFilterBox->SelectEntryPos( nSelPos );
1139 else
1141 if (bDataSelect)
1142 pFilterBox->SetNoSelection();
1145 pFilterBox->EndInit();
1147 if (!bDataSelect)
1149 // AutoFilter (aus MouseButtonDown):
1150 // der naechste MouseMove auf die Filterbox ist wie ein ButtonDown
1152 nMouseStatus = SC_GM_FILTER;
1153 CaptureMouse();
1158 void ScGridWindow::FilterSelect( ULONG nSel )
1160 String aString;
1162 SvLBoxEntry* pEntry = pFilterBox->GetEntry( nSel );
1163 if (pEntry)
1165 SvLBoxString* pStringEntry = (SvLBoxString*) pEntry->GetFirstItem( SV_ITEM_ID_LBOXSTRING );
1166 if ( pStringEntry )
1167 aString = pStringEntry->GetText();
1170 aString = pFilterBox->GetEntry( static_cast< USHORT >( nSel ) );
1172 SCCOL nCol = pFilterBox->GetCol();
1173 SCROW nRow = pFilterBox->GetRow();
1174 switch ( pFilterBox->GetMode() )
1176 case SC_FILTERBOX_DATASELECT:
1177 ExecDataSelect( nCol, nRow, aString );
1178 break;
1179 case SC_FILTERBOX_FILTER:
1180 ExecFilter( nSel, nCol, nRow, aString, pFilterBox->HasDates() );
1181 break;
1182 case SC_FILTERBOX_SCENARIO:
1183 pViewData->GetView()->UseScenario( aString );
1184 break;
1185 case SC_FILTERBOX_PAGEFIELD:
1186 // first entry is "all"
1187 ExecPageFieldSelect( nCol, nRow, (nSel != 0), aString );
1188 break;
1191 if (pFilterFloat)
1192 pFilterFloat->EndPopupMode();
1194 GrabFocus(); // unter OS/2 stimmt der Focus sonst nicht
1197 void ScGridWindow::ExecDataSelect( SCCOL nCol, SCROW nRow, const String& rStr )
1199 if ( rStr.Len() )
1201 SCTAB nTab = pViewData->GetTabNo();
1202 ScViewFunc* pView = pViewData->GetView();
1203 pView->EnterData( nCol, nRow, nTab, rStr );
1205 // #i52307# CellContentChanged is not in EnterData so it isn't called twice
1206 // if the cursor is moved afterwards.
1207 pView->CellContentChanged();
1211 void ScGridWindow::ExecFilter( ULONG nSel,
1212 SCCOL nCol, SCROW nRow,
1213 const String& aValue, bool bCheckForDates )
1215 SCTAB nTab = pViewData->GetTabNo();
1216 ScDocument* pDoc = pViewData->GetDocument();
1218 ScDBData* pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab );
1219 if (pDBData)
1221 ScQueryParam aParam;
1222 pDBData->GetQueryParam( aParam ); // kann nur MAXQUERY Eintraege ergeben
1224 if (SC_AUTOFILTER_CUSTOM == nSel)
1226 SCTAB nAreaTab;
1227 SCCOL nStartCol;
1228 SCROW nStartRow;
1229 SCCOL nEndCol;
1230 SCROW nEndRow;
1231 pDBData->GetArea( nAreaTab, nStartCol,nStartRow,nEndCol,nEndRow );
1232 pViewData->GetView()->MarkRange( ScRange( nStartCol,nStartRow,nAreaTab,nEndCol,nEndRow,nAreaTab));
1233 pViewData->GetView()->SetCursor(nCol,nRow); //! auch ueber Slot ??
1234 pViewData->GetDispatcher().Execute( SID_FILTER, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD );
1236 else
1238 BOOL bDeleteOld = FALSE;
1239 SCSIZE nQueryPos = 0;
1240 BOOL bFound = FALSE;
1241 if (!aParam.bInplace)
1242 bDeleteOld = TRUE;
1243 if (aParam.bRegExp)
1244 bDeleteOld = TRUE;
1245 for (SCSIZE i=0; i<MAXQUERY && !bDeleteOld; i++) // bisherige Filter-Einstellungen
1246 if (aParam.GetEntry(i).bDoQuery)
1248 //! Abfrage mit DrawButtons zusammenfassen!
1250 ScQueryEntry& rEntry = aParam.GetEntry(i);
1251 if (i>0)
1252 if (rEntry.eConnect != SC_AND)
1253 bDeleteOld = TRUE;
1255 if (rEntry.nField == nCol)
1257 if (bFound) // diese Spalte zweimal?
1258 bDeleteOld = TRUE;
1259 nQueryPos = i;
1260 bFound = TRUE;
1262 if (!bFound)
1263 nQueryPos = i + 1;
1266 if (bDeleteOld)
1268 SCSIZE nEC = aParam.GetEntryCount();
1269 for (SCSIZE i=0; i<nEC; i++)
1270 aParam.GetEntry(i).Clear();
1271 nQueryPos = 0;
1272 aParam.bInplace = TRUE;
1273 aParam.bRegExp = FALSE;
1276 if ( nQueryPos < MAXQUERY || SC_AUTOFILTER_ALL == nSel ) // loeschen geht immer
1278 if (nSel)
1280 ScQueryEntry& rNewEntry = aParam.GetEntry(nQueryPos);
1282 rNewEntry.bDoQuery = TRUE;
1283 rNewEntry.bQueryByString = TRUE;
1284 rNewEntry.nField = nCol;
1285 rNewEntry.bQueryByDate = bCheckForDates;
1286 if ( nSel == SC_AUTOFILTER_TOP10 )
1288 rNewEntry.eOp = SC_TOPVAL;
1289 *rNewEntry.pStr = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("10"));
1291 else if (nSel == SC_AUTOFILTER_EMPTY)
1293 rNewEntry.pStr->Erase();
1294 rNewEntry.bQueryByString = FALSE;
1295 rNewEntry.eOp = SC_EQUAL;
1296 rNewEntry.nVal = SC_EMPTYFIELDS;
1299 else if (nSel == SC_AUTOFILTER_NOTEMPTY)
1301 rNewEntry.pStr->Erase();
1302 rNewEntry.bQueryByString = FALSE;
1303 rNewEntry.eOp = SC_EQUAL;
1304 rNewEntry.nVal = SC_NONEMPTYFIELDS;
1306 else
1308 rNewEntry.eOp = SC_EQUAL;
1309 *rNewEntry.pStr = aValue;
1311 if (nQueryPos > 0)
1312 rNewEntry.eConnect = SC_AND;
1314 else
1316 if (bFound)
1317 aParam.DeleteQuery(nQueryPos);
1320 // #100597# end edit mode - like in ScCellShell::ExecuteDB
1321 if ( pViewData->HasEditView( pViewData->GetActivePart() ) )
1323 SC_MOD()->InputEnterHandler();
1324 pViewData->GetViewShell()->UpdateInputHandler();
1327 aParam.bUseDynamicRange = true;
1328 pViewData->GetView()->Query( aParam, NULL, TRUE );
1329 pDBData->SetQueryParam( aParam ); // speichern
1331 else // "Zuviele Bedingungen"
1332 pViewData->GetView()->ErrorMessage( STR_FILTER_TOOMANY );
1335 else
1337 DBG_ERROR("Wo ist der Datenbankbereich?");
1341 void ScGridWindow::SetPointer( const Pointer& rPointer )
1343 nCurrentPointer = 0;
1344 Window::SetPointer( rPointer );
1347 void ScGridWindow::MoveMouseStatus( ScGridWindow& rDestWin )
1349 if (nButtonDown)
1351 rDestWin.nButtonDown = nButtonDown;
1352 rDestWin.nMouseStatus = nMouseStatus;
1355 if (bRFMouse)
1357 rDestWin.bRFMouse = bRFMouse;
1358 rDestWin.bRFSize = bRFSize;
1359 rDestWin.nRFIndex = nRFIndex;
1360 rDestWin.nRFAddX = nRFAddX;
1361 rDestWin.nRFAddY = nRFAddY;
1362 bRFMouse = FALSE;
1365 if (nPagebreakMouse)
1367 rDestWin.nPagebreakMouse = nPagebreakMouse;
1368 rDestWin.nPagebreakBreak = nPagebreakBreak;
1369 rDestWin.nPagebreakPrev = nPagebreakPrev;
1370 rDestWin.aPagebreakSource = aPagebreakSource;
1371 rDestWin.aPagebreakDrag = aPagebreakDrag;
1372 nPagebreakMouse = SC_PD_NONE;
1376 BOOL ScGridWindow::TestMouse( const MouseEvent& rMEvt, BOOL bAction )
1378 // MouseEvent buttons must only be checked if bAction==TRUE
1379 // to allow changing the mouse pointer in MouseMove,
1380 // but not start AutoFill with right button (#74229#).
1381 // with bAction==TRUE, SetFillMode / SetDragMode is called
1383 if ( bAction && !rMEvt.IsLeft() )
1384 return FALSE;
1386 BOOL bNewPointer = FALSE;
1388 SfxInPlaceClient* pClient = pViewData->GetViewShell()->GetIPClient();
1389 BOOL bOleActive = ( pClient && pClient->IsObjectInPlaceActive() );
1391 if ( pViewData->IsActive() && !bOleActive )
1393 ScDocument* pDoc = pViewData->GetDocument();
1394 SCTAB nTab = pViewData->GetTabNo();
1395 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1396 long nLayoutSign = bLayoutRTL ? -1 : 1;
1398 // Auto-Fill
1400 ScRange aMarkRange;
1401 if (pViewData->GetSimpleArea( aMarkRange ) == SC_MARK_SIMPLE)
1403 if (aMarkRange.aStart.Tab() == pViewData->GetTabNo() && mpAutoFillRect)
1405 Point aMousePos = rMEvt.GetPosPixel();
1406 if (mpAutoFillRect->IsInside(aMousePos))
1408 SetPointer( Pointer( POINTER_CROSS ) ); //! dickeres Kreuz ?
1409 if (bAction)
1411 SCCOL nX = aMarkRange.aEnd.Col();
1412 SCROW nY = aMarkRange.aEnd.Row();
1414 if ( lcl_IsEditableMatrix( pViewData->GetDocument(), aMarkRange ) )
1415 pViewData->SetDragMode(
1416 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nX, nY, SC_FILL_MATRIX );
1417 else
1418 pViewData->SetFillMode(
1419 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nX, nY );
1421 // #108266# The simple selection must also be recognized when dragging,
1422 // where the Marking flag is set and MarkToSimple won't work anymore.
1423 pViewData->GetMarkData().MarkToSimple();
1425 bNewPointer = TRUE;
1430 // Embedded-Rechteck
1432 if (pDoc->IsEmbedded())
1434 ScRange aRange;
1435 pDoc->GetEmbedded( aRange );
1436 if ( pViewData->GetTabNo() == aRange.aStart.Tab() )
1438 Point aStartPos = pViewData->GetScrPos( aRange.aStart.Col(), aRange.aStart.Row(), eWhich );
1439 Point aEndPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aEnd.Row()+1, eWhich );
1440 Point aMousePos = rMEvt.GetPosPixel();
1441 if ( bLayoutRTL )
1443 aStartPos.X() += 2;
1444 aEndPos.X() += 2;
1446 BOOL bTop = ( aMousePos.X() >= aStartPos.X()-3 && aMousePos.X() <= aStartPos.X()+1 &&
1447 aMousePos.Y() >= aStartPos.Y()-3 && aMousePos.Y() <= aStartPos.Y()+1 );
1448 BOOL bBottom = ( aMousePos.X() >= aEndPos.X()-3 && aMousePos.X() <= aEndPos.X()+1 &&
1449 aMousePos.Y() >= aEndPos.Y()-3 && aMousePos.Y() <= aEndPos.Y()+1 );
1450 if ( bTop || bBottom )
1452 SetPointer( Pointer( POINTER_CROSS ) );
1453 if (bAction)
1455 BYTE nMode = bTop ? SC_FILL_EMBED_LT : SC_FILL_EMBED_RB;
1456 pViewData->SetDragMode(
1457 aRange.aStart.Col(), aRange.aStart.Row(),
1458 aRange.aEnd.Col(), aRange.aEnd.Row(), nMode );
1460 bNewPointer = TRUE;
1466 if (!bNewPointer && bAction)
1468 // SetPointer( POINTER_ARROW ); // in Fu...
1469 pViewData->ResetFillMode();
1472 return bNewPointer;
1475 void __EXPORT ScGridWindow::MouseButtonDown( const MouseEvent& rMEvt )
1477 nNestedButtonState = SC_NESTEDBUTTON_DOWN;
1479 HandleMouseButtonDown( rMEvt );
1481 if ( nNestedButtonState == SC_NESTEDBUTTON_UP )
1483 // #i41690# If an object is deactivated from MouseButtonDown, it might reschedule,
1484 // so MouseButtonUp comes before the MouseButtonDown call is finished. In this case,
1485 // simulate another MouseButtonUp call, so the selection state is consistent.
1487 nButtonDown = rMEvt.GetButtons();
1488 FakeButtonUp();
1490 if ( IsTracking() )
1491 EndTracking(); // normally done in VCL as part of MouseButtonUp handling
1493 nNestedButtonState = SC_NESTEDBUTTON_NONE;
1496 void ScGridWindow::HandleMouseButtonDown( const MouseEvent& rMEvt )
1498 // We have to check if a context menu is shown and we have an UI
1499 // active inplace client. In that case we have to ignore the event.
1500 // Otherwise we would crash (context menu has been
1501 // opened by inplace client and we would deactivate the inplace client,
1502 // the contex menu is closed by VCL asynchronously which in the end
1503 // would work on deleted objects or the context menu has no parent anymore)
1504 // See #126086# and #128122#
1505 SfxViewShell* pViewSh = pViewData->GetViewShell();
1506 SfxInPlaceClient* pClient = pViewSh->GetIPClient();
1507 if ( pClient &&
1508 pClient->IsObjectInPlaceActive() &&
1509 PopupMenu::IsInExecute() )
1510 return;
1512 aCurMousePos = rMEvt.GetPosPixel();
1514 // Filter-Popup beendet sich mit eigenem Mausklick, nicht erst beim Klick
1515 // in das GridWindow, darum ist die folgende Abfrage nicht mehr noetig:
1516 #if 0
1517 // merken, dass FilterBox geloescht wird, damit sichergestellt
1518 // ist, dass in diesem Handler nicht an gleicher Stelle wieder
1519 // eine neue geoeffnet wird.
1520 BOOL bWasFilterBox = ( pFilterBox != NULL &&
1521 ((Window*)pFilterBox)->IsVisible() &&
1522 !pFilterBox->IsDataSelect() );
1523 SCCOL nOldColFBox = bWasFilterBox ? pFilterBox->GetCol() : 0;
1524 SCROW nOldRowFBox = bWasFilterBox ? pFilterBox->GetRow() : 0;
1525 #endif
1526 #include "cellsuno.hxx"
1528 ClickExtern(); // loescht FilterBox, wenn vorhanden
1530 HideNoteMarker(); // Notiz-Anzeige
1532 bEEMouse = FALSE;
1534 ScModule* pScMod = SC_MOD();
1535 if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
1537 Sound::Beep();
1538 return;
1541 pScActiveViewShell = pViewData->GetViewShell(); // falls auf Link geklickt wird
1542 nScClickMouseModifier = rMEvt.GetModifier(); // um Control-Klick immer zu erkennen
1544 BOOL bDetective = pViewData->GetViewShell()->IsAuditShell();
1545 BOOL bRefMode = pViewData->IsRefMode(); // Referenz angefangen
1546 BOOL bFormulaMode = pScMod->IsFormulaMode(); // naechster Klick -> Referenz
1547 BOOL bEditMode = pViewData->HasEditView(eWhich); // auch bei Mode==SC_INPUT_TYPE
1548 BOOL bDouble = (rMEvt.GetClicks() == 2);
1550 // DeactivateIP passiert nur noch bei MarkListHasChanged
1552 // im GrabFocus Aufruf kann eine Fehlermeldung hochkommen
1553 // (z.B. beim Umbenennen von Tabellen per Tab-Reiter)
1555 if ( !nButtonDown || !bDouble ) // single (first) click is always valid
1556 nButtonDown = rMEvt.GetButtons(); // set nButtonDown first, so StopMarking works
1558 // pViewData->GetViewShell()->GetViewFrame()->GetWindow().GrabFocus();
1559 if ( ( bEditMode && pViewData->GetActivePart() == eWhich ) || !bFormulaMode )
1560 GrabFocus();
1562 // #i31846# need to cancel a double click if the first click has set the "ignore" state,
1563 // but a single (first) click is always valid
1564 if ( nMouseStatus == SC_GM_IGNORE && bDouble )
1566 nButtonDown = 0;
1567 nMouseStatus = SC_GM_NONE;
1568 return;
1571 if ( bDetective ) // Detektiv-Fuell-Modus
1573 if ( rMEvt.IsLeft() && !rMEvt.GetModifier() )
1575 Point aPos = rMEvt.GetPosPixel();
1576 SCsCOL nPosX;
1577 SCsROW nPosY;
1578 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
1580 SfxInt16Item aPosXItem( SID_RANGE_COL, nPosX );
1581 SfxInt32Item aPosYItem( SID_RANGE_ROW, nPosY );
1582 pViewData->GetDispatcher().Execute( SID_FILL_SELECT, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD,
1583 &aPosXItem, &aPosYItem, (void*)0L );
1586 nButtonDown = 0;
1587 nMouseStatus = SC_GM_NONE;
1588 return;
1591 if (!bDouble)
1592 nMouseStatus = SC_GM_NONE;
1594 if (!bFormulaMode)
1596 if ( pViewData->GetActivePart() != eWhich )
1597 pViewData->GetView()->ActivatePart( eWhich );
1599 else
1601 ScViewSelectionEngine* pSelEng = pViewData->GetView()->GetSelEngine();
1602 pSelEng->SetWindow(this);
1603 pSelEng->SetWhich(eWhich);
1604 pSelEng->SetVisibleArea( Rectangle(Point(), GetOutputSizePixel()) );
1607 if (bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()))
1609 Point aPos = rMEvt.GetPosPixel();
1610 SCsCOL nPosX;
1611 SCsROW nPosY;
1612 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
1614 EditView* pEditView;
1615 SCCOL nEditCol;
1616 SCROW nEditRow;
1617 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
1618 SCCOL nEndCol = pViewData->GetEditEndCol();
1619 SCROW nEndRow = pViewData->GetEditEndRow();
1621 if ( nPosX >= (SCsCOL) nEditCol && nPosX <= (SCsCOL) nEndCol &&
1622 nPosY >= (SCsROW) nEditRow && nPosY <= (SCsROW) nEndRow )
1624 // #53966# beim Klick in die Tabellen-EditView immer den Focus umsetzen
1625 if (bFormulaMode) // sonst ist es oben schon passiert
1626 GrabFocus();
1628 pScMod->SetInputMode( SC_INPUT_TABLE );
1629 bEEMouse = TRUE;
1630 bEditMode = pEditView->MouseButtonDown( rMEvt );
1631 return;
1635 if (pScMod->GetIsWaterCan())
1637 //! was is mit'm Mac ???
1638 if ( rMEvt.GetModifier() + rMEvt.GetButtons() == MOUSE_RIGHT )
1640 nMouseStatus = SC_GM_WATERUNDO;
1641 return;
1645 // Reihenfolge passend zum angezeigten Cursor:
1646 // RangeFinder, AutoFill, PageBreak, Drawing
1648 if ( HitRangeFinder( rMEvt.GetPosPixel(), bRFSize, &nRFIndex, &nRFAddX, &nRFAddY ) )
1650 bRFMouse = TRUE; // die anderen Variablen sind oben initialisiert
1652 if ( pViewData->GetActivePart() != eWhich )
1653 pViewData->GetView()->ActivatePart( eWhich ); //! schon oben immer ???
1655 // CaptureMouse();
1656 StartTracking();
1657 return;
1660 BOOL bCrossPointer = TestMouse( rMEvt, TRUE );
1661 if ( bCrossPointer )
1663 if ( bDouble )
1664 pViewData->GetView()->FillCrossDblClick();
1665 else
1666 pScMod->InputEnterHandler(); // Autofill etc.
1669 if ( !bCrossPointer )
1671 nPagebreakMouse = HitPageBreak( rMEvt.GetPosPixel(), &aPagebreakSource,
1672 &nPagebreakBreak, &nPagebreakPrev );
1673 if (nPagebreakMouse)
1675 bPagebreakDrawn = FALSE;
1676 // CaptureMouse();
1677 StartTracking();
1678 PagebreakMove( rMEvt, FALSE );
1679 return;
1683 if (!bFormulaMode && !bEditMode && rMEvt.IsLeft())
1685 if ( !bCrossPointer && DrawMouseButtonDown(rMEvt) )
1687 //if (DrawHasMarkedObj())
1688 // pViewData->GetViewShell()->SetDrawShellOrSub(); // Draw-Objekt selektiert
1689 return;
1692 pViewData->GetViewShell()->SetDrawShell( FALSE ); // kein Draw-Objekt selektiert
1694 // TestMouse schon oben passiert
1697 Point aPos = rMEvt.GetPosPixel();
1698 SCsCOL nPosX;
1699 SCsROW nPosY;
1700 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
1701 SCTAB nTab = pViewData->GetTabNo();
1702 ScDocument* pDoc = pViewData->GetDocument();
1706 // AutoFilter buttons
1709 if ( !bDouble && !bFormulaMode && rMEvt.IsLeft() )
1711 ScMergeFlagAttr* pAttr = (ScMergeFlagAttr*)
1712 pDoc->GetAttr( nPosX, nPosY, nTab, ATTR_MERGE_FLAG );
1713 if (pAttr->HasAutoFilter())
1715 if (DoAutoFilterButton(nPosX, nPosY, rMEvt))
1716 return;
1718 if (pAttr->HasButton())
1720 DoPushButton( nPosX, nPosY, rMEvt ); // setzt evtl. bPivotMouse / bDPMouse
1721 return;
1724 // List Validity drop-down button
1726 if ( bListValButton )
1728 Rectangle aButtonRect = GetListValButtonRect( aListValPos );
1729 if ( aButtonRect.IsInside( aPos ) )
1731 DoAutoFilterMenue( aListValPos.Col(), aListValPos.Row(), TRUE );
1733 nMouseStatus = SC_GM_FILTER; // not set in DoAutoFilterMenue for bDataSelect
1734 CaptureMouse();
1735 return;
1741 // scenario selection
1744 ScRange aScenRange;
1745 if ( rMEvt.IsLeft() && HasScenarioButton( aPos, aScenRange ) )
1747 DoScenarioMenue( aScenRange );
1748 return;
1752 // Doppelklick angefangen ?
1755 // StopMarking kann aus DrawMouseButtonDown gerufen werden
1757 if ( nMouseStatus != SC_GM_IGNORE && !bRefMode )
1759 if ( bDouble && !bCrossPointer )
1761 if (nMouseStatus == SC_GM_TABDOWN)
1762 nMouseStatus = SC_GM_DBLDOWN;
1764 else
1765 nMouseStatus = SC_GM_TABDOWN;
1769 // Links in Edit-Zellen
1772 BOOL bAlt = rMEvt.IsMod2();
1773 if ( !bAlt && rMEvt.IsLeft() &&
1774 GetEditUrl(rMEvt.GetPosPixel()) ) // Klick auf Link: Cursor nicht bewegen
1776 SetPointer( Pointer( POINTER_REFHAND ) );
1777 nMouseStatus = SC_GM_URLDOWN; // auch nur dann beim ButtonUp ausfuehren
1778 return;
1782 // Gridwin - SelectionEngine
1785 if ( rMEvt.IsLeft() )
1787 ScViewSelectionEngine* pSelEng = pViewData->GetView()->GetSelEngine();
1788 pSelEng->SetWindow(this);
1789 pSelEng->SetWhich(eWhich);
1790 pSelEng->SetVisibleArea( Rectangle(Point(), GetOutputSizePixel()) );
1792 // SelMouseButtonDown an der View setzt noch das bMoveIsShift Flag
1793 if ( pViewData->GetView()->SelMouseButtonDown( rMEvt ) )
1795 if (IsMouseCaptured())
1797 // Tracking statt CaptureMouse, damit sauber abgebrochen werden kann
1798 //! Irgendwann sollte die SelectionEngine selber StartTracking rufen!?!
1799 ReleaseMouse();
1800 StartTracking();
1802 pViewData->GetMarkData().SetMarking(TRUE);
1803 return;
1808 void __EXPORT ScGridWindow::MouseButtonUp( const MouseEvent& rMEvt )
1810 aCurMousePos = rMEvt.GetPosPixel();
1811 ScDocument* pDoc = pViewData->GetDocument();
1812 ScMarkData& rMark = pViewData->GetMarkData();
1814 // #i41690# detect a MouseButtonUp call from within MouseButtonDown
1815 // (possible through Reschedule from storing an OLE object that is deselected)
1817 if ( nNestedButtonState == SC_NESTEDBUTTON_DOWN )
1818 nNestedButtonState = SC_NESTEDBUTTON_UP;
1820 if (nButtonDown != rMEvt.GetButtons())
1821 nMouseStatus = SC_GM_IGNORE; // reset und return
1823 nButtonDown = 0;
1825 if (nMouseStatus == SC_GM_IGNORE)
1827 nMouseStatus = SC_GM_NONE;
1828 // Selection-Engine: Markieren abbrechen
1829 pViewData->GetView()->GetSelEngine()->Reset();
1830 rMark.SetMarking(FALSE);
1831 if (pViewData->IsAnyFillMode())
1833 pViewData->GetView()->StopRefMode();
1834 pViewData->ResetFillMode();
1836 StopMarking();
1837 DrawEndAction(); // Markieren/Verschieben auf Drawing-Layer abbrechen
1838 ReleaseMouse();
1839 return;
1842 if (nMouseStatus == SC_GM_FILTER)
1844 if ( pFilterBox && pFilterBox->GetMode() == SC_FILTERBOX_FILTER )
1846 if (mpFilterButton.get())
1848 bool bFilterActive = IsAutoFilterActive(
1849 pFilterBox->GetCol(), pFilterBox->GetRow(), pViewData->GetTabNo() );
1851 mpFilterButton->setHasHiddenMember(bFilterActive);
1852 mpFilterButton->setPopupPressed(false);
1853 HideCursor();
1854 mpFilterButton->draw();
1855 ShowCursor();
1858 nMouseStatus = SC_GM_NONE;
1859 ReleaseMouse();
1860 return; // da muss nix mehr passieren
1863 ScModule* pScMod = SC_MOD();
1864 if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
1865 return;
1867 SfxBindings& rBindings = pViewData->GetBindings();
1868 if (bEEMouse && pViewData->HasEditView( eWhich ))
1870 EditView* pEditView;
1871 SCCOL nEditCol;
1872 SCROW nEditRow;
1873 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
1874 pEditView->MouseButtonUp( rMEvt );
1876 if ( rMEvt.IsMiddle() &&
1877 GetSettings().GetMouseSettings().GetMiddleButtonAction() == MOUSE_MIDDLE_PASTESELECTION )
1879 // EditView may have pasted from selection
1880 pScMod->InputChanged( pEditView );
1882 else
1883 pScMod->InputSelection( pEditView ); // parentheses etc.
1885 pViewData->GetView()->InvalidateAttribs();
1886 rBindings.Invalidate( SID_HYPERLINK_GETLINK );
1887 bEEMouse = FALSE;
1888 return;
1891 if (bDPMouse)
1893 DPMouseButtonUp( rMEvt ); // resets bDPMouse
1894 return;
1897 if (bRFMouse)
1899 RFMouseMove( rMEvt, TRUE ); // Range wieder richtigherum
1900 bRFMouse = FALSE;
1901 SetPointer( Pointer( POINTER_ARROW ) );
1902 ReleaseMouse();
1903 return;
1906 if (nPagebreakMouse)
1908 PagebreakMove( rMEvt, TRUE );
1909 nPagebreakMouse = SC_PD_NONE;
1910 SetPointer( Pointer( POINTER_ARROW ) );
1911 ReleaseMouse();
1912 return;
1915 if (nMouseStatus == SC_GM_WATERUNDO) // Undo im Giesskannenmodus
1917 SfxUndoManager* pMgr = pViewData->GetDocShell()->GetUndoManager();
1918 if ( pMgr->GetUndoActionCount() && pMgr->GetUndoActionId() == STR_UNDO_APPLYCELLSTYLE )
1919 pMgr->Undo();
1920 else
1921 Sound::Beep();
1922 return;
1925 if (DrawMouseButtonUp(rMEvt)) // includes format paint brush handling for drawing objects
1926 return;
1928 rMark.SetMarking(FALSE);
1930 SetPointer( Pointer( POINTER_ARROW ) );
1932 if (pViewData->IsFillMode() ||
1933 ( pViewData->GetFillMode() == SC_FILL_MATRIX && rMEvt.IsMod1() ))
1935 nScFillModeMouseModifier = rMEvt.GetModifier();
1936 SCCOL nStartCol;
1937 SCROW nStartRow;
1938 SCCOL nEndCol;
1939 SCROW nEndRow;
1940 pViewData->GetFillData( nStartCol, nStartRow, nEndCol, nEndRow );
1941 // DBG_ASSERT( nStartCol==pViewData->GetRefStartX() && nStartRow==pViewData->GetRefStartY(),
1942 // "Block falsch fuer AutoFill" );
1943 ScRange aDelRange;
1944 BOOL bIsDel = pViewData->GetDelMark( aDelRange );
1946 ScViewFunc* pView = pViewData->GetView();
1947 pView->StopRefMode();
1948 pViewData->ResetFillMode();
1949 pView->GetFunctionSet()->SetAnchorFlag( FALSE ); // #i5819# don't use AutoFill anchor flag for selection
1951 if ( bIsDel )
1953 pView->MarkRange( aDelRange, FALSE );
1954 pView->DeleteContents( IDF_CONTENTS );
1955 SCTAB nTab = pViewData->GetTabNo();
1956 ScRange aBlockRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab );
1957 if ( aBlockRange != aDelRange )
1959 if ( aDelRange.aStart.Row() == nStartRow )
1960 aBlockRange.aEnd.SetCol( aDelRange.aStart.Col() - 1 );
1961 else
1962 aBlockRange.aEnd.SetRow( aDelRange.aStart.Row() - 1 );
1963 pView->MarkRange( aBlockRange, FALSE );
1966 else
1967 pViewData->GetDispatcher().Execute( FID_FILL_AUTO, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD );
1969 else if (pViewData->GetFillMode() == SC_FILL_MATRIX)
1971 SCTAB nTab = pViewData->GetTabNo();
1972 SCCOL nStartCol;
1973 SCROW nStartRow;
1974 SCCOL nEndCol;
1975 SCROW nEndRow;
1976 pViewData->GetFillData( nStartCol, nStartRow, nEndCol, nEndRow );
1977 ScRange aBlockRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab );
1978 SCCOL nFillCol = pViewData->GetRefEndX();
1979 SCROW nFillRow = pViewData->GetRefEndY();
1980 ScAddress aEndPos( nFillCol, nFillRow, nTab );
1982 ScTabView* pView = pViewData->GetView();
1983 pView->StopRefMode();
1984 pViewData->ResetFillMode();
1985 pView->GetFunctionSet()->SetAnchorFlag( FALSE );
1987 if ( aEndPos != aBlockRange.aEnd )
1989 pViewData->GetDocShell()->GetDocFunc().ResizeMatrix( aBlockRange, aEndPos, FALSE );
1990 pViewData->GetView()->MarkRange( ScRange( aBlockRange.aStart, aEndPos ) );
1993 else if (pViewData->IsAnyFillMode())
1995 // Embedded-Area has been changed
1996 ScTabView* pView = pViewData->GetView();
1997 pView->StopRefMode();
1998 pViewData->ResetFillMode();
1999 pView->GetFunctionSet()->SetAnchorFlag( FALSE );
2000 pViewData->GetDocShell()->UpdateOle(pViewData);
2003 BOOL bRefMode = pViewData->IsRefMode();
2004 if (bRefMode)
2005 pScMod->EndReference();
2008 // Giesskannen-Modus (Gestalter)
2011 if (pScMod->GetIsWaterCan())
2013 // Abfrage auf Undo schon oben
2015 ScStyleSheetPool* pStylePool = (ScStyleSheetPool*)
2016 (pViewData->GetDocument()->
2017 GetStyleSheetPool());
2018 if ( pStylePool )
2020 SfxStyleSheet* pStyleSheet = (SfxStyleSheet*)
2021 pStylePool->GetActualStyleSheet();
2023 if ( pStyleSheet )
2025 SfxStyleFamily eFamily = pStyleSheet->GetFamily();
2027 switch ( eFamily )
2029 case SFX_STYLE_FAMILY_PARA:
2030 pViewData->GetView()->SetStyleSheetToMarked( pStyleSheet );
2031 pViewData->GetView()->DoneBlockMode();
2032 break;
2034 case SFX_STYLE_FAMILY_PAGE:
2035 pViewData->GetDocument()->SetPageStyle( pViewData->GetTabNo(),
2036 pStyleSheet->GetName() );
2038 ScPrintFunc( pViewData->GetDocShell(),
2039 pViewData->GetViewShell()->GetPrinter(TRUE),
2040 pViewData->GetTabNo() ).UpdatePages();
2042 rBindings.Invalidate( SID_STATUS_PAGESTYLE );
2043 break;
2045 default:
2046 break;
2052 ScDBFunc* pView = pViewData->GetView();
2053 ScDocument* pBrushDoc = pView->GetBrushDocument();
2054 if ( pBrushDoc )
2056 pView->PasteFromClip( IDF_ATTRIB, pBrushDoc );
2057 if ( !pView->IsPaintBrushLocked() )
2058 pView->ResetBrushDocument(); // invalidates pBrushDoc pointer
2062 // double click (only left button)
2065 BOOL bDouble = ( rMEvt.GetClicks() == 2 && rMEvt.IsLeft() );
2066 if ( bDouble && !bRefMode && nMouseStatus == SC_GM_DBLDOWN && !pScMod->IsRefDialogOpen() )
2068 // data pilot table
2069 Point aPos = rMEvt.GetPosPixel();
2070 SCsCOL nPosX;
2071 SCsROW nPosY;
2072 SCTAB nTab = pViewData->GetTabNo();
2073 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
2074 ScDPObject* pDPObj = pDoc->GetDPAtCursor( nPosX, nPosY, nTab );
2075 if ( pDPObj && pDPObj->GetSaveData()->GetDrillDown() )
2077 ScAddress aCellPos( nPosX, nPosY, pViewData->GetTabNo() );
2079 // Check for header drill-down first.
2080 sheet::DataPilotTableHeaderData aData;
2081 pDPObj->GetHeaderPositionData(aCellPos, aData);
2083 if ( ( aData.Flags & sheet::MemberResultFlags::HASMEMBER ) &&
2084 ! ( aData.Flags & sheet::MemberResultFlags::SUBTOTAL ) )
2086 USHORT nDummy;
2087 if ( pView->HasSelectionForDrillDown( nDummy ) )
2089 // execute slot to show dialog
2090 pViewData->GetDispatcher().Execute( SID_OUTLINE_SHOW, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD );
2092 else
2094 // toggle single entry
2095 ScDPObject aNewObj( *pDPObj );
2096 pDPObj->ToggleDetails( aData, &aNewObj );
2097 ScDBDocFunc aFunc( *pViewData->GetDocShell() );
2098 aFunc.DataPilotUpdate( pDPObj, &aNewObj, TRUE, FALSE );
2099 pViewData->GetView()->CursorPosChanged(); // shells may be switched
2102 else
2104 // Check if the data area is double-clicked.
2106 Sequence<sheet::DataPilotFieldFilter> aFilters;
2107 if ( pDPObj->GetDataFieldPositionData(aCellPos, aFilters) )
2108 pViewData->GetView()->ShowDataPilotSourceData( *pDPObj, aFilters );
2109 else
2110 Sound::Beep(); // nothing to expand/collapse/show
2113 return;
2116 // Check for cell protection attribute.
2117 ScTableProtection* pProtect = pDoc->GetTabProtection( nTab );
2118 bool bEditAllowed = true;
2119 if ( pProtect && pProtect->isProtected() )
2121 bool bCellProtected = pDoc->HasAttrib(nPosX, nPosY, nTab, nPosX, nPosY, nTab, HASATTR_PROTECTED);
2122 bool bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
2123 bool bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
2125 if ( bSkipProtected && bSkipUnprotected )
2126 bEditAllowed = false;
2127 else if ( (bCellProtected && bSkipProtected) || (!bCellProtected && bSkipUnprotected) )
2128 bEditAllowed = false;
2131 if ( bEditAllowed )
2133 // edit cell contents
2134 pViewData->GetViewShell()->UpdateInputHandler();
2135 pScMod->SetInputMode( SC_INPUT_TABLE );
2136 if (pViewData->HasEditView(eWhich))
2138 // Text-Cursor gleich an die geklickte Stelle setzen
2139 EditView* pEditView = pViewData->GetEditView( eWhich );
2140 MouseEvent aEditEvt( rMEvt.GetPosPixel(), 1, MOUSE_SYNTHETIC, MOUSE_LEFT, 0 );
2141 pEditView->MouseButtonDown( aEditEvt );
2142 pEditView->MouseButtonUp( aEditEvt );
2145 return;
2149 // Links in edit cells
2152 BOOL bAlt = rMEvt.IsMod2();
2153 if ( !bAlt && !bRefMode && !bDouble && nMouseStatus == SC_GM_URLDOWN )
2155 // beim ButtonUp nur ausfuehren, wenn ButtonDown auch ueber einer URL war
2157 String aName, aUrl, aTarget;
2158 if ( GetEditUrl( rMEvt.GetPosPixel(), &aName, &aUrl, &aTarget ) )
2160 nMouseStatus = SC_GM_NONE; // keinen Doppelklick anfangen
2161 ScGlobal::OpenURL( aUrl, aTarget );
2163 // fire worksheet_followhyperlink event
2164 Point aPos = rMEvt.GetPosPixel();
2165 SCsCOL nPosX;
2166 SCsROW nPosY;
2167 SCTAB nTab = pViewData->GetTabNo();
2168 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
2169 ScBaseCell* pCell = NULL;
2171 BOOL bFound = lcl_GetHyperlinkCell( pDoc, nPosX, nPosY, nTab, pCell );
2172 if( bFound )
2174 ScAddress aCellPos( nPosX, nPosY, nTab );
2175 ScCellObj* pObj = new ScCellObj( pViewData->GetDocShell(), aCellPos );
2176 uno::Sequence< uno::Any > aArgs(1);
2177 aArgs[0] = uno::makeAny(uno::Reference<uno::XInterface>(static_cast<cppu::OWeakObject*>(pObj)));
2178 uno::Reference< document::XVbaEventsHelper > xVbaEventsHelper ( pViewData->GetDocument()->GetVbaEventsHelper(), uno::UNO_QUERY );
2179 if( xVbaEventsHelper.is() )
2180 xVbaEventsHelper->ProcessCompatibleVbaEvent( VBAEVENT_WORKSHEET_FOLLOWHYPERLINK, aArgs );
2182 return;
2187 // Gridwin - SelectionEngine
2190 // SelMouseButtonDown is called only for left button, but SelMouseButtonUp would return
2191 // TRUE for any call, so IsLeft must be checked here, too.
2193 if ( rMEvt.IsLeft() && pViewData->GetView()->GetSelEngine()->SelMouseButtonUp( rMEvt ) )
2195 // rMark.MarkToSimple();
2196 pViewData->GetView()->UpdateAutoFillMark();
2198 SfxDispatcher* pDisp = pViewData->GetViewShell()->GetDispatcher();
2199 BOOL bFormulaMode = pScMod->IsFormulaMode();
2200 DBG_ASSERT( pDisp || bFormulaMode, "Cursor auf nicht aktiver View bewegen ?" );
2202 // #i14927# execute SID_CURRENTCELL (for macro recording) only if there is no
2203 // multiple selection, so the argument string completely describes the selection,
2204 // and executing the slot won't change the existing selection (executing the slot
2205 // here and from a recorded macro is treated equally)
2207 if ( pDisp && !bFormulaMode && !rMark.IsMultiMarked() )
2209 String aAddr; // CurrentCell
2210 if( rMark.IsMarked() )
2212 // BOOL bKeep = rMark.IsMultiMarked(); //! wohin damit ???
2214 ScRange aScRange;
2215 rMark.GetMarkArea( aScRange );
2216 aScRange.Format( aAddr, SCR_ABS );
2217 if ( aScRange.aStart == aScRange.aEnd )
2219 // make sure there is a range selection string even for a single cell
2220 String aSingle = aAddr;
2221 aAddr.Append( (sal_Char) ':' );
2222 aAddr.Append( aSingle );
2225 //! SID_MARKAREA gibts nicht mehr ???
2226 //! was passiert beim Markieren mit dem Cursor ???
2228 else // nur Cursor bewegen
2230 ScAddress aScAddress( pViewData->GetCurX(), pViewData->GetCurY(), 0 );
2231 aScAddress.Format( aAddr, SCA_ABS );
2234 SfxStringItem aPosItem( SID_CURRENTCELL, aAddr );
2235 // We don't want to align to the cursor position because if the
2236 // cell cursor isn't visible after making selection, it would jump
2237 // back to the origin of the selection where the cell cursor is.
2238 SfxBoolItem aAlignCursorItem( FN_PARAM_2, false );
2239 pDisp->Execute( SID_CURRENTCELL, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD,
2240 &aPosItem, &aAlignCursorItem, (void*)0L );
2242 pViewData->GetView()->InvalidateAttribs();
2244 return;
2248 void ScGridWindow::FakeButtonUp()
2250 if ( nButtonDown )
2252 MouseEvent aEvent( aCurMousePos ); // nButtons = 0 -> ignore
2253 MouseButtonUp( aEvent );
2257 void __EXPORT ScGridWindow::MouseMove( const MouseEvent& rMEvt )
2259 aCurMousePos = rMEvt.GetPosPixel();
2261 if ( rMEvt.IsLeaveWindow() && pNoteMarker && !pNoteMarker->IsByKeyboard() )
2262 HideNoteMarker();
2264 ScModule* pScMod = SC_MOD();
2265 if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
2266 return;
2268 // Ob aus dem Edit-Modus Drag&Drop gestartet wurde, bekommt man leider
2269 // nicht anders mit:
2271 if (bEEMouse && nButtonDown && !rMEvt.GetButtons())
2273 bEEMouse = FALSE;
2274 nButtonDown = 0;
2275 nMouseStatus = SC_GM_NONE;
2276 return;
2279 if (nMouseStatus == SC_GM_IGNORE)
2280 return;
2282 if (nMouseStatus == SC_GM_WATERUNDO) // Undo im Giesskannenmodus -> nur auf Up warten
2283 return;
2285 if ( pViewData->GetViewShell()->IsAuditShell() ) // Detektiv-Fuell-Modus
2287 SetPointer( Pointer( POINTER_FILL ) );
2288 return;
2291 if (nMouseStatus == SC_GM_FILTER && pFilterBox)
2293 Point aRelPos = pFilterBox->ScreenToOutputPixel( OutputToScreenPixel( rMEvt.GetPosPixel() ) );
2294 if ( Rectangle(Point(),pFilterBox->GetOutputSizePixel()).IsInside(aRelPos) )
2296 nButtonDown = 0;
2297 nMouseStatus = SC_GM_NONE;
2298 if ( pFilterBox->GetMode() == SC_FILTERBOX_FILTER )
2300 if (mpFilterButton.get())
2302 mpFilterButton->setHasHiddenMember(false);
2303 mpFilterButton->setPopupPressed(false);
2304 HideCursor();
2305 mpFilterButton->draw();
2306 ShowCursor();
2309 ReleaseMouse();
2310 pFilterBox->MouseButtonDown( MouseEvent( aRelPos, 1, MOUSE_SIMPLECLICK, MOUSE_LEFT ) );
2311 return;
2315 BOOL bFormulaMode = pScMod->IsFormulaMode(); // naechster Klick -> Referenz
2317 if (bEEMouse && pViewData->HasEditView( eWhich ))
2319 EditView* pEditView;
2320 SCCOL nEditCol;
2321 SCROW nEditRow;
2322 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
2323 pEditView->MouseMove( rMEvt );
2324 return;
2327 if (bDPMouse)
2329 DPMouseMove( rMEvt );
2330 return;
2333 if (bRFMouse)
2335 RFMouseMove( rMEvt, FALSE );
2336 return;
2339 if (nPagebreakMouse)
2341 PagebreakMove( rMEvt, FALSE );
2342 return;
2345 // anderen Mauszeiger anzeigen?
2347 BOOL bEditMode = pViewData->HasEditView(eWhich);
2349 //! Testen ob RefMode-Dragging !!!
2350 if ( bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()) )
2352 Point aPos = rMEvt.GetPosPixel();
2353 SCsCOL nPosX;
2354 SCsROW nPosY;
2355 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
2357 EditView* pEditView;
2358 SCCOL nEditCol;
2359 SCROW nEditRow;
2360 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
2361 SCCOL nEndCol = pViewData->GetEditEndCol();
2362 SCROW nEndRow = pViewData->GetEditEndRow();
2364 if ( nPosX >= (SCsCOL) nEditCol && nPosX <= (SCsCOL) nEndCol &&
2365 nPosY >= (SCsROW) nEditRow && nPosY <= (SCsROW) nEndRow )
2367 // Field can only be URL field
2368 BOOL bAlt = rMEvt.IsMod2();
2369 if ( !bAlt && !nButtonDown && pEditView && pEditView->GetFieldUnderMousePointer() )
2370 SetPointer( Pointer( POINTER_REFHAND ) );
2371 else if ( pEditView && pEditView->GetEditEngine()->IsVertical() )
2372 SetPointer( Pointer( POINTER_TEXT_VERTICAL ) );
2373 else
2374 SetPointer( Pointer( POINTER_TEXT ) );
2375 return;
2379 BOOL bWater = SC_MOD()->GetIsWaterCan() || pViewData->GetView()->HasPaintBrush();
2380 if (bWater)
2381 SetPointer( Pointer(POINTER_FILL) );
2383 if (!bWater)
2385 BOOL bCross = FALSE;
2387 // Range-Finder
2389 BOOL bCorner;
2390 if ( HitRangeFinder( rMEvt.GetPosPixel(), bCorner ) )
2392 if (bCorner)
2393 SetPointer( Pointer( POINTER_CROSS ) );
2394 else
2395 SetPointer( Pointer( POINTER_HAND ) );
2396 bCross = TRUE;
2399 // Page-Break-Modus
2401 USHORT nBreakType;
2402 if ( !nButtonDown && pViewData->IsPagebreakMode() &&
2403 ( nBreakType = HitPageBreak( rMEvt.GetPosPixel() ) ) != 0 )
2405 PointerStyle eNew = POINTER_ARROW;
2406 switch ( nBreakType )
2408 case SC_PD_RANGE_L:
2409 case SC_PD_RANGE_R:
2410 case SC_PD_BREAK_H:
2411 eNew = POINTER_ESIZE;
2412 break;
2413 case SC_PD_RANGE_T:
2414 case SC_PD_RANGE_B:
2415 case SC_PD_BREAK_V:
2416 eNew = POINTER_SSIZE;
2417 break;
2418 case SC_PD_RANGE_TL:
2419 case SC_PD_RANGE_BR:
2420 eNew = POINTER_SESIZE;
2421 break;
2422 case SC_PD_RANGE_TR:
2423 case SC_PD_RANGE_BL:
2424 eNew = POINTER_NESIZE;
2425 break;
2427 SetPointer( Pointer( eNew ) );
2428 bCross = TRUE;
2431 // Fill-Cursor anzeigen ?
2433 if ( !bFormulaMode && !nButtonDown )
2434 if (TestMouse( rMEvt, FALSE ))
2435 bCross = TRUE;
2437 if ( nButtonDown && pViewData->IsAnyFillMode() )
2439 SetPointer( Pointer( POINTER_CROSS ) );
2440 bCross = TRUE;
2441 nScFillModeMouseModifier = rMEvt.GetModifier(); // ausgewertet bei AutoFill und Matrix
2444 if (!bCross)
2446 BOOL bAlt = rMEvt.IsMod2();
2448 if (bEditMode) // Edit-Mode muss zuerst kommen!
2449 SetPointer( Pointer( POINTER_ARROW ) );
2450 else if ( !bAlt && !nButtonDown &&
2451 GetEditUrl(rMEvt.GetPosPixel()) )
2452 SetPointer( Pointer( POINTER_REFHAND ) );
2453 else if ( DrawMouseMove(rMEvt) ) // setzt Pointer um
2454 return;
2458 if ( pViewData->GetView()->GetSelEngine()->SelMouseMove( rMEvt ) )
2459 return;
2462 void lcl_InitMouseEvent( ::com::sun::star::awt::MouseEvent& rEvent, const MouseEvent& rEvt )
2464 rEvent.Modifiers = 0;
2465 if ( rEvt.IsShift() )
2466 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::SHIFT;
2467 if ( rEvt.IsMod1() )
2468 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD1;
2469 if ( rEvt.IsMod2() )
2470 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD2;
2471 if ( rEvt.IsMod3() )
2472 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD3;
2474 rEvent.Buttons = 0;
2475 if ( rEvt.IsLeft() )
2476 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::LEFT;
2477 if ( rEvt.IsRight() )
2478 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::RIGHT;
2479 if ( rEvt.IsMiddle() )
2480 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::MIDDLE;
2482 rEvent.X = rEvt.GetPosPixel().X();
2483 rEvent.Y = rEvt.GetPosPixel().Y();
2484 rEvent.ClickCount = rEvt.GetClicks();
2485 rEvent.PopupTrigger = sal_False;
2488 long ScGridWindow::PreNotify( NotifyEvent& rNEvt )
2490 USHORT nType = rNEvt.GetType();
2491 if ( nType == EVENT_MOUSEBUTTONUP || nType == EVENT_MOUSEBUTTONDOWN )
2493 Window* pWindow = rNEvt.GetWindow();
2494 if (pWindow == this && pViewData)
2496 SfxViewFrame* pViewFrame = pViewData->GetViewShell()->GetViewFrame();
2497 if (pViewFrame)
2499 SfxFrame* pFrame = pViewFrame->GetFrame();
2500 if (pFrame)
2502 com::sun::star::uno::Reference<com::sun::star::frame::XController> xController = pFrame->GetController();
2503 if (xController.is())
2505 ScTabViewObj* pImp = ScTabViewObj::getImplementation( xController );
2506 if (pImp && pImp->IsMouseListening())
2508 ::com::sun::star::awt::MouseEvent aEvent;
2509 lcl_InitMouseEvent( aEvent, *rNEvt.GetMouseEvent() );
2510 if ( rNEvt.GetWindow() )
2511 aEvent.Source = rNEvt.GetWindow()->GetComponentInterface();
2512 if ( nType == EVENT_MOUSEBUTTONDOWN)
2513 pImp->MousePressed( aEvent );
2514 else
2515 pImp->MouseReleased( aEvent );
2523 return Window::PreNotify( rNEvt );
2526 void ScGridWindow::Tracking( const TrackingEvent& rTEvt )
2528 // Weil die SelectionEngine kein Tracking kennt, die Events nur auf
2529 // die verschiedenen MouseHandler verteilen...
2531 const MouseEvent& rMEvt = rTEvt.GetMouseEvent();
2533 if ( rTEvt.IsTrackingCanceled() ) // alles abbrechen...
2535 if (!pViewData->GetView()->IsInActivatePart())
2537 if (bDPMouse)
2538 bDPMouse = FALSE; // gezeichnet wird per bDragRect
2539 if (bDragRect)
2541 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
2542 bDragRect = FALSE;
2543 UpdateDragRectOverlay();
2545 if (bRFMouse)
2547 RFMouseMove( rMEvt, TRUE ); // richtig abbrechen geht dabei nicht...
2548 bRFMouse = FALSE;
2550 if (nPagebreakMouse)
2552 // if (bPagebreakDrawn)
2553 // DrawDragRect( aPagebreakDrag.aStart.Col(), aPagebreakDrag.aStart.Row(),
2554 // aPagebreakDrag.aEnd.Col(), aPagebreakDrag.aEnd.Row(), FALSE );
2555 bPagebreakDrawn = FALSE;
2556 UpdateDragRectOverlay();
2557 nPagebreakMouse = SC_PD_NONE;
2560 SetPointer( Pointer( POINTER_ARROW ) );
2561 StopMarking();
2562 MouseButtonUp( rMEvt ); // mit Status SC_GM_IGNORE aus StopMarking
2564 BOOL bRefMode = pViewData->IsRefMode();
2565 if (bRefMode)
2566 SC_MOD()->EndReference(); // #63148# Dialog nicht verkleinert lassen
2569 else if ( rTEvt.IsTrackingEnded() )
2571 // MouseButtonUp immer mit passenden Buttons (z.B. wegen Testtool, #63148#)
2572 // Schliesslich behauptet der Tracking-Event ja, dass normal beendet und nicht
2573 // abgebrochen wurde.
2575 MouseEvent aUpEvt( rMEvt.GetPosPixel(), rMEvt.GetClicks(),
2576 rMEvt.GetMode(), nButtonDown, rMEvt.GetModifier() );
2577 MouseButtonUp( aUpEvt );
2579 else
2580 MouseMove( rMEvt );
2583 void ScGridWindow::StartDrag( sal_Int8 /* nAction */, const Point& rPosPixel )
2585 if ( pFilterBox || nPagebreakMouse )
2586 return;
2588 HideNoteMarker();
2590 CommandEvent aDragEvent( rPosPixel, COMMAND_STARTDRAG, TRUE );
2592 if (bEEMouse && pViewData->HasEditView( eWhich ))
2594 EditView* pEditView;
2595 SCCOL nEditCol;
2596 SCROW nEditRow;
2597 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
2599 // #63263# don't remove the edit view while switching views
2600 ScModule* pScMod = SC_MOD();
2601 pScMod->SetInEditCommand( TRUE );
2603 pEditView->Command( aDragEvent );
2605 ScInputHandler* pHdl = pScMod->GetInputHdl();
2606 if (pHdl)
2607 pHdl->DataChanged();
2609 pScMod->SetInEditCommand( FALSE );
2610 if (!pViewData->IsActive()) // dropped to different view?
2612 ScInputHandler* pViewHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
2613 if ( pViewHdl && pViewData->HasEditView( eWhich ) )
2615 pViewHdl->CancelHandler();
2616 ShowCursor(); // missing from KillEditView
2620 else
2621 if ( !DrawCommand(aDragEvent) )
2622 pViewData->GetView()->GetSelEngine()->Command( aDragEvent );
2625 void lcl_SetTextCursorPos( ScViewData* pViewData, ScSplitPos eWhich, Window* pWin )
2627 SCCOL nCol = pViewData->GetCurX();
2628 SCROW nRow = pViewData->GetCurY();
2629 Rectangle aEditArea = pViewData->GetEditArea( eWhich, nCol, nRow, pWin, NULL, TRUE );
2630 aEditArea.Right() = aEditArea.Left();
2631 aEditArea = pWin->PixelToLogic( aEditArea );
2632 pWin->SetCursorRect( &aEditArea );
2635 void __EXPORT ScGridWindow::Command( const CommandEvent& rCEvt )
2637 // The command event is send to the window after a possible context
2638 // menu from an inplace client is closed. Now we have the chance to
2639 // deactivate the inplace client without any problem regarding parent
2640 // windows and code on the stack.
2641 // For more information, see #126086# and #128122#
2642 USHORT nCmd = rCEvt.GetCommand();
2643 ScTabViewShell* pTabViewSh = pViewData->GetViewShell();
2644 SfxInPlaceClient* pClient = pTabViewSh->GetIPClient();
2645 if ( pClient &&
2646 pClient->IsObjectInPlaceActive() &&
2647 nCmd == COMMAND_CONTEXTMENU )
2649 pTabViewSh->DeactivateOle();
2650 return;
2653 ScModule* pScMod = SC_MOD();
2654 DBG_ASSERT( nCmd != COMMAND_STARTDRAG, "ScGridWindow::Command called with COMMAND_STARTDRAG" );
2656 if ( nCmd == COMMAND_STARTEXTTEXTINPUT ||
2657 nCmd == COMMAND_ENDEXTTEXTINPUT ||
2658 nCmd == COMMAND_EXTTEXTINPUT ||
2659 nCmd == COMMAND_CURSORPOS )
2661 BOOL bEditView = pViewData->HasEditView( eWhich );
2662 if (!bEditView)
2664 // only if no cell editview is active, look at drawview
2665 SdrView* pSdrView = pViewData->GetView()->GetSdrView();
2666 if ( pSdrView )
2668 OutlinerView* pOlView = pSdrView->GetTextEditOutlinerView();
2669 if ( pOlView && pOlView->GetWindow() == this )
2671 pOlView->Command( rCEvt );
2672 return; // done
2677 if ( nCmd == COMMAND_CURSORPOS && !bEditView )
2679 // #88458# CURSORPOS may be called without following text input,
2680 // to set the input method window position
2681 // -> input mode must not be started,
2682 // manually calculate text insert position if not in input mode
2684 lcl_SetTextCursorPos( pViewData, eWhich, this );
2685 return;
2688 ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
2689 if ( pHdl )
2691 pHdl->InputCommand( rCEvt, TRUE );
2692 return; // done
2695 Window::Command( rCEvt );
2696 return;
2699 if ( nCmd == COMMAND_VOICE )
2701 // Der Handler wird nur gerufen, wenn ein Text-Cursor aktiv ist,
2702 // also muss es eine EditView oder ein editiertes Zeichenobjekt geben
2704 ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
2705 if ( pHdl && pViewData->HasEditView( eWhich ) )
2707 EditView* pEditView = pViewData->GetEditView( eWhich ); // ist dann nicht 0
2708 pHdl->DataChanging();
2709 pEditView->Command( rCEvt );
2710 pHdl->DataChanged();
2711 return; // erledigt
2713 SdrView* pSdrView = pViewData->GetView()->GetSdrView();
2714 if ( pSdrView )
2716 OutlinerView* pOlView = pSdrView->GetTextEditOutlinerView();
2717 if ( pOlView && pOlView->GetWindow() == this )
2719 pOlView->Command( rCEvt );
2720 return; // erledigt
2723 Window::Command(rCEvt); // sonst soll sich die Basisklasse drum kuemmern...
2724 return;
2727 if ( nCmd == COMMAND_PASTESELECTION )
2729 if ( bEEMouse )
2731 // EditEngine handles selection in MouseButtonUp - no action
2732 // needed in command handler
2734 else
2736 PasteSelection( rCEvt.GetMousePosPixel() );
2738 return;
2741 if ( nCmd == COMMAND_INPUTLANGUAGECHANGE )
2743 // #i55929# Font and font size state depends on input language if nothing is selected,
2744 // so the slots have to be invalidated when the input language is changed.
2746 SfxBindings& rBindings = pViewData->GetBindings();
2747 rBindings.Invalidate( SID_ATTR_CHAR_FONT );
2748 rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT );
2749 return;
2752 if ( nCmd == COMMAND_WHEEL || nCmd == COMMAND_STARTAUTOSCROLL || nCmd == COMMAND_AUTOSCROLL )
2754 BOOL bDone = pViewData->GetView()->ScrollCommand( rCEvt, eWhich );
2755 if (!bDone)
2756 Window::Command(rCEvt);
2757 return;
2759 // #i7560# FormulaMode check is below scrolling - scrolling is allowed during formula input
2760 BOOL bDisable = pScMod->IsFormulaMode() ||
2761 pScMod->IsModalMode(pViewData->GetSfxDocShell());
2762 if (bDisable)
2763 return;
2765 if ( nCmd == COMMAND_CONTEXTMENU && !SC_MOD()->GetIsWaterCan() )
2767 if (pViewData->IsAnyFillMode())
2769 pViewData->GetView()->StopRefMode();
2770 pViewData->ResetFillMode();
2772 ReleaseMouse();
2773 StopMarking();
2775 Point aPosPixel = rCEvt.GetMousePosPixel();
2776 Point aMenuPos = aPosPixel;
2777 BOOL bMouse = rCEvt.IsMouseEvent();
2779 if ( bMouse )
2781 SCsCOL nCellX = -1;
2782 SCsROW nCellY = -1;
2783 pViewData->GetPosFromPixel(aPosPixel.X(), aPosPixel.Y(), eWhich, nCellX, nCellY);
2784 ScDocument* pDoc = pViewData->GetDocument();
2785 SCTAB nTab = pViewData->GetTabNo();
2786 const ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
2787 bool bSelectAllowed = true;
2788 if ( pProtect && pProtect->isProtected() )
2790 // This sheet is protected. Check if a context menu is allowed on this cell.
2791 bool bCellProtected = pDoc->HasAttrib(nCellX, nCellY, nTab, nCellX, nCellY, nTab, HASATTR_PROTECTED);
2792 bool bSelProtected = pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
2793 bool bSelUnprotected = pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
2795 if (bCellProtected)
2796 bSelectAllowed = bSelProtected;
2797 else
2798 bSelectAllowed = bSelUnprotected;
2800 if (!bSelectAllowed)
2801 // Selecting this cell is not allowed, neither is context menu.
2802 return;
2804 // #i18735# First select the item under the mouse pointer.
2805 // This can change the selection, and the view state (edit mode, etc).
2806 SelectForContextMenu( aPosPixel, nCellX, nCellY );
2809 BOOL bDone = FALSE;
2810 BOOL bEdit = pViewData->HasEditView(eWhich);
2811 if ( !bEdit )
2813 // Edit-Zelle mit Spelling-Errors ?
2814 if ( bMouse && GetEditUrlOrError( TRUE, aPosPixel ) )
2816 // GetEditUrlOrError hat den Cursor schon bewegt
2818 pScMod->SetInputMode( SC_INPUT_TABLE );
2819 bEdit = pViewData->HasEditView(eWhich); // hat's geklappt ?
2821 DBG_ASSERT( bEdit, "kann nicht in Edit-Modus schalten" );
2824 if ( bEdit )
2826 EditView* pEditView = pViewData->GetEditView( eWhich ); // ist dann nicht 0
2828 if ( !bMouse )
2830 Cursor* pCur = pEditView->GetCursor();
2831 if ( pCur )
2833 Point aLogicPos = pCur->GetPos();
2834 // use the position right of the cursor (spell popup is opened if
2835 // the cursor is before the word, but not if behind it)
2836 aLogicPos.X() += pCur->GetWidth();
2837 aLogicPos.Y() += pCur->GetHeight() / 2; // center vertically
2838 aMenuPos = LogicToPixel( aLogicPos );
2842 // if edit mode was just started above, online spelling may be incomplete
2843 pEditView->GetEditEngine()->CompleteOnlineSpelling();
2845 // IsCursorAtWrongSpelledWord could be used for !bMouse
2846 // if there was a corresponding ExecuteSpellPopup call
2848 if( pEditView->IsWrongSpelledWordAtPos( aMenuPos ) )
2850 // Wenn man unter OS/2 neben das Popupmenue klickt, kommt MouseButtonDown
2851 // vor dem Ende des Menue-Execute, darum muss SetModified vorher kommen
2852 // (Bug #40968#)
2853 ScInputHandler* pHdl = pScMod->GetInputHdl();
2854 if (pHdl)
2855 pHdl->SetModified();
2857 Link aLink = LINK( this, ScGridWindow, PopupSpellingHdl );
2858 pEditView->ExecuteSpellPopup( aMenuPos, &aLink );
2860 bDone = TRUE;
2863 else if ( !bMouse )
2865 // non-edit menu by keyboard -> use lower right of cell cursor position
2867 SCCOL nCurX = pViewData->GetCurX();
2868 SCROW nCurY = pViewData->GetCurY();
2869 aMenuPos = pViewData->GetScrPos( nCurX, nCurY, eWhich, TRUE );
2870 long nSizeXPix;
2871 long nSizeYPix;
2872 pViewData->GetMergeSizePixel( nCurX, nCurY, nSizeXPix, nSizeYPix );
2873 aMenuPos.X() += nSizeXPix;
2874 aMenuPos.Y() += nSizeYPix;
2876 if (pViewData)
2878 ScTabViewShell* pViewSh = pViewData->GetViewShell();
2879 if (pViewSh)
2881 // Is a draw object selected?
2883 SdrView* pDrawView = pViewSh->GetSdrView();
2884 if (pDrawView && pDrawView->AreObjectsMarked())
2886 // #100442#; the conext menu should open in the middle of the selected objects
2887 Rectangle aSelectRect(LogicToPixel(pDrawView->GetAllMarkedBoundRect()));
2888 aMenuPos = aSelectRect.Center();
2894 if (!bDone)
2896 SfxDispatcher::ExecutePopup( 0, this, &aMenuPos );
2901 void ScGridWindow::SelectForContextMenu( const Point& rPosPixel, SCsCOL nCellX, SCsROW nCellY )
2903 // #i18735# if the click was outside of the current selection,
2904 // the cursor is moved or an object at the click position selected.
2905 // (see SwEditWin::SelectMenuPosition in Writer)
2907 ScTabView* pView = pViewData->GetView();
2908 ScDrawView* pDrawView = pView->GetScDrawView();
2910 // check cell edit mode
2912 if ( pViewData->HasEditView(eWhich) )
2914 ScModule* pScMod = SC_MOD();
2915 SCCOL nEditStartCol = pViewData->GetEditViewCol(); //! change to GetEditStartCol after calcrtl is integrated
2916 SCROW nEditStartRow = pViewData->GetEditViewRow();
2917 SCCOL nEditEndCol = pViewData->GetEditEndCol();
2918 SCROW nEditEndRow = pViewData->GetEditEndRow();
2920 if ( nCellX >= (SCsCOL) nEditStartCol && nCellX <= (SCsCOL) nEditEndCol &&
2921 nCellY >= (SCsROW) nEditStartRow && nCellY <= (SCsROW) nEditEndRow )
2923 // handle selection within the EditView
2925 EditView* pEditView = pViewData->GetEditView( eWhich ); // not NULL (HasEditView)
2926 EditEngine* pEditEngine = pEditView->GetEditEngine();
2927 Rectangle aOutputArea = pEditView->GetOutputArea();
2928 Rectangle aVisArea = pEditView->GetVisArea();
2930 Point aTextPos = PixelToLogic( rPosPixel );
2931 if ( pEditEngine->IsVertical() ) // have to manually transform position
2933 aTextPos -= aOutputArea.TopRight();
2934 long nTemp = -aTextPos.X();
2935 aTextPos.X() = aTextPos.Y();
2936 aTextPos.Y() = nTemp;
2938 else
2939 aTextPos -= aOutputArea.TopLeft();
2940 aTextPos += aVisArea.TopLeft(); // position in the edit document
2942 EPosition aDocPosition = pEditEngine->FindDocPosition(aTextPos);
2943 ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex);
2944 ESelection aSelection = pEditView->GetSelection();
2945 aSelection.Adjust(); // needed for IsLess/IsGreater
2946 if ( aCompare.IsLess(aSelection) || aCompare.IsGreater(aSelection) )
2948 // clicked outside the selected text - deselect and move text cursor
2949 MouseEvent aEvent( rPosPixel );
2950 pEditView->MouseButtonDown( aEvent );
2951 pEditView->MouseButtonUp( aEvent );
2952 pScMod->InputSelection( pEditView );
2955 return; // clicked within the edit view - keep edit mode
2957 else
2959 // outside of the edit view - end edit mode, regardless of cell selection, then continue
2960 pScMod->InputEnterHandler();
2964 // check draw text edit mode
2966 Point aLogicPos = PixelToLogic( rPosPixel ); // after cell edit mode is ended
2967 if ( pDrawView && pDrawView->GetTextEditObject() && pDrawView->GetTextEditOutlinerView() )
2969 OutlinerView* pOlView = pDrawView->GetTextEditOutlinerView();
2970 Rectangle aOutputArea = pOlView->GetOutputArea();
2971 if ( aOutputArea.IsInside( aLogicPos ) )
2973 // handle selection within the OutlinerView
2975 Outliner* pOutliner = pOlView->GetOutliner();
2976 const EditEngine& rEditEngine = pOutliner->GetEditEngine();
2977 Rectangle aVisArea = pOlView->GetVisArea();
2979 Point aTextPos = aLogicPos;
2980 if ( pOutliner->IsVertical() ) // have to manually transform position
2982 aTextPos -= aOutputArea.TopRight();
2983 long nTemp = -aTextPos.X();
2984 aTextPos.X() = aTextPos.Y();
2985 aTextPos.Y() = nTemp;
2987 else
2988 aTextPos -= aOutputArea.TopLeft();
2989 aTextPos += aVisArea.TopLeft(); // position in the edit document
2991 EPosition aDocPosition = rEditEngine.FindDocPosition(aTextPos);
2992 ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex);
2993 ESelection aSelection = pOlView->GetSelection();
2994 aSelection.Adjust(); // needed for IsLess/IsGreater
2995 if ( aCompare.IsLess(aSelection) || aCompare.IsGreater(aSelection) )
2997 // clicked outside the selected text - deselect and move text cursor
2998 // use DrawView to allow extra handling there (none currently)
2999 MouseEvent aEvent( rPosPixel );
3000 pDrawView->MouseButtonDown( aEvent, this );
3001 pDrawView->MouseButtonUp( aEvent, this );
3004 return; // clicked within the edit area - keep edit mode
3006 else
3008 // Outside of the edit area - end text edit mode, then continue.
3009 // DrawDeselectAll also ends text edit mode and updates the shells.
3010 // If the click was on the edited object, it will be selected again below.
3011 pView->DrawDeselectAll();
3015 // look for existing selection
3017 BOOL bHitSelected = FALSE;
3018 if ( pDrawView && pDrawView->IsMarkedObjHit( aLogicPos ) )
3020 // clicked on selected object -> don't change anything
3021 bHitSelected = TRUE;
3023 else if ( pViewData->GetMarkData().IsCellMarked(nCellX, nCellY) )
3025 // clicked on selected cell -> don't change anything
3026 bHitSelected = TRUE;
3029 // select drawing object or move cell cursor
3031 if ( !bHitSelected )
3033 BOOL bWasDraw = ( pDrawView && pDrawView->AreObjectsMarked() );
3034 BOOL bHitDraw = FALSE;
3035 if ( pDrawView )
3037 pDrawView->UnmarkAllObj();
3038 // Unlock the Internal Layer in order to activate the context menu.
3039 // re-lock in ScDrawView::MarkListHasChanged()
3040 lcl_UnLockComment( pDrawView, pDrawView->GetSdrPageView(), pDrawView->GetModel(), aLogicPos ,pViewData);
3041 bHitDraw = pDrawView->MarkObj( aLogicPos );
3042 // draw shell is activated in MarkListHasChanged
3044 if ( !bHitDraw )
3046 pView->Unmark();
3047 pView->SetCursor(nCellX, nCellY);
3048 if ( bWasDraw )
3049 pViewData->GetViewShell()->SetDrawShell( FALSE ); // switch shells
3054 static void ClearSingleSelection( ScViewData* pViewData )
3056 SCCOL nX;
3057 SCROW nY;
3058 ScTransferObj* pTransObj = ScTransferObj::GetOwnClipboard(
3059 pViewData->GetActiveWin() );
3060 if (!pTransObj)
3061 return;
3063 ScDocument* pClipDoc = pTransObj->GetDocument();
3064 pClipDoc->GetClipArea( nX, nY, TRUE );
3065 if (nX == 0 && nY == 0)
3067 ScTabView* pView = pViewData->GetView();
3068 pView->Unmark();
3072 void __EXPORT ScGridWindow::KeyInput(const KeyEvent& rKEvt)
3074 // #96965# Cursor control for ref input dialog
3075 const KeyCode& rKeyCode = rKEvt.GetKeyCode();
3076 if( SC_MOD()->IsRefDialogOpen() )
3078 if( !rKeyCode.GetModifier() && (rKeyCode.GetCode() == KEY_F2) )
3080 SC_MOD()->EndReference();
3081 return;
3083 else if( pViewData->GetViewShell()->MoveCursorKeyInput( rKEvt ) )
3085 ScRange aRef(
3086 pViewData->GetRefStartX(), pViewData->GetRefStartY(), pViewData->GetRefStartZ(),
3087 pViewData->GetRefEndX(), pViewData->GetRefEndY(), pViewData->GetRefEndZ() );
3088 SC_MOD()->SetReference( aRef, pViewData->GetDocument() );
3089 return;
3092 else if( rKeyCode.GetCode() == KEY_RETURN && pViewData->IsPasteMode() )
3094 ScTabViewShell* pTabViewShell = pViewData->GetViewShell();
3096 ScCellShell::PasteFromClipboard( pViewData, pTabViewShell, FALSE );
3097 ClearSingleSelection( pViewData );
3099 uno::Reference<datatransfer::clipboard::XClipboard> xSystemClipboard =
3100 TransferableHelper::GetSystemClipboard();
3101 if (xSystemClipboard.is())
3103 xSystemClipboard->setContents(
3104 uno::Reference<datatransfer::XTransferable>(),
3105 uno::Reference<datatransfer::clipboard::XClipboardOwner>());
3108 // hide the border around the copy source
3109 pViewData->SetPasteMode( SC_PASTE_NONE );
3110 UpdateCopySourceOverlay();
3111 return;
3113 // wenn semi-Modeless-SfxChildWindow-Dialog oben, keine KeyInputs:
3114 else if( !pViewData->IsAnyFillMode() )
3116 if (rKeyCode.GetCode() == KEY_ESCAPE)
3118 pViewData->SetPasteMode( SC_PASTE_NONE );
3119 UpdateCopySourceOverlay();
3121 // query for existing note marker before calling ViewShell's keyboard handling
3122 // which may remove the marker
3123 BOOL bHadKeyMarker = ( pNoteMarker && pNoteMarker->IsByKeyboard() );
3124 ScTabViewShell* pViewSh = pViewData->GetViewShell();
3126 if (pViewData->GetDocShell()->GetProgress())
3127 return;
3129 if (DrawKeyInput(rKEvt))
3130 return;
3132 if (!pViewData->GetView()->IsDrawSelMode() && !DrawHasMarkedObj()) // keine Eingaben im Zeichenmodus
3133 { //! DrawShell abfragen !!!
3134 if (pViewSh->TabKeyInput(rKEvt))
3135 return;
3137 else
3138 if (pViewSh->SfxViewShell::KeyInput(rKEvt)) // von SfxViewShell
3139 return;
3141 KeyCode aCode = rKEvt.GetKeyCode();
3142 if ( aCode.GetCode() == KEY_ESCAPE && aCode.GetModifier() == 0 )
3144 if ( bHadKeyMarker )
3145 HideNoteMarker();
3146 else
3147 pViewSh->Escape();
3148 return;
3150 if ( aCode.GetCode() == KEY_F1 && aCode.GetModifier() == KEY_MOD1 )
3152 // ctrl-F1 shows or hides the note or redlining info for the cursor position
3153 // (hard-coded because F1 can't be configured)
3155 if ( bHadKeyMarker )
3156 HideNoteMarker(); // hide when previously visible
3157 else
3158 ShowNoteMarker( pViewData->GetCurX(), pViewData->GetCurY(), TRUE );
3159 return;
3161 if (aCode.GetCode() == KEY_BRACKETLEFT && aCode.GetModifier() == KEY_MOD1)
3163 pViewSh->DetectiveMarkPred();
3164 return;
3166 if (aCode.GetCode() == KEY_BRACKETRIGHT && aCode.GetModifier() == KEY_MOD1)
3168 pViewSh->DetectiveMarkSucc();
3169 return;
3174 Window::KeyInput(rKEvt);
3177 void ScGridWindow::StopMarking()
3179 DrawEndAction(); // Markieren/Verschieben auf Drawing-Layer abbrechen
3181 if (nButtonDown)
3183 pViewData->GetMarkData().SetMarking(FALSE);
3184 nMouseStatus = SC_GM_IGNORE;
3188 void ScGridWindow::UpdateInputContext()
3190 BOOL bReadOnly = pViewData->GetDocShell()->IsReadOnly();
3191 ULONG nOptions = bReadOnly ? 0 : ( INPUTCONTEXT_TEXT | INPUTCONTEXT_EXTTEXTINPUT );
3193 // when font from InputContext is used,
3194 // it must be taken from the cursor position's cell attributes
3196 InputContext aContext;
3197 aContext.SetOptions( nOptions );
3198 SetInputContext( aContext );
3201 //--------------------------------------------------------
3203 // sensitiver Bereich (Pixel)
3204 #define SCROLL_SENSITIVE 20
3206 BOOL ScGridWindow::DropScroll( const Point& rMousePos )
3208 /* doch auch auf nicht aktiven Views...
3209 if ( !pViewData->IsActive() )
3210 return FALSE;
3212 SCsCOL nDx = 0;
3213 SCsROW nDy = 0;
3214 Size aSize = GetOutputSizePixel();
3216 if (aSize.Width() > SCROLL_SENSITIVE * 3)
3218 if ( rMousePos.X() < SCROLL_SENSITIVE && pViewData->GetPosX(WhichH(eWhich)) > 0 )
3219 nDx = -1;
3220 if ( rMousePos.X() >= aSize.Width() - SCROLL_SENSITIVE
3221 && pViewData->GetPosX(WhichH(eWhich)) < MAXCOL )
3222 nDx = 1;
3224 if (aSize.Height() > SCROLL_SENSITIVE * 3)
3226 if ( rMousePos.Y() < SCROLL_SENSITIVE && pViewData->GetPosY(WhichV(eWhich)) > 0 )
3227 nDy = -1;
3228 if ( rMousePos.Y() >= aSize.Height() - SCROLL_SENSITIVE
3229 && pViewData->GetPosY(WhichV(eWhich)) < MAXROW )
3230 nDy = 1;
3233 if ( nDx != 0 || nDy != 0 )
3235 // if (bDragRect)
3236 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3238 if ( nDx != 0 )
3239 pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) );
3240 if ( nDy != 0 )
3241 pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) );
3243 // if (bDragRect)
3244 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3247 return FALSE;
3250 BOOL lcl_TestScenarioRedliningDrop( ScDocument* pDoc, const ScRange& aDragRange)
3252 // Testet, ob bei eingeschalteten RedLining,
3253 // bei einem Drop ein Scenario betroffen ist.
3255 BOOL bReturn = FALSE;
3256 SCTAB nTab = aDragRange.aStart.Tab();
3257 SCTAB nTabCount = pDoc->GetTableCount();
3259 if(pDoc->GetChangeTrack()!=NULL)
3261 if( pDoc->IsScenario(nTab) && pDoc->HasScenarioRange(nTab, aDragRange))
3263 bReturn = TRUE;
3265 else
3267 for(SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
3269 if(pDoc->HasScenarioRange(i, aDragRange))
3271 bReturn = TRUE;
3272 break;
3277 return bReturn;
3280 ScRange lcl_MakeDropRange( SCCOL nPosX, SCROW nPosY, SCTAB nTab, const ScRange& rSource )
3282 SCCOL nCol1 = nPosX;
3283 SCCOL nCol2 = nCol1 + ( rSource.aEnd.Col() - rSource.aStart.Col() );
3284 if ( nCol2 > MAXCOL )
3286 nCol1 -= nCol2 - MAXCOL;
3287 nCol2 = MAXCOL;
3289 SCROW nRow1 = nPosY;
3290 SCROW nRow2 = nRow1 + ( rSource.aEnd.Row() - rSource.aStart.Row() );
3291 if ( nRow2 > MAXROW )
3293 nRow1 -= nRow2 - MAXROW;
3294 nRow2 = MAXROW;
3297 return ScRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab );
3300 //--------------------------------------------------------
3302 extern BOOL bPasteIsDrop; // viewfun4 -> move to header
3303 extern BOOL bPasteIsMove; // viewfun7 -> move to header
3305 //--------------------------------------------------------
3307 sal_Int8 ScGridWindow::AcceptPrivateDrop( const AcceptDropEvent& rEvt )
3309 if ( rEvt.mbLeaving )
3311 // if (bDragRect)
3312 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3313 bDragRect = FALSE;
3314 UpdateDragRectOverlay();
3315 return rEvt.mnAction;
3318 const ScDragData& rData = SC_MOD()->GetDragData();
3319 if ( rData.pCellTransfer )
3321 // Don't move source that would include filtered rows.
3322 if ((rEvt.mnAction & DND_ACTION_MOVE) && rData.pCellTransfer->HasFilteredRows())
3324 if (bDragRect)
3326 bDragRect = FALSE;
3327 UpdateDragRectOverlay();
3329 return DND_ACTION_NONE;
3332 Point aPos = rEvt.maPosPixel;
3334 ScDocument* pSourceDoc = rData.pCellTransfer->GetSourceDocument();
3335 ScDocument* pThisDoc = pViewData->GetDocument();
3336 if (pSourceDoc == pThisDoc)
3338 if ( pThisDoc->HasChartAtPoint(pViewData->GetTabNo(), PixelToLogic(aPos)) )
3340 if (bDragRect) // Rechteck loeschen
3342 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3343 bDragRect = FALSE;
3344 UpdateDragRectOverlay();
3347 //! highlight chart? (selection border?)
3349 sal_Int8 nRet = rEvt.mnAction;
3350 //! if ( rEvt.GetAction() == DROP_LINK )
3351 //! bOk = rEvt.SetAction( DROP_COPY ); // can't link onto chart
3352 return nRet;
3355 //! else
3356 //! if ( rEvt.GetAction() == DROP_MOVE )
3357 //! rEvt.SetAction( DROP_COPY ); // different doc: default=COPY
3360 if ( rData.pCellTransfer->GetDragSourceFlags() & SC_DROP_TABLE ) // whole sheet?
3362 BOOL bOk = pThisDoc->IsDocEditable();
3363 return bOk ? rEvt.mnAction : 0; // don't draw selection frame
3366 SCsCOL nPosX;
3367 SCsROW nPosY;
3368 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
3370 ScRange aSourceRange = rData.pCellTransfer->GetRange();
3371 SCCOL nSourceStartX = aSourceRange.aStart.Col();
3372 SCROW nSourceStartY = aSourceRange.aStart.Row();
3373 SCCOL nSourceEndX = aSourceRange.aEnd.Col();
3374 SCROW nSourceEndY = aSourceRange.aEnd.Row();
3375 SCCOL nSizeX = nSourceEndX - nSourceStartX + 1;
3376 SCROW nSizeY = nSourceEndY - nSourceStartY + 1;
3378 if ( rEvt.mnAction != DND_ACTION_MOVE )
3379 nSizeY = rData.pCellTransfer->GetNonFilteredRows(); // copy/link: no filtered rows
3381 SCsCOL nNewDragX = nPosX - rData.pCellTransfer->GetDragHandleX();
3382 if (nNewDragX<0) nNewDragX=0;
3383 if (nNewDragX+(nSizeX-1) > MAXCOL)
3384 nNewDragX = MAXCOL-(nSizeX-1);
3385 SCsROW nNewDragY = nPosY - rData.pCellTransfer->GetDragHandleY();
3386 if (nNewDragY<0) nNewDragY=0;
3387 if (nNewDragY+(nSizeY-1) > MAXROW)
3388 nNewDragY = MAXROW-(nSizeY-1);
3390 // don't break scenario ranges, don't drop on filtered
3391 SCTAB nTab = pViewData->GetTabNo();
3392 ScRange aDropRange = lcl_MakeDropRange( nNewDragX, nNewDragY, nTab, aSourceRange );
3393 if ( lcl_TestScenarioRedliningDrop( pThisDoc, aDropRange ) ||
3394 lcl_TestScenarioRedliningDrop( pSourceDoc, aSourceRange ) ||
3395 ScViewUtil::HasFiltered( aDropRange, pThisDoc) )
3397 if (bDragRect)
3399 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3400 bDragRect = FALSE;
3401 UpdateDragRectOverlay();
3403 return DND_ACTION_NONE;
3406 InsCellCmd eDragInsertMode = INS_NONE;
3407 Window::PointerState aState = GetPointerState();
3409 // check for datapilot item sorting
3410 ScDPObject* pDPObj = NULL;
3411 if ( pThisDoc == pSourceDoc && ( pDPObj = pThisDoc->GetDPAtCursor( nNewDragX, nNewDragY, nTab ) ) != NULL )
3413 // drop on DataPilot table: sort or nothing
3415 bool bDPSort = false;
3416 if ( pThisDoc->GetDPAtCursor( nSourceStartX, nSourceStartY, aSourceRange.aStart.Tab() ) == pDPObj )
3418 sheet::DataPilotTableHeaderData aDestData;
3419 pDPObj->GetHeaderPositionData( ScAddress(nNewDragX, nNewDragY, nTab), aDestData );
3420 bool bValid = ( aDestData.Dimension >= 0 ); // dropping onto a field
3422 // look through the source range
3423 for (SCROW nRow = aSourceRange.aStart.Row(); bValid && nRow <= aSourceRange.aEnd.Row(); ++nRow )
3424 for (SCCOL nCol = aSourceRange.aStart.Col(); bValid && nCol <= aSourceRange.aEnd.Col(); ++nCol )
3426 sheet::DataPilotTableHeaderData aSourceData;
3427 pDPObj->GetHeaderPositionData( ScAddress( nCol, nRow, aSourceRange.aStart.Tab() ), aSourceData );
3428 if ( aSourceData.Dimension != aDestData.Dimension || !aSourceData.MemberName.getLength() )
3429 bValid = false; // empty (subtotal) or different field
3432 if ( bValid )
3434 BOOL bIsDataLayout;
3435 String aDimName = pDPObj->GetDimName( aDestData.Dimension, bIsDataLayout );
3436 const ScDPSaveDimension* pDim = pDPObj->GetSaveData()->GetExistingDimensionByName( aDimName );
3437 if ( pDim )
3439 ScRange aOutRange = pDPObj->GetOutRange();
3441 USHORT nOrient = pDim->GetOrientation();
3442 if ( nOrient == sheet::DataPilotFieldOrientation_COLUMN )
3444 eDragInsertMode = INS_CELLSRIGHT;
3445 nSizeY = aOutRange.aEnd.Row() - nNewDragY + 1;
3446 bDPSort = true;
3448 else if ( nOrient == sheet::DataPilotFieldOrientation_ROW )
3450 eDragInsertMode = INS_CELLSDOWN;
3451 nSizeX = aOutRange.aEnd.Col() - nNewDragX + 1;
3452 bDPSort = true;
3458 if ( !bDPSort )
3460 // no valid sorting in a DataPilot table -> disallow
3461 if ( bDragRect )
3463 bDragRect = FALSE;
3464 UpdateDragRectOverlay();
3466 return DND_ACTION_NONE;
3469 else if ( aState.mnState & KEY_MOD2 )
3471 if ( pThisDoc == pSourceDoc && nTab == aSourceRange.aStart.Tab() )
3473 long nDeltaX = labs( static_cast< long >( nNewDragX - nSourceStartX ) );
3474 long nDeltaY = labs( static_cast< long >( nNewDragY - nSourceStartY ) );
3475 if ( nDeltaX <= nDeltaY )
3477 eDragInsertMode = INS_CELLSDOWN;
3479 else
3481 eDragInsertMode = INS_CELLSRIGHT;
3484 if ( ( eDragInsertMode == INS_CELLSDOWN && nNewDragY <= nSourceEndY &&
3485 ( nNewDragX + nSizeX - 1 ) >= nSourceStartX && nNewDragX <= nSourceEndX &&
3486 ( nNewDragX != nSourceStartX || nNewDragY >= nSourceStartY ) ) ||
3487 ( eDragInsertMode == INS_CELLSRIGHT && nNewDragX <= nSourceEndX &&
3488 ( nNewDragY + nSizeY - 1 ) >= nSourceStartY && nNewDragY <= nSourceEndY &&
3489 ( nNewDragY != nSourceStartY || nNewDragX >= nSourceStartX ) ) )
3491 if ( bDragRect )
3493 bDragRect = FALSE;
3494 UpdateDragRectOverlay();
3496 return DND_ACTION_NONE;
3499 else
3501 if ( static_cast< long >( nSizeX ) >= static_cast< long >( nSizeY ) )
3503 eDragInsertMode = INS_CELLSDOWN;
3506 else
3508 eDragInsertMode = INS_CELLSRIGHT;
3513 if ( nNewDragX != (SCsCOL) nDragStartX || nNewDragY != (SCsROW) nDragStartY ||
3514 nDragStartX+nSizeX-1 != nDragEndX || nDragStartY+nSizeY-1 != nDragEndY ||
3515 !bDragRect || eDragInsertMode != meDragInsertMode )
3517 // if (bDragRect)
3518 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3520 nDragStartX = nNewDragX;
3521 nDragStartY = nNewDragY;
3522 nDragEndX = nDragStartX+nSizeX-1;
3523 nDragEndY = nDragStartY+nSizeY-1;
3524 bDragRect = TRUE;
3525 meDragInsertMode = eDragInsertMode;
3527 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3529 UpdateDragRectOverlay();
3531 // show target position as tip help
3532 #if 0
3533 if (Help::IsQuickHelpEnabled())
3535 ScRange aRange( nDragStartX, nDragStartY, nTab, nDragEndX, nDragEndY, nTab );
3536 String aHelpStr;
3537 aRange.Format( aHelpStr, SCA_VALID ); // non-3D
3539 Point aPos = Pointer::GetPosPixel();
3540 USHORT nAlign = QUICKHELP_BOTTOM|QUICKHELP_RIGHT;
3541 Rectangle aRect( aPos, aPos );
3542 Help::ShowQuickHelp(aRect, aHelpStr, nAlign);
3544 #endif
3548 return rEvt.mnAction;
3551 sal_Int8 ScGridWindow::AcceptDrop( const AcceptDropEvent& rEvt )
3553 const ScDragData& rData = SC_MOD()->GetDragData();
3554 if ( rEvt.mbLeaving )
3556 DrawMarkDropObj( NULL );
3557 if ( rData.pCellTransfer )
3558 return AcceptPrivateDrop( rEvt ); // hide drop marker for internal D&D
3559 else
3560 return rEvt.mnAction;
3563 if ( pViewData->GetDocShell()->IsReadOnly() )
3564 return DND_ACTION_NONE;
3567 sal_Int8 nRet = DND_ACTION_NONE;
3569 if (rData.pCellTransfer)
3571 ScRange aSource = rData.pCellTransfer->GetRange();
3572 if ( aSource.aStart.Col() != 0 || aSource.aEnd.Col() != MAXCOL ||
3573 aSource.aStart.Row() != 0 || aSource.aEnd.Row() != MAXROW )
3574 DropScroll( rEvt.maPosPixel );
3576 nRet = AcceptPrivateDrop( rEvt );
3578 else
3580 if ( rData.aLinkDoc.Len() )
3582 String aThisName;
3583 ScDocShell* pDocSh = pViewData->GetDocShell();
3584 if (pDocSh && pDocSh->HasName())
3585 aThisName = pDocSh->GetMedium()->GetName();
3587 if ( rData.aLinkDoc != aThisName )
3588 nRet = rEvt.mnAction;
3590 else if (rData.aJumpTarget.Len())
3592 // internal bookmarks (from Navigator)
3593 // local jumps from an unnamed document are possible only within a document
3595 if ( !rData.pJumpLocalDoc || rData.pJumpLocalDoc == pViewData->GetDocument() )
3596 nRet = rEvt.mnAction;
3598 else
3600 sal_Int8 nMyAction = rEvt.mnAction;
3602 if ( !rData.pDrawTransfer ||
3603 !IsMyModel(rData.pDrawTransfer->GetDragSourceView()) ) // drawing within the document
3604 if ( rEvt.mbDefault && nMyAction == DND_ACTION_MOVE )
3605 nMyAction = DND_ACTION_COPY;
3607 ScDocument* pThisDoc = pViewData->GetDocument();
3608 SdrObject* pHitObj = pThisDoc->GetObjectAtPoint(
3609 pViewData->GetTabNo(), PixelToLogic(rEvt.maPosPixel) );
3610 if ( pHitObj && nMyAction == DND_ACTION_LINK && !rData.pDrawTransfer )
3612 if ( IsDropFormatSupported(SOT_FORMATSTR_ID_SVXB)
3613 || IsDropFormatSupported(SOT_FORMAT_GDIMETAFILE)
3614 || IsDropFormatSupported(SOT_FORMAT_BITMAP) )
3616 // graphic dragged onto drawing object
3617 DrawMarkDropObj( pHitObj );
3618 nRet = nMyAction;
3621 if (!nRet)
3622 DrawMarkDropObj( NULL );
3624 if (!nRet)
3626 switch ( nMyAction )
3628 case DND_ACTION_COPY:
3629 case DND_ACTION_MOVE:
3630 case DND_ACTION_COPYMOVE:
3632 BOOL bMove = ( nMyAction == DND_ACTION_MOVE );
3633 if ( IsDropFormatSupported( SOT_FORMATSTR_ID_EMBED_SOURCE ) ||
3634 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE ) ||
3635 IsDropFormatSupported( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) ||
3636 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ||
3637 IsDropFormatSupported( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) ||
3638 IsDropFormatSupported( SOT_FORMAT_STRING ) ||
3639 IsDropFormatSupported( SOT_FORMATSTR_ID_SYLK ) ||
3640 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK ) ||
3641 IsDropFormatSupported( SOT_FORMATSTR_ID_HTML ) ||
3642 IsDropFormatSupported( SOT_FORMATSTR_ID_HTML_SIMPLE ) ||
3643 IsDropFormatSupported( SOT_FORMATSTR_ID_DIF ) ||
3644 IsDropFormatSupported( SOT_FORMATSTR_ID_DRAWING ) ||
3645 IsDropFormatSupported( SOT_FORMATSTR_ID_SVXB ) ||
3646 IsDropFormatSupported( SOT_FORMAT_RTF ) ||
3647 IsDropFormatSupported( SOT_FORMAT_GDIMETAFILE ) ||
3648 IsDropFormatSupported( SOT_FORMAT_BITMAP ) ||
3649 IsDropFormatSupported( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) ||
3650 IsDropFormatSupported( SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE ) ||
3651 ( !bMove && (
3652 IsDropFormatSupported( SOT_FORMAT_FILE_LIST ) ||
3653 IsDropFormatSupported( SOT_FORMAT_FILE ) ||
3654 IsDropFormatSupported( SOT_FORMATSTR_ID_SOLK ) ||
3655 IsDropFormatSupported( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) ||
3656 IsDropFormatSupported( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) ||
3657 IsDropFormatSupported( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) ) ) )
3659 nRet = nMyAction;
3662 break;
3663 case DND_ACTION_LINK:
3664 if ( IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE ) ||
3665 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ||
3666 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK ) ||
3667 IsDropFormatSupported( SOT_FORMAT_FILE_LIST ) ||
3668 IsDropFormatSupported( SOT_FORMAT_FILE ) ||
3669 IsDropFormatSupported( SOT_FORMATSTR_ID_SOLK ) ||
3670 IsDropFormatSupported( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) ||
3671 IsDropFormatSupported( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) ||
3672 IsDropFormatSupported( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
3674 nRet = nMyAction;
3676 break;
3679 if ( nRet )
3681 // Simple check for protection: It's not known here if the drop will result
3682 // in cells or drawing objects (some formats can be both) and how many cells
3683 // the result will be. But if IsFormatEditable for the drop cell position
3684 // is FALSE (ignores matrix formulas), nothing can be pasted, so the drop
3685 // can already be rejected here.
3687 Point aPos = rEvt.maPosPixel;
3688 SCsCOL nPosX;
3689 SCsROW nPosY;
3690 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
3691 SCTAB nTab = pViewData->GetTabNo();
3692 ScDocument* pDoc = pViewData->GetDocument();
3694 ScEditableTester aTester( pDoc, nTab, nPosX,nPosY, nPosX,nPosY );
3695 if ( !aTester.IsFormatEditable() )
3696 nRet = DND_ACTION_NONE; // forbidden
3701 // scroll only for accepted formats
3702 if (nRet)
3703 DropScroll( rEvt.maPosPixel );
3706 return nRet;
3709 ULONG lcl_GetDropFormatId( const uno::Reference<datatransfer::XTransferable>& xTransfer, bool bPreferText = false )
3711 TransferableDataHelper aDataHelper( xTransfer );
3713 if ( !aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) )
3715 // use bookmark formats if no sba is present
3717 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SOLK ) )
3718 return SOT_FORMATSTR_ID_SOLK;
3719 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) )
3720 return SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR;
3721 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) )
3722 return SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK;
3723 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
3724 return SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR;
3727 ULONG nFormatId = 0;
3728 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING ) )
3729 nFormatId = SOT_FORMATSTR_ID_DRAWING;
3730 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ) )
3731 nFormatId = SOT_FORMATSTR_ID_SVXB;
3732 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ) )
3734 // If it's a Writer object, insert RTF instead of OLE
3736 BOOL bDoRtf = FALSE;
3737 SotStorageStreamRef xStm;
3738 TransferableObjectDescriptor aObjDesc;
3739 if( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) &&
3740 aDataHelper.GetSotStorageStream( SOT_FORMATSTR_ID_EMBED_SOURCE, xStm ) )
3742 SotStorageRef xStore( new SotStorage( *xStm ) );
3743 bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) ||
3744 aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) )
3745 && aDataHelper.HasFormat( SOT_FORMAT_RTF ) );
3747 if ( bDoRtf )
3748 nFormatId = FORMAT_RTF;
3749 else
3750 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE;
3752 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) )
3753 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE;
3754 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) )
3755 nFormatId = SOT_FORMATSTR_ID_SBA_DATAEXCHANGE;
3756 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE ) )
3757 nFormatId = SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE;
3758 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_BIFF_8 ) )
3759 nFormatId = SOT_FORMATSTR_ID_BIFF_8;
3760 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_BIFF_5 ) )
3761 nFormatId = SOT_FORMATSTR_ID_BIFF_5;
3762 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) )
3763 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE_OLE;
3764 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) )
3765 nFormatId = SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE;
3766 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) )
3767 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE;
3768 else if ( aDataHelper.HasFormat( SOT_FORMAT_RTF ) )
3769 nFormatId = SOT_FORMAT_RTF;
3770 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_HTML ) )
3771 nFormatId = SOT_FORMATSTR_ID_HTML;
3772 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_HTML_SIMPLE ) )
3773 nFormatId = SOT_FORMATSTR_ID_HTML_SIMPLE;
3774 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SYLK ) )
3775 nFormatId = SOT_FORMATSTR_ID_SYLK;
3776 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK ) )
3777 nFormatId = SOT_FORMATSTR_ID_LINK;
3778 else if ( bPreferText && aDataHelper.HasFormat( SOT_FORMAT_STRING ) ) // #i86734# the behaviour introduced in #i62773# is wrong when pasting
3779 nFormatId = SOT_FORMAT_STRING;
3780 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) )
3781 nFormatId = SOT_FORMAT_FILE_LIST;
3782 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE ) ) // #i62773# FILE_LIST/FILE before STRING (Unix file managers)
3783 nFormatId = SOT_FORMAT_FILE;
3784 else if ( aDataHelper.HasFormat( SOT_FORMAT_STRING ) )
3785 nFormatId = SOT_FORMAT_STRING;
3786 else if ( aDataHelper.HasFormat( SOT_FORMAT_GDIMETAFILE ) )
3787 nFormatId = SOT_FORMAT_GDIMETAFILE;
3788 else if ( aDataHelper.HasFormat( SOT_FORMAT_BITMAP ) )
3789 nFormatId = SOT_FORMAT_BITMAP;
3791 return nFormatId;
3794 ULONG lcl_GetDropLinkId( const uno::Reference<datatransfer::XTransferable>& xTransfer )
3796 TransferableDataHelper aDataHelper( xTransfer );
3798 ULONG nFormatId = 0;
3799 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) )
3800 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE;
3801 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) )
3802 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE;
3803 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK ) )
3804 nFormatId = SOT_FORMATSTR_ID_LINK;
3805 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) )
3806 nFormatId = SOT_FORMAT_FILE_LIST;
3807 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE ) )
3808 nFormatId = SOT_FORMAT_FILE;
3809 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SOLK ) )
3810 nFormatId = SOT_FORMATSTR_ID_SOLK;
3811 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) )
3812 nFormatId = SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR;
3813 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) )
3814 nFormatId = SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK;
3815 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
3816 nFormatId = SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR;
3818 return nFormatId;
3822 sal_Int8 ScGridWindow::ExecutePrivateDrop( const ExecuteDropEvent& rEvt )
3824 // hide drop marker
3825 // if (bDragRect)
3826 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3827 bDragRect = FALSE;
3828 UpdateDragRectOverlay();
3830 ScModule* pScMod = SC_MOD();
3831 const ScDragData& rData = pScMod->GetDragData();
3833 return DropTransferObj( rData.pCellTransfer, nDragStartX, nDragStartY,
3834 PixelToLogic(rEvt.maPosPixel), rEvt.mnAction );
3837 sal_Int8 ScGridWindow::DropTransferObj( ScTransferObj* pTransObj, SCCOL nDestPosX, SCROW nDestPosY,
3838 const Point& rLogicPos, sal_Int8 nDndAction )
3840 if ( !pTransObj )
3841 return 0;
3843 ScDocument* pSourceDoc = pTransObj->GetSourceDocument();
3844 ScDocShell* pDocSh = pViewData->GetDocShell();
3845 ScDocument* pThisDoc = pViewData->GetDocument();
3846 ScViewFunc* pView = pViewData->GetView();
3847 SCTAB nThisTab = pViewData->GetTabNo();
3848 USHORT nFlags = pTransObj->GetDragSourceFlags();
3850 BOOL bIsNavi = ( nFlags & SC_DROP_NAVIGATOR ) != 0;
3851 BOOL bIsMove = ( nDndAction == DND_ACTION_MOVE && !bIsNavi );
3853 // workaround for wrong nDndAction on Windows when pressing solely
3854 // the Alt key during drag and drop;
3855 // can be removed after #i79215# has been fixed
3856 if ( meDragInsertMode != INS_NONE )
3858 bIsMove = ( nDndAction & DND_ACTION_MOVE && !bIsNavi );
3861 BOOL bIsLink = ( nDndAction == DND_ACTION_LINK );
3863 ScRange aSource = pTransObj->GetRange();
3865 // only use visible tab from source range - when dragging within one table,
3866 // all selected tables at the time of dropping are used (handled in MoveBlockTo)
3867 SCTAB nSourceTab = pTransObj->GetVisibleTab();
3868 aSource.aStart.SetTab( nSourceTab );
3869 aSource.aEnd.SetTab( nSourceTab );
3871 SCCOL nSizeX = aSource.aEnd.Col() - aSource.aStart.Col() + 1;
3872 SCROW nSizeY = (bIsMove ? (aSource.aEnd.Row() - aSource.aStart.Row() + 1) :
3873 pTransObj->GetNonFilteredRows()); // copy/link: no filtered rows
3874 ScRange aDest( nDestPosX, nDestPosY, nThisTab,
3875 nDestPosX + nSizeX - 1, nDestPosY + nSizeY - 1, nThisTab );
3878 /* NOTE: AcceptPrivateDrop() already checked for filtered conditions during
3879 * dragging and adapted drawing of the selection frame. We check here
3880 * (again) because this may actually also be called from PasteSelection(),
3881 * we would have to duplicate determination of flags and destination range
3882 * and would lose the context of the "filtered destination is OK" cases
3883 * below, which is already awkward enough as is. */
3885 // Don't move filtered source.
3886 bool bFiltered = (bIsMove && pTransObj->HasFilteredRows());
3887 if (!bFiltered)
3889 if (pSourceDoc != pThisDoc && ((nFlags & SC_DROP_TABLE) ||
3890 (!bIsLink && meDragInsertMode == INS_NONE)))
3892 // Nothing. Either entire sheet to be dropped, or the one case
3893 // where PasteFromClip() is to be called that handles a filtered
3894 // destination itself. Drag-copy from another document without
3895 // inserting cells.
3897 else
3898 // Don't copy or move to filtered destination.
3899 bFiltered = ScViewUtil::HasFiltered( aDest, pThisDoc);
3902 BOOL bDone = FALSE;
3904 if (!bFiltered && pSourceDoc == pThisDoc)
3906 if ( nFlags & SC_DROP_TABLE ) // whole sheet?
3908 if ( pThisDoc->IsDocEditable() )
3910 SCTAB nSrcTab = aSource.aStart.Tab();
3911 pViewData->GetDocShell()->MoveTable( nSrcTab, nThisTab, !bIsMove, TRUE ); // with Undo
3912 pView->SetTabNo( nThisTab, TRUE );
3913 bDone = TRUE;
3916 else // move/copy block
3918 String aChartName;
3919 if (pThisDoc->HasChartAtPoint( nThisTab, rLogicPos, &aChartName ))
3921 String aRangeName;
3922 aSource.Format( aRangeName, SCR_ABS_3D, pThisDoc );
3923 SfxStringItem aNameItem( SID_CHART_NAME, aChartName );
3924 SfxStringItem aRangeItem( SID_CHART_SOURCE, aRangeName );
3925 USHORT nId = bIsMove ? SID_CHART_SOURCE : SID_CHART_ADDSOURCE;
3926 pViewData->GetDispatcher().Execute( nId, SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD,
3927 &aRangeItem, &aNameItem, (void*) NULL );
3928 bDone = TRUE;
3930 else if ( pThisDoc->GetDPAtCursor( nDestPosX, nDestPosY, nThisTab ) )
3932 // drop on DataPilot table: try to sort, fail if that isn't possible
3934 ScAddress aDestPos( nDestPosX, nDestPosY, nThisTab );
3935 if ( aDestPos != aSource.aStart )
3936 bDone = pViewData->GetView()->DataPilotMove( aSource, aDestPos );
3937 else
3938 bDone = TRUE; // same position: nothing
3940 else if ( nDestPosX != aSource.aStart.Col() || nDestPosY != aSource.aStart.Row() ||
3941 nSourceTab != nThisTab )
3943 String aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY );
3944 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
3946 bDone = TRUE;
3947 if ( meDragInsertMode != INS_NONE )
3949 // call with bApi = TRUE to avoid error messages in drop handler
3950 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, TRUE /*bRecord*/, TRUE /*bApi*/, TRUE /*bPartOfPaste*/ );
3951 if ( bDone )
3953 if ( nThisTab == nSourceTab )
3955 if ( meDragInsertMode == INS_CELLSDOWN &&
3956 nDestPosX == aSource.aStart.Col() && nDestPosY < aSource.aStart.Row() )
3958 bDone = aSource.Move( 0, nSizeY, 0, pSourceDoc );
3960 else if ( meDragInsertMode == INS_CELLSRIGHT &&
3961 nDestPosY == aSource.aStart.Row() && nDestPosX < aSource.aStart.Col() )
3963 bDone = aSource.Move( nSizeX, 0, 0, pSourceDoc );
3966 pDocSh->UpdateOle( pViewData );
3967 pView->CellContentChanged();
3971 if ( bDone )
3973 if ( bIsLink )
3975 // call with bApi = TRUE to avoid error messages in drop handler
3976 bDone = pView->LinkBlock( aSource, aDest.aStart, TRUE /*bApi*/ );
3978 else
3980 // call with bApi = TRUE to avoid error messages in drop handler
3981 bDone = pView->MoveBlockTo( aSource, aDest.aStart, bIsMove, TRUE /*bRecord*/, TRUE /*bPaint*/, TRUE /*bApi*/ );
3985 if ( bDone && meDragInsertMode != INS_NONE && bIsMove && nThisTab == nSourceTab )
3987 DelCellCmd eCmd = DEL_NONE;
3988 if ( meDragInsertMode == INS_CELLSDOWN )
3990 eCmd = DEL_CELLSUP;
3992 else if ( meDragInsertMode == INS_CELLSRIGHT )
3994 eCmd = DEL_CELLSLEFT;
3997 if ( ( eCmd == DEL_CELLSUP && nDestPosX == aSource.aStart.Col() ) ||
3998 ( eCmd == DEL_CELLSLEFT && nDestPosY == aSource.aStart.Row() ) )
4000 // call with bApi = TRUE to avoid error messages in drop handler
4001 bDone = pDocSh->GetDocFunc().DeleteCells( aSource, NULL, eCmd, TRUE /*bRecord*/, TRUE /*bApi*/ );
4002 if ( bDone )
4004 if ( eCmd == DEL_CELLSUP && nDestPosY > aSource.aEnd.Row() )
4006 bDone = aDest.Move( 0, -nSizeY, 0, pThisDoc );
4008 else if ( eCmd == DEL_CELLSLEFT && nDestPosX > aSource.aEnd.Col() )
4010 bDone = aDest.Move( -nSizeX, 0, 0, pThisDoc );
4012 pDocSh->UpdateOle( pViewData );
4013 pView->CellContentChanged();
4018 if ( bDone )
4020 pView->MarkRange( aDest, FALSE, FALSE );
4022 SCCOL nDCol = pViewData->GetCurX() - aSource.aStart.Col();
4023 SCROW nDRow = pViewData->GetCurY() - aSource.aStart.Row();
4024 pView->SetCursor( aDest.aStart.Col() + nDCol, aDest.aStart.Row() + nDRow );
4027 pDocSh->GetUndoManager()->LeaveListAction();
4029 if (!bDone)
4030 Sound::Beep(); // instead of error message in drop handler
4032 else
4033 bDone = TRUE; // nothing to do
4036 if (bDone)
4037 pTransObj->SetDragWasInternal(); // don't delete source in DragFinished
4039 else if ( !bFiltered && pSourceDoc ) // between documents
4041 if ( nFlags & SC_DROP_TABLE ) // copy/link sheets between documents
4043 if ( pThisDoc->IsDocEditable() )
4045 ScDocShell* pSrcShell = pTransObj->GetSourceDocShell();
4047 SCTAB nTabs[MAXTABCOUNT];
4049 ScMarkData aMark = pTransObj->GetSourceMarkData();
4050 SCTAB nTabCount = pSourceDoc->GetTableCount();
4051 SCTAB nTabSelCount = 0;
4053 for(SCTAB i=0; i<nTabCount; i++)
4055 if(aMark.GetTableSelect(i))
4057 nTabs[nTabSelCount++]=i;
4058 for(SCTAB j=i+1;j<nTabCount;j++)
4060 if((!pSourceDoc->IsVisible(j))&&(pSourceDoc->IsScenario(j)))
4062 nTabs[nTabSelCount++]=j;
4063 i=j;
4065 else break;
4070 pView->ImportTables( pSrcShell,nTabSelCount, nTabs, bIsLink, nThisTab );
4071 bDone = TRUE;
4074 else if ( bIsLink )
4076 // as in PasteDDE
4077 // (external references might be used instead?)
4079 SfxObjectShell* pSourceSh = pSourceDoc->GetDocumentShell();
4080 DBG_ASSERT(pSourceSh, "drag document has no shell");
4081 if (pSourceSh)
4083 String aUndo = ScGlobal::GetRscString( STR_UNDO_COPY );
4084 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
4086 bDone = TRUE;
4087 if ( meDragInsertMode != INS_NONE )
4089 // call with bApi = TRUE to avoid error messages in drop handler
4090 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, TRUE /*bRecord*/, TRUE /*bApi*/, TRUE /*bPartOfPaste*/ );
4091 if ( bDone )
4093 pDocSh->UpdateOle( pViewData );
4094 pView->CellContentChanged();
4098 if ( bDone )
4100 String aApp = Application::GetAppName();
4101 String aTopic = pSourceSh->GetTitle( SFX_TITLE_FULLNAME );
4102 String aItem;
4103 aSource.Format( aItem, SCA_VALID | SCA_TAB_3D, pSourceDoc );
4105 // TODO: we could define ocQuote for "
4106 const String aQuote( '"' );
4107 const String& sSep = ScCompiler::GetNativeSymbol( ocSep);
4108 String aFormula( '=' );
4109 aFormula += ScCompiler::GetNativeSymbol( ocDde);
4110 aFormula += ScCompiler::GetNativeSymbol( ocOpen);
4111 aFormula += aQuote;
4112 aFormula += aApp;
4113 aFormula += aQuote;
4114 aFormula += sSep;
4115 aFormula += aQuote;
4116 aFormula += aTopic;
4117 aFormula += aQuote;
4118 aFormula += sSep;
4119 aFormula += aQuote;
4120 aFormula += aItem;
4121 aFormula += aQuote;
4122 aFormula += ScCompiler::GetNativeSymbol( ocClose);
4124 pView->DoneBlockMode();
4125 pView->InitBlockMode( nDestPosX, nDestPosY, nThisTab );
4126 pView->MarkCursor( nDestPosX + nSizeX - 1,
4127 nDestPosY + nSizeY - 1, nThisTab );
4129 pView->EnterMatrix( aFormula );
4131 pView->MarkRange( aDest, FALSE, FALSE );
4132 pView->SetCursor( aDest.aStart.Col(), aDest.aStart.Row() );
4135 pDocSh->GetUndoManager()->LeaveListAction();
4138 else
4140 //! HasSelectedBlockMatrixFragment without selected sheet?
4141 //! or don't start dragging on a part of a matrix
4143 String aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY );
4144 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
4146 bDone = TRUE;
4147 if ( meDragInsertMode != INS_NONE )
4149 // call with bApi = TRUE to avoid error messages in drop handler
4150 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, TRUE /*bRecord*/, TRUE /*bApi*/, TRUE /*bPartOfPaste*/ );
4151 if ( bDone )
4153 pDocSh->UpdateOle( pViewData );
4154 pView->CellContentChanged();
4158 if ( bDone )
4160 pView->Unmark(); // before SetCursor, so CheckSelectionTransfer isn't called with a selection
4161 pView->SetCursor( nDestPosX, nDestPosY );
4162 bDone = pView->PasteFromClip( IDF_ALL, pTransObj->GetDocument() ); // clip-doc
4163 if ( bDone )
4165 pView->MarkRange( aDest, FALSE, FALSE );
4166 pView->SetCursor( aDest.aStart.Col(), aDest.aStart.Row() );
4170 pDocSh->GetUndoManager()->LeaveListAction();
4172 // no longer call ResetMark here - the inserted block has been selected
4173 // and may have been copied to primary selection
4177 sal_Int8 nRet = bDone ? nDndAction : DND_ACTION_NONE;
4178 return nRet;
4181 sal_Int8 ScGridWindow::ExecuteDrop( const ExecuteDropEvent& rEvt )
4183 DrawMarkDropObj( NULL ); // drawing layer
4185 ScModule* pScMod = SC_MOD();
4186 const ScDragData& rData = pScMod->GetDragData();
4187 if (rData.pCellTransfer)
4188 return ExecutePrivateDrop( rEvt );
4190 Point aPos = rEvt.maPosPixel;
4192 if ( rData.aLinkDoc.Len() )
4194 // try to insert a link
4196 BOOL bOk = TRUE;
4197 String aThisName;
4198 ScDocShell* pDocSh = pViewData->GetDocShell();
4199 if (pDocSh && pDocSh->HasName())
4200 aThisName = pDocSh->GetMedium()->GetName();
4202 if ( rData.aLinkDoc == aThisName ) // error - no link within a document
4203 bOk = FALSE;
4204 else
4206 ScViewFunc* pView = pViewData->GetView();
4207 if ( rData.aLinkTable.Len() )
4208 pView->InsertTableLink( rData.aLinkDoc, EMPTY_STRING, EMPTY_STRING,
4209 rData.aLinkTable );
4210 else if ( rData.aLinkArea.Len() )
4212 SCsCOL nPosX;
4213 SCsROW nPosY;
4214 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
4215 pView->MoveCursorAbs( nPosX, nPosY, SC_FOLLOW_NONE, FALSE, FALSE );
4217 pView->InsertAreaLink( rData.aLinkDoc, EMPTY_STRING, EMPTY_STRING,
4218 rData.aLinkArea, 0 );
4220 else
4222 DBG_ERROR("drop with link: no sheet nor area");
4223 bOk = FALSE;
4227 return bOk ? rEvt.mnAction : DND_ACTION_NONE; // don't try anything else
4230 Point aLogicPos = PixelToLogic(aPos);
4232 if (rData.pDrawTransfer)
4234 USHORT nFlags = rData.pDrawTransfer->GetDragSourceFlags();
4236 BOOL bIsNavi = ( nFlags & SC_DROP_NAVIGATOR ) != 0;
4237 BOOL bIsMove = ( rEvt.mnAction == DND_ACTION_MOVE && !bIsNavi );
4239 bPasteIsMove = bIsMove;
4241 pViewData->GetView()->PasteDraw( aLogicPos, rData.pDrawTransfer->GetModel() );
4243 if (bPasteIsMove)
4244 rData.pDrawTransfer->SetDragWasInternal();
4245 bPasteIsMove = FALSE;
4247 return rEvt.mnAction;
4251 SCsCOL nPosX;
4252 SCsROW nPosY;
4253 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
4255 if (rData.aJumpTarget.Len())
4257 // internal bookmark (from Navigator)
4258 // bookmark clipboard formats are in PasteScDataObject
4260 if ( !rData.pJumpLocalDoc || rData.pJumpLocalDoc == pViewData->GetDocument() )
4262 pViewData->GetViewShell()->InsertBookmark( rData.aJumpText, rData.aJumpTarget,
4263 nPosX, nPosY );
4264 return rEvt.mnAction;
4268 BOOL bIsLink = ( rEvt.mnAction == DND_ACTION_LINK );
4270 ScDocument* pThisDoc = pViewData->GetDocument();
4271 SdrObject* pHitObj = pThisDoc->GetObjectAtPoint( pViewData->GetTabNo(), PixelToLogic(aPos) );
4272 if ( pHitObj && bIsLink )
4274 // dropped on drawing object
4275 // PasteOnDrawObject checks for valid formats
4276 if ( pViewData->GetView()->PasteOnDrawObject( rEvt.maDropEvent.Transferable, pHitObj, TRUE ) )
4277 return rEvt.mnAction;
4280 BOOL bDone = FALSE;
4282 ULONG nFormatId = bIsLink ?
4283 lcl_GetDropLinkId( rEvt.maDropEvent.Transferable ) :
4284 lcl_GetDropFormatId( rEvt.maDropEvent.Transferable );
4285 if ( nFormatId )
4287 pScMod->SetInExecuteDrop( TRUE ); // #i28468# prevent error messages from PasteDataFormat
4288 bPasteIsDrop = TRUE;
4289 bDone = pViewData->GetView()->PasteDataFormat(
4290 nFormatId, rEvt.maDropEvent.Transferable, nPosX, nPosY, &aLogicPos, bIsLink );
4291 bPasteIsDrop = FALSE;
4292 pScMod->SetInExecuteDrop( FALSE );
4295 sal_Int8 nRet = bDone ? rEvt.mnAction : DND_ACTION_NONE;
4296 return nRet;
4299 //--------------------------------------------------------
4301 void ScGridWindow::PasteSelection( const Point& rPosPixel )
4303 Point aLogicPos = PixelToLogic( rPosPixel );
4305 SCsCOL nPosX;
4306 SCsROW nPosY;
4307 pViewData->GetPosFromPixel( rPosPixel.X(), rPosPixel.Y(), eWhich, nPosX, nPosY );
4309 ScSelectionTransferObj* pOwnSelection = SC_MOD()->GetSelectionTransfer();
4310 if ( pOwnSelection )
4312 // within Calc
4314 ScTransferObj* pCellTransfer = pOwnSelection->GetCellData();
4315 if ( pCellTransfer )
4317 // keep a reference to the data in case the selection is changed during paste
4318 uno::Reference<datatransfer::XTransferable> xRef( pCellTransfer );
4319 DropTransferObj( pCellTransfer, nPosX, nPosY, aLogicPos, DND_ACTION_COPY );
4321 else
4323 ScDrawTransferObj* pDrawTransfer = pOwnSelection->GetDrawData();
4324 if ( pDrawTransfer )
4326 // keep a reference to the data in case the selection is changed during paste
4327 uno::Reference<datatransfer::XTransferable> xRef( pDrawTransfer );
4329 // #96821# bSameDocClipboard argument for PasteDraw is needed
4330 // because only DragData is checked directly inside PasteDraw
4331 pViewData->GetView()->PasteDraw( aLogicPos, pDrawTransfer->GetModel(), FALSE,
4332 pDrawTransfer->GetSourceDocID() == pViewData->GetDocument()->GetDocumentID() );
4336 else
4338 // get selection from system
4340 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSelection( this ) );
4341 uno::Reference<datatransfer::XTransferable> xTransferable = aDataHelper.GetTransferable();
4342 if ( xTransferable.is() )
4344 ULONG nFormatId = lcl_GetDropFormatId( xTransferable, true );
4345 if ( nFormatId )
4347 bPasteIsDrop = TRUE;
4348 pViewData->GetView()->PasteDataFormat( nFormatId, xTransferable, nPosX, nPosY, &aLogicPos );
4349 bPasteIsDrop = FALSE;
4355 //--------------------------------------------------------
4357 void ScGridWindow::UpdateEditViewPos()
4359 if (pViewData->HasEditView(eWhich))
4361 EditView* pView;
4362 SCCOL nCol;
4363 SCROW nRow;
4364 pViewData->GetEditView( eWhich, pView, nCol, nRow );
4365 SCCOL nEndCol = pViewData->GetEditEndCol();
4366 SCROW nEndRow = pViewData->GetEditEndRow();
4368 // hide EditView?
4370 BOOL bHide = ( nEndCol<pViewData->GetPosX(eHWhich) || nEndRow<pViewData->GetPosY(eVWhich) );
4371 if ( SC_MOD()->IsFormulaMode() )
4372 if ( pViewData->GetTabNo() != pViewData->GetRefTabNo() )
4373 bHide = TRUE;
4375 if (bHide)
4377 Rectangle aRect = pView->GetOutputArea();
4378 long nHeight = aRect.Bottom() - aRect.Top();
4379 aRect.Top() = PixelToLogic(GetOutputSizePixel(), pViewData->GetLogicMode()).
4380 Height() * 2;
4381 aRect.Bottom() = aRect.Top() + nHeight;
4382 pView->SetOutputArea( aRect );
4383 pView->HideCursor();
4385 else
4387 // bForceToTop = TRUE for editing
4388 Rectangle aPixRect = pViewData->GetEditArea( eWhich, nCol, nRow, this, NULL, TRUE );
4389 Point aScrPos = PixelToLogic( aPixRect.TopLeft(), pViewData->GetLogicMode() );
4391 Rectangle aRect = pView->GetOutputArea();
4392 aRect.SetPos( aScrPos );
4393 pView->SetOutputArea( aRect );
4394 pView->ShowCursor();
4399 void ScGridWindow::ScrollPixel( long nDifX, long nDifY )
4401 ClickExtern();
4402 HideNoteMarker();
4404 bIsInScroll = TRUE;
4405 //BOOL bXor=DrawBeforeScroll();
4407 SetMapMode(MAP_PIXEL);
4408 Scroll( nDifX, nDifY, SCROLL_CHILDREN );
4409 SetMapMode( GetDrawMapMode() ); // verschobenen MapMode erzeugen
4411 UpdateEditViewPos();
4413 DrawAfterScroll(); //bXor);
4414 bIsInScroll = FALSE;
4417 // Formeln neu zeichnen -------------------------------------------------
4419 void ScGridWindow::UpdateFormulas()
4421 if (pViewData->GetView()->IsMinimized())
4422 return;
4424 if ( nPaintCount )
4426 // nicht anfangen, verschachtelt zu painten
4427 // (dann wuerde zumindest der MapMode nicht mehr stimmen)
4429 bNeedsRepaint = TRUE; // -> am Ende vom Paint nochmal Invalidate auf alles
4430 aRepaintPixel = Rectangle(); // alles
4431 return;
4434 SCCOL nX1 = pViewData->GetPosX( eHWhich );
4435 SCROW nY1 = pViewData->GetPosY( eVWhich );
4436 SCCOL nX2 = nX1 + pViewData->VisibleCellsX( eHWhich );
4437 SCROW nY2 = nY1 + pViewData->VisibleCellsY( eVWhich );
4439 if (nX2 > MAXCOL) nX2 = MAXCOL;
4440 if (nY2 > MAXROW) nY2 = MAXROW;
4442 // Draw( nX1, nY1, nX2, nY2, SC_UPDATE_CHANGED );
4444 // don't draw directly - instead use OutputData to find changed area and invalidate
4446 SCROW nPosY = nY1;
4448 ScDocShell* pDocSh = pViewData->GetDocShell();
4449 ScDocument* pDoc = pDocSh->GetDocument();
4450 SCTAB nTab = pViewData->GetTabNo();
4452 pDoc->ExtendHidden( nX1, nY1, nX2, nY2, nTab );
4454 Point aScrPos = pViewData->GetScrPos( nX1, nY1, eWhich );
4455 long nMirrorWidth = GetSizePixel().Width();
4456 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
4457 // unused variable long nLayoutSign = bLayoutRTL ? -1 : 1;
4458 if ( bLayoutRTL )
4460 long nEndPixel = pViewData->GetScrPos( nX2+1, nPosY, eWhich ).X();
4461 nMirrorWidth = aScrPos.X() - nEndPixel;
4462 aScrPos.X() = nEndPixel + 1;
4465 long nScrX = aScrPos.X();
4466 long nScrY = aScrPos.Y();
4468 double nPPTX = pViewData->GetPPTX();
4469 double nPPTY = pViewData->GetPPTY();
4471 ScTableInfo aTabInfo;
4472 pDoc->FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nTab, nPPTX, nPPTY, FALSE, FALSE );
4474 Fraction aZoomX = pViewData->GetZoomX();
4475 Fraction aZoomY = pViewData->GetZoomY();
4476 ScOutputData aOutputData( this, OUTTYPE_WINDOW, aTabInfo, pDoc, nTab,
4477 nScrX, nScrY, nX1, nY1, nX2, nY2, nPPTX, nPPTY,
4478 &aZoomX, &aZoomY );
4479 aOutputData.SetMirrorWidth( nMirrorWidth );
4481 aOutputData.FindChanged();
4483 PolyPolygon aChangedPoly( aOutputData.GetChangedArea() ); // logic (PixelToLogic)
4484 if ( aChangedPoly.Count() )
4486 Invalidate( aChangedPoly );
4489 CheckNeedsRepaint(); // #i90362# used to be called via Draw() - still needed here
4492 void ScGridWindow::UpdateAutoFillMark(BOOL bMarked, const ScRange& rMarkRange)
4494 if ( bMarked != bAutoMarkVisible || ( bMarked && rMarkRange.aEnd != aAutoMarkPos ) )
4496 HideCursor();
4497 bAutoMarkVisible = bMarked;
4498 if ( bMarked )
4499 aAutoMarkPos = rMarkRange.aEnd;
4500 ShowCursor();
4502 UpdateAutoFillOverlay();
4506 void ScGridWindow::UpdateListValPos( BOOL bVisible, const ScAddress& rPos )
4508 BOOL bOldButton = bListValButton;
4509 ScAddress aOldPos = aListValPos;
4511 bListValButton = bVisible;
4512 aListValPos = rPos;
4514 if ( bListValButton )
4516 if ( !bOldButton || aListValPos != aOldPos )
4518 // paint area of new button
4519 Invalidate( PixelToLogic( GetListValButtonRect( aListValPos ) ) );
4522 if ( bOldButton )
4524 if ( !bListValButton || aListValPos != aOldPos )
4526 // paint area of old button
4527 Invalidate( PixelToLogic( GetListValButtonRect( aOldPos ) ) );
4532 void ScGridWindow::HideCursor()
4534 ++nCursorHideCount;
4535 if (nCursorHideCount==1)
4537 DrawCursor();
4538 DrawAutoFillMark();
4542 void ScGridWindow::ShowCursor()
4544 if (nCursorHideCount==0)
4546 DBG_ERROR("zuviel ShowCursor");
4547 return;
4550 if (nCursorHideCount==1)
4552 // #i57745# Draw the cursor before setting the variable, in case the
4553 // GetSizePixel call from drawing causes a repaint (resize handler is called)
4554 DrawAutoFillMark();
4555 DrawCursor();
4558 --nCursorHideCount;
4561 void __EXPORT ScGridWindow::GetFocus()
4563 ScTabViewShell* pViewShell = pViewData->GetViewShell();
4564 pViewShell->GotFocus();
4565 pViewShell->SetFormShellAtTop( FALSE ); // focus in GridWindow -> FormShell no longer on top
4567 if (pViewShell->HasAccessibilityObjects())
4568 pViewShell->BroadcastAccessibility(ScAccGridWinFocusGotHint(eWhich, GetAccessible()));
4571 if ( !SC_MOD()->IsFormulaMode() )
4573 pViewShell->UpdateInputHandler();
4574 // StopMarking(); // falls Dialog (Fehler), weil dann kein ButtonUp
4575 // MO: nur wenn nicht im RefInput-Modus
4576 // -> GetFocus/MouseButtonDown-Reihenfolge
4577 // auf dem Mac
4580 Window::GetFocus();
4583 void __EXPORT ScGridWindow::LoseFocus()
4585 ScTabViewShell* pViewShell = pViewData->GetViewShell();
4586 pViewShell->LostFocus();
4588 if (pViewShell->HasAccessibilityObjects())
4589 pViewShell->BroadcastAccessibility(ScAccGridWinFocusLostHint(eWhich, GetAccessible()));
4591 Window::LoseFocus();
4594 Point ScGridWindow::GetMousePosPixel() const { return aCurMousePos; }
4596 //------------------------------------------------------------------------
4598 BOOL ScGridWindow::HitRangeFinder( const Point& rMouse, BOOL& rCorner,
4599 USHORT* pIndex, SCsCOL* pAddX, SCsROW* pAddY )
4601 BOOL bFound = FALSE;
4602 ScInputHandler* pHdl = SC_MOD()->GetInputHdl( pViewData->GetViewShell() );
4603 if (pHdl)
4605 ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList();
4606 if ( pRangeFinder && !pRangeFinder->IsHidden() &&
4607 pRangeFinder->GetDocName() == pViewData->GetDocShell()->GetTitle() )
4609 ScDocument* pDoc = pViewData->GetDocument();
4610 SCTAB nTab = pViewData->GetTabNo();
4611 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
4612 long nLayoutSign = bLayoutRTL ? -1 : 1;
4614 SCsCOL nPosX;
4615 SCsROW nPosY;
4616 pViewData->GetPosFromPixel( rMouse.X(), rMouse.Y(), eWhich, nPosX, nPosY );
4617 // zusammengefasste (einzeln/Bereich) ???
4618 ScAddress aAddr( nPosX, nPosY, nTab );
4620 // Point aNext = pViewData->GetScrPos( nPosX+1, nPosY+1, eWhich );
4622 Point aNext = pViewData->GetScrPos( nPosX, nPosY, eWhich, TRUE );
4623 long nSizeXPix;
4624 long nSizeYPix;
4625 pViewData->GetMergeSizePixel( nPosX, nPosY, nSizeXPix, nSizeYPix );
4626 aNext.X() += nSizeXPix * nLayoutSign;
4627 aNext.Y() += nSizeYPix;
4629 BOOL bCornerHor;
4630 if ( bLayoutRTL )
4631 bCornerHor = ( rMouse.X() >= aNext.X() && rMouse.X() <= aNext.X() + 8 );
4632 else
4633 bCornerHor = ( rMouse.X() >= aNext.X() - 8 && rMouse.X() <= aNext.X() );
4635 BOOL bCellCorner = ( bCornerHor &&
4636 rMouse.Y() >= aNext.Y() - 8 && rMouse.Y() <= aNext.Y() );
4637 // corner is hit only if the mouse is within the cell
4639 USHORT nCount = (USHORT)pRangeFinder->Count();
4640 for (USHORT i=nCount; i;)
4642 // rueckwaerts suchen, damit der zuletzt gepaintete Rahmen gefunden wird
4643 --i;
4644 ScRangeFindData* pData = pRangeFinder->GetObject(i);
4645 if ( pData && pData->aRef.In(aAddr) )
4647 if (pIndex) *pIndex = i;
4648 if (pAddX) *pAddX = nPosX - pData->aRef.aStart.Col();
4649 if (pAddY) *pAddY = nPosY - pData->aRef.aStart.Row();
4650 bFound = TRUE;
4651 rCorner = ( bCellCorner && aAddr == pData->aRef.aEnd );
4652 break;
4657 return bFound;
4660 #define SCE_TOP 1
4661 #define SCE_BOTTOM 2
4662 #define SCE_LEFT 4
4663 #define SCE_RIGHT 8
4664 #define SCE_ALL 15
4666 void lcl_PaintOneRange( ScDocShell* pDocSh, const ScRange& rRange, USHORT nEdges )
4668 // der Range ist immer richtigherum
4670 SCCOL nCol1 = rRange.aStart.Col();
4671 SCROW nRow1 = rRange.aStart.Row();
4672 SCTAB nTab1 = rRange.aStart.Tab();
4673 SCCOL nCol2 = rRange.aEnd.Col();
4674 SCROW nRow2 = rRange.aEnd.Row();
4675 SCTAB nTab2 = rRange.aEnd.Tab();
4676 BOOL bHiddenEdge = FALSE;
4677 SCROW nTmp;
4679 ScDocument* pDoc = pDocSh->GetDocument();
4680 while ( nCol1 > 0 && pDoc->ColHidden(nCol1, nTab1) )
4682 --nCol1;
4683 bHiddenEdge = TRUE;
4685 while ( nCol2 < MAXCOL && pDoc->ColHidden(nCol2, nTab1) )
4687 ++nCol2;
4688 bHiddenEdge = TRUE;
4690 nTmp = pDoc->FirstVisibleRow(0, nRow1, nTab1);
4691 if (!ValidRow(nTmp))
4692 nTmp = 0;
4693 if (nTmp < nRow1)
4695 nRow1 = nTmp;
4696 bHiddenEdge = TRUE;
4698 nTmp = pDoc->FirstVisibleRow(nRow2, MAXROW, nTab1);
4699 if (!ValidRow(nTmp))
4700 nTmp = MAXROW;
4701 if (nTmp > nRow2)
4703 nRow2 = nTmp;
4704 bHiddenEdge = TRUE;
4707 if ( nCol2 > nCol1 + 1 && nRow2 > nRow1 + 1 && !bHiddenEdge )
4709 // nur an den Raendern entlang
4710 // (die Ecken werden evtl. zweimal getroffen)
4712 if ( nEdges & SCE_TOP )
4713 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol2, nRow1, nTab2, PAINT_MARKS );
4714 if ( nEdges & SCE_LEFT )
4715 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol1, nRow2, nTab2, PAINT_MARKS );
4716 if ( nEdges & SCE_RIGHT )
4717 pDocSh->PostPaint( nCol2, nRow1, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
4718 if ( nEdges & SCE_BOTTOM )
4719 pDocSh->PostPaint( nCol1, nRow2, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
4721 else // everything in one call
4722 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
4725 void lcl_PaintRefChanged( ScDocShell* pDocSh, const ScRange& rOldUn, const ScRange& rNewUn )
4727 // Repaint fuer die Teile des Rahmens in Old, die bei New nicht mehr da sind
4729 ScRange aOld = rOldUn;
4730 ScRange aNew = rNewUn;
4731 aOld.Justify();
4732 aNew.Justify();
4734 if ( aOld.aStart == aOld.aEnd ) //! Tab ignorieren?
4735 pDocSh->GetDocument()->ExtendMerge(aOld);
4736 if ( aNew.aStart == aNew.aEnd ) //! Tab ignorieren?
4737 pDocSh->GetDocument()->ExtendMerge(aNew);
4739 SCCOL nOldCol1 = aOld.aStart.Col();
4740 SCROW nOldRow1 = aOld.aStart.Row();
4741 SCCOL nOldCol2 = aOld.aEnd.Col();
4742 SCROW nOldRow2 = aOld.aEnd.Row();
4743 SCCOL nNewCol1 = aNew.aStart.Col();
4744 SCROW nNewRow1 = aNew.aStart.Row();
4745 SCCOL nNewCol2 = aNew.aEnd.Col();
4746 SCROW nNewRow2 = aNew.aEnd.Row();
4747 SCTAB nTab1 = aOld.aStart.Tab(); // Tab aendert sich nicht
4748 SCTAB nTab2 = aOld.aEnd.Tab();
4750 if ( nNewRow2 < nOldRow1 || nNewRow1 > nOldRow2 ||
4751 nNewCol2 < nOldCol1 || nNewCol1 > nOldCol2 ||
4752 ( nNewCol1 != nOldCol1 && nNewRow1 != nOldRow1 &&
4753 nNewCol2 != nOldCol2 && nNewRow2 != nOldRow2 ) )
4755 // komplett weggeschoben oder alle Seiten veraendert
4756 // (Abfrage <= statt < geht schief bei einzelnen Zeilen/Spalten)
4758 lcl_PaintOneRange( pDocSh, aOld, SCE_ALL );
4760 else // alle vier Kanten einzeln testen
4762 // oberer Teil
4763 if ( nNewRow1 < nOldRow1 ) // nur obere Linie loeschen
4764 lcl_PaintOneRange( pDocSh, ScRange(
4765 nOldCol1, nOldRow1, nTab1, nOldCol2, nOldRow1, nTab2 ), SCE_ALL );
4766 else if ( nNewRow1 > nOldRow1 ) // den Teil, der oben wegkommt
4767 lcl_PaintOneRange( pDocSh, ScRange(
4768 nOldCol1, nOldRow1, nTab1, nOldCol2, nNewRow1-1, nTab2 ),
4769 SCE_ALL &~ SCE_BOTTOM );
4771 // unterer Teil
4772 if ( nNewRow2 > nOldRow2 ) // nur untere Linie loeschen
4773 lcl_PaintOneRange( pDocSh, ScRange(
4774 nOldCol1, nOldRow2, nTab1, nOldCol2, nOldRow2, nTab2 ), SCE_ALL );
4775 else if ( nNewRow2 < nOldRow2 ) // den Teil, der unten wegkommt
4776 lcl_PaintOneRange( pDocSh, ScRange(
4777 nOldCol1, nNewRow2+1, nTab1, nOldCol2, nOldRow2, nTab2 ),
4778 SCE_ALL &~ SCE_TOP );
4780 // linker Teil
4781 if ( nNewCol1 < nOldCol1 ) // nur linke Linie loeschen
4782 lcl_PaintOneRange( pDocSh, ScRange(
4783 nOldCol1, nOldRow1, nTab1, nOldCol1, nOldRow2, nTab2 ), SCE_ALL );
4784 else if ( nNewCol1 > nOldCol1 ) // den Teil, der links wegkommt
4785 lcl_PaintOneRange( pDocSh, ScRange(
4786 nOldCol1, nOldRow1, nTab1, nNewCol1-1, nOldRow2, nTab2 ),
4787 SCE_ALL &~ SCE_RIGHT );
4789 // rechter Teil
4790 if ( nNewCol2 > nOldCol2 ) // nur rechte Linie loeschen
4791 lcl_PaintOneRange( pDocSh, ScRange(
4792 nOldCol2, nOldRow1, nTab1, nOldCol2, nOldRow2, nTab2 ), SCE_ALL );
4793 else if ( nNewCol2 < nOldCol2 ) // den Teil, der rechts wegkommt
4794 lcl_PaintOneRange( pDocSh, ScRange(
4795 nNewCol2+1, nOldRow1, nTab1, nOldCol2, nOldRow2, nTab2 ),
4796 SCE_ALL &~ SCE_LEFT );
4800 void ScGridWindow::RFMouseMove( const MouseEvent& rMEvt, BOOL bUp )
4802 ScInputHandler* pHdl = SC_MOD()->GetInputHdl( pViewData->GetViewShell() );
4803 if (!pHdl)
4804 return;
4805 ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList();
4806 if (!pRangeFinder || nRFIndex >= pRangeFinder->Count())
4807 return;
4808 ScRangeFindData* pData = pRangeFinder->GetObject( nRFIndex );
4809 if (!pData)
4810 return;
4812 // Mauszeiger
4814 if (bRFSize)
4815 SetPointer( Pointer( POINTER_CROSS ) );
4816 else
4817 SetPointer( Pointer( POINTER_HAND ) );
4819 // Scrolling
4821 BOOL bTimer = FALSE;
4822 Point aPos = rMEvt.GetPosPixel();
4823 SCsCOL nDx = 0;
4824 SCsROW nDy = 0;
4825 if ( aPos.X() < 0 ) nDx = -1;
4826 if ( aPos.Y() < 0 ) nDy = -1;
4827 Size aSize = GetOutputSizePixel();
4828 if ( aPos.X() >= aSize.Width() )
4829 nDx = 1;
4830 if ( aPos.Y() >= aSize.Height() )
4831 nDy = 1;
4832 if ( nDx != 0 || nDy != 0 )
4834 if ( nDx != 0) pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) );
4835 if ( nDy != 0 ) pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) );
4836 bTimer = TRUE;
4839 // Umschalten bei Fixierung (damit Scrolling funktioniert)
4841 if ( eWhich == pViewData->GetActivePart() ) //??
4843 if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX )
4844 if ( nDx > 0 )
4846 if ( eWhich == SC_SPLIT_TOPLEFT )
4847 pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT );
4848 else if ( eWhich == SC_SPLIT_BOTTOMLEFT )
4849 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT );
4852 if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX )
4853 if ( nDy > 0 )
4855 if ( eWhich == SC_SPLIT_TOPLEFT )
4856 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT );
4857 else if ( eWhich == SC_SPLIT_TOPRIGHT )
4858 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT );
4862 // Verschieben
4864 SCsCOL nPosX;
4865 SCsROW nPosY;
4866 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
4868 ScRange aOld = pData->aRef;
4869 ScRange aNew = aOld;
4870 if ( bRFSize )
4872 aNew.aEnd.SetCol((SCCOL)nPosX);
4873 aNew.aEnd.SetRow((SCROW)nPosY);
4875 else
4877 long nStartX = nPosX - nRFAddX;
4878 if ( nStartX < 0 ) nStartX = 0;
4879 long nStartY = nPosY - nRFAddY;
4880 if ( nStartY < 0 ) nStartY = 0;
4881 long nEndX = nStartX + aOld.aEnd.Col() - aOld.aStart.Col();
4882 if ( nEndX > MAXCOL )
4884 nStartX -= ( nEndX - MAXROW );
4885 nEndX = MAXCOL;
4887 long nEndY = nStartY + aOld.aEnd.Row() - aOld.aStart.Row();
4888 if ( nEndY > MAXROW )
4890 nStartY -= ( nEndY - MAXROW );
4891 nEndY = MAXROW;
4894 aNew.aStart.SetCol((SCCOL)nStartX);
4895 aNew.aStart.SetRow((SCROW)nStartY);
4896 aNew.aEnd.SetCol((SCCOL)nEndX);
4897 aNew.aEnd.SetRow((SCROW)nEndY);
4900 if ( bUp )
4901 aNew.Justify(); // beim ButtonUp wieder richtigherum
4903 if ( aNew != aOld )
4905 pHdl->UpdateRange( nRFIndex, aNew );
4907 ScDocShell* pDocSh = pViewData->GetDocShell();
4909 // nur das neuzeichnen, was sich veraendert hat...
4910 lcl_PaintRefChanged( pDocSh, aOld, aNew );
4912 // neuen Rahmen nur drueberzeichnen (synchron)
4913 pDocSh->Broadcast( ScIndexHint( SC_HINT_SHOWRANGEFINDER, nRFIndex ) );
4915 Update(); // was man bewegt, will man auch sofort sehen
4918 // Timer fuer Scrolling
4920 if (bTimer)
4921 pViewData->GetView()->SetTimer( this, rMEvt ); // Event wiederholen
4922 else
4923 pViewData->GetView()->ResetTimer();
4926 //------------------------------------------------------------------------
4928 BOOL ScGridWindow::GetEditUrl( const Point& rPos,
4929 String* pName, String* pUrl, String* pTarget )
4931 return GetEditUrlOrError( FALSE, rPos, pName, pUrl, pTarget );
4934 BOOL ScGridWindow::GetEditUrlOrError( BOOL bSpellErr, const Point& rPos,
4935 String* pName, String* pUrl, String* pTarget )
4937 //! nPosX/Y mit uebergeben?
4938 SCsCOL nPosX;
4939 SCsROW nPosY;
4940 pViewData->GetPosFromPixel( rPos.X(), rPos.Y(), eWhich, nPosX, nPosY );
4942 SCTAB nTab = pViewData->GetTabNo();
4943 ScDocShell* pDocSh = pViewData->GetDocShell();
4944 ScDocument* pDoc = pDocSh->GetDocument();
4945 ScBaseCell* pCell = NULL;
4947 BOOL bFound = lcl_GetHyperlinkCell( pDoc, nPosX, nPosY, nTab, pCell );
4948 if( !bFound )
4949 return FALSE;
4951 ScHideTextCursor aHideCursor( pViewData, eWhich ); // before GetEditArea (MapMode is changed)
4953 const ScPatternAttr* pPattern = pDoc->GetPattern( nPosX, nPosY, nTab );
4954 // bForceToTop = FALSE, use the cell's real position
4955 Rectangle aEditRect = pViewData->GetEditArea( eWhich, nPosX, nPosY, this, pPattern, FALSE );
4956 if (rPos.Y() < aEditRect.Top())
4957 return FALSE;
4959 // vertikal kann (noch) nicht angeklickt werden:
4961 if (pPattern->GetCellOrientation() != SVX_ORIENTATION_STANDARD)
4962 return FALSE;
4964 BOOL bBreak = ((SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK)).GetValue() ||
4965 ((SvxCellHorJustify)((const SvxHorJustifyItem&)pPattern->
4966 GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_BLOCK);
4967 SvxCellHorJustify eHorJust = (SvxCellHorJustify)((SvxHorJustifyItem&)pPattern->
4968 GetItem(ATTR_HOR_JUSTIFY)).GetValue();
4970 // EditEngine
4972 ScFieldEditEngine aEngine( pDoc->GetEditPool() );
4973 ScSizeDeviceProvider aProv(pDocSh);
4974 aEngine.SetRefDevice( aProv.GetDevice() );
4975 aEngine.SetRefMapMode( MAP_100TH_MM );
4976 SfxItemSet aDefault( aEngine.GetEmptyItemSet() );
4977 pPattern->FillEditItemSet( &aDefault );
4978 SvxAdjust eSvxAdjust = SVX_ADJUST_LEFT;
4979 switch (eHorJust)
4981 case SVX_HOR_JUSTIFY_LEFT:
4982 case SVX_HOR_JUSTIFY_REPEAT: // nicht implementiert
4983 case SVX_HOR_JUSTIFY_STANDARD: // always Text if an EditCell type
4984 eSvxAdjust = SVX_ADJUST_LEFT;
4985 break;
4986 case SVX_HOR_JUSTIFY_RIGHT:
4987 eSvxAdjust = SVX_ADJUST_RIGHT;
4988 break;
4989 case SVX_HOR_JUSTIFY_CENTER:
4990 eSvxAdjust = SVX_ADJUST_CENTER;
4991 break;
4992 case SVX_HOR_JUSTIFY_BLOCK:
4993 eSvxAdjust = SVX_ADJUST_BLOCK;
4994 break;
4996 aDefault.Put( SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) );
4997 aEngine.SetDefaults( aDefault );
4998 if (bSpellErr)
4999 aEngine.SetControlWord( aEngine.GetControlWord() | EE_CNTRL_ONLINESPELLING );
5001 MapMode aEditMode = pViewData->GetLogicMode(eWhich); // ohne Drawing-Skalierung
5002 Rectangle aLogicEdit = PixelToLogic( aEditRect, aEditMode );
5003 long nThisColLogic = aLogicEdit.Right() - aLogicEdit.Left() + 1;
5004 Size aPaperSize = Size( 1000000, 1000000 );
5005 if(pCell->GetCellType() == CELLTYPE_FORMULA)
5007 long nSizeX = 0;
5008 long nSizeY = 0;
5009 pViewData->GetMergeSizePixel( nPosX, nPosY, nSizeX, nSizeY );
5010 aPaperSize = Size(nSizeX, nSizeY );
5011 aPaperSize = PixelToLogic(aPaperSize);
5014 if (bBreak)
5015 aPaperSize.Width() = nThisColLogic;
5016 aEngine.SetPaperSize( aPaperSize );
5018 ::std::auto_ptr< EditTextObject > pTextObj;
5019 const EditTextObject* pData;
5020 if(pCell->GetCellType() == CELLTYPE_EDIT)
5022 ((ScEditCell*)pCell)->GetData(pData);
5023 if (pData)
5024 aEngine.SetText(*pData);
5026 else // HyperLink Formula cell
5028 pTextObj.reset((static_cast<ScFormulaCell*>(pCell))->CreateURLObject());
5029 if (pTextObj.get())
5030 aEngine.SetText(*pTextObj);
5033 long nStartX = aLogicEdit.Left();
5035 long nTextWidth = aEngine.CalcTextWidth();
5036 long nTextHeight = aEngine.GetTextHeight();
5037 if ( nTextWidth < nThisColLogic )
5039 if (eHorJust == SVX_HOR_JUSTIFY_RIGHT)
5040 nStartX += nThisColLogic - nTextWidth;
5041 else if (eHorJust == SVX_HOR_JUSTIFY_CENTER)
5042 nStartX += (nThisColLogic - nTextWidth) / 2;
5045 aLogicEdit.Left() = nStartX;
5046 if (!bBreak)
5047 aLogicEdit.Right() = nStartX + nTextWidth;
5049 // There is one glitch when dealing with a hyperlink cell and
5050 // the cell content is NUMERIC. This defaults to right aligned and
5051 // we need to adjust accordingly.
5052 if(pCell->GetCellType() == CELLTYPE_FORMULA &&
5053 static_cast<ScFormulaCell*>(pCell)->IsValue() &&
5054 eHorJust == SVX_HOR_JUSTIFY_STANDARD)
5056 aLogicEdit.Right() = aLogicEdit.Left() + nThisColLogic - 1;
5057 aLogicEdit.Left() = aLogicEdit.Right() - nTextWidth;
5059 aLogicEdit.Bottom() = aLogicEdit.Top() + nTextHeight;
5062 Point aLogicClick = PixelToLogic(rPos,aEditMode);
5063 if ( aLogicEdit.IsInside(aLogicClick) )
5065 // aEngine.SetUpdateMode(FALSE);
5066 EditView aTempView( &aEngine, this );
5067 aTempView.SetOutputArea( aLogicEdit );
5069 BOOL bRet = FALSE;
5070 MapMode aOld = GetMapMode();
5071 SetMapMode(aEditMode); // kein return mehr
5073 if (bSpellErr) // Spelling-Fehler suchen
5075 bRet = aTempView.IsWrongSpelledWordAtPos( rPos );
5076 if ( bRet )
5077 pViewData->GetView()->SetCursor( nPosX, nPosY ); // Cursor setzen
5079 else // URL suchen
5081 const SvxFieldItem* pFieldItem = aTempView.GetFieldUnderMousePointer();
5083 if (pFieldItem)
5085 const SvxFieldData* pField = pFieldItem->GetField();
5086 if ( pField && pField->ISA(SvxURLField) )
5088 if ( pName || pUrl || pTarget )
5090 const SvxURLField* pURLField = (const SvxURLField*)pField;
5091 if (pName)
5092 *pName = pURLField->GetRepresentation();
5093 if (pUrl)
5094 *pUrl = pURLField->GetURL();
5095 if (pTarget)
5096 *pTarget = pURLField->GetTargetFrame();
5098 bRet = TRUE;
5103 SetMapMode(aOld);
5105 // text cursor is restored in ScHideTextCursor dtor
5107 return bRet;
5109 return FALSE;
5112 BOOL ScGridWindow::HasScenarioButton( const Point& rPosPixel, ScRange& rScenRange )
5114 ScDocument* pDoc = pViewData->GetDocument();
5115 SCTAB nTab = pViewData->GetTabNo();
5116 SCTAB nTabCount = pDoc->GetTableCount();
5117 if ( nTab+1<nTabCount && pDoc->IsScenario(nTab+1) && !pDoc->IsScenario(nTab) )
5119 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5121 Size aButSize = pViewData->GetScenButSize();
5122 long nBWidth = aButSize.Width();
5123 if (!nBWidth)
5124 return FALSE; // noch kein Button gezeichnet -> da ist auch keiner
5125 long nBHeight = aButSize.Height();
5126 long nHSpace = (long)( SC_SCENARIO_HSPACE * pViewData->GetPPTX() );
5128 //! Ranges an der Table cachen!!!!
5130 ScMarkData aMarks;
5131 for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
5132 pDoc->MarkScenario( i, nTab, aMarks, FALSE, SC_SCENARIO_SHOWFRAME );
5133 ScRangeList aRanges;
5134 aMarks.FillRangeListWithMarks( &aRanges, FALSE );
5137 ULONG nRangeCount = aRanges.Count();
5138 for (ULONG j=0; j<nRangeCount; j++)
5140 ScRange aRange = *aRanges.GetObject(j);
5141 // Szenario-Rahmen immer dann auf zusammengefasste Zellen erweitern, wenn
5142 // dadurch keine neuen nicht-ueberdeckten Zellen mit umrandet werden
5143 pDoc->ExtendTotalMerge( aRange );
5145 BOOL bTextBelow = ( aRange.aStart.Row() == 0 );
5147 Point aButtonPos;
5148 if ( bTextBelow )
5150 aButtonPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aEnd.Row()+1,
5151 eWhich, TRUE );
5153 else
5155 aButtonPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aStart.Row(),
5156 eWhich, TRUE );
5157 aButtonPos.Y() -= nBHeight;
5159 if ( bLayoutRTL )
5160 aButtonPos.X() -= nHSpace - 1;
5161 else
5162 aButtonPos.X() -= nBWidth - nHSpace; // same for top or bottom
5164 Rectangle aButRect( aButtonPos, Size(nBWidth,nBHeight) );
5165 if ( aButRect.IsInside( rPosPixel ) )
5167 rScenRange = aRange;
5168 return TRUE;
5173 return FALSE;
5176 // #114409#
5177 void ScGridWindow::DrawLayerCreated()
5179 SetMapMode( GetDrawMapMode() );
5181 // initially create overlay objects
5182 ImpCreateOverlayObjects();
5185 // #114409#
5186 void ScGridWindow::CursorChanged()
5188 // here the created OverlayObjects may be transformed in later versions. For
5189 // now, just re-create them
5191 UpdateCursorOverlay();
5194 // #114409#
5195 void ScGridWindow::ImpCreateOverlayObjects()
5197 UpdateCursorOverlay();
5198 UpdateCopySourceOverlay();
5199 UpdateSelectionOverlay();
5200 UpdateAutoFillOverlay();
5201 UpdateDragRectOverlay();
5202 UpdateHeaderOverlay();
5203 UpdateShrinkOverlay();
5206 // #114409#
5207 void ScGridWindow::ImpDestroyOverlayObjects()
5209 DeleteCursorOverlay();
5210 DeleteCopySourceOverlay();
5211 DeleteSelectionOverlay();
5212 DeleteAutoFillOverlay();
5213 DeleteDragRectOverlay();
5214 DeleteHeaderOverlay();
5215 DeleteShrinkOverlay();
5218 void ScGridWindow::UpdateAllOverlays()
5220 // delete and re-allocate all overlay objects
5222 ImpDestroyOverlayObjects();
5223 ImpCreateOverlayObjects();
5226 void ScGridWindow::DeleteCursorOverlay()
5228 DELETEZ( mpOOCursors );
5231 void ScGridWindow::DeleteCopySourceOverlay()
5233 DELETEZ( mpOOSelectionBorder );
5236 void ScGridWindow::UpdateCopySourceOverlay()
5238 MapMode aDrawMode = GetDrawMapMode();
5239 MapMode aOldMode = GetMapMode();
5240 if ( aOldMode != aDrawMode )
5241 SetMapMode( aDrawMode );
5243 DeleteCopySourceOverlay();
5245 if (!pViewData->ShowPasteSource())
5246 return;
5247 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5248 if (!pOverlayManager)
5249 return;
5250 ScTransferObj* pTransObj = ScTransferObj::GetOwnClipboard( pViewData->GetActiveWin() );
5251 if (!pTransObj)
5252 return;
5253 ScDocument* pClipDoc = pTransObj->GetDocument();
5254 if (!pClipDoc)
5255 return;
5257 SCTAB nCurTab = pViewData->GetCurPos().Tab();
5259 ScClipParam& rClipParam = pClipDoc->GetClipParam();
5260 mpOOSelectionBorder = new ::sdr::overlay::OverlayObjectList;
5261 for (ScRange* p = rClipParam.maRanges.First(); p; p = rClipParam.maRanges.Next())
5263 if (p->aStart.Tab() != nCurTab)
5264 continue;
5266 SCCOL nClipStartX = p->aStart.Col();
5267 SCROW nClipStartY = p->aStart.Row();
5268 SCCOL nClipEndX = p->aEnd.Col();
5269 SCROW nClipEndY = p->aEnd.Row();
5271 Point aClipStartScrPos = pViewData->GetScrPos( nClipStartX, nClipStartY, eWhich );
5272 Point aClipEndScrPos = pViewData->GetScrPos( nClipEndX + 1, nClipEndY + 1, eWhich );
5273 aClipStartScrPos -= Point(1, 1);
5274 long nSizeXPix = aClipEndScrPos.X() - aClipStartScrPos.X();
5275 long nSizeYPix = aClipEndScrPos.Y() - aClipStartScrPos.Y();
5277 Rectangle aRect( aClipStartScrPos, Size(nSizeXPix, nSizeYPix) );
5280 Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
5282 Rectangle aLogic = PixelToLogic(aRect, aDrawMode);
5283 ::basegfx::B2DRange aRange(aLogic.Left(), aLogic.Top(), aLogic.Right(), aLogic.Bottom());
5284 ScOverlayDashedBorder* pDashedBorder = new ScOverlayDashedBorder(aRange, aHighlight, this);
5285 pOverlayManager->add(*pDashedBorder);
5286 mpOOSelectionBorder->append(*pDashedBorder);
5289 if ( aOldMode != aDrawMode )
5290 SetMapMode( aOldMode );
5293 void ScGridWindow::UpdateCursorOverlay()
5295 MapMode aDrawMode = GetDrawMapMode();
5296 MapMode aOldMode = GetMapMode();
5297 if ( aOldMode != aDrawMode )
5298 SetMapMode( aDrawMode );
5300 // Existing OverlayObjects may be transformed in later versions.
5301 // For now, just re-create them.
5303 DeleteCursorOverlay();
5305 std::vector<Rectangle> aPixelRects;
5308 // determine the cursor rectangles in pixels (moved from ScGridWindow::DrawCursor)
5311 SCTAB nTab = pViewData->GetTabNo();
5312 SCCOL nX = pViewData->GetCurX();
5313 SCROW nY = pViewData->GetCurY();
5315 if (!maVisibleRange.isInside(nX, nY))
5316 return;
5318 // don't show the cursor in overlapped cells
5320 ScDocument* pDoc = pViewData->GetDocument();
5321 const ScPatternAttr* pPattern = pDoc->GetPattern(nX,nY,nTab);
5322 const ScMergeFlagAttr& rMergeFlag = (const ScMergeFlagAttr&) pPattern->GetItem(ATTR_MERGE_FLAG);
5323 BOOL bOverlapped = rMergeFlag.IsOverlapped();
5325 // left or above of the screen?
5327 BOOL bVis = ( nX>=pViewData->GetPosX(eHWhich) && nY>=pViewData->GetPosY(eVWhich) );
5328 if (!bVis)
5330 SCCOL nEndX = nX;
5331 SCROW nEndY = nY;
5332 const ScMergeAttr& rMerge = (const ScMergeAttr&) pPattern->GetItem(ATTR_MERGE);
5333 if (rMerge.GetColMerge() > 1)
5334 nEndX += rMerge.GetColMerge()-1;
5335 if (rMerge.GetRowMerge() > 1)
5336 nEndY += rMerge.GetRowMerge()-1;
5337 bVis = ( nEndX>=pViewData->GetPosX(eHWhich) && nEndY>=pViewData->GetPosY(eVWhich) );
5340 if ( bVis && !bOverlapped && !pViewData->HasEditView(eWhich) && pViewData->IsActive() )
5342 Point aScrPos = pViewData->GetScrPos( nX, nY, eWhich, TRUE );
5343 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5345 // completely right of/below the screen?
5346 // (test with logical start position in aScrPos)
5347 BOOL bMaybeVisible;
5348 if ( bLayoutRTL )
5349 bMaybeVisible = ( aScrPos.X() >= -2 && aScrPos.Y() >= -2 );
5350 else
5352 Size aOutSize = GetOutputSizePixel();
5353 bMaybeVisible = ( aScrPos.X() <= aOutSize.Width() + 2 && aScrPos.Y() <= aOutSize.Height() + 2 );
5355 if ( bMaybeVisible )
5357 long nSizeXPix;
5358 long nSizeYPix;
5359 pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix );
5361 if ( bLayoutRTL )
5362 aScrPos.X() -= nSizeXPix - 2; // move instead of mirroring
5364 // Now, draw the cursor.
5366 aScrPos.X() -= 2;
5367 aScrPos.Y() -= 2;
5368 Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) );
5370 aPixelRects.push_back(Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() ));
5371 aPixelRects.push_back(Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() ));
5372 aPixelRects.push_back(Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 ));
5373 aPixelRects.push_back(Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() ));
5377 if ( aPixelRects.size() )
5379 // #i70788# get the OverlayManager safely
5380 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5382 if(pOverlayManager)
5384 Color aCursorColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
5385 if (pViewData->GetActivePart() != eWhich)
5386 // non-active pane uses a different color.
5387 aCursorColor = SC_MOD()->GetColorConfig().GetColorValue(svtools::CALCPAGEBREAKAUTOMATIC).nColor;
5388 std::vector< basegfx::B2DRange > aRanges;
5389 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5391 for(sal_uInt32 a(0); a < aPixelRects.size(); a++)
5393 const Rectangle aRA(aPixelRects[a]);
5394 basegfx::B2DRange aRB(aRA.Left(), aRA.Top(), aRA.Right() + 1, aRA.Bottom() + 1);
5395 aRB.transform(aTransform);
5396 aRanges.push_back(aRB);
5399 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5400 sdr::overlay::OVERLAY_SOLID,
5401 aCursorColor,
5402 aRanges,
5403 false);
5405 pOverlayManager->add(*pOverlay);
5406 mpOOCursors = new ::sdr::overlay::OverlayObjectList;
5407 mpOOCursors->append(*pOverlay);
5411 if ( aOldMode != aDrawMode )
5412 SetMapMode( aOldMode );
5415 void ScGridWindow::DeleteSelectionOverlay()
5417 DELETEZ( mpOOSelection );
5420 void ScGridWindow::UpdateSelectionOverlay()
5422 MapMode aDrawMode = GetDrawMapMode();
5423 MapMode aOldMode = GetMapMode();
5424 if ( aOldMode != aDrawMode )
5425 SetMapMode( aDrawMode );
5427 DeleteSelectionOverlay();
5428 std::vector<Rectangle> aPixelRects;
5429 GetSelectionRects( aPixelRects );
5431 if ( aPixelRects.size() && pViewData->IsActive() )
5433 // #i70788# get the OverlayManager safely
5434 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5436 if(pOverlayManager)
5438 std::vector< basegfx::B2DRange > aRanges;
5439 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5441 for(sal_uInt32 a(0); a < aPixelRects.size(); a++)
5443 const Rectangle aRA(aPixelRects[a]);
5444 basegfx::B2DRange aRB(aRA.Left() - 1, aRA.Top() - 1, aRA.Right(), aRA.Bottom());
5445 aRB.transform(aTransform);
5446 aRanges.push_back(aRB);
5449 // #i97672# get the system's hilight color and limit it to the maximum
5450 // allowed luminance. This is needed to react on too bright hilight colors
5451 // which would otherwise vive a bad visualisation
5452 Color aHighlight(GetSettings().GetStyleSettings().GetHighlightColor());
5453 const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
5454 const basegfx::BColor aSelection(aHighlight.getBColor());
5455 const double fLuminance(aSelection.luminance());
5456 const double fMaxLum(aSvtOptionsDrawinglayer.GetSelectionMaximumLuminancePercent() / 100.0);
5458 if(fLuminance > fMaxLum)
5460 const double fFactor(fMaxLum / fLuminance);
5461 const basegfx::BColor aNewSelection(
5462 aSelection.getRed() * fFactor,
5463 aSelection.getGreen() * fFactor,
5464 aSelection.getBlue() * fFactor);
5466 aHighlight = Color(aNewSelection);
5469 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5470 sdr::overlay::OVERLAY_TRANSPARENT,
5471 aHighlight,
5472 aRanges,
5473 true);
5475 pOverlayManager->add(*pOverlay);
5476 mpOOSelection = new ::sdr::overlay::OverlayObjectList;
5477 mpOOSelection->append(*pOverlay);
5481 if ( aOldMode != aDrawMode )
5482 SetMapMode( aOldMode );
5485 void ScGridWindow::DeleteAutoFillOverlay()
5487 DELETEZ( mpOOAutoFill );
5488 mpAutoFillRect.reset();
5491 void ScGridWindow::UpdateAutoFillOverlay()
5493 MapMode aDrawMode = GetDrawMapMode();
5494 MapMode aOldMode = GetMapMode();
5495 if ( aOldMode != aDrawMode )
5496 SetMapMode( aDrawMode );
5498 DeleteAutoFillOverlay();
5501 // get the AutoFill handle rectangle in pixels (moved from ScGridWindow::DrawAutoFillMark)
5504 if ( bAutoMarkVisible && aAutoMarkPos.Tab() == pViewData->GetTabNo() &&
5505 !pViewData->HasEditView(eWhich) && pViewData->IsActive() )
5507 SCCOL nX = aAutoMarkPos.Col();
5508 SCROW nY = aAutoMarkPos.Row();
5510 if (!maVisibleRange.isInside(nX, nY))
5511 // Autofill mark is not visible. Bail out.
5512 return;
5514 SCTAB nTab = pViewData->GetTabNo();
5515 ScDocument* pDoc = pViewData->GetDocument();
5516 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5518 Point aFillPos = pViewData->GetScrPos( nX, nY, eWhich, TRUE );
5519 long nSizeXPix;
5520 long nSizeYPix;
5521 pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix );
5522 if ( bLayoutRTL )
5523 aFillPos.X() -= nSizeXPix + 3;
5524 else
5525 aFillPos.X() += nSizeXPix - 2;
5527 aFillPos.Y() += nSizeYPix;
5528 aFillPos.Y() -= 2;
5529 mpAutoFillRect.reset(new Rectangle(aFillPos, Size(6, 6)));
5531 // #i70788# get the OverlayManager safely
5532 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5534 if(pOverlayManager)
5536 Color aHandleColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
5537 if (pViewData->GetActivePart() != eWhich)
5538 // non-active pane uses a different color.
5539 aHandleColor = SC_MOD()->GetColorConfig().GetColorValue(svtools::CALCPAGEBREAKAUTOMATIC).nColor;
5540 std::vector< basegfx::B2DRange > aRanges;
5541 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5542 basegfx::B2DRange aRB(mpAutoFillRect->Left(), mpAutoFillRect->Top(), mpAutoFillRect->Right() + 1, mpAutoFillRect->Bottom() + 1);
5544 aRB.transform(aTransform);
5545 aRanges.push_back(aRB);
5547 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5548 sdr::overlay::OVERLAY_SOLID,
5549 aHandleColor,
5550 aRanges,
5551 false);
5553 pOverlayManager->add(*pOverlay);
5554 mpOOAutoFill = new ::sdr::overlay::OverlayObjectList;
5555 mpOOAutoFill->append(*pOverlay);
5558 if ( aOldMode != aDrawMode )
5559 SetMapMode( aOldMode );
5563 void ScGridWindow::DeleteDragRectOverlay()
5565 DELETEZ( mpOODragRect );
5568 void ScGridWindow::UpdateDragRectOverlay()
5570 MapMode aDrawMode = GetDrawMapMode();
5571 MapMode aOldMode = GetMapMode();
5572 if ( aOldMode != aDrawMode )
5573 SetMapMode( aDrawMode );
5575 DeleteDragRectOverlay();
5578 // get the rectangles in pixels (moved from DrawDragRect)
5581 if ( bDragRect || bPagebreakDrawn )
5583 std::vector<Rectangle> aPixelRects;
5585 SCCOL nX1 = bDragRect ? nDragStartX : aPagebreakDrag.aStart.Col();
5586 SCROW nY1 = bDragRect ? nDragStartY : aPagebreakDrag.aStart.Row();
5587 SCCOL nX2 = bDragRect ? nDragEndX : aPagebreakDrag.aEnd.Col();
5588 SCROW nY2 = bDragRect ? nDragEndY : aPagebreakDrag.aEnd.Row();
5590 SCTAB nTab = pViewData->GetTabNo();
5592 SCCOL nPosX = pViewData->GetPosX(WhichH(eWhich));
5593 SCROW nPosY = pViewData->GetPosY(WhichV(eWhich));
5594 if (nX1 < nPosX) nX1 = nPosX;
5595 if (nX2 < nPosX) nX2 = nPosX;
5596 if (nY1 < nPosY) nY1 = nPosY;
5597 if (nY2 < nPosY) nY2 = nPosY;
5599 Point aScrPos( pViewData->GetScrPos( nX1, nY1, eWhich ) );
5601 long nSizeXPix=0;
5602 long nSizeYPix=0;
5603 ScDocument* pDoc = pViewData->GetDocument();
5604 double nPPTX = pViewData->GetPPTX();
5605 double nPPTY = pViewData->GetPPTY();
5606 SCCOLROW i;
5608 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5609 long nLayoutSign = bLayoutRTL ? -1 : 1;
5611 if (ValidCol(nX2) && nX2>=nX1)
5612 for (i=nX1; i<=nX2; i++)
5613 nSizeXPix += ScViewData::ToPixel( pDoc->GetColWidth( static_cast<SCCOL>(i), nTab ), nPPTX );
5614 else
5616 aScrPos.X() -= nLayoutSign;
5617 nSizeXPix += 2;
5620 if (ValidRow(nY2) && nY2>=nY1)
5621 for (i=nY1; i<=nY2; i++)
5622 nSizeYPix += ScViewData::ToPixel( pDoc->GetRowHeight( i, nTab ), nPPTY );
5623 else
5625 aScrPos.Y() -= 1;
5626 nSizeYPix += 2;
5629 aScrPos.X() -= 2 * nLayoutSign;
5630 aScrPos.Y() -= 2;
5631 // Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) );
5632 Rectangle aRect( aScrPos.X(), aScrPos.Y(),
5633 aScrPos.X() + ( nSizeXPix + 2 ) * nLayoutSign, aScrPos.Y() + nSizeYPix + 2 );
5634 if ( bLayoutRTL )
5636 aRect.Left() = aRect.Right(); // end position is left
5637 aRect.Right() = aScrPos.X();
5640 if ( meDragInsertMode == INS_CELLSDOWN )
5642 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Top()+3, aRect.Left()+1, aRect.Bottom()-2 ) );
5643 aPixelRects.push_back( Rectangle( aRect.Right()-1, aRect.Top()+3, aRect.Right()-1, aRect.Bottom()-2 ) );
5644 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Top(), aRect.Right()-1, aRect.Top()+2 ) );
5645 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Bottom()-1, aRect.Right()-1, aRect.Bottom()-1 ) );
5647 else if ( meDragInsertMode == INS_CELLSRIGHT )
5649 aPixelRects.push_back( Rectangle( aRect.Left(), aRect.Top()+1, aRect.Left()+2, aRect.Bottom()-1 ) );
5650 aPixelRects.push_back( Rectangle( aRect.Right()-1, aRect.Top()+1, aRect.Right()-1, aRect.Bottom()-1 ) );
5651 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Top()+1, aRect.Right()-2, aRect.Top()+1 ) );
5652 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Bottom()-1, aRect.Right()-2, aRect.Bottom()-1 ) );
5654 else
5656 aPixelRects.push_back( Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() ) );
5657 aPixelRects.push_back( Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() ) );
5658 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 ) );
5659 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() ) );
5662 // #i70788# get the OverlayManager safely
5663 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5665 if(pOverlayManager)
5667 // Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
5668 std::vector< basegfx::B2DRange > aRanges;
5669 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5671 for(sal_uInt32 a(0); a < aPixelRects.size(); a++)
5673 const Rectangle aRA(aPixelRects[a]);
5674 basegfx::B2DRange aRB(aRA.Left(), aRA.Top(), aRA.Right() + 1, aRA.Bottom() + 1);
5675 aRB.transform(aTransform);
5676 aRanges.push_back(aRB);
5679 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5680 sdr::overlay::OVERLAY_INVERT,
5681 Color(COL_BLACK),
5682 aRanges,
5683 false);
5685 pOverlayManager->add(*pOverlay);
5686 mpOODragRect = new ::sdr::overlay::OverlayObjectList;
5687 mpOODragRect->append(*pOverlay);
5691 if ( aOldMode != aDrawMode )
5692 SetMapMode( aOldMode );
5695 void ScGridWindow::DeleteHeaderOverlay()
5697 DELETEZ( mpOOHeader );
5700 void ScGridWindow::UpdateHeaderOverlay()
5702 MapMode aDrawMode = GetDrawMapMode();
5703 MapMode aOldMode = GetMapMode();
5704 if ( aOldMode != aDrawMode )
5705 SetMapMode( aDrawMode );
5707 DeleteHeaderOverlay();
5709 // Pixel rectangle is in aInvertRect
5710 if ( !aInvertRect.IsEmpty() )
5712 // #i70788# get the OverlayManager safely
5713 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5715 if(pOverlayManager)
5717 // Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
5718 std::vector< basegfx::B2DRange > aRanges;
5719 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5720 basegfx::B2DRange aRB(aInvertRect.Left(), aInvertRect.Top(), aInvertRect.Right() + 1, aInvertRect.Bottom() + 1);
5722 aRB.transform(aTransform);
5723 aRanges.push_back(aRB);
5725 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5726 sdr::overlay::OVERLAY_INVERT,
5727 Color(COL_BLACK),
5728 aRanges,
5729 false);
5731 pOverlayManager->add(*pOverlay);
5732 mpOOHeader = new ::sdr::overlay::OverlayObjectList;
5733 mpOOHeader->append(*pOverlay);
5737 if ( aOldMode != aDrawMode )
5738 SetMapMode( aOldMode );
5741 void ScGridWindow::DeleteShrinkOverlay()
5743 DELETEZ( mpOOShrink );
5746 void ScGridWindow::UpdateShrinkOverlay()
5748 MapMode aDrawMode = GetDrawMapMode();
5749 MapMode aOldMode = GetMapMode();
5750 if ( aOldMode != aDrawMode )
5751 SetMapMode( aDrawMode );
5753 DeleteShrinkOverlay();
5756 // get the rectangle in pixels
5759 Rectangle aPixRect;
5760 ScRange aRange;
5761 SCTAB nTab = pViewData->GetTabNo();
5762 if ( pViewData->IsRefMode() && nTab >= pViewData->GetRefStartZ() && nTab <= pViewData->GetRefEndZ() &&
5763 pViewData->GetDelMark( aRange ) )
5765 //! limit to visible area
5766 if ( aRange.aStart.Col() <= aRange.aEnd.Col() &&
5767 aRange.aStart.Row() <= aRange.aEnd.Row() )
5769 Point aStart = pViewData->GetScrPos( aRange.aStart.Col(),
5770 aRange.aStart.Row(), eWhich );
5771 Point aEnd = pViewData->GetScrPos( aRange.aEnd.Col()+1,
5772 aRange.aEnd.Row()+1, eWhich );
5773 aEnd.X() -= 1;
5774 aEnd.Y() -= 1;
5776 aPixRect = Rectangle( aStart,aEnd );
5780 if ( !aPixRect.IsEmpty() )
5782 // #i70788# get the OverlayManager safely
5783 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5785 if(pOverlayManager)
5787 // Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
5788 std::vector< basegfx::B2DRange > aRanges;
5789 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5790 basegfx::B2DRange aRB(aPixRect.Left(), aPixRect.Top(), aPixRect.Right() + 1, aPixRect.Bottom() + 1);
5792 aRB.transform(aTransform);
5793 aRanges.push_back(aRB);
5795 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5796 sdr::overlay::OVERLAY_INVERT,
5797 Color(COL_BLACK),
5798 aRanges,
5799 false);
5801 pOverlayManager->add(*pOverlay);
5802 mpOOShrink = new ::sdr::overlay::OverlayObjectList;
5803 mpOOShrink->append(*pOverlay);
5807 if ( aOldMode != aDrawMode )
5808 SetMapMode( aOldMode );
5811 // #i70788# central method to get the OverlayManager safely
5812 ::sdr::overlay::OverlayManager* ScGridWindow::getOverlayManager()
5814 SdrPageView* pPV = pViewData->GetView()->GetScDrawView()->GetSdrPageView();
5816 if(pPV)
5818 SdrPageWindow* pPageWin = pPV->FindPageWindow( *this );
5820 if ( pPageWin )
5822 return (pPageWin->GetOverlayManager());
5826 return 0L;
5829 void ScGridWindow::flushOverlayManager()
5831 // #i70788# get the OverlayManager safely
5832 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5834 if(pOverlayManager)
5836 pOverlayManager->flush();
5840 // ---------------------------------------------------------------------------
5841 // eof