Version 4.0.2.1, tag libreoffice-4.0.2.1
[LibreOffice.git] / sc / source / ui / view / gridwin.cxx
blob5d8583114e0534a654acf419750b7d3b73f0a791
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "scitems.hxx"
23 #include <memory> //auto_ptr
24 #include <editeng/adjitem.hxx>
25 #include <svx/algitem.hxx>
26 #include <editeng/editview.hxx>
27 #include <editeng/editstat.hxx>
28 #include <editeng/flditem.hxx>
29 #include <editeng/justifyitem.hxx>
30 #include <svx/svdetc.hxx>
31 #include <editeng/editobj.hxx>
32 #include <sfx2/dispatch.hxx>
33 #include <sfx2/viewfrm.hxx>
34 #include <sfx2/docfile.hxx>
35 #include <svl/stritem.hxx>
36 #include <svtools/svtabbx.hxx>
37 #include <svl/urlbmk.hxx>
38 #include <vcl/cursor.hxx>
39 #include <vcl/graph.hxx>
40 #include <vcl/hatch.hxx>
41 #include <sot/formats.hxx>
42 #include <sot/clsids.hxx>
43 #include <sal/macros.h>
45 #include <svx/svdview.hxx> // fuer Command-Handler (COMMAND_INSERTTEXT)
46 #include <editeng/outliner.hxx> // fuer Command-Handler (COMMAND_INSERTTEXT)
47 #include <svx/svditer.hxx>
48 #include <svx/svdocapt.hxx>
49 #include <svx/svdpagv.hxx>
51 #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
52 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
53 #include <com/sun/star/sheet/DataPilotTableHeaderData.hpp>
54 #include <com/sun/star/sheet/DataPilotTableResultData.hpp>
55 #include <com/sun/star/sheet/DataPilotTablePositionData.hpp>
56 #include <com/sun/star/sheet/DataPilotTablePositionType.hpp>
57 #include <com/sun/star/sheet/MemberResultFlags.hpp>
58 #include <com/sun/star/awt/KeyModifier.hpp>
59 #include <com/sun/star/awt/MouseButton.hpp>
60 #include <com/sun/star/script/vba/VBAEventId.hpp>
61 #include <com/sun/star/script/vba/XVBAEventProcessor.hpp>
63 #include "gridwin.hxx"
64 #include "tabvwsh.hxx"
65 #include "docsh.hxx"
66 #include "viewdata.hxx"
67 #include "tabview.hxx"
68 #include "select.hxx"
69 #include "scmod.hxx"
70 #include "document.hxx"
71 #include "attrib.hxx"
72 #include "dbdata.hxx"
73 #include "stlpool.hxx"
74 #include "printfun.hxx"
75 #include "cbutton.hxx"
76 #include "sc.hrc"
77 #include "globstr.hrc"
78 #include "editutil.hxx"
79 #include "scresid.hxx"
80 #include "inputhdl.hxx"
81 #include "uiitems.hxx" // Filter-Dialog - auslagern !!!
82 #include "filtdlg.hxx"
83 #include "impex.hxx" // Sylk-ID fuer CB
84 #include "cell.hxx" // fuer Edit-Felder
85 #include "patattr.hxx"
86 #include "notemark.hxx"
87 #include "rfindlst.hxx"
88 #include "docpool.hxx"
89 #include "output.hxx"
90 #include "docfunc.hxx"
91 #include "dbdocfun.hxx"
92 #include "dpobject.hxx"
93 #include "dpoutput.hxx"
94 #include "transobj.hxx"
95 #include "drwtrans.hxx"
96 #include "seltrans.hxx"
97 #include "sizedev.hxx"
98 #include "AccessibilityHints.hxx"
99 #include "dpsave.hxx"
100 #include "viewuno.hxx"
101 #include "compiler.hxx"
102 #include "editable.hxx"
103 #include "fillinfo.hxx"
104 #include "userdat.hxx"
105 #include "drwlayer.hxx"
106 #include "validat.hxx"
107 #include "tabprotection.hxx"
108 #include "postit.hxx"
109 #include "dpcontrol.hxx"
110 #include "checklistmenu.hxx"
111 #include "clipparam.hxx"
112 #include "cellsh.hxx"
113 #include "overlayobject.hxx"
114 #include "cellsuno.hxx"
115 #include "drawview.hxx"
116 #include "dragdata.hxx"
117 #include "cliputil.hxx"
118 #include "queryentry.hxx"
119 #include "markdata.hxx"
120 #include "checklistmenu.hrc"
121 #include "strload.hxx"
122 #include "externalrefmgr.hxx"
124 #include <svx/sdrpagewindow.hxx>
125 #include <svx/sdr/overlay/overlaymanager.hxx>
126 #include <vcl/svapp.hxx>
127 #include <svx/sdr/overlay/overlayselection.hxx>
129 #include <vector>
131 using namespace com::sun::star;
132 using ::com::sun::star::uno::Sequence;
133 using ::com::sun::star::uno::Any;
134 using ::rtl::OUString;
136 const sal_uInt8 SC_NESTEDBUTTON_NONE = 0;
137 const sal_uInt8 SC_NESTEDBUTTON_DOWN = 1;
138 const sal_uInt8 SC_NESTEDBUTTON_UP = 2;
140 #define SC_AUTOFILTER_ALL 0
141 #define SC_AUTOFILTER_TOP10 1
142 #define SC_AUTOFILTER_CUSTOM 2
143 #define SC_AUTOFILTER_EMPTY 3
144 #define SC_AUTOFILTER_NOTEMPTY 4
146 // Modi fuer die FilterListBox
147 enum ScFilterBoxMode
149 SC_FILTERBOX_FILTER,
150 SC_FILTERBOX_DATASELECT,
151 SC_FILTERBOX_SCENARIO,
152 SC_FILTERBOX_PAGEFIELD
155 extern SfxViewShell* pScActiveViewShell; // global.cxx
156 extern sal_uInt16 nScClickMouseModifier; // global.cxx
157 extern sal_uInt16 nScFillModeMouseModifier; // global.cxx
159 struct ScGridWindow::MouseEventState
161 bool mbActivatePart;
163 MouseEventState() : mbActivatePart(false) {}
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 sal_Bool bButtonDown;
189 sal_Bool bInit;
190 sal_Bool bCancelled;
191 sal_Bool bInSelect;
192 bool mbListHasDates;
193 sal_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 sal_Bool IsDataSelect() const { return (eMode == SC_FILTERBOX_DATASELECT); }
212 void EndInit();
213 sal_Bool IsInInit() const { return bInit; }
214 void SetCancelled() { bCancelled = sal_True; }
215 sal_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( sal_True ),
231 bCancelled( false ),
232 bInSelect( false ),
233 mbListHasDates(false),
234 nSel( 0 ),
235 eMode( eNewMode )
239 ScFilterListBox::~ScFilterListBox()
241 if (IsMouseCaptured())
242 ReleaseMouse();
245 void ScFilterListBox::EndInit()
247 sal_uInt16 nPos = GetSelectEntryPos();
248 if ( LISTBOX_ENTRY_NOTFOUND == nPos )
249 nSel = 0;
250 else
251 nSel = nPos;
253 bInit = false;
256 void 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 sal_uInt16 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 ScFilterListBox::Select()
293 ListBox::Select();
294 SelectHdl();
297 void ScFilterListBox::SelectHdl()
299 if ( !IsTravelSelect() && !bInit && !bCancelled )
301 sal_uInt16 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 = sal_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 static sal_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 static 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.GetNotes( aCellPos.Tab() )->findByAddress( 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 static sal_Bool lcl_GetHyperlinkCell(ScDocument* pDoc, SCCOL& rPosX, SCROW& rPosY, SCTAB nTab, ScBaseCell*& rpCell )
383 sal_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 = sal_True;
396 else if (rpCell->GetCellType() == CELLTYPE_FORMULA &&
397 static_cast<ScFormulaCell*>(rpCell)->IsHyperLinkCell())
398 bFound = sal_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 mpOOSelectionBorder( NULL ),
416 mpOOAutoFill( NULL ),
417 mpOODragRect( NULL ),
418 mpOOHeader( NULL ),
419 mpOOShrink( NULL ),
420 mpAutoFillRect(static_cast<Rectangle*>(NULL)),
421 pViewData( pData ),
422 eWhich( eWhichPos ),
423 pNoteMarker( NULL ),
424 pFilterBox( NULL ),
425 pFilterFloat( NULL ),
426 mpAutoFilterPopup(NULL),
427 mpDPFieldPopup(NULL),
428 mpFilterButton(NULL),
429 nCursorHideCount( 0 ),
430 nButtonDown( 0 ),
431 nMouseStatus( SC_GM_NONE ),
432 nNestedButtonState( SC_NESTEDBUTTON_NONE ),
433 nPagebreakMouse( SC_PD_NONE ),
434 nPageScript( 0 ),
435 nDragStartX( -1 ),
436 nDragStartY( -1 ),
437 nDragEndX( -1 ),
438 nDragEndY( -1 ),
439 meDragInsertMode( INS_NONE ),
440 nCurrentPointer( 0 ),
441 aComboButton( this ),
442 aCurMousePos( 0,0 ),
443 nPaintCount( 0 ),
444 bEEMouse( false ),
445 bDPMouse( false ),
446 bRFMouse( false ),
447 bRFSize( false ),
448 bPagebreakDrawn( false ),
449 bDragRect( false ),
450 bIsInScroll( false ),
451 bIsInPaint( false ),
452 bNeedsRepaint( false ),
453 bAutoMarkVisible( false ),
454 bListValButton( false )
456 switch(eWhich)
458 case SC_SPLIT_TOPLEFT:
459 eHWhich = SC_SPLIT_LEFT;
460 eVWhich = SC_SPLIT_TOP;
461 break;
462 case SC_SPLIT_TOPRIGHT:
463 eHWhich = SC_SPLIT_RIGHT;
464 eVWhich = SC_SPLIT_TOP;
465 break;
466 case SC_SPLIT_BOTTOMLEFT:
467 eHWhich = SC_SPLIT_LEFT;
468 eVWhich = SC_SPLIT_BOTTOM;
469 break;
470 case SC_SPLIT_BOTTOMRIGHT:
471 eHWhich = SC_SPLIT_RIGHT;
472 eVWhich = SC_SPLIT_BOTTOM;
473 break;
474 default:
475 OSL_FAIL("GridWindow: falsche Position");
478 SetBackground();
480 SetMapMode(pViewData->GetLogicMode(eWhich));
481 EnableChildTransparentMode();
482 SetDialogControlFlags( WINDOW_DLGCTRL_RETURN | WINDOW_DLGCTRL_WANTFOCUS );
484 SetHelpId( HID_SC_WIN_GRIDWIN );
485 SetUniqueId( HID_SC_WIN_GRIDWIN );
487 SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
488 EnableRTL( false );
491 ScGridWindow::~ScGridWindow()
493 // #114409#
494 ImpDestroyOverlayObjects();
496 delete pFilterBox;
497 delete pFilterFloat;
498 delete pNoteMarker;
501 void ScGridWindow::Resize( const Size& )
503 // gar nix
506 void ScGridWindow::ClickExtern()
510 // #i81298# don't delete the filter box when called from its select handler
511 // (possible through row header size update)
512 // #i84277# when initializing the filter box, a Basic error can deactivate the view
513 if ( pFilterBox && ( pFilterBox->IsInSelect() || pFilterBox->IsInInit() ) )
515 break;
518 DELETEZ(pFilterBox);
519 DELETEZ(pFilterFloat);
521 while (false);
523 if (mpDPFieldPopup)
525 mpDPFieldPopup->close(false);
526 mpDPFieldPopup.reset();
530 IMPL_LINK_NOARG(ScGridWindow, PopupModeEndHdl)
532 if (pFilterBox)
533 pFilterBox->SetCancelled(); // nicht mehr auswaehlen
534 GrabFocus();
535 return 0;
538 IMPL_LINK( ScGridWindow, PopupSpellingHdl, SpellCallbackInfo*, pInfo )
540 if( pInfo->nCommand == SPELLCMD_STARTSPELLDLG )
541 pViewData->GetDispatcher().Execute( SID_SPELL_DIALOG, SFX_CALLMODE_ASYNCHRON );
542 return 0;
545 void ScGridWindow::ExecPageFieldSelect( SCCOL nCol, SCROW nRow, sal_Bool bHasSelection, const String& rStr )
547 //! gridwin2 ?
549 ScDocument* pDoc = pViewData->GetDocument();
550 SCTAB nTab = pViewData->GetTabNo();
551 ScDPObject* pDPObj = pDoc->GetDPAtCursor(nCol, nRow, nTab);
552 if ( pDPObj && nCol > 0 )
554 // look for the dimension header left of the drop-down arrow
555 sal_uInt16 nOrient = sheet::DataPilotFieldOrientation_HIDDEN;
556 long nField = pDPObj->GetHeaderDim( ScAddress( nCol-1, nRow, nTab ), nOrient );
557 if ( nField >= 0 && nOrient == sheet::DataPilotFieldOrientation_PAGE )
559 ScDPSaveData aSaveData( *pDPObj->GetSaveData() );
561 bool bIsDataLayout;
562 OUString aDimName = pDPObj->GetDimName( nField, bIsDataLayout );
563 if ( !bIsDataLayout )
565 ScDPSaveDimension* pDim = aSaveData.GetDimensionByName(aDimName);
567 if ( bHasSelection )
569 const ::rtl::OUString aName = rStr;
570 pDim->SetCurrentPage( &aName );
572 else
573 pDim->SetCurrentPage( NULL );
575 ScDPObject aNewObj( *pDPObj );
576 aNewObj.SetSaveData( aSaveData );
577 ScDBDocFunc aFunc( *pViewData->GetDocShell() );
578 aFunc.DataPilotUpdate( pDPObj, &aNewObj, sal_True, false );
579 pViewData->GetView()->CursorPosChanged(); // shells may be switched
585 namespace {
587 struct AutoFilterData : public ScCheckListMenuWindow::ExtendedData
589 ScAddress maPos;
590 ScDBData* mpData;
593 class AutoFilterAction : public ScMenuFloatingWindow::Action
595 ScGridWindow* mpWindow;
596 ScGridWindow::AutoFilterMode meMode;
597 public:
598 AutoFilterAction(ScGridWindow* p, ScGridWindow::AutoFilterMode eMode) :
599 mpWindow(p), meMode(eMode) {}
600 virtual void execute()
602 mpWindow->UpdateAutoFilterFromMenu(meMode);
606 class AutoFilterPopupEndAction : public ScMenuFloatingWindow::Action
608 ScGridWindow* mpWindow;
609 ScAddress maPos;
610 public:
611 AutoFilterPopupEndAction(ScGridWindow* p, const ScAddress& rPos) :
612 mpWindow(p), maPos(rPos) {}
613 virtual void execute()
615 mpWindow->RefreshAutoFilterButton(maPos);
619 class AddItemToEntry : public std::unary_function<rtl::OUString, void>
621 ScQueryEntry::QueryItemsType& mrItems;
622 public:
623 AddItemToEntry(ScQueryEntry::QueryItemsType& rItems) : mrItems(rItems) {}
624 void operator() (const rtl::OUString& rSelected)
626 ScQueryEntry::Item aNew;
627 aNew.maString = rSelected;
628 aNew.meType = ScQueryEntry::ByString;
629 aNew.mfVal = 0.0;
630 mrItems.push_back(aNew);
634 class AddSelectedItemString : public std::unary_function<ScQueryEntry::Item, void>
636 boost::unordered_set<rtl::OUString, rtl::OUStringHash>& mrSet;
637 public:
638 AddSelectedItemString(boost::unordered_set<rtl::OUString, rtl::OUStringHash>& r) :
639 mrSet(r) {}
641 void operator() (const ScQueryEntry::Item& rItem)
643 mrSet.insert(rItem.maString);
649 void ScGridWindow::LaunchAutoFilterMenu(SCCOL nCol, SCROW nRow)
651 SCTAB nTab = pViewData->GetTabNo();
652 ScDocument* pDoc = pViewData->GetDocument();
654 mpAutoFilterPopup.reset(new ScCheckListMenuWindow(this, pDoc));
655 mpAutoFilterPopup->setOKAction(new AutoFilterAction(this, Normal));
656 mpAutoFilterPopup->setPopupEndAction(
657 new AutoFilterPopupEndAction(this, ScAddress(nCol, nRow, nTab)));
658 std::auto_ptr<AutoFilterData> pData(new AutoFilterData);
659 pData->maPos = ScAddress(nCol, nRow, nTab);
661 Point aPos = pViewData->GetScrPos(nCol, nRow, eWhich);
662 long nSizeX = 0;
663 long nSizeY = 0;
664 pViewData->GetMergeSizePixel(nCol, nRow, nSizeX, nSizeY);
665 Rectangle aCellRect(OutputToScreenPixel(aPos), Size(nSizeX, nSizeY));
667 ScDBData* pDBData = pDoc->GetDBAtCursor(nCol, nRow, nTab);
668 if (!pDBData)
669 return;
671 pData->mpData = pDBData;
672 mpAutoFilterPopup->setExtendedData(pData.release());
674 ScQueryParam aParam;
675 pDBData->GetQueryParam(aParam);
676 ScQueryEntry* pEntry = aParam.FindEntryByField(nCol, false);
677 boost::unordered_set<rtl::OUString, rtl::OUStringHash> aSelected;
678 if (pEntry && pEntry->bDoQuery)
680 if (pEntry->eOp == SC_EQUAL)
682 ScQueryEntry::QueryItemsType& rItems = pEntry->GetQueryItems();
683 std::for_each(rItems.begin(), rItems.end(), AddSelectedItemString(aSelected));
687 // Populate the check box list.
688 bool bHasDates = false;
689 std::vector<ScTypedStrData> aStrings;
690 pDoc->GetFilterEntries(nCol, nRow, nTab, true, aStrings, bHasDates);
692 mpAutoFilterPopup->setMemberSize(aStrings.size());
693 std::vector<ScTypedStrData>::const_iterator it = aStrings.begin(), itEnd = aStrings.end();
694 for (; it != itEnd; ++it)
696 const rtl::OUString& aVal = it->GetString();
697 bool bSelected = true;
698 if (!aSelected.empty())
699 bSelected = aSelected.count(aVal) > 0;
700 mpAutoFilterPopup->addMember(aVal, bSelected);
702 mpAutoFilterPopup->initMembers();
704 // Populate the menu.
705 mpAutoFilterPopup->addMenuItem(
706 ScRscStrLoader(RID_POPUP_FILTER, STR_MENU_SORT_ASC).GetString(),
707 true, new AutoFilterAction(this, SortAscending));
708 mpAutoFilterPopup->addMenuItem(
709 ScRscStrLoader(RID_POPUP_FILTER, STR_MENU_SORT_DESC).GetString(),
710 true, new AutoFilterAction(this, SortDescending));
711 mpAutoFilterPopup->addSeparator();
712 mpAutoFilterPopup->addMenuItem(
713 SC_RESSTR(SCSTR_TOP10FILTER), true, new AutoFilterAction(this, Top10));
714 mpAutoFilterPopup->addMenuItem(
715 SC_RESSTR(SCSTR_FILTER_EMPTY), true, new AutoFilterAction(this, Empty));
716 mpAutoFilterPopup->addMenuItem(
717 SC_RESSTR(SCSTR_FILTER_NOTEMPTY), true, new AutoFilterAction(this, NonEmpty));
718 mpAutoFilterPopup->addSeparator();
719 mpAutoFilterPopup->addMenuItem(
720 SC_RESSTR(SCSTR_STDFILTER), true, new AutoFilterAction(this, Custom));
722 ScCheckListMenuWindow::Config aConfig;
723 aConfig.mbAllowEmptySet = false;
724 aConfig.mbRTL = pViewData->GetDocument()->IsLayoutRTL(pViewData->GetTabNo());
725 mpAutoFilterPopup->setConfig(aConfig);
726 mpAutoFilterPopup->launch(aCellRect);
729 void ScGridWindow::RefreshAutoFilterButton(const ScAddress& rPos)
731 if (mpFilterButton)
733 bool bFilterActive = IsAutoFilterActive(rPos.Col(), rPos.Row(), rPos.Tab());
734 mpFilterButton->setHasHiddenMember(bFilterActive);
735 mpFilterButton->setPopupPressed(false);
736 mpFilterButton->draw();
740 void ScGridWindow::UpdateAutoFilterFromMenu(AutoFilterMode eMode)
742 const AutoFilterData* pData =
743 static_cast<const AutoFilterData*>(mpAutoFilterPopup->getExtendedData());
745 if (!pData)
746 return;
748 const ScAddress& rPos = pData->maPos;
749 ScDBData* pDBData = pData->mpData;
750 if (!pDBData)
751 return;
753 switch (eMode)
755 case SortAscending:
756 case SortDescending:
758 ScDocument* pDoc = pViewData->GetDocument();
759 SCTAB nTab = pViewData->GetTabNo();
760 SCCOL nCol = rPos.Col();
761 ScSortParam aSortParam;
762 pDBData->GetSortParam(aSortParam);
763 if (nCol < aSortParam.nCol1 || nCol > aSortParam.nCol2)
764 // out of bound
765 return;
767 bool bHasHeader = pDoc->HasColHeader(
768 aSortParam.nCol1, aSortParam.nRow1, aSortParam.nCol2, aSortParam.nRow2, nTab);
770 aSortParam.bHasHeader = bHasHeader;
771 aSortParam.bByRow = true;
772 aSortParam.bCaseSens = false;
773 aSortParam.bNaturalSort = false;
774 aSortParam.bIncludePattern = true;
775 aSortParam.bInplace = true;
776 aSortParam.maKeyState[0].bDoSort = true;
777 aSortParam.maKeyState[0].nField = nCol;
778 aSortParam.maKeyState[0].bAscending = (eMode == SortAscending);
780 for (size_t i = 1; i < aSortParam.GetSortKeyCount(); ++i)
781 aSortParam.maKeyState[i].bDoSort = false;
783 pViewData->GetViewShell()->UISort(aSortParam);
784 return;
786 default:
790 if (eMode == Custom)
792 ScRange aRange;
793 pDBData->GetArea(aRange);
794 pViewData->GetView()->MarkRange(aRange);
795 pViewData->GetView()->SetCursor(rPos.Col(), rPos.Row());
796 pViewData->GetDispatcher().Execute(SID_FILTER, SFX_CALLMODE_SLOT|SFX_CALLMODE_RECORD);
797 return;
800 ScQueryParam aParam;
801 pDBData->GetQueryParam(aParam);
803 if (eMode == Normal && mpAutoFilterPopup->isAllSelected())
805 // Remove this entry.
806 aParam.RemoveEntryByField(rPos.Col());
808 else
810 // Try to use the existing entry for the column (if one exists).
811 ScQueryEntry* pEntry = aParam.FindEntryByField(rPos.Col(), true);
813 if (!pEntry)
814 // Something went terribly wrong!
815 return;
817 pEntry->bDoQuery = true;
818 pEntry->nField = rPos.Col();
819 pEntry->eConnect = SC_AND;
821 switch (eMode)
823 case Normal:
825 pEntry->eOp = SC_EQUAL;
827 ScCheckListMenuWindow::ResultType aResult;
828 mpAutoFilterPopup->getResult(aResult);
829 std::vector<rtl::OUString> aSelected;
830 ScCheckListMenuWindow::ResultType::const_iterator itr = aResult.begin(), itrEnd = aResult.end();
831 for (; itr != itrEnd; ++itr)
833 if (itr->second)
834 aSelected.push_back(itr->first);
837 ScQueryEntry::QueryItemsType& rItems = pEntry->GetQueryItems();
838 rItems.clear();
839 std::for_each(aSelected.begin(), aSelected.end(), AddItemToEntry(rItems));
841 break;
842 case Top10:
843 pEntry->eOp = SC_TOPVAL;
844 pEntry->GetQueryItem().meType = ScQueryEntry::ByString;
845 pEntry->GetQueryItem().maString = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("10"));
846 break;
847 case Empty:
848 pEntry->SetQueryByEmpty();
849 break;
850 case NonEmpty:
851 pEntry->SetQueryByNonEmpty();
852 break;
853 default:
854 // We don't know how to handle this!
855 return;
859 pViewData->GetView()->Query(aParam, NULL, true);
860 pDBData->SetQueryParam(aParam);
863 namespace {
865 void getCellGeometry(Point& rScrPos, Size& rScrSize, const ScViewData* pViewData, SCCOL nCol, SCROW nRow, ScSplitPos eWhich)
867 // Get the screen position of the cell.
868 rScrPos = pViewData->GetScrPos(nCol, nRow, eWhich);
870 // Get the screen size of the cell.
871 long nSizeX, nSizeY;
872 pViewData->GetMergeSizePixel(nCol, nRow, nSizeX, nSizeY);
873 rScrSize = Size(nSizeX-1, nSizeY-1);
878 void ScGridWindow::LaunchPageFieldMenu( SCCOL nCol, SCROW nRow )
880 if (nCol == 0)
881 // We assume that the page field button is located in cell to the immediate left.
882 return;
884 SCTAB nTab = pViewData->GetTabNo();
885 ScDPObject* pDPObj = pViewData->GetDocument()->GetDPAtCursor(nCol, nRow, nTab);
886 if (!pDPObj)
887 return;
889 Point aScrPos;
890 Size aScrSize;
891 getCellGeometry(aScrPos, aScrSize, pViewData, nCol, nRow, eWhich);
892 DPLaunchFieldPopupMenu(OutputToScreenPixel(aScrPos), aScrSize, ScAddress(nCol-1, nRow, nTab), pDPObj);
895 void ScGridWindow::LaunchDPFieldMenu( SCCOL nCol, SCROW nRow )
897 SCTAB nTab = pViewData->GetTabNo();
898 ScDPObject* pDPObj = pViewData->GetDocument()->GetDPAtCursor(nCol, nRow, nTab);
899 if (!pDPObj)
900 return;
902 Point aScrPos;
903 Size aScrSize;
904 getCellGeometry(aScrPos, aScrSize, pViewData, nCol, nRow, eWhich);
905 DPLaunchFieldPopupMenu(OutputToScreenPixel(aScrPos), aScrSize, ScAddress(nCol, nRow, nTab), pDPObj);
908 void ScGridWindow::DoScenarioMenue( const ScRange& rScenRange )
910 delete pFilterBox;
911 delete pFilterFloat;
913 SCCOL nCol = rScenRange.aEnd.Col(); // Zelle unterhalb des Buttons
914 SCROW nRow = rScenRange.aStart.Row();
915 if (nRow == 0)
917 nRow = rScenRange.aEnd.Row() + 1; // Bereich ganz oben -> Button unterhalb
918 if (nRow>MAXROW) nRow = MAXROW;
919 //! Texthoehe addieren (wenn sie an der View gespeichert ist...)
922 ScDocument* pDoc = pViewData->GetDocument();
923 SCTAB nTab = pViewData->GetTabNo();
924 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
926 long nSizeX = 0;
927 long nSizeY = 0;
928 long nHeight = 0;
929 pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
930 // The button height should not use the merged cell height, should still use single row height
931 nSizeY = pViewData->ToPixel(pDoc->GetRowHeight(nRow, nTab), pViewData->GetPPTY());
932 Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich );
933 if ( bLayoutRTL )
934 aPos.X() -= nSizeX;
935 Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) );
936 aCellRect.Top() -= nSizeY;
937 aCellRect.Bottom() -= nSizeY - 1;
938 // Die ListBox direkt unter der schwarzen Linie auf dem Zellgitter
939 // (wenn die Linie verdeckt wird, sieht es komisch aus...)
941 pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) ); // nicht resizable etc.
942 pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) );
943 pFilterBox = new ScFilterListBox( pFilterFloat, this, nCol, nRow, SC_FILTERBOX_SCENARIO );
944 if ( bLayoutRTL )
945 pFilterBox->EnableMirroring();
947 nSizeX += 1;
950 Font aOldFont = GetFont(); SetFont( pFilterBox->GetFont() );
951 MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL );
953 nHeight = GetTextHeight();
954 nHeight *= SC_FILTERLISTBOX_LINES;
956 SetMapMode( aOldMode );
957 SetFont( aOldFont );
960 // SetSize spaeter
962 // ParentSize Abfrage fehlt
963 Size aSize( nSizeX, nHeight );
964 pFilterBox->SetSizePixel( aSize );
965 pFilterBox->Show(); // Show muss vor SetUpdateMode kommen !!!
966 pFilterBox->SetUpdateMode(false);
968 // SetOutputSizePixel/StartPopupMode erst unten, wenn die Groesse feststeht
970 // Listbox fuellen
972 long nMaxText = 0;
973 rtl::OUString aCurrent;
974 rtl::OUString aTabName;
975 SCTAB nTabCount = pDoc->GetTableCount();
976 SCTAB nEntryCount = 0;
977 for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
979 if (pDoc->HasScenarioRange( i, rScenRange ))
980 if (pDoc->GetName( i, aTabName ))
982 pFilterBox->InsertEntry( aTabName );
983 if (pDoc->IsActiveScenario(i))
984 aCurrent = aTabName;
985 long nTextWidth = pFilterBox->GetTextWidth( aTabName );
986 if ( nTextWidth > nMaxText )
987 nMaxText = nTextWidth;
988 ++nEntryCount;
991 if (nEntryCount > SC_FILTERLISTBOX_LINES)
992 nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize();
993 nMaxText += 4; // fuer Rand
994 if ( nMaxText > 300 )
995 nMaxText = 300; // auch nicht uebertreiben (Pixel)
997 if (nMaxText > nSizeX) // Groesse auf benoetigte Groesse anpassen
999 long nDiff = nMaxText - nSizeX;
1000 aSize = Size( nMaxText, nHeight );
1001 pFilterBox->SetSizePixel( aSize );
1002 pFilterFloat->SetOutputSizePixel( aSize );
1004 if ( !bLayoutRTL )
1006 // also move popup position
1007 long nNewX = aCellRect.Left() - nDiff;
1008 if ( nNewX < 0 )
1009 nNewX = 0;
1010 aCellRect.Left() = nNewX;
1014 pFilterFloat->SetOutputSizePixel( aSize );
1015 pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS );
1017 pFilterBox->SetUpdateMode(sal_True);
1018 pFilterBox->GrabFocus();
1020 sal_uInt16 nPos = LISTBOX_ENTRY_NOTFOUND;
1021 if (!aCurrent.isEmpty())
1023 nPos = pFilterBox->GetEntryPos(String(aCurrent));
1025 if (LISTBOX_ENTRY_NOTFOUND == nPos && pFilterBox->GetEntryCount() > 0 )
1026 nPos = 0;
1027 if (LISTBOX_ENTRY_NOTFOUND != nPos )
1028 pFilterBox->SelectEntryPos(nPos);
1030 pFilterBox->EndInit();
1032 // Szenario-Auswahl kommt aus MouseButtonDown:
1033 // der naechste MouseMove auf die Filterbox ist wie ein ButtonDown
1035 nMouseStatus = SC_GM_FILTER;
1036 CaptureMouse();
1039 void ScGridWindow::LaunchDataSelectMenu( SCCOL nCol, SCROW nRow, bool bDataSelect )
1041 delete pFilterBox;
1042 delete pFilterFloat;
1044 sal_uInt16 i;
1045 ScDocument* pDoc = pViewData->GetDocument();
1046 SCTAB nTab = pViewData->GetTabNo();
1047 bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1049 long nSizeX = 0;
1050 long nSizeY = 0;
1051 long nHeight = 0;
1052 pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
1053 Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich );
1054 if ( bLayoutRTL )
1055 aPos.X() -= nSizeX;
1057 Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) );
1059 aPos.X() -= 1;
1060 aPos.Y() += nSizeY - 1;
1062 pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) ); // nicht resizable etc.
1063 pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) );
1064 pFilterBox = new ScFilterListBox(
1065 pFilterFloat, this, nCol, nRow, bDataSelect ? SC_FILTERBOX_DATASELECT : SC_FILTERBOX_FILTER );
1066 // Fix for bug fdo#44925
1067 if (Application::GetSettings().GetLayoutRTL() != bLayoutRTL)
1068 pFilterBox->EnableMirroring();
1070 nSizeX += 1;
1073 Font aOldFont = GetFont(); SetFont( pFilterBox->GetFont() );
1074 MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL );
1076 nHeight = GetTextHeight();
1077 nHeight *= SC_FILTERLISTBOX_LINES;
1079 SetMapMode( aOldMode );
1080 SetFont( aOldFont );
1083 // SetSize spaeter
1085 bool bEmpty = false;
1086 std::vector<ScTypedStrData> aStrings; // case sensitive
1087 if ( bDataSelect ) // Auswahl-Liste
1089 // Liste fuellen
1090 pDoc->GetDataEntries(nCol, nRow, nTab, true, aStrings);
1091 if (aStrings.empty())
1092 bEmpty = true;
1094 else // AutoFilter
1096 //! wird der Titel ueberhaupt ausgewertet ???
1097 String aString;
1098 pDoc->GetString( nCol, nRow, nTab, aString );
1099 pFilterBox->SetText( aString );
1101 long nMaxText = 0;
1103 // default entries
1104 static const sal_uInt16 nDefIDs[] = { SCSTR_TOP10FILTER, SCSTR_STDFILTER, SCSTR_FILTER_EMPTY, SCSTR_FILTER_NOTEMPTY };
1105 const size_t nDefCount = SAL_N_ELEMENTS(nDefIDs);
1106 for (i=0; i<nDefCount; i++)
1108 String aEntry( (ScResId) nDefIDs[i] );
1109 pFilterBox->InsertEntry( aEntry );
1110 long nTextWidth = pFilterBox->GetTextWidth( aEntry );
1111 if ( nTextWidth > nMaxText )
1112 nMaxText = nTextWidth;
1114 pFilterBox->SetSeparatorPos( nDefCount - 1 );
1116 // get list entries
1117 bool bHasDates = false;
1118 pDoc->GetFilterEntries( nCol, nRow, nTab, true, aStrings, bHasDates);
1119 pFilterBox->SetListHasDates(bHasDates);
1121 // check widths of numerical entries (string entries are not included)
1122 // so all numbers are completely visible
1123 std::vector<ScTypedStrData>::const_iterator it = aStrings.begin(), itEnd = aStrings.end();
1124 for (; it != itEnd; ++it)
1126 if (!it->IsStrData()) // only numerical entries
1128 long nTextWidth = pFilterBox->GetTextWidth(it->GetString());
1129 if ( nTextWidth > nMaxText )
1130 nMaxText = nTextWidth;
1134 // add scrollbar width if needed (string entries are counted here)
1135 // (scrollbar is shown if the box is exactly full?)
1136 if (aStrings.size() + nDefCount >= SC_FILTERLISTBOX_LINES)
1137 nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize();
1139 nMaxText += 4; // for borders
1141 if ( nMaxText > nSizeX )
1142 nSizeX = nMaxText; // just modify width - starting position is unchanged
1145 if (!bEmpty)
1147 // Position und Groesse an Fenster anpassen
1148 //! vorher Abfrage, ob die Eintraege hineinpassen (Breite)
1150 Size aParentSize = GetParent()->GetOutputSizePixel();
1151 Size aSize( nSizeX, nHeight );
1153 if ( aSize.Height() > aParentSize.Height() )
1154 aSize.Height() = aParentSize.Height();
1155 if ( aPos.Y() + aSize.Height() > aParentSize.Height() )
1156 aPos.Y() = aParentSize.Height() - aSize.Height();
1158 pFilterBox->SetSizePixel( aSize );
1159 pFilterBox->Show(); // Show muss vor SetUpdateMode kommen !!!
1160 pFilterBox->SetUpdateMode(false);
1162 pFilterFloat->SetOutputSizePixel( aSize );
1163 pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS);
1165 // Listbox fuellen
1166 bool bWait = aStrings.size() > 100;
1168 if (bWait)
1169 EnterWait();
1171 std::vector<ScTypedStrData>::const_iterator it = aStrings.begin(), itEnd = aStrings.end();
1172 for (; it != itEnd; ++it)
1173 pFilterBox->InsertEntry(it->GetString());
1175 if (bWait)
1176 LeaveWait();
1178 pFilterBox->SetUpdateMode(true);
1181 sal_uInt16 nSelPos = LISTBOX_ENTRY_NOTFOUND;
1183 if (!bDataSelect) // AutoFilter: aktiven Eintrag selektieren
1185 ScDBData* pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab );
1186 if (pDBData)
1188 ScQueryParam aParam;
1189 pDBData->GetQueryParam( aParam ); // kann nur MAXQUERY Eintraege ergeben
1191 sal_Bool bValid = sal_True;
1192 SCSIZE nCount = aParam.GetEntryCount();
1193 for (SCSIZE j = 0; j < nCount && bValid; ++j) // bisherige Filter-Einstellungen
1194 if (aParam.GetEntry(j).bDoQuery)
1196 //! Abfrage mit DrawButtons zusammenfassen!
1198 ScQueryEntry& rEntry = aParam.GetEntry(j);
1199 if (j>0)
1200 if (rEntry.eConnect != SC_AND)
1201 bValid = false;
1202 if (rEntry.nField == nCol)
1204 const rtl::OUString& rQueryStr = rEntry.GetQueryItem().maString;
1205 if (rEntry.eOp == SC_EQUAL)
1207 if (!rQueryStr.isEmpty())
1209 nSelPos = pFilterBox->GetEntryPos(rQueryStr);
1212 else if ( rEntry.eOp == SC_TOPVAL && rQueryStr == "10" )
1213 nSelPos = SC_AUTOFILTER_TOP10;
1214 else
1215 nSelPos = SC_AUTOFILTER_CUSTOM;
1219 if (!bValid)
1220 nSelPos = SC_AUTOFILTER_CUSTOM;
1223 else
1226 sal_uLong nIndex = ((SfxUInt32Item*)pDoc->GetAttr(
1227 nCol, nRow, nTab, ATTR_VALIDDATA ))->GetValue();
1228 if ( nIndex )
1230 const ScValidationData* pData = pDoc->GetValidationEntry( nIndex );
1231 if (pData)
1233 ScTypedStrData* pNew = NULL;
1234 rtl::OUString aDocStr;
1235 pDoc->GetString( nCol, nRow, nTab, aDocStr );
1236 if ( pDoc->HasValueData( nCol, nRow, nTab ) )
1238 double fVal = pDoc->GetValue(ScAddress(nCol, nRow, nTab));
1239 pNew = new ScTypedStrData(aDocStr, fVal, ScTypedStrData::Value);
1241 else
1242 pNew = new ScTypedStrData(aDocStr, 0.0, ScTypedStrData::Standard);
1244 bool bSortList = ( pData->GetListType() == ValidListType::SORTEDASCENDING);
1245 if ( bSortList )
1247 std::vector<ScTypedStrData>::const_iterator itBeg = aStrings.begin(), itEnd = aStrings.end();
1248 std::vector<ScTypedStrData>::const_iterator it =
1249 std::find_if(itBeg, itEnd, FindTypedStrData(*pNew, true));
1250 if (it != itEnd)
1251 // Found!
1252 nSelPos = std::distance(itBeg, it);
1254 else
1256 ScTypedStrData::EqualCaseSensitive aHdl;
1257 std::vector<ScTypedStrData>::const_iterator itBeg = aStrings.begin(), itEnd = aStrings.end();
1258 std::vector<ScTypedStrData>::const_iterator it = itBeg;
1259 for (; it != itEnd && LISTBOX_ENTRY_NOTFOUND == nSelPos; ++it)
1261 if (aHdl(*it, *pNew))
1262 nSelPos = std::distance(itBeg, it);
1265 delete pNew;
1270 // neu (309): irgendwas muss immer selektiert sein:
1271 if ( LISTBOX_ENTRY_NOTFOUND == nSelPos && pFilterBox->GetEntryCount() > 0 && !bDataSelect)
1272 nSelPos = 0;
1274 // keine leere Auswahl-Liste anzeigen:
1276 if ( bEmpty )
1278 DELETEZ(pFilterBox); // war nix
1279 DELETEZ(pFilterFloat);
1281 else
1283 pFilterBox->GrabFocus();
1285 // Select erst nach GrabFocus, damit das Focus-Rechteck richtig landet
1286 if ( LISTBOX_ENTRY_NOTFOUND != nSelPos )
1287 pFilterBox->SelectEntryPos( nSelPos );
1288 else
1290 if (bDataSelect)
1291 pFilterBox->SetNoSelection();
1294 pFilterBox->EndInit();
1296 if (!bDataSelect)
1298 // AutoFilter (aus MouseButtonDown):
1299 // der naechste MouseMove auf die Filterbox ist wie ein ButtonDown
1301 nMouseStatus = SC_GM_FILTER;
1302 CaptureMouse();
1307 void ScGridWindow::FilterSelect( sal_uLong nSel )
1309 String aString = pFilterBox->GetEntry( static_cast< sal_uInt16 >( nSel ) );
1311 SCCOL nCol = pFilterBox->GetCol();
1312 SCROW nRow = pFilterBox->GetRow();
1313 switch ( pFilterBox->GetMode() )
1315 case SC_FILTERBOX_DATASELECT:
1316 ExecDataSelect( nCol, nRow, aString );
1317 break;
1318 case SC_FILTERBOX_FILTER:
1319 ExecFilter( nSel, nCol, nRow, aString, pFilterBox->HasDates() );
1320 break;
1321 case SC_FILTERBOX_SCENARIO:
1322 pViewData->GetView()->UseScenario( aString );
1323 break;
1324 case SC_FILTERBOX_PAGEFIELD:
1325 // first entry is "all"
1326 ExecPageFieldSelect( nCol, nRow, (nSel != 0), aString );
1327 break;
1330 if (pFilterFloat)
1331 pFilterFloat->EndPopupMode();
1333 GrabFocus(); // unter OS/2 stimmt der Focus sonst nicht
1336 void ScGridWindow::ExecDataSelect( SCCOL nCol, SCROW nRow, const String& rStr )
1338 if ( rStr.Len() )
1340 SCTAB nTab = pViewData->GetTabNo();
1341 ScViewFunc* pView = pViewData->GetView();
1342 pView->EnterData( nCol, nRow, nTab, rStr );
1344 // #i52307# CellContentChanged is not in EnterData so it isn't called twice
1345 // if the cursor is moved afterwards.
1346 pView->CellContentChanged();
1350 void ScGridWindow::ExecFilter( sal_uLong nSel,
1351 SCCOL nCol, SCROW nRow,
1352 const String& aValue, bool bCheckForDates )
1354 SCTAB nTab = pViewData->GetTabNo();
1355 ScDocument* pDoc = pViewData->GetDocument();
1357 ScDBData* pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab );
1358 if (pDBData)
1360 ScQueryParam aParam;
1361 pDBData->GetQueryParam( aParam ); // kann nur MAXQUERY Eintraege ergeben
1363 if (SC_AUTOFILTER_CUSTOM == nSel)
1365 SCTAB nAreaTab;
1366 SCCOL nStartCol;
1367 SCROW nStartRow;
1368 SCCOL nEndCol;
1369 SCROW nEndRow;
1370 pDBData->GetArea( nAreaTab, nStartCol,nStartRow,nEndCol,nEndRow );
1371 pViewData->GetView()->MarkRange( ScRange( nStartCol,nStartRow,nAreaTab,nEndCol,nEndRow,nAreaTab));
1372 pViewData->GetView()->SetCursor(nCol,nRow); //! auch ueber Slot ??
1373 pViewData->GetDispatcher().Execute( SID_FILTER, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD );
1375 else
1377 sal_Bool bDeleteOld = false;
1378 SCSIZE nQueryPos = 0;
1379 sal_Bool bFound = false;
1380 if (!aParam.bInplace)
1381 bDeleteOld = sal_True;
1382 if (aParam.bRegExp)
1383 bDeleteOld = sal_True;
1384 SCSIZE nCount = aParam.GetEntryCount();
1385 for (SCSIZE i = 0; i < nCount && !bDeleteOld; ++i) // bisherige Filter-Einstellungen
1386 if (aParam.GetEntry(i).bDoQuery)
1388 //! Abfrage mit DrawButtons zusammenfassen!
1390 ScQueryEntry& rEntry = aParam.GetEntry(i);
1391 if (i>0)
1392 if (rEntry.eConnect != SC_AND)
1393 bDeleteOld = sal_True;
1395 if (rEntry.nField == nCol)
1397 if (bFound) // diese Spalte zweimal?
1398 bDeleteOld = sal_True;
1399 nQueryPos = i;
1400 bFound = sal_True;
1402 if (!bFound)
1403 nQueryPos = i + 1;
1406 if (bDeleteOld)
1408 SCSIZE nEC = aParam.GetEntryCount();
1409 for (SCSIZE i=0; i<nEC; i++)
1410 aParam.GetEntry(i).Clear();
1411 nQueryPos = 0;
1412 aParam.bInplace = sal_True;
1413 aParam.bRegExp = false;
1416 if ( nQueryPos < nCount || SC_AUTOFILTER_ALL == nSel ) // loeschen geht immer
1418 if (nSel)
1420 ScQueryEntry& rNewEntry = aParam.GetEntry(nQueryPos);
1421 ScQueryEntry::Item& rItem = rNewEntry.GetQueryItem();
1422 rNewEntry.bDoQuery = true;
1423 rNewEntry.nField = nCol;
1424 rItem.meType = bCheckForDates ? ScQueryEntry::ByDate : ScQueryEntry::ByString;
1426 if ( nSel == SC_AUTOFILTER_TOP10 )
1428 rNewEntry.eOp = SC_TOPVAL;
1429 rItem.maString = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("10"));
1431 else if (nSel == SC_AUTOFILTER_EMPTY)
1433 rNewEntry.SetQueryByEmpty();
1435 else if (nSel == SC_AUTOFILTER_NOTEMPTY)
1437 rNewEntry.SetQueryByNonEmpty();
1439 else
1441 rNewEntry.eOp = SC_EQUAL;
1442 rItem.maString = aValue;
1444 if (nQueryPos > 0)
1445 rNewEntry.eConnect = SC_AND;
1447 else
1449 if (bFound)
1450 aParam.RemoveEntryByField(nCol);
1453 // end edit mode - like in ScCellShell::ExecuteDB
1454 if ( pViewData->HasEditView( pViewData->GetActivePart() ) )
1456 SC_MOD()->InputEnterHandler();
1457 pViewData->GetViewShell()->UpdateInputHandler();
1460 pViewData->GetView()->Query( aParam, NULL, true );
1461 pDBData->SetQueryParam( aParam ); // speichern
1463 else // "Zuviele Bedingungen"
1464 pViewData->GetView()->ErrorMessage( STR_FILTER_TOOMANY );
1467 else
1469 OSL_FAIL("Wo ist der Datenbankbereich?");
1473 void ScGridWindow::SetPointer( const Pointer& rPointer )
1475 nCurrentPointer = 0;
1476 Window::SetPointer( rPointer );
1479 void ScGridWindow::MoveMouseStatus( ScGridWindow& rDestWin )
1481 if (nButtonDown)
1483 rDestWin.nButtonDown = nButtonDown;
1484 rDestWin.nMouseStatus = nMouseStatus;
1487 if (bRFMouse)
1489 rDestWin.bRFMouse = bRFMouse;
1490 rDestWin.bRFSize = bRFSize;
1491 rDestWin.nRFIndex = nRFIndex;
1492 rDestWin.nRFAddX = nRFAddX;
1493 rDestWin.nRFAddY = nRFAddY;
1494 bRFMouse = false;
1497 if (nPagebreakMouse)
1499 rDestWin.nPagebreakMouse = nPagebreakMouse;
1500 rDestWin.nPagebreakBreak = nPagebreakBreak;
1501 rDestWin.nPagebreakPrev = nPagebreakPrev;
1502 rDestWin.aPagebreakSource = aPagebreakSource;
1503 rDestWin.aPagebreakDrag = aPagebreakDrag;
1504 nPagebreakMouse = SC_PD_NONE;
1508 bool ScGridWindow::TestMouse( const MouseEvent& rMEvt, bool bAction )
1510 // MouseEvent buttons must only be checked if bAction==TRUE
1511 // to allow changing the mouse pointer in MouseMove,
1512 // but not start AutoFill with right button (#74229#).
1513 // with bAction==sal_True, SetFillMode / SetDragMode is called
1515 if ( bAction && !rMEvt.IsLeft() )
1516 return false;
1518 bool bNewPointer = false;
1520 SfxInPlaceClient* pClient = pViewData->GetViewShell()->GetIPClient();
1521 bool bOleActive = ( pClient && pClient->IsObjectInPlaceActive() );
1523 if ( pViewData->IsActive() && !bOleActive )
1525 ScDocument* pDoc = pViewData->GetDocument();
1526 SCTAB nTab = pViewData->GetTabNo();
1527 bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1529 // Auto-Fill
1531 ScRange aMarkRange;
1532 if (pViewData->GetSimpleArea( aMarkRange ) == SC_MARK_SIMPLE)
1534 if (aMarkRange.aStart.Tab() == pViewData->GetTabNo() && mpAutoFillRect)
1536 Point aMousePos = rMEvt.GetPosPixel();
1537 if (mpAutoFillRect->IsInside(aMousePos))
1539 SetPointer( Pointer( POINTER_CROSS ) ); //! dickeres Kreuz ?
1540 if (bAction)
1542 SCCOL nX = aMarkRange.aEnd.Col();
1543 SCROW nY = aMarkRange.aEnd.Row();
1545 if ( lcl_IsEditableMatrix( pViewData->GetDocument(), aMarkRange ) )
1546 pViewData->SetDragMode(
1547 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nX, nY, SC_FILL_MATRIX );
1548 else
1549 pViewData->SetFillMode(
1550 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nX, nY );
1552 // The simple selection must also be recognized when dragging,
1553 // where the Marking flag is set and MarkToSimple won't work anymore.
1554 pViewData->GetMarkData().MarkToSimple();
1556 bNewPointer = true;
1561 // Embedded-Rechteck
1563 if (pDoc->IsEmbedded())
1565 ScRange aRange;
1566 pDoc->GetEmbedded( aRange );
1567 if ( pViewData->GetTabNo() == aRange.aStart.Tab() )
1569 Point aStartPos = pViewData->GetScrPos( aRange.aStart.Col(), aRange.aStart.Row(), eWhich );
1570 Point aEndPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aEnd.Row()+1, eWhich );
1571 Point aMousePos = rMEvt.GetPosPixel();
1572 if ( bLayoutRTL )
1574 aStartPos.X() += 2;
1575 aEndPos.X() += 2;
1577 bool bTop = ( aMousePos.X() >= aStartPos.X()-3 && aMousePos.X() <= aStartPos.X()+1 &&
1578 aMousePos.Y() >= aStartPos.Y()-3 && aMousePos.Y() <= aStartPos.Y()+1 );
1579 bool bBottom = ( aMousePos.X() >= aEndPos.X()-3 && aMousePos.X() <= aEndPos.X()+1 &&
1580 aMousePos.Y() >= aEndPos.Y()-3 && aMousePos.Y() <= aEndPos.Y()+1 );
1581 if ( bTop || bBottom )
1583 SetPointer( Pointer( POINTER_CROSS ) );
1584 if (bAction)
1586 sal_uInt8 nMode = bTop ? SC_FILL_EMBED_LT : SC_FILL_EMBED_RB;
1587 pViewData->SetDragMode(
1588 aRange.aStart.Col(), aRange.aStart.Row(),
1589 aRange.aEnd.Col(), aRange.aEnd.Row(), nMode );
1591 bNewPointer = true;
1597 if (!bNewPointer && bAction)
1599 pViewData->ResetFillMode();
1602 return bNewPointer;
1605 void ScGridWindow::MouseButtonDown( const MouseEvent& rMEvt )
1607 nNestedButtonState = SC_NESTEDBUTTON_DOWN;
1609 MouseEventState aState;
1610 HandleMouseButtonDown(rMEvt, aState);
1611 if (aState.mbActivatePart)
1612 pViewData->GetView()->ActivatePart(eWhich);
1614 if ( nNestedButtonState == SC_NESTEDBUTTON_UP )
1616 // #i41690# If an object is deactivated from MouseButtonDown, it might reschedule,
1617 // so MouseButtonUp comes before the MouseButtonDown call is finished. In this case,
1618 // simulate another MouseButtonUp call, so the selection state is consistent.
1620 nButtonDown = rMEvt.GetButtons();
1621 FakeButtonUp();
1623 if ( IsTracking() )
1624 EndTracking(); // normally done in VCL as part of MouseButtonUp handling
1626 nNestedButtonState = SC_NESTEDBUTTON_NONE;
1629 void ScGridWindow::HandleMouseButtonDown( const MouseEvent& rMEvt, MouseEventState& rState )
1631 // We have to check if a context menu is shown and we have an UI
1632 // active inplace client. In that case we have to ignore the event.
1633 // Otherwise we would crash (context menu has been
1634 // opened by inplace client and we would deactivate the inplace client,
1635 // the contex menu is closed by VCL asynchronously which in the end
1636 // would work on deleted objects or the context menu has no parent anymore)
1637 SfxViewShell* pViewSh = pViewData->GetViewShell();
1638 SfxInPlaceClient* pClient = pViewSh->GetIPClient();
1639 if ( pClient &&
1640 pClient->IsObjectInPlaceActive() &&
1641 PopupMenu::IsInExecute() )
1642 return;
1644 aCurMousePos = rMEvt.GetPosPixel();
1646 // Filter-Popup beendet sich mit eigenem Mausklick, nicht erst beim Klick
1647 // in das GridWindow, darum ist die folgende Abfrage nicht mehr noetig:
1648 ClickExtern(); // loescht FilterBox, wenn vorhanden
1650 HideNoteMarker(); // Notiz-Anzeige
1652 bEEMouse = false;
1654 ScModule* pScMod = SC_MOD();
1655 if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
1656 return;
1658 pScActiveViewShell = pViewData->GetViewShell(); // falls auf Link geklickt wird
1659 nScClickMouseModifier = rMEvt.GetModifier(); // um Control-Klick immer zu erkennen
1661 sal_Bool bDetective = pViewData->GetViewShell()->IsAuditShell();
1662 sal_Bool bRefMode = pViewData->IsRefMode(); // Referenz angefangen
1663 sal_Bool bFormulaMode = pScMod->IsFormulaMode(); // naechster Klick -> Referenz
1664 sal_Bool bEditMode = pViewData->HasEditView(eWhich); // auch bei Mode==SC_INPUT_TYPE
1665 sal_Bool bDouble = (rMEvt.GetClicks() == 2);
1667 // DeactivateIP passiert nur noch bei MarkListHasChanged
1669 // im GrabFocus Aufruf kann eine Fehlermeldung hochkommen
1670 // (z.B. beim Umbenennen von Tabellen per Tab-Reiter)
1672 if ( !nButtonDown || !bDouble ) // single (first) click is always valid
1673 nButtonDown = rMEvt.GetButtons(); // set nButtonDown first, so StopMarking works
1675 if ( ( bEditMode && pViewData->GetActivePart() == eWhich ) || !bFormulaMode )
1676 GrabFocus();
1678 // #i31846# need to cancel a double click if the first click has set the "ignore" state,
1679 // but a single (first) click is always valid
1680 if ( nMouseStatus == SC_GM_IGNORE && bDouble )
1682 nButtonDown = 0;
1683 nMouseStatus = SC_GM_NONE;
1684 return;
1687 if ( bDetective ) // Detektiv-Fuell-Modus
1689 if ( rMEvt.IsLeft() && !rMEvt.GetModifier() )
1691 Point aPos = rMEvt.GetPosPixel();
1692 SCsCOL nPosX;
1693 SCsROW nPosY;
1694 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
1696 SfxInt16Item aPosXItem( SID_RANGE_COL, nPosX );
1697 SfxInt32Item aPosYItem( SID_RANGE_ROW, nPosY );
1698 pViewData->GetDispatcher().Execute( SID_FILL_SELECT, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD,
1699 &aPosXItem, &aPosYItem, (void*)0L );
1702 nButtonDown = 0;
1703 nMouseStatus = SC_GM_NONE;
1704 return;
1707 if (!bDouble)
1708 nMouseStatus = SC_GM_NONE;
1710 rState.mbActivatePart = !bFormulaMode; // Don't activate when in formula mode.
1712 if (bFormulaMode)
1714 ScViewSelectionEngine* pSelEng = pViewData->GetView()->GetSelEngine();
1715 pSelEng->SetWindow(this);
1716 pSelEng->SetWhich(eWhich);
1717 pSelEng->SetVisibleArea( Rectangle(Point(), GetOutputSizePixel()) );
1720 if (bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()))
1722 Point aPos = rMEvt.GetPosPixel();
1723 SCsCOL nPosX;
1724 SCsROW nPosY;
1725 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
1727 EditView* pEditView;
1728 SCCOL nEditCol;
1729 SCROW nEditRow;
1730 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
1731 SCCOL nEndCol = pViewData->GetEditEndCol();
1732 SCROW nEndRow = pViewData->GetEditEndRow();
1734 if ( nPosX >= (SCsCOL) nEditCol && nPosX <= (SCsCOL) nEndCol &&
1735 nPosY >= (SCsROW) nEditRow && nPosY <= (SCsROW) nEndRow )
1737 // beim Klick in die Tabellen-EditView immer den Focus umsetzen
1738 if (bFormulaMode) // sonst ist es oben schon passiert
1739 GrabFocus();
1741 pScMod->SetInputMode( SC_INPUT_TABLE );
1742 bEEMouse = true;
1743 bEditMode = pEditView->MouseButtonDown( rMEvt );
1744 return;
1748 if (pScMod->GetIsWaterCan())
1750 //! was is mit'm Mac ???
1751 if ( rMEvt.GetModifier() + rMEvt.GetButtons() == MOUSE_RIGHT )
1753 nMouseStatus = SC_GM_WATERUNDO;
1754 return;
1758 // Reihenfolge passend zum angezeigten Cursor:
1759 // RangeFinder, AutoFill, PageBreak, Drawing
1761 bool bCorner;
1762 bool bFound = HitRangeFinder(rMEvt.GetPosPixel(), bCorner, &nRFIndex, &nRFAddX, &nRFAddY);
1763 bRFSize = bCorner;
1764 if (bFound)
1766 bRFMouse = true; // die anderen Variablen sind oben initialisiert
1768 rState.mbActivatePart = true; // always activate ?
1769 StartTracking();
1770 return;
1773 sal_Bool bCrossPointer = TestMouse( rMEvt, sal_True );
1774 if ( bCrossPointer )
1776 if ( bDouble )
1777 pViewData->GetView()->FillCrossDblClick();
1778 else
1779 pScMod->InputEnterHandler(); // Autofill etc.
1782 if ( !bCrossPointer )
1784 nPagebreakMouse = HitPageBreak( rMEvt.GetPosPixel(), &aPagebreakSource,
1785 &nPagebreakBreak, &nPagebreakPrev );
1786 if (nPagebreakMouse)
1788 bPagebreakDrawn = false;
1789 StartTracking();
1790 PagebreakMove( rMEvt, false );
1791 return;
1795 if (!bFormulaMode && !bEditMode && rMEvt.IsLeft())
1797 if ( !bCrossPointer && DrawMouseButtonDown(rMEvt) )
1799 return;
1802 pViewData->GetViewShell()->SetDrawShell( false ); // kein Draw-Objekt selektiert
1804 // TestMouse schon oben passiert
1807 Point aPos = rMEvt.GetPosPixel();
1808 SCsCOL nPosX;
1809 SCsROW nPosY;
1810 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
1811 SCTAB nTab = pViewData->GetTabNo();
1812 ScDocument* pDoc = pViewData->GetDocument();
1814 // Auto filter / pivot table / data select popup. This shouldn't activate the part.
1816 if ( !bDouble && !bFormulaMode && rMEvt.IsLeft() )
1818 SCsCOL nRealPosX;
1819 SCsROW nRealPosY;
1820 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nRealPosX, nRealPosY, false );//the real row/col
1821 ScMergeFlagAttr* pRealPosAttr = (ScMergeFlagAttr*)
1822 pDoc->GetAttr( nRealPosX, nRealPosY, nTab, ATTR_MERGE_FLAG );
1823 ScMergeFlagAttr* pAttr = (ScMergeFlagAttr*)
1824 pDoc->GetAttr( nPosX, nPosY, nTab, ATTR_MERGE_FLAG );
1825 if( pRealPosAttr->HasAutoFilter() )
1827 SC_MOD()->InputEnterHandler();
1828 if (DoAutoFilterButton( nRealPosX, nRealPosY, rMEvt))
1829 return;
1831 if (pAttr->HasAutoFilter())
1833 if (DoAutoFilterButton(nPosX, nPosY, rMEvt))
1835 rState.mbActivatePart = false;
1836 return;
1840 if (pAttr->HasPivotButton() || pAttr->HasPivotPopupButton())
1842 DoPushPivotButton(nPosX, nPosY, rMEvt, pAttr->HasPivotButton(), pAttr->HasPivotPopupButton());
1843 rState.mbActivatePart = false;
1844 return;
1847 // List Validity drop-down button
1849 if ( bListValButton )
1851 Rectangle aButtonRect = GetListValButtonRect( aListValPos );
1852 if ( aButtonRect.IsInside( aPos ) )
1854 LaunchDataSelectMenu( aListValPos.Col(), aListValPos.Row(), true );
1856 nMouseStatus = SC_GM_FILTER; // not set in DoAutoFilterMenue for bDataSelect
1857 CaptureMouse();
1858 rState.mbActivatePart = false;
1859 return;
1865 // scenario selection
1868 ScRange aScenRange;
1869 if ( rMEvt.IsLeft() && HasScenarioButton( aPos, aScenRange ) )
1871 DoScenarioMenue( aScenRange );
1872 return;
1876 // Doppelklick angefangen ?
1879 // StopMarking kann aus DrawMouseButtonDown gerufen werden
1881 if ( nMouseStatus != SC_GM_IGNORE && !bRefMode )
1883 if ( bDouble && !bCrossPointer )
1885 if (nMouseStatus == SC_GM_TABDOWN)
1886 nMouseStatus = SC_GM_DBLDOWN;
1888 else
1889 nMouseStatus = SC_GM_TABDOWN;
1893 // Links in Edit-Zellen
1896 sal_Bool bAlt = rMEvt.IsMod2();
1897 if ( !bAlt && rMEvt.IsLeft() &&
1898 GetEditUrl(rMEvt.GetPosPixel()) ) // Klick auf Link: Cursor nicht bewegen
1900 SetPointer( Pointer( POINTER_REFHAND ) );
1901 nMouseStatus = SC_GM_URLDOWN; // auch nur dann beim ButtonUp ausfuehren
1902 return;
1906 // Gridwin - SelectionEngine
1909 if ( rMEvt.IsLeft() )
1911 ScViewSelectionEngine* pSelEng = pViewData->GetView()->GetSelEngine();
1912 pSelEng->SetWindow(this);
1913 pSelEng->SetWhich(eWhich);
1914 pSelEng->SetVisibleArea( Rectangle(Point(), GetOutputSizePixel()) );
1916 // SelMouseButtonDown an der View setzt noch das bMoveIsShift Flag
1917 if ( pViewData->GetView()->SelMouseButtonDown( rMEvt ) )
1919 if (IsMouseCaptured())
1921 // Tracking statt CaptureMouse, damit sauber abgebrochen werden kann
1922 //! Irgendwann sollte die SelectionEngine selber StartTracking rufen!?!
1923 ReleaseMouse();
1924 StartTracking();
1926 pViewData->GetMarkData().SetMarking(sal_True);
1927 return;
1932 void ScGridWindow::MouseButtonUp( const MouseEvent& rMEvt )
1934 aCurMousePos = rMEvt.GetPosPixel();
1935 ScDocument* pDoc = pViewData->GetDocument();
1936 ScMarkData& rMark = pViewData->GetMarkData();
1938 // #i41690# detect a MouseButtonUp call from within MouseButtonDown
1939 // (possible through Reschedule from storing an OLE object that is deselected)
1941 if ( nNestedButtonState == SC_NESTEDBUTTON_DOWN )
1942 nNestedButtonState = SC_NESTEDBUTTON_UP;
1944 if (nButtonDown != rMEvt.GetButtons())
1945 nMouseStatus = SC_GM_IGNORE; // reset und return
1947 nButtonDown = 0;
1949 if (nMouseStatus == SC_GM_IGNORE)
1951 nMouseStatus = SC_GM_NONE;
1952 // Selection-Engine: Markieren abbrechen
1953 pViewData->GetView()->GetSelEngine()->Reset();
1954 rMark.SetMarking(false);
1955 if (pViewData->IsAnyFillMode())
1957 pViewData->GetView()->StopRefMode();
1958 pViewData->ResetFillMode();
1960 StopMarking();
1961 DrawEndAction(); // Markieren/Verschieben auf Drawing-Layer abbrechen
1962 ReleaseMouse();
1963 return;
1966 if (nMouseStatus == SC_GM_FILTER)
1968 nMouseStatus = SC_GM_NONE;
1969 ReleaseMouse();
1970 return; // da muss nix mehr passieren
1973 ScModule* pScMod = SC_MOD();
1974 if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
1975 return;
1977 SfxBindings& rBindings = pViewData->GetBindings();
1978 if (bEEMouse && pViewData->HasEditView( eWhich ))
1980 EditView* pEditView;
1981 SCCOL nEditCol;
1982 SCROW nEditRow;
1983 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
1984 pEditView->MouseButtonUp( rMEvt );
1986 if ( rMEvt.IsMiddle() &&
1987 GetSettings().GetMouseSettings().GetMiddleButtonAction() == MOUSE_MIDDLE_PASTESELECTION )
1989 // EditView may have pasted from selection
1990 pScMod->InputChanged( pEditView );
1992 else
1993 pScMod->InputSelection( pEditView ); // parentheses etc.
1995 pViewData->GetView()->InvalidateAttribs();
1996 rBindings.Invalidate( SID_HYPERLINK_GETLINK );
1997 bEEMouse = false;
1998 return;
2001 if (bDPMouse)
2003 DPMouseButtonUp( rMEvt ); // resets bDPMouse
2004 return;
2007 if (bRFMouse)
2009 RFMouseMove( rMEvt, sal_True ); // Range wieder richtigherum
2010 bRFMouse = false;
2011 SetPointer( Pointer( POINTER_ARROW ) );
2012 ReleaseMouse();
2013 return;
2016 if (nPagebreakMouse)
2018 PagebreakMove( rMEvt, sal_True );
2019 nPagebreakMouse = SC_PD_NONE;
2020 SetPointer( Pointer( POINTER_ARROW ) );
2021 ReleaseMouse();
2022 return;
2025 if (nMouseStatus == SC_GM_WATERUNDO) // Undo im Giesskannenmodus
2027 ::svl::IUndoManager* pMgr = pViewData->GetDocShell()->GetUndoManager();
2028 if ( pMgr->GetUndoActionCount() && pMgr->GetUndoActionId() == STR_UNDO_APPLYCELLSTYLE )
2029 pMgr->Undo();
2030 return;
2033 if (DrawMouseButtonUp(rMEvt)) // includes format paint brush handling for drawing objects
2034 return;
2036 rMark.SetMarking(false);
2038 SetPointer( Pointer( POINTER_ARROW ) );
2040 if (pViewData->IsFillMode() ||
2041 ( pViewData->GetFillMode() == SC_FILL_MATRIX && rMEvt.IsMod1() ))
2043 nScFillModeMouseModifier = rMEvt.GetModifier();
2044 SCCOL nStartCol;
2045 SCROW nStartRow;
2046 SCCOL nEndCol;
2047 SCROW nEndRow;
2048 pViewData->GetFillData( nStartCol, nStartRow, nEndCol, nEndRow );
2049 ScRange aDelRange;
2050 sal_Bool bIsDel = pViewData->GetDelMark( aDelRange );
2052 ScViewFunc* pView = pViewData->GetView();
2053 pView->StopRefMode();
2054 pViewData->ResetFillMode();
2055 pView->GetFunctionSet()->SetAnchorFlag( false ); // #i5819# don't use AutoFill anchor flag for selection
2057 if ( bIsDel )
2059 pView->MarkRange( aDelRange, false );
2060 pView->DeleteContents( IDF_CONTENTS );
2061 SCTAB nTab = pViewData->GetTabNo();
2062 ScRange aBlockRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab );
2063 if ( aBlockRange != aDelRange )
2065 if ( aDelRange.aStart.Row() == nStartRow )
2066 aBlockRange.aEnd.SetCol( aDelRange.aStart.Col() - 1 );
2067 else
2068 aBlockRange.aEnd.SetRow( aDelRange.aStart.Row() - 1 );
2069 pView->MarkRange( aBlockRange, false );
2072 else
2073 pViewData->GetDispatcher().Execute( FID_FILL_AUTO, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD );
2075 else if (pViewData->GetFillMode() == SC_FILL_MATRIX)
2077 SCTAB nTab = pViewData->GetTabNo();
2078 SCCOL nStartCol;
2079 SCROW nStartRow;
2080 SCCOL nEndCol;
2081 SCROW nEndRow;
2082 pViewData->GetFillData( nStartCol, nStartRow, nEndCol, nEndRow );
2083 ScRange aBlockRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab );
2084 SCCOL nFillCol = pViewData->GetRefEndX();
2085 SCROW nFillRow = pViewData->GetRefEndY();
2086 ScAddress aEndPos( nFillCol, nFillRow, nTab );
2088 ScTabView* pView = pViewData->GetView();
2089 pView->StopRefMode();
2090 pViewData->ResetFillMode();
2091 pView->GetFunctionSet()->SetAnchorFlag( false );
2093 if ( aEndPos != aBlockRange.aEnd )
2095 pViewData->GetDocShell()->GetDocFunc().ResizeMatrix( aBlockRange, aEndPos, false );
2096 pViewData->GetView()->MarkRange( ScRange( aBlockRange.aStart, aEndPos ) );
2099 else if (pViewData->IsAnyFillMode())
2101 // Embedded-Area has been changed
2102 ScTabView* pView = pViewData->GetView();
2103 pView->StopRefMode();
2104 pViewData->ResetFillMode();
2105 pView->GetFunctionSet()->SetAnchorFlag( false );
2106 pViewData->GetDocShell()->UpdateOle(pViewData);
2109 sal_Bool bRefMode = pViewData->IsRefMode();
2110 if (bRefMode)
2111 pScMod->EndReference();
2114 // Giesskannen-Modus (Gestalter)
2117 if (pScMod->GetIsWaterCan())
2119 // Abfrage auf Undo schon oben
2121 ScStyleSheetPool* pStylePool = (ScStyleSheetPool*)
2122 (pViewData->GetDocument()->
2123 GetStyleSheetPool());
2124 if ( pStylePool )
2126 SfxStyleSheet* pStyleSheet = (SfxStyleSheet*)
2127 pStylePool->GetActualStyleSheet();
2129 if ( pStyleSheet )
2131 SfxStyleFamily eFamily = pStyleSheet->GetFamily();
2133 switch ( eFamily )
2135 case SFX_STYLE_FAMILY_PARA:
2136 pViewData->GetView()->SetStyleSheetToMarked( pStyleSheet );
2137 pViewData->GetView()->DoneBlockMode();
2138 break;
2140 case SFX_STYLE_FAMILY_PAGE:
2141 pViewData->GetDocument()->SetPageStyle( pViewData->GetTabNo(),
2142 pStyleSheet->GetName() );
2144 ScPrintFunc( pViewData->GetDocShell(),
2145 pViewData->GetViewShell()->GetPrinter(sal_True),
2146 pViewData->GetTabNo() ).UpdatePages();
2148 rBindings.Invalidate( SID_STATUS_PAGESTYLE );
2149 break;
2151 default:
2152 break;
2158 ScDBFunc* pView = pViewData->GetView();
2159 ScDocument* pBrushDoc = pView->GetBrushDocument();
2160 if ( pBrushDoc )
2162 pView->PasteFromClip( IDF_ATTRIB, pBrushDoc );
2163 if ( !pView->IsPaintBrushLocked() )
2164 pView->ResetBrushDocument(); // invalidates pBrushDoc pointer
2168 // double click (only left button)
2171 sal_Bool bDouble = ( rMEvt.GetClicks() == 2 && rMEvt.IsLeft() );
2172 if ( bDouble && !bRefMode && nMouseStatus == SC_GM_DBLDOWN && !pScMod->IsRefDialogOpen() )
2174 // data pilot table
2175 Point aPos = rMEvt.GetPosPixel();
2176 SCsCOL nPosX;
2177 SCsROW nPosY;
2178 SCTAB nTab = pViewData->GetTabNo();
2179 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
2180 ScDPObject* pDPObj = pDoc->GetDPAtCursor( nPosX, nPosY, nTab );
2181 if ( pDPObj && pDPObj->GetSaveData()->GetDrillDown() )
2183 ScAddress aCellPos( nPosX, nPosY, pViewData->GetTabNo() );
2185 // Check for header drill-down first.
2186 sheet::DataPilotTableHeaderData aData;
2187 pDPObj->GetHeaderPositionData(aCellPos, aData);
2189 if ( ( aData.Flags & sheet::MemberResultFlags::HASMEMBER ) &&
2190 ! ( aData.Flags & sheet::MemberResultFlags::SUBTOTAL ) )
2192 sal_uInt16 nDummy;
2193 if ( pView->HasSelectionForDrillDown( nDummy ) )
2195 // execute slot to show dialog
2196 pViewData->GetDispatcher().Execute( SID_OUTLINE_SHOW, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD );
2198 else
2200 // toggle single entry
2201 ScDPObject aNewObj( *pDPObj );
2202 pDPObj->ToggleDetails( aData, &aNewObj );
2203 ScDBDocFunc aFunc( *pViewData->GetDocShell() );
2204 aFunc.DataPilotUpdate( pDPObj, &aNewObj, sal_True, false );
2205 pViewData->GetView()->CursorPosChanged(); // shells may be switched
2208 else
2210 // Check if the data area is double-clicked.
2212 Sequence<sheet::DataPilotFieldFilter> aFilters;
2213 if ( pDPObj->GetDataFieldPositionData(aCellPos, aFilters) )
2214 pViewData->GetView()->ShowDataPilotSourceData( *pDPObj, aFilters );
2217 return;
2220 // Check for cell protection attribute.
2221 ScTableProtection* pProtect = pDoc->GetTabProtection( nTab );
2222 bool bEditAllowed = true;
2223 if ( pProtect && pProtect->isProtected() )
2225 bool bCellProtected = pDoc->HasAttrib(nPosX, nPosY, nTab, nPosX, nPosY, nTab, HASATTR_PROTECTED);
2226 bool bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
2227 bool bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
2229 if ( bSkipProtected && bSkipUnprotected )
2230 bEditAllowed = false;
2231 else if ( (bCellProtected && bSkipProtected) || (!bCellProtected && bSkipUnprotected) )
2232 bEditAllowed = false;
2235 if ( bEditAllowed )
2237 // edit cell contents
2238 pViewData->GetViewShell()->UpdateInputHandler();
2239 pScMod->SetInputMode( SC_INPUT_TABLE );
2240 if (pViewData->HasEditView(eWhich))
2242 // Text-Cursor gleich an die geklickte Stelle setzen
2243 EditView* pEditView = pViewData->GetEditView( eWhich );
2244 MouseEvent aEditEvt( rMEvt.GetPosPixel(), 1, MOUSE_SYNTHETIC, MOUSE_LEFT, 0 );
2245 pEditView->MouseButtonDown( aEditEvt );
2246 pEditView->MouseButtonUp( aEditEvt );
2249 return;
2253 // Links in edit cells
2256 sal_Bool bAlt = rMEvt.IsMod2();
2257 if ( !bAlt && !bRefMode && !bDouble && nMouseStatus == SC_GM_URLDOWN )
2259 // beim ButtonUp nur ausfuehren, wenn ButtonDown auch ueber einer URL war
2261 String aName, aUrl, aTarget;
2262 if ( GetEditUrl( rMEvt.GetPosPixel(), &aName, &aUrl, &aTarget ) )
2264 nMouseStatus = SC_GM_NONE; // keinen Doppelklick anfangen
2266 // ScGlobal::OpenURL() only understands Calc A1 style syntax.
2267 // Convert it to Calc A1 before calling OpenURL().
2269 if (pDoc->GetAddressConvention() == formula::FormulaGrammar::CONV_OOO)
2270 ScGlobal::OpenURL(aUrl, aTarget);
2271 else
2273 ScAddress aTempAddr;
2274 ScAddress::ExternalInfo aExtInfo;
2275 sal_uInt16 nRes = aTempAddr.Parse(aUrl, pDoc, pDoc->GetAddressConvention(), &aExtInfo);
2276 if (!(nRes & SCA_VALID))
2278 // Not a reference string. Pass it through unmodified.
2279 ScGlobal::OpenURL(aUrl, aTarget);
2280 return;
2283 OUStringBuffer aBuf;
2284 if (aExtInfo.mbExternal)
2286 // External reference.
2287 ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
2288 const OUString* pStr = pRefMgr->getExternalFileName(aExtInfo.mnFileId);
2289 if (pStr)
2290 aBuf.append(*pStr);
2292 aBuf.append('#');
2293 aBuf.append(aExtInfo.maTabName);
2294 aBuf.append('.');
2295 OUString aRefCalcA1;
2296 aTempAddr.Format(aRefCalcA1, SCA_ABS, NULL, formula::FormulaGrammar::CONV_OOO);
2297 aBuf.append(aRefCalcA1);
2298 ScGlobal::OpenURL(aBuf.makeStringAndClear(), aTarget);
2300 else
2302 // Internal reference.
2303 aBuf.append('#');
2304 OUString aUrlCalcA1;
2305 aTempAddr.Format(aUrlCalcA1, SCA_ABS_3D, pDoc, formula::FormulaGrammar::CONV_OOO);
2306 aBuf.append(aUrlCalcA1);
2307 ScGlobal::OpenURL(aBuf.makeStringAndClear(), aTarget);
2311 // fire worksheet_followhyperlink event
2312 uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents = pDoc->GetVbaEventProcessor();
2313 if( xVbaEvents.is() ) try
2315 Point aPos = rMEvt.GetPosPixel();
2316 SCsCOL nPosX;
2317 SCsROW nPosY;
2318 SCTAB nTab = pViewData->GetTabNo();
2319 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
2320 ScBaseCell* pCell = NULL;
2321 if( lcl_GetHyperlinkCell( pDoc, nPosX, nPosY, nTab, pCell ) )
2323 ScAddress aCellPos( nPosX, nPosY, nTab );
2324 uno::Reference< table::XCell > xCell( new ScCellObj( pViewData->GetDocShell(), aCellPos ) );
2325 uno::Sequence< uno::Any > aArgs(1);
2326 aArgs[0] <<= xCell;
2327 xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKSHEET_FOLLOWHYPERLINK, aArgs );
2330 catch( uno::Exception& )
2334 return;
2339 // Gridwin - SelectionEngine
2342 // SelMouseButtonDown is called only for left button, but SelMouseButtonUp would return
2343 // sal_True for any call, so IsLeft must be checked here, too.
2345 if ( rMEvt.IsLeft() && pViewData->GetView()->GetSelEngine()->SelMouseButtonUp( rMEvt ) )
2347 pViewData->GetView()->SelectionChanged();
2349 SfxDispatcher* pDisp = pViewData->GetViewShell()->GetDispatcher();
2350 sal_Bool bFormulaMode = pScMod->IsFormulaMode();
2351 OSL_ENSURE( pDisp || bFormulaMode, "Cursor auf nicht aktiver View bewegen ?" );
2353 // #i14927# execute SID_CURRENTCELL (for macro recording) only if there is no
2354 // multiple selection, so the argument string completely describes the selection,
2355 // and executing the slot won't change the existing selection (executing the slot
2356 // here and from a recorded macro is treated equally)
2358 if ( pDisp && !bFormulaMode && !rMark.IsMultiMarked() )
2360 String aAddr; // CurrentCell
2361 if( rMark.IsMarked() )
2363 ScRange aScRange;
2364 rMark.GetMarkArea( aScRange );
2365 aScRange.Format( aAddr, SCR_ABS );
2366 if ( aScRange.aStart == aScRange.aEnd )
2368 // make sure there is a range selection string even for a single cell
2369 String aSingle = aAddr;
2370 aAddr.Append( (sal_Char) ':' );
2371 aAddr.Append( aSingle );
2374 //! SID_MARKAREA gibts nicht mehr ???
2375 //! was passiert beim Markieren mit dem Cursor ???
2377 else // nur Cursor bewegen
2379 ScAddress aScAddress( pViewData->GetCurX(), pViewData->GetCurY(), 0 );
2380 aScAddress.Format( aAddr, SCA_ABS );
2383 SfxStringItem aPosItem( SID_CURRENTCELL, aAddr );
2384 // We don't want to align to the cursor position because if the
2385 // cell cursor isn't visible after making selection, it would jump
2386 // back to the origin of the selection where the cell cursor is.
2387 SfxBoolItem aAlignCursorItem( FN_PARAM_2, false );
2388 pDisp->Execute( SID_CURRENTCELL, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD,
2389 &aPosItem, &aAlignCursorItem, (void*)0L );
2391 pViewData->GetView()->InvalidateAttribs();
2393 return;
2397 void ScGridWindow::FakeButtonUp()
2399 if ( nButtonDown )
2401 MouseEvent aEvent( aCurMousePos ); // nButtons = 0 -> ignore
2402 MouseButtonUp( aEvent );
2406 void ScGridWindow::MouseMove( const MouseEvent& rMEvt )
2408 aCurMousePos = rMEvt.GetPosPixel();
2410 if ( rMEvt.IsLeaveWindow() && pNoteMarker && !pNoteMarker->IsByKeyboard() )
2411 HideNoteMarker();
2413 ScModule* pScMod = SC_MOD();
2414 if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
2415 return;
2417 // Ob aus dem Edit-Modus Drag&Drop gestartet wurde, bekommt man leider
2418 // nicht anders mit:
2420 if (bEEMouse && nButtonDown && !rMEvt.GetButtons())
2422 bEEMouse = false;
2423 nButtonDown = 0;
2424 nMouseStatus = SC_GM_NONE;
2425 return;
2428 if (nMouseStatus == SC_GM_IGNORE)
2429 return;
2431 if (nMouseStatus == SC_GM_WATERUNDO) // Undo im Giesskannenmodus -> nur auf Up warten
2432 return;
2434 if ( pViewData->GetViewShell()->IsAuditShell() ) // Detektiv-Fuell-Modus
2436 SetPointer( Pointer( POINTER_FILL ) );
2437 return;
2440 if (nMouseStatus == SC_GM_FILTER && pFilterBox)
2442 Point aRelPos = pFilterBox->ScreenToOutputPixel( OutputToScreenPixel( rMEvt.GetPosPixel() ) );
2443 if ( Rectangle(Point(),pFilterBox->GetOutputSizePixel()).IsInside(aRelPos) )
2445 nButtonDown = 0;
2446 nMouseStatus = SC_GM_NONE;
2447 ReleaseMouse();
2448 pFilterBox->MouseButtonDown( MouseEvent( aRelPos, 1, MOUSE_SIMPLECLICK, MOUSE_LEFT ) );
2449 return;
2453 sal_Bool bFormulaMode = pScMod->IsFormulaMode(); // naechster Klick -> Referenz
2455 if (bEEMouse && pViewData->HasEditView( eWhich ))
2457 EditView* pEditView;
2458 SCCOL nEditCol;
2459 SCROW nEditRow;
2460 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
2461 pEditView->MouseMove( rMEvt );
2462 return;
2465 if (bDPMouse)
2467 DPMouseMove( rMEvt );
2468 return;
2471 if (bRFMouse)
2473 RFMouseMove( rMEvt, false );
2474 return;
2477 if (nPagebreakMouse)
2479 PagebreakMove( rMEvt, false );
2480 return;
2483 // anderen Mauszeiger anzeigen?
2485 sal_Bool bEditMode = pViewData->HasEditView(eWhich);
2487 //! Testen ob RefMode-Dragging !!!
2488 if ( bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()) )
2490 Point aPos = rMEvt.GetPosPixel();
2491 SCsCOL nPosX;
2492 SCsROW nPosY;
2493 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
2495 EditView* pEditView;
2496 SCCOL nEditCol;
2497 SCROW nEditRow;
2498 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
2499 SCCOL nEndCol = pViewData->GetEditEndCol();
2500 SCROW nEndRow = pViewData->GetEditEndRow();
2502 if ( nPosX >= (SCsCOL) nEditCol && nPosX <= (SCsCOL) nEndCol &&
2503 nPosY >= (SCsROW) nEditRow && nPosY <= (SCsROW) nEndRow )
2505 // Field can only be URL field
2506 sal_Bool bAlt = rMEvt.IsMod2();
2507 if ( !bAlt && !nButtonDown && pEditView && pEditView->GetFieldUnderMousePointer() )
2508 SetPointer( Pointer( POINTER_REFHAND ) );
2509 else if ( pEditView && pEditView->GetEditEngine()->IsVertical() )
2510 SetPointer( Pointer( POINTER_TEXT_VERTICAL ) );
2511 else
2512 SetPointer( Pointer( POINTER_TEXT ) );
2513 return;
2517 sal_Bool bWater = SC_MOD()->GetIsWaterCan() || pViewData->GetView()->HasPaintBrush();
2518 if (bWater)
2519 SetPointer( Pointer(POINTER_FILL) );
2521 if (!bWater)
2523 sal_Bool bCross = false;
2525 // Range-Finder
2527 bool bCorner;
2528 if ( HitRangeFinder( rMEvt.GetPosPixel(), bCorner ) )
2530 if (bCorner)
2531 SetPointer( Pointer( POINTER_CROSS ) );
2532 else
2533 SetPointer( Pointer( POINTER_HAND ) );
2534 bCross = sal_True;
2537 // Page-Break-Modus
2539 sal_uInt16 nBreakType;
2540 if ( !nButtonDown && pViewData->IsPagebreakMode() &&
2541 ( nBreakType = HitPageBreak( rMEvt.GetPosPixel() ) ) != 0 )
2543 PointerStyle eNew = POINTER_ARROW;
2544 switch ( nBreakType )
2546 case SC_PD_RANGE_L:
2547 case SC_PD_RANGE_R:
2548 case SC_PD_BREAK_H:
2549 eNew = POINTER_ESIZE;
2550 break;
2551 case SC_PD_RANGE_T:
2552 case SC_PD_RANGE_B:
2553 case SC_PD_BREAK_V:
2554 eNew = POINTER_SSIZE;
2555 break;
2556 case SC_PD_RANGE_TL:
2557 case SC_PD_RANGE_BR:
2558 eNew = POINTER_SESIZE;
2559 break;
2560 case SC_PD_RANGE_TR:
2561 case SC_PD_RANGE_BL:
2562 eNew = POINTER_NESIZE;
2563 break;
2565 SetPointer( Pointer( eNew ) );
2566 bCross = sal_True;
2569 // Fill-Cursor anzeigen ?
2571 if ( !bFormulaMode && !nButtonDown )
2572 if (TestMouse( rMEvt, false ))
2573 bCross = sal_True;
2575 if ( nButtonDown && pViewData->IsAnyFillMode() )
2577 SetPointer( Pointer( POINTER_CROSS ) );
2578 bCross = sal_True;
2579 nScFillModeMouseModifier = rMEvt.GetModifier(); // ausgewertet bei AutoFill und Matrix
2582 if (!bCross)
2584 sal_Bool bAlt = rMEvt.IsMod2();
2586 if (bEditMode) // Edit-Mode muss zuerst kommen!
2587 SetPointer( Pointer( POINTER_ARROW ) );
2588 else if ( !bAlt && !nButtonDown &&
2589 GetEditUrl(rMEvt.GetPosPixel()) )
2590 SetPointer( Pointer( POINTER_REFHAND ) );
2591 else if ( DrawMouseMove(rMEvt) ) // setzt Pointer um
2592 return;
2596 if ( pViewData->GetView()->GetSelEngine()->SelMouseMove( rMEvt ) )
2597 return;
2600 static void lcl_InitMouseEvent( ::com::sun::star::awt::MouseEvent& rEvent, const MouseEvent& rEvt )
2602 rEvent.Modifiers = 0;
2603 if ( rEvt.IsShift() )
2604 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::SHIFT;
2605 if ( rEvt.IsMod1() )
2606 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD1;
2607 if ( rEvt.IsMod2() )
2608 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD2;
2609 if ( rEvt.IsMod3() )
2610 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD3;
2612 rEvent.Buttons = 0;
2613 if ( rEvt.IsLeft() )
2614 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::LEFT;
2615 if ( rEvt.IsRight() )
2616 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::RIGHT;
2617 if ( rEvt.IsMiddle() )
2618 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::MIDDLE;
2620 rEvent.X = rEvt.GetPosPixel().X();
2621 rEvent.Y = rEvt.GetPosPixel().Y();
2622 rEvent.ClickCount = rEvt.GetClicks();
2623 rEvent.PopupTrigger = false;
2626 long ScGridWindow::PreNotify( NotifyEvent& rNEvt )
2628 bool bDone = false;
2629 sal_uInt16 nType = rNEvt.GetType();
2630 if ( nType == EVENT_MOUSEBUTTONUP || nType == EVENT_MOUSEBUTTONDOWN )
2632 Window* pWindow = rNEvt.GetWindow();
2633 if (pWindow == this && pViewData)
2635 SfxViewFrame* pViewFrame = pViewData->GetViewShell()->GetViewFrame();
2636 if (pViewFrame)
2638 com::sun::star::uno::Reference<com::sun::star::frame::XController> xController = pViewFrame->GetFrame().GetController();
2639 if (xController.is())
2641 ScTabViewObj* pImp = ScTabViewObj::getImplementation( xController );
2642 if (pImp && pImp->IsMouseListening())
2644 ::com::sun::star::awt::MouseEvent aEvent;
2645 lcl_InitMouseEvent( aEvent, *rNEvt.GetMouseEvent() );
2646 if ( rNEvt.GetWindow() )
2647 aEvent.Source = rNEvt.GetWindow()->GetComponentInterface();
2648 if ( nType == EVENT_MOUSEBUTTONDOWN)
2649 bDone = pImp->MousePressed( aEvent );
2650 else
2651 bDone = pImp->MouseReleased( aEvent );
2657 if (bDone) // event consumed by a listener
2659 if ( nType == EVENT_MOUSEBUTTONDOWN )
2661 const MouseEvent* pMouseEvent = rNEvt.GetMouseEvent();
2662 if ( pMouseEvent->IsRight() && pMouseEvent->GetClicks() == 1 )
2664 // If a listener returned true for a right-click call, also prevent opening the context menu
2665 // (this works only if the context menu is opened on mouse-down)
2666 nMouseStatus = SC_GM_IGNORE;
2670 return 1;
2672 else
2673 return Window::PreNotify( rNEvt );
2676 void ScGridWindow::Tracking( const TrackingEvent& rTEvt )
2678 // Weil die SelectionEngine kein Tracking kennt, die Events nur auf
2679 // die verschiedenen MouseHandler verteilen...
2681 const MouseEvent& rMEvt = rTEvt.GetMouseEvent();
2683 if ( rTEvt.IsTrackingCanceled() ) // alles abbrechen...
2685 if (!pViewData->GetView()->IsInActivatePart() && !SC_MOD()->IsRefDialogOpen())
2687 if (bDPMouse)
2688 bDPMouse = false; // gezeichnet wird per bDragRect
2689 if (bDragRect)
2691 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
2692 bDragRect = false;
2693 UpdateDragRectOverlay();
2695 if (bRFMouse)
2697 RFMouseMove( rMEvt, true ); // richtig abbrechen geht dabei nicht...
2698 bRFMouse = false;
2700 if (nPagebreakMouse)
2702 // if (bPagebreakDrawn)
2703 // DrawDragRect( aPagebreakDrag.aStart.Col(), aPagebreakDrag.aStart.Row(),
2704 // aPagebreakDrag.aEnd.Col(), aPagebreakDrag.aEnd.Row(), sal_False );
2705 bPagebreakDrawn = false;
2706 UpdateDragRectOverlay();
2707 nPagebreakMouse = SC_PD_NONE;
2710 SetPointer( Pointer( POINTER_ARROW ) );
2711 StopMarking();
2712 MouseButtonUp( rMEvt ); // mit Status SC_GM_IGNORE aus StopMarking
2714 sal_Bool bRefMode = pViewData->IsRefMode();
2715 if (bRefMode)
2716 SC_MOD()->EndReference(); // Dialog nicht verkleinert lassen
2719 else if ( rTEvt.IsTrackingEnded() )
2721 // MouseButtonUp immer mit passenden Buttons (z.B. wegen Testtool, #63148#)
2722 // Schliesslich behauptet der Tracking-Event ja, dass normal beendet und nicht
2723 // abgebrochen wurde.
2725 MouseEvent aUpEvt( rMEvt.GetPosPixel(), rMEvt.GetClicks(),
2726 rMEvt.GetMode(), nButtonDown, rMEvt.GetModifier() );
2727 MouseButtonUp( aUpEvt );
2729 else
2730 MouseMove( rMEvt );
2733 void ScGridWindow::StartDrag( sal_Int8 /* nAction */, const Point& rPosPixel )
2735 if ( pFilterBox || nPagebreakMouse )
2736 return;
2738 HideNoteMarker();
2740 CommandEvent aDragEvent( rPosPixel, COMMAND_STARTDRAG, sal_True );
2742 if (bEEMouse && pViewData->HasEditView( eWhich ))
2744 EditView* pEditView;
2745 SCCOL nEditCol;
2746 SCROW nEditRow;
2747 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
2749 // don't remove the edit view while switching views
2750 ScModule* pScMod = SC_MOD();
2751 pScMod->SetInEditCommand( sal_True );
2753 pEditView->Command( aDragEvent );
2755 ScInputHandler* pHdl = pScMod->GetInputHdl();
2756 if (pHdl)
2757 pHdl->DataChanged();
2759 pScMod->SetInEditCommand( false );
2760 if (!pViewData->IsActive()) // dropped to different view?
2762 ScInputHandler* pViewHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
2763 if ( pViewHdl && pViewData->HasEditView( eWhich ) )
2765 pViewHdl->CancelHandler();
2766 ShowCursor(); // missing from KillEditView
2770 else
2771 if ( !DrawCommand(aDragEvent) )
2772 pViewData->GetView()->GetSelEngine()->Command( aDragEvent );
2775 static void lcl_SetTextCursorPos( ScViewData* pViewData, ScSplitPos eWhich, Window* pWin )
2777 SCCOL nCol = pViewData->GetCurX();
2778 SCROW nRow = pViewData->GetCurY();
2779 Rectangle aEditArea = pViewData->GetEditArea( eWhich, nCol, nRow, pWin, NULL, sal_True );
2780 aEditArea.Right() = aEditArea.Left();
2781 aEditArea = pWin->PixelToLogic( aEditArea );
2782 pWin->SetCursorRect( &aEditArea );
2785 void ScGridWindow::Command( const CommandEvent& rCEvt )
2787 // The command event is send to the window after a possible context
2788 // menu from an inplace client is closed. Now we have the chance to
2789 // deactivate the inplace client without any problem regarding parent
2790 // windows and code on the stack.
2791 sal_uInt16 nCmd = rCEvt.GetCommand();
2792 ScTabViewShell* pTabViewSh = pViewData->GetViewShell();
2793 SfxInPlaceClient* pClient = pTabViewSh->GetIPClient();
2794 if ( pClient &&
2795 pClient->IsObjectInPlaceActive() &&
2796 nCmd == COMMAND_CONTEXTMENU )
2798 pTabViewSh->DeactivateOle();
2799 return;
2802 ScModule* pScMod = SC_MOD();
2803 OSL_ENSURE( nCmd != COMMAND_STARTDRAG, "ScGridWindow::Command called with COMMAND_STARTDRAG" );
2805 if ( nCmd == COMMAND_STARTEXTTEXTINPUT ||
2806 nCmd == COMMAND_ENDEXTTEXTINPUT ||
2807 nCmd == COMMAND_EXTTEXTINPUT ||
2808 nCmd == COMMAND_CURSORPOS )
2810 sal_Bool bEditView = pViewData->HasEditView( eWhich );
2811 if (!bEditView)
2813 // only if no cell editview is active, look at drawview
2814 SdrView* pSdrView = pViewData->GetView()->GetSdrView();
2815 if ( pSdrView )
2817 OutlinerView* pOlView = pSdrView->GetTextEditOutlinerView();
2818 if ( pOlView && pOlView->GetWindow() == this )
2820 pOlView->Command( rCEvt );
2821 return; // done
2826 if ( nCmd == COMMAND_CURSORPOS && !bEditView )
2828 // CURSORPOS may be called without following text input,
2829 // to set the input method window position
2830 // -> input mode must not be started,
2831 // manually calculate text insert position if not in input mode
2833 lcl_SetTextCursorPos( pViewData, eWhich, this );
2834 return;
2837 ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
2838 if ( pHdl )
2840 pHdl->InputCommand( rCEvt, sal_True );
2841 return; // done
2844 Window::Command( rCEvt );
2845 return;
2848 if ( nCmd == COMMAND_VOICE )
2850 // Der Handler wird nur gerufen, wenn ein Text-Cursor aktiv ist,
2851 // also muss es eine EditView oder ein editiertes Zeichenobjekt geben
2853 ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
2854 if ( pHdl && pViewData->HasEditView( eWhich ) )
2856 EditView* pEditView = pViewData->GetEditView( eWhich ); // ist dann nicht 0
2857 pHdl->DataChanging();
2858 pEditView->Command( rCEvt );
2859 pHdl->DataChanged();
2860 return; // erledigt
2862 SdrView* pSdrView = pViewData->GetView()->GetSdrView();
2863 if ( pSdrView )
2865 OutlinerView* pOlView = pSdrView->GetTextEditOutlinerView();
2866 if ( pOlView && pOlView->GetWindow() == this )
2868 pOlView->Command( rCEvt );
2869 return; // erledigt
2872 Window::Command(rCEvt); // sonst soll sich die Basisklasse drum kuemmern...
2873 return;
2876 if ( nCmd == COMMAND_PASTESELECTION )
2878 if ( bEEMouse )
2880 // EditEngine handles selection in MouseButtonUp - no action
2881 // needed in command handler
2883 else
2885 PasteSelection( rCEvt.GetMousePosPixel() );
2887 return;
2890 if ( nCmd == COMMAND_INPUTLANGUAGECHANGE )
2892 // #i55929# Font and font size state depends on input language if nothing is selected,
2893 // so the slots have to be invalidated when the input language is changed.
2895 SfxBindings& rBindings = pViewData->GetBindings();
2896 rBindings.Invalidate( SID_ATTR_CHAR_FONT );
2897 rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT );
2898 return;
2901 if ( nCmd == COMMAND_WHEEL || nCmd == COMMAND_STARTAUTOSCROLL || nCmd == COMMAND_AUTOSCROLL )
2903 sal_Bool bDone = pViewData->GetView()->ScrollCommand( rCEvt, eWhich );
2904 if (!bDone)
2905 Window::Command(rCEvt);
2906 return;
2908 // #i7560# FormulaMode check is below scrolling - scrolling is allowed during formula input
2909 sal_Bool bDisable = pScMod->IsFormulaMode() ||
2910 pScMod->IsModalMode(pViewData->GetSfxDocShell());
2911 if (bDisable)
2912 return;
2914 if ( nCmd == COMMAND_CONTEXTMENU && !SC_MOD()->GetIsWaterCan() )
2916 sal_Bool bMouse = rCEvt.IsMouseEvent();
2917 if ( bMouse && nMouseStatus == SC_GM_IGNORE )
2918 return;
2920 if (pViewData->IsAnyFillMode())
2922 pViewData->GetView()->StopRefMode();
2923 pViewData->ResetFillMode();
2925 ReleaseMouse();
2926 StopMarking();
2928 Point aPosPixel = rCEvt.GetMousePosPixel();
2929 Point aMenuPos = aPosPixel;
2931 if ( bMouse )
2933 SCsCOL nCellX = -1;
2934 SCsROW nCellY = -1;
2935 pViewData->GetPosFromPixel(aPosPixel.X(), aPosPixel.Y(), eWhich, nCellX, nCellY);
2936 ScDocument* pDoc = pViewData->GetDocument();
2937 SCTAB nTab = pViewData->GetTabNo();
2938 const ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
2939 bool bSelectAllowed = true;
2940 if ( pProtect && pProtect->isProtected() )
2942 // This sheet is protected. Check if a context menu is allowed on this cell.
2943 bool bCellProtected = pDoc->HasAttrib(nCellX, nCellY, nTab, nCellX, nCellY, nTab, HASATTR_PROTECTED);
2944 bool bSelProtected = pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
2945 bool bSelUnprotected = pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
2947 if (bCellProtected)
2948 bSelectAllowed = bSelProtected;
2949 else
2950 bSelectAllowed = bSelUnprotected;
2952 if (!bSelectAllowed)
2953 // Selecting this cell is not allowed, neither is context menu.
2954 return;
2956 // #i18735# First select the item under the mouse pointer.
2957 // This can change the selection, and the view state (edit mode, etc).
2958 SelectForContextMenu( aPosPixel, nCellX, nCellY );
2961 sal_Bool bDone = false;
2962 sal_Bool bEdit = pViewData->HasEditView(eWhich);
2963 if ( !bEdit )
2965 // Edit-Zelle mit Spelling-Errors ?
2966 if ( bMouse && GetEditUrlOrError( sal_True, aPosPixel ) )
2968 // GetEditUrlOrError hat den Cursor schon bewegt
2970 pScMod->SetInputMode( SC_INPUT_TABLE );
2971 bEdit = pViewData->HasEditView(eWhich); // hat's geklappt ?
2973 OSL_ENSURE( bEdit, "kann nicht in Edit-Modus schalten" );
2976 if ( bEdit )
2978 EditView* pEditView = pViewData->GetEditView( eWhich ); // ist dann nicht 0
2980 if ( !bMouse )
2982 Cursor* pCur = pEditView->GetCursor();
2983 if ( pCur )
2985 Point aLogicPos = pCur->GetPos();
2986 // use the position right of the cursor (spell popup is opened if
2987 // the cursor is before the word, but not if behind it)
2988 aLogicPos.X() += pCur->GetWidth();
2989 aLogicPos.Y() += pCur->GetHeight() / 2; // center vertically
2990 aMenuPos = LogicToPixel( aLogicPos );
2994 // if edit mode was just started above, online spelling may be incomplete
2995 pEditView->GetEditEngine()->CompleteOnlineSpelling();
2997 // IsCursorAtWrongSpelledWord could be used for !bMouse
2998 // if there was a corresponding ExecuteSpellPopup call
3000 if( pEditView->IsWrongSpelledWordAtPos( aMenuPos ) )
3002 // Wenn man unter OS/2 neben das Popupmenue klickt, kommt MouseButtonDown
3003 // vor dem Ende des Menue-Execute, darum muss SetModified vorher kommen
3004 // (Bug #40968#)
3005 ScInputHandler* pHdl = pScMod->GetInputHdl();
3006 if (pHdl)
3007 pHdl->SetModified();
3009 Link aLink = LINK( this, ScGridWindow, PopupSpellingHdl );
3010 pEditView->ExecuteSpellPopup( aMenuPos, &aLink );
3012 bDone = sal_True;
3015 else if ( !bMouse )
3017 // non-edit menu by keyboard -> use lower right of cell cursor position
3019 SCCOL nCurX = pViewData->GetCurX();
3020 SCROW nCurY = pViewData->GetCurY();
3021 aMenuPos = pViewData->GetScrPos( nCurX, nCurY, eWhich, sal_True );
3022 long nSizeXPix;
3023 long nSizeYPix;
3024 pViewData->GetMergeSizePixel( nCurX, nCurY, nSizeXPix, nSizeYPix );
3025 aMenuPos.X() += nSizeXPix;
3026 aMenuPos.Y() += nSizeYPix;
3028 if (pViewData)
3030 ScTabViewShell* pViewSh = pViewData->GetViewShell();
3031 if (pViewSh)
3033 // Is a draw object selected?
3035 SdrView* pDrawView = pViewSh->GetSdrView();
3036 if (pDrawView && pDrawView->AreObjectsMarked())
3038 // #100442#; the conext menu should open in the middle of the selected objects
3039 Rectangle aSelectRect(LogicToPixel(pDrawView->GetAllMarkedBoundRect()));
3040 aMenuPos = aSelectRect.Center();
3046 if (!bDone)
3048 SfxDispatcher::ExecutePopup( 0, this, &aMenuPos );
3053 void ScGridWindow::SelectForContextMenu( const Point& rPosPixel, SCsCOL nCellX, SCsROW nCellY )
3055 // #i18735# if the click was outside of the current selection,
3056 // the cursor is moved or an object at the click position selected.
3057 // (see SwEditWin::SelectMenuPosition in Writer)
3059 ScTabView* pView = pViewData->GetView();
3060 ScDrawView* pDrawView = pView->GetScDrawView();
3062 // check cell edit mode
3064 if ( pViewData->HasEditView(eWhich) )
3066 ScModule* pScMod = SC_MOD();
3067 SCCOL nEditStartCol = pViewData->GetEditViewCol(); //! change to GetEditStartCol after calcrtl is integrated
3068 SCROW nEditStartRow = pViewData->GetEditViewRow();
3069 SCCOL nEditEndCol = pViewData->GetEditEndCol();
3070 SCROW nEditEndRow = pViewData->GetEditEndRow();
3072 if ( nCellX >= (SCsCOL) nEditStartCol && nCellX <= (SCsCOL) nEditEndCol &&
3073 nCellY >= (SCsROW) nEditStartRow && nCellY <= (SCsROW) nEditEndRow )
3075 // handle selection within the EditView
3077 EditView* pEditView = pViewData->GetEditView( eWhich ); // not NULL (HasEditView)
3078 EditEngine* pEditEngine = pEditView->GetEditEngine();
3079 Rectangle aOutputArea = pEditView->GetOutputArea();
3080 Rectangle aVisArea = pEditView->GetVisArea();
3082 Point aTextPos = PixelToLogic( rPosPixel );
3083 if ( pEditEngine->IsVertical() ) // have to manually transform position
3085 aTextPos -= aOutputArea.TopRight();
3086 long nTemp = -aTextPos.X();
3087 aTextPos.X() = aTextPos.Y();
3088 aTextPos.Y() = nTemp;
3090 else
3091 aTextPos -= aOutputArea.TopLeft();
3092 aTextPos += aVisArea.TopLeft(); // position in the edit document
3094 EPosition aDocPosition = pEditEngine->FindDocPosition(aTextPos);
3095 ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex);
3096 ESelection aSelection = pEditView->GetSelection();
3097 aSelection.Adjust(); // needed for IsLess/IsGreater
3098 if ( aCompare.IsLess(aSelection) || aCompare.IsGreater(aSelection) )
3100 // clicked outside the selected text - deselect and move text cursor
3101 MouseEvent aEvent( rPosPixel );
3102 pEditView->MouseButtonDown( aEvent );
3103 pEditView->MouseButtonUp( aEvent );
3104 pScMod->InputSelection( pEditView );
3107 return; // clicked within the edit view - keep edit mode
3109 else
3111 // outside of the edit view - end edit mode, regardless of cell selection, then continue
3112 pScMod->InputEnterHandler();
3116 // check draw text edit mode
3118 Point aLogicPos = PixelToLogic( rPosPixel ); // after cell edit mode is ended
3119 if ( pDrawView && pDrawView->GetTextEditObject() && pDrawView->GetTextEditOutlinerView() )
3121 OutlinerView* pOlView = pDrawView->GetTextEditOutlinerView();
3122 Rectangle aOutputArea = pOlView->GetOutputArea();
3123 if ( aOutputArea.IsInside( aLogicPos ) )
3125 // handle selection within the OutlinerView
3127 Outliner* pOutliner = pOlView->GetOutliner();
3128 const EditEngine& rEditEngine = pOutliner->GetEditEngine();
3129 Rectangle aVisArea = pOlView->GetVisArea();
3131 Point aTextPos = aLogicPos;
3132 if ( pOutliner->IsVertical() ) // have to manually transform position
3134 aTextPos -= aOutputArea.TopRight();
3135 long nTemp = -aTextPos.X();
3136 aTextPos.X() = aTextPos.Y();
3137 aTextPos.Y() = nTemp;
3139 else
3140 aTextPos -= aOutputArea.TopLeft();
3141 aTextPos += aVisArea.TopLeft(); // position in the edit document
3143 EPosition aDocPosition = rEditEngine.FindDocPosition(aTextPos);
3144 ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex);
3145 ESelection aSelection = pOlView->GetSelection();
3146 aSelection.Adjust(); // needed for IsLess/IsGreater
3147 if ( aCompare.IsLess(aSelection) || aCompare.IsGreater(aSelection) )
3149 // clicked outside the selected text - deselect and move text cursor
3150 // use DrawView to allow extra handling there (none currently)
3151 MouseEvent aEvent( rPosPixel );
3152 pDrawView->MouseButtonDown( aEvent, this );
3153 pDrawView->MouseButtonUp( aEvent, this );
3156 return; // clicked within the edit area - keep edit mode
3158 else
3160 // Outside of the edit area - end text edit mode, then continue.
3161 // DrawDeselectAll also ends text edit mode and updates the shells.
3162 // If the click was on the edited object, it will be selected again below.
3163 pView->DrawDeselectAll();
3167 // look for existing selection
3169 sal_Bool bHitSelected = false;
3170 if ( pDrawView && pDrawView->IsMarkedObjHit( aLogicPos ) )
3172 // clicked on selected object -> don't change anything
3173 bHitSelected = sal_True;
3175 else if ( pViewData->GetMarkData().IsCellMarked(nCellX, nCellY) )
3177 // clicked on selected cell -> don't change anything
3178 bHitSelected = sal_True;
3181 // select drawing object or move cell cursor
3183 if ( !bHitSelected )
3185 sal_Bool bWasDraw = ( pDrawView && pDrawView->AreObjectsMarked() );
3186 sal_Bool bHitDraw = false;
3187 if ( pDrawView )
3189 pDrawView->UnmarkAllObj();
3190 // Unlock the Internal Layer in order to activate the context menu.
3191 // re-lock in ScDrawView::MarkListHasChanged()
3192 lcl_UnLockComment( pDrawView, pDrawView->GetSdrPageView(), pDrawView->GetModel(), aLogicPos ,pViewData);
3193 bHitDraw = pDrawView->MarkObj( aLogicPos );
3194 // draw shell is activated in MarkListHasChanged
3196 if ( !bHitDraw )
3198 pView->Unmark();
3199 pView->SetCursor(nCellX, nCellY);
3200 if ( bWasDraw )
3201 pViewData->GetViewShell()->SetDrawShell( false ); // switch shells
3206 void ScGridWindow::KeyInput(const KeyEvent& rKEvt)
3208 // Cursor control for ref input dialog
3209 const KeyCode& rKeyCode = rKEvt.GetKeyCode();
3210 if( SC_MOD()->IsRefDialogOpen() )
3212 if( !rKeyCode.GetModifier() && (rKeyCode.GetCode() == KEY_F2) )
3214 SC_MOD()->EndReference();
3215 return;
3217 else if( pViewData->GetViewShell()->MoveCursorKeyInput( rKEvt ) )
3219 ScRange aRef(
3220 pViewData->GetRefStartX(), pViewData->GetRefStartY(), pViewData->GetRefStartZ(),
3221 pViewData->GetRefEndX(), pViewData->GetRefEndY(), pViewData->GetRefEndZ() );
3222 SC_MOD()->SetReference( aRef, pViewData->GetDocument() );
3223 return;
3226 else if( rKeyCode.GetCode() == KEY_RETURN && pViewData->IsPasteMode() )
3228 ScTabViewShell* pTabViewShell = pViewData->GetViewShell();
3229 ScClipUtil::PasteFromClipboard( pViewData, pTabViewShell, false );
3231 // Clear clipboard content.
3232 uno::Reference<datatransfer::clipboard::XClipboard> xSystemClipboard =
3233 TransferableHelper::GetSystemClipboard();
3234 if (xSystemClipboard.is())
3236 xSystemClipboard->setContents(
3237 uno::Reference<datatransfer::XTransferable>(),
3238 uno::Reference<datatransfer::clipboard::XClipboardOwner>());
3241 // hide the border around the copy source
3242 pViewData->SetPasteMode( SC_PASTE_NONE );
3243 UpdateCopySourceOverlay();
3244 return;
3246 // wenn semi-Modeless-SfxChildWindow-Dialog oben, keine KeyInputs:
3247 else if( !pViewData->IsAnyFillMode() )
3249 if (rKeyCode.GetCode() == KEY_ESCAPE)
3251 pViewData->SetPasteMode( SC_PASTE_NONE );
3252 UpdateCopySourceOverlay();
3254 // query for existing note marker before calling ViewShell's keyboard handling
3255 // which may remove the marker
3256 sal_Bool bHadKeyMarker = ( pNoteMarker && pNoteMarker->IsByKeyboard() );
3257 ScTabViewShell* pViewSh = pViewData->GetViewShell();
3259 if (pViewData->GetDocShell()->GetProgress())
3260 return;
3262 if (DrawKeyInput(rKEvt))
3263 return;
3265 if (!pViewData->GetView()->IsDrawSelMode() && !DrawHasMarkedObj()) // keine Eingaben im Zeichenmodus
3266 { //! DrawShell abfragen !!!
3267 if (pViewSh->TabKeyInput(rKEvt))
3268 return;
3270 else
3271 if (pViewSh->SfxViewShell::KeyInput(rKEvt)) // von SfxViewShell
3272 return;
3274 KeyCode aCode = rKEvt.GetKeyCode();
3275 if ( aCode.GetCode() == KEY_ESCAPE && aCode.GetModifier() == 0 )
3277 if ( bHadKeyMarker )
3278 HideNoteMarker();
3279 else
3280 pViewSh->Escape();
3281 return;
3283 if ( aCode.GetCode() == KEY_F1 && aCode.GetModifier() == KEY_MOD1 )
3285 // ctrl-F1 shows or hides the note or redlining info for the cursor position
3286 // (hard-coded because F1 can't be configured)
3288 if ( bHadKeyMarker )
3289 HideNoteMarker(); // hide when previously visible
3290 else
3291 ShowNoteMarker( pViewData->GetCurX(), pViewData->GetCurY(), sal_True );
3292 return;
3294 if (aCode.GetCode() == KEY_BRACKETLEFT && aCode.GetModifier() == KEY_MOD1)
3296 pViewSh->DetectiveMarkPred();
3297 return;
3299 if (aCode.GetCode() == KEY_BRACKETRIGHT && aCode.GetModifier() == KEY_MOD1)
3301 pViewSh->DetectiveMarkSucc();
3302 return;
3307 Window::KeyInput(rKEvt);
3310 void ScGridWindow::StopMarking()
3312 DrawEndAction(); // Markieren/Verschieben auf Drawing-Layer abbrechen
3314 if (nButtonDown)
3316 pViewData->GetMarkData().SetMarking(false);
3317 nMouseStatus = SC_GM_IGNORE;
3321 void ScGridWindow::UpdateInputContext()
3323 sal_Bool bReadOnly = pViewData->GetDocShell()->IsReadOnly();
3324 sal_uLong nOptions = bReadOnly ? 0 : ( INPUTCONTEXT_TEXT | INPUTCONTEXT_EXTTEXTINPUT );
3326 // when font from InputContext is used,
3327 // it must be taken from the cursor position's cell attributes
3329 InputContext aContext;
3330 aContext.SetOptions( nOptions );
3331 SetInputContext( aContext );
3334 //--------------------------------------------------------
3336 // sensitiver Bereich (Pixel)
3337 #define SCROLL_SENSITIVE 20
3339 bool ScGridWindow::DropScroll( const Point& rMousePos )
3341 SCsCOL nDx = 0;
3342 SCsROW nDy = 0;
3343 Size aSize = GetOutputSizePixel();
3345 if (aSize.Width() > SCROLL_SENSITIVE * 3)
3347 if ( rMousePos.X() < SCROLL_SENSITIVE && pViewData->GetPosX(WhichH(eWhich)) > 0 )
3348 nDx = -1;
3349 if ( rMousePos.X() >= aSize.Width() - SCROLL_SENSITIVE
3350 && pViewData->GetPosX(WhichH(eWhich)) < MAXCOL )
3351 nDx = 1;
3353 if (aSize.Height() > SCROLL_SENSITIVE * 3)
3355 if ( rMousePos.Y() < SCROLL_SENSITIVE && pViewData->GetPosY(WhichV(eWhich)) > 0 )
3356 nDy = -1;
3357 if ( rMousePos.Y() >= aSize.Height() - SCROLL_SENSITIVE
3358 && pViewData->GetPosY(WhichV(eWhich)) < MAXROW )
3359 nDy = 1;
3362 if ( nDx != 0 || nDy != 0 )
3364 if ( nDx != 0 )
3365 pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) );
3366 if ( nDy != 0 )
3367 pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) );
3370 return false;
3373 static sal_Bool lcl_TestScenarioRedliningDrop( ScDocument* pDoc, const ScRange& aDragRange)
3375 // Testet, ob bei eingeschalteten RedLining,
3376 // bei einem Drop ein Scenario betroffen ist.
3378 sal_Bool bReturn = false;
3379 SCTAB nTab = aDragRange.aStart.Tab();
3380 SCTAB nTabCount = pDoc->GetTableCount();
3382 if(pDoc->GetChangeTrack()!=NULL)
3384 if( pDoc->IsScenario(nTab) && pDoc->HasScenarioRange(nTab, aDragRange))
3386 bReturn = sal_True;
3388 else
3390 for(SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
3392 if(pDoc->HasScenarioRange(i, aDragRange))
3394 bReturn = sal_True;
3395 break;
3400 return bReturn;
3403 static ScRange lcl_MakeDropRange( SCCOL nPosX, SCROW nPosY, SCTAB nTab, const ScRange& rSource )
3405 SCCOL nCol1 = nPosX;
3406 SCCOL nCol2 = nCol1 + ( rSource.aEnd.Col() - rSource.aStart.Col() );
3407 if ( nCol2 > MAXCOL )
3409 nCol1 -= nCol2 - MAXCOL;
3410 nCol2 = MAXCOL;
3412 SCROW nRow1 = nPosY;
3413 SCROW nRow2 = nRow1 + ( rSource.aEnd.Row() - rSource.aStart.Row() );
3414 if ( nRow2 > MAXROW )
3416 nRow1 -= nRow2 - MAXROW;
3417 nRow2 = MAXROW;
3420 return ScRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab );
3423 //--------------------------------------------------------
3425 extern sal_Bool bPasteIsDrop; // viewfun4 -> move to header
3426 extern sal_Bool bPasteIsMove; // viewfun7 -> move to header
3428 //--------------------------------------------------------
3430 sal_Int8 ScGridWindow::AcceptPrivateDrop( const AcceptDropEvent& rEvt )
3432 if ( rEvt.mbLeaving )
3434 bDragRect = false;
3435 UpdateDragRectOverlay();
3436 return rEvt.mnAction;
3439 const ScDragData& rData = SC_MOD()->GetDragData();
3440 if ( rData.pCellTransfer )
3442 // Don't move source that would include filtered rows.
3443 if ((rEvt.mnAction & DND_ACTION_MOVE) && rData.pCellTransfer->HasFilteredRows())
3445 if (bDragRect)
3447 bDragRect = false;
3448 UpdateDragRectOverlay();
3450 return DND_ACTION_NONE;
3453 Point aPos = rEvt.maPosPixel;
3455 ScDocument* pSourceDoc = rData.pCellTransfer->GetSourceDocument();
3456 ScDocument* pThisDoc = pViewData->GetDocument();
3457 if (pSourceDoc == pThisDoc)
3459 rtl::OUString aName;
3460 if ( pThisDoc->HasChartAtPoint(pViewData->GetTabNo(), PixelToLogic(aPos), aName ))
3462 if (bDragRect) // Rechteck loeschen
3464 bDragRect = false;
3465 UpdateDragRectOverlay();
3468 //! highlight chart? (selection border?)
3470 sal_Int8 nRet = rEvt.mnAction;
3471 return nRet;
3475 if ( rData.pCellTransfer->GetDragSourceFlags() & SC_DROP_TABLE ) // whole sheet?
3477 sal_Bool bOk = pThisDoc->IsDocEditable();
3478 return bOk ? rEvt.mnAction : 0; // don't draw selection frame
3481 SCsCOL nPosX;
3482 SCsROW nPosY;
3483 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
3485 ScRange aSourceRange = rData.pCellTransfer->GetRange();
3486 SCCOL nSourceStartX = aSourceRange.aStart.Col();
3487 SCROW nSourceStartY = aSourceRange.aStart.Row();
3488 SCCOL nSourceEndX = aSourceRange.aEnd.Col();
3489 SCROW nSourceEndY = aSourceRange.aEnd.Row();
3490 SCCOL nSizeX = nSourceEndX - nSourceStartX + 1;
3491 SCROW nSizeY = nSourceEndY - nSourceStartY + 1;
3493 if ( rEvt.mnAction != DND_ACTION_MOVE )
3494 nSizeY = rData.pCellTransfer->GetNonFilteredRows(); // copy/link: no filtered rows
3496 SCsCOL nNewDragX = nPosX - rData.pCellTransfer->GetDragHandleX();
3497 if (nNewDragX<0) nNewDragX=0;
3498 if (nNewDragX+(nSizeX-1) > MAXCOL)
3499 nNewDragX = MAXCOL-(nSizeX-1);
3500 SCsROW nNewDragY = nPosY - rData.pCellTransfer->GetDragHandleY();
3501 if (nNewDragY<0) nNewDragY=0;
3502 if (nNewDragY+(nSizeY-1) > MAXROW)
3503 nNewDragY = MAXROW-(nSizeY-1);
3505 // don't break scenario ranges, don't drop on filtered
3506 SCTAB nTab = pViewData->GetTabNo();
3507 ScRange aDropRange = lcl_MakeDropRange( nNewDragX, nNewDragY, nTab, aSourceRange );
3508 if ( lcl_TestScenarioRedliningDrop( pThisDoc, aDropRange ) ||
3509 lcl_TestScenarioRedliningDrop( pSourceDoc, aSourceRange ) ||
3510 ScViewUtil::HasFiltered( aDropRange, pThisDoc) )
3512 if (bDragRect)
3514 bDragRect = false;
3515 UpdateDragRectOverlay();
3517 return DND_ACTION_NONE;
3520 InsCellCmd eDragInsertMode = INS_NONE;
3521 Window::PointerState aState = GetPointerState();
3523 // check for datapilot item sorting
3524 ScDPObject* pDPObj = NULL;
3525 if ( pThisDoc == pSourceDoc && ( pDPObj = pThisDoc->GetDPAtCursor( nNewDragX, nNewDragY, nTab ) ) != NULL )
3527 // drop on DataPilot table: sort or nothing
3529 bool bDPSort = false;
3530 if ( pThisDoc->GetDPAtCursor( nSourceStartX, nSourceStartY, aSourceRange.aStart.Tab() ) == pDPObj )
3532 sheet::DataPilotTableHeaderData aDestData;
3533 pDPObj->GetHeaderPositionData( ScAddress(nNewDragX, nNewDragY, nTab), aDestData );
3534 bool bValid = ( aDestData.Dimension >= 0 ); // dropping onto a field
3536 // look through the source range
3537 for (SCROW nRow = aSourceRange.aStart.Row(); bValid && nRow <= aSourceRange.aEnd.Row(); ++nRow )
3538 for (SCCOL nCol = aSourceRange.aStart.Col(); bValid && nCol <= aSourceRange.aEnd.Col(); ++nCol )
3540 sheet::DataPilotTableHeaderData aSourceData;
3541 pDPObj->GetHeaderPositionData( ScAddress( nCol, nRow, aSourceRange.aStart.Tab() ), aSourceData );
3542 if ( aSourceData.Dimension != aDestData.Dimension || aSourceData.MemberName.isEmpty() )
3543 bValid = false; // empty (subtotal) or different field
3546 if ( bValid )
3548 bool bIsDataLayout;
3549 OUString aDimName = pDPObj->GetDimName( aDestData.Dimension, bIsDataLayout );
3550 const ScDPSaveDimension* pDim = pDPObj->GetSaveData()->GetExistingDimensionByName( aDimName );
3551 if ( pDim )
3553 ScRange aOutRange = pDPObj->GetOutRange();
3555 sal_uInt16 nOrient = pDim->GetOrientation();
3556 if ( nOrient == sheet::DataPilotFieldOrientation_COLUMN )
3558 eDragInsertMode = INS_CELLSRIGHT;
3559 nSizeY = aOutRange.aEnd.Row() - nNewDragY + 1;
3560 bDPSort = true;
3562 else if ( nOrient == sheet::DataPilotFieldOrientation_ROW )
3564 eDragInsertMode = INS_CELLSDOWN;
3565 nSizeX = aOutRange.aEnd.Col() - nNewDragX + 1;
3566 bDPSort = true;
3572 if ( !bDPSort )
3574 // no valid sorting in a DataPilot table -> disallow
3575 if ( bDragRect )
3577 bDragRect = false;
3578 UpdateDragRectOverlay();
3580 return DND_ACTION_NONE;
3583 else if ( aState.mnState & KEY_MOD2 )
3585 if ( pThisDoc == pSourceDoc && nTab == aSourceRange.aStart.Tab() )
3587 long nDeltaX = labs( static_cast< long >( nNewDragX - nSourceStartX ) );
3588 long nDeltaY = labs( static_cast< long >( nNewDragY - nSourceStartY ) );
3589 if ( nDeltaX <= nDeltaY )
3591 eDragInsertMode = INS_CELLSDOWN;
3593 else
3595 eDragInsertMode = INS_CELLSRIGHT;
3598 if ( ( eDragInsertMode == INS_CELLSDOWN && nNewDragY <= nSourceEndY &&
3599 ( nNewDragX + nSizeX - 1 ) >= nSourceStartX && nNewDragX <= nSourceEndX &&
3600 ( nNewDragX != nSourceStartX || nNewDragY >= nSourceStartY ) ) ||
3601 ( eDragInsertMode == INS_CELLSRIGHT && nNewDragX <= nSourceEndX &&
3602 ( nNewDragY + nSizeY - 1 ) >= nSourceStartY && nNewDragY <= nSourceEndY &&
3603 ( nNewDragY != nSourceStartY || nNewDragX >= nSourceStartX ) ) )
3605 if ( bDragRect )
3607 bDragRect = false;
3608 UpdateDragRectOverlay();
3610 return DND_ACTION_NONE;
3613 else
3615 if ( static_cast< long >( nSizeX ) >= static_cast< long >( nSizeY ) )
3617 eDragInsertMode = INS_CELLSDOWN;
3620 else
3622 eDragInsertMode = INS_CELLSRIGHT;
3627 if ( nNewDragX != (SCsCOL) nDragStartX || nNewDragY != (SCsROW) nDragStartY ||
3628 nDragStartX+nSizeX-1 != nDragEndX || nDragStartY+nSizeY-1 != nDragEndY ||
3629 !bDragRect || eDragInsertMode != meDragInsertMode )
3631 nDragStartX = nNewDragX;
3632 nDragStartY = nNewDragY;
3633 nDragEndX = nDragStartX+nSizeX-1;
3634 nDragEndY = nDragStartY+nSizeY-1;
3635 bDragRect = true;
3636 meDragInsertMode = eDragInsertMode;
3638 UpdateDragRectOverlay();
3642 return rEvt.mnAction;
3645 sal_Int8 ScGridWindow::AcceptDrop( const AcceptDropEvent& rEvt )
3647 const ScDragData& rData = SC_MOD()->GetDragData();
3648 if ( rEvt.mbLeaving )
3650 DrawMarkDropObj( NULL );
3651 if ( rData.pCellTransfer )
3652 return AcceptPrivateDrop( rEvt ); // hide drop marker for internal D&D
3653 else
3654 return rEvt.mnAction;
3657 if ( pViewData->GetDocShell()->IsReadOnly() )
3658 return DND_ACTION_NONE;
3661 sal_Int8 nRet = DND_ACTION_NONE;
3663 if (rData.pCellTransfer)
3665 ScRange aSource = rData.pCellTransfer->GetRange();
3666 if ( aSource.aStart.Col() != 0 || aSource.aEnd.Col() != MAXCOL ||
3667 aSource.aStart.Row() != 0 || aSource.aEnd.Row() != MAXROW )
3668 DropScroll( rEvt.maPosPixel );
3670 nRet = AcceptPrivateDrop( rEvt );
3672 else
3674 if ( !rData.aLinkDoc.isEmpty() )
3676 rtl::OUString aThisName;
3677 ScDocShell* pDocSh = pViewData->GetDocShell();
3678 if (pDocSh && pDocSh->HasName())
3679 aThisName = pDocSh->GetMedium()->GetName();
3681 if ( !rData.aLinkDoc.equals(aThisName) )
3682 nRet = rEvt.mnAction;
3684 else if (!rData.aJumpTarget.isEmpty())
3686 // internal bookmarks (from Navigator)
3687 // local jumps from an unnamed document are possible only within a document
3689 if ( !rData.pJumpLocalDoc || rData.pJumpLocalDoc == pViewData->GetDocument() )
3690 nRet = rEvt.mnAction;
3692 else
3694 sal_Int8 nMyAction = rEvt.mnAction;
3696 if ( !rData.pDrawTransfer ||
3697 !IsMyModel(rData.pDrawTransfer->GetDragSourceView()) ) // drawing within the document
3698 if ( rEvt.mbDefault && nMyAction == DND_ACTION_MOVE )
3699 nMyAction = DND_ACTION_COPY;
3701 ScDocument* pThisDoc = pViewData->GetDocument();
3702 SdrObject* pHitObj = pThisDoc->GetObjectAtPoint(
3703 pViewData->GetTabNo(), PixelToLogic(rEvt.maPosPixel) );
3704 if ( pHitObj && nMyAction == DND_ACTION_LINK && !rData.pDrawTransfer )
3706 if ( IsDropFormatSupported(SOT_FORMATSTR_ID_SVXB)
3707 || IsDropFormatSupported(SOT_FORMAT_GDIMETAFILE)
3708 || IsDropFormatSupported(SOT_FORMAT_BITMAP) )
3710 // graphic dragged onto drawing object
3711 DrawMarkDropObj( pHitObj );
3712 nRet = nMyAction;
3715 if (!nRet)
3716 DrawMarkDropObj( NULL );
3718 if (!nRet)
3720 switch ( nMyAction )
3722 case DND_ACTION_COPY:
3723 case DND_ACTION_MOVE:
3724 case DND_ACTION_COPYMOVE:
3726 sal_Bool bMove = ( nMyAction == DND_ACTION_MOVE );
3727 if ( IsDropFormatSupported( SOT_FORMATSTR_ID_EMBED_SOURCE ) ||
3728 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE ) ||
3729 IsDropFormatSupported( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) ||
3730 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ||
3731 IsDropFormatSupported( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) ||
3732 IsDropFormatSupported( SOT_FORMAT_STRING ) ||
3733 IsDropFormatSupported( SOT_FORMATSTR_ID_SYLK ) ||
3734 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK ) ||
3735 IsDropFormatSupported( SOT_FORMATSTR_ID_HTML ) ||
3736 IsDropFormatSupported( SOT_FORMATSTR_ID_HTML_SIMPLE ) ||
3737 IsDropFormatSupported( SOT_FORMATSTR_ID_DIF ) ||
3738 IsDropFormatSupported( SOT_FORMATSTR_ID_DRAWING ) ||
3739 IsDropFormatSupported( SOT_FORMATSTR_ID_SVXB ) ||
3740 IsDropFormatSupported( SOT_FORMAT_RTF ) ||
3741 IsDropFormatSupported( SOT_FORMAT_GDIMETAFILE ) ||
3742 IsDropFormatSupported( SOT_FORMAT_BITMAP ) ||
3743 IsDropFormatSupported( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) ||
3744 IsDropFormatSupported( SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE ) ||
3745 ( !bMove && (
3746 IsDropFormatSupported( SOT_FORMAT_FILE_LIST ) ||
3747 IsDropFormatSupported( SOT_FORMAT_FILE ) ||
3748 IsDropFormatSupported( SOT_FORMATSTR_ID_SOLK ) ||
3749 IsDropFormatSupported( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) ||
3750 IsDropFormatSupported( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) ||
3751 IsDropFormatSupported( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) ) ) )
3753 nRet = nMyAction;
3756 break;
3757 case DND_ACTION_LINK:
3758 if ( IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE ) ||
3759 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ||
3760 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK ) ||
3761 IsDropFormatSupported( SOT_FORMAT_FILE_LIST ) ||
3762 IsDropFormatSupported( SOT_FORMAT_FILE ) ||
3763 IsDropFormatSupported( SOT_FORMATSTR_ID_SOLK ) ||
3764 IsDropFormatSupported( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) ||
3765 IsDropFormatSupported( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) ||
3766 IsDropFormatSupported( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
3768 nRet = nMyAction;
3770 break;
3773 if ( nRet )
3775 // Simple check for protection: It's not known here if the drop will result
3776 // in cells or drawing objects (some formats can be both) and how many cells
3777 // the result will be. But if IsFormatEditable for the drop cell position
3778 // is sal_False (ignores matrix formulas), nothing can be pasted, so the drop
3779 // can already be rejected here.
3781 Point aPos = rEvt.maPosPixel;
3782 SCsCOL nPosX;
3783 SCsROW nPosY;
3784 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
3785 SCTAB nTab = pViewData->GetTabNo();
3786 ScDocument* pDoc = pViewData->GetDocument();
3788 ScEditableTester aTester( pDoc, nTab, nPosX,nPosY, nPosX,nPosY );
3789 if ( !aTester.IsFormatEditable() )
3790 nRet = DND_ACTION_NONE; // forbidden
3795 // scroll only for accepted formats
3796 if (nRet)
3797 DropScroll( rEvt.maPosPixel );
3800 return nRet;
3803 static sal_uLong lcl_GetDropFormatId( const uno::Reference<datatransfer::XTransferable>& xTransfer, bool bPreferText = false )
3805 TransferableDataHelper aDataHelper( xTransfer );
3807 if ( !aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) )
3809 // use bookmark formats if no sba is present
3811 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SOLK ) )
3812 return SOT_FORMATSTR_ID_SOLK;
3813 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) )
3814 return SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR;
3815 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) )
3816 return SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK;
3817 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
3818 return SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR;
3821 sal_uLong nFormatId = 0;
3822 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING ) )
3823 nFormatId = SOT_FORMATSTR_ID_DRAWING;
3824 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ) )
3825 nFormatId = SOT_FORMATSTR_ID_SVXB;
3826 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ) )
3828 // If it's a Writer object, insert RTF instead of OLE
3830 sal_Bool bDoRtf = false;
3831 SotStorageStreamRef xStm;
3832 TransferableObjectDescriptor aObjDesc;
3833 if( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) &&
3834 aDataHelper.GetSotStorageStream( SOT_FORMATSTR_ID_EMBED_SOURCE, xStm ) )
3836 SotStorageRef xStore( new SotStorage( *xStm ) );
3837 bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) ||
3838 aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) )
3839 && aDataHelper.HasFormat( SOT_FORMAT_RTF ) );
3841 if ( bDoRtf )
3842 nFormatId = FORMAT_RTF;
3843 else
3844 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE;
3846 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) )
3847 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE;
3848 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) )
3849 nFormatId = SOT_FORMATSTR_ID_SBA_DATAEXCHANGE;
3850 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE ) )
3851 nFormatId = SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE;
3852 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_BIFF_8 ) )
3853 nFormatId = SOT_FORMATSTR_ID_BIFF_8;
3854 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_BIFF_5 ) )
3855 nFormatId = SOT_FORMATSTR_ID_BIFF_5;
3856 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) )
3857 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE_OLE;
3858 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) )
3859 nFormatId = SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE;
3860 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) )
3861 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE;
3862 else if ( aDataHelper.HasFormat( SOT_FORMAT_RTF ) )
3863 nFormatId = SOT_FORMAT_RTF;
3864 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_HTML ) )
3865 nFormatId = SOT_FORMATSTR_ID_HTML;
3866 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_HTML_SIMPLE ) )
3867 nFormatId = SOT_FORMATSTR_ID_HTML_SIMPLE;
3868 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SYLK ) )
3869 nFormatId = SOT_FORMATSTR_ID_SYLK;
3870 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK ) )
3871 nFormatId = SOT_FORMATSTR_ID_LINK;
3872 else if ( bPreferText && aDataHelper.HasFormat( SOT_FORMAT_STRING ) ) // #i86734# the behaviour introduced in #i62773# is wrong when pasting
3873 nFormatId = SOT_FORMAT_STRING;
3874 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) )
3875 nFormatId = SOT_FORMAT_FILE_LIST;
3876 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE ) ) // #i62773# FILE_LIST/FILE before STRING (Unix file managers)
3877 nFormatId = SOT_FORMAT_FILE;
3878 else if ( aDataHelper.HasFormat( SOT_FORMAT_STRING ) )
3879 nFormatId = SOT_FORMAT_STRING;
3880 else if ( aDataHelper.HasFormat( SOT_FORMAT_GDIMETAFILE ) )
3881 nFormatId = SOT_FORMAT_GDIMETAFILE;
3882 else if ( aDataHelper.HasFormat( SOT_FORMAT_BITMAP ) )
3883 nFormatId = SOT_FORMAT_BITMAP;
3885 return nFormatId;
3888 static sal_uLong lcl_GetDropLinkId( const uno::Reference<datatransfer::XTransferable>& xTransfer )
3890 TransferableDataHelper aDataHelper( xTransfer );
3892 sal_uLong nFormatId = 0;
3893 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) )
3894 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE;
3895 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) )
3896 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE;
3897 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK ) )
3898 nFormatId = SOT_FORMATSTR_ID_LINK;
3899 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) )
3900 nFormatId = SOT_FORMAT_FILE_LIST;
3901 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE ) )
3902 nFormatId = SOT_FORMAT_FILE;
3903 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SOLK ) )
3904 nFormatId = SOT_FORMATSTR_ID_SOLK;
3905 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) )
3906 nFormatId = SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR;
3907 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) )
3908 nFormatId = SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK;
3909 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
3910 nFormatId = SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR;
3912 return nFormatId;
3916 sal_Int8 ScGridWindow::ExecutePrivateDrop( const ExecuteDropEvent& rEvt )
3918 // hide drop marker
3919 bDragRect = false;
3920 UpdateDragRectOverlay();
3922 ScModule* pScMod = SC_MOD();
3923 const ScDragData& rData = pScMod->GetDragData();
3925 return DropTransferObj( rData.pCellTransfer, nDragStartX, nDragStartY,
3926 PixelToLogic(rEvt.maPosPixel), rEvt.mnAction );
3929 sal_Int8 ScGridWindow::DropTransferObj( ScTransferObj* pTransObj, SCCOL nDestPosX, SCROW nDestPosY,
3930 const Point& rLogicPos, sal_Int8 nDndAction )
3932 if ( !pTransObj )
3933 return 0;
3935 ScDocument* pSourceDoc = pTransObj->GetSourceDocument();
3936 ScDocShell* pDocSh = pViewData->GetDocShell();
3937 ScDocument* pThisDoc = pViewData->GetDocument();
3938 ScViewFunc* pView = pViewData->GetView();
3939 SCTAB nThisTab = pViewData->GetTabNo();
3940 sal_uInt16 nFlags = pTransObj->GetDragSourceFlags();
3942 sal_Bool bIsNavi = ( nFlags & SC_DROP_NAVIGATOR ) != 0;
3943 sal_Bool bIsMove = ( nDndAction == DND_ACTION_MOVE && !bIsNavi );
3945 // workaround for wrong nDndAction on Windows when pressing solely
3946 // the Alt key during drag and drop;
3947 // can be removed after #i79215# has been fixed
3948 if ( meDragInsertMode != INS_NONE )
3950 bIsMove = ( nDndAction & DND_ACTION_MOVE && !bIsNavi );
3953 sal_Bool bIsLink = ( nDndAction == DND_ACTION_LINK );
3955 ScRange aSource = pTransObj->GetRange();
3957 // only use visible tab from source range - when dragging within one table,
3958 // all selected tables at the time of dropping are used (handled in MoveBlockTo)
3959 SCTAB nSourceTab = pTransObj->GetVisibleTab();
3960 aSource.aStart.SetTab( nSourceTab );
3961 aSource.aEnd.SetTab( nSourceTab );
3963 SCCOL nSizeX = aSource.aEnd.Col() - aSource.aStart.Col() + 1;
3964 SCROW nSizeY = (bIsMove ? (aSource.aEnd.Row() - aSource.aStart.Row() + 1) :
3965 pTransObj->GetNonFilteredRows()); // copy/link: no filtered rows
3966 ScRange aDest( nDestPosX, nDestPosY, nThisTab,
3967 nDestPosX + nSizeX - 1, nDestPosY + nSizeY - 1, nThisTab );
3970 /* NOTE: AcceptPrivateDrop() already checked for filtered conditions during
3971 * dragging and adapted drawing of the selection frame. We check here
3972 * (again) because this may actually also be called from PasteSelection(),
3973 * we would have to duplicate determination of flags and destination range
3974 * and would lose the context of the "filtered destination is OK" cases
3975 * below, which is already awkward enough as is. */
3977 // Don't move filtered source.
3978 bool bFiltered = (bIsMove && pTransObj->HasFilteredRows());
3979 if (!bFiltered)
3981 if (pSourceDoc != pThisDoc && ((nFlags & SC_DROP_TABLE) ||
3982 (!bIsLink && meDragInsertMode == INS_NONE)))
3984 // Nothing. Either entire sheet to be dropped, or the one case
3985 // where PasteFromClip() is to be called that handles a filtered
3986 // destination itself. Drag-copy from another document without
3987 // inserting cells.
3989 else
3990 // Don't copy or move to filtered destination.
3991 bFiltered = ScViewUtil::HasFiltered( aDest, pThisDoc);
3994 sal_Bool bDone = false;
3996 if (!bFiltered && pSourceDoc == pThisDoc)
3998 if ( nFlags & SC_DROP_TABLE ) // whole sheet?
4000 if ( pThisDoc->IsDocEditable() )
4002 SCTAB nSrcTab = aSource.aStart.Tab();
4003 pViewData->GetDocShell()->MoveTable( nSrcTab, nThisTab, !bIsMove, sal_True ); // with Undo
4004 pView->SetTabNo( nThisTab, sal_True );
4005 bDone = sal_True;
4008 else // move/copy block
4010 rtl::OUString aChartName;
4011 if (pThisDoc->HasChartAtPoint( nThisTab, rLogicPos, aChartName ))
4013 String aRangeName;
4014 aSource.Format( aRangeName, SCR_ABS_3D, pThisDoc );
4015 SfxStringItem aNameItem( SID_CHART_NAME, aChartName );
4016 SfxStringItem aRangeItem( SID_CHART_SOURCE, aRangeName );
4017 sal_uInt16 nId = bIsMove ? SID_CHART_SOURCE : SID_CHART_ADDSOURCE;
4018 pViewData->GetDispatcher().Execute( nId, SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD,
4019 &aRangeItem, &aNameItem, (void*) NULL );
4020 bDone = sal_True;
4022 else if ( pThisDoc->GetDPAtCursor( nDestPosX, nDestPosY, nThisTab ) )
4024 // drop on DataPilot table: try to sort, fail if that isn't possible
4026 ScAddress aDestPos( nDestPosX, nDestPosY, nThisTab );
4027 if ( aDestPos != aSource.aStart )
4028 bDone = pViewData->GetView()->DataPilotMove( aSource, aDestPos );
4029 else
4030 bDone = sal_True; // same position: nothing
4032 else if ( nDestPosX != aSource.aStart.Col() || nDestPosY != aSource.aStart.Row() ||
4033 nSourceTab != nThisTab )
4035 String aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY );
4036 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
4038 SCsCOL nCorrectCursorPosCol = 0;
4039 SCsROW nCorrectCursorPosRow = 0;
4041 bDone = sal_True;
4042 if ( meDragInsertMode != INS_NONE )
4044 // call with bApi = sal_True to avoid error messages in drop handler
4045 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, sal_True /*bRecord*/, sal_True /*bApi*/, sal_True /*bPartOfPaste*/ );
4046 if ( bDone )
4048 if ( nThisTab == nSourceTab )
4050 if ( meDragInsertMode == INS_CELLSDOWN &&
4051 nDestPosX == aSource.aStart.Col() && nDestPosY < aSource.aStart.Row() )
4053 bDone = aSource.Move( 0, nSizeY, 0, pSourceDoc );
4054 nCorrectCursorPosRow = nSizeY;
4056 else if ( meDragInsertMode == INS_CELLSRIGHT &&
4057 nDestPosY == aSource.aStart.Row() && nDestPosX < aSource.aStart.Col() )
4059 bDone = aSource.Move( nSizeX, 0, 0, pSourceDoc );
4060 nCorrectCursorPosCol = nSizeX;
4063 pDocSh->UpdateOle( pViewData );
4064 pView->CellContentChanged();
4068 if ( bDone )
4070 if ( bIsLink )
4072 // call with bApi = sal_True to avoid error messages in drop handler
4073 bDone = pView->LinkBlock( aSource, aDest.aStart, sal_True /*bApi*/ );
4075 else
4077 // call with bApi = sal_True to avoid error messages in drop handler
4078 bDone = pView->MoveBlockTo( aSource, aDest.aStart, bIsMove, sal_True /*bRecord*/, sal_True /*bPaint*/, sal_True /*bApi*/ );
4082 if ( bDone && meDragInsertMode != INS_NONE && bIsMove && nThisTab == nSourceTab )
4084 DelCellCmd eCmd = DEL_NONE;
4085 if ( meDragInsertMode == INS_CELLSDOWN )
4087 eCmd = DEL_CELLSUP;
4089 else if ( meDragInsertMode == INS_CELLSRIGHT )
4091 eCmd = DEL_CELLSLEFT;
4094 if ( ( eCmd == DEL_CELLSUP && nDestPosX == aSource.aStart.Col() ) ||
4095 ( eCmd == DEL_CELLSLEFT && nDestPosY == aSource.aStart.Row() ) )
4097 // call with bApi = sal_True to avoid error messages in drop handler
4098 bDone = pDocSh->GetDocFunc().DeleteCells( aSource, NULL, eCmd, sal_True /*bRecord*/, sal_True /*bApi*/ );
4099 if ( bDone )
4101 if ( eCmd == DEL_CELLSUP && nDestPosY > aSource.aEnd.Row() )
4103 bDone = aDest.Move( 0, -nSizeY, 0, pThisDoc );
4105 else if ( eCmd == DEL_CELLSLEFT && nDestPosX > aSource.aEnd.Col() )
4107 bDone = aDest.Move( -nSizeX, 0, 0, pThisDoc );
4109 pDocSh->UpdateOle( pViewData );
4110 pView->CellContentChanged();
4115 if ( bDone )
4117 pView->MarkRange( aDest, false, false );
4119 SCCOL nDCol = pViewData->GetCurX() - aSource.aStart.Col() + nCorrectCursorPosCol;
4120 SCROW nDRow = pViewData->GetCurY() - aSource.aStart.Row() + nCorrectCursorPosRow;
4121 pView->SetCursor( aDest.aStart.Col() + nDCol, aDest.aStart.Row() + nDRow );
4124 pDocSh->GetUndoManager()->LeaveListAction();
4127 else
4128 bDone = sal_True; // nothing to do
4131 if (bDone)
4132 pTransObj->SetDragWasInternal(); // don't delete source in DragFinished
4134 else if ( !bFiltered && pSourceDoc ) // between documents
4136 if ( nFlags & SC_DROP_TABLE ) // copy/link sheets between documents
4138 if ( pThisDoc->IsDocEditable() )
4140 ScDocShell* pSrcShell = pTransObj->GetSourceDocShell();
4142 std::vector<SCTAB> nTabs;
4144 ScMarkData aMark = pTransObj->GetSourceMarkData();
4145 SCTAB nTabCount = pSourceDoc->GetTableCount();
4147 for(SCTAB i=0; i<nTabCount; i++)
4149 if(aMark.GetTableSelect(i))
4151 nTabs.push_back(i);
4152 for(SCTAB j=i+1;j<nTabCount;j++)
4154 if((!pSourceDoc->IsVisible(j))&&(pSourceDoc->IsScenario(j)))
4156 nTabs.push_back( j );
4157 i=j;
4159 else break;
4164 pView->ImportTables( pSrcShell,static_cast<SCTAB>(nTabs.size()), &nTabs[0], bIsLink, nThisTab );
4165 bDone = sal_True;
4168 else if ( bIsLink )
4170 // as in PasteDDE
4171 // (external references might be used instead?)
4173 SfxObjectShell* pSourceSh = pSourceDoc->GetDocumentShell();
4174 OSL_ENSURE(pSourceSh, "drag document has no shell");
4175 if (pSourceSh)
4177 String aUndo = ScGlobal::GetRscString( STR_UNDO_COPY );
4178 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
4180 bDone = sal_True;
4181 if ( meDragInsertMode != INS_NONE )
4183 // call with bApi = sal_True to avoid error messages in drop handler
4184 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, sal_True /*bRecord*/, sal_True /*bApi*/, sal_True /*bPartOfPaste*/ );
4185 if ( bDone )
4187 pDocSh->UpdateOle( pViewData );
4188 pView->CellContentChanged();
4192 if ( bDone )
4194 String aApp = Application::GetAppName();
4195 String aTopic = pSourceSh->GetTitle( SFX_TITLE_FULLNAME );
4196 String aItem;
4197 aSource.Format( aItem, SCA_VALID | SCA_TAB_3D, pSourceDoc );
4199 // TODO: we could define ocQuote for "
4200 const rtl::OUString aQuote('"');
4201 const String& sSep = ScCompiler::GetNativeSymbol( ocSep);
4202 rtl::OUStringBuffer aFormula;
4203 aFormula.append('=');
4204 aFormula.append(ScCompiler::GetNativeSymbol(ocDde));
4205 aFormula.append(ScCompiler::GetNativeSymbol(ocOpen));
4206 aFormula.append(aQuote);
4207 aFormula.append(aApp);
4208 aFormula.append(aQuote);
4209 aFormula.append(sSep);
4210 aFormula.append(aQuote);
4211 aFormula.append(aTopic);
4212 aFormula.append(aQuote);
4213 aFormula.append(sSep);
4214 aFormula.append(aQuote);
4215 aFormula.append(aItem);
4216 aFormula.append(aQuote);
4217 aFormula.append(ScCompiler::GetNativeSymbol(ocClose));
4219 pView->DoneBlockMode();
4220 pView->InitBlockMode( nDestPosX, nDestPosY, nThisTab );
4221 pView->MarkCursor( nDestPosX + nSizeX - 1,
4222 nDestPosY + nSizeY - 1, nThisTab );
4224 pView->EnterMatrix( aFormula.makeStringAndClear(), ::formula::FormulaGrammar::GRAM_NATIVE );
4226 pView->MarkRange( aDest, false, false );
4227 pView->SetCursor( aDest.aStart.Col(), aDest.aStart.Row() );
4230 pDocSh->GetUndoManager()->LeaveListAction();
4233 else
4235 //! HasSelectedBlockMatrixFragment without selected sheet?
4236 //! or don't start dragging on a part of a matrix
4238 String aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY );
4239 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
4241 bDone = sal_True;
4242 if ( meDragInsertMode != INS_NONE )
4244 // call with bApi = sal_True to avoid error messages in drop handler
4245 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, sal_True /*bRecord*/, sal_True /*bApi*/, sal_True /*bPartOfPaste*/ );
4246 if ( bDone )
4248 pDocSh->UpdateOle( pViewData );
4249 pView->CellContentChanged();
4253 if ( bDone )
4255 pView->Unmark(); // before SetCursor, so CheckSelectionTransfer isn't called with a selection
4256 pView->SetCursor( nDestPosX, nDestPosY );
4257 bDone = pView->PasteFromClip( IDF_ALL, pTransObj->GetDocument() ); // clip-doc
4258 if ( bDone )
4260 pView->MarkRange( aDest, false, false );
4261 pView->SetCursor( aDest.aStart.Col(), aDest.aStart.Row() );
4265 pDocSh->GetUndoManager()->LeaveListAction();
4267 // no longer call ResetMark here - the inserted block has been selected
4268 // and may have been copied to primary selection
4272 sal_Int8 nRet = bDone ? nDndAction : DND_ACTION_NONE;
4273 return nRet;
4276 sal_Int8 ScGridWindow::ExecuteDrop( const ExecuteDropEvent& rEvt )
4278 DrawMarkDropObj( NULL ); // drawing layer
4280 ScModule* pScMod = SC_MOD();
4281 const ScDragData& rData = pScMod->GetDragData();
4282 if (rData.pCellTransfer)
4283 return ExecutePrivateDrop( rEvt );
4285 Point aPos = rEvt.maPosPixel;
4287 if ( !rData.aLinkDoc.isEmpty() )
4289 // try to insert a link
4291 bool bOk = true;
4292 rtl::OUString aThisName;
4293 ScDocShell* pDocSh = pViewData->GetDocShell();
4294 if (pDocSh && pDocSh->HasName())
4295 aThisName = pDocSh->GetMedium()->GetName();
4297 if ( rData.aLinkDoc.equals(aThisName) ) // error - no link within a document
4298 bOk = false;
4299 else
4301 ScViewFunc* pView = pViewData->GetView();
4302 if ( !rData.aLinkTable.isEmpty() )
4303 pView->InsertTableLink( rData.aLinkDoc, EMPTY_STRING, EMPTY_STRING,
4304 rData.aLinkTable );
4305 else if ( !rData.aLinkArea.isEmpty() )
4307 SCsCOL nPosX;
4308 SCsROW nPosY;
4309 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
4310 pView->MoveCursorAbs( nPosX, nPosY, SC_FOLLOW_NONE, false, false );
4312 pView->InsertAreaLink( rData.aLinkDoc, EMPTY_STRING, EMPTY_STRING,
4313 rData.aLinkArea, 0 );
4315 else
4317 OSL_FAIL("drop with link: no sheet nor area");
4318 bOk = false;
4322 return bOk ? rEvt.mnAction : DND_ACTION_NONE; // don't try anything else
4325 Point aLogicPos = PixelToLogic(aPos);
4327 if (rData.pDrawTransfer)
4329 sal_uInt16 nFlags = rData.pDrawTransfer->GetDragSourceFlags();
4331 sal_Bool bIsNavi = ( nFlags & SC_DROP_NAVIGATOR ) != 0;
4332 sal_Bool bIsMove = ( rEvt.mnAction == DND_ACTION_MOVE && !bIsNavi );
4334 bPasteIsMove = bIsMove;
4336 pViewData->GetView()->PasteDraw( aLogicPos, rData.pDrawTransfer->GetModel() );
4338 if (bPasteIsMove)
4339 rData.pDrawTransfer->SetDragWasInternal();
4340 bPasteIsMove = false;
4342 return rEvt.mnAction;
4346 SCsCOL nPosX;
4347 SCsROW nPosY;
4348 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
4350 if (!rData.aJumpTarget.isEmpty())
4352 // internal bookmark (from Navigator)
4353 // bookmark clipboard formats are in PasteScDataObject
4355 if ( !rData.pJumpLocalDoc || rData.pJumpLocalDoc == pViewData->GetDocument() )
4357 pViewData->GetViewShell()->InsertBookmark( rData.aJumpText, rData.aJumpTarget,
4358 nPosX, nPosY );
4359 return rEvt.mnAction;
4363 sal_Bool bIsLink = ( rEvt.mnAction == DND_ACTION_LINK );
4365 ScDocument* pThisDoc = pViewData->GetDocument();
4366 SdrObject* pHitObj = pThisDoc->GetObjectAtPoint( pViewData->GetTabNo(), PixelToLogic(aPos) );
4367 if ( pHitObj && bIsLink )
4369 // dropped on drawing object
4370 // PasteOnDrawObject checks for valid formats
4371 if ( pViewData->GetView()->PasteOnDrawObject( rEvt.maDropEvent.Transferable, pHitObj, sal_True ) )
4372 return rEvt.mnAction;
4375 sal_Bool bDone = false;
4377 sal_uLong nFormatId = bIsLink ?
4378 lcl_GetDropLinkId( rEvt.maDropEvent.Transferable ) :
4379 lcl_GetDropFormatId( rEvt.maDropEvent.Transferable );
4380 if ( nFormatId )
4382 pScMod->SetInExecuteDrop( sal_True ); // #i28468# prevent error messages from PasteDataFormat
4383 bPasteIsDrop = sal_True;
4384 bDone = pViewData->GetView()->PasteDataFormat(
4385 nFormatId, rEvt.maDropEvent.Transferable, nPosX, nPosY, &aLogicPos, bIsLink );
4386 bPasteIsDrop = false;
4387 pScMod->SetInExecuteDrop( false );
4390 sal_Int8 nRet = bDone ? rEvt.mnAction : DND_ACTION_NONE;
4391 return nRet;
4394 //--------------------------------------------------------
4396 void ScGridWindow::PasteSelection( const Point& rPosPixel )
4398 Point aLogicPos = PixelToLogic( rPosPixel );
4400 SCsCOL nPosX;
4401 SCsROW nPosY;
4402 pViewData->GetPosFromPixel( rPosPixel.X(), rPosPixel.Y(), eWhich, nPosX, nPosY );
4404 // If the mouse down was inside a visible note window, ignore it and
4405 // leave it up to the ScPostIt to handle it
4406 SdrView* pDrawView = pViewData->GetViewShell()->GetSdrView();
4407 if (pDrawView)
4409 sal_uLong nCount = pDrawView->GetMarkedObjectCount();
4410 for (sal_uLong i = 0; i < nCount; ++i)
4412 SdrObject* pObj = pDrawView->GetMarkedObjectByIndex(i);
4413 if (pObj && pObj->GetLogicRect().IsInside(aLogicPos))
4415 // Inside an active drawing object. Bail out.
4416 return;
4421 ScSelectionTransferObj* pOwnSelection = SC_MOD()->GetSelectionTransfer();
4422 if ( pOwnSelection )
4424 // within Calc
4426 ScTransferObj* pCellTransfer = pOwnSelection->GetCellData();
4427 if ( pCellTransfer )
4429 // keep a reference to the data in case the selection is changed during paste
4430 uno::Reference<datatransfer::XTransferable> xRef( pCellTransfer );
4431 DropTransferObj( pCellTransfer, nPosX, nPosY, aLogicPos, DND_ACTION_COPY );
4433 else
4435 ScDrawTransferObj* pDrawTransfer = pOwnSelection->GetDrawData();
4436 if ( pDrawTransfer )
4438 // keep a reference to the data in case the selection is changed during paste
4439 uno::Reference<datatransfer::XTransferable> xRef( pDrawTransfer );
4441 // bSameDocClipboard argument for PasteDraw is needed
4442 // because only DragData is checked directly inside PasteDraw
4443 pViewData->GetView()->PasteDraw( aLogicPos, pDrawTransfer->GetModel(), false,
4444 pDrawTransfer->GetSourceDocID() == pViewData->GetDocument()->GetDocumentID() );
4448 else
4450 // get selection from system
4452 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSelection( this ) );
4453 uno::Reference<datatransfer::XTransferable> xTransferable = aDataHelper.GetTransferable();
4454 if ( xTransferable.is() )
4456 sal_uLong nFormatId = lcl_GetDropFormatId( xTransferable, true );
4457 if ( nFormatId )
4459 bPasteIsDrop = sal_True;
4460 pViewData->GetView()->PasteDataFormat( nFormatId, xTransferable, nPosX, nPosY, &aLogicPos );
4461 bPasteIsDrop = false;
4467 //--------------------------------------------------------
4469 void ScGridWindow::UpdateEditViewPos()
4471 if (pViewData->HasEditView(eWhich))
4473 EditView* pView;
4474 SCCOL nCol;
4475 SCROW nRow;
4476 pViewData->GetEditView( eWhich, pView, nCol, nRow );
4477 SCCOL nEndCol = pViewData->GetEditEndCol();
4478 SCROW nEndRow = pViewData->GetEditEndRow();
4480 // hide EditView?
4482 sal_Bool bHide = ( nEndCol<pViewData->GetPosX(eHWhich) || nEndRow<pViewData->GetPosY(eVWhich) );
4483 if ( SC_MOD()->IsFormulaMode() )
4484 if ( pViewData->GetTabNo() != pViewData->GetRefTabNo() )
4485 bHide = sal_True;
4487 if (bHide)
4489 Rectangle aRect = pView->GetOutputArea();
4490 long nHeight = aRect.Bottom() - aRect.Top();
4491 aRect.Top() = PixelToLogic(GetOutputSizePixel(), pViewData->GetLogicMode()).
4492 Height() * 2;
4493 aRect.Bottom() = aRect.Top() + nHeight;
4494 pView->SetOutputArea( aRect );
4495 pView->HideCursor();
4497 else
4499 // bForceToTop = sal_True for editing
4500 Rectangle aPixRect = pViewData->GetEditArea( eWhich, nCol, nRow, this, NULL, sal_True );
4501 Point aScrPos = PixelToLogic( aPixRect.TopLeft(), pViewData->GetLogicMode() );
4503 Rectangle aRect = pView->GetOutputArea();
4504 aRect.SetPos( aScrPos );
4505 pView->SetOutputArea( aRect );
4506 pView->ShowCursor();
4511 void ScGridWindow::ScrollPixel( long nDifX, long nDifY )
4513 ClickExtern();
4514 HideNoteMarker();
4516 bIsInScroll = true;
4518 SetMapMode(MAP_PIXEL);
4519 Scroll( nDifX, nDifY, SCROLL_CHILDREN );
4520 SetMapMode( GetDrawMapMode() ); // verschobenen MapMode erzeugen
4522 UpdateEditViewPos();
4524 DrawAfterScroll();
4525 bIsInScroll = false;
4528 // Formeln neu zeichnen -------------------------------------------------
4530 void ScGridWindow::UpdateFormulas()
4532 if (pViewData->GetView()->IsMinimized())
4533 return;
4535 if ( nPaintCount )
4537 // nicht anfangen, verschachtelt zu painten
4538 // (dann wuerde zumindest der MapMode nicht mehr stimmen)
4540 bNeedsRepaint = true; // -> am Ende vom Paint nochmal Invalidate auf alles
4541 aRepaintPixel = Rectangle(); // alles
4542 return;
4545 SCCOL nX1 = pViewData->GetPosX( eHWhich );
4546 SCROW nY1 = pViewData->GetPosY( eVWhich );
4547 SCCOL nX2 = nX1 + pViewData->VisibleCellsX( eHWhich );
4548 SCROW nY2 = nY1 + pViewData->VisibleCellsY( eVWhich );
4550 if (nX2 > MAXCOL) nX2 = MAXCOL;
4551 if (nY2 > MAXROW) nY2 = MAXROW;
4553 // Draw( nX1, nY1, nX2, nY2, SC_UPDATE_CHANGED );
4555 // don't draw directly - instead use OutputData to find changed area and invalidate
4557 SCROW nPosY = nY1;
4559 ScDocShell* pDocSh = pViewData->GetDocShell();
4560 ScDocument* pDoc = pDocSh->GetDocument();
4561 SCTAB nTab = pViewData->GetTabNo();
4563 pDoc->ExtendHidden( nX1, nY1, nX2, nY2, nTab );
4565 Point aScrPos = pViewData->GetScrPos( nX1, nY1, eWhich );
4566 long nMirrorWidth = GetSizePixel().Width();
4567 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
4568 if ( bLayoutRTL )
4570 long nEndPixel = pViewData->GetScrPos( nX2+1, nPosY, eWhich ).X();
4571 nMirrorWidth = aScrPos.X() - nEndPixel;
4572 aScrPos.X() = nEndPixel + 1;
4575 long nScrX = aScrPos.X();
4576 long nScrY = aScrPos.Y();
4578 double nPPTX = pViewData->GetPPTX();
4579 double nPPTY = pViewData->GetPPTY();
4581 ScTableInfo aTabInfo;
4582 pDoc->FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nTab, nPPTX, nPPTY, false, false );
4584 Fraction aZoomX = pViewData->GetZoomX();
4585 Fraction aZoomY = pViewData->GetZoomY();
4586 ScOutputData aOutputData( this, OUTTYPE_WINDOW, aTabInfo, pDoc, nTab,
4587 nScrX, nScrY, nX1, nY1, nX2, nY2, nPPTX, nPPTY,
4588 &aZoomX, &aZoomY );
4589 aOutputData.SetMirrorWidth( nMirrorWidth );
4591 aOutputData.FindChanged();
4593 PolyPolygon aChangedPoly( aOutputData.GetChangedArea() ); // logic (PixelToLogic)
4594 if ( aChangedPoly.Count() )
4596 Invalidate( aChangedPoly );
4599 CheckNeedsRepaint(); // #i90362# used to be called via Draw() - still needed here
4602 void ScGridWindow::UpdateAutoFillMark(bool bMarked, const ScRange& rMarkRange)
4604 if ( bMarked != bAutoMarkVisible || ( bMarked && rMarkRange.aEnd != aAutoMarkPos ) )
4606 bAutoMarkVisible = bMarked;
4607 if ( bMarked )
4608 aAutoMarkPos = rMarkRange.aEnd;
4610 UpdateAutoFillOverlay();
4614 void ScGridWindow::UpdateListValPos( bool bVisible, const ScAddress& rPos )
4616 bool bOldButton = bListValButton;
4617 ScAddress aOldPos = aListValPos;
4619 bListValButton = bVisible;
4620 aListValPos = rPos;
4622 if ( bListValButton )
4624 if ( !bOldButton || aListValPos != aOldPos )
4626 // paint area of new button
4627 Invalidate( PixelToLogic( GetListValButtonRect( aListValPos ) ) );
4630 if ( bOldButton )
4632 if ( !bListValButton || aListValPos != aOldPos )
4634 // paint area of old button
4635 Invalidate( PixelToLogic( GetListValButtonRect( aOldPos ) ) );
4640 void ScGridWindow::HideCursor()
4642 ++nCursorHideCount;
4645 void ScGridWindow::ShowCursor()
4647 --nCursorHideCount;
4650 void ScGridWindow::GetFocus()
4652 ScTabViewShell* pViewShell = pViewData->GetViewShell();
4653 pViewShell->GotFocus();
4654 pViewShell->SetFormShellAtTop( false ); // focus in GridWindow -> FormShell no longer on top
4656 if (pViewShell->HasAccessibilityObjects())
4657 pViewShell->BroadcastAccessibility(ScAccGridWinFocusGotHint(eWhich, GetAccessible()));
4660 if ( !SC_MOD()->IsFormulaMode() )
4662 pViewShell->UpdateInputHandler();
4663 // StopMarking(); // falls Dialog (Fehler), weil dann kein ButtonUp
4664 // MO: nur wenn nicht im RefInput-Modus
4665 // -> GetFocus/MouseButtonDown-Reihenfolge
4666 // auf dem Mac
4669 pViewData->GetDocShell()->CheckConfigOptions();
4670 Window::GetFocus();
4673 void ScGridWindow::LoseFocus()
4675 ScTabViewShell* pViewShell = pViewData->GetViewShell();
4676 pViewShell->LostFocus();
4678 if (pViewShell->HasAccessibilityObjects())
4679 pViewShell->BroadcastAccessibility(ScAccGridWinFocusLostHint(eWhich, GetAccessible()));
4681 Window::LoseFocus();
4684 Point ScGridWindow::GetMousePosPixel() const { return aCurMousePos; }
4686 //------------------------------------------------------------------------
4688 bool ScGridWindow::HitRangeFinder( const Point& rMouse, bool& rCorner,
4689 sal_uInt16* pIndex, SCsCOL* pAddX, SCsROW* pAddY )
4691 bool bFound = false;
4692 ScInputHandler* pHdl = SC_MOD()->GetInputHdl( pViewData->GetViewShell() );
4693 if (pHdl)
4695 ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList();
4696 if ( pRangeFinder && !pRangeFinder->IsHidden() &&
4697 pRangeFinder->GetDocName() == pViewData->GetDocShell()->GetTitle() )
4699 ScDocument* pDoc = pViewData->GetDocument();
4700 SCTAB nTab = pViewData->GetTabNo();
4701 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
4702 long nLayoutSign = bLayoutRTL ? -1 : 1;
4704 SCsCOL nPosX;
4705 SCsROW nPosY;
4706 pViewData->GetPosFromPixel( rMouse.X(), rMouse.Y(), eWhich, nPosX, nPosY );
4707 // zusammengefasste (einzeln/Bereich) ???
4708 ScAddress aAddr( nPosX, nPosY, nTab );
4710 Point aNext = pViewData->GetScrPos( nPosX, nPosY, eWhich, true );
4711 long nSizeXPix;
4712 long nSizeYPix;
4713 pViewData->GetMergeSizePixel( nPosX, nPosY, nSizeXPix, nSizeYPix );
4714 aNext.X() += nSizeXPix * nLayoutSign;
4715 aNext.Y() += nSizeYPix;
4717 bool bCornerHor;
4718 if ( bLayoutRTL )
4719 bCornerHor = ( rMouse.X() >= aNext.X() && rMouse.X() <= aNext.X() + 8 );
4720 else
4721 bCornerHor = ( rMouse.X() >= aNext.X() - 8 && rMouse.X() <= aNext.X() );
4723 bool bCellCorner = ( bCornerHor &&
4724 rMouse.Y() >= aNext.Y() - 8 && rMouse.Y() <= aNext.Y() );
4725 // corner is hit only if the mouse is within the cell
4727 sal_uInt16 nCount = (sal_uInt16)pRangeFinder->Count();
4728 for (sal_uInt16 i=nCount; i;)
4730 // rueckwaerts suchen, damit der zuletzt gepaintete Rahmen gefunden wird
4731 --i;
4732 ScRangeFindData* pData = pRangeFinder->GetObject(i);
4733 if ( pData->aRef.In(aAddr) )
4735 if (pIndex) *pIndex = i;
4736 if (pAddX) *pAddX = nPosX - pData->aRef.aStart.Col();
4737 if (pAddY) *pAddY = nPosY - pData->aRef.aStart.Row();
4738 bFound = sal_True;
4739 rCorner = ( bCellCorner && aAddr == pData->aRef.aEnd );
4740 break;
4745 return bFound;
4748 #define SCE_TOP 1
4749 #define SCE_BOTTOM 2
4750 #define SCE_LEFT 4
4751 #define SCE_RIGHT 8
4752 #define SCE_ALL 15
4754 static void lcl_PaintOneRange( ScDocShell* pDocSh, const ScRange& rRange, sal_uInt16 nEdges )
4756 // der Range ist immer richtigherum
4758 SCCOL nCol1 = rRange.aStart.Col();
4759 SCROW nRow1 = rRange.aStart.Row();
4760 SCTAB nTab1 = rRange.aStart.Tab();
4761 SCCOL nCol2 = rRange.aEnd.Col();
4762 SCROW nRow2 = rRange.aEnd.Row();
4763 SCTAB nTab2 = rRange.aEnd.Tab();
4764 sal_Bool bHiddenEdge = false;
4765 SCROW nTmp;
4767 ScDocument* pDoc = pDocSh->GetDocument();
4768 while ( nCol1 > 0 && pDoc->ColHidden(nCol1, nTab1) )
4770 --nCol1;
4771 bHiddenEdge = sal_True;
4773 while ( nCol2 < MAXCOL && pDoc->ColHidden(nCol2, nTab1) )
4775 ++nCol2;
4776 bHiddenEdge = sal_True;
4778 nTmp = pDoc->FirstVisibleRow(0, nRow1, nTab1);
4779 if (!ValidRow(nTmp))
4780 nTmp = 0;
4781 if (nTmp < nRow1)
4783 nRow1 = nTmp;
4784 bHiddenEdge = sal_True;
4786 nTmp = pDoc->FirstVisibleRow(nRow2, MAXROW, nTab1);
4787 if (!ValidRow(nTmp))
4788 nTmp = MAXROW;
4789 if (nTmp > nRow2)
4791 nRow2 = nTmp;
4792 bHiddenEdge = sal_True;
4795 if ( nCol2 > nCol1 + 1 && nRow2 > nRow1 + 1 && !bHiddenEdge )
4797 // nur an den Raendern entlang
4798 // (die Ecken werden evtl. zweimal getroffen)
4800 if ( nEdges & SCE_TOP )
4801 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol2, nRow1, nTab2, PAINT_MARKS );
4802 if ( nEdges & SCE_LEFT )
4803 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol1, nRow2, nTab2, PAINT_MARKS );
4804 if ( nEdges & SCE_RIGHT )
4805 pDocSh->PostPaint( nCol2, nRow1, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
4806 if ( nEdges & SCE_BOTTOM )
4807 pDocSh->PostPaint( nCol1, nRow2, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
4809 else // everything in one call
4810 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
4813 static void lcl_PaintRefChanged( ScDocShell* pDocSh, const ScRange& rOldUn, const ScRange& rNewUn )
4815 // Repaint fuer die Teile des Rahmens in Old, die bei New nicht mehr da sind
4817 ScRange aOld = rOldUn;
4818 ScRange aNew = rNewUn;
4819 aOld.Justify();
4820 aNew.Justify();
4822 if ( aOld.aStart == aOld.aEnd ) //! Tab ignorieren?
4823 pDocSh->GetDocument()->ExtendMerge(aOld);
4824 if ( aNew.aStart == aNew.aEnd ) //! Tab ignorieren?
4825 pDocSh->GetDocument()->ExtendMerge(aNew);
4827 SCCOL nOldCol1 = aOld.aStart.Col();
4828 SCROW nOldRow1 = aOld.aStart.Row();
4829 SCCOL nOldCol2 = aOld.aEnd.Col();
4830 SCROW nOldRow2 = aOld.aEnd.Row();
4831 SCCOL nNewCol1 = aNew.aStart.Col();
4832 SCROW nNewRow1 = aNew.aStart.Row();
4833 SCCOL nNewCol2 = aNew.aEnd.Col();
4834 SCROW nNewRow2 = aNew.aEnd.Row();
4835 SCTAB nTab1 = aOld.aStart.Tab(); // Tab aendert sich nicht
4836 SCTAB nTab2 = aOld.aEnd.Tab();
4838 if ( nNewRow2 < nOldRow1 || nNewRow1 > nOldRow2 ||
4839 nNewCol2 < nOldCol1 || nNewCol1 > nOldCol2 ||
4840 ( nNewCol1 != nOldCol1 && nNewRow1 != nOldRow1 &&
4841 nNewCol2 != nOldCol2 && nNewRow2 != nOldRow2 ) )
4843 // komplett weggeschoben oder alle Seiten veraendert
4844 // (Abfrage <= statt < geht schief bei einzelnen Zeilen/Spalten)
4846 lcl_PaintOneRange( pDocSh, aOld, SCE_ALL );
4848 else // alle vier Kanten einzeln testen
4850 // oberer Teil
4851 if ( nNewRow1 < nOldRow1 ) // nur obere Linie loeschen
4852 lcl_PaintOneRange( pDocSh, ScRange(
4853 nOldCol1, nOldRow1, nTab1, nOldCol2, nOldRow1, nTab2 ), SCE_ALL );
4854 else if ( nNewRow1 > nOldRow1 ) // den Teil, der oben wegkommt
4855 lcl_PaintOneRange( pDocSh, ScRange(
4856 nOldCol1, nOldRow1, nTab1, nOldCol2, nNewRow1-1, nTab2 ),
4857 SCE_ALL &~ SCE_BOTTOM );
4859 // unterer Teil
4860 if ( nNewRow2 > nOldRow2 ) // nur untere Linie loeschen
4861 lcl_PaintOneRange( pDocSh, ScRange(
4862 nOldCol1, nOldRow2, nTab1, nOldCol2, nOldRow2, nTab2 ), SCE_ALL );
4863 else if ( nNewRow2 < nOldRow2 ) // den Teil, der unten wegkommt
4864 lcl_PaintOneRange( pDocSh, ScRange(
4865 nOldCol1, nNewRow2+1, nTab1, nOldCol2, nOldRow2, nTab2 ),
4866 SCE_ALL &~ SCE_TOP );
4868 // linker Teil
4869 if ( nNewCol1 < nOldCol1 ) // nur linke Linie loeschen
4870 lcl_PaintOneRange( pDocSh, ScRange(
4871 nOldCol1, nOldRow1, nTab1, nOldCol1, nOldRow2, nTab2 ), SCE_ALL );
4872 else if ( nNewCol1 > nOldCol1 ) // den Teil, der links wegkommt
4873 lcl_PaintOneRange( pDocSh, ScRange(
4874 nOldCol1, nOldRow1, nTab1, nNewCol1-1, nOldRow2, nTab2 ),
4875 SCE_ALL &~ SCE_RIGHT );
4877 // rechter Teil
4878 if ( nNewCol2 > nOldCol2 ) // nur rechte Linie loeschen
4879 lcl_PaintOneRange( pDocSh, ScRange(
4880 nOldCol2, nOldRow1, nTab1, nOldCol2, nOldRow2, nTab2 ), SCE_ALL );
4881 else if ( nNewCol2 < nOldCol2 ) // den Teil, der rechts wegkommt
4882 lcl_PaintOneRange( pDocSh, ScRange(
4883 nNewCol2+1, nOldRow1, nTab1, nOldCol2, nOldRow2, nTab2 ),
4884 SCE_ALL &~ SCE_LEFT );
4888 void ScGridWindow::RFMouseMove( const MouseEvent& rMEvt, sal_Bool bUp )
4890 ScInputHandler* pHdl = SC_MOD()->GetInputHdl( pViewData->GetViewShell() );
4891 if (!pHdl)
4892 return;
4893 ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList();
4894 if (!pRangeFinder || nRFIndex >= pRangeFinder->Count())
4895 return;
4896 ScRangeFindData* pData = pRangeFinder->GetObject( nRFIndex );
4898 // Mauszeiger
4900 if (bRFSize)
4901 SetPointer( Pointer( POINTER_CROSS ) );
4902 else
4903 SetPointer( Pointer( POINTER_HAND ) );
4905 // Scrolling
4907 sal_Bool bTimer = false;
4908 Point aPos = rMEvt.GetPosPixel();
4909 SCsCOL nDx = 0;
4910 SCsROW nDy = 0;
4911 if ( aPos.X() < 0 ) nDx = -1;
4912 if ( aPos.Y() < 0 ) nDy = -1;
4913 Size aSize = GetOutputSizePixel();
4914 if ( aPos.X() >= aSize.Width() )
4915 nDx = 1;
4916 if ( aPos.Y() >= aSize.Height() )
4917 nDy = 1;
4918 if ( nDx != 0 || nDy != 0 )
4920 if ( nDx != 0) pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) );
4921 if ( nDy != 0 ) pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) );
4922 bTimer = sal_True;
4925 // Umschalten bei Fixierung (damit Scrolling funktioniert)
4927 if ( eWhich == pViewData->GetActivePart() ) //??
4929 if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX )
4930 if ( nDx > 0 )
4932 if ( eWhich == SC_SPLIT_TOPLEFT )
4933 pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT );
4934 else if ( eWhich == SC_SPLIT_BOTTOMLEFT )
4935 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT );
4938 if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX )
4939 if ( nDy > 0 )
4941 if ( eWhich == SC_SPLIT_TOPLEFT )
4942 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT );
4943 else if ( eWhich == SC_SPLIT_TOPRIGHT )
4944 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT );
4948 // Verschieben
4950 SCsCOL nPosX;
4951 SCsROW nPosY;
4952 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
4954 ScRange aOld = pData->aRef;
4955 ScRange aNew = aOld;
4956 if ( bRFSize )
4958 aNew.aEnd.SetCol((SCCOL)nPosX);
4959 aNew.aEnd.SetRow((SCROW)nPosY);
4961 else
4963 long nStartX = nPosX - nRFAddX;
4964 if ( nStartX < 0 ) nStartX = 0;
4965 long nStartY = nPosY - nRFAddY;
4966 if ( nStartY < 0 ) nStartY = 0;
4967 long nEndX = nStartX + aOld.aEnd.Col() - aOld.aStart.Col();
4968 if ( nEndX > MAXCOL )
4970 nStartX -= ( nEndX - MAXROW );
4971 nEndX = MAXCOL;
4973 long nEndY = nStartY + aOld.aEnd.Row() - aOld.aStart.Row();
4974 if ( nEndY > MAXROW )
4976 nStartY -= ( nEndY - MAXROW );
4977 nEndY = MAXROW;
4980 aNew.aStart.SetCol((SCCOL)nStartX);
4981 aNew.aStart.SetRow((SCROW)nStartY);
4982 aNew.aEnd.SetCol((SCCOL)nEndX);
4983 aNew.aEnd.SetRow((SCROW)nEndY);
4986 if ( bUp )
4987 aNew.Justify(); // beim ButtonUp wieder richtigherum
4989 if ( aNew != aOld )
4991 pHdl->UpdateRange( nRFIndex, aNew );
4993 ScDocShell* pDocSh = pViewData->GetDocShell();
4995 // nur das neuzeichnen, was sich veraendert hat...
4996 lcl_PaintRefChanged( pDocSh, aOld, aNew );
4998 // neuen Rahmen nur drueberzeichnen (synchron)
4999 pDocSh->Broadcast( ScIndexHint( SC_HINT_SHOWRANGEFINDER, nRFIndex ) );
5001 Update(); // was man bewegt, will man auch sofort sehen
5004 // Timer fuer Scrolling
5006 if (bTimer)
5007 pViewData->GetView()->SetTimer( this, rMEvt ); // Event wiederholen
5008 else
5009 pViewData->GetView()->ResetTimer();
5012 //------------------------------------------------------------------------
5014 bool ScGridWindow::GetEditUrl( const Point& rPos,
5015 String* pName, String* pUrl, String* pTarget )
5017 return GetEditUrlOrError( false, rPos, pName, pUrl, pTarget );
5020 bool ScGridWindow::GetEditUrlOrError( bool bSpellErr, const Point& rPos,
5021 String* pName, String* pUrl, String* pTarget )
5023 //! nPosX/Y mit uebergeben?
5024 SCsCOL nPosX;
5025 SCsROW nPosY;
5026 pViewData->GetPosFromPixel( rPos.X(), rPos.Y(), eWhich, nPosX, nPosY );
5028 SCTAB nTab = pViewData->GetTabNo();
5029 ScDocShell* pDocSh = pViewData->GetDocShell();
5030 ScDocument* pDoc = pDocSh->GetDocument();
5031 ScBaseCell* pCell = NULL;
5033 sal_Bool bFound = lcl_GetHyperlinkCell( pDoc, nPosX, nPosY, nTab, pCell );
5034 if( !bFound )
5035 return false;
5037 const ScPatternAttr* pPattern = pDoc->GetPattern( nPosX, nPosY, nTab );
5038 // bForceToTop = sal_False, use the cell's real position
5039 Rectangle aEditRect = pViewData->GetEditArea( eWhich, nPosX, nPosY, this, pPattern, false );
5040 if (rPos.Y() < aEditRect.Top())
5041 return false;
5043 // vertikal kann (noch) nicht angeklickt werden:
5045 if (pPattern->GetCellOrientation() != SVX_ORIENTATION_STANDARD)
5046 return false;
5048 sal_Bool bBreak = ((SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK)).GetValue() ||
5049 ((SvxCellHorJustify)((const SvxHorJustifyItem&)pPattern->
5050 GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_BLOCK);
5051 SvxCellHorJustify eHorJust = (SvxCellHorJustify)((SvxHorJustifyItem&)pPattern->
5052 GetItem(ATTR_HOR_JUSTIFY)).GetValue();
5054 // EditEngine
5056 ScFieldEditEngine aEngine(pDoc, pDoc->GetEditPool());
5057 ScSizeDeviceProvider aProv(pDocSh);
5058 aEngine.SetRefDevice( aProv.GetDevice() );
5059 aEngine.SetRefMapMode( MAP_100TH_MM );
5060 SfxItemSet aDefault( aEngine.GetEmptyItemSet() );
5061 pPattern->FillEditItemSet( &aDefault );
5062 SvxAdjust eSvxAdjust = SVX_ADJUST_LEFT;
5063 switch (eHorJust)
5065 case SVX_HOR_JUSTIFY_LEFT:
5066 case SVX_HOR_JUSTIFY_REPEAT: // nicht implementiert
5067 case SVX_HOR_JUSTIFY_STANDARD: // always Text if an EditCell type
5068 eSvxAdjust = SVX_ADJUST_LEFT;
5069 break;
5070 case SVX_HOR_JUSTIFY_RIGHT:
5071 eSvxAdjust = SVX_ADJUST_RIGHT;
5072 break;
5073 case SVX_HOR_JUSTIFY_CENTER:
5074 eSvxAdjust = SVX_ADJUST_CENTER;
5075 break;
5076 case SVX_HOR_JUSTIFY_BLOCK:
5077 eSvxAdjust = SVX_ADJUST_BLOCK;
5078 break;
5080 aDefault.Put( SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) );
5081 aEngine.SetDefaults( aDefault );
5082 if (bSpellErr)
5083 aEngine.SetControlWord( aEngine.GetControlWord() | EE_CNTRL_ONLINESPELLING );
5085 MapMode aEditMode = pViewData->GetLogicMode(eWhich); // ohne Drawing-Skalierung
5086 Rectangle aLogicEdit = PixelToLogic( aEditRect, aEditMode );
5087 long nThisColLogic = aLogicEdit.Right() - aLogicEdit.Left() + 1;
5088 Size aPaperSize = Size( 1000000, 1000000 );
5089 if(pCell->GetCellType() == CELLTYPE_FORMULA)
5091 long nSizeX = 0;
5092 long nSizeY = 0;
5093 pViewData->GetMergeSizePixel( nPosX, nPosY, nSizeX, nSizeY );
5094 aPaperSize = Size(nSizeX, nSizeY );
5095 aPaperSize = PixelToLogic(aPaperSize);
5098 if (bBreak)
5099 aPaperSize.Width() = nThisColLogic;
5100 aEngine.SetPaperSize( aPaperSize );
5102 ::std::auto_ptr< EditTextObject > pTextObj;
5103 const EditTextObject* pData;
5104 if(pCell->GetCellType() == CELLTYPE_EDIT)
5106 ((ScEditCell*)pCell)->GetData(pData);
5107 if (pData)
5108 aEngine.SetText(*pData);
5110 else // HyperLink Formula cell
5112 pTextObj.reset((static_cast<ScFormulaCell*>(pCell))->CreateURLObject());
5113 if (pTextObj.get())
5114 aEngine.SetText(*pTextObj);
5117 long nStartX = aLogicEdit.Left();
5119 long nTextWidth = aEngine.CalcTextWidth();
5120 long nTextHeight = aEngine.GetTextHeight();
5121 if ( nTextWidth < nThisColLogic )
5123 if (eHorJust == SVX_HOR_JUSTIFY_RIGHT)
5124 nStartX += nThisColLogic - nTextWidth;
5125 else if (eHorJust == SVX_HOR_JUSTIFY_CENTER)
5126 nStartX += (nThisColLogic - nTextWidth) / 2;
5129 aLogicEdit.Left() = nStartX;
5130 if (!bBreak)
5131 aLogicEdit.Right() = nStartX + nTextWidth;
5133 // There is one glitch when dealing with a hyperlink cell and
5134 // the cell content is NUMERIC. This defaults to right aligned and
5135 // we need to adjust accordingly.
5136 if(pCell->GetCellType() == CELLTYPE_FORMULA &&
5137 static_cast<ScFormulaCell*>(pCell)->IsValue() &&
5138 eHorJust == SVX_HOR_JUSTIFY_STANDARD)
5140 aLogicEdit.Right() = aLogicEdit.Left() + nThisColLogic - 1;
5141 aLogicEdit.Left() = aLogicEdit.Right() - nTextWidth;
5143 aLogicEdit.Bottom() = aLogicEdit.Top() + nTextHeight;
5146 Point aLogicClick = PixelToLogic(rPos,aEditMode);
5147 if ( aLogicEdit.IsInside(aLogicClick) )
5149 EditView aTempView( &aEngine, this );
5150 aTempView.SetOutputArea( aLogicEdit );
5152 sal_Bool bRet = false;
5153 MapMode aOld = GetMapMode();
5154 SetMapMode(aEditMode); // kein return mehr
5156 if (bSpellErr) // Spelling-Fehler suchen
5158 bRet = aTempView.IsWrongSpelledWordAtPos( rPos );
5159 if ( bRet )
5160 pViewData->GetView()->SetCursor( nPosX, nPosY ); // Cursor setzen
5162 else // URL suchen
5164 const SvxFieldItem* pFieldItem = aTempView.GetFieldUnderMousePointer();
5166 if (pFieldItem)
5168 const SvxFieldData* pField = pFieldItem->GetField();
5169 if ( pField && pField->ISA(SvxURLField) )
5171 if ( pName || pUrl || pTarget )
5173 const SvxURLField* pURLField = (const SvxURLField*)pField;
5174 if (pName)
5175 *pName = pURLField->GetRepresentation();
5176 if (pUrl)
5177 *pUrl = pURLField->GetURL();
5178 if (pTarget)
5179 *pTarget = pURLField->GetTargetFrame();
5181 bRet = sal_True;
5186 SetMapMode(aOld);
5188 return bRet;
5190 return false;
5193 bool ScGridWindow::HasScenarioButton( const Point& rPosPixel, ScRange& rScenRange )
5195 ScDocument* pDoc = pViewData->GetDocument();
5196 SCTAB nTab = pViewData->GetTabNo();
5197 SCTAB nTabCount = pDoc->GetTableCount();
5198 if ( nTab+1<nTabCount && pDoc->IsScenario(nTab+1) && !pDoc->IsScenario(nTab) )
5200 bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5202 Size aButSize = pViewData->GetScenButSize();
5203 long nBWidth = aButSize.Width();
5204 if (!nBWidth)
5205 return false; // noch kein Button gezeichnet -> da ist auch keiner
5206 long nBHeight = aButSize.Height();
5207 long nHSpace = (long)( SC_SCENARIO_HSPACE * pViewData->GetPPTX() );
5209 //! Ranges an der Table cachen!!!!
5211 ScMarkData aMarks;
5212 for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
5213 pDoc->MarkScenario( i, nTab, aMarks, false, SC_SCENARIO_SHOWFRAME );
5214 ScRangeList aRanges;
5215 aMarks.FillRangeListWithMarks( &aRanges, false );
5218 size_t nRangeCount = aRanges.size();
5219 for (size_t j=0; j< nRangeCount; ++j)
5221 ScRange aRange = *aRanges[j];
5222 // Szenario-Rahmen immer dann auf zusammengefasste Zellen erweitern, wenn
5223 // dadurch keine neuen nicht-ueberdeckten Zellen mit umrandet werden
5224 pDoc->ExtendTotalMerge( aRange );
5226 bool bTextBelow = ( aRange.aStart.Row() == 0 );
5228 Point aButtonPos;
5229 if ( bTextBelow )
5231 aButtonPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aEnd.Row()+1,
5232 eWhich, sal_True );
5234 else
5236 aButtonPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aStart.Row(),
5237 eWhich, sal_True );
5238 aButtonPos.Y() -= nBHeight;
5240 if ( bLayoutRTL )
5241 aButtonPos.X() -= nHSpace - 1;
5242 else
5243 aButtonPos.X() -= nBWidth - nHSpace; // same for top or bottom
5245 Rectangle aButRect( aButtonPos, Size(nBWidth,nBHeight) );
5246 if ( aButRect.IsInside( rPosPixel ) )
5248 rScenRange = aRange;
5249 return true;
5254 return false;
5257 // #114409#
5258 void ScGridWindow::DrawLayerCreated()
5260 SetMapMode( GetDrawMapMode() );
5262 // initially create overlay objects
5263 ImpCreateOverlayObjects();
5266 // #114409#
5267 void ScGridWindow::CursorChanged()
5269 // here the created OverlayObjects may be transformed in later versions. For
5270 // now, just re-create them
5272 UpdateCursorOverlay();
5275 // #114409#
5276 void ScGridWindow::ImpCreateOverlayObjects()
5278 UpdateCursorOverlay();
5279 UpdateCopySourceOverlay();
5280 UpdateSelectionOverlay();
5281 UpdateAutoFillOverlay();
5282 UpdateDragRectOverlay();
5283 UpdateHeaderOverlay();
5284 UpdateShrinkOverlay();
5287 // #114409#
5288 void ScGridWindow::ImpDestroyOverlayObjects()
5290 DeleteCursorOverlay();
5291 DeleteCopySourceOverlay();
5292 DeleteSelectionOverlay();
5293 DeleteAutoFillOverlay();
5294 DeleteDragRectOverlay();
5295 DeleteHeaderOverlay();
5296 DeleteShrinkOverlay();
5299 void ScGridWindow::UpdateAllOverlays()
5301 // delete and re-allocate all overlay objects
5303 ImpDestroyOverlayObjects();
5304 ImpCreateOverlayObjects();
5307 void ScGridWindow::DeleteCursorOverlay()
5309 DELETEZ( mpOOCursors );
5312 void ScGridWindow::DeleteCopySourceOverlay()
5314 DELETEZ( mpOOSelectionBorder );
5317 void ScGridWindow::UpdateCopySourceOverlay()
5319 MapMode aDrawMode = GetDrawMapMode();
5320 MapMode aOldMode = GetMapMode();
5321 if ( aOldMode != aDrawMode )
5322 SetMapMode( aDrawMode );
5324 DeleteCopySourceOverlay();
5326 if (!pViewData->ShowPasteSource())
5327 return;
5328 rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager = getOverlayManager();
5329 if (!xOverlayManager.is())
5330 return;
5331 ScTransferObj* pTransObj = ScTransferObj::GetOwnClipboard( pViewData->GetActiveWin() );
5332 if (!pTransObj)
5333 return;
5334 ScDocument* pClipDoc = pTransObj->GetDocument();
5335 if (!pClipDoc)
5336 return;
5338 SCTAB nCurTab = pViewData->GetCurPos().Tab();
5340 ScClipParam& rClipParam = pClipDoc->GetClipParam();
5341 mpOOSelectionBorder = new ::sdr::overlay::OverlayObjectList;
5342 for ( size_t i = 0; i < rClipParam.maRanges.size(); ++i )
5344 ScRange* p = rClipParam.maRanges[i];
5345 if (p->aStart.Tab() != nCurTab)
5346 continue;
5348 SCCOL nClipStartX = p->aStart.Col();
5349 SCROW nClipStartY = p->aStart.Row();
5350 SCCOL nClipEndX = p->aEnd.Col();
5351 SCROW nClipEndY = p->aEnd.Row();
5353 Point aClipStartScrPos = pViewData->GetScrPos( nClipStartX, nClipStartY, eWhich );
5354 Point aClipEndScrPos = pViewData->GetScrPos( nClipEndX + 1, nClipEndY + 1, eWhich );
5355 aClipStartScrPos -= Point(1, 1);
5356 long nSizeXPix = aClipEndScrPos.X() - aClipStartScrPos.X();
5357 long nSizeYPix = aClipEndScrPos.Y() - aClipStartScrPos.Y();
5359 Rectangle aRect( aClipStartScrPos, Size(nSizeXPix, nSizeYPix) );
5362 Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
5364 Rectangle aLogic = PixelToLogic(aRect, aDrawMode);
5365 ::basegfx::B2DRange aRange(aLogic.Left(), aLogic.Top(), aLogic.Right(), aLogic.Bottom());
5366 ScOverlayDashedBorder* pDashedBorder = new ScOverlayDashedBorder(aRange, aHighlight);
5367 xOverlayManager->add(*pDashedBorder);
5368 mpOOSelectionBorder->append(*pDashedBorder);
5371 if ( aOldMode != aDrawMode )
5372 SetMapMode( aOldMode );
5375 void ScGridWindow::UpdateCursorOverlay()
5377 MapMode aDrawMode = GetDrawMapMode();
5378 MapMode aOldMode = GetMapMode();
5379 if ( aOldMode != aDrawMode )
5380 SetMapMode( aDrawMode );
5382 // Existing OverlayObjects may be transformed in later versions.
5383 // For now, just re-create them.
5385 DeleteCursorOverlay();
5387 std::vector<Rectangle> aPixelRects;
5390 // determine the cursor rectangles in pixels (moved from ScGridWindow::DrawCursor)
5393 SCTAB nTab = pViewData->GetTabNo();
5394 SCCOL nX = pViewData->GetCurX();
5395 SCROW nY = pViewData->GetCurY();
5397 if (!maVisibleRange.isInside(nX, nY))
5398 return;
5400 // don't show the cursor in overlapped cells
5402 ScDocument* pDoc = pViewData->GetDocument();
5403 const ScPatternAttr* pPattern = pDoc->GetPattern(nX,nY,nTab);
5404 const ScMergeFlagAttr& rMergeFlag = (const ScMergeFlagAttr&) pPattern->GetItem(ATTR_MERGE_FLAG);
5405 sal_Bool bOverlapped = rMergeFlag.IsOverlapped();
5407 // left or above of the screen?
5409 sal_Bool bVis = ( nX>=pViewData->GetPosX(eHWhich) && nY>=pViewData->GetPosY(eVWhich) );
5410 if (!bVis)
5412 SCCOL nEndX = nX;
5413 SCROW nEndY = nY;
5414 const ScMergeAttr& rMerge = (const ScMergeAttr&) pPattern->GetItem(ATTR_MERGE);
5415 if (rMerge.GetColMerge() > 1)
5416 nEndX += rMerge.GetColMerge()-1;
5417 if (rMerge.GetRowMerge() > 1)
5418 nEndY += rMerge.GetRowMerge()-1;
5419 bVis = ( nEndX>=pViewData->GetPosX(eHWhich) && nEndY>=pViewData->GetPosY(eVWhich) );
5422 if ( bVis && !bOverlapped && !pViewData->HasEditView(eWhich) && pViewData->IsActive() )
5424 Point aScrPos = pViewData->GetScrPos( nX, nY, eWhich, sal_True );
5425 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5427 // completely right of/below the screen?
5428 // (test with logical start position in aScrPos)
5429 sal_Bool bMaybeVisible;
5430 if ( bLayoutRTL )
5431 bMaybeVisible = ( aScrPos.X() >= -2 && aScrPos.Y() >= -2 );
5432 else
5434 Size aOutSize = GetOutputSizePixel();
5435 bMaybeVisible = ( aScrPos.X() <= aOutSize.Width() + 2 && aScrPos.Y() <= aOutSize.Height() + 2 );
5437 if ( bMaybeVisible )
5439 long nSizeXPix;
5440 long nSizeYPix;
5441 pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix );
5443 if ( bLayoutRTL )
5444 aScrPos.X() -= nSizeXPix - 2; // move instead of mirroring
5446 // Now, draw the cursor.
5448 aScrPos.X() -= 2;
5449 aScrPos.Y() -= 2;
5450 Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) );
5452 aPixelRects.push_back(Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() ));
5453 aPixelRects.push_back(Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() ));
5454 aPixelRects.push_back(Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 ));
5455 aPixelRects.push_back(Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() ));
5459 if ( !aPixelRects.empty() )
5461 // #i70788# get the OverlayManager safely
5462 rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager = getOverlayManager();
5464 if (xOverlayManager.is())
5466 Color aCursorColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
5467 if (pViewData->GetActivePart() != eWhich)
5468 // non-active pane uses a different color.
5469 aCursorColor = SC_MOD()->GetColorConfig().GetColorValue(svtools::CALCPAGEBREAKAUTOMATIC).nColor;
5470 std::vector< basegfx::B2DRange > aRanges;
5471 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5473 for(sal_uInt32 a(0); a < aPixelRects.size(); a++)
5475 const Rectangle aRA(aPixelRects[a]);
5476 basegfx::B2DRange aRB(aRA.Left(), aRA.Top(), aRA.Right() + 1, aRA.Bottom() + 1);
5477 aRB.transform(aTransform);
5478 aRanges.push_back(aRB);
5481 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5482 sdr::overlay::OVERLAY_SOLID,
5483 aCursorColor,
5484 aRanges,
5485 false);
5487 xOverlayManager->add(*pOverlay);
5488 mpOOCursors = new ::sdr::overlay::OverlayObjectList;
5489 mpOOCursors->append(*pOverlay);
5493 if ( aOldMode != aDrawMode )
5494 SetMapMode( aOldMode );
5497 void ScGridWindow::DeleteSelectionOverlay()
5499 DELETEZ( mpOOSelection );
5502 void ScGridWindow::UpdateSelectionOverlay()
5504 MapMode aDrawMode = GetDrawMapMode();
5505 MapMode aOldMode = GetMapMode();
5506 if ( aOldMode != aDrawMode )
5507 SetMapMode( aDrawMode );
5509 DeleteSelectionOverlay();
5510 std::vector<Rectangle> aPixelRects;
5511 GetSelectionRects( aPixelRects );
5513 if ( aPixelRects.size() && pViewData->IsActive() )
5515 // #i70788# get the OverlayManager safely
5516 rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager = getOverlayManager();
5518 if (xOverlayManager.is())
5520 std::vector< basegfx::B2DRange > aRanges;
5521 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5523 for(sal_uInt32 a(0); a < aPixelRects.size(); a++)
5525 const Rectangle aRA(aPixelRects[a]);
5526 basegfx::B2DRange aRB(aRA.Left() - 1, aRA.Top() - 1, aRA.Right(), aRA.Bottom());
5527 aRB.transform(aTransform);
5528 aRanges.push_back(aRB);
5531 // #i97672# get the system's hilight color and limit it to the maximum
5532 // allowed luminance. This is needed to react on too bright hilight colors
5533 // which would otherwise vive a bad visualisation
5534 Color aHighlight(GetSettings().GetStyleSettings().GetHighlightColor());
5535 const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
5536 const basegfx::BColor aSelection(aHighlight.getBColor());
5537 const double fLuminance(aSelection.luminance());
5538 const double fMaxLum(aSvtOptionsDrawinglayer.GetSelectionMaximumLuminancePercent() / 100.0);
5540 if(fLuminance > fMaxLum)
5542 const double fFactor(fMaxLum / fLuminance);
5543 const basegfx::BColor aNewSelection(
5544 aSelection.getRed() * fFactor,
5545 aSelection.getGreen() * fFactor,
5546 aSelection.getBlue() * fFactor);
5548 aHighlight = Color(aNewSelection);
5551 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5552 sdr::overlay::OVERLAY_TRANSPARENT,
5553 aHighlight,
5554 aRanges,
5555 true);
5557 xOverlayManager->add(*pOverlay);
5558 mpOOSelection = new ::sdr::overlay::OverlayObjectList;
5559 mpOOSelection->append(*pOverlay);
5563 if ( aOldMode != aDrawMode )
5564 SetMapMode( aOldMode );
5567 void ScGridWindow::DeleteAutoFillOverlay()
5569 DELETEZ( mpOOAutoFill );
5570 mpAutoFillRect.reset();
5573 void ScGridWindow::UpdateAutoFillOverlay()
5575 MapMode aDrawMode = GetDrawMapMode();
5576 MapMode aOldMode = GetMapMode();
5577 if ( aOldMode != aDrawMode )
5578 SetMapMode( aDrawMode );
5580 DeleteAutoFillOverlay();
5583 // get the AutoFill handle rectangle in pixels
5586 if ( bAutoMarkVisible && aAutoMarkPos.Tab() == pViewData->GetTabNo() &&
5587 !pViewData->HasEditView(eWhich) && pViewData->IsActive() )
5589 SCCOL nX = aAutoMarkPos.Col();
5590 SCROW nY = aAutoMarkPos.Row();
5592 if (!maVisibleRange.isInside(nX, nY))
5593 // Autofill mark is not visible. Bail out.
5594 return;
5596 SCTAB nTab = pViewData->GetTabNo();
5597 ScDocument* pDoc = pViewData->GetDocument();
5598 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5600 Point aFillPos = pViewData->GetScrPos( nX, nY, eWhich, sal_True );
5601 long nSizeXPix;
5602 long nSizeYPix;
5603 pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix );
5604 if ( bLayoutRTL )
5605 aFillPos.X() -= nSizeXPix + 3;
5606 else
5607 aFillPos.X() += nSizeXPix - 2;
5609 aFillPos.Y() += nSizeYPix;
5610 aFillPos.Y() -= 2;
5611 mpAutoFillRect.reset(new Rectangle(aFillPos, Size(6, 6)));
5613 // #i70788# get the OverlayManager safely
5614 rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager = getOverlayManager();
5616 if (xOverlayManager.is())
5618 Color aHandleColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
5619 if (pViewData->GetActivePart() != eWhich)
5620 // non-active pane uses a different color.
5621 aHandleColor = SC_MOD()->GetColorConfig().GetColorValue(svtools::CALCPAGEBREAKAUTOMATIC).nColor;
5622 std::vector< basegfx::B2DRange > aRanges;
5623 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5624 basegfx::B2DRange aRB(mpAutoFillRect->Left(), mpAutoFillRect->Top(), mpAutoFillRect->Right() + 1, mpAutoFillRect->Bottom() + 1);
5626 aRB.transform(aTransform);
5627 aRanges.push_back(aRB);
5629 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5630 sdr::overlay::OVERLAY_SOLID,
5631 aHandleColor,
5632 aRanges,
5633 false);
5635 xOverlayManager->add(*pOverlay);
5636 mpOOAutoFill = new ::sdr::overlay::OverlayObjectList;
5637 mpOOAutoFill->append(*pOverlay);
5640 if ( aOldMode != aDrawMode )
5641 SetMapMode( aOldMode );
5645 void ScGridWindow::DeleteDragRectOverlay()
5647 DELETEZ( mpOODragRect );
5650 void ScGridWindow::UpdateDragRectOverlay()
5652 MapMode aDrawMode = GetDrawMapMode();
5653 MapMode aOldMode = GetMapMode();
5654 if ( aOldMode != aDrawMode )
5655 SetMapMode( aDrawMode );
5657 DeleteDragRectOverlay();
5660 // get the rectangles in pixels (moved from DrawDragRect)
5663 if ( bDragRect || bPagebreakDrawn )
5665 std::vector<Rectangle> aPixelRects;
5667 SCCOL nX1 = bDragRect ? nDragStartX : aPagebreakDrag.aStart.Col();
5668 SCROW nY1 = bDragRect ? nDragStartY : aPagebreakDrag.aStart.Row();
5669 SCCOL nX2 = bDragRect ? nDragEndX : aPagebreakDrag.aEnd.Col();
5670 SCROW nY2 = bDragRect ? nDragEndY : aPagebreakDrag.aEnd.Row();
5672 SCTAB nTab = pViewData->GetTabNo();
5674 SCCOL nPosX = pViewData->GetPosX(WhichH(eWhich));
5675 SCROW nPosY = pViewData->GetPosY(WhichV(eWhich));
5676 if (nX1 < nPosX) nX1 = nPosX;
5677 if (nX2 < nPosX) nX2 = nPosX;
5678 if (nY1 < nPosY) nY1 = nPosY;
5679 if (nY2 < nPosY) nY2 = nPosY;
5681 Point aScrPos( pViewData->GetScrPos( nX1, nY1, eWhich ) );
5683 long nSizeXPix=0;
5684 long nSizeYPix=0;
5685 ScDocument* pDoc = pViewData->GetDocument();
5686 double nPPTX = pViewData->GetPPTX();
5687 double nPPTY = pViewData->GetPPTY();
5688 SCCOLROW i;
5690 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5691 long nLayoutSign = bLayoutRTL ? -1 : 1;
5693 if (ValidCol(nX2) && nX2>=nX1)
5694 for (i=nX1; i<=nX2; i++)
5695 nSizeXPix += ScViewData::ToPixel( pDoc->GetColWidth( static_cast<SCCOL>(i), nTab ), nPPTX );
5696 else
5698 aScrPos.X() -= nLayoutSign;
5699 nSizeXPix += 2;
5702 if (ValidRow(nY2) && nY2>=nY1)
5703 for (i=nY1; i<=nY2; i++)
5704 nSizeYPix += ScViewData::ToPixel( pDoc->GetRowHeight( i, nTab ), nPPTY );
5705 else
5707 aScrPos.Y() -= 1;
5708 nSizeYPix += 2;
5711 aScrPos.X() -= 2 * nLayoutSign;
5712 aScrPos.Y() -= 2;
5713 Rectangle aRect( aScrPos.X(), aScrPos.Y(),
5714 aScrPos.X() + ( nSizeXPix + 2 ) * nLayoutSign, aScrPos.Y() + nSizeYPix + 2 );
5715 if ( bLayoutRTL )
5717 aRect.Left() = aRect.Right(); // end position is left
5718 aRect.Right() = aScrPos.X();
5721 if ( meDragInsertMode == INS_CELLSDOWN )
5723 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Top()+3, aRect.Left()+1, aRect.Bottom()-2 ) );
5724 aPixelRects.push_back( Rectangle( aRect.Right()-1, aRect.Top()+3, aRect.Right()-1, aRect.Bottom()-2 ) );
5725 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Top(), aRect.Right()-1, aRect.Top()+2 ) );
5726 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Bottom()-1, aRect.Right()-1, aRect.Bottom()-1 ) );
5728 else if ( meDragInsertMode == INS_CELLSRIGHT )
5730 aPixelRects.push_back( Rectangle( aRect.Left(), aRect.Top()+1, aRect.Left()+2, aRect.Bottom()-1 ) );
5731 aPixelRects.push_back( Rectangle( aRect.Right()-1, aRect.Top()+1, aRect.Right()-1, aRect.Bottom()-1 ) );
5732 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Top()+1, aRect.Right()-2, aRect.Top()+1 ) );
5733 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Bottom()-1, aRect.Right()-2, aRect.Bottom()-1 ) );
5735 else
5737 aPixelRects.push_back( Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() ) );
5738 aPixelRects.push_back( Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() ) );
5739 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 ) );
5740 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() ) );
5743 // #i70788# get the OverlayManager safely
5744 rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager = getOverlayManager();
5746 if (xOverlayManager.is())
5748 std::vector< basegfx::B2DRange > aRanges;
5749 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5751 for(sal_uInt32 a(0); a < aPixelRects.size(); a++)
5753 const Rectangle aRA(aPixelRects[a]);
5754 basegfx::B2DRange aRB(aRA.Left(), aRA.Top(), aRA.Right() + 1, aRA.Bottom() + 1);
5755 aRB.transform(aTransform);
5756 aRanges.push_back(aRB);
5759 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5760 sdr::overlay::OVERLAY_INVERT,
5761 Color(COL_BLACK),
5762 aRanges,
5763 false);
5765 xOverlayManager->add(*pOverlay);
5766 mpOODragRect = new ::sdr::overlay::OverlayObjectList;
5767 mpOODragRect->append(*pOverlay);
5771 if ( aOldMode != aDrawMode )
5772 SetMapMode( aOldMode );
5775 void ScGridWindow::DeleteHeaderOverlay()
5777 DELETEZ( mpOOHeader );
5780 void ScGridWindow::UpdateHeaderOverlay()
5782 MapMode aDrawMode = GetDrawMapMode();
5783 MapMode aOldMode = GetMapMode();
5784 if ( aOldMode != aDrawMode )
5785 SetMapMode( aDrawMode );
5787 DeleteHeaderOverlay();
5789 // Pixel rectangle is in aInvertRect
5790 if ( !aInvertRect.IsEmpty() )
5792 // #i70788# get the OverlayManager safely
5793 rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager = getOverlayManager();
5795 if (xOverlayManager.is())
5797 // Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
5798 std::vector< basegfx::B2DRange > aRanges;
5799 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5800 basegfx::B2DRange aRB(aInvertRect.Left(), aInvertRect.Top(), aInvertRect.Right() + 1, aInvertRect.Bottom() + 1);
5802 aRB.transform(aTransform);
5803 aRanges.push_back(aRB);
5805 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5806 sdr::overlay::OVERLAY_INVERT,
5807 Color(COL_BLACK),
5808 aRanges,
5809 false);
5811 xOverlayManager->add(*pOverlay);
5812 mpOOHeader = new ::sdr::overlay::OverlayObjectList;
5813 mpOOHeader->append(*pOverlay);
5817 if ( aOldMode != aDrawMode )
5818 SetMapMode( aOldMode );
5821 void ScGridWindow::DeleteShrinkOverlay()
5823 DELETEZ( mpOOShrink );
5826 void ScGridWindow::UpdateShrinkOverlay()
5828 MapMode aDrawMode = GetDrawMapMode();
5829 MapMode aOldMode = GetMapMode();
5830 if ( aOldMode != aDrawMode )
5831 SetMapMode( aDrawMode );
5833 DeleteShrinkOverlay();
5836 // get the rectangle in pixels
5839 Rectangle aPixRect;
5840 ScRange aRange;
5841 SCTAB nTab = pViewData->GetTabNo();
5842 if ( pViewData->IsRefMode() && nTab >= pViewData->GetRefStartZ() && nTab <= pViewData->GetRefEndZ() &&
5843 pViewData->GetDelMark( aRange ) )
5845 //! limit to visible area
5846 if ( aRange.aStart.Col() <= aRange.aEnd.Col() &&
5847 aRange.aStart.Row() <= aRange.aEnd.Row() )
5849 Point aStart = pViewData->GetScrPos( aRange.aStart.Col(),
5850 aRange.aStart.Row(), eWhich );
5851 Point aEnd = pViewData->GetScrPos( aRange.aEnd.Col()+1,
5852 aRange.aEnd.Row()+1, eWhich );
5853 aEnd.X() -= 1;
5854 aEnd.Y() -= 1;
5856 aPixRect = Rectangle( aStart,aEnd );
5860 if ( !aPixRect.IsEmpty() )
5862 // #i70788# get the OverlayManager safely
5863 rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager = getOverlayManager();
5865 if (xOverlayManager.is())
5867 std::vector< basegfx::B2DRange > aRanges;
5868 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5869 basegfx::B2DRange aRB(aPixRect.Left(), aPixRect.Top(), aPixRect.Right() + 1, aPixRect.Bottom() + 1);
5871 aRB.transform(aTransform);
5872 aRanges.push_back(aRB);
5874 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5875 sdr::overlay::OVERLAY_INVERT,
5876 Color(COL_BLACK),
5877 aRanges,
5878 false);
5880 xOverlayManager->add(*pOverlay);
5881 mpOOShrink = new ::sdr::overlay::OverlayObjectList;
5882 mpOOShrink->append(*pOverlay);
5886 if ( aOldMode != aDrawMode )
5887 SetMapMode( aOldMode );
5890 // #i70788# central method to get the OverlayManager safely
5891 rtl::Reference<sdr::overlay::OverlayManager> ScGridWindow::getOverlayManager()
5893 SdrPageView* pPV = pViewData->GetView()->GetScDrawView()->GetSdrPageView();
5895 if(pPV)
5897 SdrPageWindow* pPageWin = pPV->FindPageWindow( *this );
5899 if ( pPageWin )
5901 return (pPageWin->GetOverlayManager());
5905 return rtl::Reference<sdr::overlay::OverlayManager>();
5908 void ScGridWindow::flushOverlayManager()
5910 // #i70788# get the OverlayManager safely
5911 rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager = getOverlayManager();
5913 if (xOverlayManager.is())
5914 xOverlayManager->flush();
5917 void ScGridWindow::SetInRefMode( bool bInRefMode )
5919 WinBits nBits = GetStyle();
5920 if(bInRefMode)
5921 nBits |= WB_REFMODE;
5922 else
5923 nBits &= ~WB_REFMODE;
5925 SetStyle( nBits );
5928 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */