update dev300-m58
[ooovba.git] / sc / source / ui / view / gridwin.cxx
blob42173c4c54c0cf17b3b8801bfeb711fbca4af64d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: gridwin.cxx,v $
10 * $Revision: 1.96.50.4 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 #include "scitems.hxx"
36 #include <memory> //auto_ptr
37 #include <svx/adjitem.hxx>
38 #include <svx/algitem.hxx>
39 #include <svx/dbexch.hrc>
40 #include <svx/editview.hxx>
41 #include <svx/editstat.hxx>
42 #include <svx/flditem.hxx>
43 #include <svx/svdetc.hxx>
44 #include <svx/editobj.hxx>
45 #include <sfx2/dispatch.hxx>
46 #include <sfx2/viewfrm.hxx>
47 #include <sfx2/docfile.hxx>
48 #include <svtools/stritem.hxx>
49 #include <svtools/svlbox.hxx>
50 #include <svtools/svtabbx.hxx>
51 #include <svtools/urlbmk.hxx>
52 #include <tools/urlobj.hxx>
53 #include <vcl/cursor.hxx>
54 #include <vcl/sound.hxx>
55 #include <vcl/graph.hxx>
56 #include <vcl/hatch.hxx>
57 #include <sot/formats.hxx>
58 #include <sot/clsids.hxx>
60 #include <svx/svdview.hxx> // fuer Command-Handler (COMMAND_INSERTTEXT)
61 #include <svx/outliner.hxx> // fuer Command-Handler (COMMAND_INSERTTEXT)
62 #include <svx/svditer.hxx>
63 #include <svx/svdocapt.hxx>
64 #include <svx/svdpagv.hxx>
66 #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
67 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
68 #include <com/sun/star/sheet/DataPilotTableHeaderData.hpp>
69 #include <com/sun/star/sheet/DataPilotTableResultData.hpp>
70 #include <com/sun/star/sheet/DataPilotTablePositionData.hpp>
71 #include <com/sun/star/sheet/DataPilotTablePositionType.hpp>
72 #include <com/sun/star/sheet/MemberResultFlags.hpp>
73 #include <com/sun/star/awt/KeyModifier.hpp>
74 #include <com/sun/star/awt/MouseButton.hpp>
76 #include "gridwin.hxx"
77 #include "tabvwsh.hxx"
78 #include "docsh.hxx"
79 #include "viewdata.hxx"
80 #include "tabview.hxx"
81 #include "select.hxx"
82 #include "scmod.hxx"
83 #include "document.hxx"
84 #include "attrib.hxx"
85 #include "dbcolect.hxx"
86 #include "stlpool.hxx"
87 #include "printfun.hxx"
88 #include "cbutton.hxx"
89 #include "sc.hrc"
90 #include "globstr.hrc"
91 #include "editutil.hxx"
92 #include "scresid.hxx"
93 #include "inputhdl.hxx"
94 #include "uiitems.hxx" // Filter-Dialog - auslagern !!!
95 #include "filtdlg.hxx"
96 #include "impex.hxx" // Sylk-ID fuer CB
97 #include "cell.hxx" // fuer Edit-Felder
98 #include "patattr.hxx"
99 #include "notemark.hxx"
100 #include "rfindlst.hxx"
101 #include "docpool.hxx"
102 #include "output.hxx"
103 #include "docfunc.hxx"
104 #include "dbdocfun.hxx"
105 #include "dpobject.hxx"
106 #include "dpoutput.hxx"
107 #include "transobj.hxx"
108 #include "drwtrans.hxx"
109 #include "seltrans.hxx"
110 #include "sizedev.hxx"
111 #include "AccessibilityHints.hxx"
112 #include "dpsave.hxx"
113 #include "viewuno.hxx"
114 #include "compiler.hxx"
115 #include "editable.hxx"
116 #include "fillinfo.hxx"
117 #include "scitems.hxx"
118 #include "userdat.hxx"
119 #include "drwlayer.hxx"
120 #include "attrib.hxx"
121 #include "cellsh.hxx"
122 #include "validat.hxx"
123 #include "tabprotection.hxx"
124 #include "postit.hxx"
125 #include "dpcontrol.hxx"
127 #include "drawview.hxx"
128 #include <svx/sdrpagewindow.hxx>
129 #include <svx/sdr/overlay/overlaymanager.hxx>
130 #include <vcl/svapp.hxx>
131 #include <svx/sdr/overlay/overlayselection.hxx>
133 #include "cellsuno.hxx"
135 #include <com/sun/star/document/XVbaEventsHelper.hpp>
136 #include <com/sun/star/document/VbaEventId.hpp>
138 using namespace com::sun::star;
139 using namespace com::sun::star::document::VbaEventId;
140 using ::com::sun::star::uno::Sequence;
141 using ::com::sun::star::uno::Any;
143 const BYTE SC_NESTEDBUTTON_NONE = 0;
144 const BYTE SC_NESTEDBUTTON_DOWN = 1;
145 const BYTE SC_NESTEDBUTTON_UP = 2;
147 #define SC_AUTOFILTER_ALL 0
148 #define SC_AUTOFILTER_TOP10 1
149 #define SC_AUTOFILTER_CUSTOM 2
150 #define SC_AUTOFILTER_EMPTY 3
151 #define SC_AUTOFILTER_NOTEMPTY 4
153 // Modi fuer die FilterListBox
154 enum ScFilterBoxMode
156 SC_FILTERBOX_FILTER,
157 SC_FILTERBOX_DATASELECT,
158 SC_FILTERBOX_SCENARIO,
159 SC_FILTERBOX_PAGEFIELD
162 extern SfxViewShell* pScActiveViewShell; // global.cxx
163 extern USHORT nScClickMouseModifier; // global.cxx
164 extern USHORT nScFillModeMouseModifier; // global.cxx
166 #define SC_FILTERLISTBOX_LINES 12
168 // ============================================================================
170 ScGridWindow::VisibleRange::VisibleRange() :
171 mnCol1(0), mnCol2(MAXCOL), mnRow1(0), mnRow2(MAXROW)
175 bool ScGridWindow::VisibleRange::isInside(SCCOL nCol, SCROW nRow) const
177 return mnCol1 <= nCol && nCol <= mnCol2 && mnRow1 <= nRow && nRow <= mnRow2;
180 // ============================================================================
182 class ScFilterListBox : public ListBox
184 private:
185 ScGridWindow* pGridWin;
186 SCCOL nCol;
187 SCROW nRow;
188 BOOL bButtonDown;
189 BOOL bInit;
190 BOOL bCancelled;
191 BOOL bInSelect;
192 bool mbListHasDates;
193 ULONG nSel;
194 ScFilterBoxMode eMode;
196 protected:
197 virtual void LoseFocus();
198 void SelectHdl();
200 public:
201 ScFilterListBox( Window* pParent, ScGridWindow* pGrid,
202 SCCOL nNewCol, SCROW nNewRow, ScFilterBoxMode eNewMode );
203 ~ScFilterListBox();
205 virtual long PreNotify( NotifyEvent& rNEvt );
206 virtual void Select();
208 SCCOL GetCol() const { return nCol; }
209 SCROW GetRow() const { return nRow; }
210 ScFilterBoxMode GetMode() const { return eMode; }
211 BOOL IsDataSelect() const { return (eMode == SC_FILTERBOX_DATASELECT); }
212 void EndInit();
213 BOOL IsInInit() const { return bInit; }
214 void SetCancelled() { bCancelled = TRUE; }
215 BOOL IsInSelect() const { return bInSelect; }
216 void SetListHasDates(bool b) { mbListHasDates = b; }
217 bool HasDates() const { return mbListHasDates; }
220 //-------------------------------------------------------------------
222 // ListBox in einem FloatingWindow (pParent)
223 ScFilterListBox::ScFilterListBox( Window* pParent, ScGridWindow* pGrid,
224 SCCOL nNewCol, SCROW nNewRow, ScFilterBoxMode eNewMode ) :
225 ListBox( pParent, WB_AUTOHSCROLL ),
226 pGridWin( pGrid ),
227 nCol( nNewCol ),
228 nRow( nNewRow ),
229 bButtonDown( FALSE ),
230 bInit( TRUE ),
231 bCancelled( FALSE ),
232 bInSelect( FALSE ),
233 mbListHasDates(false),
234 nSel( 0 ),
235 eMode( eNewMode )
239 __EXPORT ScFilterListBox::~ScFilterListBox()
241 if (IsMouseCaptured())
242 ReleaseMouse();
245 void ScFilterListBox::EndInit()
247 USHORT nPos = GetSelectEntryPos();
248 if ( LISTBOX_ENTRY_NOTFOUND == nPos )
249 nSel = 0;
250 else
251 nSel = nPos;
253 bInit = FALSE;
256 void __EXPORT ScFilterListBox::LoseFocus()
258 #ifndef UNX
259 Hide();
260 #endif
263 // -----------------------------------------------------------------------
265 long ScFilterListBox::PreNotify( NotifyEvent& rNEvt )
267 long nDone = 0;
268 if ( rNEvt.GetType() == EVENT_KEYINPUT )
270 KeyEvent aKeyEvt = *rNEvt.GetKeyEvent();
271 KeyCode aCode = aKeyEvt.GetKeyCode();
272 if ( !aCode.GetModifier() ) // ohne alle Modifiers
274 USHORT nKey = aCode.GetCode();
275 if ( nKey == KEY_RETURN )
277 SelectHdl(); // auswaehlen
278 nDone = 1;
280 else if ( nKey == KEY_ESCAPE )
282 pGridWin->ClickExtern(); // loescht die List-Box !!!
283 nDone = 1;
288 return nDone ? nDone : ListBox::PreNotify( rNEvt );
291 void __EXPORT ScFilterListBox::Select()
293 ListBox::Select();
294 SelectHdl();
297 void __EXPORT ScFilterListBox::SelectHdl()
299 if ( !IsTravelSelect() && !bInit && !bCancelled )
301 USHORT nPos = GetSelectEntryPos();
302 if ( LISTBOX_ENTRY_NOTFOUND != nPos )
304 nSel = nPos;
305 if (!bButtonDown)
307 // #i81298# set bInSelect flag, so the box isn't deleted from modifications within FilterSelect
308 bInSelect = TRUE;
309 pGridWin->FilterSelect( nSel );
310 bInSelect = FALSE;
316 // ============================================================================
318 // use a System floating window for the above filter listbox
319 class ScFilterFloatingWindow : public FloatingWindow
321 public:
322 ScFilterFloatingWindow( Window* pParent, WinBits nStyle = WB_STDFLOATWIN );
323 virtual ~ScFilterFloatingWindow();
324 // required for System FloatingWindows that will not process KeyInput by themselves
325 virtual Window* GetPreferredKeyInputWindow();
328 ScFilterFloatingWindow::ScFilterFloatingWindow( Window* pParent, WinBits nStyle ) :
329 FloatingWindow( pParent, nStyle|WB_SYSTEMWINDOW ) // make it a system floater
332 ScFilterFloatingWindow::~ScFilterFloatingWindow()
334 EndPopupMode();
337 Window* ScFilterFloatingWindow::GetPreferredKeyInputWindow()
339 // redirect keyinput in the child window
340 return GetWindow(WINDOW_FIRSTCHILD) ? GetWindow(WINDOW_FIRSTCHILD)->GetPreferredKeyInputWindow() : NULL; // will be the FilterBox
343 // ============================================================================
345 BOOL lcl_IsEditableMatrix( ScDocument* pDoc, const ScRange& rRange )
347 // wenn es ein editierbarer Bereich ist, und rechts unten eine Matrix-Zelle
348 // mit Origin links oben liegt, enthaelt der Bereich genau die Matrix.
349 //! Direkt die MatrixEdges Funktionen von der Column herausreichen ???
351 if ( !pDoc->IsBlockEditable( rRange.aStart.Tab(), rRange.aStart.Col(),rRange.aStart.Row(),
352 rRange.aEnd.Col(),rRange.aEnd.Row() ) )
353 return FALSE;
355 ScAddress aPos;
356 const ScBaseCell* pCell = pDoc->GetCell( rRange.aEnd );
357 return ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA &&
358 ((ScFormulaCell*)pCell)->GetMatrixOrigin(aPos) && aPos == rRange.aStart );
362 void lcl_UnLockComment( ScDrawView* pView, SdrPageView* pPV, SdrModel* pDrDoc, const Point& rPos, ScViewData* pViewData )
364 if (!pView && !pPV && !pDrDoc && !pViewData)
365 return;
367 ScDocument& rDoc = *pViewData->GetDocument();
368 ScAddress aCellPos( pViewData->GetCurX(), pViewData->GetCurY(), pViewData->GetTabNo() );
369 ScPostIt* pNote = rDoc.GetNote( aCellPos );
370 SdrObject* pObj = pNote ? pNote->GetCaption() : 0;
371 if( pObj && pObj->GetLogicRect().IsInside( rPos ) && ScDrawLayer::IsNoteCaption( pObj ) )
373 const ScProtectionAttr* pProtAttr = static_cast< const ScProtectionAttr* > (rDoc.GetAttr( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab(), ATTR_PROTECTION ) );
374 bool bProtectAttr = pProtAttr->GetProtection() || pProtAttr->GetHideCell() ;
375 bool bProtectDoc = rDoc.IsTabProtected( aCellPos.Tab() ) || pViewData->GetSfxDocShell()->IsReadOnly() ;
376 // unlock internal layer (if not protected), will be relocked in ScDrawView::MarkListHasChanged()
377 pView->LockInternalLayer( bProtectDoc && bProtectAttr );
381 sal_Bool lcl_GetHyperlinkCell(ScDocument* pDoc, SCCOL& rPosX, SCROW& rPosY, SCTAB nTab, ScBaseCell*& rpCell )
383 BOOL bFound = FALSE;
386 pDoc->GetCell( rPosX, rPosY, nTab, rpCell );
387 if ( !rpCell || rpCell->GetCellType() == CELLTYPE_NOTE )
389 if ( rPosX <= 0 )
390 return FALSE; // alles leer bis links
391 else
392 --rPosX; // weitersuchen
394 else if ( rpCell->GetCellType() == CELLTYPE_EDIT)
395 bFound = TRUE;
396 else if (rpCell->GetCellType() == CELLTYPE_FORMULA &&
397 static_cast<ScFormulaCell*>(rpCell)->IsHyperLinkCell())
398 bFound = TRUE;
399 else
400 return FALSE; // andere Zelle
402 while ( !bFound );
404 return bFound;
407 // ---------------------------------------------------------------------------
408 // WB_DIALOGCONTROL noetig fuer UNO-Controls
409 ScGridWindow::ScGridWindow( Window* pParent, ScViewData* pData, ScSplitPos eWhichPos )
410 : Window( pParent, WB_CLIPCHILDREN | WB_DIALOGCONTROL ),
411 DropTargetHelper( this ),
412 DragSourceHelper( this ),
413 mpOOCursors( NULL ),
414 mpOOSelection( NULL ),
415 mpOOAutoFill( NULL ),
416 mpOODragRect( NULL ),
417 mpOOHeader( NULL ),
418 mpOOShrink( NULL ),
419 mpAutoFillRect(static_cast<Rectangle*>(NULL)),
420 pViewData( pData ),
421 eWhich( eWhichPos ),
422 pNoteMarker( NULL ),
423 pFilterBox( NULL ),
424 pFilterFloat( NULL ),
425 mpDPFieldPopup(NULL),
426 mpFilterButton(NULL),
427 nCursorHideCount( 0 ),
428 bMarking( FALSE ),
429 nButtonDown( 0 ),
430 bEEMouse( FALSE ),
431 nMouseStatus( SC_GM_NONE ),
432 nNestedButtonState( SC_NESTEDBUTTON_NONE ),
433 bDPMouse( FALSE ),
434 bRFMouse( FALSE ),
435 nPagebreakMouse( SC_PD_NONE ),
436 bPagebreakDrawn( FALSE ),
437 nPageScript( 0 ),
438 bDragRect( FALSE ),
439 meDragInsertMode( INS_NONE ),
440 nCurrentPointer( 0 ),
441 bIsInScroll( FALSE ),
442 bIsInPaint( FALSE ),
443 aComboButton( this ),
444 aCurMousePos( 0,0 ),
445 nPaintCount( 0 ),
446 bNeedsRepaint( FALSE ),
447 bAutoMarkVisible( FALSE ),
448 bListValButton( FALSE )
450 switch(eWhich)
452 case SC_SPLIT_TOPLEFT:
453 eHWhich = SC_SPLIT_LEFT;
454 eVWhich = SC_SPLIT_TOP;
455 break;
456 case SC_SPLIT_TOPRIGHT:
457 eHWhich = SC_SPLIT_RIGHT;
458 eVWhich = SC_SPLIT_TOP;
459 break;
460 case SC_SPLIT_BOTTOMLEFT:
461 eHWhich = SC_SPLIT_LEFT;
462 eVWhich = SC_SPLIT_BOTTOM;
463 break;
464 case SC_SPLIT_BOTTOMRIGHT:
465 eHWhich = SC_SPLIT_RIGHT;
466 eVWhich = SC_SPLIT_BOTTOM;
467 break;
468 default:
469 DBG_ERROR("GridWindow: falsche Position");
472 SetBackground();
474 SetMapMode(pViewData->GetLogicMode(eWhich));
475 // EnableDrop();
476 EnableChildTransparentMode();
477 SetDialogControlFlags( WINDOW_DLGCTRL_RETURN | WINDOW_DLGCTRL_WANTFOCUS );
479 SetHelpId( HID_SC_WIN_GRIDWIN );
480 SetUniqueId( HID_SC_WIN_GRIDWIN );
482 SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
483 EnableRTL( FALSE );
486 __EXPORT ScGridWindow::~ScGridWindow()
488 // #114409#
489 ImpDestroyOverlayObjects();
491 delete pFilterBox;
492 delete pFilterFloat;
493 delete pNoteMarker;
496 void __EXPORT ScGridWindow::Resize( const Size& )
498 // gar nix
501 void ScGridWindow::ClickExtern()
505 // #i81298# don't delete the filter box when called from its select handler
506 // (possible through row header size update)
507 // #i84277# when initializing the filter box, a Basic error can deactivate the view
508 if ( pFilterBox && ( pFilterBox->IsInSelect() || pFilterBox->IsInInit() ) )
510 break;
513 DELETEZ(pFilterBox);
514 DELETEZ(pFilterFloat);
516 while (false);
518 if (mpDPFieldPopup.get())
520 mpDPFieldPopup->close(false);
521 mpDPFieldPopup.reset();
525 IMPL_LINK( ScGridWindow, PopupModeEndHdl, FloatingWindow*, EMPTYARG )
527 if (pFilterBox)
528 pFilterBox->SetCancelled(); // nicht mehr auswaehlen
529 GrabFocus();
530 return 0;
533 IMPL_LINK( ScGridWindow, PopupSpellingHdl, SpellCallbackInfo*, pInfo )
535 if( pInfo->nCommand == SPELLCMD_STARTSPELLDLG )
536 pViewData->GetDispatcher().Execute( SID_SPELL_DIALOG, SFX_CALLMODE_ASYNCHRON );
537 return 0;
540 void ScGridWindow::ExecPageFieldSelect( SCCOL nCol, SCROW nRow, BOOL bHasSelection, const String& rStr )
542 //! gridwin2 ?
544 ScDocument* pDoc = pViewData->GetDocument();
545 SCTAB nTab = pViewData->GetTabNo();
546 ScDPObject* pDPObj = pDoc->GetDPAtCursor(nCol, nRow, nTab);
547 if ( pDPObj && nCol > 0 )
549 // look for the dimension header left of the drop-down arrow
550 USHORT nOrient = sheet::DataPilotFieldOrientation_HIDDEN;
551 long nField = pDPObj->GetHeaderDim( ScAddress( nCol-1, nRow, nTab ), nOrient );
552 if ( nField >= 0 && nOrient == sheet::DataPilotFieldOrientation_PAGE )
554 ScDPSaveData aSaveData( *pDPObj->GetSaveData() );
556 BOOL bIsDataLayout;
557 String aDimName = pDPObj->GetDimName( nField, bIsDataLayout );
558 if ( !bIsDataLayout )
560 ScDPSaveDimension* pDim = aSaveData.GetDimensionByName(aDimName);
562 if ( bHasSelection )
563 pDim->SetCurrentPage( &rStr );
564 else
565 pDim->SetCurrentPage( NULL );
567 ScDPObject aNewObj( *pDPObj );
568 aNewObj.SetSaveData( aSaveData );
569 ScDBDocFunc aFunc( *pViewData->GetDocShell() );
570 aFunc.DataPilotUpdate( pDPObj, &aNewObj, TRUE, FALSE );
571 pViewData->GetView()->CursorPosChanged(); // shells may be switched
577 void ScGridWindow::LaunchPageFieldMenu( SCCOL nCol, SCROW nRow )
579 //! merge position/size handling with DoAutoFilterMenue
581 delete pFilterBox;
582 delete pFilterFloat;
584 USHORT i;
585 ScDocument* pDoc = pViewData->GetDocument();
586 SCTAB nTab = pViewData->GetTabNo();
587 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
589 long nSizeX = 0;
590 long nSizeY = 0;
591 long nHeight = 0;
592 pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
593 Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich );
594 if ( bLayoutRTL )
595 aPos.X() -= nSizeX;
597 Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) );
599 aPos.X() -= 1;
600 aPos.Y() += nSizeY - 1;
602 pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) ); // not resizable etc.
603 pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) );
604 pFilterBox = new ScFilterListBox( pFilterFloat, this, nCol, nRow, SC_FILTERBOX_PAGEFIELD );
605 if ( bLayoutRTL )
606 pFilterBox->EnableMirroring();
608 nSizeX += 1;
611 Font aOldFont = GetFont(); SetFont( pFilterBox->GetFont() );
612 MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL );
614 nHeight = GetTextHeight();
615 nHeight *= SC_FILTERLISTBOX_LINES;
617 SetMapMode( aOldMode );
618 SetFont( aOldFont );
621 // SetSize comes later
623 TypedScStrCollection aStrings( 128, 128 );
625 // get list box entries and selection
626 BOOL bHasCurrentPage = FALSE;
627 String aCurrentPage;
628 ScDPObject* pDPObj = pDoc->GetDPAtCursor(nCol, nRow, nTab);
629 if ( pDPObj && nCol > 0 )
631 // look for the dimension header left of the drop-down arrow
632 USHORT nOrient = sheet::DataPilotFieldOrientation_HIDDEN;
633 long nField = pDPObj->GetHeaderDim( ScAddress( nCol-1, nRow, nTab ), nOrient );
634 if ( nField >= 0 && nOrient == sheet::DataPilotFieldOrientation_PAGE )
636 pDPObj->FillPageList( aStrings, nField );
638 // get current page from SaveData
640 ScDPSaveData* pSaveData = pDPObj->GetSaveData();
641 BOOL bIsDataLayout;
642 String aDimName = pDPObj->GetDimName( nField, bIsDataLayout );
643 if ( pSaveData && !bIsDataLayout )
645 ScDPSaveDimension* pDim = pSaveData->GetExistingDimensionByName(aDimName);
646 if ( pDim && pDim->HasCurrentPage() )
648 aCurrentPage = pDim->GetCurrentPage();
649 bHasCurrentPage = TRUE;
655 // include all entry widths for the size of the drop-down
656 long nMaxText = 0;
657 USHORT nCount = aStrings.GetCount();
658 for (i=0; i<nCount; i++)
660 TypedStrData* pData = aStrings[i];
661 long nTextWidth = pFilterBox->GetTextWidth( pData->GetString() );
662 if ( nTextWidth > nMaxText )
663 nMaxText = nTextWidth;
666 // add scrollbar width if needed (string entries are counted here)
667 // (scrollbar is shown if the box is exactly full?)
668 if ( nCount >= SC_FILTERLISTBOX_LINES )
669 nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize();
671 nMaxText += 4; // for borders
673 if ( nMaxText > nSizeX )
674 nSizeX = nMaxText; // just modify width - starting position is unchanged
676 // adjust position and size to window
678 Size aParentSize = GetParent()->GetOutputSizePixel();
679 Size aSize( nSizeX, nHeight );
681 if ( aSize.Height() > aParentSize.Height() )
682 aSize.Height() = aParentSize.Height();
683 if ( aPos.Y() + aSize.Height() > aParentSize.Height() )
684 aPos.Y() = aParentSize.Height() - aSize.Height();
686 pFilterBox->SetSizePixel( aSize );
687 pFilterBox->Show(); // Show must be called before SetUpdateMode
688 pFilterBox->SetUpdateMode(FALSE);
690 pFilterFloat->SetOutputSizePixel( aSize );
691 pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS);
693 // fill the list box
694 BOOL bWait = ( nCount > 100 );
696 if (bWait)
697 EnterWait();
699 for (i=0; i<nCount; i++)
700 pFilterBox->InsertEntry( aStrings[i]->GetString() );
702 pFilterBox->SetSeparatorPos( 0 );
704 if (bWait)
705 LeaveWait();
707 pFilterBox->SetUpdateMode(TRUE);
709 USHORT nSelPos = LISTBOX_ENTRY_NOTFOUND;
710 if (bHasCurrentPage)
711 nSelPos = pFilterBox->GetEntryPos( aCurrentPage );
713 if ( nSelPos == LISTBOX_ENTRY_NOTFOUND )
714 nSelPos = 0; // first entry
716 pFilterBox->GrabFocus();
718 // call Select after GrabFocus, so the focus rectangle ends up in the right position
719 if ( nSelPos != LISTBOX_ENTRY_NOTFOUND )
720 pFilterBox->SelectEntryPos( nSelPos );
722 pFilterBox->EndInit();
724 nMouseStatus = SC_GM_FILTER;
725 CaptureMouse();
728 void ScGridWindow::LaunchDPFieldMenu( SCCOL nCol, SCROW nRow )
730 SCTAB nTab = pViewData->GetTabNo();
731 ScDPObject* pDPObj = pViewData->GetDocument()->GetDPAtCursor(nCol, nRow, nTab);
732 if (!pDPObj)
733 return;
735 // Get the geometry of the cell.
736 Point aScrPos = pViewData->GetScrPos(nCol, nRow, eWhich);
737 long nSizeX, nSizeY;
738 pViewData->GetMergeSizePixel(nCol, nRow, nSizeX, nSizeY);
739 Size aScrSize(nSizeX-1, nSizeY-1);
741 DPLaunchFieldPopupMenu(OutputToScreenPixel(aScrPos), aScrSize, ScAddress(nCol, nRow, nTab), pDPObj);
744 void ScGridWindow::DoScenarioMenue( const ScRange& rScenRange )
746 delete pFilterBox;
747 delete pFilterFloat;
749 SCCOL nCol = rScenRange.aEnd.Col(); // Zelle unterhalb des Buttons
750 SCROW nRow = rScenRange.aStart.Row();
751 if (nRow == 0)
753 nRow = rScenRange.aEnd.Row() + 1; // Bereich ganz oben -> Button unterhalb
754 if (nRow>MAXROW) nRow = MAXROW;
755 //! Texthoehe addieren (wenn sie an der View gespeichert ist...)
758 ScDocument* pDoc = pViewData->GetDocument();
759 SCTAB nTab = pViewData->GetTabNo();
760 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
762 long nSizeX = 0;
763 long nSizeY = 0;
764 long nHeight = 0;
765 pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
766 Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich );
767 if ( bLayoutRTL )
768 aPos.X() -= nSizeX;
769 Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) );
770 aCellRect.Top() -= nSizeY;
771 aCellRect.Bottom() -= nSizeY - 1;
772 // Die ListBox direkt unter der schwarzen Linie auf dem Zellgitter
773 // (wenn die Linie verdeckt wird, sieht es komisch aus...)
775 pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) ); // nicht resizable etc.
776 pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) );
777 pFilterBox = new ScFilterListBox( pFilterFloat, this, nCol, nRow, SC_FILTERBOX_SCENARIO );
778 if ( bLayoutRTL )
779 pFilterBox->EnableMirroring();
781 nSizeX += 1;
784 Font aOldFont = GetFont(); SetFont( pFilterBox->GetFont() );
785 MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL );
787 nHeight = GetTextHeight();
788 nHeight *= SC_FILTERLISTBOX_LINES;
790 SetMapMode( aOldMode );
791 SetFont( aOldFont );
794 // SetSize spaeter
796 pFilterBox->SetSelectionMode( SINGLE_SELECTION );
797 pFilterBox->SetTabs( nFilterBoxTabs, MapUnit( MAP_APPFONT ));
798 pFilterBox->SetTabJustify( 1, bLayoutRTL ? AdjustRight : AdjustLeft );
801 // ParentSize Abfrage fehlt
802 Size aSize( nSizeX, nHeight );
803 pFilterBox->SetSizePixel( aSize );
804 pFilterBox->Show(); // Show muss vor SetUpdateMode kommen !!!
805 pFilterBox->SetUpdateMode(FALSE);
807 // SetOutputSizePixel/StartPopupMode erst unten, wenn die Groesse feststeht
809 // Listbox fuellen
811 long nMaxText = 0;
812 String aCurrent;
813 String aTabName;
814 SCTAB nTabCount = pDoc->GetTableCount();
815 SCTAB nEntryCount = 0;
816 for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
818 if (pDoc->HasScenarioRange( i, rScenRange ))
819 if (pDoc->GetName( i, aTabName ))
821 pFilterBox->InsertEntry( aTabName );
822 if (pDoc->IsActiveScenario(i))
823 aCurrent = aTabName;
824 long nTextWidth = pFilterBox->GetTextWidth( aTabName );
825 if ( nTextWidth > nMaxText )
826 nMaxText = nTextWidth;
827 ++nEntryCount;
830 if (nEntryCount > SC_FILTERLISTBOX_LINES)
831 nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize();
832 nMaxText += 4; // fuer Rand
833 if ( nMaxText > 300 )
834 nMaxText = 300; // auch nicht uebertreiben (Pixel)
836 if (nMaxText > nSizeX) // Groesse auf benoetigte Groesse anpassen
838 long nDiff = nMaxText - nSizeX;
839 aSize = Size( nMaxText, nHeight );
840 pFilterBox->SetSizePixel( aSize );
841 pFilterFloat->SetOutputSizePixel( aSize );
843 if ( !bLayoutRTL )
845 // also move popup position
846 long nNewX = aCellRect.Left() - nDiff;
847 if ( nNewX < 0 )
848 nNewX = 0;
849 aCellRect.Left() = nNewX;
853 pFilterFloat->SetOutputSizePixel( aSize );
854 pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS );
856 pFilterBox->SetUpdateMode(TRUE);
857 pFilterBox->GrabFocus();
859 // Select erst nach GrabFocus, damit das Focus-Rechteck richtig landet
860 //! SvLBoxEntry* pSelect = NULL;
861 USHORT nPos = LISTBOX_ENTRY_NOTFOUND;
862 if (aCurrent.Len())
864 nPos = pFilterBox->GetEntryPos( aCurrent );
865 //! pSelect = pFilterBox->GetEntry( nPos );
867 if (/*!pSelect*/ LISTBOX_ENTRY_NOTFOUND == nPos && pFilterBox->GetEntryCount() > 0 )
868 nPos = 0;
869 //! pSelect = pFilterBox->GetEntry(0); // einer sollte immer selektiert sein
870 if (/*pSelect*/ LISTBOX_ENTRY_NOTFOUND != nPos )
871 pFilterBox->SelectEntryPos(nPos);
873 pFilterBox->EndInit();
875 // Szenario-Auswahl kommt aus MouseButtonDown:
876 // der naechste MouseMove auf die Filterbox ist wie ein ButtonDown
878 nMouseStatus = SC_GM_FILTER;
879 CaptureMouse();
882 void ScGridWindow::DoAutoFilterMenue( SCCOL nCol, SCROW nRow, BOOL bDataSelect )
884 delete pFilterBox;
885 delete pFilterFloat;
887 USHORT i;
888 ScDocument* pDoc = pViewData->GetDocument();
889 SCTAB nTab = pViewData->GetTabNo();
890 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
892 long nSizeX = 0;
893 long nSizeY = 0;
894 long nHeight = 0;
895 pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
896 Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich );
897 if ( bLayoutRTL )
898 aPos.X() -= nSizeX;
900 Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) );
902 aPos.X() -= 1;
903 aPos.Y() += nSizeY - 1;
905 pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) ); // nicht resizable etc.
906 pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) );
907 pFilterBox = new ScFilterListBox(
908 pFilterFloat, this, nCol, nRow, bDataSelect ? SC_FILTERBOX_DATASELECT : SC_FILTERBOX_FILTER );
909 if ( bLayoutRTL )
910 pFilterBox->EnableMirroring();
912 nSizeX += 1;
915 Font aOldFont = GetFont(); SetFont( pFilterBox->GetFont() );
916 MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL );
918 nHeight = GetTextHeight();
919 nHeight *= SC_FILTERLISTBOX_LINES;
921 SetMapMode( aOldMode );
922 SetFont( aOldFont );
925 // SetSize spaeter
927 pFilterBox->SetSelectionMode( SINGLE_SELECTION );
928 pFilterBox->SetTabs( nFilterBoxTabs, MapUnit( MAP_APPFONT ));
929 pFilterBox->SetTabJustify( 1, bLayoutRTL ? AdjustRight : AdjustLeft );
932 BOOL bEmpty = FALSE;
933 TypedScStrCollection aStrings( 128, 128 );
934 if ( bDataSelect ) // Auswahl-Liste
936 // Liste fuellen
937 aStrings.SetCaseSensitive( TRUE );
938 pDoc->GetDataEntries( nCol, nRow, nTab, aStrings );
939 if ( aStrings.GetCount() == 0 )
940 bEmpty = TRUE;
942 else // AutoFilter
944 //! wird der Titel ueberhaupt ausgewertet ???
945 String aString;
946 pDoc->GetString( nCol, nRow, nTab, aString );
947 pFilterBox->SetText( aString );
949 long nMaxText = 0;
951 // default entries
952 static const USHORT nDefIDs[] = { SCSTR_ALLFILTER, SCSTR_TOP10FILTER, SCSTR_STDFILTER, SCSTR_EMPTY, SCSTR_NOTEMPTY };
953 const USHORT nDefCount = sizeof(nDefIDs) / sizeof(USHORT);
954 for (i=0; i<nDefCount; i++)
956 String aEntry( (ScResId) nDefIDs[i] );
957 pFilterBox->InsertEntry( aEntry );
958 long nTextWidth = pFilterBox->GetTextWidth( aEntry );
959 if ( nTextWidth > nMaxText )
960 nMaxText = nTextWidth;
962 pFilterBox->SetSeparatorPos( nDefCount - 1 );
964 // get list entries
965 bool bHasDates = false;
966 pDoc->GetFilterEntries( nCol, nRow, nTab, true, aStrings, bHasDates);
967 pFilterBox->SetListHasDates(bHasDates);
969 // check widths of numerical entries (string entries are not included)
970 // so all numbers are completely visible
971 USHORT nCount = aStrings.GetCount();
972 for (i=0; i<nCount; i++)
974 TypedStrData* pData = aStrings[i];
975 if ( !pData->IsStrData() ) // only numerical entries
977 long nTextWidth = pFilterBox->GetTextWidth( pData->GetString() );
978 if ( nTextWidth > nMaxText )
979 nMaxText = nTextWidth;
983 // add scrollbar width if needed (string entries are counted here)
984 // (scrollbar is shown if the box is exactly full?)
985 if ( nCount + nDefCount >= SC_FILTERLISTBOX_LINES )
986 nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize();
988 nMaxText += 4; // for borders
990 if ( nMaxText > nSizeX )
991 nSizeX = nMaxText; // just modify width - starting position is unchanged
994 if (!bEmpty)
996 // Position und Groesse an Fenster anpassen
997 //! vorher Abfrage, ob die Eintraege hineinpassen (Breite)
999 Size aParentSize = GetParent()->GetOutputSizePixel();
1000 Size aSize( nSizeX, nHeight );
1002 if ( aSize.Height() > aParentSize.Height() )
1003 aSize.Height() = aParentSize.Height();
1004 if ( aPos.Y() + aSize.Height() > aParentSize.Height() )
1005 aPos.Y() = aParentSize.Height() - aSize.Height();
1007 pFilterBox->SetSizePixel( aSize );
1008 pFilterBox->Show(); // Show muss vor SetUpdateMode kommen !!!
1009 pFilterBox->SetUpdateMode(FALSE);
1011 pFilterFloat->SetOutputSizePixel( aSize );
1012 pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS);
1014 // Listbox fuellen
1015 USHORT nCount = aStrings.GetCount();
1016 BOOL bWait = ( nCount > 100 );
1018 if (bWait)
1019 EnterWait();
1021 for (i=0; i<nCount; i++)
1022 pFilterBox->InsertEntry( aStrings[i]->GetString() );
1024 if (bWait)
1025 LeaveWait();
1027 pFilterBox->SetUpdateMode(TRUE);
1030 //! SvLBoxEntry* pSelect = NULL;
1031 USHORT nSelPos = LISTBOX_ENTRY_NOTFOUND;
1033 if (!bDataSelect) // AutoFilter: aktiven Eintrag selektieren
1035 ScDBData* pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab );
1036 if (pDBData)
1038 ScQueryParam aParam;
1039 pDBData->GetQueryParam( aParam ); // kann nur MAXQUERY Eintraege ergeben
1041 BOOL bValid = TRUE;
1042 for (SCSIZE j=0; j<MAXQUERY && bValid; j++) // bisherige Filter-Einstellungen
1043 if (aParam.GetEntry(j).bDoQuery)
1045 //! Abfrage mit DrawButtons zusammenfassen!
1047 ScQueryEntry& rEntry = aParam.GetEntry(j);
1048 if (j>0)
1049 if (rEntry.eConnect != SC_AND)
1050 bValid = FALSE;
1051 if (rEntry.nField == nCol)
1053 if (rEntry.eOp == SC_EQUAL)
1055 String* pStr = rEntry.pStr;
1056 if (pStr)
1058 nSelPos = pFilterBox->GetEntryPos( *pStr );
1059 //! pSelect = pFilterBox->GetEntry( nPos );
1062 else if (rEntry.eOp == SC_TOPVAL && rEntry.pStr &&
1063 rEntry.pStr->EqualsAscii("10"))
1064 nSelPos = SC_AUTOFILTER_TOP10;
1065 else
1066 nSelPos = SC_AUTOFILTER_CUSTOM;
1070 if (!bValid)
1071 nSelPos = SC_AUTOFILTER_CUSTOM;
1074 else
1077 ULONG nIndex = ((SfxUInt32Item*)pDoc->GetAttr(
1078 nCol, nRow, nTab, ATTR_VALIDDATA ))->GetValue();
1079 if ( nIndex )
1081 const ScValidationData* pData = pDoc->GetValidationEntry( nIndex );
1082 if (pData)
1084 TypedStrData* pNew = NULL;
1085 String aDocStr;
1086 pDoc->GetString( nCol, nRow, nTab, aDocStr );
1087 if ( pDoc->HasValueData( nCol, nRow, nTab ) )
1089 double fVal = pDoc->GetValue(ScAddress(nCol, nRow, nTab));
1090 pNew = new TypedStrData( aDocStr, fVal, SC_STRTYPE_VALUE );
1092 else
1093 pNew = new TypedStrData( aDocStr, 0.0, SC_STRTYPE_STANDARD );
1095 bool bSortList = ( pData->GetListType() == ValidListType::SORTEDASCENDING);
1096 if ( bSortList )
1098 USHORT nStrIndex;
1099 if (aStrings.Search(pNew,nStrIndex))
1100 nSelPos = nStrIndex;
1102 else
1104 USHORT nCount = aStrings.GetCount();
1105 for (i = 0; ((i < nCount) && ( LISTBOX_ENTRY_NOTFOUND == nSelPos)); i++)
1107 if ( aStrings.Compare(aStrings[i], pNew)==0 )
1108 nSelPos = i;
1111 delete pNew;
1116 // neu (309): irgendwas muss immer selektiert sein:
1117 if ( LISTBOX_ENTRY_NOTFOUND == nSelPos && pFilterBox->GetEntryCount() > 0 && !bDataSelect)
1118 nSelPos = 0;
1120 // keine leere Auswahl-Liste anzeigen:
1122 if ( bEmpty )
1124 DELETEZ(pFilterBox); // war nix
1125 DELETEZ(pFilterFloat);
1126 Sound::Beep(); // bemerkbar machen
1128 else
1130 // pFilterBox->Show(); // schon vorne
1131 pFilterBox->GrabFocus();
1133 // Select erst nach GrabFocus, damit das Focus-Rechteck richtig landet
1134 if ( LISTBOX_ENTRY_NOTFOUND != nSelPos )
1135 pFilterBox->SelectEntryPos( nSelPos );
1136 else
1138 if (bDataSelect)
1139 pFilterBox->SetNoSelection();
1142 pFilterBox->EndInit();
1144 if (!bDataSelect)
1146 // AutoFilter (aus MouseButtonDown):
1147 // der naechste MouseMove auf die Filterbox ist wie ein ButtonDown
1149 nMouseStatus = SC_GM_FILTER;
1150 CaptureMouse();
1155 void ScGridWindow::FilterSelect( ULONG nSel )
1157 String aString;
1159 SvLBoxEntry* pEntry = pFilterBox->GetEntry( nSel );
1160 if (pEntry)
1162 SvLBoxString* pStringEntry = (SvLBoxString*) pEntry->GetFirstItem( SV_ITEM_ID_LBOXSTRING );
1163 if ( pStringEntry )
1164 aString = pStringEntry->GetText();
1167 aString = pFilterBox->GetEntry( static_cast< USHORT >( nSel ) );
1169 SCCOL nCol = pFilterBox->GetCol();
1170 SCROW nRow = pFilterBox->GetRow();
1171 switch ( pFilterBox->GetMode() )
1173 case SC_FILTERBOX_DATASELECT:
1174 ExecDataSelect( nCol, nRow, aString );
1175 break;
1176 case SC_FILTERBOX_FILTER:
1177 ExecFilter( nSel, nCol, nRow, aString, pFilterBox->HasDates() );
1178 break;
1179 case SC_FILTERBOX_SCENARIO:
1180 pViewData->GetView()->UseScenario( aString );
1181 break;
1182 case SC_FILTERBOX_PAGEFIELD:
1183 // first entry is "all"
1184 ExecPageFieldSelect( nCol, nRow, (nSel != 0), aString );
1185 break;
1188 if (pFilterFloat)
1189 pFilterFloat->EndPopupMode();
1191 GrabFocus(); // unter OS/2 stimmt der Focus sonst nicht
1194 void ScGridWindow::ExecDataSelect( SCCOL nCol, SCROW nRow, const String& rStr )
1196 if ( rStr.Len() )
1198 SCTAB nTab = pViewData->GetTabNo();
1199 ScViewFunc* pView = pViewData->GetView();
1200 pView->EnterData( nCol, nRow, nTab, rStr );
1202 // #i52307# CellContentChanged is not in EnterData so it isn't called twice
1203 // if the cursor is moved afterwards.
1204 pView->CellContentChanged();
1208 void ScGridWindow::ExecFilter( ULONG nSel,
1209 SCCOL nCol, SCROW nRow,
1210 const String& aValue, bool bCheckForDates )
1212 SCTAB nTab = pViewData->GetTabNo();
1213 ScDocument* pDoc = pViewData->GetDocument();
1215 ScDBData* pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab );
1216 if (pDBData)
1218 ScQueryParam aParam;
1219 pDBData->GetQueryParam( aParam ); // kann nur MAXQUERY Eintraege ergeben
1221 if (SC_AUTOFILTER_CUSTOM == nSel)
1223 SCTAB nAreaTab;
1224 SCCOL nStartCol;
1225 SCROW nStartRow;
1226 SCCOL nEndCol;
1227 SCROW nEndRow;
1228 pDBData->GetArea( nAreaTab, nStartCol,nStartRow,nEndCol,nEndRow );
1229 pViewData->GetView()->MarkRange( ScRange( nStartCol,nStartRow,nAreaTab,nEndCol,nEndRow,nAreaTab));
1230 pViewData->GetView()->SetCursor(nCol,nRow); //! auch ueber Slot ??
1231 pViewData->GetDispatcher().Execute( SID_FILTER, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD );
1233 else
1235 BOOL bDeleteOld = FALSE;
1236 SCSIZE nQueryPos = 0;
1237 BOOL bFound = FALSE;
1238 if (!aParam.bInplace)
1239 bDeleteOld = TRUE;
1240 if (aParam.bRegExp)
1241 bDeleteOld = TRUE;
1242 for (SCSIZE i=0; i<MAXQUERY && !bDeleteOld; i++) // bisherige Filter-Einstellungen
1243 if (aParam.GetEntry(i).bDoQuery)
1245 //! Abfrage mit DrawButtons zusammenfassen!
1247 ScQueryEntry& rEntry = aParam.GetEntry(i);
1248 if (i>0)
1249 if (rEntry.eConnect != SC_AND)
1250 bDeleteOld = TRUE;
1252 if (rEntry.nField == nCol)
1254 if (bFound) // diese Spalte zweimal?
1255 bDeleteOld = TRUE;
1256 nQueryPos = i;
1257 bFound = TRUE;
1259 if (!bFound)
1260 nQueryPos = i + 1;
1263 if (bDeleteOld)
1265 SCSIZE nEC = aParam.GetEntryCount();
1266 for (SCSIZE i=0; i<nEC; i++)
1267 aParam.GetEntry(i).Clear();
1268 nQueryPos = 0;
1269 aParam.bInplace = TRUE;
1270 aParam.bRegExp = FALSE;
1273 if ( nQueryPos < MAXQUERY || SC_AUTOFILTER_ALL == nSel ) // loeschen geht immer
1275 if (nSel)
1277 ScQueryEntry& rNewEntry = aParam.GetEntry(nQueryPos);
1279 rNewEntry.bDoQuery = TRUE;
1280 rNewEntry.bQueryByString = TRUE;
1281 rNewEntry.nField = nCol;
1282 rNewEntry.bQueryByDate = bCheckForDates;
1283 if ( nSel == SC_AUTOFILTER_TOP10 )
1285 rNewEntry.eOp = SC_TOPVAL;
1286 *rNewEntry.pStr = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("10"));
1288 else if (nSel == SC_AUTOFILTER_EMPTY)
1290 rNewEntry.pStr->Erase();
1291 rNewEntry.bQueryByString = FALSE;
1292 rNewEntry.eOp = SC_EQUAL;
1293 rNewEntry.nVal = SC_EMPTYFIELDS;
1296 else if (nSel == SC_AUTOFILTER_NOTEMPTY)
1298 rNewEntry.pStr->Erase();
1299 rNewEntry.bQueryByString = FALSE;
1300 rNewEntry.eOp = SC_EQUAL;
1301 rNewEntry.nVal = SC_NONEMPTYFIELDS;
1303 else
1305 rNewEntry.eOp = SC_EQUAL;
1306 *rNewEntry.pStr = aValue;
1308 if (nQueryPos > 0)
1309 rNewEntry.eConnect = SC_AND;
1311 else
1313 if (bFound)
1314 aParam.DeleteQuery(nQueryPos);
1317 // #100597# end edit mode - like in ScCellShell::ExecuteDB
1318 if ( pViewData->HasEditView( pViewData->GetActivePart() ) )
1320 SC_MOD()->InputEnterHandler();
1321 pViewData->GetViewShell()->UpdateInputHandler();
1324 aParam.bUseDynamicRange = true;
1325 pViewData->GetView()->Query( aParam, NULL, TRUE );
1326 pDBData->SetQueryParam( aParam ); // speichern
1328 else // "Zuviele Bedingungen"
1329 pViewData->GetView()->ErrorMessage( STR_FILTER_TOOMANY );
1332 else
1334 DBG_ERROR("Wo ist der Datenbankbereich?");
1338 void ScGridWindow::SetPointer( const Pointer& rPointer )
1340 nCurrentPointer = 0;
1341 Window::SetPointer( rPointer );
1344 void ScGridWindow::MoveMouseStatus( ScGridWindow& rDestWin )
1346 if (nButtonDown)
1348 rDestWin.nButtonDown = nButtonDown;
1349 rDestWin.nMouseStatus = nMouseStatus;
1352 if (bRFMouse)
1354 rDestWin.bRFMouse = bRFMouse;
1355 rDestWin.bRFSize = bRFSize;
1356 rDestWin.nRFIndex = nRFIndex;
1357 rDestWin.nRFAddX = nRFAddX;
1358 rDestWin.nRFAddY = nRFAddY;
1359 bRFMouse = FALSE;
1362 if (nPagebreakMouse)
1364 rDestWin.nPagebreakMouse = nPagebreakMouse;
1365 rDestWin.nPagebreakBreak = nPagebreakBreak;
1366 rDestWin.nPagebreakPrev = nPagebreakPrev;
1367 rDestWin.aPagebreakSource = aPagebreakSource;
1368 rDestWin.aPagebreakDrag = aPagebreakDrag;
1369 nPagebreakMouse = SC_PD_NONE;
1373 BOOL ScGridWindow::TestMouse( const MouseEvent& rMEvt, BOOL bAction )
1375 // MouseEvent buttons must only be checked if bAction==TRUE
1376 // to allow changing the mouse pointer in MouseMove,
1377 // but not start AutoFill with right button (#74229#).
1378 // with bAction==TRUE, SetFillMode / SetDragMode is called
1380 if ( bAction && !rMEvt.IsLeft() )
1381 return FALSE;
1383 BOOL bNewPointer = FALSE;
1385 SfxInPlaceClient* pClient = pViewData->GetViewShell()->GetIPClient();
1386 BOOL bOleActive = ( pClient && pClient->IsObjectInPlaceActive() );
1388 if ( pViewData->IsActive() && !bOleActive )
1390 ScDocument* pDoc = pViewData->GetDocument();
1391 SCTAB nTab = pViewData->GetTabNo();
1392 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1393 long nLayoutSign = bLayoutRTL ? -1 : 1;
1395 // Auto-Fill
1397 ScRange aMarkRange;
1398 if (pViewData->GetSimpleArea( aMarkRange ) == SC_MARK_SIMPLE)
1400 if (aMarkRange.aStart.Tab() == pViewData->GetTabNo() && mpAutoFillRect)
1402 Point aMousePos = rMEvt.GetPosPixel();
1403 if (mpAutoFillRect->IsInside(aMousePos))
1405 SetPointer( Pointer( POINTER_CROSS ) ); //! dickeres Kreuz ?
1406 if (bAction)
1408 SCCOL nX = aMarkRange.aEnd.Col();
1409 SCROW nY = aMarkRange.aEnd.Row();
1411 if ( lcl_IsEditableMatrix( pViewData->GetDocument(), aMarkRange ) )
1412 pViewData->SetDragMode(
1413 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nX, nY, SC_FILL_MATRIX );
1414 else
1415 pViewData->SetFillMode(
1416 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nX, nY );
1418 // #108266# The simple selection must also be recognized when dragging,
1419 // where the Marking flag is set and MarkToSimple won't work anymore.
1420 pViewData->GetMarkData().MarkToSimple();
1422 bNewPointer = TRUE;
1427 // Embedded-Rechteck
1429 if (pDoc->IsEmbedded())
1431 ScRange aRange;
1432 pDoc->GetEmbedded( aRange );
1433 if ( pViewData->GetTabNo() == aRange.aStart.Tab() )
1435 Point aStartPos = pViewData->GetScrPos( aRange.aStart.Col(), aRange.aStart.Row(), eWhich );
1436 Point aEndPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aEnd.Row()+1, eWhich );
1437 Point aMousePos = rMEvt.GetPosPixel();
1438 if ( bLayoutRTL )
1440 aStartPos.X() += 2;
1441 aEndPos.X() += 2;
1443 BOOL bTop = ( aMousePos.X() >= aStartPos.X()-3 && aMousePos.X() <= aStartPos.X()+1 &&
1444 aMousePos.Y() >= aStartPos.Y()-3 && aMousePos.Y() <= aStartPos.Y()+1 );
1445 BOOL bBottom = ( aMousePos.X() >= aEndPos.X()-3 && aMousePos.X() <= aEndPos.X()+1 &&
1446 aMousePos.Y() >= aEndPos.Y()-3 && aMousePos.Y() <= aEndPos.Y()+1 );
1447 if ( bTop || bBottom )
1449 SetPointer( Pointer( POINTER_CROSS ) );
1450 if (bAction)
1452 BYTE nMode = bTop ? SC_FILL_EMBED_LT : SC_FILL_EMBED_RB;
1453 pViewData->SetDragMode(
1454 aRange.aStart.Col(), aRange.aStart.Row(),
1455 aRange.aEnd.Col(), aRange.aEnd.Row(), nMode );
1457 bNewPointer = TRUE;
1463 if (!bNewPointer && bAction)
1465 // SetPointer( POINTER_ARROW ); // in Fu...
1466 pViewData->ResetFillMode();
1469 return bNewPointer;
1472 void __EXPORT ScGridWindow::MouseButtonDown( const MouseEvent& rMEvt )
1474 nNestedButtonState = SC_NESTEDBUTTON_DOWN;
1476 HandleMouseButtonDown( rMEvt );
1478 if ( nNestedButtonState == SC_NESTEDBUTTON_UP )
1480 // #i41690# If an object is deactivated from MouseButtonDown, it might reschedule,
1481 // so MouseButtonUp comes before the MouseButtonDown call is finished. In this case,
1482 // simulate another MouseButtonUp call, so the selection state is consistent.
1484 nButtonDown = rMEvt.GetButtons();
1485 FakeButtonUp();
1487 if ( IsTracking() )
1488 EndTracking(); // normally done in VCL as part of MouseButtonUp handling
1490 nNestedButtonState = SC_NESTEDBUTTON_NONE;
1493 void ScGridWindow::HandleMouseButtonDown( const MouseEvent& rMEvt )
1495 // We have to check if a context menu is shown and we have an UI
1496 // active inplace client. In that case we have to ignore the event.
1497 // Otherwise we would crash (context menu has been
1498 // opened by inplace client and we would deactivate the inplace client,
1499 // the contex menu is closed by VCL asynchronously which in the end
1500 // would work on deleted objects or the context menu has no parent anymore)
1501 // See #126086# and #128122#
1502 SfxViewShell* pViewSh = pViewData->GetViewShell();
1503 SfxInPlaceClient* pClient = pViewSh->GetIPClient();
1504 if ( pClient &&
1505 pClient->IsObjectInPlaceActive() &&
1506 PopupMenu::IsInExecute() )
1507 return;
1509 aCurMousePos = rMEvt.GetPosPixel();
1511 // Filter-Popup beendet sich mit eigenem Mausklick, nicht erst beim Klick
1512 // in das GridWindow, darum ist die folgende Abfrage nicht mehr noetig:
1513 #if 0
1514 // merken, dass FilterBox geloescht wird, damit sichergestellt
1515 // ist, dass in diesem Handler nicht an gleicher Stelle wieder
1516 // eine neue geoeffnet wird.
1517 BOOL bWasFilterBox = ( pFilterBox != NULL &&
1518 ((Window*)pFilterBox)->IsVisible() &&
1519 !pFilterBox->IsDataSelect() );
1520 SCCOL nOldColFBox = bWasFilterBox ? pFilterBox->GetCol() : 0;
1521 SCROW nOldRowFBox = bWasFilterBox ? pFilterBox->GetRow() : 0;
1522 #endif
1523 #include "cellsuno.hxx"
1525 ClickExtern(); // loescht FilterBox, wenn vorhanden
1527 HideNoteMarker(); // Notiz-Anzeige
1529 bEEMouse = FALSE;
1531 ScModule* pScMod = SC_MOD();
1532 if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
1534 Sound::Beep();
1535 return;
1538 pScActiveViewShell = pViewData->GetViewShell(); // falls auf Link geklickt wird
1539 nScClickMouseModifier = rMEvt.GetModifier(); // um Control-Klick immer zu erkennen
1541 BOOL bDetective = pViewData->GetViewShell()->IsAuditShell();
1542 BOOL bRefMode = pViewData->IsRefMode(); // Referenz angefangen
1543 BOOL bFormulaMode = pScMod->IsFormulaMode(); // naechster Klick -> Referenz
1544 BOOL bEditMode = pViewData->HasEditView(eWhich); // auch bei Mode==SC_INPUT_TYPE
1545 BOOL bDouble = (rMEvt.GetClicks() == 2);
1547 // DeactivateIP passiert nur noch bei MarkListHasChanged
1549 // im GrabFocus Aufruf kann eine Fehlermeldung hochkommen
1550 // (z.B. beim Umbenennen von Tabellen per Tab-Reiter)
1552 if ( !nButtonDown || !bDouble ) // single (first) click is always valid
1553 nButtonDown = rMEvt.GetButtons(); // set nButtonDown first, so StopMarking works
1555 // pViewData->GetViewShell()->GetViewFrame()->GetWindow().GrabFocus();
1556 if ( ( bEditMode && pViewData->GetActivePart() == eWhich ) || !bFormulaMode )
1557 GrabFocus();
1559 // #i31846# need to cancel a double click if the first click has set the "ignore" state,
1560 // but a single (first) click is always valid
1561 if ( nMouseStatus == SC_GM_IGNORE && bDouble )
1563 nButtonDown = 0;
1564 nMouseStatus = SC_GM_NONE;
1565 return;
1568 if ( bDetective ) // Detektiv-Fuell-Modus
1570 if ( rMEvt.IsLeft() && !rMEvt.GetModifier() )
1572 Point aPos = rMEvt.GetPosPixel();
1573 SCsCOL nPosX;
1574 SCsROW nPosY;
1575 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
1577 SfxInt16Item aPosXItem( SID_RANGE_COL, nPosX );
1578 SfxInt32Item aPosYItem( SID_RANGE_ROW, nPosY );
1579 pViewData->GetDispatcher().Execute( SID_FILL_SELECT, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD,
1580 &aPosXItem, &aPosYItem, (void*)0L );
1583 nButtonDown = 0;
1584 nMouseStatus = SC_GM_NONE;
1585 return;
1588 if (!bDouble)
1589 nMouseStatus = SC_GM_NONE;
1591 if (!bFormulaMode)
1593 if ( pViewData->GetActivePart() != eWhich )
1594 pViewData->GetView()->ActivatePart( eWhich );
1596 else
1598 ScViewSelectionEngine* pSelEng = pViewData->GetView()->GetSelEngine();
1599 pSelEng->SetWindow(this);
1600 pSelEng->SetWhich(eWhich);
1601 pSelEng->SetVisibleArea( Rectangle(Point(), GetOutputSizePixel()) );
1604 if (bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()))
1606 Point aPos = rMEvt.GetPosPixel();
1607 SCsCOL nPosX;
1608 SCsROW nPosY;
1609 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
1611 EditView* pEditView;
1612 SCCOL nEditCol;
1613 SCROW nEditRow;
1614 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
1615 SCCOL nEndCol = pViewData->GetEditEndCol();
1616 SCROW nEndRow = pViewData->GetEditEndRow();
1618 if ( nPosX >= (SCsCOL) nEditCol && nPosX <= (SCsCOL) nEndCol &&
1619 nPosY >= (SCsROW) nEditRow && nPosY <= (SCsROW) nEndRow )
1621 // #53966# beim Klick in die Tabellen-EditView immer den Focus umsetzen
1622 if (bFormulaMode) // sonst ist es oben schon passiert
1623 GrabFocus();
1625 pScMod->SetInputMode( SC_INPUT_TABLE );
1626 bEEMouse = TRUE;
1627 bEditMode = pEditView->MouseButtonDown( rMEvt );
1628 return;
1632 if (pScMod->GetIsWaterCan())
1634 //! was is mit'm Mac ???
1635 if ( rMEvt.GetModifier() + rMEvt.GetButtons() == MOUSE_RIGHT )
1637 nMouseStatus = SC_GM_WATERUNDO;
1638 return;
1642 // Reihenfolge passend zum angezeigten Cursor:
1643 // RangeFinder, AutoFill, PageBreak, Drawing
1645 if ( HitRangeFinder( rMEvt.GetPosPixel(), bRFSize, &nRFIndex, &nRFAddX, &nRFAddY ) )
1647 bRFMouse = TRUE; // die anderen Variablen sind oben initialisiert
1649 if ( pViewData->GetActivePart() != eWhich )
1650 pViewData->GetView()->ActivatePart( eWhich ); //! schon oben immer ???
1652 // CaptureMouse();
1653 StartTracking();
1654 return;
1657 BOOL bCrossPointer = TestMouse( rMEvt, TRUE );
1658 if ( bCrossPointer )
1660 if ( bDouble )
1661 pViewData->GetView()->FillCrossDblClick();
1662 else
1663 pScMod->InputEnterHandler(); // Autofill etc.
1666 if ( !bCrossPointer )
1668 nPagebreakMouse = HitPageBreak( rMEvt.GetPosPixel(), &aPagebreakSource,
1669 &nPagebreakBreak, &nPagebreakPrev );
1670 if (nPagebreakMouse)
1672 bPagebreakDrawn = FALSE;
1673 // CaptureMouse();
1674 StartTracking();
1675 PagebreakMove( rMEvt, FALSE );
1676 return;
1680 if (!bFormulaMode && !bEditMode && rMEvt.IsLeft())
1682 if ( !bCrossPointer && DrawMouseButtonDown(rMEvt) )
1684 //if (DrawHasMarkedObj())
1685 // pViewData->GetViewShell()->SetDrawShellOrSub(); // Draw-Objekt selektiert
1686 return;
1689 pViewData->GetViewShell()->SetDrawShell( FALSE ); // kein Draw-Objekt selektiert
1691 // TestMouse schon oben passiert
1694 Point aPos = rMEvt.GetPosPixel();
1695 SCsCOL nPosX;
1696 SCsROW nPosY;
1697 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
1698 SCTAB nTab = pViewData->GetTabNo();
1699 ScDocument* pDoc = pViewData->GetDocument();
1703 // AutoFilter buttons
1706 if ( !bDouble && !bFormulaMode && rMEvt.IsLeft() )
1708 ScMergeFlagAttr* pAttr = (ScMergeFlagAttr*)
1709 pDoc->GetAttr( nPosX, nPosY, nTab, ATTR_MERGE_FLAG );
1710 if (pAttr->HasAutoFilter())
1712 if (DoAutoFilterButton(nPosX, nPosY, rMEvt))
1713 return;
1715 if (pAttr->HasButton())
1717 DoPushButton( nPosX, nPosY, rMEvt ); // setzt evtl. bPivotMouse / bDPMouse
1718 return;
1721 // List Validity drop-down button
1723 if ( bListValButton )
1725 Rectangle aButtonRect = GetListValButtonRect( aListValPos );
1726 if ( aButtonRect.IsInside( aPos ) )
1728 DoAutoFilterMenue( aListValPos.Col(), aListValPos.Row(), TRUE );
1730 nMouseStatus = SC_GM_FILTER; // not set in DoAutoFilterMenue for bDataSelect
1731 CaptureMouse();
1732 return;
1738 // scenario selection
1741 ScRange aScenRange;
1742 if ( rMEvt.IsLeft() && HasScenarioButton( aPos, aScenRange ) )
1744 DoScenarioMenue( aScenRange );
1745 return;
1749 // Doppelklick angefangen ?
1752 // StopMarking kann aus DrawMouseButtonDown gerufen werden
1754 if ( nMouseStatus != SC_GM_IGNORE && !bRefMode )
1756 if ( bDouble && !bCrossPointer )
1758 if (nMouseStatus == SC_GM_TABDOWN)
1759 nMouseStatus = SC_GM_DBLDOWN;
1761 else
1762 nMouseStatus = SC_GM_TABDOWN;
1766 // Links in Edit-Zellen
1769 BOOL bAlt = rMEvt.IsMod2();
1770 if ( !bAlt && rMEvt.IsLeft() &&
1771 GetEditUrl(rMEvt.GetPosPixel()) ) // Klick auf Link: Cursor nicht bewegen
1773 SetPointer( Pointer( POINTER_REFHAND ) );
1774 nMouseStatus = SC_GM_URLDOWN; // auch nur dann beim ButtonUp ausfuehren
1775 return;
1779 // Gridwin - SelectionEngine
1782 if ( rMEvt.IsLeft() )
1784 ScViewSelectionEngine* pSelEng = pViewData->GetView()->GetSelEngine();
1785 pSelEng->SetWindow(this);
1786 pSelEng->SetWhich(eWhich);
1787 pSelEng->SetVisibleArea( Rectangle(Point(), GetOutputSizePixel()) );
1789 // SelMouseButtonDown an der View setzt noch das bMoveIsShift Flag
1790 if ( pViewData->GetView()->SelMouseButtonDown( rMEvt ) )
1792 if (IsMouseCaptured())
1794 // Tracking statt CaptureMouse, damit sauber abgebrochen werden kann
1795 //! Irgendwann sollte die SelectionEngine selber StartTracking rufen!?!
1796 ReleaseMouse();
1797 StartTracking();
1799 pViewData->GetMarkData().SetMarking(TRUE);
1800 return;
1805 void __EXPORT ScGridWindow::MouseButtonUp( const MouseEvent& rMEvt )
1807 aCurMousePos = rMEvt.GetPosPixel();
1808 ScDocument* pDoc = pViewData->GetDocument();
1809 ScMarkData& rMark = pViewData->GetMarkData();
1811 // #i41690# detect a MouseButtonUp call from within MouseButtonDown
1812 // (possible through Reschedule from storing an OLE object that is deselected)
1814 if ( nNestedButtonState == SC_NESTEDBUTTON_DOWN )
1815 nNestedButtonState = SC_NESTEDBUTTON_UP;
1817 if (nButtonDown != rMEvt.GetButtons())
1818 nMouseStatus = SC_GM_IGNORE; // reset und return
1820 nButtonDown = 0;
1822 if (nMouseStatus == SC_GM_IGNORE)
1824 nMouseStatus = SC_GM_NONE;
1825 // Selection-Engine: Markieren abbrechen
1826 pViewData->GetView()->GetSelEngine()->Reset();
1827 rMark.SetMarking(FALSE);
1828 if (pViewData->IsAnyFillMode())
1830 pViewData->GetView()->StopRefMode();
1831 pViewData->ResetFillMode();
1833 StopMarking();
1834 DrawEndAction(); // Markieren/Verschieben auf Drawing-Layer abbrechen
1835 ReleaseMouse();
1836 return;
1839 if (nMouseStatus == SC_GM_FILTER)
1841 if ( pFilterBox && pFilterBox->GetMode() == SC_FILTERBOX_FILTER )
1843 if (mpFilterButton.get())
1845 bool bFilterActive = IsAutoFilterActive(
1846 pFilterBox->GetCol(), pFilterBox->GetRow(), pViewData->GetTabNo() );
1848 mpFilterButton->setHasHiddenMember(bFilterActive);
1849 mpFilterButton->setPopupPressed(false);
1850 HideCursor();
1851 mpFilterButton->draw();
1852 ShowCursor();
1855 nMouseStatus = SC_GM_NONE;
1856 ReleaseMouse();
1857 return; // da muss nix mehr passieren
1860 ScModule* pScMod = SC_MOD();
1861 if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
1862 return;
1864 SfxBindings& rBindings = pViewData->GetBindings();
1865 if (bEEMouse && pViewData->HasEditView( eWhich ))
1867 EditView* pEditView;
1868 SCCOL nEditCol;
1869 SCROW nEditRow;
1870 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
1871 pEditView->MouseButtonUp( rMEvt );
1873 if ( rMEvt.IsMiddle() &&
1874 GetSettings().GetMouseSettings().GetMiddleButtonAction() == MOUSE_MIDDLE_PASTESELECTION )
1876 // EditView may have pasted from selection
1877 pScMod->InputChanged( pEditView );
1879 else
1880 pScMod->InputSelection( pEditView ); // parentheses etc.
1882 pViewData->GetView()->InvalidateAttribs();
1883 rBindings.Invalidate( SID_HYPERLINK_GETLINK );
1884 bEEMouse = FALSE;
1885 return;
1888 if (bDPMouse)
1890 DPMouseButtonUp( rMEvt ); // resets bDPMouse
1891 return;
1894 if (bRFMouse)
1896 RFMouseMove( rMEvt, TRUE ); // Range wieder richtigherum
1897 bRFMouse = FALSE;
1898 SetPointer( Pointer( POINTER_ARROW ) );
1899 ReleaseMouse();
1900 return;
1903 if (nPagebreakMouse)
1905 PagebreakMove( rMEvt, TRUE );
1906 nPagebreakMouse = SC_PD_NONE;
1907 SetPointer( Pointer( POINTER_ARROW ) );
1908 ReleaseMouse();
1909 return;
1912 if (nMouseStatus == SC_GM_WATERUNDO) // Undo im Giesskannenmodus
1914 SfxUndoManager* pMgr = pViewData->GetDocShell()->GetUndoManager();
1915 if ( pMgr->GetUndoActionCount() && pMgr->GetUndoActionId() == STR_UNDO_APPLYCELLSTYLE )
1916 pMgr->Undo();
1917 else
1918 Sound::Beep();
1919 return;
1922 if (DrawMouseButtonUp(rMEvt)) // includes format paint brush handling for drawing objects
1923 return;
1925 rMark.SetMarking(FALSE);
1927 SetPointer( Pointer( POINTER_ARROW ) );
1929 if (pViewData->IsFillMode() ||
1930 ( pViewData->GetFillMode() == SC_FILL_MATRIX && rMEvt.IsMod1() ))
1932 nScFillModeMouseModifier = rMEvt.GetModifier();
1933 SCCOL nStartCol;
1934 SCROW nStartRow;
1935 SCCOL nEndCol;
1936 SCROW nEndRow;
1937 pViewData->GetFillData( nStartCol, nStartRow, nEndCol, nEndRow );
1938 // DBG_ASSERT( nStartCol==pViewData->GetRefStartX() && nStartRow==pViewData->GetRefStartY(),
1939 // "Block falsch fuer AutoFill" );
1940 ScRange aDelRange;
1941 BOOL bIsDel = pViewData->GetDelMark( aDelRange );
1943 ScViewFunc* pView = pViewData->GetView();
1944 pView->StopRefMode();
1945 pViewData->ResetFillMode();
1946 pView->GetFunctionSet()->SetAnchorFlag( FALSE ); // #i5819# don't use AutoFill anchor flag for selection
1948 if ( bIsDel )
1950 pView->MarkRange( aDelRange, FALSE );
1951 pView->DeleteContents( IDF_CONTENTS );
1952 SCTAB nTab = pViewData->GetTabNo();
1953 ScRange aBlockRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab );
1954 if ( aBlockRange != aDelRange )
1956 if ( aDelRange.aStart.Row() == nStartRow )
1957 aBlockRange.aEnd.SetCol( aDelRange.aStart.Col() - 1 );
1958 else
1959 aBlockRange.aEnd.SetRow( aDelRange.aStart.Row() - 1 );
1960 pView->MarkRange( aBlockRange, FALSE );
1963 else
1964 pViewData->GetDispatcher().Execute( FID_FILL_AUTO, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD );
1966 else if (pViewData->GetFillMode() == SC_FILL_MATRIX)
1968 SCTAB nTab = pViewData->GetTabNo();
1969 SCCOL nStartCol;
1970 SCROW nStartRow;
1971 SCCOL nEndCol;
1972 SCROW nEndRow;
1973 pViewData->GetFillData( nStartCol, nStartRow, nEndCol, nEndRow );
1974 ScRange aBlockRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab );
1975 SCCOL nFillCol = pViewData->GetRefEndX();
1976 SCROW nFillRow = pViewData->GetRefEndY();
1977 ScAddress aEndPos( nFillCol, nFillRow, nTab );
1979 ScTabView* pView = pViewData->GetView();
1980 pView->StopRefMode();
1981 pViewData->ResetFillMode();
1982 pView->GetFunctionSet()->SetAnchorFlag( FALSE );
1984 if ( aEndPos != aBlockRange.aEnd )
1986 pViewData->GetDocShell()->GetDocFunc().ResizeMatrix( aBlockRange, aEndPos, FALSE );
1987 pViewData->GetView()->MarkRange( ScRange( aBlockRange.aStart, aEndPos ) );
1990 else if (pViewData->IsAnyFillMode())
1992 // Embedded-Area has been changed
1993 ScTabView* pView = pViewData->GetView();
1994 pView->StopRefMode();
1995 pViewData->ResetFillMode();
1996 pView->GetFunctionSet()->SetAnchorFlag( FALSE );
1997 pViewData->GetDocShell()->UpdateOle(pViewData);
2000 BOOL bRefMode = pViewData->IsRefMode();
2001 if (bRefMode)
2002 pScMod->EndReference();
2005 // Giesskannen-Modus (Gestalter)
2008 if (pScMod->GetIsWaterCan())
2010 // Abfrage auf Undo schon oben
2012 ScStyleSheetPool* pStylePool = (ScStyleSheetPool*)
2013 (pViewData->GetDocument()->
2014 GetStyleSheetPool());
2015 if ( pStylePool )
2017 SfxStyleSheet* pStyleSheet = (SfxStyleSheet*)
2018 pStylePool->GetActualStyleSheet();
2020 if ( pStyleSheet )
2022 SfxStyleFamily eFamily = pStyleSheet->GetFamily();
2024 switch ( eFamily )
2026 case SFX_STYLE_FAMILY_PARA:
2027 pViewData->GetView()->SetStyleSheetToMarked( pStyleSheet );
2028 pViewData->GetView()->DoneBlockMode();
2029 break;
2031 case SFX_STYLE_FAMILY_PAGE:
2032 pViewData->GetDocument()->SetPageStyle( pViewData->GetTabNo(),
2033 pStyleSheet->GetName() );
2035 ScPrintFunc( pViewData->GetDocShell(),
2036 pViewData->GetViewShell()->GetPrinter(TRUE),
2037 pViewData->GetTabNo() ).UpdatePages();
2039 rBindings.Invalidate( SID_STATUS_PAGESTYLE );
2040 break;
2042 default:
2043 break;
2049 ScDBFunc* pView = pViewData->GetView();
2050 ScDocument* pBrushDoc = pView->GetBrushDocument();
2051 if ( pBrushDoc )
2053 pView->PasteFromClip( IDF_ATTRIB, pBrushDoc );
2054 if ( !pView->IsPaintBrushLocked() )
2055 pView->ResetBrushDocument(); // invalidates pBrushDoc pointer
2059 // double click (only left button)
2062 BOOL bDouble = ( rMEvt.GetClicks() == 2 && rMEvt.IsLeft() );
2063 if ( bDouble && !bRefMode && nMouseStatus == SC_GM_DBLDOWN && !pScMod->IsRefDialogOpen() )
2065 // data pilot table
2066 Point aPos = rMEvt.GetPosPixel();
2067 SCsCOL nPosX;
2068 SCsROW nPosY;
2069 SCTAB nTab = pViewData->GetTabNo();
2070 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
2071 ScDPObject* pDPObj = pDoc->GetDPAtCursor( nPosX, nPosY, nTab );
2072 if ( pDPObj && pDPObj->GetSaveData()->GetDrillDown() )
2074 ScAddress aCellPos( nPosX, nPosY, pViewData->GetTabNo() );
2076 // Check for header drill-down first.
2077 sheet::DataPilotTableHeaderData aData;
2078 pDPObj->GetHeaderPositionData(aCellPos, aData);
2080 if ( ( aData.Flags & sheet::MemberResultFlags::HASMEMBER ) &&
2081 ! ( aData.Flags & sheet::MemberResultFlags::SUBTOTAL ) )
2083 USHORT nDummy;
2084 if ( pView->HasSelectionForDrillDown( nDummy ) )
2086 // execute slot to show dialog
2087 pViewData->GetDispatcher().Execute( SID_OUTLINE_SHOW, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD );
2089 else
2091 // toggle single entry
2092 ScDPObject aNewObj( *pDPObj );
2093 pDPObj->ToggleDetails( aData, &aNewObj );
2094 ScDBDocFunc aFunc( *pViewData->GetDocShell() );
2095 aFunc.DataPilotUpdate( pDPObj, &aNewObj, TRUE, FALSE );
2096 pViewData->GetView()->CursorPosChanged(); // shells may be switched
2099 else
2101 // Check if the data area is double-clicked.
2103 Sequence<sheet::DataPilotFieldFilter> aFilters;
2104 if ( pDPObj->GetDataFieldPositionData(aCellPos, aFilters) )
2105 pViewData->GetView()->ShowDataPilotSourceData( *pDPObj, aFilters );
2106 else
2107 Sound::Beep(); // nothing to expand/collapse/show
2110 return;
2113 // Check for cell protection attribute.
2114 ScTableProtection* pProtect = pDoc->GetTabProtection( nTab );
2115 bool bEditAllowed = true;
2116 if ( pProtect && pProtect->isProtected() )
2118 bool bCellProtected = pDoc->HasAttrib(nPosX, nPosY, nTab, nPosX, nPosY, nTab, HASATTR_PROTECTED);
2119 bool bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
2120 bool bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
2122 if ( bSkipProtected && bSkipUnprotected )
2123 bEditAllowed = false;
2124 else if ( (bCellProtected && bSkipProtected) || (!bCellProtected && bSkipUnprotected) )
2125 bEditAllowed = false;
2128 if ( bEditAllowed )
2130 // edit cell contents
2131 pViewData->GetViewShell()->UpdateInputHandler();
2132 pScMod->SetInputMode( SC_INPUT_TABLE );
2133 if (pViewData->HasEditView(eWhich))
2135 // Text-Cursor gleich an die geklickte Stelle setzen
2136 EditView* pEditView = pViewData->GetEditView( eWhich );
2137 MouseEvent aEditEvt( rMEvt.GetPosPixel(), 1, MOUSE_SYNTHETIC, MOUSE_LEFT, 0 );
2138 pEditView->MouseButtonDown( aEditEvt );
2139 pEditView->MouseButtonUp( aEditEvt );
2142 return;
2146 // Links in edit cells
2149 BOOL bAlt = rMEvt.IsMod2();
2150 if ( !bAlt && !bRefMode && !bDouble && nMouseStatus == SC_GM_URLDOWN )
2152 // beim ButtonUp nur ausfuehren, wenn ButtonDown auch ueber einer URL war
2154 String aName, aUrl, aTarget;
2155 if ( GetEditUrl( rMEvt.GetPosPixel(), &aName, &aUrl, &aTarget ) )
2157 nMouseStatus = SC_GM_NONE; // keinen Doppelklick anfangen
2158 ScGlobal::OpenURL( aUrl, aTarget );
2160 // fire worksheet_followhyperlink event
2161 Point aPos = rMEvt.GetPosPixel();
2162 SCsCOL nPosX;
2163 SCsROW nPosY;
2164 SCTAB nTab = pViewData->GetTabNo();
2165 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
2166 ScBaseCell* pCell = NULL;
2168 BOOL bFound = lcl_GetHyperlinkCell( pDoc, nPosX, nPosY, nTab, pCell );
2169 if( bFound )
2171 ScAddress aCellPos( nPosX, nPosY, nTab );
2172 ScCellObj* pObj = new ScCellObj( pViewData->GetDocShell(), aCellPos );
2173 uno::Sequence< uno::Any > aArgs(1);
2174 aArgs[0] = uno::makeAny(uno::Reference<uno::XInterface>(static_cast<cppu::OWeakObject*>(pObj)));
2175 uno::Reference< document::XVbaEventsHelper > xVbaEventsHelper ( pViewData->GetDocument()->GetVbaEventsHelper(), uno::UNO_QUERY );
2176 if( xVbaEventsHelper.is() )
2177 xVbaEventsHelper->ProcessCompatibleVbaEvent( VBAEVENT_WORKSHEET_FOLLOWHYPERLINK, aArgs );
2179 return;
2184 // Gridwin - SelectionEngine
2187 // SelMouseButtonDown is called only for left button, but SelMouseButtonUp would return
2188 // TRUE for any call, so IsLeft must be checked here, too.
2190 if ( rMEvt.IsLeft() && pViewData->GetView()->GetSelEngine()->SelMouseButtonUp( rMEvt ) )
2192 // rMark.MarkToSimple();
2193 pViewData->GetView()->UpdateAutoFillMark();
2195 SfxDispatcher* pDisp = pViewData->GetViewShell()->GetDispatcher();
2196 BOOL bFormulaMode = pScMod->IsFormulaMode();
2197 DBG_ASSERT( pDisp || bFormulaMode, "Cursor auf nicht aktiver View bewegen ?" );
2199 // #i14927# execute SID_CURRENTCELL (for macro recording) only if there is no
2200 // multiple selection, so the argument string completely describes the selection,
2201 // and executing the slot won't change the existing selection (executing the slot
2202 // here and from a recorded macro is treated equally)
2204 if ( pDisp && !bFormulaMode && !rMark.IsMultiMarked() )
2206 String aAddr; // CurrentCell
2207 if( rMark.IsMarked() )
2209 // BOOL bKeep = rMark.IsMultiMarked(); //! wohin damit ???
2211 ScRange aScRange;
2212 rMark.GetMarkArea( aScRange );
2213 aScRange.Format( aAddr, SCR_ABS );
2214 if ( aScRange.aStart == aScRange.aEnd )
2216 // make sure there is a range selection string even for a single cell
2217 String aSingle = aAddr;
2218 aAddr.Append( (sal_Char) ':' );
2219 aAddr.Append( aSingle );
2222 //! SID_MARKAREA gibts nicht mehr ???
2223 //! was passiert beim Markieren mit dem Cursor ???
2225 else // nur Cursor bewegen
2227 ScAddress aScAddress( pViewData->GetCurX(), pViewData->GetCurY(), 0 );
2228 aScAddress.Format( aAddr, SCA_ABS );
2231 SfxStringItem aPosItem( SID_CURRENTCELL, aAddr );
2232 // We don't want to align to the cursor position because if the
2233 // cell cursor isn't visible after making selection, it would jump
2234 // back to the origin of the selection where the cell cursor is.
2235 SfxBoolItem aAlignCursorItem( FN_PARAM_2, false );
2236 pDisp->Execute( SID_CURRENTCELL, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD,
2237 &aPosItem, &aAlignCursorItem, (void*)0L );
2239 pViewData->GetView()->InvalidateAttribs();
2241 return;
2245 void ScGridWindow::FakeButtonUp()
2247 if ( nButtonDown )
2249 MouseEvent aEvent( aCurMousePos ); // nButtons = 0 -> ignore
2250 MouseButtonUp( aEvent );
2254 void __EXPORT ScGridWindow::MouseMove( const MouseEvent& rMEvt )
2256 aCurMousePos = rMEvt.GetPosPixel();
2258 if ( rMEvt.IsLeaveWindow() && pNoteMarker && !pNoteMarker->IsByKeyboard() )
2259 HideNoteMarker();
2261 ScModule* pScMod = SC_MOD();
2262 if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
2263 return;
2265 // Ob aus dem Edit-Modus Drag&Drop gestartet wurde, bekommt man leider
2266 // nicht anders mit:
2268 if (bEEMouse && nButtonDown && !rMEvt.GetButtons())
2270 bEEMouse = FALSE;
2271 nButtonDown = 0;
2272 nMouseStatus = SC_GM_NONE;
2273 return;
2276 if (nMouseStatus == SC_GM_IGNORE)
2277 return;
2279 if (nMouseStatus == SC_GM_WATERUNDO) // Undo im Giesskannenmodus -> nur auf Up warten
2280 return;
2282 if ( pViewData->GetViewShell()->IsAuditShell() ) // Detektiv-Fuell-Modus
2284 SetPointer( Pointer( POINTER_FILL ) );
2285 return;
2288 if (nMouseStatus == SC_GM_FILTER && pFilterBox)
2290 Point aRelPos = pFilterBox->ScreenToOutputPixel( OutputToScreenPixel( rMEvt.GetPosPixel() ) );
2291 if ( Rectangle(Point(),pFilterBox->GetOutputSizePixel()).IsInside(aRelPos) )
2293 nButtonDown = 0;
2294 nMouseStatus = SC_GM_NONE;
2295 if ( pFilterBox->GetMode() == SC_FILTERBOX_FILTER )
2297 if (mpFilterButton.get())
2299 mpFilterButton->setHasHiddenMember(false);
2300 mpFilterButton->setPopupPressed(false);
2301 HideCursor();
2302 mpFilterButton->draw();
2303 ShowCursor();
2306 ReleaseMouse();
2307 pFilterBox->MouseButtonDown( MouseEvent( aRelPos, 1, MOUSE_SIMPLECLICK, MOUSE_LEFT ) );
2308 return;
2312 BOOL bFormulaMode = pScMod->IsFormulaMode(); // naechster Klick -> Referenz
2314 if (bEEMouse && pViewData->HasEditView( eWhich ))
2316 EditView* pEditView;
2317 SCCOL nEditCol;
2318 SCROW nEditRow;
2319 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
2320 pEditView->MouseMove( rMEvt );
2321 return;
2324 if (bDPMouse)
2326 DPMouseMove( rMEvt );
2327 return;
2330 if (bRFMouse)
2332 RFMouseMove( rMEvt, FALSE );
2333 return;
2336 if (nPagebreakMouse)
2338 PagebreakMove( rMEvt, FALSE );
2339 return;
2342 // anderen Mauszeiger anzeigen?
2344 BOOL bEditMode = pViewData->HasEditView(eWhich);
2346 //! Testen ob RefMode-Dragging !!!
2347 if ( bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()) )
2349 Point aPos = rMEvt.GetPosPixel();
2350 SCsCOL nPosX;
2351 SCsROW nPosY;
2352 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
2354 EditView* pEditView;
2355 SCCOL nEditCol;
2356 SCROW nEditRow;
2357 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
2358 SCCOL nEndCol = pViewData->GetEditEndCol();
2359 SCROW nEndRow = pViewData->GetEditEndRow();
2361 if ( nPosX >= (SCsCOL) nEditCol && nPosX <= (SCsCOL) nEndCol &&
2362 nPosY >= (SCsROW) nEditRow && nPosY <= (SCsROW) nEndRow )
2364 // Field can only be URL field
2365 BOOL bAlt = rMEvt.IsMod2();
2366 if ( !bAlt && !nButtonDown && pEditView && pEditView->GetFieldUnderMousePointer() )
2367 SetPointer( Pointer( POINTER_REFHAND ) );
2368 else if ( pEditView && pEditView->GetEditEngine()->IsVertical() )
2369 SetPointer( Pointer( POINTER_TEXT_VERTICAL ) );
2370 else
2371 SetPointer( Pointer( POINTER_TEXT ) );
2372 return;
2376 BOOL bWater = SC_MOD()->GetIsWaterCan() || pViewData->GetView()->HasPaintBrush();
2377 if (bWater)
2378 SetPointer( Pointer(POINTER_FILL) );
2380 if (!bWater)
2382 BOOL bCross = FALSE;
2384 // Range-Finder
2386 BOOL bCorner;
2387 if ( HitRangeFinder( rMEvt.GetPosPixel(), bCorner ) )
2389 if (bCorner)
2390 SetPointer( Pointer( POINTER_CROSS ) );
2391 else
2392 SetPointer( Pointer( POINTER_HAND ) );
2393 bCross = TRUE;
2396 // Page-Break-Modus
2398 USHORT nBreakType;
2399 if ( !nButtonDown && pViewData->IsPagebreakMode() &&
2400 ( nBreakType = HitPageBreak( rMEvt.GetPosPixel() ) ) != 0 )
2402 PointerStyle eNew = POINTER_ARROW;
2403 switch ( nBreakType )
2405 case SC_PD_RANGE_L:
2406 case SC_PD_RANGE_R:
2407 case SC_PD_BREAK_H:
2408 eNew = POINTER_ESIZE;
2409 break;
2410 case SC_PD_RANGE_T:
2411 case SC_PD_RANGE_B:
2412 case SC_PD_BREAK_V:
2413 eNew = POINTER_SSIZE;
2414 break;
2415 case SC_PD_RANGE_TL:
2416 case SC_PD_RANGE_BR:
2417 eNew = POINTER_SESIZE;
2418 break;
2419 case SC_PD_RANGE_TR:
2420 case SC_PD_RANGE_BL:
2421 eNew = POINTER_NESIZE;
2422 break;
2424 SetPointer( Pointer( eNew ) );
2425 bCross = TRUE;
2428 // Fill-Cursor anzeigen ?
2430 if ( !bFormulaMode && !nButtonDown )
2431 if (TestMouse( rMEvt, FALSE ))
2432 bCross = TRUE;
2434 if ( nButtonDown && pViewData->IsAnyFillMode() )
2436 SetPointer( Pointer( POINTER_CROSS ) );
2437 bCross = TRUE;
2438 nScFillModeMouseModifier = rMEvt.GetModifier(); // ausgewertet bei AutoFill und Matrix
2441 if (!bCross)
2443 BOOL bAlt = rMEvt.IsMod2();
2445 if (bEditMode) // Edit-Mode muss zuerst kommen!
2446 SetPointer( Pointer( POINTER_ARROW ) );
2447 else if ( !bAlt && !nButtonDown &&
2448 GetEditUrl(rMEvt.GetPosPixel()) )
2449 SetPointer( Pointer( POINTER_REFHAND ) );
2450 else if ( DrawMouseMove(rMEvt) ) // setzt Pointer um
2451 return;
2455 if ( pViewData->GetView()->GetSelEngine()->SelMouseMove( rMEvt ) )
2456 return;
2459 void lcl_InitMouseEvent( ::com::sun::star::awt::MouseEvent& rEvent, const MouseEvent& rEvt )
2461 rEvent.Modifiers = 0;
2462 if ( rEvt.IsShift() )
2463 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::SHIFT;
2464 if ( rEvt.IsMod1() )
2465 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD1;
2466 if ( rEvt.IsMod2() )
2467 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD2;
2468 if ( rEvt.IsMod3() )
2469 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD3;
2471 rEvent.Buttons = 0;
2472 if ( rEvt.IsLeft() )
2473 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::LEFT;
2474 if ( rEvt.IsRight() )
2475 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::RIGHT;
2476 if ( rEvt.IsMiddle() )
2477 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::MIDDLE;
2479 rEvent.X = rEvt.GetPosPixel().X();
2480 rEvent.Y = rEvt.GetPosPixel().Y();
2481 rEvent.ClickCount = rEvt.GetClicks();
2482 rEvent.PopupTrigger = sal_False;
2485 long ScGridWindow::PreNotify( NotifyEvent& rNEvt )
2487 USHORT nType = rNEvt.GetType();
2488 if ( nType == EVENT_MOUSEBUTTONUP || nType == EVENT_MOUSEBUTTONDOWN )
2490 Window* pWindow = rNEvt.GetWindow();
2491 if (pWindow == this && pViewData)
2493 SfxViewFrame* pViewFrame = pViewData->GetViewShell()->GetViewFrame();
2494 if (pViewFrame)
2496 SfxFrame* pFrame = pViewFrame->GetFrame();
2497 if (pFrame)
2499 com::sun::star::uno::Reference<com::sun::star::frame::XController> xController = pFrame->GetController();
2500 if (xController.is())
2502 ScTabViewObj* pImp = ScTabViewObj::getImplementation( xController );
2503 if (pImp && pImp->IsMouseListening())
2505 ::com::sun::star::awt::MouseEvent aEvent;
2506 lcl_InitMouseEvent( aEvent, *rNEvt.GetMouseEvent() );
2507 if ( rNEvt.GetWindow() )
2508 aEvent.Source = rNEvt.GetWindow()->GetComponentInterface();
2509 if ( nType == EVENT_MOUSEBUTTONDOWN)
2510 pImp->MousePressed( aEvent );
2511 else
2512 pImp->MouseReleased( aEvent );
2520 return Window::PreNotify( rNEvt );
2523 void ScGridWindow::Tracking( const TrackingEvent& rTEvt )
2525 // Weil die SelectionEngine kein Tracking kennt, die Events nur auf
2526 // die verschiedenen MouseHandler verteilen...
2528 const MouseEvent& rMEvt = rTEvt.GetMouseEvent();
2530 if ( rTEvt.IsTrackingCanceled() ) // alles abbrechen...
2532 if (!pViewData->GetView()->IsInActivatePart())
2534 if (bDPMouse)
2535 bDPMouse = FALSE; // gezeichnet wird per bDragRect
2536 if (bDragRect)
2538 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
2539 bDragRect = FALSE;
2540 UpdateDragRectOverlay();
2542 if (bRFMouse)
2544 RFMouseMove( rMEvt, TRUE ); // richtig abbrechen geht dabei nicht...
2545 bRFMouse = FALSE;
2547 if (nPagebreakMouse)
2549 // if (bPagebreakDrawn)
2550 // DrawDragRect( aPagebreakDrag.aStart.Col(), aPagebreakDrag.aStart.Row(),
2551 // aPagebreakDrag.aEnd.Col(), aPagebreakDrag.aEnd.Row(), FALSE );
2552 bPagebreakDrawn = FALSE;
2553 UpdateDragRectOverlay();
2554 nPagebreakMouse = SC_PD_NONE;
2557 SetPointer( Pointer( POINTER_ARROW ) );
2558 StopMarking();
2559 MouseButtonUp( rMEvt ); // mit Status SC_GM_IGNORE aus StopMarking
2561 BOOL bRefMode = pViewData->IsRefMode();
2562 if (bRefMode)
2563 SC_MOD()->EndReference(); // #63148# Dialog nicht verkleinert lassen
2566 else if ( rTEvt.IsTrackingEnded() )
2568 // MouseButtonUp immer mit passenden Buttons (z.B. wegen Testtool, #63148#)
2569 // Schliesslich behauptet der Tracking-Event ja, dass normal beendet und nicht
2570 // abgebrochen wurde.
2572 MouseEvent aUpEvt( rMEvt.GetPosPixel(), rMEvt.GetClicks(),
2573 rMEvt.GetMode(), nButtonDown, rMEvt.GetModifier() );
2574 MouseButtonUp( aUpEvt );
2576 else
2577 MouseMove( rMEvt );
2580 void ScGridWindow::StartDrag( sal_Int8 /* nAction */, const Point& rPosPixel )
2582 if ( pFilterBox || nPagebreakMouse )
2583 return;
2585 HideNoteMarker();
2587 CommandEvent aDragEvent( rPosPixel, COMMAND_STARTDRAG, TRUE );
2589 if (bEEMouse && pViewData->HasEditView( eWhich ))
2591 EditView* pEditView;
2592 SCCOL nEditCol;
2593 SCROW nEditRow;
2594 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
2596 // #63263# don't remove the edit view while switching views
2597 ScModule* pScMod = SC_MOD();
2598 pScMod->SetInEditCommand( TRUE );
2600 pEditView->Command( aDragEvent );
2602 ScInputHandler* pHdl = pScMod->GetInputHdl();
2603 if (pHdl)
2604 pHdl->DataChanged();
2606 pScMod->SetInEditCommand( FALSE );
2607 if (!pViewData->IsActive()) // dropped to different view?
2609 ScInputHandler* pViewHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
2610 if ( pViewHdl && pViewData->HasEditView( eWhich ) )
2612 pViewHdl->CancelHandler();
2613 ShowCursor(); // missing from KillEditView
2617 else
2618 if ( !DrawCommand(aDragEvent) )
2619 pViewData->GetView()->GetSelEngine()->Command( aDragEvent );
2622 void lcl_SetTextCursorPos( ScViewData* pViewData, ScSplitPos eWhich, Window* pWin )
2624 SCCOL nCol = pViewData->GetCurX();
2625 SCROW nRow = pViewData->GetCurY();
2626 Rectangle aEditArea = pViewData->GetEditArea( eWhich, nCol, nRow, pWin, NULL, TRUE );
2627 aEditArea.Right() = aEditArea.Left();
2628 aEditArea = pWin->PixelToLogic( aEditArea );
2629 pWin->SetCursorRect( &aEditArea );
2632 void __EXPORT ScGridWindow::Command( const CommandEvent& rCEvt )
2634 // The command event is send to the window after a possible context
2635 // menu from an inplace client is closed. Now we have the chance to
2636 // deactivate the inplace client without any problem regarding parent
2637 // windows and code on the stack.
2638 // For more information, see #126086# and #128122#
2639 USHORT nCmd = rCEvt.GetCommand();
2640 ScTabViewShell* pTabViewSh = pViewData->GetViewShell();
2641 SfxInPlaceClient* pClient = pTabViewSh->GetIPClient();
2642 if ( pClient &&
2643 pClient->IsObjectInPlaceActive() &&
2644 nCmd == COMMAND_CONTEXTMENU )
2646 pTabViewSh->DeactivateOle();
2647 return;
2650 ScModule* pScMod = SC_MOD();
2651 DBG_ASSERT( nCmd != COMMAND_STARTDRAG, "ScGridWindow::Command called with COMMAND_STARTDRAG" );
2653 if ( nCmd == COMMAND_STARTEXTTEXTINPUT ||
2654 nCmd == COMMAND_ENDEXTTEXTINPUT ||
2655 nCmd == COMMAND_EXTTEXTINPUT ||
2656 nCmd == COMMAND_CURSORPOS )
2658 BOOL bEditView = pViewData->HasEditView( eWhich );
2659 if (!bEditView)
2661 // only if no cell editview is active, look at drawview
2662 SdrView* pSdrView = pViewData->GetView()->GetSdrView();
2663 if ( pSdrView )
2665 OutlinerView* pOlView = pSdrView->GetTextEditOutlinerView();
2666 if ( pOlView && pOlView->GetWindow() == this )
2668 pOlView->Command( rCEvt );
2669 return; // done
2674 if ( nCmd == COMMAND_CURSORPOS && !bEditView )
2676 // #88458# CURSORPOS may be called without following text input,
2677 // to set the input method window position
2678 // -> input mode must not be started,
2679 // manually calculate text insert position if not in input mode
2681 lcl_SetTextCursorPos( pViewData, eWhich, this );
2682 return;
2685 ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
2686 if ( pHdl )
2688 pHdl->InputCommand( rCEvt, TRUE );
2689 return; // done
2692 Window::Command( rCEvt );
2693 return;
2696 if ( nCmd == COMMAND_VOICE )
2698 // Der Handler wird nur gerufen, wenn ein Text-Cursor aktiv ist,
2699 // also muss es eine EditView oder ein editiertes Zeichenobjekt geben
2701 ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
2702 if ( pHdl && pViewData->HasEditView( eWhich ) )
2704 EditView* pEditView = pViewData->GetEditView( eWhich ); // ist dann nicht 0
2705 pHdl->DataChanging();
2706 pEditView->Command( rCEvt );
2707 pHdl->DataChanged();
2708 return; // erledigt
2710 SdrView* pSdrView = pViewData->GetView()->GetSdrView();
2711 if ( pSdrView )
2713 OutlinerView* pOlView = pSdrView->GetTextEditOutlinerView();
2714 if ( pOlView && pOlView->GetWindow() == this )
2716 pOlView->Command( rCEvt );
2717 return; // erledigt
2720 Window::Command(rCEvt); // sonst soll sich die Basisklasse drum kuemmern...
2721 return;
2724 if ( nCmd == COMMAND_PASTESELECTION )
2726 if ( bEEMouse )
2728 // EditEngine handles selection in MouseButtonUp - no action
2729 // needed in command handler
2731 else
2733 PasteSelection( rCEvt.GetMousePosPixel() );
2735 return;
2738 if ( nCmd == COMMAND_INPUTLANGUAGECHANGE )
2740 // #i55929# Font and font size state depends on input language if nothing is selected,
2741 // so the slots have to be invalidated when the input language is changed.
2743 SfxBindings& rBindings = pViewData->GetBindings();
2744 rBindings.Invalidate( SID_ATTR_CHAR_FONT );
2745 rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT );
2746 return;
2749 if ( nCmd == COMMAND_WHEEL || nCmd == COMMAND_STARTAUTOSCROLL || nCmd == COMMAND_AUTOSCROLL )
2751 BOOL bDone = pViewData->GetView()->ScrollCommand( rCEvt, eWhich );
2752 if (!bDone)
2753 Window::Command(rCEvt);
2754 return;
2756 // #i7560# FormulaMode check is below scrolling - scrolling is allowed during formula input
2757 BOOL bDisable = pScMod->IsFormulaMode() ||
2758 pScMod->IsModalMode(pViewData->GetSfxDocShell());
2759 if (bDisable)
2760 return;
2762 if ( nCmd == COMMAND_CONTEXTMENU && !SC_MOD()->GetIsWaterCan() )
2764 if (pViewData->IsAnyFillMode())
2766 pViewData->GetView()->StopRefMode();
2767 pViewData->ResetFillMode();
2769 ReleaseMouse();
2770 StopMarking();
2772 Point aPosPixel = rCEvt.GetMousePosPixel();
2773 Point aMenuPos = aPosPixel;
2774 BOOL bMouse = rCEvt.IsMouseEvent();
2776 if ( bMouse )
2778 SCsCOL nCellX = -1;
2779 SCsROW nCellY = -1;
2780 pViewData->GetPosFromPixel(aPosPixel.X(), aPosPixel.Y(), eWhich, nCellX, nCellY);
2781 ScDocument* pDoc = pViewData->GetDocument();
2782 SCTAB nTab = pViewData->GetTabNo();
2783 const ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
2784 bool bSelectAllowed = true;
2785 if ( pProtect && pProtect->isProtected() )
2787 // This sheet is protected. Check if a context menu is allowed on this cell.
2788 bool bCellProtected = pDoc->HasAttrib(nCellX, nCellY, nTab, nCellX, nCellY, nTab, HASATTR_PROTECTED);
2789 bool bSelProtected = pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
2790 bool bSelUnprotected = pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
2792 if (bCellProtected)
2793 bSelectAllowed = bSelProtected;
2794 else
2795 bSelectAllowed = bSelUnprotected;
2797 if (!bSelectAllowed)
2798 // Selecting this cell is not allowed, neither is context menu.
2799 return;
2801 // #i18735# First select the item under the mouse pointer.
2802 // This can change the selection, and the view state (edit mode, etc).
2803 SelectForContextMenu( aPosPixel, nCellX, nCellY );
2806 BOOL bDone = FALSE;
2807 BOOL bEdit = pViewData->HasEditView(eWhich);
2808 if ( !bEdit )
2810 // Edit-Zelle mit Spelling-Errors ?
2811 if ( bMouse && GetEditUrlOrError( TRUE, aPosPixel ) )
2813 // GetEditUrlOrError hat den Cursor schon bewegt
2815 pScMod->SetInputMode( SC_INPUT_TABLE );
2816 bEdit = pViewData->HasEditView(eWhich); // hat's geklappt ?
2818 DBG_ASSERT( bEdit, "kann nicht in Edit-Modus schalten" );
2821 if ( bEdit )
2823 EditView* pEditView = pViewData->GetEditView( eWhich ); // ist dann nicht 0
2825 if ( !bMouse )
2827 Cursor* pCur = pEditView->GetCursor();
2828 if ( pCur )
2830 Point aLogicPos = pCur->GetPos();
2831 // use the position right of the cursor (spell popup is opened if
2832 // the cursor is before the word, but not if behind it)
2833 aLogicPos.X() += pCur->GetWidth();
2834 aLogicPos.Y() += pCur->GetHeight() / 2; // center vertically
2835 aMenuPos = LogicToPixel( aLogicPos );
2839 // if edit mode was just started above, online spelling may be incomplete
2840 pEditView->GetEditEngine()->CompleteOnlineSpelling();
2842 // IsCursorAtWrongSpelledWord could be used for !bMouse
2843 // if there was a corresponding ExecuteSpellPopup call
2845 if( pEditView->IsWrongSpelledWordAtPos( aMenuPos ) )
2847 // Wenn man unter OS/2 neben das Popupmenue klickt, kommt MouseButtonDown
2848 // vor dem Ende des Menue-Execute, darum muss SetModified vorher kommen
2849 // (Bug #40968#)
2850 ScInputHandler* pHdl = pScMod->GetInputHdl();
2851 if (pHdl)
2852 pHdl->SetModified();
2854 Link aLink = LINK( this, ScGridWindow, PopupSpellingHdl );
2855 pEditView->ExecuteSpellPopup( aMenuPos, &aLink );
2857 bDone = TRUE;
2860 else if ( !bMouse )
2862 // non-edit menu by keyboard -> use lower right of cell cursor position
2864 SCCOL nCurX = pViewData->GetCurX();
2865 SCROW nCurY = pViewData->GetCurY();
2866 aMenuPos = pViewData->GetScrPos( nCurX, nCurY, eWhich, TRUE );
2867 long nSizeXPix;
2868 long nSizeYPix;
2869 pViewData->GetMergeSizePixel( nCurX, nCurY, nSizeXPix, nSizeYPix );
2870 aMenuPos.X() += nSizeXPix;
2871 aMenuPos.Y() += nSizeYPix;
2873 if (pViewData)
2875 ScTabViewShell* pViewSh = pViewData->GetViewShell();
2876 if (pViewSh)
2878 // Is a draw object selected?
2880 SdrView* pDrawView = pViewSh->GetSdrView();
2881 if (pDrawView && pDrawView->AreObjectsMarked())
2883 // #100442#; the conext menu should open in the middle of the selected objects
2884 Rectangle aSelectRect(LogicToPixel(pDrawView->GetAllMarkedBoundRect()));
2885 aMenuPos = aSelectRect.Center();
2891 if (!bDone)
2893 SfxDispatcher::ExecutePopup( 0, this, &aMenuPos );
2898 void ScGridWindow::SelectForContextMenu( const Point& rPosPixel, SCsCOL nCellX, SCsROW nCellY )
2900 // #i18735# if the click was outside of the current selection,
2901 // the cursor is moved or an object at the click position selected.
2902 // (see SwEditWin::SelectMenuPosition in Writer)
2904 ScTabView* pView = pViewData->GetView();
2905 ScDrawView* pDrawView = pView->GetScDrawView();
2907 // check cell edit mode
2909 if ( pViewData->HasEditView(eWhich) )
2911 ScModule* pScMod = SC_MOD();
2912 SCCOL nEditStartCol = pViewData->GetEditViewCol(); //! change to GetEditStartCol after calcrtl is integrated
2913 SCROW nEditStartRow = pViewData->GetEditViewRow();
2914 SCCOL nEditEndCol = pViewData->GetEditEndCol();
2915 SCROW nEditEndRow = pViewData->GetEditEndRow();
2917 if ( nCellX >= (SCsCOL) nEditStartCol && nCellX <= (SCsCOL) nEditEndCol &&
2918 nCellY >= (SCsROW) nEditStartRow && nCellY <= (SCsROW) nEditEndRow )
2920 // handle selection within the EditView
2922 EditView* pEditView = pViewData->GetEditView( eWhich ); // not NULL (HasEditView)
2923 EditEngine* pEditEngine = pEditView->GetEditEngine();
2924 Rectangle aOutputArea = pEditView->GetOutputArea();
2925 Rectangle aVisArea = pEditView->GetVisArea();
2927 Point aTextPos = PixelToLogic( rPosPixel );
2928 if ( pEditEngine->IsVertical() ) // have to manually transform position
2930 aTextPos -= aOutputArea.TopRight();
2931 long nTemp = -aTextPos.X();
2932 aTextPos.X() = aTextPos.Y();
2933 aTextPos.Y() = nTemp;
2935 else
2936 aTextPos -= aOutputArea.TopLeft();
2937 aTextPos += aVisArea.TopLeft(); // position in the edit document
2939 EPosition aDocPosition = pEditEngine->FindDocPosition(aTextPos);
2940 ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex);
2941 ESelection aSelection = pEditView->GetSelection();
2942 aSelection.Adjust(); // needed for IsLess/IsGreater
2943 if ( aCompare.IsLess(aSelection) || aCompare.IsGreater(aSelection) )
2945 // clicked outside the selected text - deselect and move text cursor
2946 MouseEvent aEvent( rPosPixel );
2947 pEditView->MouseButtonDown( aEvent );
2948 pEditView->MouseButtonUp( aEvent );
2949 pScMod->InputSelection( pEditView );
2952 return; // clicked within the edit view - keep edit mode
2954 else
2956 // outside of the edit view - end edit mode, regardless of cell selection, then continue
2957 pScMod->InputEnterHandler();
2961 // check draw text edit mode
2963 Point aLogicPos = PixelToLogic( rPosPixel ); // after cell edit mode is ended
2964 if ( pDrawView && pDrawView->GetTextEditObject() && pDrawView->GetTextEditOutlinerView() )
2966 OutlinerView* pOlView = pDrawView->GetTextEditOutlinerView();
2967 Rectangle aOutputArea = pOlView->GetOutputArea();
2968 if ( aOutputArea.IsInside( aLogicPos ) )
2970 // handle selection within the OutlinerView
2972 Outliner* pOutliner = pOlView->GetOutliner();
2973 const EditEngine& rEditEngine = pOutliner->GetEditEngine();
2974 Rectangle aVisArea = pOlView->GetVisArea();
2976 Point aTextPos = aLogicPos;
2977 if ( pOutliner->IsVertical() ) // have to manually transform position
2979 aTextPos -= aOutputArea.TopRight();
2980 long nTemp = -aTextPos.X();
2981 aTextPos.X() = aTextPos.Y();
2982 aTextPos.Y() = nTemp;
2984 else
2985 aTextPos -= aOutputArea.TopLeft();
2986 aTextPos += aVisArea.TopLeft(); // position in the edit document
2988 EPosition aDocPosition = rEditEngine.FindDocPosition(aTextPos);
2989 ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex);
2990 ESelection aSelection = pOlView->GetSelection();
2991 aSelection.Adjust(); // needed for IsLess/IsGreater
2992 if ( aCompare.IsLess(aSelection) || aCompare.IsGreater(aSelection) )
2994 // clicked outside the selected text - deselect and move text cursor
2995 // use DrawView to allow extra handling there (none currently)
2996 MouseEvent aEvent( rPosPixel );
2997 pDrawView->MouseButtonDown( aEvent, this );
2998 pDrawView->MouseButtonUp( aEvent, this );
3001 return; // clicked within the edit area - keep edit mode
3003 else
3005 // Outside of the edit area - end text edit mode, then continue.
3006 // DrawDeselectAll also ends text edit mode and updates the shells.
3007 // If the click was on the edited object, it will be selected again below.
3008 pView->DrawDeselectAll();
3012 // look for existing selection
3014 BOOL bHitSelected = FALSE;
3015 if ( pDrawView && pDrawView->IsMarkedObjHit( aLogicPos ) )
3017 // clicked on selected object -> don't change anything
3018 bHitSelected = TRUE;
3020 else if ( pViewData->GetMarkData().IsCellMarked(nCellX, nCellY) )
3022 // clicked on selected cell -> don't change anything
3023 bHitSelected = TRUE;
3026 // select drawing object or move cell cursor
3028 if ( !bHitSelected )
3030 BOOL bWasDraw = ( pDrawView && pDrawView->AreObjectsMarked() );
3031 BOOL bHitDraw = FALSE;
3032 if ( pDrawView )
3034 pDrawView->UnmarkAllObj();
3035 // Unlock the Internal Layer in order to activate the context menu.
3036 // re-lock in ScDrawView::MarkListHasChanged()
3037 lcl_UnLockComment( pDrawView, pDrawView->GetSdrPageView(), pDrawView->GetModel(), aLogicPos ,pViewData);
3038 bHitDraw = pDrawView->MarkObj( aLogicPos );
3039 // draw shell is activated in MarkListHasChanged
3041 if ( !bHitDraw )
3043 pView->Unmark();
3044 pView->SetCursor(nCellX, nCellY);
3045 if ( bWasDraw )
3046 pViewData->GetViewShell()->SetDrawShell( FALSE ); // switch shells
3051 static void ClearSingleSelection( ScViewData* pViewData )
3053 SCCOL nX;
3054 SCROW nY;
3055 ScTransferObj* pTransObj = ScTransferObj::GetOwnClipboard(
3056 pViewData->GetActiveWin() );
3057 if (!pTransObj)
3058 return;
3060 ScDocument* pClipDoc = pTransObj->GetDocument();
3061 pClipDoc->GetClipArea( nX, nY, TRUE );
3062 if (nX == 0 && nY == 0)
3064 ScTabView* pView = pViewData->GetView();
3065 pView->Unmark();
3069 void __EXPORT ScGridWindow::KeyInput(const KeyEvent& rKEvt)
3071 // #96965# Cursor control for ref input dialog
3072 const KeyCode& rKeyCode = rKEvt.GetKeyCode();
3073 if( SC_MOD()->IsRefDialogOpen() )
3075 if( !rKeyCode.GetModifier() && (rKeyCode.GetCode() == KEY_F2) )
3077 SC_MOD()->EndReference();
3078 return;
3080 else if( pViewData->GetViewShell()->MoveCursorKeyInput( rKEvt ) )
3082 ScRange aRef(
3083 pViewData->GetRefStartX(), pViewData->GetRefStartY(), pViewData->GetRefStartZ(),
3084 pViewData->GetRefEndX(), pViewData->GetRefEndY(), pViewData->GetRefEndZ() );
3085 SC_MOD()->SetReference( aRef, pViewData->GetDocument() );
3086 return;
3089 else if( rKeyCode.GetCode() == KEY_RETURN && pViewData->IsPasteMode() )
3091 ScTabViewShell* pTabViewShell = pViewData->GetViewShell();
3093 ScCellShell::PasteFromClipboard( pViewData, pTabViewShell, FALSE );
3094 ClearSingleSelection( pViewData );
3096 uno::Reference<datatransfer::clipboard::XClipboard> xSystemClipboard =
3097 TransferableHelper::GetSystemClipboard();
3098 if (xSystemClipboard.is())
3100 xSystemClipboard->setContents(
3101 uno::Reference<datatransfer::XTransferable>(),
3102 uno::Reference<datatransfer::clipboard::XClipboardOwner>());
3105 // hide the border around the copy source
3106 pViewData->SetPasteMode( SC_PASTE_NONE );
3107 UpdateCursorOverlay();
3108 return;
3110 // wenn semi-Modeless-SfxChildWindow-Dialog oben, keine KeyInputs:
3111 else if( !pViewData->IsAnyFillMode() )
3113 if (rKeyCode.GetCode() == KEY_ESCAPE)
3115 pViewData->SetPasteMode( SC_PASTE_NONE );
3116 UpdateCursorOverlay();
3118 // query for existing note marker before calling ViewShell's keyboard handling
3119 // which may remove the marker
3120 BOOL bHadKeyMarker = ( pNoteMarker && pNoteMarker->IsByKeyboard() );
3121 ScTabViewShell* pViewSh = pViewData->GetViewShell();
3123 if (pViewData->GetDocShell()->GetProgress())
3124 return;
3126 if (DrawKeyInput(rKEvt))
3127 return;
3129 if (!pViewData->GetView()->IsDrawSelMode() && !DrawHasMarkedObj()) // keine Eingaben im Zeichenmodus
3130 { //! DrawShell abfragen !!!
3131 if (pViewSh->TabKeyInput(rKEvt))
3132 return;
3134 else
3135 if (pViewSh->SfxViewShell::KeyInput(rKEvt)) // von SfxViewShell
3136 return;
3138 KeyCode aCode = rKEvt.GetKeyCode();
3139 if ( aCode.GetCode() == KEY_ESCAPE && aCode.GetModifier() == 0 )
3141 if ( bHadKeyMarker )
3142 HideNoteMarker();
3143 else
3144 pViewSh->Escape();
3145 return;
3147 if ( aCode.GetCode() == KEY_F1 && aCode.GetModifier() == KEY_MOD1 )
3149 // ctrl-F1 shows or hides the note or redlining info for the cursor position
3150 // (hard-coded because F1 can't be configured)
3152 if ( bHadKeyMarker )
3153 HideNoteMarker(); // hide when previously visible
3154 else
3155 ShowNoteMarker( pViewData->GetCurX(), pViewData->GetCurY(), TRUE );
3156 return;
3158 if (aCode.GetCode() == KEY_BRACKETLEFT && aCode.GetModifier() == KEY_MOD1)
3160 pViewSh->DetectiveMarkPred();
3161 return;
3163 if (aCode.GetCode() == KEY_BRACKETRIGHT && aCode.GetModifier() == KEY_MOD1)
3165 pViewSh->DetectiveMarkSucc();
3166 return;
3171 Window::KeyInput(rKEvt);
3174 void ScGridWindow::StopMarking()
3176 DrawEndAction(); // Markieren/Verschieben auf Drawing-Layer abbrechen
3178 if (nButtonDown)
3180 pViewData->GetMarkData().SetMarking(FALSE);
3181 nMouseStatus = SC_GM_IGNORE;
3185 void ScGridWindow::UpdateInputContext()
3187 BOOL bReadOnly = pViewData->GetDocShell()->IsReadOnly();
3188 ULONG nOptions = bReadOnly ? 0 : ( INPUTCONTEXT_TEXT | INPUTCONTEXT_EXTTEXTINPUT );
3190 // when font from InputContext is used,
3191 // it must be taken from the cursor position's cell attributes
3193 InputContext aContext;
3194 aContext.SetOptions( nOptions );
3195 SetInputContext( aContext );
3198 //--------------------------------------------------------
3200 // sensitiver Bereich (Pixel)
3201 #define SCROLL_SENSITIVE 20
3203 BOOL ScGridWindow::DropScroll( const Point& rMousePos )
3205 /* doch auch auf nicht aktiven Views...
3206 if ( !pViewData->IsActive() )
3207 return FALSE;
3209 SCsCOL nDx = 0;
3210 SCsROW nDy = 0;
3211 Size aSize = GetOutputSizePixel();
3213 if (aSize.Width() > SCROLL_SENSITIVE * 3)
3215 if ( rMousePos.X() < SCROLL_SENSITIVE && pViewData->GetPosX(WhichH(eWhich)) > 0 )
3216 nDx = -1;
3217 if ( rMousePos.X() >= aSize.Width() - SCROLL_SENSITIVE
3218 && pViewData->GetPosX(WhichH(eWhich)) < MAXCOL )
3219 nDx = 1;
3221 if (aSize.Height() > SCROLL_SENSITIVE * 3)
3223 if ( rMousePos.Y() < SCROLL_SENSITIVE && pViewData->GetPosY(WhichV(eWhich)) > 0 )
3224 nDy = -1;
3225 if ( rMousePos.Y() >= aSize.Height() - SCROLL_SENSITIVE
3226 && pViewData->GetPosY(WhichV(eWhich)) < MAXROW )
3227 nDy = 1;
3230 if ( nDx != 0 || nDy != 0 )
3232 // if (bDragRect)
3233 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3235 if ( nDx != 0 )
3236 pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) );
3237 if ( nDy != 0 )
3238 pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) );
3240 // if (bDragRect)
3241 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3244 return FALSE;
3247 BOOL lcl_TestScenarioRedliningDrop( ScDocument* pDoc, const ScRange& aDragRange)
3249 // Testet, ob bei eingeschalteten RedLining,
3250 // bei einem Drop ein Scenario betroffen ist.
3252 BOOL bReturn = FALSE;
3253 SCTAB nTab = aDragRange.aStart.Tab();
3254 SCTAB nTabCount = pDoc->GetTableCount();
3256 if(pDoc->GetChangeTrack()!=NULL)
3258 if( pDoc->IsScenario(nTab) && pDoc->HasScenarioRange(nTab, aDragRange))
3260 bReturn = TRUE;
3262 else
3264 for(SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
3266 if(pDoc->HasScenarioRange(i, aDragRange))
3268 bReturn = TRUE;
3269 break;
3274 return bReturn;
3277 ScRange lcl_MakeDropRange( SCCOL nPosX, SCROW nPosY, SCTAB nTab, const ScRange& rSource )
3279 SCCOL nCol1 = nPosX;
3280 SCCOL nCol2 = nCol1 + ( rSource.aEnd.Col() - rSource.aStart.Col() );
3281 if ( nCol2 > MAXCOL )
3283 nCol1 -= nCol2 - MAXCOL;
3284 nCol2 = MAXCOL;
3286 SCROW nRow1 = nPosY;
3287 SCROW nRow2 = nRow1 + ( rSource.aEnd.Row() - rSource.aStart.Row() );
3288 if ( nRow2 > MAXROW )
3290 nRow1 -= nRow2 - MAXROW;
3291 nRow2 = MAXROW;
3294 return ScRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab );
3297 //--------------------------------------------------------
3299 extern BOOL bPasteIsDrop; // viewfun4 -> move to header
3300 extern BOOL bPasteIsMove; // viewfun7 -> move to header
3302 //--------------------------------------------------------
3304 sal_Int8 ScGridWindow::AcceptPrivateDrop( const AcceptDropEvent& rEvt )
3306 if ( rEvt.mbLeaving )
3308 // if (bDragRect)
3309 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3310 bDragRect = FALSE;
3311 UpdateDragRectOverlay();
3312 return rEvt.mnAction;
3315 const ScDragData& rData = SC_MOD()->GetDragData();
3316 if ( rData.pCellTransfer )
3318 // Don't move source that would include filtered rows.
3319 if ((rEvt.mnAction & DND_ACTION_MOVE) && rData.pCellTransfer->HasFilteredRows())
3321 if (bDragRect)
3323 bDragRect = FALSE;
3324 UpdateDragRectOverlay();
3326 return DND_ACTION_NONE;
3329 Point aPos = rEvt.maPosPixel;
3331 ScDocument* pSourceDoc = rData.pCellTransfer->GetSourceDocument();
3332 ScDocument* pThisDoc = pViewData->GetDocument();
3333 if (pSourceDoc == pThisDoc)
3335 if ( pThisDoc->HasChartAtPoint(pViewData->GetTabNo(), PixelToLogic(aPos)) )
3337 if (bDragRect) // Rechteck loeschen
3339 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3340 bDragRect = FALSE;
3341 UpdateDragRectOverlay();
3344 //! highlight chart? (selection border?)
3346 sal_Int8 nRet = rEvt.mnAction;
3347 //! if ( rEvt.GetAction() == DROP_LINK )
3348 //! bOk = rEvt.SetAction( DROP_COPY ); // can't link onto chart
3349 return nRet;
3352 //! else
3353 //! if ( rEvt.GetAction() == DROP_MOVE )
3354 //! rEvt.SetAction( DROP_COPY ); // different doc: default=COPY
3357 if ( rData.pCellTransfer->GetDragSourceFlags() & SC_DROP_TABLE ) // whole sheet?
3359 BOOL bOk = pThisDoc->IsDocEditable();
3360 return bOk ? rEvt.mnAction : 0; // don't draw selection frame
3363 SCsCOL nPosX;
3364 SCsROW nPosY;
3365 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
3367 ScRange aSourceRange = rData.pCellTransfer->GetRange();
3368 SCCOL nSourceStartX = aSourceRange.aStart.Col();
3369 SCROW nSourceStartY = aSourceRange.aStart.Row();
3370 SCCOL nSourceEndX = aSourceRange.aEnd.Col();
3371 SCROW nSourceEndY = aSourceRange.aEnd.Row();
3372 SCCOL nSizeX = nSourceEndX - nSourceStartX + 1;
3373 SCROW nSizeY = nSourceEndY - nSourceStartY + 1;
3375 if ( rEvt.mnAction != DND_ACTION_MOVE )
3376 nSizeY = rData.pCellTransfer->GetNonFilteredRows(); // copy/link: no filtered rows
3378 SCsCOL nNewDragX = nPosX - rData.pCellTransfer->GetDragHandleX();
3379 if (nNewDragX<0) nNewDragX=0;
3380 if (nNewDragX+(nSizeX-1) > MAXCOL)
3381 nNewDragX = MAXCOL-(nSizeX-1);
3382 SCsROW nNewDragY = nPosY - rData.pCellTransfer->GetDragHandleY();
3383 if (nNewDragY<0) nNewDragY=0;
3384 if (nNewDragY+(nSizeY-1) > MAXROW)
3385 nNewDragY = MAXROW-(nSizeY-1);
3387 // don't break scenario ranges, don't drop on filtered
3388 SCTAB nTab = pViewData->GetTabNo();
3389 ScRange aDropRange = lcl_MakeDropRange( nNewDragX, nNewDragY, nTab, aSourceRange );
3390 if ( lcl_TestScenarioRedliningDrop( pThisDoc, aDropRange ) ||
3391 lcl_TestScenarioRedliningDrop( pSourceDoc, aSourceRange ) ||
3392 ScViewUtil::HasFiltered( aDropRange, pThisDoc) )
3394 if (bDragRect)
3396 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3397 bDragRect = FALSE;
3398 UpdateDragRectOverlay();
3400 return DND_ACTION_NONE;
3403 InsCellCmd eDragInsertMode = INS_NONE;
3404 Window::PointerState aState = GetPointerState();
3406 // check for datapilot item sorting
3407 ScDPObject* pDPObj = NULL;
3408 if ( pThisDoc == pSourceDoc && ( pDPObj = pThisDoc->GetDPAtCursor( nNewDragX, nNewDragY, nTab ) ) != NULL )
3410 // drop on DataPilot table: sort or nothing
3412 bool bDPSort = false;
3413 if ( pThisDoc->GetDPAtCursor( nSourceStartX, nSourceStartY, aSourceRange.aStart.Tab() ) == pDPObj )
3415 sheet::DataPilotTableHeaderData aDestData;
3416 pDPObj->GetHeaderPositionData( ScAddress(nNewDragX, nNewDragY, nTab), aDestData );
3417 bool bValid = ( aDestData.Dimension >= 0 ); // dropping onto a field
3419 // look through the source range
3420 for (SCROW nRow = aSourceRange.aStart.Row(); bValid && nRow <= aSourceRange.aEnd.Row(); ++nRow )
3421 for (SCCOL nCol = aSourceRange.aStart.Col(); bValid && nCol <= aSourceRange.aEnd.Col(); ++nCol )
3423 sheet::DataPilotTableHeaderData aSourceData;
3424 pDPObj->GetHeaderPositionData( ScAddress( nCol, nRow, aSourceRange.aStart.Tab() ), aSourceData );
3425 if ( aSourceData.Dimension != aDestData.Dimension || !aSourceData.MemberName.getLength() )
3426 bValid = false; // empty (subtotal) or different field
3429 if ( bValid )
3431 BOOL bIsDataLayout;
3432 String aDimName = pDPObj->GetDimName( aDestData.Dimension, bIsDataLayout );
3433 const ScDPSaveDimension* pDim = pDPObj->GetSaveData()->GetExistingDimensionByName( aDimName );
3434 if ( pDim )
3436 ScRange aOutRange = pDPObj->GetOutRange();
3438 USHORT nOrient = pDim->GetOrientation();
3439 if ( nOrient == sheet::DataPilotFieldOrientation_COLUMN )
3441 eDragInsertMode = INS_CELLSRIGHT;
3442 nSizeY = aOutRange.aEnd.Row() - nNewDragY + 1;
3443 bDPSort = true;
3445 else if ( nOrient == sheet::DataPilotFieldOrientation_ROW )
3447 eDragInsertMode = INS_CELLSDOWN;
3448 nSizeX = aOutRange.aEnd.Col() - nNewDragX + 1;
3449 bDPSort = true;
3455 if ( !bDPSort )
3457 // no valid sorting in a DataPilot table -> disallow
3458 if ( bDragRect )
3460 bDragRect = FALSE;
3461 UpdateDragRectOverlay();
3463 return DND_ACTION_NONE;
3466 else if ( aState.mnState & KEY_MOD2 )
3468 if ( pThisDoc == pSourceDoc && nTab == aSourceRange.aStart.Tab() )
3470 long nDeltaX = labs( static_cast< long >( nNewDragX - nSourceStartX ) );
3471 long nDeltaY = labs( static_cast< long >( nNewDragY - nSourceStartY ) );
3472 if ( nDeltaX <= nDeltaY )
3474 eDragInsertMode = INS_CELLSDOWN;
3476 else
3478 eDragInsertMode = INS_CELLSRIGHT;
3481 if ( ( eDragInsertMode == INS_CELLSDOWN && nNewDragY <= nSourceEndY &&
3482 ( nNewDragX + nSizeX - 1 ) >= nSourceStartX && nNewDragX <= nSourceEndX &&
3483 ( nNewDragX != nSourceStartX || nNewDragY >= nSourceStartY ) ) ||
3484 ( eDragInsertMode == INS_CELLSRIGHT && nNewDragX <= nSourceEndX &&
3485 ( nNewDragY + nSizeY - 1 ) >= nSourceStartY && nNewDragY <= nSourceEndY &&
3486 ( nNewDragY != nSourceStartY || nNewDragX >= nSourceStartX ) ) )
3488 if ( bDragRect )
3490 bDragRect = FALSE;
3491 UpdateDragRectOverlay();
3493 return DND_ACTION_NONE;
3496 else
3498 if ( static_cast< long >( nSizeX ) >= static_cast< long >( nSizeY ) )
3500 eDragInsertMode = INS_CELLSDOWN;
3503 else
3505 eDragInsertMode = INS_CELLSRIGHT;
3510 if ( nNewDragX != (SCsCOL) nDragStartX || nNewDragY != (SCsROW) nDragStartY ||
3511 nDragStartX+nSizeX-1 != nDragEndX || nDragStartY+nSizeY-1 != nDragEndY ||
3512 !bDragRect || eDragInsertMode != meDragInsertMode )
3514 // if (bDragRect)
3515 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3517 nDragStartX = nNewDragX;
3518 nDragStartY = nNewDragY;
3519 nDragEndX = nDragStartX+nSizeX-1;
3520 nDragEndY = nDragStartY+nSizeY-1;
3521 bDragRect = TRUE;
3522 meDragInsertMode = eDragInsertMode;
3524 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3526 UpdateDragRectOverlay();
3528 // show target position as tip help
3529 #if 0
3530 if (Help::IsQuickHelpEnabled())
3532 ScRange aRange( nDragStartX, nDragStartY, nTab, nDragEndX, nDragEndY, nTab );
3533 String aHelpStr;
3534 aRange.Format( aHelpStr, SCA_VALID ); // non-3D
3536 Point aPos = Pointer::GetPosPixel();
3537 USHORT nAlign = QUICKHELP_BOTTOM|QUICKHELP_RIGHT;
3538 Rectangle aRect( aPos, aPos );
3539 Help::ShowQuickHelp(aRect, aHelpStr, nAlign);
3541 #endif
3545 return rEvt.mnAction;
3548 sal_Int8 ScGridWindow::AcceptDrop( const AcceptDropEvent& rEvt )
3550 const ScDragData& rData = SC_MOD()->GetDragData();
3551 if ( rEvt.mbLeaving )
3553 DrawMarkDropObj( NULL );
3554 if ( rData.pCellTransfer )
3555 return AcceptPrivateDrop( rEvt ); // hide drop marker for internal D&D
3556 else
3557 return rEvt.mnAction;
3560 if ( pViewData->GetDocShell()->IsReadOnly() )
3561 return DND_ACTION_NONE;
3564 sal_Int8 nRet = DND_ACTION_NONE;
3566 if (rData.pCellTransfer)
3568 ScRange aSource = rData.pCellTransfer->GetRange();
3569 if ( aSource.aStart.Col() != 0 || aSource.aEnd.Col() != MAXCOL ||
3570 aSource.aStart.Row() != 0 || aSource.aEnd.Row() != MAXROW )
3571 DropScroll( rEvt.maPosPixel );
3573 nRet = AcceptPrivateDrop( rEvt );
3575 else
3577 if ( rData.aLinkDoc.Len() )
3579 String aThisName;
3580 ScDocShell* pDocSh = pViewData->GetDocShell();
3581 if (pDocSh && pDocSh->HasName())
3582 aThisName = pDocSh->GetMedium()->GetName();
3584 if ( rData.aLinkDoc != aThisName )
3585 nRet = rEvt.mnAction;
3587 else if (rData.aJumpTarget.Len())
3589 // internal bookmarks (from Navigator)
3590 // local jumps from an unnamed document are possible only within a document
3592 if ( !rData.pJumpLocalDoc || rData.pJumpLocalDoc == pViewData->GetDocument() )
3593 nRet = rEvt.mnAction;
3595 else
3597 sal_Int8 nMyAction = rEvt.mnAction;
3599 if ( !rData.pDrawTransfer ||
3600 !IsMyModel(rData.pDrawTransfer->GetDragSourceView()) ) // drawing within the document
3601 if ( rEvt.mbDefault && nMyAction == DND_ACTION_MOVE )
3602 nMyAction = DND_ACTION_COPY;
3604 ScDocument* pThisDoc = pViewData->GetDocument();
3605 SdrObject* pHitObj = pThisDoc->GetObjectAtPoint(
3606 pViewData->GetTabNo(), PixelToLogic(rEvt.maPosPixel) );
3607 if ( pHitObj && nMyAction == DND_ACTION_LINK && !rData.pDrawTransfer )
3609 if ( IsDropFormatSupported(SOT_FORMATSTR_ID_SVXB)
3610 || IsDropFormatSupported(SOT_FORMAT_GDIMETAFILE)
3611 || IsDropFormatSupported(SOT_FORMAT_BITMAP) )
3613 // graphic dragged onto drawing object
3614 DrawMarkDropObj( pHitObj );
3615 nRet = nMyAction;
3618 if (!nRet)
3619 DrawMarkDropObj( NULL );
3621 if (!nRet)
3623 switch ( nMyAction )
3625 case DND_ACTION_COPY:
3626 case DND_ACTION_MOVE:
3627 case DND_ACTION_COPYMOVE:
3629 BOOL bMove = ( nMyAction == DND_ACTION_MOVE );
3630 if ( IsDropFormatSupported( SOT_FORMATSTR_ID_EMBED_SOURCE ) ||
3631 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE ) ||
3632 IsDropFormatSupported( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) ||
3633 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ||
3634 IsDropFormatSupported( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) ||
3635 IsDropFormatSupported( SOT_FORMAT_STRING ) ||
3636 IsDropFormatSupported( SOT_FORMATSTR_ID_SYLK ) ||
3637 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK ) ||
3638 IsDropFormatSupported( SOT_FORMATSTR_ID_HTML ) ||
3639 IsDropFormatSupported( SOT_FORMATSTR_ID_HTML_SIMPLE ) ||
3640 IsDropFormatSupported( SOT_FORMATSTR_ID_DIF ) ||
3641 IsDropFormatSupported( SOT_FORMATSTR_ID_DRAWING ) ||
3642 IsDropFormatSupported( SOT_FORMATSTR_ID_SVXB ) ||
3643 IsDropFormatSupported( SOT_FORMAT_RTF ) ||
3644 IsDropFormatSupported( SOT_FORMAT_GDIMETAFILE ) ||
3645 IsDropFormatSupported( SOT_FORMAT_BITMAP ) ||
3646 IsDropFormatSupported( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) ||
3647 IsDropFormatSupported( SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE ) ||
3648 ( !bMove && (
3649 IsDropFormatSupported( SOT_FORMAT_FILE_LIST ) ||
3650 IsDropFormatSupported( SOT_FORMAT_FILE ) ||
3651 IsDropFormatSupported( SOT_FORMATSTR_ID_SOLK ) ||
3652 IsDropFormatSupported( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) ||
3653 IsDropFormatSupported( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) ||
3654 IsDropFormatSupported( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) ) ) )
3656 nRet = nMyAction;
3659 break;
3660 case DND_ACTION_LINK:
3661 if ( IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE ) ||
3662 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ||
3663 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK ) ||
3664 IsDropFormatSupported( SOT_FORMAT_FILE_LIST ) ||
3665 IsDropFormatSupported( SOT_FORMAT_FILE ) ||
3666 IsDropFormatSupported( SOT_FORMATSTR_ID_SOLK ) ||
3667 IsDropFormatSupported( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) ||
3668 IsDropFormatSupported( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) ||
3669 IsDropFormatSupported( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
3671 nRet = nMyAction;
3673 break;
3676 if ( nRet )
3678 // Simple check for protection: It's not known here if the drop will result
3679 // in cells or drawing objects (some formats can be both) and how many cells
3680 // the result will be. But if IsFormatEditable for the drop cell position
3681 // is FALSE (ignores matrix formulas), nothing can be pasted, so the drop
3682 // can already be rejected here.
3684 Point aPos = rEvt.maPosPixel;
3685 SCsCOL nPosX;
3686 SCsROW nPosY;
3687 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
3688 SCTAB nTab = pViewData->GetTabNo();
3689 ScDocument* pDoc = pViewData->GetDocument();
3691 ScEditableTester aTester( pDoc, nTab, nPosX,nPosY, nPosX,nPosY );
3692 if ( !aTester.IsFormatEditable() )
3693 nRet = DND_ACTION_NONE; // forbidden
3698 // scroll only for accepted formats
3699 if (nRet)
3700 DropScroll( rEvt.maPosPixel );
3703 return nRet;
3706 ULONG lcl_GetDropFormatId( const uno::Reference<datatransfer::XTransferable>& xTransfer, bool bPreferText = false )
3708 TransferableDataHelper aDataHelper( xTransfer );
3710 if ( !aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) )
3712 // use bookmark formats if no sba is present
3714 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SOLK ) )
3715 return SOT_FORMATSTR_ID_SOLK;
3716 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) )
3717 return SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR;
3718 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) )
3719 return SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK;
3720 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
3721 return SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR;
3724 ULONG nFormatId = 0;
3725 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING ) )
3726 nFormatId = SOT_FORMATSTR_ID_DRAWING;
3727 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ) )
3728 nFormatId = SOT_FORMATSTR_ID_SVXB;
3729 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ) )
3731 // If it's a Writer object, insert RTF instead of OLE
3733 BOOL bDoRtf = FALSE;
3734 SotStorageStreamRef xStm;
3735 TransferableObjectDescriptor aObjDesc;
3736 if( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) &&
3737 aDataHelper.GetSotStorageStream( SOT_FORMATSTR_ID_EMBED_SOURCE, xStm ) )
3739 SotStorageRef xStore( new SotStorage( *xStm ) );
3740 bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) ||
3741 aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) )
3742 && aDataHelper.HasFormat( SOT_FORMAT_RTF ) );
3744 if ( bDoRtf )
3745 nFormatId = FORMAT_RTF;
3746 else
3747 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE;
3749 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) )
3750 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE;
3751 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) )
3752 nFormatId = SOT_FORMATSTR_ID_SBA_DATAEXCHANGE;
3753 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE ) )
3754 nFormatId = SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE;
3755 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_BIFF_8 ) )
3756 nFormatId = SOT_FORMATSTR_ID_BIFF_8;
3757 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_BIFF_5 ) )
3758 nFormatId = SOT_FORMATSTR_ID_BIFF_5;
3759 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) )
3760 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE_OLE;
3761 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) )
3762 nFormatId = SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE;
3763 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) )
3764 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE;
3765 else if ( aDataHelper.HasFormat( SOT_FORMAT_RTF ) )
3766 nFormatId = SOT_FORMAT_RTF;
3767 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_HTML ) )
3768 nFormatId = SOT_FORMATSTR_ID_HTML;
3769 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_HTML_SIMPLE ) )
3770 nFormatId = SOT_FORMATSTR_ID_HTML_SIMPLE;
3771 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SYLK ) )
3772 nFormatId = SOT_FORMATSTR_ID_SYLK;
3773 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK ) )
3774 nFormatId = SOT_FORMATSTR_ID_LINK;
3775 else if ( bPreferText && aDataHelper.HasFormat( SOT_FORMAT_STRING ) ) // #i86734# the behaviour introduced in #i62773# is wrong when pasting
3776 nFormatId = SOT_FORMAT_STRING;
3777 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) )
3778 nFormatId = SOT_FORMAT_FILE_LIST;
3779 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE ) ) // #i62773# FILE_LIST/FILE before STRING (Unix file managers)
3780 nFormatId = SOT_FORMAT_FILE;
3781 else if ( aDataHelper.HasFormat( SOT_FORMAT_STRING ) )
3782 nFormatId = SOT_FORMAT_STRING;
3783 else if ( aDataHelper.HasFormat( SOT_FORMAT_GDIMETAFILE ) )
3784 nFormatId = SOT_FORMAT_GDIMETAFILE;
3785 else if ( aDataHelper.HasFormat( SOT_FORMAT_BITMAP ) )
3786 nFormatId = SOT_FORMAT_BITMAP;
3788 return nFormatId;
3791 ULONG lcl_GetDropLinkId( const uno::Reference<datatransfer::XTransferable>& xTransfer )
3793 TransferableDataHelper aDataHelper( xTransfer );
3795 ULONG nFormatId = 0;
3796 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) )
3797 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE;
3798 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) )
3799 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE;
3800 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK ) )
3801 nFormatId = SOT_FORMATSTR_ID_LINK;
3802 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) )
3803 nFormatId = SOT_FORMAT_FILE_LIST;
3804 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE ) )
3805 nFormatId = SOT_FORMAT_FILE;
3806 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SOLK ) )
3807 nFormatId = SOT_FORMATSTR_ID_SOLK;
3808 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) )
3809 nFormatId = SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR;
3810 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) )
3811 nFormatId = SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK;
3812 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
3813 nFormatId = SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR;
3815 return nFormatId;
3819 sal_Int8 ScGridWindow::ExecutePrivateDrop( const ExecuteDropEvent& rEvt )
3821 // hide drop marker
3822 // if (bDragRect)
3823 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
3824 bDragRect = FALSE;
3825 UpdateDragRectOverlay();
3827 ScModule* pScMod = SC_MOD();
3828 const ScDragData& rData = pScMod->GetDragData();
3830 return DropTransferObj( rData.pCellTransfer, nDragStartX, nDragStartY,
3831 PixelToLogic(rEvt.maPosPixel), rEvt.mnAction );
3834 sal_Int8 ScGridWindow::DropTransferObj( ScTransferObj* pTransObj, SCCOL nDestPosX, SCROW nDestPosY,
3835 const Point& rLogicPos, sal_Int8 nDndAction )
3837 if ( !pTransObj )
3838 return 0;
3840 ScDocument* pSourceDoc = pTransObj->GetSourceDocument();
3841 ScDocShell* pDocSh = pViewData->GetDocShell();
3842 ScDocument* pThisDoc = pViewData->GetDocument();
3843 ScViewFunc* pView = pViewData->GetView();
3844 SCTAB nThisTab = pViewData->GetTabNo();
3845 USHORT nFlags = pTransObj->GetDragSourceFlags();
3847 BOOL bIsNavi = ( nFlags & SC_DROP_NAVIGATOR ) != 0;
3848 BOOL bIsMove = ( nDndAction == DND_ACTION_MOVE && !bIsNavi );
3850 // workaround for wrong nDndAction on Windows when pressing solely
3851 // the Alt key during drag and drop;
3852 // can be removed after #i79215# has been fixed
3853 if ( meDragInsertMode != INS_NONE )
3855 bIsMove = ( nDndAction & DND_ACTION_MOVE && !bIsNavi );
3858 BOOL bIsLink = ( nDndAction == DND_ACTION_LINK );
3860 ScRange aSource = pTransObj->GetRange();
3862 // only use visible tab from source range - when dragging within one table,
3863 // all selected tables at the time of dropping are used (handled in MoveBlockTo)
3864 SCTAB nSourceTab = pTransObj->GetVisibleTab();
3865 aSource.aStart.SetTab( nSourceTab );
3866 aSource.aEnd.SetTab( nSourceTab );
3868 SCCOL nSizeX = aSource.aEnd.Col() - aSource.aStart.Col() + 1;
3869 SCROW nSizeY = (bIsMove ? (aSource.aEnd.Row() - aSource.aStart.Row() + 1) :
3870 pTransObj->GetNonFilteredRows()); // copy/link: no filtered rows
3871 ScRange aDest( nDestPosX, nDestPosY, nThisTab,
3872 nDestPosX + nSizeX - 1, nDestPosY + nSizeY - 1, nThisTab );
3875 /* NOTE: AcceptPrivateDrop() already checked for filtered conditions during
3876 * dragging and adapted drawing of the selection frame. We check here
3877 * (again) because this may actually also be called from PasteSelection(),
3878 * we would have to duplicate determination of flags and destination range
3879 * and would lose the context of the "filtered destination is OK" cases
3880 * below, which is already awkward enough as is. */
3882 // Don't move filtered source.
3883 bool bFiltered = (bIsMove && pTransObj->HasFilteredRows());
3884 if (!bFiltered)
3886 if (pSourceDoc != pThisDoc && ((nFlags & SC_DROP_TABLE) ||
3887 (!bIsLink && meDragInsertMode == INS_NONE)))
3889 // Nothing. Either entire sheet to be dropped, or the one case
3890 // where PasteFromClip() is to be called that handles a filtered
3891 // destination itself. Drag-copy from another document without
3892 // inserting cells.
3894 else
3895 // Don't copy or move to filtered destination.
3896 bFiltered = ScViewUtil::HasFiltered( aDest, pThisDoc);
3899 BOOL bDone = FALSE;
3901 if (!bFiltered && pSourceDoc == pThisDoc)
3903 if ( nFlags & SC_DROP_TABLE ) // whole sheet?
3905 if ( pThisDoc->IsDocEditable() )
3907 SCTAB nSrcTab = aSource.aStart.Tab();
3908 pViewData->GetDocShell()->MoveTable( nSrcTab, nThisTab, !bIsMove, TRUE ); // with Undo
3909 pView->SetTabNo( nThisTab, TRUE );
3910 bDone = TRUE;
3913 else // move/copy block
3915 String aChartName;
3916 if (pThisDoc->HasChartAtPoint( nThisTab, rLogicPos, &aChartName ))
3918 String aRangeName;
3919 aSource.Format( aRangeName, SCR_ABS_3D, pThisDoc );
3920 SfxStringItem aNameItem( SID_CHART_NAME, aChartName );
3921 SfxStringItem aRangeItem( SID_CHART_SOURCE, aRangeName );
3922 USHORT nId = bIsMove ? SID_CHART_SOURCE : SID_CHART_ADDSOURCE;
3923 pViewData->GetDispatcher().Execute( nId, SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD,
3924 &aRangeItem, &aNameItem, (void*) NULL );
3925 bDone = TRUE;
3927 else if ( pThisDoc->GetDPAtCursor( nDestPosX, nDestPosY, nThisTab ) )
3929 // drop on DataPilot table: try to sort, fail if that isn't possible
3931 ScAddress aDestPos( nDestPosX, nDestPosY, nThisTab );
3932 if ( aDestPos != aSource.aStart )
3933 bDone = pViewData->GetView()->DataPilotMove( aSource, aDestPos );
3934 else
3935 bDone = TRUE; // same position: nothing
3937 else if ( nDestPosX != aSource.aStart.Col() || nDestPosY != aSource.aStart.Row() ||
3938 nSourceTab != nThisTab )
3940 String aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY );
3941 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
3943 bDone = TRUE;
3944 if ( meDragInsertMode != INS_NONE )
3946 // call with bApi = TRUE to avoid error messages in drop handler
3947 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, TRUE /*bRecord*/, TRUE /*bApi*/, TRUE /*bPartOfPaste*/ );
3948 if ( bDone )
3950 if ( nThisTab == nSourceTab )
3952 if ( meDragInsertMode == INS_CELLSDOWN &&
3953 nDestPosX == aSource.aStart.Col() && nDestPosY < aSource.aStart.Row() )
3955 bDone = aSource.Move( 0, nSizeY, 0, pSourceDoc );
3957 else if ( meDragInsertMode == INS_CELLSRIGHT &&
3958 nDestPosY == aSource.aStart.Row() && nDestPosX < aSource.aStart.Col() )
3960 bDone = aSource.Move( nSizeX, 0, 0, pSourceDoc );
3963 pDocSh->UpdateOle( pViewData );
3964 pView->CellContentChanged();
3968 if ( bDone )
3970 if ( bIsLink )
3972 // call with bApi = TRUE to avoid error messages in drop handler
3973 bDone = pView->LinkBlock( aSource, aDest.aStart, TRUE /*bApi*/ );
3975 else
3977 // call with bApi = TRUE to avoid error messages in drop handler
3978 bDone = pView->MoveBlockTo( aSource, aDest.aStart, bIsMove, TRUE /*bRecord*/, TRUE /*bPaint*/, TRUE /*bApi*/ );
3982 if ( bDone && meDragInsertMode != INS_NONE && bIsMove && nThisTab == nSourceTab )
3984 DelCellCmd eCmd = DEL_NONE;
3985 if ( meDragInsertMode == INS_CELLSDOWN )
3987 eCmd = DEL_CELLSUP;
3989 else if ( meDragInsertMode == INS_CELLSRIGHT )
3991 eCmd = DEL_CELLSLEFT;
3994 if ( ( eCmd == DEL_CELLSUP && nDestPosX == aSource.aStart.Col() ) ||
3995 ( eCmd == DEL_CELLSLEFT && nDestPosY == aSource.aStart.Row() ) )
3997 // call with bApi = TRUE to avoid error messages in drop handler
3998 bDone = pDocSh->GetDocFunc().DeleteCells( aSource, NULL, eCmd, TRUE /*bRecord*/, TRUE /*bApi*/ );
3999 if ( bDone )
4001 if ( eCmd == DEL_CELLSUP && nDestPosY > aSource.aEnd.Row() )
4003 bDone = aDest.Move( 0, -nSizeY, 0, pThisDoc );
4005 else if ( eCmd == DEL_CELLSLEFT && nDestPosX > aSource.aEnd.Col() )
4007 bDone = aDest.Move( -nSizeX, 0, 0, pThisDoc );
4009 pDocSh->UpdateOle( pViewData );
4010 pView->CellContentChanged();
4015 if ( bDone )
4017 pView->MarkRange( aDest, FALSE, FALSE );
4019 SCCOL nDCol = pViewData->GetCurX() - aSource.aStart.Col();
4020 SCROW nDRow = pViewData->GetCurY() - aSource.aStart.Row();
4021 pView->SetCursor( aDest.aStart.Col() + nDCol, aDest.aStart.Row() + nDRow );
4024 pDocSh->GetUndoManager()->LeaveListAction();
4026 if (!bDone)
4027 Sound::Beep(); // instead of error message in drop handler
4029 else
4030 bDone = TRUE; // nothing to do
4033 if (bDone)
4034 pTransObj->SetDragWasInternal(); // don't delete source in DragFinished
4036 else if ( !bFiltered && pSourceDoc ) // between documents
4038 if ( nFlags & SC_DROP_TABLE ) // copy/link sheets between documents
4040 if ( pThisDoc->IsDocEditable() )
4042 ScDocShell* pSrcShell = pTransObj->GetSourceDocShell();
4044 SCTAB nTabs[MAXTABCOUNT];
4046 ScMarkData aMark = pTransObj->GetSourceMarkData();
4047 SCTAB nTabCount = pSourceDoc->GetTableCount();
4048 SCTAB nTabSelCount = 0;
4050 for(SCTAB i=0; i<nTabCount; i++)
4052 if(aMark.GetTableSelect(i))
4054 nTabs[nTabSelCount++]=i;
4055 for(SCTAB j=i+1;j<nTabCount;j++)
4057 if((!pSourceDoc->IsVisible(j))&&(pSourceDoc->IsScenario(j)))
4059 nTabs[nTabSelCount++]=j;
4060 i=j;
4062 else break;
4067 pView->ImportTables( pSrcShell,nTabSelCount, nTabs, bIsLink, nThisTab );
4068 bDone = TRUE;
4071 else if ( bIsLink )
4073 // as in PasteDDE
4074 // (external references might be used instead?)
4076 SfxObjectShell* pSourceSh = pSourceDoc->GetDocumentShell();
4077 DBG_ASSERT(pSourceSh, "drag document has no shell");
4078 if (pSourceSh)
4080 String aUndo = ScGlobal::GetRscString( STR_UNDO_COPY );
4081 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
4083 bDone = TRUE;
4084 if ( meDragInsertMode != INS_NONE )
4086 // call with bApi = TRUE to avoid error messages in drop handler
4087 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, TRUE /*bRecord*/, TRUE /*bApi*/, TRUE /*bPartOfPaste*/ );
4088 if ( bDone )
4090 pDocSh->UpdateOle( pViewData );
4091 pView->CellContentChanged();
4095 if ( bDone )
4097 String aApp = Application::GetAppName();
4098 String aTopic = pSourceSh->GetTitle( SFX_TITLE_FULLNAME );
4099 String aItem;
4100 aSource.Format( aItem, SCA_VALID | SCA_TAB_3D, pSourceDoc );
4102 // TODO: we could define ocQuote for "
4103 const String aQuote( '"' );
4104 const String& sSep = ScCompiler::GetNativeSymbol( ocSep);
4105 String aFormula( '=' );
4106 aFormula += ScCompiler::GetNativeSymbol( ocDde);
4107 aFormula += ScCompiler::GetNativeSymbol( ocOpen);
4108 aFormula += aQuote;
4109 aFormula += aApp;
4110 aFormula += aQuote;
4111 aFormula += sSep;
4112 aFormula += aQuote;
4113 aFormula += aTopic;
4114 aFormula += aQuote;
4115 aFormula += sSep;
4116 aFormula += aQuote;
4117 aFormula += aItem;
4118 aFormula += aQuote;
4119 aFormula += ScCompiler::GetNativeSymbol( ocClose);
4121 pView->DoneBlockMode();
4122 pView->InitBlockMode( nDestPosX, nDestPosY, nThisTab );
4123 pView->MarkCursor( nDestPosX + nSizeX - 1,
4124 nDestPosY + nSizeY - 1, nThisTab );
4126 pView->EnterMatrix( aFormula );
4128 pView->MarkRange( aDest, FALSE, FALSE );
4129 pView->SetCursor( aDest.aStart.Col(), aDest.aStart.Row() );
4132 pDocSh->GetUndoManager()->LeaveListAction();
4135 else
4137 //! HasSelectedBlockMatrixFragment without selected sheet?
4138 //! or don't start dragging on a part of a matrix
4140 String aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY );
4141 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
4143 bDone = TRUE;
4144 if ( meDragInsertMode != INS_NONE )
4146 // call with bApi = TRUE to avoid error messages in drop handler
4147 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, TRUE /*bRecord*/, TRUE /*bApi*/, TRUE /*bPartOfPaste*/ );
4148 if ( bDone )
4150 pDocSh->UpdateOle( pViewData );
4151 pView->CellContentChanged();
4155 if ( bDone )
4157 pView->Unmark(); // before SetCursor, so CheckSelectionTransfer isn't called with a selection
4158 pView->SetCursor( nDestPosX, nDestPosY );
4159 bDone = pView->PasteFromClip( IDF_ALL, pTransObj->GetDocument() ); // clip-doc
4160 if ( bDone )
4162 pView->MarkRange( aDest, FALSE, FALSE );
4163 pView->SetCursor( aDest.aStart.Col(), aDest.aStart.Row() );
4167 pDocSh->GetUndoManager()->LeaveListAction();
4169 // no longer call ResetMark here - the inserted block has been selected
4170 // and may have been copied to primary selection
4174 sal_Int8 nRet = bDone ? nDndAction : DND_ACTION_NONE;
4175 return nRet;
4178 sal_Int8 ScGridWindow::ExecuteDrop( const ExecuteDropEvent& rEvt )
4180 DrawMarkDropObj( NULL ); // drawing layer
4182 ScModule* pScMod = SC_MOD();
4183 const ScDragData& rData = pScMod->GetDragData();
4184 if (rData.pCellTransfer)
4185 return ExecutePrivateDrop( rEvt );
4187 Point aPos = rEvt.maPosPixel;
4189 if ( rData.aLinkDoc.Len() )
4191 // try to insert a link
4193 BOOL bOk = TRUE;
4194 String aThisName;
4195 ScDocShell* pDocSh = pViewData->GetDocShell();
4196 if (pDocSh && pDocSh->HasName())
4197 aThisName = pDocSh->GetMedium()->GetName();
4199 if ( rData.aLinkDoc == aThisName ) // error - no link within a document
4200 bOk = FALSE;
4201 else
4203 ScViewFunc* pView = pViewData->GetView();
4204 if ( rData.aLinkTable.Len() )
4205 pView->InsertTableLink( rData.aLinkDoc, EMPTY_STRING, EMPTY_STRING,
4206 rData.aLinkTable );
4207 else if ( rData.aLinkArea.Len() )
4209 SCsCOL nPosX;
4210 SCsROW nPosY;
4211 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
4212 pView->MoveCursorAbs( nPosX, nPosY, SC_FOLLOW_NONE, FALSE, FALSE );
4214 pView->InsertAreaLink( rData.aLinkDoc, EMPTY_STRING, EMPTY_STRING,
4215 rData.aLinkArea, 0 );
4217 else
4219 DBG_ERROR("drop with link: no sheet nor area");
4220 bOk = FALSE;
4224 return bOk ? rEvt.mnAction : DND_ACTION_NONE; // don't try anything else
4227 Point aLogicPos = PixelToLogic(aPos);
4229 if (rData.pDrawTransfer)
4231 USHORT nFlags = rData.pDrawTransfer->GetDragSourceFlags();
4233 BOOL bIsNavi = ( nFlags & SC_DROP_NAVIGATOR ) != 0;
4234 BOOL bIsMove = ( rEvt.mnAction == DND_ACTION_MOVE && !bIsNavi );
4236 bPasteIsMove = bIsMove;
4238 pViewData->GetView()->PasteDraw( aLogicPos, rData.pDrawTransfer->GetModel() );
4240 if (bPasteIsMove)
4241 rData.pDrawTransfer->SetDragWasInternal();
4242 bPasteIsMove = FALSE;
4244 return rEvt.mnAction;
4248 SCsCOL nPosX;
4249 SCsROW nPosY;
4250 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
4252 if (rData.aJumpTarget.Len())
4254 // internal bookmark (from Navigator)
4255 // bookmark clipboard formats are in PasteScDataObject
4257 if ( !rData.pJumpLocalDoc || rData.pJumpLocalDoc == pViewData->GetDocument() )
4259 pViewData->GetViewShell()->InsertBookmark( rData.aJumpText, rData.aJumpTarget,
4260 nPosX, nPosY );
4261 return rEvt.mnAction;
4265 BOOL bIsLink = ( rEvt.mnAction == DND_ACTION_LINK );
4267 ScDocument* pThisDoc = pViewData->GetDocument();
4268 SdrObject* pHitObj = pThisDoc->GetObjectAtPoint( pViewData->GetTabNo(), PixelToLogic(aPos) );
4269 if ( pHitObj && bIsLink )
4271 // dropped on drawing object
4272 // PasteOnDrawObject checks for valid formats
4273 if ( pViewData->GetView()->PasteOnDrawObject( rEvt.maDropEvent.Transferable, pHitObj, TRUE ) )
4274 return rEvt.mnAction;
4277 BOOL bDone = FALSE;
4279 ULONG nFormatId = bIsLink ?
4280 lcl_GetDropLinkId( rEvt.maDropEvent.Transferable ) :
4281 lcl_GetDropFormatId( rEvt.maDropEvent.Transferable );
4282 if ( nFormatId )
4284 pScMod->SetInExecuteDrop( TRUE ); // #i28468# prevent error messages from PasteDataFormat
4285 bPasteIsDrop = TRUE;
4286 bDone = pViewData->GetView()->PasteDataFormat(
4287 nFormatId, rEvt.maDropEvent.Transferable, nPosX, nPosY, &aLogicPos, bIsLink );
4288 bPasteIsDrop = FALSE;
4289 pScMod->SetInExecuteDrop( FALSE );
4292 sal_Int8 nRet = bDone ? rEvt.mnAction : DND_ACTION_NONE;
4293 return nRet;
4296 //--------------------------------------------------------
4298 void ScGridWindow::PasteSelection( const Point& rPosPixel )
4300 Point aLogicPos = PixelToLogic( rPosPixel );
4302 SCsCOL nPosX;
4303 SCsROW nPosY;
4304 pViewData->GetPosFromPixel( rPosPixel.X(), rPosPixel.Y(), eWhich, nPosX, nPosY );
4306 ScSelectionTransferObj* pOwnSelection = SC_MOD()->GetSelectionTransfer();
4307 if ( pOwnSelection )
4309 // within Calc
4311 ScTransferObj* pCellTransfer = pOwnSelection->GetCellData();
4312 if ( pCellTransfer )
4314 // keep a reference to the data in case the selection is changed during paste
4315 uno::Reference<datatransfer::XTransferable> xRef( pCellTransfer );
4316 DropTransferObj( pCellTransfer, nPosX, nPosY, aLogicPos, DND_ACTION_COPY );
4318 else
4320 ScDrawTransferObj* pDrawTransfer = pOwnSelection->GetDrawData();
4321 if ( pDrawTransfer )
4323 // keep a reference to the data in case the selection is changed during paste
4324 uno::Reference<datatransfer::XTransferable> xRef( pDrawTransfer );
4326 // #96821# bSameDocClipboard argument for PasteDraw is needed
4327 // because only DragData is checked directly inside PasteDraw
4328 pViewData->GetView()->PasteDraw( aLogicPos, pDrawTransfer->GetModel(), FALSE,
4329 pDrawTransfer->GetSourceDocID() == pViewData->GetDocument()->GetDocumentID() );
4333 else
4335 // get selection from system
4337 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSelection( this ) );
4338 uno::Reference<datatransfer::XTransferable> xTransferable = aDataHelper.GetTransferable();
4339 if ( xTransferable.is() )
4341 ULONG nFormatId = lcl_GetDropFormatId( xTransferable, true );
4342 if ( nFormatId )
4344 bPasteIsDrop = TRUE;
4345 pViewData->GetView()->PasteDataFormat( nFormatId, xTransferable, nPosX, nPosY, &aLogicPos );
4346 bPasteIsDrop = FALSE;
4352 //--------------------------------------------------------
4354 void ScGridWindow::UpdateEditViewPos()
4356 if (pViewData->HasEditView(eWhich))
4358 EditView* pView;
4359 SCCOL nCol;
4360 SCROW nRow;
4361 pViewData->GetEditView( eWhich, pView, nCol, nRow );
4362 SCCOL nEndCol = pViewData->GetEditEndCol();
4363 SCROW nEndRow = pViewData->GetEditEndRow();
4365 // hide EditView?
4367 BOOL bHide = ( nEndCol<pViewData->GetPosX(eHWhich) || nEndRow<pViewData->GetPosY(eVWhich) );
4368 if ( SC_MOD()->IsFormulaMode() )
4369 if ( pViewData->GetTabNo() != pViewData->GetRefTabNo() )
4370 bHide = TRUE;
4372 if (bHide)
4374 Rectangle aRect = pView->GetOutputArea();
4375 long nHeight = aRect.Bottom() - aRect.Top();
4376 aRect.Top() = PixelToLogic(GetOutputSizePixel(), pViewData->GetLogicMode()).
4377 Height() * 2;
4378 aRect.Bottom() = aRect.Top() + nHeight;
4379 pView->SetOutputArea( aRect );
4380 pView->HideCursor();
4382 else
4384 // bForceToTop = TRUE for editing
4385 Rectangle aPixRect = pViewData->GetEditArea( eWhich, nCol, nRow, this, NULL, TRUE );
4386 Point aScrPos = PixelToLogic( aPixRect.TopLeft(), pViewData->GetLogicMode() );
4388 Rectangle aRect = pView->GetOutputArea();
4389 aRect.SetPos( aScrPos );
4390 pView->SetOutputArea( aRect );
4391 pView->ShowCursor();
4396 void ScGridWindow::ScrollPixel( long nDifX, long nDifY )
4398 ClickExtern();
4399 HideNoteMarker();
4401 bIsInScroll = TRUE;
4402 //BOOL bXor=DrawBeforeScroll();
4404 SetMapMode(MAP_PIXEL);
4405 Scroll( nDifX, nDifY, SCROLL_CHILDREN );
4406 SetMapMode( GetDrawMapMode() ); // verschobenen MapMode erzeugen
4408 UpdateEditViewPos();
4410 DrawAfterScroll(); //bXor);
4411 bIsInScroll = FALSE;
4414 // Formeln neu zeichnen -------------------------------------------------
4416 void ScGridWindow::UpdateFormulas()
4418 if (pViewData->GetView()->IsMinimized())
4419 return;
4421 if ( nPaintCount )
4423 // nicht anfangen, verschachtelt zu painten
4424 // (dann wuerde zumindest der MapMode nicht mehr stimmen)
4426 bNeedsRepaint = TRUE; // -> am Ende vom Paint nochmal Invalidate auf alles
4427 aRepaintPixel = Rectangle(); // alles
4428 return;
4431 SCCOL nX1 = pViewData->GetPosX( eHWhich );
4432 SCROW nY1 = pViewData->GetPosY( eVWhich );
4433 SCCOL nX2 = nX1 + pViewData->VisibleCellsX( eHWhich );
4434 SCROW nY2 = nY1 + pViewData->VisibleCellsY( eVWhich );
4436 if (nX2 > MAXCOL) nX2 = MAXCOL;
4437 if (nY2 > MAXROW) nY2 = MAXROW;
4439 // Draw( nX1, nY1, nX2, nY2, SC_UPDATE_CHANGED );
4441 // don't draw directly - instead use OutputData to find changed area and invalidate
4443 SCROW nPosY = nY1;
4445 ScDocShell* pDocSh = pViewData->GetDocShell();
4446 ScDocument* pDoc = pDocSh->GetDocument();
4447 SCTAB nTab = pViewData->GetTabNo();
4449 pDoc->ExtendHidden( nX1, nY1, nX2, nY2, nTab );
4451 Point aScrPos = pViewData->GetScrPos( nX1, nY1, eWhich );
4452 long nMirrorWidth = GetSizePixel().Width();
4453 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
4454 // unused variable long nLayoutSign = bLayoutRTL ? -1 : 1;
4455 if ( bLayoutRTL )
4457 long nEndPixel = pViewData->GetScrPos( nX2+1, nPosY, eWhich ).X();
4458 nMirrorWidth = aScrPos.X() - nEndPixel;
4459 aScrPos.X() = nEndPixel + 1;
4462 long nScrX = aScrPos.X();
4463 long nScrY = aScrPos.Y();
4465 double nPPTX = pViewData->GetPPTX();
4466 double nPPTY = pViewData->GetPPTY();
4468 ScTableInfo aTabInfo;
4469 pDoc->FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nTab, nPPTX, nPPTY, FALSE, FALSE );
4471 Fraction aZoomX = pViewData->GetZoomX();
4472 Fraction aZoomY = pViewData->GetZoomY();
4473 ScOutputData aOutputData( this, OUTTYPE_WINDOW, aTabInfo, pDoc, nTab,
4474 nScrX, nScrY, nX1, nY1, nX2, nY2, nPPTX, nPPTY,
4475 &aZoomX, &aZoomY );
4476 aOutputData.SetMirrorWidth( nMirrorWidth );
4478 aOutputData.FindChanged();
4480 PolyPolygon aChangedPoly( aOutputData.GetChangedArea() ); // logic (PixelToLogic)
4481 if ( aChangedPoly.Count() )
4483 Invalidate( aChangedPoly );
4486 CheckNeedsRepaint(); // #i90362# used to be called via Draw() - still needed here
4489 void ScGridWindow::UpdateAutoFillMark(BOOL bMarked, const ScRange& rMarkRange)
4491 if ( bMarked != bAutoMarkVisible || ( bMarked && rMarkRange.aEnd != aAutoMarkPos ) )
4493 HideCursor();
4494 bAutoMarkVisible = bMarked;
4495 if ( bMarked )
4496 aAutoMarkPos = rMarkRange.aEnd;
4497 ShowCursor();
4499 UpdateAutoFillOverlay();
4503 void ScGridWindow::UpdateListValPos( BOOL bVisible, const ScAddress& rPos )
4505 BOOL bOldButton = bListValButton;
4506 ScAddress aOldPos = aListValPos;
4508 bListValButton = bVisible;
4509 aListValPos = rPos;
4511 if ( bListValButton )
4513 if ( !bOldButton || aListValPos != aOldPos )
4515 // paint area of new button
4516 Invalidate( PixelToLogic( GetListValButtonRect( aListValPos ) ) );
4519 if ( bOldButton )
4521 if ( !bListValButton || aListValPos != aOldPos )
4523 // paint area of old button
4524 Invalidate( PixelToLogic( GetListValButtonRect( aOldPos ) ) );
4529 void ScGridWindow::HideCursor()
4531 ++nCursorHideCount;
4532 if (nCursorHideCount==1)
4534 DrawCursor();
4535 DrawAutoFillMark();
4539 void ScGridWindow::ShowCursor()
4541 if (nCursorHideCount==0)
4543 DBG_ERROR("zuviel ShowCursor");
4544 return;
4547 if (nCursorHideCount==1)
4549 // #i57745# Draw the cursor before setting the variable, in case the
4550 // GetSizePixel call from drawing causes a repaint (resize handler is called)
4551 DrawAutoFillMark();
4552 DrawCursor();
4555 --nCursorHideCount;
4558 void __EXPORT ScGridWindow::GetFocus()
4560 ScTabViewShell* pViewShell = pViewData->GetViewShell();
4561 pViewShell->GotFocus();
4562 pViewShell->SetFormShellAtTop( FALSE ); // focus in GridWindow -> FormShell no longer on top
4564 if (pViewShell->HasAccessibilityObjects())
4565 pViewShell->BroadcastAccessibility(ScAccGridWinFocusGotHint(eWhich, GetAccessible()));
4568 if ( !SC_MOD()->IsFormulaMode() )
4570 pViewShell->UpdateInputHandler();
4571 // StopMarking(); // falls Dialog (Fehler), weil dann kein ButtonUp
4572 // MO: nur wenn nicht im RefInput-Modus
4573 // -> GetFocus/MouseButtonDown-Reihenfolge
4574 // auf dem Mac
4577 Window::GetFocus();
4580 void __EXPORT ScGridWindow::LoseFocus()
4582 ScTabViewShell* pViewShell = pViewData->GetViewShell();
4583 pViewShell->LostFocus();
4585 if (pViewShell->HasAccessibilityObjects())
4586 pViewShell->BroadcastAccessibility(ScAccGridWinFocusLostHint(eWhich, GetAccessible()));
4588 Window::LoseFocus();
4591 Point ScGridWindow::GetMousePosPixel() const { return aCurMousePos; }
4593 //------------------------------------------------------------------------
4595 BOOL ScGridWindow::HitRangeFinder( const Point& rMouse, BOOL& rCorner,
4596 USHORT* pIndex, SCsCOL* pAddX, SCsROW* pAddY )
4598 BOOL bFound = FALSE;
4599 ScInputHandler* pHdl = SC_MOD()->GetInputHdl( pViewData->GetViewShell() );
4600 if (pHdl)
4602 ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList();
4603 if ( pRangeFinder && !pRangeFinder->IsHidden() &&
4604 pRangeFinder->GetDocName() == pViewData->GetDocShell()->GetTitle() )
4606 ScDocument* pDoc = pViewData->GetDocument();
4607 SCTAB nTab = pViewData->GetTabNo();
4608 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
4609 long nLayoutSign = bLayoutRTL ? -1 : 1;
4611 SCsCOL nPosX;
4612 SCsROW nPosY;
4613 pViewData->GetPosFromPixel( rMouse.X(), rMouse.Y(), eWhich, nPosX, nPosY );
4614 // zusammengefasste (einzeln/Bereich) ???
4615 ScAddress aAddr( nPosX, nPosY, nTab );
4617 // Point aNext = pViewData->GetScrPos( nPosX+1, nPosY+1, eWhich );
4619 Point aNext = pViewData->GetScrPos( nPosX, nPosY, eWhich, TRUE );
4620 long nSizeXPix;
4621 long nSizeYPix;
4622 pViewData->GetMergeSizePixel( nPosX, nPosY, nSizeXPix, nSizeYPix );
4623 aNext.X() += nSizeXPix * nLayoutSign;
4624 aNext.Y() += nSizeYPix;
4626 BOOL bCornerHor;
4627 if ( bLayoutRTL )
4628 bCornerHor = ( rMouse.X() >= aNext.X() && rMouse.X() <= aNext.X() + 8 );
4629 else
4630 bCornerHor = ( rMouse.X() >= aNext.X() - 8 && rMouse.X() <= aNext.X() );
4632 BOOL bCellCorner = ( bCornerHor &&
4633 rMouse.Y() >= aNext.Y() - 8 && rMouse.Y() <= aNext.Y() );
4634 // corner is hit only if the mouse is within the cell
4636 USHORT nCount = (USHORT)pRangeFinder->Count();
4637 for (USHORT i=nCount; i;)
4639 // rueckwaerts suchen, damit der zuletzt gepaintete Rahmen gefunden wird
4640 --i;
4641 ScRangeFindData* pData = pRangeFinder->GetObject(i);
4642 if ( pData && pData->aRef.In(aAddr) )
4644 if (pIndex) *pIndex = i;
4645 if (pAddX) *pAddX = nPosX - pData->aRef.aStart.Col();
4646 if (pAddY) *pAddY = nPosY - pData->aRef.aStart.Row();
4647 bFound = TRUE;
4648 rCorner = ( bCellCorner && aAddr == pData->aRef.aEnd );
4649 break;
4654 return bFound;
4657 #define SCE_TOP 1
4658 #define SCE_BOTTOM 2
4659 #define SCE_LEFT 4
4660 #define SCE_RIGHT 8
4661 #define SCE_ALL 15
4663 void lcl_PaintOneRange( ScDocShell* pDocSh, const ScRange& rRange, USHORT nEdges )
4665 // der Range ist immer richtigherum
4667 SCCOL nCol1 = rRange.aStart.Col();
4668 SCROW nRow1 = rRange.aStart.Row();
4669 SCTAB nTab1 = rRange.aStart.Tab();
4670 SCCOL nCol2 = rRange.aEnd.Col();
4671 SCROW nRow2 = rRange.aEnd.Row();
4672 SCTAB nTab2 = rRange.aEnd.Tab();
4673 BOOL bHiddenEdge = FALSE;
4674 SCROW nTmp;
4676 ScDocument* pDoc = pDocSh->GetDocument();
4677 while ( nCol1 > 0 && pDoc->ColHidden(nCol1, nTab1) )
4679 --nCol1;
4680 bHiddenEdge = TRUE;
4682 while ( nCol2 < MAXCOL && pDoc->ColHidden(nCol2, nTab1) )
4684 ++nCol2;
4685 bHiddenEdge = TRUE;
4687 nTmp = pDoc->FirstVisibleRow(0, nRow1, nTab1);
4688 if (!ValidRow(nTmp))
4689 nTmp = 0;
4690 if (nTmp < nRow1)
4692 nRow1 = nTmp;
4693 bHiddenEdge = TRUE;
4695 nTmp = pDoc->FirstVisibleRow(nRow2, MAXROW, nTab1);
4696 if (!ValidRow(nTmp))
4697 nTmp = MAXROW;
4698 if (nTmp > nRow2)
4700 nRow2 = nTmp;
4701 bHiddenEdge = TRUE;
4704 if ( nCol2 > nCol1 + 1 && nRow2 > nRow1 + 1 && !bHiddenEdge )
4706 // nur an den Raendern entlang
4707 // (die Ecken werden evtl. zweimal getroffen)
4709 if ( nEdges & SCE_TOP )
4710 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol2, nRow1, nTab2, PAINT_MARKS );
4711 if ( nEdges & SCE_LEFT )
4712 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol1, nRow2, nTab2, PAINT_MARKS );
4713 if ( nEdges & SCE_RIGHT )
4714 pDocSh->PostPaint( nCol2, nRow1, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
4715 if ( nEdges & SCE_BOTTOM )
4716 pDocSh->PostPaint( nCol1, nRow2, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
4718 else // everything in one call
4719 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
4722 void lcl_PaintRefChanged( ScDocShell* pDocSh, const ScRange& rOldUn, const ScRange& rNewUn )
4724 // Repaint fuer die Teile des Rahmens in Old, die bei New nicht mehr da sind
4726 ScRange aOld = rOldUn;
4727 ScRange aNew = rNewUn;
4728 aOld.Justify();
4729 aNew.Justify();
4731 if ( aOld.aStart == aOld.aEnd ) //! Tab ignorieren?
4732 pDocSh->GetDocument()->ExtendMerge(aOld);
4733 if ( aNew.aStart == aNew.aEnd ) //! Tab ignorieren?
4734 pDocSh->GetDocument()->ExtendMerge(aNew);
4736 SCCOL nOldCol1 = aOld.aStart.Col();
4737 SCROW nOldRow1 = aOld.aStart.Row();
4738 SCCOL nOldCol2 = aOld.aEnd.Col();
4739 SCROW nOldRow2 = aOld.aEnd.Row();
4740 SCCOL nNewCol1 = aNew.aStart.Col();
4741 SCROW nNewRow1 = aNew.aStart.Row();
4742 SCCOL nNewCol2 = aNew.aEnd.Col();
4743 SCROW nNewRow2 = aNew.aEnd.Row();
4744 SCTAB nTab1 = aOld.aStart.Tab(); // Tab aendert sich nicht
4745 SCTAB nTab2 = aOld.aEnd.Tab();
4747 if ( nNewRow2 < nOldRow1 || nNewRow1 > nOldRow2 ||
4748 nNewCol2 < nOldCol1 || nNewCol1 > nOldCol2 ||
4749 ( nNewCol1 != nOldCol1 && nNewRow1 != nOldRow1 &&
4750 nNewCol2 != nOldCol2 && nNewRow2 != nOldRow2 ) )
4752 // komplett weggeschoben oder alle Seiten veraendert
4753 // (Abfrage <= statt < geht schief bei einzelnen Zeilen/Spalten)
4755 lcl_PaintOneRange( pDocSh, aOld, SCE_ALL );
4757 else // alle vier Kanten einzeln testen
4759 // oberer Teil
4760 if ( nNewRow1 < nOldRow1 ) // nur obere Linie loeschen
4761 lcl_PaintOneRange( pDocSh, ScRange(
4762 nOldCol1, nOldRow1, nTab1, nOldCol2, nOldRow1, nTab2 ), SCE_ALL );
4763 else if ( nNewRow1 > nOldRow1 ) // den Teil, der oben wegkommt
4764 lcl_PaintOneRange( pDocSh, ScRange(
4765 nOldCol1, nOldRow1, nTab1, nOldCol2, nNewRow1-1, nTab2 ),
4766 SCE_ALL &~ SCE_BOTTOM );
4768 // unterer Teil
4769 if ( nNewRow2 > nOldRow2 ) // nur untere Linie loeschen
4770 lcl_PaintOneRange( pDocSh, ScRange(
4771 nOldCol1, nOldRow2, nTab1, nOldCol2, nOldRow2, nTab2 ), SCE_ALL );
4772 else if ( nNewRow2 < nOldRow2 ) // den Teil, der unten wegkommt
4773 lcl_PaintOneRange( pDocSh, ScRange(
4774 nOldCol1, nNewRow2+1, nTab1, nOldCol2, nOldRow2, nTab2 ),
4775 SCE_ALL &~ SCE_TOP );
4777 // linker Teil
4778 if ( nNewCol1 < nOldCol1 ) // nur linke Linie loeschen
4779 lcl_PaintOneRange( pDocSh, ScRange(
4780 nOldCol1, nOldRow1, nTab1, nOldCol1, nOldRow2, nTab2 ), SCE_ALL );
4781 else if ( nNewCol1 > nOldCol1 ) // den Teil, der links wegkommt
4782 lcl_PaintOneRange( pDocSh, ScRange(
4783 nOldCol1, nOldRow1, nTab1, nNewCol1-1, nOldRow2, nTab2 ),
4784 SCE_ALL &~ SCE_RIGHT );
4786 // rechter Teil
4787 if ( nNewCol2 > nOldCol2 ) // nur rechte Linie loeschen
4788 lcl_PaintOneRange( pDocSh, ScRange(
4789 nOldCol2, nOldRow1, nTab1, nOldCol2, nOldRow2, nTab2 ), SCE_ALL );
4790 else if ( nNewCol2 < nOldCol2 ) // den Teil, der rechts wegkommt
4791 lcl_PaintOneRange( pDocSh, ScRange(
4792 nNewCol2+1, nOldRow1, nTab1, nOldCol2, nOldRow2, nTab2 ),
4793 SCE_ALL &~ SCE_LEFT );
4797 void ScGridWindow::RFMouseMove( const MouseEvent& rMEvt, BOOL bUp )
4799 ScInputHandler* pHdl = SC_MOD()->GetInputHdl( pViewData->GetViewShell() );
4800 if (!pHdl)
4801 return;
4802 ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList();
4803 if (!pRangeFinder || nRFIndex >= pRangeFinder->Count())
4804 return;
4805 ScRangeFindData* pData = pRangeFinder->GetObject( nRFIndex );
4806 if (!pData)
4807 return;
4809 // Mauszeiger
4811 if (bRFSize)
4812 SetPointer( Pointer( POINTER_CROSS ) );
4813 else
4814 SetPointer( Pointer( POINTER_HAND ) );
4816 // Scrolling
4818 BOOL bTimer = FALSE;
4819 Point aPos = rMEvt.GetPosPixel();
4820 SCsCOL nDx = 0;
4821 SCsROW nDy = 0;
4822 if ( aPos.X() < 0 ) nDx = -1;
4823 if ( aPos.Y() < 0 ) nDy = -1;
4824 Size aSize = GetOutputSizePixel();
4825 if ( aPos.X() >= aSize.Width() )
4826 nDx = 1;
4827 if ( aPos.Y() >= aSize.Height() )
4828 nDy = 1;
4829 if ( nDx != 0 || nDy != 0 )
4831 if ( nDx != 0) pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) );
4832 if ( nDy != 0 ) pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) );
4833 bTimer = TRUE;
4836 // Umschalten bei Fixierung (damit Scrolling funktioniert)
4838 if ( eWhich == pViewData->GetActivePart() ) //??
4840 if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX )
4841 if ( nDx > 0 )
4843 if ( eWhich == SC_SPLIT_TOPLEFT )
4844 pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT );
4845 else if ( eWhich == SC_SPLIT_BOTTOMLEFT )
4846 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT );
4849 if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX )
4850 if ( nDy > 0 )
4852 if ( eWhich == SC_SPLIT_TOPLEFT )
4853 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT );
4854 else if ( eWhich == SC_SPLIT_TOPRIGHT )
4855 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT );
4859 // Verschieben
4861 SCsCOL nPosX;
4862 SCsROW nPosY;
4863 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
4865 ScRange aOld = pData->aRef;
4866 ScRange aNew = aOld;
4867 if ( bRFSize )
4869 aNew.aEnd.SetCol((SCCOL)nPosX);
4870 aNew.aEnd.SetRow((SCROW)nPosY);
4872 else
4874 long nStartX = nPosX - nRFAddX;
4875 if ( nStartX < 0 ) nStartX = 0;
4876 long nStartY = nPosY - nRFAddY;
4877 if ( nStartY < 0 ) nStartY = 0;
4878 long nEndX = nStartX + aOld.aEnd.Col() - aOld.aStart.Col();
4879 if ( nEndX > MAXCOL )
4881 nStartX -= ( nEndX - MAXROW );
4882 nEndX = MAXCOL;
4884 long nEndY = nStartY + aOld.aEnd.Row() - aOld.aStart.Row();
4885 if ( nEndY > MAXROW )
4887 nStartY -= ( nEndY - MAXROW );
4888 nEndY = MAXROW;
4891 aNew.aStart.SetCol((SCCOL)nStartX);
4892 aNew.aStart.SetRow((SCROW)nStartY);
4893 aNew.aEnd.SetCol((SCCOL)nEndX);
4894 aNew.aEnd.SetRow((SCROW)nEndY);
4897 if ( bUp )
4898 aNew.Justify(); // beim ButtonUp wieder richtigherum
4900 if ( aNew != aOld )
4902 pHdl->UpdateRange( nRFIndex, aNew );
4904 ScDocShell* pDocSh = pViewData->GetDocShell();
4906 // nur das neuzeichnen, was sich veraendert hat...
4907 lcl_PaintRefChanged( pDocSh, aOld, aNew );
4909 // neuen Rahmen nur drueberzeichnen (synchron)
4910 pDocSh->Broadcast( ScIndexHint( SC_HINT_SHOWRANGEFINDER, nRFIndex ) );
4912 Update(); // was man bewegt, will man auch sofort sehen
4915 // Timer fuer Scrolling
4917 if (bTimer)
4918 pViewData->GetView()->SetTimer( this, rMEvt ); // Event wiederholen
4919 else
4920 pViewData->GetView()->ResetTimer();
4923 //------------------------------------------------------------------------
4925 BOOL ScGridWindow::GetEditUrl( const Point& rPos,
4926 String* pName, String* pUrl, String* pTarget )
4928 return GetEditUrlOrError( FALSE, rPos, pName, pUrl, pTarget );
4931 BOOL ScGridWindow::GetEditUrlOrError( BOOL bSpellErr, const Point& rPos,
4932 String* pName, String* pUrl, String* pTarget )
4934 //! nPosX/Y mit uebergeben?
4935 SCsCOL nPosX;
4936 SCsROW nPosY;
4937 pViewData->GetPosFromPixel( rPos.X(), rPos.Y(), eWhich, nPosX, nPosY );
4939 SCTAB nTab = pViewData->GetTabNo();
4940 ScDocShell* pDocSh = pViewData->GetDocShell();
4941 ScDocument* pDoc = pDocSh->GetDocument();
4942 ScBaseCell* pCell = NULL;
4944 BOOL bFound = lcl_GetHyperlinkCell( pDoc, nPosX, nPosY, nTab, pCell );
4945 if( !bFound )
4946 return FALSE;
4948 ScHideTextCursor aHideCursor( pViewData, eWhich ); // before GetEditArea (MapMode is changed)
4950 const ScPatternAttr* pPattern = pDoc->GetPattern( nPosX, nPosY, nTab );
4951 // bForceToTop = FALSE, use the cell's real position
4952 Rectangle aEditRect = pViewData->GetEditArea( eWhich, nPosX, nPosY, this, pPattern, FALSE );
4953 if (rPos.Y() < aEditRect.Top())
4954 return FALSE;
4956 // vertikal kann (noch) nicht angeklickt werden:
4958 if (pPattern->GetCellOrientation() != SVX_ORIENTATION_STANDARD)
4959 return FALSE;
4961 BOOL bBreak = ((SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK)).GetValue() ||
4962 ((SvxCellHorJustify)((const SvxHorJustifyItem&)pPattern->
4963 GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_BLOCK);
4964 SvxCellHorJustify eHorJust = (SvxCellHorJustify)((SvxHorJustifyItem&)pPattern->
4965 GetItem(ATTR_HOR_JUSTIFY)).GetValue();
4967 // EditEngine
4969 ScFieldEditEngine aEngine( pDoc->GetEditPool() );
4970 ScSizeDeviceProvider aProv(pDocSh);
4971 aEngine.SetRefDevice( aProv.GetDevice() );
4972 aEngine.SetRefMapMode( MAP_100TH_MM );
4973 SfxItemSet aDefault( aEngine.GetEmptyItemSet() );
4974 pPattern->FillEditItemSet( &aDefault );
4975 SvxAdjust eSvxAdjust = SVX_ADJUST_LEFT;
4976 switch (eHorJust)
4978 case SVX_HOR_JUSTIFY_LEFT:
4979 case SVX_HOR_JUSTIFY_REPEAT: // nicht implementiert
4980 case SVX_HOR_JUSTIFY_STANDARD: // always Text if an EditCell type
4981 eSvxAdjust = SVX_ADJUST_LEFT;
4982 break;
4983 case SVX_HOR_JUSTIFY_RIGHT:
4984 eSvxAdjust = SVX_ADJUST_RIGHT;
4985 break;
4986 case SVX_HOR_JUSTIFY_CENTER:
4987 eSvxAdjust = SVX_ADJUST_CENTER;
4988 break;
4989 case SVX_HOR_JUSTIFY_BLOCK:
4990 eSvxAdjust = SVX_ADJUST_BLOCK;
4991 break;
4993 aDefault.Put( SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) );
4994 aEngine.SetDefaults( aDefault );
4995 if (bSpellErr)
4996 aEngine.SetControlWord( aEngine.GetControlWord() | EE_CNTRL_ONLINESPELLING );
4998 MapMode aEditMode = pViewData->GetLogicMode(eWhich); // ohne Drawing-Skalierung
4999 Rectangle aLogicEdit = PixelToLogic( aEditRect, aEditMode );
5000 long nThisColLogic = aLogicEdit.Right() - aLogicEdit.Left() + 1;
5001 Size aPaperSize = Size( 1000000, 1000000 );
5002 if(pCell->GetCellType() == CELLTYPE_FORMULA)
5004 long nSizeX = 0;
5005 long nSizeY = 0;
5006 pViewData->GetMergeSizePixel( nPosX, nPosY, nSizeX, nSizeY );
5007 aPaperSize = Size(nSizeX, nSizeY );
5008 aPaperSize = PixelToLogic(aPaperSize);
5011 if (bBreak)
5012 aPaperSize.Width() = nThisColLogic;
5013 aEngine.SetPaperSize( aPaperSize );
5015 ::std::auto_ptr< EditTextObject > pTextObj;
5016 const EditTextObject* pData;
5017 if(pCell->GetCellType() == CELLTYPE_EDIT)
5019 ((ScEditCell*)pCell)->GetData(pData);
5020 if (pData)
5021 aEngine.SetText(*pData);
5023 else // HyperLink Formula cell
5025 pTextObj.reset((static_cast<ScFormulaCell*>(pCell))->CreateURLObject());
5026 if (pTextObj.get())
5027 aEngine.SetText(*pTextObj);
5030 long nStartX = aLogicEdit.Left();
5032 long nTextWidth = aEngine.CalcTextWidth();
5033 long nTextHeight = aEngine.GetTextHeight();
5034 if ( nTextWidth < nThisColLogic )
5036 if (eHorJust == SVX_HOR_JUSTIFY_RIGHT)
5037 nStartX += nThisColLogic - nTextWidth;
5038 else if (eHorJust == SVX_HOR_JUSTIFY_CENTER)
5039 nStartX += (nThisColLogic - nTextWidth) / 2;
5042 aLogicEdit.Left() = nStartX;
5043 if (!bBreak)
5044 aLogicEdit.Right() = nStartX + nTextWidth;
5046 // There is one glitch when dealing with a hyperlink cell and
5047 // the cell content is NUMERIC. This defaults to right aligned and
5048 // we need to adjust accordingly.
5049 if(pCell->GetCellType() == CELLTYPE_FORMULA &&
5050 static_cast<ScFormulaCell*>(pCell)->IsValue() &&
5051 eHorJust == SVX_HOR_JUSTIFY_STANDARD)
5053 aLogicEdit.Right() = aLogicEdit.Left() + nThisColLogic - 1;
5054 aLogicEdit.Left() = aLogicEdit.Right() - nTextWidth;
5056 aLogicEdit.Bottom() = aLogicEdit.Top() + nTextHeight;
5059 Point aLogicClick = PixelToLogic(rPos,aEditMode);
5060 if ( aLogicEdit.IsInside(aLogicClick) )
5062 // aEngine.SetUpdateMode(FALSE);
5063 EditView aTempView( &aEngine, this );
5064 aTempView.SetOutputArea( aLogicEdit );
5066 BOOL bRet = FALSE;
5067 MapMode aOld = GetMapMode();
5068 SetMapMode(aEditMode); // kein return mehr
5070 if (bSpellErr) // Spelling-Fehler suchen
5072 bRet = aTempView.IsWrongSpelledWordAtPos( rPos );
5073 if ( bRet )
5074 pViewData->GetView()->SetCursor( nPosX, nPosY ); // Cursor setzen
5076 else // URL suchen
5078 const SvxFieldItem* pFieldItem = aTempView.GetFieldUnderMousePointer();
5080 if (pFieldItem)
5082 const SvxFieldData* pField = pFieldItem->GetField();
5083 if ( pField && pField->ISA(SvxURLField) )
5085 if ( pName || pUrl || pTarget )
5087 const SvxURLField* pURLField = (const SvxURLField*)pField;
5088 if (pName)
5089 *pName = pURLField->GetRepresentation();
5090 if (pUrl)
5091 *pUrl = pURLField->GetURL();
5092 if (pTarget)
5093 *pTarget = pURLField->GetTargetFrame();
5095 bRet = TRUE;
5100 SetMapMode(aOld);
5102 // text cursor is restored in ScHideTextCursor dtor
5104 return bRet;
5106 return FALSE;
5109 BOOL ScGridWindow::HasScenarioButton( const Point& rPosPixel, ScRange& rScenRange )
5111 ScDocument* pDoc = pViewData->GetDocument();
5112 SCTAB nTab = pViewData->GetTabNo();
5113 SCTAB nTabCount = pDoc->GetTableCount();
5114 if ( nTab+1<nTabCount && pDoc->IsScenario(nTab+1) && !pDoc->IsScenario(nTab) )
5116 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5118 Size aButSize = pViewData->GetScenButSize();
5119 long nBWidth = aButSize.Width();
5120 if (!nBWidth)
5121 return FALSE; // noch kein Button gezeichnet -> da ist auch keiner
5122 long nBHeight = aButSize.Height();
5123 long nHSpace = (long)( SC_SCENARIO_HSPACE * pViewData->GetPPTX() );
5125 //! Ranges an der Table cachen!!!!
5127 ScMarkData aMarks;
5128 for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
5129 pDoc->MarkScenario( i, nTab, aMarks, FALSE, SC_SCENARIO_SHOWFRAME );
5130 ScRangeList aRanges;
5131 aMarks.FillRangeListWithMarks( &aRanges, FALSE );
5134 ULONG nRangeCount = aRanges.Count();
5135 for (ULONG j=0; j<nRangeCount; j++)
5137 ScRange aRange = *aRanges.GetObject(j);
5138 // Szenario-Rahmen immer dann auf zusammengefasste Zellen erweitern, wenn
5139 // dadurch keine neuen nicht-ueberdeckten Zellen mit umrandet werden
5140 pDoc->ExtendTotalMerge( aRange );
5142 BOOL bTextBelow = ( aRange.aStart.Row() == 0 );
5144 Point aButtonPos;
5145 if ( bTextBelow )
5147 aButtonPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aEnd.Row()+1,
5148 eWhich, TRUE );
5150 else
5152 aButtonPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aStart.Row(),
5153 eWhich, TRUE );
5154 aButtonPos.Y() -= nBHeight;
5156 if ( bLayoutRTL )
5157 aButtonPos.X() -= nHSpace - 1;
5158 else
5159 aButtonPos.X() -= nBWidth - nHSpace; // same for top or bottom
5161 Rectangle aButRect( aButtonPos, Size(nBWidth,nBHeight) );
5162 if ( aButRect.IsInside( rPosPixel ) )
5164 rScenRange = aRange;
5165 return TRUE;
5170 return FALSE;
5173 // #114409#
5174 void ScGridWindow::DrawLayerCreated()
5176 SetMapMode( GetDrawMapMode() );
5178 // initially create overlay objects
5179 ImpCreateOverlayObjects();
5182 // #114409#
5183 void ScGridWindow::CursorChanged()
5185 // here the created OverlayObjects may be transformed in later versions. For
5186 // now, just re-create them
5188 UpdateCursorOverlay();
5191 // #114409#
5192 void ScGridWindow::ImpCreateOverlayObjects()
5194 UpdateCursorOverlay();
5195 UpdateSelectionOverlay();
5196 UpdateAutoFillOverlay();
5197 UpdateDragRectOverlay();
5198 UpdateHeaderOverlay();
5199 UpdateShrinkOverlay();
5202 // #114409#
5203 void ScGridWindow::ImpDestroyOverlayObjects()
5205 DeleteCursorOverlay();
5206 DeleteSelectionOverlay();
5207 DeleteAutoFillOverlay();
5208 DeleteDragRectOverlay();
5209 DeleteHeaderOverlay();
5210 DeleteShrinkOverlay();
5213 void ScGridWindow::UpdateAllOverlays()
5215 // delete and re-allocate all overlay objects
5217 ImpDestroyOverlayObjects();
5218 ImpCreateOverlayObjects();
5221 void ScGridWindow::DeleteCursorOverlay()
5223 DELETEZ( mpOOCursors );
5226 void ScGridWindow::UpdateCursorOverlay()
5228 MapMode aDrawMode = GetDrawMapMode();
5229 MapMode aOldMode = GetMapMode();
5230 if ( aOldMode != aDrawMode )
5231 SetMapMode( aDrawMode );
5233 // Existing OverlayObjects may be transformed in later versions.
5234 // For now, just re-create them.
5236 DeleteCursorOverlay();
5238 std::vector<Rectangle> aPixelRects;
5241 // determine the cursor rectangles in pixels (moved from ScGridWindow::DrawCursor)
5244 SCTAB nTab = pViewData->GetTabNo();
5245 SCCOL nX = pViewData->GetCurX();
5246 SCROW nY = pViewData->GetCurY();
5248 if (!maVisibleRange.isInside(nX, nY))
5249 return;
5251 // don't show the cursor in overlapped cells
5253 ScDocument* pDoc = pViewData->GetDocument();
5254 const ScPatternAttr* pPattern = pDoc->GetPattern(nX,nY,nTab);
5255 const ScMergeFlagAttr& rMergeFlag = (const ScMergeFlagAttr&) pPattern->GetItem(ATTR_MERGE_FLAG);
5256 BOOL bOverlapped = rMergeFlag.IsOverlapped();
5258 // left or above of the screen?
5260 BOOL bVis = ( nX>=pViewData->GetPosX(eHWhich) && nY>=pViewData->GetPosY(eVWhich) );
5261 if (!bVis)
5263 SCCOL nEndX = nX;
5264 SCROW nEndY = nY;
5265 const ScMergeAttr& rMerge = (const ScMergeAttr&) pPattern->GetItem(ATTR_MERGE);
5266 if (rMerge.GetColMerge() > 1)
5267 nEndX += rMerge.GetColMerge()-1;
5268 if (rMerge.GetRowMerge() > 1)
5269 nEndY += rMerge.GetRowMerge()-1;
5270 bVis = ( nEndX>=pViewData->GetPosX(eHWhich) && nEndY>=pViewData->GetPosY(eVWhich) );
5273 if ( bVis && !bOverlapped && !pViewData->HasEditView(eWhich) && pViewData->IsActive() )
5275 Point aScrPos = pViewData->GetScrPos( nX, nY, eWhich, TRUE );
5276 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5278 // completely right of/below the screen?
5279 // (test with logical start position in aScrPos)
5280 BOOL bMaybeVisible;
5281 if ( bLayoutRTL )
5282 bMaybeVisible = ( aScrPos.X() >= -2 && aScrPos.Y() >= -2 );
5283 else
5285 Size aOutSize = GetOutputSizePixel();
5286 bMaybeVisible = ( aScrPos.X() <= aOutSize.Width() + 2 && aScrPos.Y() <= aOutSize.Height() + 2 );
5288 if ( bMaybeVisible )
5290 long nSizeXPix;
5291 long nSizeYPix;
5292 pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix );
5294 if ( bLayoutRTL )
5295 aScrPos.X() -= nSizeXPix - 2; // move instead of mirroring
5297 // Now, draw the cursor.
5299 aScrPos.X() -= 2;
5300 aScrPos.Y() -= 2;
5301 Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) );
5303 aPixelRects.push_back(Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() ));
5304 aPixelRects.push_back(Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() ));
5305 aPixelRects.push_back(Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 ));
5306 aPixelRects.push_back(Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() ));
5310 if ( aPixelRects.size() )
5312 // #i70788# get the OverlayManager safely
5313 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5315 if(pOverlayManager)
5317 Color aCursorColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
5318 if (pViewData->GetActivePart() != eWhich)
5319 // non-active pane uses a different color.
5320 aCursorColor = SC_MOD()->GetColorConfig().GetColorValue(svtools::CALCPAGEBREAKAUTOMATIC).nColor;
5321 std::vector< basegfx::B2DRange > aRanges;
5322 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5324 for(sal_uInt32 a(0); a < aPixelRects.size(); a++)
5326 const Rectangle aRA(aPixelRects[a]);
5327 basegfx::B2DRange aRB(aRA.Left(), aRA.Top(), aRA.Right() + 1, aRA.Bottom() + 1);
5328 aRB.transform(aTransform);
5329 aRanges.push_back(aRB);
5332 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5333 sdr::overlay::OVERLAY_SOLID,
5334 aCursorColor,
5335 aRanges,
5336 false);
5338 pOverlayManager->add(*pOverlay);
5339 mpOOCursors = new ::sdr::overlay::OverlayObjectList;
5340 mpOOCursors->append(*pOverlay);
5344 if ( aOldMode != aDrawMode )
5345 SetMapMode( aOldMode );
5348 void ScGridWindow::DeleteSelectionOverlay()
5350 DELETEZ( mpOOSelection );
5353 void ScGridWindow::UpdateSelectionOverlay()
5355 MapMode aDrawMode = GetDrawMapMode();
5356 MapMode aOldMode = GetMapMode();
5357 if ( aOldMode != aDrawMode )
5358 SetMapMode( aDrawMode );
5360 DeleteSelectionOverlay();
5361 std::vector<Rectangle> aPixelRects;
5362 GetSelectionRects( aPixelRects );
5364 if ( aPixelRects.size() && pViewData->IsActive() )
5366 // #i70788# get the OverlayManager safely
5367 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5369 if(pOverlayManager)
5371 std::vector< basegfx::B2DRange > aRanges;
5372 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5374 for(sal_uInt32 a(0); a < aPixelRects.size(); a++)
5376 const Rectangle aRA(aPixelRects[a]);
5377 basegfx::B2DRange aRB(aRA.Left() - 1, aRA.Top() - 1, aRA.Right(), aRA.Bottom());
5378 aRB.transform(aTransform);
5379 aRanges.push_back(aRB);
5382 // #i97672# get the system's hilight color and limit it to the maximum
5383 // allowed luminance. This is needed to react on too bright hilight colors
5384 // which would otherwise vive a bad visualisation
5385 Color aHighlight(GetSettings().GetStyleSettings().GetHighlightColor());
5386 const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
5387 const basegfx::BColor aSelection(aHighlight.getBColor());
5388 const double fLuminance(aSelection.luminance());
5389 const double fMaxLum(aSvtOptionsDrawinglayer.GetSelectionMaximumLuminancePercent() / 100.0);
5391 if(fLuminance > fMaxLum)
5393 const double fFactor(fMaxLum / fLuminance);
5394 const basegfx::BColor aNewSelection(
5395 aSelection.getRed() * fFactor,
5396 aSelection.getGreen() * fFactor,
5397 aSelection.getBlue() * fFactor);
5399 aHighlight = Color(aNewSelection);
5402 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5403 sdr::overlay::OVERLAY_TRANSPARENT,
5404 aHighlight,
5405 aRanges,
5406 true);
5408 pOverlayManager->add(*pOverlay);
5409 mpOOSelection = new ::sdr::overlay::OverlayObjectList;
5410 mpOOSelection->append(*pOverlay);
5414 if ( aOldMode != aDrawMode )
5415 SetMapMode( aOldMode );
5418 void ScGridWindow::DeleteAutoFillOverlay()
5420 DELETEZ( mpOOAutoFill );
5421 mpAutoFillRect.reset();
5424 void ScGridWindow::UpdateAutoFillOverlay()
5426 MapMode aDrawMode = GetDrawMapMode();
5427 MapMode aOldMode = GetMapMode();
5428 if ( aOldMode != aDrawMode )
5429 SetMapMode( aDrawMode );
5431 DeleteAutoFillOverlay();
5434 // get the AutoFill handle rectangle in pixels (moved from ScGridWindow::DrawAutoFillMark)
5437 if ( bAutoMarkVisible && aAutoMarkPos.Tab() == pViewData->GetTabNo() &&
5438 !pViewData->HasEditView(eWhich) && pViewData->IsActive() )
5440 SCCOL nX = aAutoMarkPos.Col();
5441 SCROW nY = aAutoMarkPos.Row();
5443 if (!maVisibleRange.isInside(nX, nY))
5444 // Autofill mark is not visible. Bail out.
5445 return;
5447 SCTAB nTab = pViewData->GetTabNo();
5448 ScDocument* pDoc = pViewData->GetDocument();
5449 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5451 Point aFillPos = pViewData->GetScrPos( nX, nY, eWhich, TRUE );
5452 long nSizeXPix;
5453 long nSizeYPix;
5454 pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix );
5455 if ( bLayoutRTL )
5456 aFillPos.X() -= nSizeXPix + 3;
5457 else
5458 aFillPos.X() += nSizeXPix - 2;
5460 aFillPos.Y() += nSizeYPix;
5461 aFillPos.Y() -= 2;
5462 mpAutoFillRect.reset(new Rectangle(aFillPos, Size(6, 6)));
5464 // #i70788# get the OverlayManager safely
5465 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5467 if(pOverlayManager)
5469 Color aHandleColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
5470 if (pViewData->GetActivePart() != eWhich)
5471 // non-active pane uses a different color.
5472 aHandleColor = SC_MOD()->GetColorConfig().GetColorValue(svtools::CALCPAGEBREAKAUTOMATIC).nColor;
5473 std::vector< basegfx::B2DRange > aRanges;
5474 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5475 basegfx::B2DRange aRB(mpAutoFillRect->Left(), mpAutoFillRect->Top(), mpAutoFillRect->Right() + 1, mpAutoFillRect->Bottom() + 1);
5477 aRB.transform(aTransform);
5478 aRanges.push_back(aRB);
5480 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5481 sdr::overlay::OVERLAY_SOLID,
5482 aHandleColor,
5483 aRanges,
5484 false);
5486 pOverlayManager->add(*pOverlay);
5487 mpOOAutoFill = new ::sdr::overlay::OverlayObjectList;
5488 mpOOAutoFill->append(*pOverlay);
5491 if ( aOldMode != aDrawMode )
5492 SetMapMode( aOldMode );
5496 void ScGridWindow::DeleteDragRectOverlay()
5498 DELETEZ( mpOODragRect );
5501 void ScGridWindow::UpdateDragRectOverlay()
5503 MapMode aDrawMode = GetDrawMapMode();
5504 MapMode aOldMode = GetMapMode();
5505 if ( aOldMode != aDrawMode )
5506 SetMapMode( aDrawMode );
5508 DeleteDragRectOverlay();
5511 // get the rectangles in pixels (moved from DrawDragRect)
5514 if ( bDragRect || bPagebreakDrawn )
5516 std::vector<Rectangle> aPixelRects;
5518 SCCOL nX1 = bDragRect ? nDragStartX : aPagebreakDrag.aStart.Col();
5519 SCROW nY1 = bDragRect ? nDragStartY : aPagebreakDrag.aStart.Row();
5520 SCCOL nX2 = bDragRect ? nDragEndX : aPagebreakDrag.aEnd.Col();
5521 SCROW nY2 = bDragRect ? nDragEndY : aPagebreakDrag.aEnd.Row();
5523 SCTAB nTab = pViewData->GetTabNo();
5525 SCCOL nPosX = pViewData->GetPosX(WhichH(eWhich));
5526 SCROW nPosY = pViewData->GetPosY(WhichV(eWhich));
5527 if (nX1 < nPosX) nX1 = nPosX;
5528 if (nX2 < nPosX) nX2 = nPosX;
5529 if (nY1 < nPosY) nY1 = nPosY;
5530 if (nY2 < nPosY) nY2 = nPosY;
5532 Point aScrPos( pViewData->GetScrPos( nX1, nY1, eWhich ) );
5534 long nSizeXPix=0;
5535 long nSizeYPix=0;
5536 ScDocument* pDoc = pViewData->GetDocument();
5537 double nPPTX = pViewData->GetPPTX();
5538 double nPPTY = pViewData->GetPPTY();
5539 SCCOLROW i;
5541 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5542 long nLayoutSign = bLayoutRTL ? -1 : 1;
5544 if (ValidCol(nX2) && nX2>=nX1)
5545 for (i=nX1; i<=nX2; i++)
5546 nSizeXPix += ScViewData::ToPixel( pDoc->GetColWidth( static_cast<SCCOL>(i), nTab ), nPPTX );
5547 else
5549 aScrPos.X() -= nLayoutSign;
5550 nSizeXPix += 2;
5553 if (ValidRow(nY2) && nY2>=nY1)
5554 for (i=nY1; i<=nY2; i++)
5555 nSizeYPix += ScViewData::ToPixel( pDoc->GetRowHeight( i, nTab ), nPPTY );
5556 else
5558 aScrPos.Y() -= 1;
5559 nSizeYPix += 2;
5562 aScrPos.X() -= 2 * nLayoutSign;
5563 aScrPos.Y() -= 2;
5564 // Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) );
5565 Rectangle aRect( aScrPos.X(), aScrPos.Y(),
5566 aScrPos.X() + ( nSizeXPix + 2 ) * nLayoutSign, aScrPos.Y() + nSizeYPix + 2 );
5567 if ( bLayoutRTL )
5569 aRect.Left() = aRect.Right(); // end position is left
5570 aRect.Right() = aScrPos.X();
5573 if ( meDragInsertMode == INS_CELLSDOWN )
5575 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Top()+3, aRect.Left()+1, aRect.Bottom()-2 ) );
5576 aPixelRects.push_back( Rectangle( aRect.Right()-1, aRect.Top()+3, aRect.Right()-1, aRect.Bottom()-2 ) );
5577 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Top(), aRect.Right()-1, aRect.Top()+2 ) );
5578 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Bottom()-1, aRect.Right()-1, aRect.Bottom()-1 ) );
5580 else if ( meDragInsertMode == INS_CELLSRIGHT )
5582 aPixelRects.push_back( Rectangle( aRect.Left(), aRect.Top()+1, aRect.Left()+2, aRect.Bottom()-1 ) );
5583 aPixelRects.push_back( Rectangle( aRect.Right()-1, aRect.Top()+1, aRect.Right()-1, aRect.Bottom()-1 ) );
5584 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Top()+1, aRect.Right()-2, aRect.Top()+1 ) );
5585 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Bottom()-1, aRect.Right()-2, aRect.Bottom()-1 ) );
5587 else
5589 aPixelRects.push_back( Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() ) );
5590 aPixelRects.push_back( Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() ) );
5591 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 ) );
5592 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() ) );
5595 // #i70788# get the OverlayManager safely
5596 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5598 if(pOverlayManager)
5600 // Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
5601 std::vector< basegfx::B2DRange > aRanges;
5602 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5604 for(sal_uInt32 a(0); a < aPixelRects.size(); a++)
5606 const Rectangle aRA(aPixelRects[a]);
5607 basegfx::B2DRange aRB(aRA.Left(), aRA.Top(), aRA.Right() + 1, aRA.Bottom() + 1);
5608 aRB.transform(aTransform);
5609 aRanges.push_back(aRB);
5612 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5613 sdr::overlay::OVERLAY_INVERT,
5614 Color(COL_BLACK),
5615 aRanges,
5616 false);
5618 pOverlayManager->add(*pOverlay);
5619 mpOODragRect = new ::sdr::overlay::OverlayObjectList;
5620 mpOODragRect->append(*pOverlay);
5624 if ( aOldMode != aDrawMode )
5625 SetMapMode( aOldMode );
5628 void ScGridWindow::DeleteHeaderOverlay()
5630 DELETEZ( mpOOHeader );
5633 void ScGridWindow::UpdateHeaderOverlay()
5635 MapMode aDrawMode = GetDrawMapMode();
5636 MapMode aOldMode = GetMapMode();
5637 if ( aOldMode != aDrawMode )
5638 SetMapMode( aDrawMode );
5640 DeleteHeaderOverlay();
5642 // Pixel rectangle is in aInvertRect
5643 if ( !aInvertRect.IsEmpty() )
5645 // #i70788# get the OverlayManager safely
5646 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5648 if(pOverlayManager)
5650 // Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
5651 std::vector< basegfx::B2DRange > aRanges;
5652 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5653 basegfx::B2DRange aRB(aInvertRect.Left(), aInvertRect.Top(), aInvertRect.Right() + 1, aInvertRect.Bottom() + 1);
5655 aRB.transform(aTransform);
5656 aRanges.push_back(aRB);
5658 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5659 sdr::overlay::OVERLAY_INVERT,
5660 Color(COL_BLACK),
5661 aRanges,
5662 false);
5664 pOverlayManager->add(*pOverlay);
5665 mpOOHeader = new ::sdr::overlay::OverlayObjectList;
5666 mpOOHeader->append(*pOverlay);
5670 if ( aOldMode != aDrawMode )
5671 SetMapMode( aOldMode );
5674 void ScGridWindow::DeleteShrinkOverlay()
5676 DELETEZ( mpOOShrink );
5679 void ScGridWindow::UpdateShrinkOverlay()
5681 MapMode aDrawMode = GetDrawMapMode();
5682 MapMode aOldMode = GetMapMode();
5683 if ( aOldMode != aDrawMode )
5684 SetMapMode( aDrawMode );
5686 DeleteShrinkOverlay();
5689 // get the rectangle in pixels
5692 Rectangle aPixRect;
5693 ScRange aRange;
5694 SCTAB nTab = pViewData->GetTabNo();
5695 if ( pViewData->IsRefMode() && nTab >= pViewData->GetRefStartZ() && nTab <= pViewData->GetRefEndZ() &&
5696 pViewData->GetDelMark( aRange ) )
5698 //! limit to visible area
5699 if ( aRange.aStart.Col() <= aRange.aEnd.Col() &&
5700 aRange.aStart.Row() <= aRange.aEnd.Row() )
5702 Point aStart = pViewData->GetScrPos( aRange.aStart.Col(),
5703 aRange.aStart.Row(), eWhich );
5704 Point aEnd = pViewData->GetScrPos( aRange.aEnd.Col()+1,
5705 aRange.aEnd.Row()+1, eWhich );
5706 aEnd.X() -= 1;
5707 aEnd.Y() -= 1;
5709 aPixRect = Rectangle( aStart,aEnd );
5713 if ( !aPixRect.IsEmpty() )
5715 // #i70788# get the OverlayManager safely
5716 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5718 if(pOverlayManager)
5720 // Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
5721 std::vector< basegfx::B2DRange > aRanges;
5722 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5723 basegfx::B2DRange aRB(aPixRect.Left(), aPixRect.Top(), aPixRect.Right() + 1, aPixRect.Bottom() + 1);
5725 aRB.transform(aTransform);
5726 aRanges.push_back(aRB);
5728 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5729 sdr::overlay::OVERLAY_INVERT,
5730 Color(COL_BLACK),
5731 aRanges,
5732 false);
5734 pOverlayManager->add(*pOverlay);
5735 mpOOShrink = new ::sdr::overlay::OverlayObjectList;
5736 mpOOShrink->append(*pOverlay);
5740 if ( aOldMode != aDrawMode )
5741 SetMapMode( aOldMode );
5744 // #i70788# central method to get the OverlayManager safely
5745 ::sdr::overlay::OverlayManager* ScGridWindow::getOverlayManager()
5747 SdrPageView* pPV = pViewData->GetView()->GetScDrawView()->GetSdrPageView();
5749 if(pPV)
5751 SdrPageWindow* pPageWin = pPV->FindPageWindow( *this );
5753 if ( pPageWin )
5755 return (pPageWin->GetOverlayManager());
5759 return 0L;
5762 void ScGridWindow::flushOverlayManager()
5764 // #i70788# get the OverlayManager safely
5765 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager();
5767 if(pOverlayManager)
5769 pOverlayManager->flush();
5773 // ---------------------------------------------------------------------------
5774 // eof