bump product version to 4.1.6.2
[LibreOffice.git] / sc / source / ui / view / gridwin.cxx
blob4a5c9b5229474955845a7f377eac43e677c83718
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/adjustitem.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 <comphelper/classids.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 "formulacell.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>
130 #include <boost/scoped_ptr.hpp>
132 using namespace com::sun::star;
133 using ::com::sun::star::uno::Sequence;
134 using ::com::sun::star::uno::Any;
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 ScRefCellValue aCell;
356 aCell.assign(*pDoc, rRange.aEnd);
357 ScAddress aPos;
358 return (aCell.meType == CELLTYPE_FORMULA && aCell.mpFormula->GetMatrixOrigin(aPos) && aPos == rRange.aStart);
361 static void lcl_UnLockComment( ScDrawView* pView, SdrPageView* pPV, SdrModel* pDrDoc, const Point& rPos, ScViewData* pViewData )
363 if (!pView && !pPV && !pDrDoc && !pViewData)
364 return;
366 ScDocument& rDoc = *pViewData->GetDocument();
367 ScAddress aCellPos( pViewData->GetCurX(), pViewData->GetCurY(), pViewData->GetTabNo() );
368 ScPostIt* pNote = rDoc.GetNotes( aCellPos.Tab() )->findByAddress( aCellPos );
369 SdrObject* pObj = pNote ? pNote->GetCaption() : 0;
370 if( pObj && pObj->GetLogicRect().IsInside( rPos ) && ScDrawLayer::IsNoteCaption( pObj ) )
372 const ScProtectionAttr* pProtAttr = static_cast< const ScProtectionAttr* > (rDoc.GetAttr( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab(), ATTR_PROTECTION ) );
373 bool bProtectAttr = pProtAttr->GetProtection() || pProtAttr->GetHideCell() ;
374 bool bProtectDoc = rDoc.IsTabProtected( aCellPos.Tab() ) || pViewData->GetSfxDocShell()->IsReadOnly() ;
375 // unlock internal layer (if not protected), will be relocked in ScDrawView::MarkListHasChanged()
376 pView->LockInternalLayer( bProtectDoc && bProtectAttr );
380 static bool lcl_GetHyperlinkCell(
381 ScDocument* pDoc, SCCOL& rPosX, SCROW& rPosY, SCTAB nTab, ScRefCellValue& rCell, OUString& rURL )
383 bool bFound = false;
386 ScAddress aPos(rPosX, rPosY, nTab);
387 rCell.assign(*pDoc, aPos);
388 if (rCell.isEmpty())
390 if ( rPosX <= 0 )
391 return false; // alles leer bis links
392 else
393 --rPosX; // weitersuchen
395 else
397 const ScPatternAttr* pPattern = pDoc->GetPattern(aPos);
398 if ( !((SfxStringItem&)pPattern->GetItem(ATTR_HYPERLINK)).GetValue().isEmpty() )
400 rURL = ((SfxStringItem&)pPattern->GetItem(ATTR_HYPERLINK)).GetValue();
401 bFound = true;
403 else if (rCell.meType == CELLTYPE_EDIT)
404 bFound = true;
405 else if (rCell.meType == CELLTYPE_FORMULA && rCell.mpFormula->IsHyperLinkCell())
406 bFound = true;
407 else
408 return false; // andere Zelle
411 while ( !bFound );
413 return bFound;
416 // ---------------------------------------------------------------------------
417 // WB_DIALOGCONTROL noetig fuer UNO-Controls
418 ScGridWindow::ScGridWindow( Window* pParent, ScViewData* pData, ScSplitPos eWhichPos )
419 : Window( pParent, WB_CLIPCHILDREN | WB_DIALOGCONTROL ),
420 DropTargetHelper( this ),
421 DragSourceHelper( this ),
422 mpOOCursors( NULL ),
423 mpOOSelection( NULL ),
424 mpOOSelectionBorder( NULL ),
425 mpOOAutoFill( NULL ),
426 mpOODragRect( NULL ),
427 mpOOHeader( NULL ),
428 mpOOShrink( NULL ),
429 mpAutoFillRect(static_cast<Rectangle*>(NULL)),
430 pViewData( pData ),
431 eWhich( eWhichPos ),
432 pNoteMarker( NULL ),
433 pFilterBox( NULL ),
434 pFilterFloat( NULL ),
435 mpAutoFilterPopup(NULL),
436 mpDPFieldPopup(NULL),
437 mpFilterButton(NULL),
438 nCursorHideCount( 0 ),
439 nButtonDown( 0 ),
440 nMouseStatus( SC_GM_NONE ),
441 nNestedButtonState( SC_NESTEDBUTTON_NONE ),
442 nPagebreakMouse( SC_PD_NONE ),
443 nPageScript( 0 ),
444 nDragStartX( -1 ),
445 nDragStartY( -1 ),
446 nDragEndX( -1 ),
447 nDragEndY( -1 ),
448 meDragInsertMode( INS_NONE ),
449 nCurrentPointer( 0 ),
450 aComboButton( this ),
451 aCurMousePos( 0,0 ),
452 nPaintCount( 0 ),
453 bEEMouse( false ),
454 bDPMouse( false ),
455 bRFMouse( false ),
456 bRFSize( false ),
457 bPagebreakDrawn( false ),
458 bDragRect( false ),
459 bIsInScroll( false ),
460 bIsInPaint( false ),
461 bNeedsRepaint( false ),
462 bAutoMarkVisible( false ),
463 bListValButton( false )
465 switch(eWhich)
467 case SC_SPLIT_TOPLEFT:
468 eHWhich = SC_SPLIT_LEFT;
469 eVWhich = SC_SPLIT_TOP;
470 break;
471 case SC_SPLIT_TOPRIGHT:
472 eHWhich = SC_SPLIT_RIGHT;
473 eVWhich = SC_SPLIT_TOP;
474 break;
475 case SC_SPLIT_BOTTOMLEFT:
476 eHWhich = SC_SPLIT_LEFT;
477 eVWhich = SC_SPLIT_BOTTOM;
478 break;
479 case SC_SPLIT_BOTTOMRIGHT:
480 eHWhich = SC_SPLIT_RIGHT;
481 eVWhich = SC_SPLIT_BOTTOM;
482 break;
483 default:
484 OSL_FAIL("GridWindow: falsche Position");
487 SetBackground();
489 SetMapMode(pViewData->GetLogicMode(eWhich));
490 EnableChildTransparentMode();
491 SetDialogControlFlags( WINDOW_DLGCTRL_RETURN | WINDOW_DLGCTRL_WANTFOCUS );
493 SetHelpId( HID_SC_WIN_GRIDWIN );
494 SetUniqueId( HID_SC_WIN_GRIDWIN );
496 SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
497 EnableRTL( false );
500 ScGridWindow::~ScGridWindow()
502 // #114409#
503 ImpDestroyOverlayObjects();
505 delete pFilterBox;
506 delete pFilterFloat;
507 delete pNoteMarker;
510 void ScGridWindow::Resize( const Size& )
512 // gar nix
515 void ScGridWindow::ClickExtern()
519 // #i81298# don't delete the filter box when called from its select handler
520 // (possible through row header size update)
521 // #i84277# when initializing the filter box, a Basic error can deactivate the view
522 if ( pFilterBox && ( pFilterBox->IsInSelect() || pFilterBox->IsInInit() ) )
524 break;
527 DELETEZ(pFilterBox);
528 DELETEZ(pFilterFloat);
530 while (false);
532 if (mpDPFieldPopup)
534 mpDPFieldPopup->close(false);
535 mpDPFieldPopup.reset();
539 IMPL_LINK_NOARG(ScGridWindow, PopupModeEndHdl)
541 if (pFilterBox)
542 pFilterBox->SetCancelled(); // nicht mehr auswaehlen
543 GrabFocus();
544 return 0;
547 IMPL_LINK( ScGridWindow, PopupSpellingHdl, SpellCallbackInfo*, pInfo )
549 if( pInfo->nCommand == SPELLCMD_STARTSPELLDLG )
550 pViewData->GetDispatcher().Execute( SID_SPELL_DIALOG, SFX_CALLMODE_ASYNCHRON );
551 return 0;
554 void ScGridWindow::ExecPageFieldSelect( SCCOL nCol, SCROW nRow, sal_Bool bHasSelection, const String& rStr )
556 //! gridwin2 ?
558 ScDocument* pDoc = pViewData->GetDocument();
559 SCTAB nTab = pViewData->GetTabNo();
560 ScDPObject* pDPObj = pDoc->GetDPAtCursor(nCol, nRow, nTab);
561 if ( pDPObj && nCol > 0 )
563 // look for the dimension header left of the drop-down arrow
564 sal_uInt16 nOrient = sheet::DataPilotFieldOrientation_HIDDEN;
565 long nField = pDPObj->GetHeaderDim( ScAddress( nCol-1, nRow, nTab ), nOrient );
566 if ( nField >= 0 && nOrient == sheet::DataPilotFieldOrientation_PAGE )
568 ScDPSaveData aSaveData( *pDPObj->GetSaveData() );
570 bool bIsDataLayout;
571 OUString aDimName = pDPObj->GetDimName( nField, bIsDataLayout );
572 if ( !bIsDataLayout )
574 ScDPSaveDimension* pDim = aSaveData.GetDimensionByName(aDimName);
576 if ( bHasSelection )
578 const OUString aName = rStr;
579 pDim->SetCurrentPage( &aName );
581 else
582 pDim->SetCurrentPage( NULL );
584 ScDPObject aNewObj( *pDPObj );
585 aNewObj.SetSaveData( aSaveData );
586 ScDBDocFunc aFunc( *pViewData->GetDocShell() );
587 aFunc.DataPilotUpdate( pDPObj, &aNewObj, sal_True, false );
588 pViewData->GetView()->CursorPosChanged(); // shells may be switched
594 namespace {
596 struct AutoFilterData : public ScCheckListMenuWindow::ExtendedData
598 ScAddress maPos;
599 ScDBData* mpData;
602 class AutoFilterAction : public ScMenuFloatingWindow::Action
604 ScGridWindow* mpWindow;
605 ScGridWindow::AutoFilterMode meMode;
606 public:
607 AutoFilterAction(ScGridWindow* p, ScGridWindow::AutoFilterMode eMode) :
608 mpWindow(p), meMode(eMode) {}
609 virtual void execute()
611 mpWindow->UpdateAutoFilterFromMenu(meMode);
615 class AutoFilterPopupEndAction : public ScMenuFloatingWindow::Action
617 ScGridWindow* mpWindow;
618 ScAddress maPos;
619 public:
620 AutoFilterPopupEndAction(ScGridWindow* p, const ScAddress& rPos) :
621 mpWindow(p), maPos(rPos) {}
622 virtual void execute()
624 mpWindow->RefreshAutoFilterButton(maPos);
628 class AddItemToEntry : public std::unary_function<OUString, void>
630 ScQueryEntry::QueryItemsType& mrItems;
631 public:
632 AddItemToEntry(ScQueryEntry::QueryItemsType& rItems) : mrItems(rItems) {}
633 void operator() (const OUString& rSelected)
635 ScQueryEntry::Item aNew;
636 aNew.maString = rSelected;
637 aNew.meType = ScQueryEntry::ByString;
638 aNew.mfVal = 0.0;
639 mrItems.push_back(aNew);
643 class AddSelectedItemString : public std::unary_function<ScQueryEntry::Item, void>
645 boost::unordered_set<OUString, OUStringHash>& mrSet;
646 public:
647 AddSelectedItemString(boost::unordered_set<OUString, OUStringHash>& r) :
648 mrSet(r) {}
650 void operator() (const ScQueryEntry::Item& rItem)
652 mrSet.insert(rItem.maString);
658 void ScGridWindow::LaunchAutoFilterMenu(SCCOL nCol, SCROW nRow)
660 SCTAB nTab = pViewData->GetTabNo();
661 ScDocument* pDoc = pViewData->GetDocument();
663 mpAutoFilterPopup.reset(new ScCheckListMenuWindow(this, pDoc));
664 mpAutoFilterPopup->setOKAction(new AutoFilterAction(this, Normal));
665 mpAutoFilterPopup->setPopupEndAction(
666 new AutoFilterPopupEndAction(this, ScAddress(nCol, nRow, nTab)));
667 std::auto_ptr<AutoFilterData> pData(new AutoFilterData);
668 pData->maPos = ScAddress(nCol, nRow, nTab);
670 Point aPos = pViewData->GetScrPos(nCol, nRow, eWhich);
671 long nSizeX = 0;
672 long nSizeY = 0;
673 pViewData->GetMergeSizePixel(nCol, nRow, nSizeX, nSizeY);
674 Rectangle aCellRect(OutputToScreenPixel(aPos), Size(nSizeX, nSizeY));
676 ScDBData* pDBData = pDoc->GetDBAtCursor(nCol, nRow, nTab);
677 if (!pDBData)
678 return;
680 pData->mpData = pDBData;
681 mpAutoFilterPopup->setExtendedData(pData.release());
683 ScQueryParam aParam;
684 pDBData->GetQueryParam(aParam);
685 ScQueryEntry* pEntry = aParam.FindEntryByField(nCol, false);
686 boost::unordered_set<OUString, OUStringHash> aSelected;
687 if (pEntry && pEntry->bDoQuery)
689 if (pEntry->eOp == SC_EQUAL)
691 ScQueryEntry::QueryItemsType& rItems = pEntry->GetQueryItems();
692 std::for_each(rItems.begin(), rItems.end(), AddSelectedItemString(aSelected));
696 // Populate the check box list.
697 bool bHasDates = false;
698 std::vector<ScTypedStrData> aStrings;
699 pDoc->GetFilterEntries(nCol, nRow, nTab, true, aStrings, bHasDates);
701 mpAutoFilterPopup->setMemberSize(aStrings.size());
702 std::vector<ScTypedStrData>::const_iterator it = aStrings.begin(), itEnd = aStrings.end();
703 for (; it != itEnd; ++it)
705 const OUString& aVal = it->GetString();
706 bool bSelected = true;
707 if (!aSelected.empty())
708 bSelected = aSelected.count(aVal) > 0;
709 mpAutoFilterPopup->addMember(aVal, bSelected);
711 mpAutoFilterPopup->initMembers();
713 // Populate the menu.
714 mpAutoFilterPopup->addMenuItem(
715 ScRscStrLoader(RID_POPUP_FILTER, STR_MENU_SORT_ASC).GetString(),
716 true, new AutoFilterAction(this, SortAscending));
717 mpAutoFilterPopup->addMenuItem(
718 ScRscStrLoader(RID_POPUP_FILTER, STR_MENU_SORT_DESC).GetString(),
719 true, new AutoFilterAction(this, SortDescending));
720 mpAutoFilterPopup->addSeparator();
721 mpAutoFilterPopup->addMenuItem(
722 SC_RESSTR(SCSTR_TOP10FILTER), true, new AutoFilterAction(this, Top10));
723 mpAutoFilterPopup->addMenuItem(
724 SC_RESSTR(SCSTR_FILTER_EMPTY), true, new AutoFilterAction(this, Empty));
725 mpAutoFilterPopup->addMenuItem(
726 SC_RESSTR(SCSTR_FILTER_NOTEMPTY), true, new AutoFilterAction(this, NonEmpty));
727 mpAutoFilterPopup->addSeparator();
728 mpAutoFilterPopup->addMenuItem(
729 SC_RESSTR(SCSTR_STDFILTER), true, new AutoFilterAction(this, Custom));
731 ScCheckListMenuWindow::Config aConfig;
732 aConfig.mbAllowEmptySet = false;
733 aConfig.mbRTL = pViewData->GetDocument()->IsLayoutRTL(pViewData->GetTabNo());
734 mpAutoFilterPopup->setConfig(aConfig);
735 mpAutoFilterPopup->launch(aCellRect);
738 void ScGridWindow::RefreshAutoFilterButton(const ScAddress& rPos)
740 if (mpFilterButton)
742 bool bFilterActive = IsAutoFilterActive(rPos.Col(), rPos.Row(), rPos.Tab());
743 mpFilterButton->setHasHiddenMember(bFilterActive);
744 mpFilterButton->setPopupPressed(false);
745 mpFilterButton->draw();
749 void ScGridWindow::UpdateAutoFilterFromMenu(AutoFilterMode eMode)
751 const AutoFilterData* pData =
752 static_cast<const AutoFilterData*>(mpAutoFilterPopup->getExtendedData());
754 if (!pData)
755 return;
757 const ScAddress& rPos = pData->maPos;
758 ScDBData* pDBData = pData->mpData;
759 if (!pDBData)
760 return;
762 switch (eMode)
764 case SortAscending:
765 case SortDescending:
767 ScDocument* pDoc = pViewData->GetDocument();
768 SCTAB nTab = pViewData->GetTabNo();
769 SCCOL nCol = rPos.Col();
770 ScSortParam aSortParam;
771 pDBData->GetSortParam(aSortParam);
772 if (nCol < aSortParam.nCol1 || nCol > aSortParam.nCol2)
773 // out of bound
774 return;
776 bool bHasHeader = pDoc->HasColHeader(
777 aSortParam.nCol1, aSortParam.nRow1, aSortParam.nCol2, aSortParam.nRow2, nTab);
779 aSortParam.bHasHeader = bHasHeader;
780 aSortParam.bByRow = true;
781 aSortParam.bCaseSens = false;
782 aSortParam.bNaturalSort = false;
783 aSortParam.bIncludePattern = true;
784 aSortParam.bInplace = true;
785 aSortParam.maKeyState[0].bDoSort = true;
786 aSortParam.maKeyState[0].nField = nCol;
787 aSortParam.maKeyState[0].bAscending = (eMode == SortAscending);
789 for (size_t i = 1; i < aSortParam.GetSortKeyCount(); ++i)
790 aSortParam.maKeyState[i].bDoSort = false;
792 pViewData->GetViewShell()->UISort(aSortParam);
793 return;
795 default:
799 if (eMode == Custom)
801 ScRange aRange;
802 pDBData->GetArea(aRange);
803 pViewData->GetView()->MarkRange(aRange);
804 pViewData->GetView()->SetCursor(rPos.Col(), rPos.Row());
805 pViewData->GetDispatcher().Execute(SID_FILTER, SFX_CALLMODE_SLOT|SFX_CALLMODE_RECORD);
806 return;
809 ScQueryParam aParam;
810 pDBData->GetQueryParam(aParam);
812 if (eMode == Normal && mpAutoFilterPopup->isAllSelected())
814 // Remove this entry.
815 aParam.RemoveEntryByField(rPos.Col());
817 else
819 // Try to use the existing entry for the column (if one exists).
820 ScQueryEntry* pEntry = aParam.FindEntryByField(rPos.Col(), true);
822 if (!pEntry)
823 // Something went terribly wrong!
824 return;
826 pEntry->bDoQuery = true;
827 pEntry->nField = rPos.Col();
828 pEntry->eConnect = SC_AND;
830 switch (eMode)
832 case Normal:
834 pEntry->eOp = SC_EQUAL;
836 ScCheckListMenuWindow::ResultType aResult;
837 mpAutoFilterPopup->getResult(aResult);
838 std::vector<OUString> aSelected;
839 ScCheckListMenuWindow::ResultType::const_iterator itr = aResult.begin(), itrEnd = aResult.end();
840 for (; itr != itrEnd; ++itr)
842 if (itr->second)
843 aSelected.push_back(itr->first);
846 ScQueryEntry::QueryItemsType& rItems = pEntry->GetQueryItems();
847 rItems.clear();
848 std::for_each(aSelected.begin(), aSelected.end(), AddItemToEntry(rItems));
850 break;
851 case Top10:
852 pEntry->eOp = SC_TOPVAL;
853 pEntry->GetQueryItem().meType = ScQueryEntry::ByString;
854 pEntry->GetQueryItem().maString = OUString("10");
855 break;
856 case Empty:
857 pEntry->SetQueryByEmpty();
858 break;
859 case NonEmpty:
860 pEntry->SetQueryByNonEmpty();
861 break;
862 default:
863 // We don't know how to handle this!
864 return;
868 pViewData->GetView()->Query(aParam, NULL, true);
869 pDBData->SetQueryParam(aParam);
872 namespace {
874 void getCellGeometry(Point& rScrPos, Size& rScrSize, const ScViewData* pViewData, SCCOL nCol, SCROW nRow, ScSplitPos eWhich)
876 // Get the screen position of the cell.
877 rScrPos = pViewData->GetScrPos(nCol, nRow, eWhich);
879 // Get the screen size of the cell.
880 long nSizeX, nSizeY;
881 pViewData->GetMergeSizePixel(nCol, nRow, nSizeX, nSizeY);
882 rScrSize = Size(nSizeX-1, nSizeY-1);
887 void ScGridWindow::LaunchPageFieldMenu( SCCOL nCol, SCROW nRow )
889 if (nCol == 0)
890 // We assume that the page field button is located in cell to the immediate left.
891 return;
893 SCTAB nTab = pViewData->GetTabNo();
894 ScDPObject* pDPObj = pViewData->GetDocument()->GetDPAtCursor(nCol, nRow, nTab);
895 if (!pDPObj)
896 return;
898 Point aScrPos;
899 Size aScrSize;
900 getCellGeometry(aScrPos, aScrSize, pViewData, nCol, nRow, eWhich);
901 DPLaunchFieldPopupMenu(OutputToScreenPixel(aScrPos), aScrSize, ScAddress(nCol-1, nRow, nTab), pDPObj);
904 void ScGridWindow::LaunchDPFieldMenu( SCCOL nCol, SCROW nRow )
906 SCTAB nTab = pViewData->GetTabNo();
907 ScDPObject* pDPObj = pViewData->GetDocument()->GetDPAtCursor(nCol, nRow, nTab);
908 if (!pDPObj)
909 return;
911 Point aScrPos;
912 Size aScrSize;
913 getCellGeometry(aScrPos, aScrSize, pViewData, nCol, nRow, eWhich);
914 DPLaunchFieldPopupMenu(OutputToScreenPixel(aScrPos), aScrSize, ScAddress(nCol, nRow, nTab), pDPObj);
917 void ScGridWindow::DoScenarioMenu( const ScRange& rScenRange )
919 delete pFilterBox;
920 delete pFilterFloat;
922 SCCOL nCol = rScenRange.aEnd.Col(); // Zelle unterhalb des Buttons
923 SCROW nRow = rScenRange.aStart.Row();
924 if (nRow == 0)
926 nRow = rScenRange.aEnd.Row() + 1; // Bereich ganz oben -> Button unterhalb
927 if (nRow>MAXROW) nRow = MAXROW;
928 //! Texthoehe addieren (wenn sie an der View gespeichert ist...)
931 ScDocument* pDoc = pViewData->GetDocument();
932 SCTAB nTab = pViewData->GetTabNo();
933 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
935 long nSizeX = 0;
936 long nSizeY = 0;
937 long nHeight = 0;
938 pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
939 // The button height should not use the merged cell height, should still use single row height
940 nSizeY = pViewData->ToPixel(pDoc->GetRowHeight(nRow, nTab), pViewData->GetPPTY());
941 Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich );
942 if ( bLayoutRTL )
943 aPos.X() -= nSizeX;
944 Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) );
945 aCellRect.Top() -= nSizeY;
946 aCellRect.Bottom() -= nSizeY - 1;
947 // Die ListBox direkt unter der schwarzen Linie auf dem Zellgitter
948 // (wenn die Linie verdeckt wird, sieht es komisch aus...)
950 pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) ); // nicht resizable etc.
951 pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) );
952 pFilterBox = new ScFilterListBox( pFilterFloat, this, nCol, nRow, SC_FILTERBOX_SCENARIO );
953 if ( bLayoutRTL )
954 pFilterBox->EnableMirroring();
956 nSizeX += 1;
959 Font aOldFont = GetFont(); SetFont( pFilterBox->GetFont() );
960 MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL );
962 nHeight = GetTextHeight();
963 nHeight *= SC_FILTERLISTBOX_LINES;
965 SetMapMode( aOldMode );
966 SetFont( aOldFont );
969 // SetSize spaeter
971 // ParentSize Abfrage fehlt
972 Size aSize( nSizeX, nHeight );
973 pFilterBox->SetSizePixel( aSize );
974 pFilterBox->Show(); // Show muss vor SetUpdateMode kommen !!!
975 pFilterBox->SetUpdateMode(false);
977 // SetOutputSizePixel/StartPopupMode erst unten, wenn die Groesse feststeht
979 // Listbox fuellen
981 long nMaxText = 0;
982 OUString aCurrent;
983 OUString aTabName;
984 SCTAB nTabCount = pDoc->GetTableCount();
985 SCTAB nEntryCount = 0;
986 for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
988 if (pDoc->HasScenarioRange( i, rScenRange ))
989 if (pDoc->GetName( i, aTabName ))
991 pFilterBox->InsertEntry( aTabName );
992 if (pDoc->IsActiveScenario(i))
993 aCurrent = aTabName;
994 long nTextWidth = pFilterBox->GetTextWidth( aTabName );
995 if ( nTextWidth > nMaxText )
996 nMaxText = nTextWidth;
997 ++nEntryCount;
1000 if (nEntryCount > SC_FILTERLISTBOX_LINES)
1001 nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize();
1002 nMaxText += 4; // fuer Rand
1003 if ( nMaxText > 300 )
1004 nMaxText = 300; // auch nicht uebertreiben (Pixel)
1006 if (nMaxText > nSizeX) // Groesse auf benoetigte Groesse anpassen
1008 long nDiff = nMaxText - nSizeX;
1009 aSize = Size( nMaxText, nHeight );
1010 pFilterBox->SetSizePixel( aSize );
1011 pFilterFloat->SetOutputSizePixel( aSize );
1013 if ( !bLayoutRTL )
1015 // also move popup position
1016 long nNewX = aCellRect.Left() - nDiff;
1017 if ( nNewX < 0 )
1018 nNewX = 0;
1019 aCellRect.Left() = nNewX;
1023 pFilterFloat->SetOutputSizePixel( aSize );
1024 pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS );
1026 pFilterBox->SetUpdateMode(sal_True);
1027 pFilterBox->GrabFocus();
1029 sal_uInt16 nPos = LISTBOX_ENTRY_NOTFOUND;
1030 if (!aCurrent.isEmpty())
1032 nPos = pFilterBox->GetEntryPos(String(aCurrent));
1034 if (LISTBOX_ENTRY_NOTFOUND == nPos && pFilterBox->GetEntryCount() > 0 )
1035 nPos = 0;
1036 if (LISTBOX_ENTRY_NOTFOUND != nPos )
1037 pFilterBox->SelectEntryPos(nPos);
1039 pFilterBox->EndInit();
1041 // Szenario-Auswahl kommt aus MouseButtonDown:
1042 // der naechste MouseMove auf die Filterbox ist wie ein ButtonDown
1044 nMouseStatus = SC_GM_FILTER;
1045 CaptureMouse();
1048 void ScGridWindow::LaunchDataSelectMenu( SCCOL nCol, SCROW nRow, bool bDataSelect )
1050 delete pFilterBox;
1051 delete pFilterFloat;
1053 sal_uInt16 i;
1054 ScDocument* pDoc = pViewData->GetDocument();
1055 SCTAB nTab = pViewData->GetTabNo();
1056 bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1058 long nSizeX = 0;
1059 long nSizeY = 0;
1060 long nHeight = 0;
1061 pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
1062 Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich );
1063 if ( bLayoutRTL )
1064 aPos.X() -= nSizeX;
1066 Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) );
1068 aPos.X() -= 1;
1069 aPos.Y() += nSizeY - 1;
1071 pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) ); // nicht resizable etc.
1072 pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) );
1073 pFilterBox = new ScFilterListBox(
1074 pFilterFloat, this, nCol, nRow, bDataSelect ? SC_FILTERBOX_DATASELECT : SC_FILTERBOX_FILTER );
1075 // Fix for bug fdo#44925
1076 if (Application::GetSettings().GetLayoutRTL() != bLayoutRTL)
1077 pFilterBox->EnableMirroring();
1079 nSizeX += 1;
1082 Font aOldFont = GetFont(); SetFont( pFilterBox->GetFont() );
1083 MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL );
1085 nHeight = GetTextHeight();
1086 nHeight *= SC_FILTERLISTBOX_LINES;
1088 SetMapMode( aOldMode );
1089 SetFont( aOldFont );
1092 // SetSize spaeter
1094 bool bEmpty = false;
1095 std::vector<ScTypedStrData> aStrings; // case sensitive
1096 if ( bDataSelect ) // Auswahl-Liste
1098 // Liste fuellen
1099 pDoc->GetDataEntries(nCol, nRow, nTab, true, aStrings);
1100 if (aStrings.empty())
1101 bEmpty = true;
1103 else // AutoFilter
1105 //! wird der Titel ueberhaupt ausgewertet ???
1106 OUString aString = pDoc->GetString(nCol, nRow, nTab);
1107 pFilterBox->SetText( aString );
1109 long nMaxText = 0;
1111 // default entries
1112 static const sal_uInt16 nDefIDs[] = { SCSTR_TOP10FILTER, SCSTR_STDFILTER, SCSTR_FILTER_EMPTY, SCSTR_FILTER_NOTEMPTY };
1113 const size_t nDefCount = SAL_N_ELEMENTS(nDefIDs);
1114 for (i=0; i<nDefCount; i++)
1116 String aEntry( (ScResId) nDefIDs[i] );
1117 pFilterBox->InsertEntry( aEntry );
1118 long nTextWidth = pFilterBox->GetTextWidth( aEntry );
1119 if ( nTextWidth > nMaxText )
1120 nMaxText = nTextWidth;
1122 pFilterBox->SetSeparatorPos( nDefCount - 1 );
1124 // get list entries
1125 bool bHasDates = false;
1126 pDoc->GetFilterEntries( nCol, nRow, nTab, true, aStrings, bHasDates);
1127 pFilterBox->SetListHasDates(bHasDates);
1129 // check widths of numerical entries (string entries are not included)
1130 // so all numbers are completely visible
1131 std::vector<ScTypedStrData>::const_iterator it = aStrings.begin(), itEnd = aStrings.end();
1132 for (; it != itEnd; ++it)
1134 if (!it->IsStrData()) // only numerical entries
1136 long nTextWidth = pFilterBox->GetTextWidth(it->GetString());
1137 if ( nTextWidth > nMaxText )
1138 nMaxText = nTextWidth;
1142 // add scrollbar width if needed (string entries are counted here)
1143 // (scrollbar is shown if the box is exactly full?)
1144 if (aStrings.size() + nDefCount >= SC_FILTERLISTBOX_LINES)
1145 nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize();
1147 nMaxText += 4; // for borders
1149 if ( nMaxText > nSizeX )
1150 nSizeX = nMaxText; // just modify width - starting position is unchanged
1153 if (!bEmpty)
1155 // Position und Groesse an Fenster anpassen
1156 //! vorher Abfrage, ob die Eintraege hineinpassen (Breite)
1158 Size aParentSize = GetParent()->GetOutputSizePixel();
1159 Size aSize( nSizeX, nHeight );
1161 if ( aSize.Height() > aParentSize.Height() )
1162 aSize.Height() = aParentSize.Height();
1163 if ( aPos.Y() + aSize.Height() > aParentSize.Height() )
1164 aPos.Y() = aParentSize.Height() - aSize.Height();
1166 pFilterBox->SetSizePixel( aSize );
1167 pFilterBox->Show(); // Show muss vor SetUpdateMode kommen !!!
1168 pFilterBox->SetUpdateMode(false);
1170 pFilterFloat->SetOutputSizePixel( aSize );
1171 pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS);
1173 // Listbox fuellen
1174 bool bWait = aStrings.size() > 100;
1176 if (bWait)
1177 EnterWait();
1179 std::vector<ScTypedStrData>::const_iterator it = aStrings.begin(), itEnd = aStrings.end();
1180 for (; it != itEnd; ++it)
1181 pFilterBox->InsertEntry(it->GetString());
1183 if (bWait)
1184 LeaveWait();
1186 pFilterBox->SetUpdateMode(true);
1189 sal_uInt16 nSelPos = LISTBOX_ENTRY_NOTFOUND;
1191 if (!bDataSelect) // AutoFilter: aktiven Eintrag selektieren
1193 ScDBData* pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab );
1194 if (pDBData)
1196 ScQueryParam aParam;
1197 pDBData->GetQueryParam( aParam ); // kann nur MAXQUERY Eintraege ergeben
1199 sal_Bool bValid = sal_True;
1200 SCSIZE nCount = aParam.GetEntryCount();
1201 for (SCSIZE j = 0; j < nCount && bValid; ++j) // bisherige Filter-Einstellungen
1202 if (aParam.GetEntry(j).bDoQuery)
1204 //! Abfrage mit DrawButtons zusammenfassen!
1206 ScQueryEntry& rEntry = aParam.GetEntry(j);
1207 if (j>0)
1208 if (rEntry.eConnect != SC_AND)
1209 bValid = false;
1210 if (rEntry.nField == nCol)
1212 const OUString& rQueryStr = rEntry.GetQueryItem().maString;
1213 if (rEntry.eOp == SC_EQUAL)
1215 if (!rQueryStr.isEmpty())
1217 nSelPos = pFilterBox->GetEntryPos(rQueryStr);
1220 else if ( rEntry.eOp == SC_TOPVAL && rQueryStr == "10" )
1221 nSelPos = SC_AUTOFILTER_TOP10;
1222 else
1223 nSelPos = SC_AUTOFILTER_CUSTOM;
1227 if (!bValid)
1228 nSelPos = SC_AUTOFILTER_CUSTOM;
1231 else
1234 sal_uLong nIndex = ((SfxUInt32Item*)pDoc->GetAttr(
1235 nCol, nRow, nTab, ATTR_VALIDDATA ))->GetValue();
1236 if ( nIndex )
1238 const ScValidationData* pData = pDoc->GetValidationEntry( nIndex );
1239 if (pData)
1241 ScTypedStrData* pNew = NULL;
1242 OUString aDocStr = pDoc->GetString(nCol, nRow, nTab);
1243 if ( pDoc->HasValueData( nCol, nRow, nTab ) )
1245 double fVal = pDoc->GetValue(ScAddress(nCol, nRow, nTab));
1246 pNew = new ScTypedStrData(aDocStr, fVal, ScTypedStrData::Value);
1248 else
1249 pNew = new ScTypedStrData(aDocStr, 0.0, ScTypedStrData::Standard);
1251 bool bSortList = ( pData->GetListType() == ValidListType::SORTEDASCENDING);
1252 if ( bSortList )
1254 std::vector<ScTypedStrData>::const_iterator itBeg = aStrings.begin(), itEnd = aStrings.end();
1255 std::vector<ScTypedStrData>::const_iterator it =
1256 std::find_if(itBeg, itEnd, FindTypedStrData(*pNew, true));
1257 if (it != itEnd)
1258 // Found!
1259 nSelPos = std::distance(itBeg, it);
1261 else
1263 ScTypedStrData::EqualCaseSensitive aHdl;
1264 std::vector<ScTypedStrData>::const_iterator itBeg = aStrings.begin(), itEnd = aStrings.end();
1265 std::vector<ScTypedStrData>::const_iterator it = itBeg;
1266 for (; it != itEnd && LISTBOX_ENTRY_NOTFOUND == nSelPos; ++it)
1268 if (aHdl(*it, *pNew))
1269 nSelPos = std::distance(itBeg, it);
1272 delete pNew;
1277 // neu (309): irgendwas muss immer selektiert sein:
1278 if ( LISTBOX_ENTRY_NOTFOUND == nSelPos && pFilterBox->GetEntryCount() > 0 && !bDataSelect)
1279 nSelPos = 0;
1281 // keine leere Auswahl-Liste anzeigen:
1283 if ( bEmpty )
1285 DELETEZ(pFilterBox); // war nix
1286 DELETEZ(pFilterFloat);
1288 else
1290 pFilterBox->GrabFocus();
1292 // Select erst nach GrabFocus, damit das Focus-Rechteck richtig landet
1293 if ( LISTBOX_ENTRY_NOTFOUND != nSelPos )
1294 pFilterBox->SelectEntryPos( nSelPos );
1295 else
1297 if (bDataSelect)
1298 pFilterBox->SetNoSelection();
1301 pFilterBox->EndInit();
1303 if (!bDataSelect)
1305 // AutoFilter (aus MouseButtonDown):
1306 // der naechste MouseMove auf die Filterbox ist wie ein ButtonDown
1308 nMouseStatus = SC_GM_FILTER;
1309 CaptureMouse();
1314 void ScGridWindow::FilterSelect( sal_uLong nSel )
1316 String aString = pFilterBox->GetEntry( static_cast< sal_uInt16 >( nSel ) );
1318 SCCOL nCol = pFilterBox->GetCol();
1319 SCROW nRow = pFilterBox->GetRow();
1320 switch ( pFilterBox->GetMode() )
1322 case SC_FILTERBOX_DATASELECT:
1323 ExecDataSelect( nCol, nRow, aString );
1324 break;
1325 case SC_FILTERBOX_FILTER:
1326 ExecFilter( nSel, nCol, nRow, aString, pFilterBox->HasDates() );
1327 break;
1328 case SC_FILTERBOX_SCENARIO:
1329 pViewData->GetView()->UseScenario( aString );
1330 break;
1331 case SC_FILTERBOX_PAGEFIELD:
1332 // first entry is "all"
1333 ExecPageFieldSelect( nCol, nRow, (nSel != 0), aString );
1334 break;
1337 if (pFilterFloat)
1338 pFilterFloat->EndPopupMode();
1340 GrabFocus(); // unter OS/2 stimmt der Focus sonst nicht
1343 void ScGridWindow::ExecDataSelect( SCCOL nCol, SCROW nRow, const String& rStr )
1345 if ( rStr.Len() )
1347 SCTAB nTab = pViewData->GetTabNo();
1348 ScViewFunc* pView = pViewData->GetView();
1349 pView->EnterData( nCol, nRow, nTab, rStr );
1351 // #i52307# CellContentChanged is not in EnterData so it isn't called twice
1352 // if the cursor is moved afterwards.
1353 pView->CellContentChanged();
1357 void ScGridWindow::ExecFilter( sal_uLong nSel,
1358 SCCOL nCol, SCROW nRow,
1359 const String& aValue, bool bCheckForDates )
1361 SCTAB nTab = pViewData->GetTabNo();
1362 ScDocument* pDoc = pViewData->GetDocument();
1364 ScDBData* pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab );
1365 if (pDBData)
1367 ScQueryParam aParam;
1368 pDBData->GetQueryParam( aParam ); // kann nur MAXQUERY Eintraege ergeben
1370 if (SC_AUTOFILTER_CUSTOM == nSel)
1372 SCTAB nAreaTab;
1373 SCCOL nStartCol;
1374 SCROW nStartRow;
1375 SCCOL nEndCol;
1376 SCROW nEndRow;
1377 pDBData->GetArea( nAreaTab, nStartCol,nStartRow,nEndCol,nEndRow );
1378 pViewData->GetView()->MarkRange( ScRange( nStartCol,nStartRow,nAreaTab,nEndCol,nEndRow,nAreaTab));
1379 pViewData->GetView()->SetCursor(nCol,nRow); //! auch ueber Slot ??
1380 pViewData->GetDispatcher().Execute( SID_FILTER, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD );
1382 else
1384 sal_Bool bDeleteOld = false;
1385 SCSIZE nQueryPos = 0;
1386 sal_Bool bFound = false;
1387 if (!aParam.bInplace)
1388 bDeleteOld = sal_True;
1389 if (aParam.bRegExp)
1390 bDeleteOld = sal_True;
1391 SCSIZE nCount = aParam.GetEntryCount();
1392 for (SCSIZE i = 0; i < nCount && !bDeleteOld; ++i) // bisherige Filter-Einstellungen
1393 if (aParam.GetEntry(i).bDoQuery)
1395 //! Abfrage mit DrawButtons zusammenfassen!
1397 ScQueryEntry& rEntry = aParam.GetEntry(i);
1398 if (i>0)
1399 if (rEntry.eConnect != SC_AND)
1400 bDeleteOld = sal_True;
1402 if (rEntry.nField == nCol)
1404 if (bFound) // diese Spalte zweimal?
1405 bDeleteOld = sal_True;
1406 nQueryPos = i;
1407 bFound = sal_True;
1409 if (!bFound)
1410 nQueryPos = i + 1;
1413 if (bDeleteOld)
1415 SCSIZE nEC = aParam.GetEntryCount();
1416 for (SCSIZE i=0; i<nEC; i++)
1417 aParam.GetEntry(i).Clear();
1418 nQueryPos = 0;
1419 aParam.bInplace = sal_True;
1420 aParam.bRegExp = false;
1423 if ( nQueryPos < nCount || SC_AUTOFILTER_ALL == nSel ) // loeschen geht immer
1425 if (nSel)
1427 ScQueryEntry& rNewEntry = aParam.GetEntry(nQueryPos);
1428 ScQueryEntry::Item& rItem = rNewEntry.GetQueryItem();
1429 rNewEntry.bDoQuery = true;
1430 rNewEntry.nField = nCol;
1431 rItem.meType = bCheckForDates ? ScQueryEntry::ByDate : ScQueryEntry::ByString;
1433 if ( nSel == SC_AUTOFILTER_TOP10 )
1435 rNewEntry.eOp = SC_TOPVAL;
1436 rItem.maString = OUString("10");
1438 else if (nSel == SC_AUTOFILTER_EMPTY)
1440 rNewEntry.SetQueryByEmpty();
1442 else if (nSel == SC_AUTOFILTER_NOTEMPTY)
1444 rNewEntry.SetQueryByNonEmpty();
1446 else
1448 rNewEntry.eOp = SC_EQUAL;
1449 rItem.maString = aValue;
1451 if (nQueryPos > 0)
1452 rNewEntry.eConnect = SC_AND;
1454 else
1456 if (bFound)
1457 aParam.RemoveEntryByField(nCol);
1460 // end edit mode - like in ScCellShell::ExecuteDB
1461 if ( pViewData->HasEditView( pViewData->GetActivePart() ) )
1463 SC_MOD()->InputEnterHandler();
1464 pViewData->GetViewShell()->UpdateInputHandler();
1467 pViewData->GetView()->Query( aParam, NULL, true );
1468 pDBData->SetQueryParam( aParam ); // speichern
1470 else // "Zuviele Bedingungen"
1471 pViewData->GetView()->ErrorMessage( STR_FILTER_TOOMANY );
1474 else
1476 OSL_FAIL("Wo ist der Datenbankbereich?");
1480 void ScGridWindow::SetPointer( const Pointer& rPointer )
1482 nCurrentPointer = 0;
1483 Window::SetPointer( rPointer );
1486 void ScGridWindow::MoveMouseStatus( ScGridWindow& rDestWin )
1488 if (nButtonDown)
1490 rDestWin.nButtonDown = nButtonDown;
1491 rDestWin.nMouseStatus = nMouseStatus;
1494 if (bRFMouse)
1496 rDestWin.bRFMouse = bRFMouse;
1497 rDestWin.bRFSize = bRFSize;
1498 rDestWin.nRFIndex = nRFIndex;
1499 rDestWin.nRFAddX = nRFAddX;
1500 rDestWin.nRFAddY = nRFAddY;
1501 bRFMouse = false;
1504 if (nPagebreakMouse)
1506 rDestWin.nPagebreakMouse = nPagebreakMouse;
1507 rDestWin.nPagebreakBreak = nPagebreakBreak;
1508 rDestWin.nPagebreakPrev = nPagebreakPrev;
1509 rDestWin.aPagebreakSource = aPagebreakSource;
1510 rDestWin.aPagebreakDrag = aPagebreakDrag;
1511 nPagebreakMouse = SC_PD_NONE;
1515 bool ScGridWindow::TestMouse( const MouseEvent& rMEvt, bool bAction )
1517 // MouseEvent buttons must only be checked if bAction==TRUE
1518 // to allow changing the mouse pointer in MouseMove,
1519 // but not start AutoFill with right button (#74229#).
1520 // with bAction==sal_True, SetFillMode / SetDragMode is called
1522 if ( bAction && !rMEvt.IsLeft() )
1523 return false;
1525 bool bNewPointer = false;
1527 SfxInPlaceClient* pClient = pViewData->GetViewShell()->GetIPClient();
1528 bool bOleActive = ( pClient && pClient->IsObjectInPlaceActive() );
1530 if ( pViewData->IsActive() && !bOleActive )
1532 ScDocument* pDoc = pViewData->GetDocument();
1533 SCTAB nTab = pViewData->GetTabNo();
1534 bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1536 // Auto-Fill
1538 ScRange aMarkRange;
1539 if (pViewData->GetSimpleArea( aMarkRange ) == SC_MARK_SIMPLE)
1541 if (aMarkRange.aStart.Tab() == pViewData->GetTabNo() && mpAutoFillRect)
1543 Point aMousePos = rMEvt.GetPosPixel();
1544 if (mpAutoFillRect->IsInside(aMousePos))
1546 SetPointer( Pointer( POINTER_CROSS ) ); //! dickeres Kreuz ?
1547 if (bAction)
1549 SCCOL nX = aMarkRange.aEnd.Col();
1550 SCROW nY = aMarkRange.aEnd.Row();
1552 if ( lcl_IsEditableMatrix( pViewData->GetDocument(), aMarkRange ) )
1553 pViewData->SetDragMode(
1554 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nX, nY, SC_FILL_MATRIX );
1555 else
1556 pViewData->SetFillMode(
1557 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nX, nY );
1559 // The simple selection must also be recognized when dragging,
1560 // where the Marking flag is set and MarkToSimple won't work anymore.
1561 pViewData->GetMarkData().MarkToSimple();
1563 bNewPointer = true;
1568 // Embedded-Rechteck
1570 if (pDoc->IsEmbedded())
1572 ScRange aRange;
1573 pDoc->GetEmbedded( aRange );
1574 if ( pViewData->GetTabNo() == aRange.aStart.Tab() )
1576 Point aStartPos = pViewData->GetScrPos( aRange.aStart.Col(), aRange.aStart.Row(), eWhich );
1577 Point aEndPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aEnd.Row()+1, eWhich );
1578 Point aMousePos = rMEvt.GetPosPixel();
1579 if ( bLayoutRTL )
1581 aStartPos.X() += 2;
1582 aEndPos.X() += 2;
1584 bool bTop = ( aMousePos.X() >= aStartPos.X()-3 && aMousePos.X() <= aStartPos.X()+1 &&
1585 aMousePos.Y() >= aStartPos.Y()-3 && aMousePos.Y() <= aStartPos.Y()+1 );
1586 bool bBottom = ( aMousePos.X() >= aEndPos.X()-3 && aMousePos.X() <= aEndPos.X()+1 &&
1587 aMousePos.Y() >= aEndPos.Y()-3 && aMousePos.Y() <= aEndPos.Y()+1 );
1588 if ( bTop || bBottom )
1590 SetPointer( Pointer( POINTER_CROSS ) );
1591 if (bAction)
1593 sal_uInt8 nMode = bTop ? SC_FILL_EMBED_LT : SC_FILL_EMBED_RB;
1594 pViewData->SetDragMode(
1595 aRange.aStart.Col(), aRange.aStart.Row(),
1596 aRange.aEnd.Col(), aRange.aEnd.Row(), nMode );
1598 bNewPointer = true;
1604 if (!bNewPointer && bAction)
1606 pViewData->ResetFillMode();
1609 return bNewPointer;
1612 void ScGridWindow::MouseButtonDown( const MouseEvent& rMEvt )
1614 nNestedButtonState = SC_NESTEDBUTTON_DOWN;
1616 MouseEventState aState;
1617 HandleMouseButtonDown(rMEvt, aState);
1618 if (aState.mbActivatePart)
1619 pViewData->GetView()->ActivatePart(eWhich);
1621 if ( nNestedButtonState == SC_NESTEDBUTTON_UP )
1623 // #i41690# If an object is deactivated from MouseButtonDown, it might reschedule,
1624 // so MouseButtonUp comes before the MouseButtonDown call is finished. In this case,
1625 // simulate another MouseButtonUp call, so the selection state is consistent.
1627 nButtonDown = rMEvt.GetButtons();
1628 FakeButtonUp();
1630 if ( IsTracking() )
1631 EndTracking(); // normally done in VCL as part of MouseButtonUp handling
1633 nNestedButtonState = SC_NESTEDBUTTON_NONE;
1636 void ScGridWindow::HandleMouseButtonDown( const MouseEvent& rMEvt, MouseEventState& rState )
1638 // We have to check if a context menu is shown and we have an UI
1639 // active inplace client. In that case we have to ignore the event.
1640 // Otherwise we would crash (context menu has been
1641 // opened by inplace client and we would deactivate the inplace client,
1642 // the contex menu is closed by VCL asynchronously which in the end
1643 // would work on deleted objects or the context menu has no parent anymore)
1644 SfxViewShell* pViewSh = pViewData->GetViewShell();
1645 SfxInPlaceClient* pClient = pViewSh->GetIPClient();
1646 if ( pClient &&
1647 pClient->IsObjectInPlaceActive() &&
1648 PopupMenu::IsInExecute() )
1649 return;
1651 aCurMousePos = rMEvt.GetPosPixel();
1653 // Filter-Popup beendet sich mit eigenem Mausklick, nicht erst beim Klick
1654 // in das GridWindow, darum ist die folgende Abfrage nicht mehr noetig:
1655 ClickExtern(); // loescht FilterBox, wenn vorhanden
1657 HideNoteMarker(); // Notiz-Anzeige
1659 bEEMouse = false;
1661 ScModule* pScMod = SC_MOD();
1662 if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
1663 return;
1665 pScActiveViewShell = pViewData->GetViewShell(); // falls auf Link geklickt wird
1666 nScClickMouseModifier = rMEvt.GetModifier(); // um Control-Klick immer zu erkennen
1668 sal_Bool bDetective = pViewData->GetViewShell()->IsAuditShell();
1669 sal_Bool bRefMode = pViewData->IsRefMode(); // Referenz angefangen
1670 sal_Bool bFormulaMode = pScMod->IsFormulaMode(); // naechster Klick -> Referenz
1671 sal_Bool bEditMode = pViewData->HasEditView(eWhich); // auch bei Mode==SC_INPUT_TYPE
1672 sal_Bool bDouble = (rMEvt.GetClicks() == 2);
1674 // DeactivateIP passiert nur noch bei MarkListHasChanged
1676 // im GrabFocus Aufruf kann eine Fehlermeldung hochkommen
1677 // (z.B. beim Umbenennen von Tabellen per Tab-Reiter)
1679 if ( !nButtonDown || !bDouble ) // single (first) click is always valid
1680 nButtonDown = rMEvt.GetButtons(); // set nButtonDown first, so StopMarking works
1682 if ( ( bEditMode && pViewData->GetActivePart() == eWhich ) || !bFormulaMode )
1683 GrabFocus();
1685 // #i31846# need to cancel a double click if the first click has set the "ignore" state,
1686 // but a single (first) click is always valid
1687 if ( nMouseStatus == SC_GM_IGNORE && bDouble )
1689 nButtonDown = 0;
1690 nMouseStatus = SC_GM_NONE;
1691 return;
1694 if ( bDetective ) // Detektiv-Fuell-Modus
1696 if ( rMEvt.IsLeft() && !rMEvt.GetModifier() )
1698 Point aPos = rMEvt.GetPosPixel();
1699 SCsCOL nPosX;
1700 SCsROW nPosY;
1701 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
1703 SfxInt16Item aPosXItem( SID_RANGE_COL, nPosX );
1704 SfxInt32Item aPosYItem( SID_RANGE_ROW, nPosY );
1705 pViewData->GetDispatcher().Execute( SID_FILL_SELECT, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD,
1706 &aPosXItem, &aPosYItem, (void*)0L );
1709 nButtonDown = 0;
1710 nMouseStatus = SC_GM_NONE;
1711 return;
1714 if (!bDouble)
1715 nMouseStatus = SC_GM_NONE;
1717 rState.mbActivatePart = !bFormulaMode; // Don't activate when in formula mode.
1719 if (bFormulaMode)
1721 ScViewSelectionEngine* pSelEng = pViewData->GetView()->GetSelEngine();
1722 pSelEng->SetWindow(this);
1723 pSelEng->SetWhich(eWhich);
1724 pSelEng->SetVisibleArea( Rectangle(Point(), GetOutputSizePixel()) );
1727 if (bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()))
1729 Point aPos = rMEvt.GetPosPixel();
1730 SCsCOL nPosX;
1731 SCsROW nPosY;
1732 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
1734 EditView* pEditView;
1735 SCCOL nEditCol;
1736 SCROW nEditRow;
1737 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
1738 SCCOL nEndCol = pViewData->GetEditEndCol();
1739 SCROW nEndRow = pViewData->GetEditEndRow();
1741 if ( nPosX >= (SCsCOL) nEditCol && nPosX <= (SCsCOL) nEndCol &&
1742 nPosY >= (SCsROW) nEditRow && nPosY <= (SCsROW) nEndRow )
1744 // beim Klick in die Tabellen-EditView immer den Focus umsetzen
1745 if (bFormulaMode) // sonst ist es oben schon passiert
1746 GrabFocus();
1748 pScMod->SetInputMode( SC_INPUT_TABLE );
1749 bEEMouse = true;
1750 bEditMode = pEditView->MouseButtonDown( rMEvt );
1751 return;
1755 if (pScMod->GetIsWaterCan())
1757 //! was is mit'm Mac ???
1758 if ( rMEvt.GetModifier() + rMEvt.GetButtons() == MOUSE_RIGHT )
1760 nMouseStatus = SC_GM_WATERUNDO;
1761 return;
1765 // Reihenfolge passend zum angezeigten Cursor:
1766 // RangeFinder, AutoFill, PageBreak, Drawing
1768 bool bCorner;
1769 bool bFound = HitRangeFinder(rMEvt.GetPosPixel(), bCorner, &nRFIndex, &nRFAddX, &nRFAddY);
1770 bRFSize = bCorner;
1771 if (bFound)
1773 bRFMouse = true; // die anderen Variablen sind oben initialisiert
1775 rState.mbActivatePart = true; // always activate ?
1776 StartTracking();
1777 return;
1780 sal_Bool bCrossPointer = TestMouse( rMEvt, sal_True );
1781 if ( bCrossPointer )
1783 if ( bDouble )
1784 pViewData->GetView()->FillCrossDblClick();
1785 else
1786 pScMod->InputEnterHandler(); // Autofill etc.
1789 if ( !bCrossPointer )
1791 nPagebreakMouse = HitPageBreak( rMEvt.GetPosPixel(), &aPagebreakSource,
1792 &nPagebreakBreak, &nPagebreakPrev );
1793 if (nPagebreakMouse)
1795 bPagebreakDrawn = false;
1796 StartTracking();
1797 PagebreakMove( rMEvt, false );
1798 return;
1802 if (!bFormulaMode && !bEditMode && rMEvt.IsLeft())
1804 if ( !bCrossPointer && DrawMouseButtonDown(rMEvt) )
1806 return;
1809 pViewData->GetViewShell()->SetDrawShell( false ); // kein Draw-Objekt selektiert
1811 // TestMouse schon oben passiert
1814 Point aPos = rMEvt.GetPosPixel();
1815 SCsCOL nPosX;
1816 SCsROW nPosY;
1817 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
1818 SCTAB nTab = pViewData->GetTabNo();
1819 ScDocument* pDoc = pViewData->GetDocument();
1821 // Auto filter / pivot table / data select popup. This shouldn't activate the part.
1823 if ( !bDouble && !bFormulaMode && rMEvt.IsLeft() )
1825 SCsCOL nRealPosX;
1826 SCsROW nRealPosY;
1827 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nRealPosX, nRealPosY, false );//the real row/col
1828 ScMergeFlagAttr* pRealPosAttr = (ScMergeFlagAttr*)
1829 pDoc->GetAttr( nRealPosX, nRealPosY, nTab, ATTR_MERGE_FLAG );
1830 ScMergeFlagAttr* pAttr = (ScMergeFlagAttr*)
1831 pDoc->GetAttr( nPosX, nPosY, nTab, ATTR_MERGE_FLAG );
1832 if( pRealPosAttr->HasAutoFilter() )
1834 SC_MOD()->InputEnterHandler();
1835 if (DoAutoFilterButton( nRealPosX, nRealPosY, rMEvt))
1836 return;
1838 if (pAttr->HasAutoFilter())
1840 if (DoAutoFilterButton(nPosX, nPosY, rMEvt))
1842 rState.mbActivatePart = false;
1843 return;
1847 if (pAttr->HasPivotButton() || pAttr->HasPivotPopupButton())
1849 DoPushPivotButton(nPosX, nPosY, rMEvt, pAttr->HasPivotButton(), pAttr->HasPivotPopupButton());
1850 rState.mbActivatePart = false;
1851 return;
1854 // List Validity drop-down button
1856 if ( bListValButton )
1858 Rectangle aButtonRect = GetListValButtonRect( aListValPos );
1859 if ( aButtonRect.IsInside( aPos ) )
1861 LaunchDataSelectMenu( aListValPos.Col(), aListValPos.Row(), true );
1863 nMouseStatus = SC_GM_FILTER; // not set in DoAutoFilterMenue for bDataSelect
1864 CaptureMouse();
1865 rState.mbActivatePart = false;
1866 return;
1872 // scenario selection
1875 ScRange aScenRange;
1876 if ( rMEvt.IsLeft() && HasScenarioButton( aPos, aScenRange ) )
1878 DoScenarioMenu( aScenRange );
1879 return;
1883 // Doppelklick angefangen ?
1886 // StopMarking kann aus DrawMouseButtonDown gerufen werden
1888 if ( nMouseStatus != SC_GM_IGNORE && !bRefMode )
1890 if ( bDouble && !bCrossPointer )
1892 if (nMouseStatus == SC_GM_TABDOWN)
1893 nMouseStatus = SC_GM_DBLDOWN;
1895 else
1896 nMouseStatus = SC_GM_TABDOWN;
1900 // Links in Edit-Zellen
1903 sal_Bool bAlt = rMEvt.IsMod2();
1904 if ( !bAlt && rMEvt.IsLeft() &&
1905 GetEditUrl(rMEvt.GetPosPixel()) ) // Klick auf Link: Cursor nicht bewegen
1907 SetPointer( Pointer( POINTER_REFHAND ) );
1908 nMouseStatus = SC_GM_URLDOWN; // auch nur dann beim ButtonUp ausfuehren
1909 return;
1913 // Gridwin - SelectionEngine
1916 if ( rMEvt.IsLeft() )
1918 ScViewSelectionEngine* pSelEng = pViewData->GetView()->GetSelEngine();
1919 pSelEng->SetWindow(this);
1920 pSelEng->SetWhich(eWhich);
1921 pSelEng->SetVisibleArea( Rectangle(Point(), GetOutputSizePixel()) );
1923 // SelMouseButtonDown an der View setzt noch das bMoveIsShift Flag
1924 if ( pViewData->GetView()->SelMouseButtonDown( rMEvt ) )
1926 if (IsMouseCaptured())
1928 // Tracking statt CaptureMouse, damit sauber abgebrochen werden kann
1929 //! Irgendwann sollte die SelectionEngine selber StartTracking rufen!?!
1930 ReleaseMouse();
1931 StartTracking();
1933 pViewData->GetMarkData().SetMarking(sal_True);
1934 return;
1939 void ScGridWindow::MouseButtonUp( const MouseEvent& rMEvt )
1941 aCurMousePos = rMEvt.GetPosPixel();
1942 ScDocument* pDoc = pViewData->GetDocument();
1943 ScMarkData& rMark = pViewData->GetMarkData();
1945 // #i41690# detect a MouseButtonUp call from within MouseButtonDown
1946 // (possible through Reschedule from storing an OLE object that is deselected)
1948 if ( nNestedButtonState == SC_NESTEDBUTTON_DOWN )
1949 nNestedButtonState = SC_NESTEDBUTTON_UP;
1951 if (nButtonDown != rMEvt.GetButtons())
1952 nMouseStatus = SC_GM_IGNORE; // reset und return
1954 nButtonDown = 0;
1956 if (nMouseStatus == SC_GM_IGNORE)
1958 nMouseStatus = SC_GM_NONE;
1959 // Selection-Engine: Markieren abbrechen
1960 pViewData->GetView()->GetSelEngine()->Reset();
1961 rMark.SetMarking(false);
1962 if (pViewData->IsAnyFillMode())
1964 pViewData->GetView()->StopRefMode();
1965 pViewData->ResetFillMode();
1967 StopMarking();
1968 DrawEndAction(); // Markieren/Verschieben auf Drawing-Layer abbrechen
1969 ReleaseMouse();
1970 return;
1973 if (nMouseStatus == SC_GM_FILTER)
1975 nMouseStatus = SC_GM_NONE;
1976 ReleaseMouse();
1977 return; // da muss nix mehr passieren
1980 ScModule* pScMod = SC_MOD();
1981 if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
1982 return;
1984 SfxBindings& rBindings = pViewData->GetBindings();
1985 if (bEEMouse && pViewData->HasEditView( eWhich ))
1987 EditView* pEditView;
1988 SCCOL nEditCol;
1989 SCROW nEditRow;
1990 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
1991 pEditView->MouseButtonUp( rMEvt );
1993 if ( rMEvt.IsMiddle() &&
1994 GetSettings().GetMouseSettings().GetMiddleButtonAction() == MOUSE_MIDDLE_PASTESELECTION )
1996 // EditView may have pasted from selection
1997 pScMod->InputChanged( pEditView );
1999 else
2000 pScMod->InputSelection( pEditView ); // parentheses etc.
2002 pViewData->GetView()->InvalidateAttribs();
2003 rBindings.Invalidate( SID_HYPERLINK_GETLINK );
2004 bEEMouse = false;
2005 return;
2008 if (bDPMouse)
2010 DPMouseButtonUp( rMEvt ); // resets bDPMouse
2011 return;
2014 if (bRFMouse)
2016 RFMouseMove( rMEvt, sal_True ); // Range wieder richtigherum
2017 bRFMouse = false;
2018 SetPointer( Pointer( POINTER_ARROW ) );
2019 ReleaseMouse();
2020 return;
2023 if (nPagebreakMouse)
2025 PagebreakMove( rMEvt, sal_True );
2026 nPagebreakMouse = SC_PD_NONE;
2027 SetPointer( Pointer( POINTER_ARROW ) );
2028 ReleaseMouse();
2029 return;
2032 if (nMouseStatus == SC_GM_WATERUNDO) // Undo im Giesskannenmodus
2034 ::svl::IUndoManager* pMgr = pViewData->GetDocShell()->GetUndoManager();
2035 if ( pMgr->GetUndoActionCount() && pMgr->GetUndoActionId() == STR_UNDO_APPLYCELLSTYLE )
2036 pMgr->Undo();
2037 return;
2040 if (DrawMouseButtonUp(rMEvt)) // includes format paint brush handling for drawing objects
2042 ScTabViewShell* pViewShell = pViewData->GetViewShell();
2043 SfxBindings& rFrmBindings=pViewShell->GetViewFrame()->GetBindings();
2044 rFrmBindings.Invalidate(SID_ATTR_TRANSFORM_WIDTH);
2045 rFrmBindings.Invalidate(SID_ATTR_TRANSFORM_HEIGHT);
2046 rFrmBindings.Invalidate(SID_ATTR_TRANSFORM_POS_X);
2047 rFrmBindings.Invalidate(SID_ATTR_TRANSFORM_POS_Y);
2048 rFrmBindings.Invalidate(SID_ATTR_TRANSFORM_ANGLE);
2049 rFrmBindings.Invalidate(SID_ATTR_TRANSFORM_ROT_X);
2050 rFrmBindings.Invalidate(SID_ATTR_TRANSFORM_ROT_Y);
2051 rFrmBindings.Invalidate(SID_ATTR_TRANSFORM_AUTOWIDTH);
2052 rFrmBindings.Invalidate(SID_ATTR_TRANSFORM_AUTOHEIGHT);
2053 return;
2056 rMark.SetMarking(false);
2058 SetPointer( Pointer( POINTER_ARROW ) );
2060 if (pViewData->IsFillMode() ||
2061 ( pViewData->GetFillMode() == SC_FILL_MATRIX && rMEvt.IsMod1() ))
2063 nScFillModeMouseModifier = rMEvt.GetModifier();
2064 SCCOL nStartCol;
2065 SCROW nStartRow;
2066 SCCOL nEndCol;
2067 SCROW nEndRow;
2068 pViewData->GetFillData( nStartCol, nStartRow, nEndCol, nEndRow );
2069 ScRange aDelRange;
2070 sal_Bool bIsDel = pViewData->GetDelMark( aDelRange );
2072 ScViewFunc* pView = pViewData->GetView();
2073 pView->StopRefMode();
2074 pViewData->ResetFillMode();
2075 pView->GetFunctionSet()->SetAnchorFlag( false ); // #i5819# don't use AutoFill anchor flag for selection
2077 if ( bIsDel )
2079 pView->MarkRange( aDelRange, false );
2080 pView->DeleteContents( IDF_CONTENTS );
2081 SCTAB nTab = pViewData->GetTabNo();
2082 ScRange aBlockRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab );
2083 if ( aBlockRange != aDelRange )
2085 if ( aDelRange.aStart.Row() == nStartRow )
2086 aBlockRange.aEnd.SetCol( aDelRange.aStart.Col() - 1 );
2087 else
2088 aBlockRange.aEnd.SetRow( aDelRange.aStart.Row() - 1 );
2089 pView->MarkRange( aBlockRange, false );
2092 else
2093 pViewData->GetDispatcher().Execute( FID_FILL_AUTO, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD );
2095 else if (pViewData->GetFillMode() == SC_FILL_MATRIX)
2097 SCTAB nTab = pViewData->GetTabNo();
2098 SCCOL nStartCol;
2099 SCROW nStartRow;
2100 SCCOL nEndCol;
2101 SCROW nEndRow;
2102 pViewData->GetFillData( nStartCol, nStartRow, nEndCol, nEndRow );
2103 ScRange aBlockRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab );
2104 SCCOL nFillCol = pViewData->GetRefEndX();
2105 SCROW nFillRow = pViewData->GetRefEndY();
2106 ScAddress aEndPos( nFillCol, nFillRow, nTab );
2108 ScTabView* pView = pViewData->GetView();
2109 pView->StopRefMode();
2110 pViewData->ResetFillMode();
2111 pView->GetFunctionSet()->SetAnchorFlag( false );
2113 if ( aEndPos != aBlockRange.aEnd )
2115 pViewData->GetDocShell()->GetDocFunc().ResizeMatrix( aBlockRange, aEndPos, false );
2116 pViewData->GetView()->MarkRange( ScRange( aBlockRange.aStart, aEndPos ) );
2119 else if (pViewData->IsAnyFillMode())
2121 // Embedded-Area has been changed
2122 ScTabView* pView = pViewData->GetView();
2123 pView->StopRefMode();
2124 pViewData->ResetFillMode();
2125 pView->GetFunctionSet()->SetAnchorFlag( false );
2126 pViewData->GetDocShell()->UpdateOle(pViewData);
2129 sal_Bool bRefMode = pViewData->IsRefMode();
2130 if (bRefMode)
2131 pScMod->EndReference();
2134 // Giesskannen-Modus (Gestalter)
2137 if (pScMod->GetIsWaterCan())
2139 // Abfrage auf Undo schon oben
2141 ScStyleSheetPool* pStylePool = (ScStyleSheetPool*)
2142 (pViewData->GetDocument()->
2143 GetStyleSheetPool());
2144 if ( pStylePool )
2146 SfxStyleSheet* pStyleSheet = (SfxStyleSheet*)
2147 pStylePool->GetActualStyleSheet();
2149 if ( pStyleSheet )
2151 SfxStyleFamily eFamily = pStyleSheet->GetFamily();
2153 switch ( eFamily )
2155 case SFX_STYLE_FAMILY_PARA:
2156 pViewData->GetView()->SetStyleSheetToMarked( pStyleSheet );
2157 pViewData->GetView()->DoneBlockMode();
2158 break;
2160 case SFX_STYLE_FAMILY_PAGE:
2161 pViewData->GetDocument()->SetPageStyle( pViewData->GetTabNo(),
2162 pStyleSheet->GetName() );
2164 ScPrintFunc( pViewData->GetDocShell(),
2165 pViewData->GetViewShell()->GetPrinter(sal_True),
2166 pViewData->GetTabNo() ).UpdatePages();
2168 rBindings.Invalidate( SID_STATUS_PAGESTYLE );
2169 break;
2171 default:
2172 break;
2178 ScDBFunc* pView = pViewData->GetView();
2179 ScDocument* pBrushDoc = pView->GetBrushDocument();
2180 if ( pBrushDoc )
2182 pView->PasteFromClip( IDF_ATTRIB, pBrushDoc );
2183 if ( !pView->IsPaintBrushLocked() )
2184 pView->ResetBrushDocument(); // invalidates pBrushDoc pointer
2188 // double click (only left button)
2191 sal_Bool bDouble = ( rMEvt.GetClicks() == 2 && rMEvt.IsLeft() );
2192 if ( bDouble && !bRefMode && nMouseStatus == SC_GM_DBLDOWN && !pScMod->IsRefDialogOpen() )
2194 // data pilot table
2195 Point aPos = rMEvt.GetPosPixel();
2196 SCsCOL nPosX;
2197 SCsROW nPosY;
2198 SCTAB nTab = pViewData->GetTabNo();
2199 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
2200 ScDPObject* pDPObj = pDoc->GetDPAtCursor( nPosX, nPosY, nTab );
2201 if ( pDPObj && pDPObj->GetSaveData()->GetDrillDown() )
2203 ScAddress aCellPos( nPosX, nPosY, pViewData->GetTabNo() );
2205 // Check for header drill-down first.
2206 sheet::DataPilotTableHeaderData aData;
2207 pDPObj->GetHeaderPositionData(aCellPos, aData);
2209 if ( ( aData.Flags & sheet::MemberResultFlags::HASMEMBER ) &&
2210 ! ( aData.Flags & sheet::MemberResultFlags::SUBTOTAL ) )
2212 sal_uInt16 nDummy;
2213 if ( pView->HasSelectionForDrillDown( nDummy ) )
2215 // execute slot to show dialog
2216 pViewData->GetDispatcher().Execute( SID_OUTLINE_SHOW, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD );
2218 else
2220 // toggle single entry
2221 ScDPObject aNewObj( *pDPObj );
2222 pDPObj->ToggleDetails( aData, &aNewObj );
2223 ScDBDocFunc aFunc( *pViewData->GetDocShell() );
2224 aFunc.DataPilotUpdate( pDPObj, &aNewObj, sal_True, false );
2225 pViewData->GetView()->CursorPosChanged(); // shells may be switched
2228 else
2230 // Check if the data area is double-clicked.
2232 Sequence<sheet::DataPilotFieldFilter> aFilters;
2233 if ( pDPObj->GetDataFieldPositionData(aCellPos, aFilters) )
2234 pViewData->GetView()->ShowDataPilotSourceData( *pDPObj, aFilters );
2237 return;
2240 // Check for cell protection attribute.
2241 ScTableProtection* pProtect = pDoc->GetTabProtection( nTab );
2242 bool bEditAllowed = true;
2243 if ( pProtect && pProtect->isProtected() )
2245 bool bCellProtected = pDoc->HasAttrib(nPosX, nPosY, nTab, nPosX, nPosY, nTab, HASATTR_PROTECTED);
2246 bool bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
2247 bool bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
2249 if ( bSkipProtected && bSkipUnprotected )
2250 bEditAllowed = false;
2251 else if ( (bCellProtected && bSkipProtected) || (!bCellProtected && bSkipUnprotected) )
2252 bEditAllowed = false;
2255 if ( bEditAllowed )
2257 // edit cell contents
2258 pViewData->GetViewShell()->UpdateInputHandler();
2259 pScMod->SetInputMode( SC_INPUT_TABLE );
2260 if (pViewData->HasEditView(eWhich))
2262 // Text-Cursor gleich an die geklickte Stelle setzen
2263 EditView* pEditView = pViewData->GetEditView( eWhich );
2264 MouseEvent aEditEvt( rMEvt.GetPosPixel(), 1, MOUSE_SYNTHETIC, MOUSE_LEFT, 0 );
2265 pEditView->MouseButtonDown( aEditEvt );
2266 pEditView->MouseButtonUp( aEditEvt );
2269 return;
2273 // Links in edit cells
2276 sal_Bool bAlt = rMEvt.IsMod2();
2277 if ( !bAlt && !bRefMode && !bDouble && nMouseStatus == SC_GM_URLDOWN )
2279 // beim ButtonUp nur ausfuehren, wenn ButtonDown auch ueber einer URL war
2281 String aName, aUrl, aTarget;
2282 if ( GetEditUrl( rMEvt.GetPosPixel(), &aName, &aUrl, &aTarget ) )
2284 nMouseStatus = SC_GM_NONE; // keinen Doppelklick anfangen
2286 // ScGlobal::OpenURL() only understands Calc A1 style syntax.
2287 // Convert it to Calc A1 before calling OpenURL().
2289 if (pDoc->GetAddressConvention() == formula::FormulaGrammar::CONV_OOO)
2290 ScGlobal::OpenURL(aUrl, aTarget);
2291 else
2293 ScAddress aTempAddr;
2294 ScAddress::ExternalInfo aExtInfo;
2295 sal_uInt16 nRes = aTempAddr.Parse(aUrl, pDoc, pDoc->GetAddressConvention(), &aExtInfo);
2296 if (!(nRes & SCA_VALID))
2298 // Not a reference string. Pass it through unmodified.
2299 ScGlobal::OpenURL(aUrl, aTarget);
2300 return;
2303 OUStringBuffer aBuf;
2304 if (aExtInfo.mbExternal)
2306 // External reference.
2307 ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
2308 const OUString* pStr = pRefMgr->getExternalFileName(aExtInfo.mnFileId);
2309 if (pStr)
2310 aBuf.append(*pStr);
2312 aBuf.append('#');
2313 aBuf.append(aExtInfo.maTabName);
2314 aBuf.append('.');
2315 OUString aRefCalcA1;
2316 aTempAddr.Format(aRefCalcA1, SCA_ABS, NULL, formula::FormulaGrammar::CONV_OOO);
2317 aBuf.append(aRefCalcA1);
2318 ScGlobal::OpenURL(aBuf.makeStringAndClear(), aTarget);
2320 else
2322 // Internal reference.
2323 aBuf.append('#');
2324 OUString aUrlCalcA1;
2325 aTempAddr.Format(aUrlCalcA1, SCA_ABS_3D, pDoc, formula::FormulaGrammar::CONV_OOO);
2326 aBuf.append(aUrlCalcA1);
2327 ScGlobal::OpenURL(aBuf.makeStringAndClear(), aTarget);
2331 // fire worksheet_followhyperlink event
2332 uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents = pDoc->GetVbaEventProcessor();
2333 if( xVbaEvents.is() ) try
2335 Point aPos = rMEvt.GetPosPixel();
2336 SCsCOL nPosX;
2337 SCsROW nPosY;
2338 SCTAB nTab = pViewData->GetTabNo();
2339 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
2340 OUString sURL;
2341 ScRefCellValue aCell;
2342 if (lcl_GetHyperlinkCell(pDoc, nPosX, nPosY, nTab, aCell, sURL))
2344 ScAddress aCellPos( nPosX, nPosY, nTab );
2345 uno::Reference< table::XCell > xCell( new ScCellObj( pViewData->GetDocShell(), aCellPos ) );
2346 uno::Sequence< uno::Any > aArgs(1);
2347 aArgs[0] <<= xCell;
2348 xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKSHEET_FOLLOWHYPERLINK, aArgs );
2351 catch( uno::Exception& )
2355 return;
2360 // Gridwin - SelectionEngine
2363 // SelMouseButtonDown is called only for left button, but SelMouseButtonUp would return
2364 // sal_True for any call, so IsLeft must be checked here, too.
2366 if ( rMEvt.IsLeft() && pViewData->GetView()->GetSelEngine()->SelMouseButtonUp( rMEvt ) )
2368 pViewData->GetView()->SelectionChanged();
2370 SfxDispatcher* pDisp = pViewData->GetViewShell()->GetDispatcher();
2371 sal_Bool bFormulaMode = pScMod->IsFormulaMode();
2372 OSL_ENSURE( pDisp || bFormulaMode, "Cursor auf nicht aktiver View bewegen ?" );
2374 // #i14927# execute SID_CURRENTCELL (for macro recording) only if there is no
2375 // multiple selection, so the argument string completely describes the selection,
2376 // and executing the slot won't change the existing selection (executing the slot
2377 // here and from a recorded macro is treated equally)
2379 if ( pDisp && !bFormulaMode && !rMark.IsMultiMarked() )
2381 String aAddr; // CurrentCell
2382 if( rMark.IsMarked() )
2384 ScRange aScRange;
2385 rMark.GetMarkArea( aScRange );
2386 aScRange.Format( aAddr, SCR_ABS );
2387 if ( aScRange.aStart == aScRange.aEnd )
2389 // make sure there is a range selection string even for a single cell
2390 String aSingle = aAddr;
2391 aAddr.Append( (sal_Char) ':' );
2392 aAddr.Append( aSingle );
2395 //! SID_MARKAREA gibts nicht mehr ???
2396 //! was passiert beim Markieren mit dem Cursor ???
2398 else // nur Cursor bewegen
2400 ScAddress aScAddress( pViewData->GetCurX(), pViewData->GetCurY(), 0 );
2401 aScAddress.Format( aAddr, SCA_ABS );
2404 SfxStringItem aPosItem( SID_CURRENTCELL, aAddr );
2405 // We don't want to align to the cursor position because if the
2406 // cell cursor isn't visible after making selection, it would jump
2407 // back to the origin of the selection where the cell cursor is.
2408 SfxBoolItem aAlignCursorItem( FN_PARAM_2, false );
2409 pDisp->Execute( SID_CURRENTCELL, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD,
2410 &aPosItem, &aAlignCursorItem, (void*)0L );
2412 pViewData->GetView()->InvalidateAttribs();
2414 return;
2418 void ScGridWindow::FakeButtonUp()
2420 if ( nButtonDown )
2422 MouseEvent aEvent( aCurMousePos ); // nButtons = 0 -> ignore
2423 MouseButtonUp( aEvent );
2427 void ScGridWindow::MouseMove( const MouseEvent& rMEvt )
2429 aCurMousePos = rMEvt.GetPosPixel();
2431 if ( rMEvt.IsLeaveWindow() && pNoteMarker && !pNoteMarker->IsByKeyboard() )
2432 HideNoteMarker();
2434 ScModule* pScMod = SC_MOD();
2435 if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
2436 return;
2438 // Ob aus dem Edit-Modus Drag&Drop gestartet wurde, bekommt man leider
2439 // nicht anders mit:
2441 if (bEEMouse && nButtonDown && !rMEvt.GetButtons())
2443 bEEMouse = false;
2444 nButtonDown = 0;
2445 nMouseStatus = SC_GM_NONE;
2446 return;
2449 if (nMouseStatus == SC_GM_IGNORE)
2450 return;
2452 if (nMouseStatus == SC_GM_WATERUNDO) // Undo im Giesskannenmodus -> nur auf Up warten
2453 return;
2455 if ( pViewData->GetViewShell()->IsAuditShell() ) // Detektiv-Fuell-Modus
2457 SetPointer( Pointer( POINTER_FILL ) );
2458 return;
2461 if (nMouseStatus == SC_GM_FILTER && pFilterBox)
2463 Point aRelPos = pFilterBox->ScreenToOutputPixel( OutputToScreenPixel( rMEvt.GetPosPixel() ) );
2464 if ( Rectangle(Point(),pFilterBox->GetOutputSizePixel()).IsInside(aRelPos) )
2466 nButtonDown = 0;
2467 nMouseStatus = SC_GM_NONE;
2468 ReleaseMouse();
2469 pFilterBox->MouseButtonDown( MouseEvent( aRelPos, 1, MOUSE_SIMPLECLICK, MOUSE_LEFT ) );
2470 return;
2474 sal_Bool bFormulaMode = pScMod->IsFormulaMode(); // naechster Klick -> Referenz
2476 if (bEEMouse && pViewData->HasEditView( eWhich ))
2478 EditView* pEditView;
2479 SCCOL nEditCol;
2480 SCROW nEditRow;
2481 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
2482 pEditView->MouseMove( rMEvt );
2483 return;
2486 if (bDPMouse)
2488 DPMouseMove( rMEvt );
2489 return;
2492 if (bRFMouse)
2494 RFMouseMove( rMEvt, false );
2495 return;
2498 if (nPagebreakMouse)
2500 PagebreakMove( rMEvt, false );
2501 return;
2504 // anderen Mauszeiger anzeigen?
2506 sal_Bool bEditMode = pViewData->HasEditView(eWhich);
2508 //! Testen ob RefMode-Dragging !!!
2509 if ( bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()) )
2511 Point aPos = rMEvt.GetPosPixel();
2512 SCsCOL nPosX;
2513 SCsROW nPosY;
2514 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
2516 EditView* pEditView;
2517 SCCOL nEditCol;
2518 SCROW nEditRow;
2519 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
2520 SCCOL nEndCol = pViewData->GetEditEndCol();
2521 SCROW nEndRow = pViewData->GetEditEndRow();
2523 if ( nPosX >= (SCsCOL) nEditCol && nPosX <= (SCsCOL) nEndCol &&
2524 nPosY >= (SCsROW) nEditRow && nPosY <= (SCsROW) nEndRow )
2526 // Field can only be URL field
2527 sal_Bool bAlt = rMEvt.IsMod2();
2528 if ( !bAlt && !nButtonDown && pEditView && pEditView->GetFieldUnderMousePointer() )
2529 SetPointer( Pointer( POINTER_REFHAND ) );
2530 else if ( pEditView && pEditView->GetEditEngine()->IsVertical() )
2531 SetPointer( Pointer( POINTER_TEXT_VERTICAL ) );
2532 else
2533 SetPointer( Pointer( POINTER_TEXT ) );
2534 return;
2538 sal_Bool bWater = SC_MOD()->GetIsWaterCan() || pViewData->GetView()->HasPaintBrush();
2539 if (bWater)
2540 SetPointer( Pointer(POINTER_FILL) );
2542 if (!bWater)
2544 sal_Bool bCross = false;
2546 // Range-Finder
2548 bool bCorner;
2549 if ( HitRangeFinder( rMEvt.GetPosPixel(), bCorner ) )
2551 if (bCorner)
2552 SetPointer( Pointer( POINTER_CROSS ) );
2553 else
2554 SetPointer( Pointer( POINTER_HAND ) );
2555 bCross = sal_True;
2558 // Page-Break-Modus
2560 sal_uInt16 nBreakType;
2561 if ( !nButtonDown && pViewData->IsPagebreakMode() &&
2562 ( nBreakType = HitPageBreak( rMEvt.GetPosPixel() ) ) != 0 )
2564 PointerStyle eNew = POINTER_ARROW;
2565 switch ( nBreakType )
2567 case SC_PD_RANGE_L:
2568 case SC_PD_RANGE_R:
2569 case SC_PD_BREAK_H:
2570 eNew = POINTER_ESIZE;
2571 break;
2572 case SC_PD_RANGE_T:
2573 case SC_PD_RANGE_B:
2574 case SC_PD_BREAK_V:
2575 eNew = POINTER_SSIZE;
2576 break;
2577 case SC_PD_RANGE_TL:
2578 case SC_PD_RANGE_BR:
2579 eNew = POINTER_SESIZE;
2580 break;
2581 case SC_PD_RANGE_TR:
2582 case SC_PD_RANGE_BL:
2583 eNew = POINTER_NESIZE;
2584 break;
2586 SetPointer( Pointer( eNew ) );
2587 bCross = sal_True;
2590 // Fill-Cursor anzeigen ?
2592 if ( !bFormulaMode && !nButtonDown )
2593 if (TestMouse( rMEvt, false ))
2594 bCross = sal_True;
2596 if ( nButtonDown && pViewData->IsAnyFillMode() )
2598 SetPointer( Pointer( POINTER_CROSS ) );
2599 bCross = sal_True;
2600 nScFillModeMouseModifier = rMEvt.GetModifier(); // ausgewertet bei AutoFill und Matrix
2603 if (!bCross)
2605 sal_Bool bAlt = rMEvt.IsMod2();
2607 if (bEditMode) // Edit-Mode muss zuerst kommen!
2608 SetPointer( Pointer( POINTER_ARROW ) );
2609 else if ( !bAlt && !nButtonDown &&
2610 GetEditUrl(rMEvt.GetPosPixel()) )
2611 SetPointer( Pointer( POINTER_REFHAND ) );
2612 else if ( DrawMouseMove(rMEvt) ) // setzt Pointer um
2613 return;
2617 if ( pViewData->GetView()->GetSelEngine()->SelMouseMove( rMEvt ) )
2618 return;
2621 static void lcl_InitMouseEvent( ::com::sun::star::awt::MouseEvent& rEvent, const MouseEvent& rEvt )
2623 rEvent.Modifiers = 0;
2624 if ( rEvt.IsShift() )
2625 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::SHIFT;
2626 if ( rEvt.IsMod1() )
2627 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD1;
2628 if ( rEvt.IsMod2() )
2629 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD2;
2630 if ( rEvt.IsMod3() )
2631 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD3;
2633 rEvent.Buttons = 0;
2634 if ( rEvt.IsLeft() )
2635 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::LEFT;
2636 if ( rEvt.IsRight() )
2637 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::RIGHT;
2638 if ( rEvt.IsMiddle() )
2639 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::MIDDLE;
2641 rEvent.X = rEvt.GetPosPixel().X();
2642 rEvent.Y = rEvt.GetPosPixel().Y();
2643 rEvent.ClickCount = rEvt.GetClicks();
2644 rEvent.PopupTrigger = false;
2647 long ScGridWindow::PreNotify( NotifyEvent& rNEvt )
2649 bool bDone = false;
2650 sal_uInt16 nType = rNEvt.GetType();
2651 if ( nType == EVENT_MOUSEBUTTONUP || nType == EVENT_MOUSEBUTTONDOWN )
2653 Window* pWindow = rNEvt.GetWindow();
2654 if (pWindow == this && pViewData)
2656 SfxViewFrame* pViewFrame = pViewData->GetViewShell()->GetViewFrame();
2657 if (pViewFrame)
2659 com::sun::star::uno::Reference<com::sun::star::frame::XController> xController = pViewFrame->GetFrame().GetController();
2660 if (xController.is())
2662 ScTabViewObj* pImp = ScTabViewObj::getImplementation( xController );
2663 if (pImp && pImp->IsMouseListening())
2665 ::com::sun::star::awt::MouseEvent aEvent;
2666 lcl_InitMouseEvent( aEvent, *rNEvt.GetMouseEvent() );
2667 if ( rNEvt.GetWindow() )
2668 aEvent.Source = rNEvt.GetWindow()->GetComponentInterface();
2669 if ( nType == EVENT_MOUSEBUTTONDOWN)
2670 bDone = pImp->MousePressed( aEvent );
2671 else
2672 bDone = pImp->MouseReleased( aEvent );
2678 if (bDone) // event consumed by a listener
2680 if ( nType == EVENT_MOUSEBUTTONDOWN )
2682 const MouseEvent* pMouseEvent = rNEvt.GetMouseEvent();
2683 if ( pMouseEvent->IsRight() && pMouseEvent->GetClicks() == 1 )
2685 // If a listener returned true for a right-click call, also prevent opening the context menu
2686 // (this works only if the context menu is opened on mouse-down)
2687 nMouseStatus = SC_GM_IGNORE;
2691 return 1;
2693 else
2694 return Window::PreNotify( rNEvt );
2697 void ScGridWindow::Tracking( const TrackingEvent& rTEvt )
2699 // Weil die SelectionEngine kein Tracking kennt, die Events nur auf
2700 // die verschiedenen MouseHandler verteilen...
2702 const MouseEvent& rMEvt = rTEvt.GetMouseEvent();
2704 if ( rTEvt.IsTrackingCanceled() ) // alles abbrechen...
2706 if (!pViewData->GetView()->IsInActivatePart() && !SC_MOD()->IsRefDialogOpen())
2708 if (bDPMouse)
2709 bDPMouse = false; // gezeichnet wird per bDragRect
2710 if (bDragRect)
2712 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
2713 bDragRect = false;
2714 UpdateDragRectOverlay();
2716 if (bRFMouse)
2718 RFMouseMove( rMEvt, true ); // richtig abbrechen geht dabei nicht...
2719 bRFMouse = false;
2721 if (nPagebreakMouse)
2723 // if (bPagebreakDrawn)
2724 // DrawDragRect( aPagebreakDrag.aStart.Col(), aPagebreakDrag.aStart.Row(),
2725 // aPagebreakDrag.aEnd.Col(), aPagebreakDrag.aEnd.Row(), sal_False );
2726 bPagebreakDrawn = false;
2727 UpdateDragRectOverlay();
2728 nPagebreakMouse = SC_PD_NONE;
2731 SetPointer( Pointer( POINTER_ARROW ) );
2732 StopMarking();
2733 MouseButtonUp( rMEvt ); // mit Status SC_GM_IGNORE aus StopMarking
2735 sal_Bool bRefMode = pViewData->IsRefMode();
2736 if (bRefMode)
2737 SC_MOD()->EndReference(); // Dialog nicht verkleinert lassen
2740 else if ( rTEvt.IsTrackingEnded() )
2742 // MouseButtonUp immer mit passenden Buttons (z.B. wegen Testtool, #63148#)
2743 // Schliesslich behauptet der Tracking-Event ja, dass normal beendet und nicht
2744 // abgebrochen wurde.
2746 MouseEvent aUpEvt( rMEvt.GetPosPixel(), rMEvt.GetClicks(),
2747 rMEvt.GetMode(), nButtonDown, rMEvt.GetModifier() );
2748 MouseButtonUp( aUpEvt );
2750 else
2751 MouseMove( rMEvt );
2754 void ScGridWindow::StartDrag( sal_Int8 /* nAction */, const Point& rPosPixel )
2756 if ( pFilterBox || nPagebreakMouse )
2757 return;
2759 HideNoteMarker();
2761 CommandEvent aDragEvent( rPosPixel, COMMAND_STARTDRAG, sal_True );
2763 if (bEEMouse && pViewData->HasEditView( eWhich ))
2765 EditView* pEditView;
2766 SCCOL nEditCol;
2767 SCROW nEditRow;
2768 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
2770 // don't remove the edit view while switching views
2771 ScModule* pScMod = SC_MOD();
2772 pScMod->SetInEditCommand( sal_True );
2774 pEditView->Command( aDragEvent );
2776 ScInputHandler* pHdl = pScMod->GetInputHdl();
2777 if (pHdl)
2778 pHdl->DataChanged();
2780 pScMod->SetInEditCommand( false );
2781 if (!pViewData->IsActive()) // dropped to different view?
2783 ScInputHandler* pViewHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
2784 if ( pViewHdl && pViewData->HasEditView( eWhich ) )
2786 pViewHdl->CancelHandler();
2787 ShowCursor(); // missing from KillEditView
2791 else
2792 if ( !DrawCommand(aDragEvent) )
2793 pViewData->GetView()->GetSelEngine()->Command( aDragEvent );
2796 static void lcl_SetTextCursorPos( ScViewData* pViewData, ScSplitPos eWhich, Window* pWin )
2798 SCCOL nCol = pViewData->GetCurX();
2799 SCROW nRow = pViewData->GetCurY();
2800 Rectangle aEditArea = pViewData->GetEditArea( eWhich, nCol, nRow, pWin, NULL, sal_True );
2801 aEditArea.Right() = aEditArea.Left();
2802 aEditArea = pWin->PixelToLogic( aEditArea );
2803 pWin->SetCursorRect( &aEditArea );
2806 void ScGridWindow::Command( const CommandEvent& rCEvt )
2808 // The command event is send to the window after a possible context
2809 // menu from an inplace client is closed. Now we have the chance to
2810 // deactivate the inplace client without any problem regarding parent
2811 // windows and code on the stack.
2812 sal_uInt16 nCmd = rCEvt.GetCommand();
2813 ScTabViewShell* pTabViewSh = pViewData->GetViewShell();
2814 SfxInPlaceClient* pClient = pTabViewSh->GetIPClient();
2815 if ( pClient &&
2816 pClient->IsObjectInPlaceActive() &&
2817 nCmd == COMMAND_CONTEXTMENU )
2819 pTabViewSh->DeactivateOle();
2820 return;
2823 ScModule* pScMod = SC_MOD();
2824 OSL_ENSURE( nCmd != COMMAND_STARTDRAG, "ScGridWindow::Command called with COMMAND_STARTDRAG" );
2826 if ( nCmd == COMMAND_STARTEXTTEXTINPUT ||
2827 nCmd == COMMAND_ENDEXTTEXTINPUT ||
2828 nCmd == COMMAND_EXTTEXTINPUT ||
2829 nCmd == COMMAND_CURSORPOS ||
2830 nCmd == COMMAND_QUERYCHARPOSITION )
2832 sal_Bool bEditView = pViewData->HasEditView( eWhich );
2833 if (!bEditView)
2835 // only if no cell editview is active, look at drawview
2836 SdrView* pSdrView = pViewData->GetView()->GetSdrView();
2837 if ( pSdrView )
2839 OutlinerView* pOlView = pSdrView->GetTextEditOutlinerView();
2840 if ( pOlView && pOlView->GetWindow() == this )
2842 pOlView->Command( rCEvt );
2843 return; // done
2848 if ( nCmd == COMMAND_CURSORPOS && !bEditView )
2850 // CURSORPOS may be called without following text input,
2851 // to set the input method window position
2852 // -> input mode must not be started,
2853 // manually calculate text insert position if not in input mode
2855 lcl_SetTextCursorPos( pViewData, eWhich, this );
2856 return;
2859 ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
2860 if ( pHdl )
2862 pHdl->InputCommand( rCEvt, sal_True );
2863 return; // done
2866 Window::Command( rCEvt );
2867 return;
2870 if ( nCmd == COMMAND_PASTESELECTION )
2872 if ( bEEMouse )
2874 // EditEngine handles selection in MouseButtonUp - no action
2875 // needed in command handler
2877 else
2879 PasteSelection( rCEvt.GetMousePosPixel() );
2881 return;
2884 if ( nCmd == COMMAND_INPUTLANGUAGECHANGE )
2886 // #i55929# Font and font size state depends on input language if nothing is selected,
2887 // so the slots have to be invalidated when the input language is changed.
2889 SfxBindings& rBindings = pViewData->GetBindings();
2890 rBindings.Invalidate( SID_ATTR_CHAR_FONT );
2891 rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT );
2892 return;
2895 if ( nCmd == COMMAND_WHEEL || nCmd == COMMAND_STARTAUTOSCROLL || nCmd == COMMAND_AUTOSCROLL )
2897 sal_Bool bDone = pViewData->GetView()->ScrollCommand( rCEvt, eWhich );
2898 if (!bDone)
2899 Window::Command(rCEvt);
2900 return;
2902 // #i7560# FormulaMode check is below scrolling - scrolling is allowed during formula input
2903 sal_Bool bDisable = pScMod->IsFormulaMode() ||
2904 pScMod->IsModalMode(pViewData->GetSfxDocShell());
2905 if (bDisable)
2906 return;
2908 if ( nCmd == COMMAND_CONTEXTMENU && !SC_MOD()->GetIsWaterCan() )
2910 sal_Bool bMouse = rCEvt.IsMouseEvent();
2911 if ( bMouse && nMouseStatus == SC_GM_IGNORE )
2912 return;
2914 if (pViewData->IsAnyFillMode())
2916 pViewData->GetView()->StopRefMode();
2917 pViewData->ResetFillMode();
2919 ReleaseMouse();
2920 StopMarking();
2922 Point aPosPixel = rCEvt.GetMousePosPixel();
2923 Point aMenuPos = aPosPixel;
2925 if ( bMouse )
2927 SCsCOL nCellX = -1;
2928 SCsROW nCellY = -1;
2929 pViewData->GetPosFromPixel(aPosPixel.X(), aPosPixel.Y(), eWhich, nCellX, nCellY);
2930 ScDocument* pDoc = pViewData->GetDocument();
2931 SCTAB nTab = pViewData->GetTabNo();
2932 const ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
2933 bool bSelectAllowed = true;
2934 if ( pProtect && pProtect->isProtected() )
2936 // This sheet is protected. Check if a context menu is allowed on this cell.
2937 bool bCellProtected = pDoc->HasAttrib(nCellX, nCellY, nTab, nCellX, nCellY, nTab, HASATTR_PROTECTED);
2938 bool bSelProtected = pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
2939 bool bSelUnprotected = pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
2941 if (bCellProtected)
2942 bSelectAllowed = bSelProtected;
2943 else
2944 bSelectAllowed = bSelUnprotected;
2946 if (!bSelectAllowed)
2947 // Selecting this cell is not allowed, neither is context menu.
2948 return;
2950 // #i18735# First select the item under the mouse pointer.
2951 // This can change the selection, and the view state (edit mode, etc).
2952 SelectForContextMenu( aPosPixel, nCellX, nCellY );
2955 sal_Bool bDone = false;
2956 sal_Bool bEdit = pViewData->HasEditView(eWhich);
2957 if ( !bEdit )
2959 // Edit-Zelle mit Spelling-Errors ?
2960 if ( bMouse && GetEditUrlOrError( sal_True, aPosPixel ) )
2962 // GetEditUrlOrError hat den Cursor schon bewegt
2964 pScMod->SetInputMode( SC_INPUT_TABLE );
2965 bEdit = pViewData->HasEditView(eWhich); // hat's geklappt ?
2967 OSL_ENSURE( bEdit, "kann nicht in Edit-Modus schalten" );
2970 if ( bEdit )
2972 EditView* pEditView = pViewData->GetEditView( eWhich ); // ist dann nicht 0
2974 if ( !bMouse )
2976 Cursor* pCur = pEditView->GetCursor();
2977 if ( pCur )
2979 Point aLogicPos = pCur->GetPos();
2980 // use the position right of the cursor (spell popup is opened if
2981 // the cursor is before the word, but not if behind it)
2982 aLogicPos.X() += pCur->GetWidth();
2983 aLogicPos.Y() += pCur->GetHeight() / 2; // center vertically
2984 aMenuPos = LogicToPixel( aLogicPos );
2988 // if edit mode was just started above, online spelling may be incomplete
2989 pEditView->GetEditEngine()->CompleteOnlineSpelling();
2991 // IsCursorAtWrongSpelledWord could be used for !bMouse
2992 // if there was a corresponding ExecuteSpellPopup call
2994 if( pEditView->IsWrongSpelledWordAtPos( aMenuPos ) )
2996 // Wenn man unter OS/2 neben das Popupmenue klickt, kommt MouseButtonDown
2997 // vor dem Ende des Menue-Execute, darum muss SetModified vorher kommen
2998 // (Bug #40968#)
2999 ScInputHandler* pHdl = pScMod->GetInputHdl();
3000 if (pHdl)
3001 pHdl->SetModified();
3003 Link aLink = LINK( this, ScGridWindow, PopupSpellingHdl );
3004 pEditView->ExecuteSpellPopup( aMenuPos, &aLink );
3006 bDone = sal_True;
3009 else if ( !bMouse )
3011 // non-edit menu by keyboard -> use lower right of cell cursor position
3012 ScDocument* aDoc = pViewData->GetDocument();
3013 SCTAB nTabNo = pViewData->GetTabNo();
3014 sal_Bool bLayoutIsRTL = aDoc->IsLayoutRTL(nTabNo);
3016 SCCOL nCurX = pViewData->GetCurX();
3017 SCROW nCurY = pViewData->GetCurY();
3018 aMenuPos = pViewData->GetScrPos( nCurX, nCurY, eWhich, sal_True );
3019 long nSizeXPix;
3020 long nSizeYPix;
3021 pViewData->GetMergeSizePixel( nCurX, nCurY, nSizeXPix, nSizeYPix );
3022 // fdo#55432 take the correct position for RTL sheet
3023 aMenuPos.X() += bLayoutIsRTL ? -nSizeXPix : nSizeXPix;
3024 aMenuPos.Y() += nSizeYPix;
3026 if (pViewData)
3028 ScTabViewShell* pViewSh = pViewData->GetViewShell();
3029 if (pViewSh)
3031 // Is a draw object selected?
3033 SdrView* pDrawView = pViewSh->GetSdrView();
3034 if (pDrawView && pDrawView->AreObjectsMarked())
3036 // #100442#; the conext menu should open in the middle of the selected objects
3037 Rectangle aSelectRect(LogicToPixel(pDrawView->GetAllMarkedBoundRect()));
3038 aMenuPos = aSelectRect.Center();
3044 if (!bDone)
3046 SfxDispatcher::ExecutePopup( 0, this, &aMenuPos );
3051 void ScGridWindow::SelectForContextMenu( const Point& rPosPixel, SCsCOL nCellX, SCsROW nCellY )
3053 // #i18735# if the click was outside of the current selection,
3054 // the cursor is moved or an object at the click position selected.
3055 // (see SwEditWin::SelectMenuPosition in Writer)
3057 ScTabView* pView = pViewData->GetView();
3058 ScDrawView* pDrawView = pView->GetScDrawView();
3060 // check cell edit mode
3062 if ( pViewData->HasEditView(eWhich) )
3064 ScModule* pScMod = SC_MOD();
3065 SCCOL nEditStartCol = pViewData->GetEditViewCol(); //! change to GetEditStartCol after calcrtl is integrated
3066 SCROW nEditStartRow = pViewData->GetEditViewRow();
3067 SCCOL nEditEndCol = pViewData->GetEditEndCol();
3068 SCROW nEditEndRow = pViewData->GetEditEndRow();
3070 if ( nCellX >= (SCsCOL) nEditStartCol && nCellX <= (SCsCOL) nEditEndCol &&
3071 nCellY >= (SCsROW) nEditStartRow && nCellY <= (SCsROW) nEditEndRow )
3073 // handle selection within the EditView
3075 EditView* pEditView = pViewData->GetEditView( eWhich ); // not NULL (HasEditView)
3076 EditEngine* pEditEngine = pEditView->GetEditEngine();
3077 Rectangle aOutputArea = pEditView->GetOutputArea();
3078 Rectangle aVisArea = pEditView->GetVisArea();
3080 Point aTextPos = PixelToLogic( rPosPixel );
3081 if ( pEditEngine->IsVertical() ) // have to manually transform position
3083 aTextPos -= aOutputArea.TopRight();
3084 long nTemp = -aTextPos.X();
3085 aTextPos.X() = aTextPos.Y();
3086 aTextPos.Y() = nTemp;
3088 else
3089 aTextPos -= aOutputArea.TopLeft();
3090 aTextPos += aVisArea.TopLeft(); // position in the edit document
3092 EPosition aDocPosition = pEditEngine->FindDocPosition(aTextPos);
3093 ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex);
3094 ESelection aSelection = pEditView->GetSelection();
3095 aSelection.Adjust(); // needed for IsLess/IsGreater
3096 if ( aCompare.IsLess(aSelection) || aCompare.IsGreater(aSelection) )
3098 // clicked outside the selected text - deselect and move text cursor
3099 MouseEvent aEvent( rPosPixel );
3100 pEditView->MouseButtonDown( aEvent );
3101 pEditView->MouseButtonUp( aEvent );
3102 pScMod->InputSelection( pEditView );
3105 return; // clicked within the edit view - keep edit mode
3107 else
3109 // outside of the edit view - end edit mode, regardless of cell selection, then continue
3110 pScMod->InputEnterHandler();
3114 // check draw text edit mode
3116 Point aLogicPos = PixelToLogic( rPosPixel ); // after cell edit mode is ended
3117 if ( pDrawView && pDrawView->GetTextEditObject() && pDrawView->GetTextEditOutlinerView() )
3119 OutlinerView* pOlView = pDrawView->GetTextEditOutlinerView();
3120 Rectangle aOutputArea = pOlView->GetOutputArea();
3121 if ( aOutputArea.IsInside( aLogicPos ) )
3123 // handle selection within the OutlinerView
3125 Outliner* pOutliner = pOlView->GetOutliner();
3126 const EditEngine& rEditEngine = pOutliner->GetEditEngine();
3127 Rectangle aVisArea = pOlView->GetVisArea();
3129 Point aTextPos = aLogicPos;
3130 if ( pOutliner->IsVertical() ) // have to manually transform position
3132 aTextPos -= aOutputArea.TopRight();
3133 long nTemp = -aTextPos.X();
3134 aTextPos.X() = aTextPos.Y();
3135 aTextPos.Y() = nTemp;
3137 else
3138 aTextPos -= aOutputArea.TopLeft();
3139 aTextPos += aVisArea.TopLeft(); // position in the edit document
3141 EPosition aDocPosition = rEditEngine.FindDocPosition(aTextPos);
3142 ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex);
3143 ESelection aSelection = pOlView->GetSelection();
3144 aSelection.Adjust(); // needed for IsLess/IsGreater
3145 if ( aCompare.IsLess(aSelection) || aCompare.IsGreater(aSelection) )
3147 // clicked outside the selected text - deselect and move text cursor
3148 // use DrawView to allow extra handling there (none currently)
3149 MouseEvent aEvent( rPosPixel );
3150 pDrawView->MouseButtonDown( aEvent, this );
3151 pDrawView->MouseButtonUp( aEvent, this );
3154 return; // clicked within the edit area - keep edit mode
3156 else
3158 // Outside of the edit area - end text edit mode, then continue.
3159 // DrawDeselectAll also ends text edit mode and updates the shells.
3160 // If the click was on the edited object, it will be selected again below.
3161 pView->DrawDeselectAll();
3165 // look for existing selection
3167 sal_Bool bHitSelected = false;
3168 if ( pDrawView && pDrawView->IsMarkedObjHit( aLogicPos ) )
3170 // clicked on selected object -> don't change anything
3171 bHitSelected = sal_True;
3173 else if ( pViewData->GetMarkData().IsCellMarked(nCellX, nCellY) )
3175 // clicked on selected cell -> don't change anything
3176 bHitSelected = sal_True;
3179 // select drawing object or move cell cursor
3181 if ( !bHitSelected )
3183 sal_Bool bWasDraw = ( pDrawView && pDrawView->AreObjectsMarked() );
3184 sal_Bool bHitDraw = false;
3185 if ( pDrawView )
3187 pDrawView->UnmarkAllObj();
3188 // Unlock the Internal Layer in order to activate the context menu.
3189 // re-lock in ScDrawView::MarkListHasChanged()
3190 lcl_UnLockComment( pDrawView, pDrawView->GetSdrPageView(), pDrawView->GetModel(), aLogicPos ,pViewData);
3191 bHitDraw = pDrawView->MarkObj( aLogicPos );
3192 // draw shell is activated in MarkListHasChanged
3194 if ( !bHitDraw )
3196 pView->Unmark();
3197 pView->SetCursor(nCellX, nCellY);
3198 if ( bWasDraw )
3199 pViewData->GetViewShell()->SetDrawShell( false ); // switch shells
3204 void ScGridWindow::KeyInput(const KeyEvent& rKEvt)
3206 // Cursor control for ref input dialog
3207 const KeyCode& rKeyCode = rKEvt.GetKeyCode();
3208 if( SC_MOD()->IsRefDialogOpen() )
3210 if( !rKeyCode.GetModifier() && (rKeyCode.GetCode() == KEY_F2) )
3212 SC_MOD()->EndReference();
3213 return;
3215 else if( pViewData->GetViewShell()->MoveCursorKeyInput( rKEvt ) )
3217 ScRange aRef(
3218 pViewData->GetRefStartX(), pViewData->GetRefStartY(), pViewData->GetRefStartZ(),
3219 pViewData->GetRefEndX(), pViewData->GetRefEndY(), pViewData->GetRefEndZ() );
3220 SC_MOD()->SetReference( aRef, pViewData->GetDocument() );
3221 return;
3224 else if( rKeyCode.GetCode() == KEY_RETURN && pViewData->IsPasteMode() )
3226 ScTabViewShell* pTabViewShell = pViewData->GetViewShell();
3227 ScClipUtil::PasteFromClipboard( pViewData, pTabViewShell, false );
3229 // Clear clipboard content.
3230 uno::Reference<datatransfer::clipboard::XClipboard> xSystemClipboard =
3231 TransferableHelper::GetSystemClipboard();
3232 if (xSystemClipboard.is())
3234 xSystemClipboard->setContents(
3235 uno::Reference<datatransfer::XTransferable>(),
3236 uno::Reference<datatransfer::clipboard::XClipboardOwner>());
3239 // hide the border around the copy source
3240 pViewData->SetPasteMode( SC_PASTE_NONE );
3241 UpdateCopySourceOverlay();
3242 return;
3244 // wenn semi-Modeless-SfxChildWindow-Dialog oben, keine KeyInputs:
3245 else if( !pViewData->IsAnyFillMode() )
3247 if (rKeyCode.GetCode() == KEY_ESCAPE)
3249 pViewData->SetPasteMode( SC_PASTE_NONE );
3250 UpdateCopySourceOverlay();
3252 // query for existing note marker before calling ViewShell's keyboard handling
3253 // which may remove the marker
3254 sal_Bool bHadKeyMarker = ( pNoteMarker && pNoteMarker->IsByKeyboard() );
3255 ScTabViewShell* pViewSh = pViewData->GetViewShell();
3257 if (pViewData->GetDocShell()->GetProgress())
3258 return;
3260 if (DrawKeyInput(rKEvt))
3262 const KeyCode& rLclKeyCode = rKEvt.GetKeyCode();
3263 if (rLclKeyCode.GetCode() == KEY_DOWN
3264 || rLclKeyCode.GetCode() == KEY_UP
3265 || rLclKeyCode.GetCode() == KEY_LEFT
3266 || rLclKeyCode.GetCode() == KEY_RIGHT)
3268 ScTabViewShell* pViewShell = pViewData->GetViewShell();
3269 SfxBindings& rBindings = pViewShell->GetViewFrame()->GetBindings();
3270 rBindings.Invalidate(SID_ATTR_TRANSFORM_POS_X);
3271 rBindings.Invalidate(SID_ATTR_TRANSFORM_POS_Y);
3273 return;
3276 if (!pViewData->GetView()->IsDrawSelMode() && !DrawHasMarkedObj()) // keine Eingaben im Zeichenmodus
3277 { //! DrawShell abfragen !!!
3278 if (pViewSh->TabKeyInput(rKEvt))
3279 return;
3281 else
3282 if (pViewSh->SfxViewShell::KeyInput(rKEvt)) // von SfxViewShell
3283 return;
3285 KeyCode aCode = rKEvt.GetKeyCode();
3286 if ( aCode.GetCode() == KEY_ESCAPE && aCode.GetModifier() == 0 )
3288 if ( bHadKeyMarker )
3289 HideNoteMarker();
3290 else
3291 pViewSh->Escape();
3292 return;
3294 if ( aCode.GetCode() == KEY_F1 && aCode.GetModifier() == KEY_MOD1 )
3296 // ctrl-F1 shows or hides the note or redlining info for the cursor position
3297 // (hard-coded because F1 can't be configured)
3299 if ( bHadKeyMarker )
3300 HideNoteMarker(); // hide when previously visible
3301 else
3302 ShowNoteMarker( pViewData->GetCurX(), pViewData->GetCurY(), sal_True );
3303 return;
3305 if (aCode.GetCode() == KEY_BRACKETLEFT && aCode.GetModifier() == KEY_MOD1)
3307 pViewSh->DetectiveMarkPred();
3308 return;
3310 if (aCode.GetCode() == KEY_BRACKETRIGHT && aCode.GetModifier() == KEY_MOD1)
3312 pViewSh->DetectiveMarkSucc();
3313 return;
3318 Window::KeyInput(rKEvt);
3321 void ScGridWindow::StopMarking()
3323 DrawEndAction(); // Markieren/Verschieben auf Drawing-Layer abbrechen
3325 if (nButtonDown)
3327 pViewData->GetMarkData().SetMarking(false);
3328 nMouseStatus = SC_GM_IGNORE;
3332 void ScGridWindow::UpdateInputContext()
3334 sal_Bool bReadOnly = pViewData->GetDocShell()->IsReadOnly();
3335 sal_uLong nOptions = bReadOnly ? 0 : ( INPUTCONTEXT_TEXT | INPUTCONTEXT_EXTTEXTINPUT );
3337 // when font from InputContext is used,
3338 // it must be taken from the cursor position's cell attributes
3340 InputContext aContext;
3341 aContext.SetOptions( nOptions );
3342 SetInputContext( aContext );
3345 //--------------------------------------------------------
3347 // sensitiver Bereich (Pixel)
3348 #define SCROLL_SENSITIVE 20
3350 bool ScGridWindow::DropScroll( const Point& rMousePos )
3352 SCsCOL nDx = 0;
3353 SCsROW nDy = 0;
3354 Size aSize = GetOutputSizePixel();
3356 if (aSize.Width() > SCROLL_SENSITIVE * 3)
3358 if ( rMousePos.X() < SCROLL_SENSITIVE && pViewData->GetPosX(WhichH(eWhich)) > 0 )
3359 nDx = -1;
3360 if ( rMousePos.X() >= aSize.Width() - SCROLL_SENSITIVE
3361 && pViewData->GetPosX(WhichH(eWhich)) < MAXCOL )
3362 nDx = 1;
3364 if (aSize.Height() > SCROLL_SENSITIVE * 3)
3366 if ( rMousePos.Y() < SCROLL_SENSITIVE && pViewData->GetPosY(WhichV(eWhich)) > 0 )
3367 nDy = -1;
3368 if ( rMousePos.Y() >= aSize.Height() - SCROLL_SENSITIVE
3369 && pViewData->GetPosY(WhichV(eWhich)) < MAXROW )
3370 nDy = 1;
3373 if ( nDx != 0 || nDy != 0 )
3375 if ( nDx != 0 )
3376 pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) );
3377 if ( nDy != 0 )
3378 pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) );
3381 return false;
3384 static sal_Bool lcl_TestScenarioRedliningDrop( ScDocument* pDoc, const ScRange& aDragRange)
3386 // Testet, ob bei eingeschalteten RedLining,
3387 // bei einem Drop ein Scenario betroffen ist.
3389 sal_Bool bReturn = false;
3390 SCTAB nTab = aDragRange.aStart.Tab();
3391 SCTAB nTabCount = pDoc->GetTableCount();
3393 if(pDoc->GetChangeTrack()!=NULL)
3395 if( pDoc->IsScenario(nTab) && pDoc->HasScenarioRange(nTab, aDragRange))
3397 bReturn = sal_True;
3399 else
3401 for(SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
3403 if(pDoc->HasScenarioRange(i, aDragRange))
3405 bReturn = sal_True;
3406 break;
3411 return bReturn;
3414 static ScRange lcl_MakeDropRange( SCCOL nPosX, SCROW nPosY, SCTAB nTab, const ScRange& rSource )
3416 SCCOL nCol1 = nPosX;
3417 SCCOL nCol2 = nCol1 + ( rSource.aEnd.Col() - rSource.aStart.Col() );
3418 if ( nCol2 > MAXCOL )
3420 nCol1 -= nCol2 - MAXCOL;
3421 nCol2 = MAXCOL;
3423 SCROW nRow1 = nPosY;
3424 SCROW nRow2 = nRow1 + ( rSource.aEnd.Row() - rSource.aStart.Row() );
3425 if ( nRow2 > MAXROW )
3427 nRow1 -= nRow2 - MAXROW;
3428 nRow2 = MAXROW;
3431 return ScRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab );
3434 //--------------------------------------------------------
3436 extern sal_Bool bPasteIsDrop; // viewfun4 -> move to header
3437 extern sal_Bool bPasteIsMove; // viewfun7 -> move to header
3439 //--------------------------------------------------------
3441 sal_Int8 ScGridWindow::AcceptPrivateDrop( const AcceptDropEvent& rEvt )
3443 if ( rEvt.mbLeaving )
3445 bDragRect = false;
3446 UpdateDragRectOverlay();
3447 return rEvt.mnAction;
3450 const ScDragData& rData = SC_MOD()->GetDragData();
3451 if ( rData.pCellTransfer )
3453 // Don't move source that would include filtered rows.
3454 if ((rEvt.mnAction & DND_ACTION_MOVE) && rData.pCellTransfer->HasFilteredRows())
3456 if (bDragRect)
3458 bDragRect = false;
3459 UpdateDragRectOverlay();
3461 return DND_ACTION_NONE;
3464 Point aPos = rEvt.maPosPixel;
3466 ScDocument* pSourceDoc = rData.pCellTransfer->GetSourceDocument();
3467 ScDocument* pThisDoc = pViewData->GetDocument();
3468 if (pSourceDoc == pThisDoc)
3470 OUString aName;
3471 if ( pThisDoc->HasChartAtPoint(pViewData->GetTabNo(), PixelToLogic(aPos), aName ))
3473 if (bDragRect) // Rechteck loeschen
3475 bDragRect = false;
3476 UpdateDragRectOverlay();
3479 //! highlight chart? (selection border?)
3481 sal_Int8 nRet = rEvt.mnAction;
3482 return nRet;
3486 if ( rData.pCellTransfer->GetDragSourceFlags() & SC_DROP_TABLE ) // whole sheet?
3488 sal_Bool bOk = pThisDoc->IsDocEditable();
3489 return bOk ? rEvt.mnAction : 0; // don't draw selection frame
3492 SCsCOL nPosX;
3493 SCsROW nPosY;
3494 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
3496 ScRange aSourceRange = rData.pCellTransfer->GetRange();
3497 SCCOL nSourceStartX = aSourceRange.aStart.Col();
3498 SCROW nSourceStartY = aSourceRange.aStart.Row();
3499 SCCOL nSourceEndX = aSourceRange.aEnd.Col();
3500 SCROW nSourceEndY = aSourceRange.aEnd.Row();
3501 SCCOL nSizeX = nSourceEndX - nSourceStartX + 1;
3502 SCROW nSizeY = nSourceEndY - nSourceStartY + 1;
3504 if ( rEvt.mnAction != DND_ACTION_MOVE )
3505 nSizeY = rData.pCellTransfer->GetNonFilteredRows(); // copy/link: no filtered rows
3507 SCsCOL nNewDragX = nPosX - rData.pCellTransfer->GetDragHandleX();
3508 if (nNewDragX<0) nNewDragX=0;
3509 if (nNewDragX+(nSizeX-1) > MAXCOL)
3510 nNewDragX = MAXCOL-(nSizeX-1);
3511 SCsROW nNewDragY = nPosY - rData.pCellTransfer->GetDragHandleY();
3512 if (nNewDragY<0) nNewDragY=0;
3513 if (nNewDragY+(nSizeY-1) > MAXROW)
3514 nNewDragY = MAXROW-(nSizeY-1);
3516 // don't break scenario ranges, don't drop on filtered
3517 SCTAB nTab = pViewData->GetTabNo();
3518 ScRange aDropRange = lcl_MakeDropRange( nNewDragX, nNewDragY, nTab, aSourceRange );
3519 if ( lcl_TestScenarioRedliningDrop( pThisDoc, aDropRange ) ||
3520 lcl_TestScenarioRedliningDrop( pSourceDoc, aSourceRange ) ||
3521 ScViewUtil::HasFiltered( aDropRange, pThisDoc) )
3523 if (bDragRect)
3525 bDragRect = false;
3526 UpdateDragRectOverlay();
3528 return DND_ACTION_NONE;
3531 InsCellCmd eDragInsertMode = INS_NONE;
3532 Window::PointerState aState = GetPointerState();
3534 // check for datapilot item sorting
3535 ScDPObject* pDPObj = NULL;
3536 if ( pThisDoc == pSourceDoc && ( pDPObj = pThisDoc->GetDPAtCursor( nNewDragX, nNewDragY, nTab ) ) != NULL )
3538 // drop on DataPilot table: sort or nothing
3540 bool bDPSort = false;
3541 if ( pThisDoc->GetDPAtCursor( nSourceStartX, nSourceStartY, aSourceRange.aStart.Tab() ) == pDPObj )
3543 sheet::DataPilotTableHeaderData aDestData;
3544 pDPObj->GetHeaderPositionData( ScAddress(nNewDragX, nNewDragY, nTab), aDestData );
3545 bool bValid = ( aDestData.Dimension >= 0 ); // dropping onto a field
3547 // look through the source range
3548 for (SCROW nRow = aSourceRange.aStart.Row(); bValid && nRow <= aSourceRange.aEnd.Row(); ++nRow )
3549 for (SCCOL nCol = aSourceRange.aStart.Col(); bValid && nCol <= aSourceRange.aEnd.Col(); ++nCol )
3551 sheet::DataPilotTableHeaderData aSourceData;
3552 pDPObj->GetHeaderPositionData( ScAddress( nCol, nRow, aSourceRange.aStart.Tab() ), aSourceData );
3553 if ( aSourceData.Dimension != aDestData.Dimension || aSourceData.MemberName.isEmpty() )
3554 bValid = false; // empty (subtotal) or different field
3557 if ( bValid )
3559 bool bIsDataLayout;
3560 OUString aDimName = pDPObj->GetDimName( aDestData.Dimension, bIsDataLayout );
3561 const ScDPSaveDimension* pDim = pDPObj->GetSaveData()->GetExistingDimensionByName( aDimName );
3562 if ( pDim )
3564 ScRange aOutRange = pDPObj->GetOutRange();
3566 sal_uInt16 nOrient = pDim->GetOrientation();
3567 if ( nOrient == sheet::DataPilotFieldOrientation_COLUMN )
3569 eDragInsertMode = INS_CELLSRIGHT;
3570 nSizeY = aOutRange.aEnd.Row() - nNewDragY + 1;
3571 bDPSort = true;
3573 else if ( nOrient == sheet::DataPilotFieldOrientation_ROW )
3575 eDragInsertMode = INS_CELLSDOWN;
3576 nSizeX = aOutRange.aEnd.Col() - nNewDragX + 1;
3577 bDPSort = true;
3583 if ( !bDPSort )
3585 // no valid sorting in a DataPilot table -> disallow
3586 if ( bDragRect )
3588 bDragRect = false;
3589 UpdateDragRectOverlay();
3591 return DND_ACTION_NONE;
3594 else if ( aState.mnState & KEY_MOD2 )
3596 if ( pThisDoc == pSourceDoc && nTab == aSourceRange.aStart.Tab() )
3598 long nDeltaX = labs( static_cast< long >( nNewDragX - nSourceStartX ) );
3599 long nDeltaY = labs( static_cast< long >( nNewDragY - nSourceStartY ) );
3600 if ( nDeltaX <= nDeltaY )
3602 eDragInsertMode = INS_CELLSDOWN;
3604 else
3606 eDragInsertMode = INS_CELLSRIGHT;
3609 if ( ( eDragInsertMode == INS_CELLSDOWN && nNewDragY <= nSourceEndY &&
3610 ( nNewDragX + nSizeX - 1 ) >= nSourceStartX && nNewDragX <= nSourceEndX &&
3611 ( nNewDragX != nSourceStartX || nNewDragY >= nSourceStartY ) ) ||
3612 ( eDragInsertMode == INS_CELLSRIGHT && nNewDragX <= nSourceEndX &&
3613 ( nNewDragY + nSizeY - 1 ) >= nSourceStartY && nNewDragY <= nSourceEndY &&
3614 ( nNewDragY != nSourceStartY || nNewDragX >= nSourceStartX ) ) )
3616 if ( bDragRect )
3618 bDragRect = false;
3619 UpdateDragRectOverlay();
3621 return DND_ACTION_NONE;
3624 else
3626 if ( static_cast< long >( nSizeX ) >= static_cast< long >( nSizeY ) )
3628 eDragInsertMode = INS_CELLSDOWN;
3631 else
3633 eDragInsertMode = INS_CELLSRIGHT;
3638 if ( nNewDragX != (SCsCOL) nDragStartX || nNewDragY != (SCsROW) nDragStartY ||
3639 nDragStartX+nSizeX-1 != nDragEndX || nDragStartY+nSizeY-1 != nDragEndY ||
3640 !bDragRect || eDragInsertMode != meDragInsertMode )
3642 nDragStartX = nNewDragX;
3643 nDragStartY = nNewDragY;
3644 nDragEndX = nDragStartX+nSizeX-1;
3645 nDragEndY = nDragStartY+nSizeY-1;
3646 bDragRect = true;
3647 meDragInsertMode = eDragInsertMode;
3649 UpdateDragRectOverlay();
3653 return rEvt.mnAction;
3656 sal_Int8 ScGridWindow::AcceptDrop( const AcceptDropEvent& rEvt )
3658 const ScDragData& rData = SC_MOD()->GetDragData();
3659 if ( rEvt.mbLeaving )
3661 DrawMarkDropObj( NULL );
3662 if ( rData.pCellTransfer )
3663 return AcceptPrivateDrop( rEvt ); // hide drop marker for internal D&D
3664 else
3665 return rEvt.mnAction;
3668 if ( pViewData->GetDocShell()->IsReadOnly() )
3669 return DND_ACTION_NONE;
3672 sal_Int8 nRet = DND_ACTION_NONE;
3674 if (rData.pCellTransfer)
3676 ScRange aSource = rData.pCellTransfer->GetRange();
3677 if ( aSource.aStart.Col() != 0 || aSource.aEnd.Col() != MAXCOL ||
3678 aSource.aStart.Row() != 0 || aSource.aEnd.Row() != MAXROW )
3679 DropScroll( rEvt.maPosPixel );
3681 nRet = AcceptPrivateDrop( rEvt );
3683 else
3685 if ( !rData.aLinkDoc.isEmpty() )
3687 OUString aThisName;
3688 ScDocShell* pDocSh = pViewData->GetDocShell();
3689 if (pDocSh && pDocSh->HasName())
3690 aThisName = pDocSh->GetMedium()->GetName();
3692 if ( !rData.aLinkDoc.equals(aThisName) )
3693 nRet = rEvt.mnAction;
3695 else if (!rData.aJumpTarget.isEmpty())
3697 // internal bookmarks (from Navigator)
3698 // local jumps from an unnamed document are possible only within a document
3700 if ( !rData.pJumpLocalDoc || rData.pJumpLocalDoc == pViewData->GetDocument() )
3701 nRet = rEvt.mnAction;
3703 else
3705 sal_Int8 nMyAction = rEvt.mnAction;
3707 if ( !rData.pDrawTransfer ||
3708 !IsMyModel(rData.pDrawTransfer->GetDragSourceView()) ) // drawing within the document
3709 if ( rEvt.mbDefault && nMyAction == DND_ACTION_MOVE )
3710 nMyAction = DND_ACTION_COPY;
3712 ScDocument* pThisDoc = pViewData->GetDocument();
3713 SdrObject* pHitObj = pThisDoc->GetObjectAtPoint(
3714 pViewData->GetTabNo(), PixelToLogic(rEvt.maPosPixel) );
3715 if ( pHitObj && nMyAction == DND_ACTION_LINK && !rData.pDrawTransfer )
3717 if ( IsDropFormatSupported(SOT_FORMATSTR_ID_SVXB)
3718 || IsDropFormatSupported(SOT_FORMAT_GDIMETAFILE)
3719 || IsDropFormatSupported(SOT_FORMAT_BITMAP) )
3721 // graphic dragged onto drawing object
3722 DrawMarkDropObj( pHitObj );
3723 nRet = nMyAction;
3726 if (!nRet)
3727 DrawMarkDropObj( NULL );
3729 if (!nRet)
3731 switch ( nMyAction )
3733 case DND_ACTION_COPY:
3734 case DND_ACTION_MOVE:
3735 case DND_ACTION_COPYMOVE:
3737 sal_Bool bMove = ( nMyAction == DND_ACTION_MOVE );
3738 if ( IsDropFormatSupported( SOT_FORMATSTR_ID_EMBED_SOURCE ) ||
3739 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE ) ||
3740 IsDropFormatSupported( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) ||
3741 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ||
3742 IsDropFormatSupported( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) ||
3743 IsDropFormatSupported( SOT_FORMAT_STRING ) ||
3744 IsDropFormatSupported( SOT_FORMATSTR_ID_SYLK ) ||
3745 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK ) ||
3746 IsDropFormatSupported( SOT_FORMATSTR_ID_HTML ) ||
3747 IsDropFormatSupported( SOT_FORMATSTR_ID_HTML_SIMPLE ) ||
3748 IsDropFormatSupported( SOT_FORMATSTR_ID_DIF ) ||
3749 IsDropFormatSupported( SOT_FORMATSTR_ID_DRAWING ) ||
3750 IsDropFormatSupported( SOT_FORMATSTR_ID_SVXB ) ||
3751 IsDropFormatSupported( SOT_FORMAT_RTF ) ||
3752 IsDropFormatSupported( SOT_FORMAT_GDIMETAFILE ) ||
3753 IsDropFormatSupported( SOT_FORMAT_BITMAP ) ||
3754 IsDropFormatSupported( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) ||
3755 IsDropFormatSupported( SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE ) ||
3756 ( !bMove && (
3757 IsDropFormatSupported( SOT_FORMAT_FILE_LIST ) ||
3758 IsDropFormatSupported( SOT_FORMAT_FILE ) ||
3759 IsDropFormatSupported( SOT_FORMATSTR_ID_SOLK ) ||
3760 IsDropFormatSupported( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) ||
3761 IsDropFormatSupported( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) ||
3762 IsDropFormatSupported( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) ) ) )
3764 nRet = nMyAction;
3767 break;
3768 case DND_ACTION_LINK:
3769 if ( IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE ) ||
3770 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ||
3771 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK ) ||
3772 IsDropFormatSupported( SOT_FORMAT_FILE_LIST ) ||
3773 IsDropFormatSupported( SOT_FORMAT_FILE ) ||
3774 IsDropFormatSupported( SOT_FORMATSTR_ID_SOLK ) ||
3775 IsDropFormatSupported( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) ||
3776 IsDropFormatSupported( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) ||
3777 IsDropFormatSupported( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
3779 nRet = nMyAction;
3781 break;
3784 if ( nRet )
3786 // Simple check for protection: It's not known here if the drop will result
3787 // in cells or drawing objects (some formats can be both) and how many cells
3788 // the result will be. But if IsFormatEditable for the drop cell position
3789 // is sal_False (ignores matrix formulas), nothing can be pasted, so the drop
3790 // can already be rejected here.
3792 Point aPos = rEvt.maPosPixel;
3793 SCsCOL nPosX;
3794 SCsROW nPosY;
3795 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
3796 SCTAB nTab = pViewData->GetTabNo();
3797 ScDocument* pDoc = pViewData->GetDocument();
3799 ScEditableTester aTester( pDoc, nTab, nPosX,nPosY, nPosX,nPosY );
3800 if ( !aTester.IsFormatEditable() )
3801 nRet = DND_ACTION_NONE; // forbidden
3806 // scroll only for accepted formats
3807 if (nRet)
3808 DropScroll( rEvt.maPosPixel );
3811 return nRet;
3814 static sal_uLong lcl_GetDropFormatId( const uno::Reference<datatransfer::XTransferable>& xTransfer, bool bPreferText = false )
3816 TransferableDataHelper aDataHelper( xTransfer );
3818 if ( !aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) )
3820 // use bookmark formats if no sba is present
3822 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SOLK ) )
3823 return SOT_FORMATSTR_ID_SOLK;
3824 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) )
3825 return SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR;
3826 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) )
3827 return SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK;
3828 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
3829 return SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR;
3832 sal_uLong nFormatId = 0;
3833 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING ) )
3834 nFormatId = SOT_FORMATSTR_ID_DRAWING;
3835 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ) )
3836 nFormatId = SOT_FORMATSTR_ID_SVXB;
3837 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ) )
3839 // If it's a Writer object, insert RTF instead of OLE
3841 sal_Bool bDoRtf = false;
3842 SotStorageStreamRef xStm;
3843 TransferableObjectDescriptor aObjDesc;
3844 if( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) &&
3845 aDataHelper.GetSotStorageStream( SOT_FORMATSTR_ID_EMBED_SOURCE, xStm ) )
3847 SotStorageRef xStore( new SotStorage( *xStm ) );
3848 bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) ||
3849 aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) )
3850 && aDataHelper.HasFormat( SOT_FORMAT_RTF ) );
3852 if ( bDoRtf )
3853 nFormatId = FORMAT_RTF;
3854 else
3855 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE;
3857 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) )
3858 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE;
3859 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) )
3860 nFormatId = SOT_FORMATSTR_ID_SBA_DATAEXCHANGE;
3861 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE ) )
3862 nFormatId = SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE;
3863 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_BIFF_8 ) )
3864 nFormatId = SOT_FORMATSTR_ID_BIFF_8;
3865 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_BIFF_5 ) )
3866 nFormatId = SOT_FORMATSTR_ID_BIFF_5;
3867 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) )
3868 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE_OLE;
3869 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) )
3870 nFormatId = SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE;
3871 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) )
3872 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE;
3873 else if ( aDataHelper.HasFormat( SOT_FORMAT_RTF ) )
3874 nFormatId = SOT_FORMAT_RTF;
3875 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_HTML ) )
3876 nFormatId = SOT_FORMATSTR_ID_HTML;
3877 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_HTML_SIMPLE ) )
3878 nFormatId = SOT_FORMATSTR_ID_HTML_SIMPLE;
3879 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SYLK ) )
3880 nFormatId = SOT_FORMATSTR_ID_SYLK;
3881 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK ) )
3882 nFormatId = SOT_FORMATSTR_ID_LINK;
3883 else if ( bPreferText && aDataHelper.HasFormat( SOT_FORMAT_STRING ) ) // #i86734# the behaviour introduced in #i62773# is wrong when pasting
3884 nFormatId = SOT_FORMAT_STRING;
3885 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) )
3886 nFormatId = SOT_FORMAT_FILE_LIST;
3887 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE ) ) // #i62773# FILE_LIST/FILE before STRING (Unix file managers)
3888 nFormatId = SOT_FORMAT_FILE;
3889 else if ( aDataHelper.HasFormat( SOT_FORMAT_STRING ) )
3890 nFormatId = SOT_FORMAT_STRING;
3891 else if ( aDataHelper.HasFormat( SOT_FORMAT_GDIMETAFILE ) )
3892 nFormatId = SOT_FORMAT_GDIMETAFILE;
3893 else if ( aDataHelper.HasFormat( SOT_FORMAT_BITMAP ) )
3894 nFormatId = SOT_FORMAT_BITMAP;
3896 return nFormatId;
3899 static sal_uLong lcl_GetDropLinkId( const uno::Reference<datatransfer::XTransferable>& xTransfer )
3901 TransferableDataHelper aDataHelper( xTransfer );
3903 sal_uLong nFormatId = 0;
3904 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) )
3905 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE;
3906 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) )
3907 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE;
3908 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK ) )
3909 nFormatId = SOT_FORMATSTR_ID_LINK;
3910 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) )
3911 nFormatId = SOT_FORMAT_FILE_LIST;
3912 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE ) )
3913 nFormatId = SOT_FORMAT_FILE;
3914 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SOLK ) )
3915 nFormatId = SOT_FORMATSTR_ID_SOLK;
3916 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) )
3917 nFormatId = SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR;
3918 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) )
3919 nFormatId = SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK;
3920 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
3921 nFormatId = SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR;
3923 return nFormatId;
3927 sal_Int8 ScGridWindow::ExecutePrivateDrop( const ExecuteDropEvent& rEvt )
3929 // hide drop marker
3930 bDragRect = false;
3931 UpdateDragRectOverlay();
3933 ScModule* pScMod = SC_MOD();
3934 const ScDragData& rData = pScMod->GetDragData();
3936 return DropTransferObj( rData.pCellTransfer, nDragStartX, nDragStartY,
3937 PixelToLogic(rEvt.maPosPixel), rEvt.mnAction );
3940 sal_Int8 ScGridWindow::DropTransferObj( ScTransferObj* pTransObj, SCCOL nDestPosX, SCROW nDestPosY,
3941 const Point& rLogicPos, sal_Int8 nDndAction )
3943 if ( !pTransObj )
3944 return 0;
3946 ScDocument* pSourceDoc = pTransObj->GetSourceDocument();
3947 ScDocShell* pDocSh = pViewData->GetDocShell();
3948 ScDocument* pThisDoc = pViewData->GetDocument();
3949 ScViewFunc* pView = pViewData->GetView();
3950 SCTAB nThisTab = pViewData->GetTabNo();
3951 sal_uInt16 nFlags = pTransObj->GetDragSourceFlags();
3953 sal_Bool bIsNavi = ( nFlags & SC_DROP_NAVIGATOR ) != 0;
3954 sal_Bool bIsMove = ( nDndAction == DND_ACTION_MOVE && !bIsNavi );
3956 // workaround for wrong nDndAction on Windows when pressing solely
3957 // the Alt key during drag and drop;
3958 // can be removed after #i79215# has been fixed
3959 if ( meDragInsertMode != INS_NONE )
3961 bIsMove = ( nDndAction & DND_ACTION_MOVE && !bIsNavi );
3964 sal_Bool bIsLink = ( nDndAction == DND_ACTION_LINK );
3966 ScRange aSource = pTransObj->GetRange();
3968 // only use visible tab from source range - when dragging within one table,
3969 // all selected tables at the time of dropping are used (handled in MoveBlockTo)
3970 SCTAB nSourceTab = pTransObj->GetVisibleTab();
3971 aSource.aStart.SetTab( nSourceTab );
3972 aSource.aEnd.SetTab( nSourceTab );
3974 SCCOL nSizeX = aSource.aEnd.Col() - aSource.aStart.Col() + 1;
3975 SCROW nSizeY = (bIsMove ? (aSource.aEnd.Row() - aSource.aStart.Row() + 1) :
3976 pTransObj->GetNonFilteredRows()); // copy/link: no filtered rows
3977 ScRange aDest( nDestPosX, nDestPosY, nThisTab,
3978 nDestPosX + nSizeX - 1, nDestPosY + nSizeY - 1, nThisTab );
3981 /* NOTE: AcceptPrivateDrop() already checked for filtered conditions during
3982 * dragging and adapted drawing of the selection frame. We check here
3983 * (again) because this may actually also be called from PasteSelection(),
3984 * we would have to duplicate determination of flags and destination range
3985 * and would lose the context of the "filtered destination is OK" cases
3986 * below, which is already awkward enough as is. */
3988 // Don't move filtered source.
3989 bool bFiltered = (bIsMove && pTransObj->HasFilteredRows());
3990 if (!bFiltered)
3992 if (pSourceDoc != pThisDoc && ((nFlags & SC_DROP_TABLE) ||
3993 (!bIsLink && meDragInsertMode == INS_NONE)))
3995 // Nothing. Either entire sheet to be dropped, or the one case
3996 // where PasteFromClip() is to be called that handles a filtered
3997 // destination itself. Drag-copy from another document without
3998 // inserting cells.
4000 else
4001 // Don't copy or move to filtered destination.
4002 bFiltered = ScViewUtil::HasFiltered( aDest, pThisDoc);
4005 sal_Bool bDone = false;
4007 if (!bFiltered && pSourceDoc == pThisDoc)
4009 if ( nFlags & SC_DROP_TABLE ) // whole sheet?
4011 if ( pThisDoc->IsDocEditable() )
4013 SCTAB nSrcTab = aSource.aStart.Tab();
4014 pViewData->GetDocShell()->MoveTable( nSrcTab, nThisTab, !bIsMove, sal_True ); // with Undo
4015 pView->SetTabNo( nThisTab, sal_True );
4016 bDone = sal_True;
4019 else // move/copy block
4021 OUString aChartName;
4022 if (pThisDoc->HasChartAtPoint( nThisTab, rLogicPos, aChartName ))
4024 String aRangeName;
4025 aSource.Format( aRangeName, SCR_ABS_3D, pThisDoc );
4026 SfxStringItem aNameItem( SID_CHART_NAME, aChartName );
4027 SfxStringItem aRangeItem( SID_CHART_SOURCE, aRangeName );
4028 sal_uInt16 nId = bIsMove ? SID_CHART_SOURCE : SID_CHART_ADDSOURCE;
4029 pViewData->GetDispatcher().Execute( nId, SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD,
4030 &aRangeItem, &aNameItem, (void*) NULL );
4031 bDone = sal_True;
4033 else if ( pThisDoc->GetDPAtCursor( nDestPosX, nDestPosY, nThisTab ) )
4035 // drop on DataPilot table: try to sort, fail if that isn't possible
4037 ScAddress aDestPos( nDestPosX, nDestPosY, nThisTab );
4038 if ( aDestPos != aSource.aStart )
4039 bDone = pViewData->GetView()->DataPilotMove( aSource, aDestPos );
4040 else
4041 bDone = sal_True; // same position: nothing
4043 else if ( nDestPosX != aSource.aStart.Col() || nDestPosY != aSource.aStart.Row() ||
4044 nSourceTab != nThisTab )
4046 String aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY );
4047 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
4049 SCsCOL nCorrectCursorPosCol = 0;
4050 SCsROW nCorrectCursorPosRow = 0;
4052 bDone = sal_True;
4053 if ( meDragInsertMode != INS_NONE )
4055 // call with bApi = sal_True to avoid error messages in drop handler
4056 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, sal_True /*bRecord*/, sal_True /*bApi*/, sal_True /*bPartOfPaste*/ );
4057 if ( bDone )
4059 if ( nThisTab == nSourceTab )
4061 if ( meDragInsertMode == INS_CELLSDOWN &&
4062 nDestPosX == aSource.aStart.Col() && nDestPosY < aSource.aStart.Row() )
4064 bDone = aSource.Move( 0, nSizeY, 0, pSourceDoc );
4065 nCorrectCursorPosRow = nSizeY;
4067 else if ( meDragInsertMode == INS_CELLSRIGHT &&
4068 nDestPosY == aSource.aStart.Row() && nDestPosX < aSource.aStart.Col() )
4070 bDone = aSource.Move( nSizeX, 0, 0, pSourceDoc );
4071 nCorrectCursorPosCol = nSizeX;
4074 pDocSh->UpdateOle( pViewData );
4075 pView->CellContentChanged();
4079 if ( bDone )
4081 if ( bIsLink )
4083 // call with bApi = sal_True to avoid error messages in drop handler
4084 bDone = pView->LinkBlock( aSource, aDest.aStart, sal_True /*bApi*/ );
4086 else
4088 // call with bApi = sal_True to avoid error messages in drop handler
4089 bDone = pView->MoveBlockTo( aSource, aDest.aStart, bIsMove, sal_True /*bRecord*/, sal_True /*bPaint*/, sal_True /*bApi*/ );
4093 if ( bDone && meDragInsertMode != INS_NONE && bIsMove && nThisTab == nSourceTab )
4095 DelCellCmd eCmd = DEL_NONE;
4096 if ( meDragInsertMode == INS_CELLSDOWN )
4098 eCmd = DEL_CELLSUP;
4100 else if ( meDragInsertMode == INS_CELLSRIGHT )
4102 eCmd = DEL_CELLSLEFT;
4105 if ( ( eCmd == DEL_CELLSUP && nDestPosX == aSource.aStart.Col() ) ||
4106 ( eCmd == DEL_CELLSLEFT && nDestPosY == aSource.aStart.Row() ) )
4108 // call with bApi = sal_True to avoid error messages in drop handler
4109 bDone = pDocSh->GetDocFunc().DeleteCells( aSource, NULL, eCmd, sal_True /*bRecord*/, sal_True /*bApi*/ );
4110 if ( bDone )
4112 if ( eCmd == DEL_CELLSUP && nDestPosY > aSource.aEnd.Row() )
4114 bDone = aDest.Move( 0, -nSizeY, 0, pThisDoc );
4116 else if ( eCmd == DEL_CELLSLEFT && nDestPosX > aSource.aEnd.Col() )
4118 bDone = aDest.Move( -nSizeX, 0, 0, pThisDoc );
4120 pDocSh->UpdateOle( pViewData );
4121 pView->CellContentChanged();
4126 if ( bDone )
4128 pView->MarkRange( aDest, false, false );
4130 SCCOL nDCol = pViewData->GetCurX() - aSource.aStart.Col() + nCorrectCursorPosCol;
4131 SCROW nDRow = pViewData->GetCurY() - aSource.aStart.Row() + nCorrectCursorPosRow;
4132 pView->SetCursor( aDest.aStart.Col() + nDCol, aDest.aStart.Row() + nDRow );
4135 pDocSh->GetUndoManager()->LeaveListAction();
4138 else
4139 bDone = sal_True; // nothing to do
4142 if (bDone)
4143 pTransObj->SetDragWasInternal(); // don't delete source in DragFinished
4145 else if ( !bFiltered && pSourceDoc ) // between documents
4147 if ( nFlags & SC_DROP_TABLE ) // copy/link sheets between documents
4149 if ( pThisDoc->IsDocEditable() )
4151 ScDocShell* pSrcShell = pTransObj->GetSourceDocShell();
4153 std::vector<SCTAB> nTabs;
4155 ScMarkData aMark = pTransObj->GetSourceMarkData();
4156 SCTAB nTabCount = pSourceDoc->GetTableCount();
4158 for(SCTAB i=0; i<nTabCount; i++)
4160 if(aMark.GetTableSelect(i))
4162 nTabs.push_back(i);
4163 for(SCTAB j=i+1;j<nTabCount;j++)
4165 if((!pSourceDoc->IsVisible(j))&&(pSourceDoc->IsScenario(j)))
4167 nTabs.push_back( j );
4168 i=j;
4170 else break;
4175 pView->ImportTables( pSrcShell,static_cast<SCTAB>(nTabs.size()), &nTabs[0], bIsLink, nThisTab );
4176 bDone = sal_True;
4179 else if ( bIsLink )
4181 // as in PasteDDE
4182 // (external references might be used instead?)
4184 SfxObjectShell* pSourceSh = pSourceDoc->GetDocumentShell();
4185 OSL_ENSURE(pSourceSh, "drag document has no shell");
4186 if (pSourceSh)
4188 String aUndo = ScGlobal::GetRscString( STR_UNDO_COPY );
4189 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
4191 bDone = sal_True;
4192 if ( meDragInsertMode != INS_NONE )
4194 // call with bApi = sal_True to avoid error messages in drop handler
4195 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, sal_True /*bRecord*/, sal_True /*bApi*/, sal_True /*bPartOfPaste*/ );
4196 if ( bDone )
4198 pDocSh->UpdateOle( pViewData );
4199 pView->CellContentChanged();
4203 if ( bDone )
4205 String aApp = Application::GetAppName();
4206 String aTopic = pSourceSh->GetTitle( SFX_TITLE_FULLNAME );
4207 String aItem;
4208 aSource.Format( aItem, SCA_VALID | SCA_TAB_3D, pSourceDoc );
4210 // TODO: we could define ocQuote for "
4211 const OUString aQuote('"');
4212 const String& sSep = ScCompiler::GetNativeSymbol( ocSep);
4213 OUStringBuffer aFormula;
4214 aFormula.append('=');
4215 aFormula.append(ScCompiler::GetNativeSymbol(ocDde));
4216 aFormula.append(ScCompiler::GetNativeSymbol(ocOpen));
4217 aFormula.append(aQuote);
4218 aFormula.append(aApp);
4219 aFormula.append(aQuote);
4220 aFormula.append(sSep);
4221 aFormula.append(aQuote);
4222 aFormula.append(aTopic);
4223 aFormula.append(aQuote);
4224 aFormula.append(sSep);
4225 aFormula.append(aQuote);
4226 aFormula.append(aItem);
4227 aFormula.append(aQuote);
4228 aFormula.append(ScCompiler::GetNativeSymbol(ocClose));
4230 pView->DoneBlockMode();
4231 pView->InitBlockMode( nDestPosX, nDestPosY, nThisTab );
4232 pView->MarkCursor( nDestPosX + nSizeX - 1,
4233 nDestPosY + nSizeY - 1, nThisTab );
4235 pView->EnterMatrix( aFormula.makeStringAndClear(), ::formula::FormulaGrammar::GRAM_NATIVE );
4237 pView->MarkRange( aDest, false, false );
4238 pView->SetCursor( aDest.aStart.Col(), aDest.aStart.Row() );
4241 pDocSh->GetUndoManager()->LeaveListAction();
4244 else
4246 //! HasSelectedBlockMatrixFragment without selected sheet?
4247 //! or don't start dragging on a part of a matrix
4249 String aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY );
4250 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
4252 bDone = sal_True;
4253 if ( meDragInsertMode != INS_NONE )
4255 // call with bApi = sal_True to avoid error messages in drop handler
4256 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, sal_True /*bRecord*/, sal_True /*bApi*/, sal_True /*bPartOfPaste*/ );
4257 if ( bDone )
4259 pDocSh->UpdateOle( pViewData );
4260 pView->CellContentChanged();
4264 if ( bDone )
4266 pView->Unmark(); // before SetCursor, so CheckSelectionTransfer isn't called with a selection
4267 pView->SetCursor( nDestPosX, nDestPosY );
4268 bDone = pView->PasteFromClip( IDF_ALL, pTransObj->GetDocument() ); // clip-doc
4269 if ( bDone )
4271 pView->MarkRange( aDest, false, false );
4272 pView->SetCursor( aDest.aStart.Col(), aDest.aStart.Row() );
4276 pDocSh->GetUndoManager()->LeaveListAction();
4278 // no longer call ResetMark here - the inserted block has been selected
4279 // and may have been copied to primary selection
4283 sal_Int8 nRet = bDone ? nDndAction : DND_ACTION_NONE;
4284 return nRet;
4287 sal_Int8 ScGridWindow::ExecuteDrop( const ExecuteDropEvent& rEvt )
4289 DrawMarkDropObj( NULL ); // drawing layer
4291 ScModule* pScMod = SC_MOD();
4292 const ScDragData& rData = pScMod->GetDragData();
4293 if (rData.pCellTransfer)
4294 return ExecutePrivateDrop( rEvt );
4296 Point aPos = rEvt.maPosPixel;
4298 if ( !rData.aLinkDoc.isEmpty() )
4300 // try to insert a link
4302 bool bOk = true;
4303 OUString aThisName;
4304 ScDocShell* pDocSh = pViewData->GetDocShell();
4305 if (pDocSh && pDocSh->HasName())
4306 aThisName = pDocSh->GetMedium()->GetName();
4308 if ( rData.aLinkDoc.equals(aThisName) ) // error - no link within a document
4309 bOk = false;
4310 else
4312 ScViewFunc* pView = pViewData->GetView();
4313 if ( !rData.aLinkTable.isEmpty() )
4314 pView->InsertTableLink( rData.aLinkDoc, EMPTY_STRING, EMPTY_STRING,
4315 rData.aLinkTable );
4316 else if ( !rData.aLinkArea.isEmpty() )
4318 SCsCOL nPosX;
4319 SCsROW nPosY;
4320 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
4321 pView->MoveCursorAbs( nPosX, nPosY, SC_FOLLOW_NONE, false, false );
4323 pView->InsertAreaLink( rData.aLinkDoc, EMPTY_STRING, EMPTY_STRING,
4324 rData.aLinkArea, 0 );
4326 else
4328 OSL_FAIL("drop with link: no sheet nor area");
4329 bOk = false;
4333 return bOk ? rEvt.mnAction : DND_ACTION_NONE; // don't try anything else
4336 Point aLogicPos = PixelToLogic(aPos);
4338 if (rData.pDrawTransfer)
4340 sal_uInt16 nFlags = rData.pDrawTransfer->GetDragSourceFlags();
4342 sal_Bool bIsNavi = ( nFlags & SC_DROP_NAVIGATOR ) != 0;
4343 sal_Bool bIsMove = ( rEvt.mnAction == DND_ACTION_MOVE && !bIsNavi );
4345 bPasteIsMove = bIsMove;
4347 pViewData->GetView()->PasteDraw( aLogicPos, rData.pDrawTransfer->GetModel() );
4349 if (bPasteIsMove)
4350 rData.pDrawTransfer->SetDragWasInternal();
4351 bPasteIsMove = false;
4353 return rEvt.mnAction;
4357 SCsCOL nPosX;
4358 SCsROW nPosY;
4359 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
4361 if (!rData.aJumpTarget.isEmpty())
4363 // internal bookmark (from Navigator)
4364 // bookmark clipboard formats are in PasteScDataObject
4366 if ( !rData.pJumpLocalDoc || rData.pJumpLocalDoc == pViewData->GetDocument() )
4368 pViewData->GetViewShell()->InsertBookmark( rData.aJumpText, rData.aJumpTarget,
4369 nPosX, nPosY );
4370 return rEvt.mnAction;
4374 sal_Bool bIsLink = ( rEvt.mnAction == DND_ACTION_LINK );
4376 ScDocument* pThisDoc = pViewData->GetDocument();
4377 SdrObject* pHitObj = pThisDoc->GetObjectAtPoint( pViewData->GetTabNo(), PixelToLogic(aPos) );
4378 if ( pHitObj && bIsLink )
4380 // dropped on drawing object
4381 // PasteOnDrawObject checks for valid formats
4382 if ( pViewData->GetView()->PasteOnDrawObject( rEvt.maDropEvent.Transferable, pHitObj, sal_True ) )
4383 return rEvt.mnAction;
4386 sal_Bool bDone = false;
4388 sal_uLong nFormatId = bIsLink ?
4389 lcl_GetDropLinkId( rEvt.maDropEvent.Transferable ) :
4390 lcl_GetDropFormatId( rEvt.maDropEvent.Transferable );
4391 if ( nFormatId )
4393 pScMod->SetInExecuteDrop( sal_True ); // #i28468# prevent error messages from PasteDataFormat
4394 bPasteIsDrop = sal_True;
4395 bDone = pViewData->GetView()->PasteDataFormat(
4396 nFormatId, rEvt.maDropEvent.Transferable, nPosX, nPosY, &aLogicPos, bIsLink );
4397 bPasteIsDrop = false;
4398 pScMod->SetInExecuteDrop( false );
4401 sal_Int8 nRet = bDone ? rEvt.mnAction : DND_ACTION_NONE;
4402 return nRet;
4405 //--------------------------------------------------------
4407 void ScGridWindow::PasteSelection( const Point& rPosPixel )
4409 Point aLogicPos = PixelToLogic( rPosPixel );
4411 SCsCOL nPosX;
4412 SCsROW nPosY;
4413 pViewData->GetPosFromPixel( rPosPixel.X(), rPosPixel.Y(), eWhich, nPosX, nPosY );
4415 // If the mouse down was inside a visible note window, ignore it and
4416 // leave it up to the ScPostIt to handle it
4417 SdrView* pDrawView = pViewData->GetViewShell()->GetSdrView();
4418 if (pDrawView)
4420 sal_uLong nCount = pDrawView->GetMarkedObjectCount();
4421 for (sal_uLong i = 0; i < nCount; ++i)
4423 SdrObject* pObj = pDrawView->GetMarkedObjectByIndex(i);
4424 if (pObj && pObj->GetLogicRect().IsInside(aLogicPos))
4426 // Inside an active drawing object. Bail out.
4427 return;
4432 ScSelectionTransferObj* pOwnSelection = SC_MOD()->GetSelectionTransfer();
4433 if ( pOwnSelection )
4435 // within Calc
4437 ScTransferObj* pCellTransfer = pOwnSelection->GetCellData();
4438 if ( pCellTransfer )
4440 // keep a reference to the data in case the selection is changed during paste
4441 uno::Reference<datatransfer::XTransferable> xRef( pCellTransfer );
4442 DropTransferObj( pCellTransfer, nPosX, nPosY, aLogicPos, DND_ACTION_COPY );
4444 else
4446 ScDrawTransferObj* pDrawTransfer = pOwnSelection->GetDrawData();
4447 if ( pDrawTransfer )
4449 // keep a reference to the data in case the selection is changed during paste
4450 uno::Reference<datatransfer::XTransferable> xRef( pDrawTransfer );
4452 // bSameDocClipboard argument for PasteDraw is needed
4453 // because only DragData is checked directly inside PasteDraw
4454 pViewData->GetView()->PasteDraw( aLogicPos, pDrawTransfer->GetModel(), false,
4455 pDrawTransfer->GetSourceDocID() == pViewData->GetDocument()->GetDocumentID() );
4459 else
4461 // get selection from system
4463 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSelection( this ) );
4464 uno::Reference<datatransfer::XTransferable> xTransferable = aDataHelper.GetTransferable();
4465 if ( xTransferable.is() )
4467 sal_uLong nFormatId = lcl_GetDropFormatId( xTransferable, true );
4468 if ( nFormatId )
4470 bPasteIsDrop = sal_True;
4471 pViewData->GetView()->PasteDataFormat( nFormatId, xTransferable, nPosX, nPosY, &aLogicPos );
4472 bPasteIsDrop = false;
4478 //--------------------------------------------------------
4480 void ScGridWindow::UpdateEditViewPos()
4482 if (pViewData->HasEditView(eWhich))
4484 EditView* pView;
4485 SCCOL nCol;
4486 SCROW nRow;
4487 pViewData->GetEditView( eWhich, pView, nCol, nRow );
4488 SCCOL nEndCol = pViewData->GetEditEndCol();
4489 SCROW nEndRow = pViewData->GetEditEndRow();
4491 // hide EditView?
4493 sal_Bool bHide = ( nEndCol<pViewData->GetPosX(eHWhich) || nEndRow<pViewData->GetPosY(eVWhich) );
4494 if ( SC_MOD()->IsFormulaMode() )
4495 if ( pViewData->GetTabNo() != pViewData->GetRefTabNo() )
4496 bHide = sal_True;
4498 if (bHide)
4500 Rectangle aRect = pView->GetOutputArea();
4501 long nHeight = aRect.Bottom() - aRect.Top();
4502 aRect.Top() = PixelToLogic(GetOutputSizePixel(), pViewData->GetLogicMode()).
4503 Height() * 2;
4504 aRect.Bottom() = aRect.Top() + nHeight;
4505 pView->SetOutputArea( aRect );
4506 pView->HideCursor();
4508 else
4510 // bForceToTop = sal_True for editing
4511 Rectangle aPixRect = pViewData->GetEditArea( eWhich, nCol, nRow, this, NULL, sal_True );
4512 Point aScrPos = PixelToLogic( aPixRect.TopLeft(), pViewData->GetLogicMode() );
4514 Rectangle aRect = pView->GetOutputArea();
4515 aRect.SetPos( aScrPos );
4516 pView->SetOutputArea( aRect );
4517 pView->ShowCursor();
4522 void ScGridWindow::ScrollPixel( long nDifX, long nDifY )
4524 ClickExtern();
4525 HideNoteMarker();
4527 bIsInScroll = true;
4529 SetMapMode(MAP_PIXEL);
4530 Scroll( nDifX, nDifY, SCROLL_CHILDREN );
4531 SetMapMode( GetDrawMapMode() ); // verschobenen MapMode erzeugen
4533 UpdateEditViewPos();
4535 DrawAfterScroll();
4536 bIsInScroll = false;
4539 // Formeln neu zeichnen -------------------------------------------------
4541 void ScGridWindow::UpdateFormulas()
4543 if (pViewData->GetView()->IsMinimized())
4544 return;
4546 if ( nPaintCount )
4548 // nicht anfangen, verschachtelt zu painten
4549 // (dann wuerde zumindest der MapMode nicht mehr stimmen)
4551 bNeedsRepaint = true; // -> am Ende vom Paint nochmal Invalidate auf alles
4552 aRepaintPixel = Rectangle(); // alles
4553 return;
4556 SCCOL nX1 = pViewData->GetPosX( eHWhich );
4557 SCROW nY1 = pViewData->GetPosY( eVWhich );
4558 SCCOL nX2 = nX1 + pViewData->VisibleCellsX( eHWhich );
4559 SCROW nY2 = nY1 + pViewData->VisibleCellsY( eVWhich );
4561 if (nX2 > MAXCOL) nX2 = MAXCOL;
4562 if (nY2 > MAXROW) nY2 = MAXROW;
4564 // Draw( nX1, nY1, nX2, nY2, SC_UPDATE_CHANGED );
4566 // don't draw directly - instead use OutputData to find changed area and invalidate
4568 SCROW nPosY = nY1;
4570 ScDocShell* pDocSh = pViewData->GetDocShell();
4571 ScDocument* pDoc = pDocSh->GetDocument();
4572 SCTAB nTab = pViewData->GetTabNo();
4574 pDoc->ExtendHidden( nX1, nY1, nX2, nY2, nTab );
4576 Point aScrPos = pViewData->GetScrPos( nX1, nY1, eWhich );
4577 long nMirrorWidth = GetSizePixel().Width();
4578 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
4579 if ( bLayoutRTL )
4581 long nEndPixel = pViewData->GetScrPos( nX2+1, nPosY, eWhich ).X();
4582 nMirrorWidth = aScrPos.X() - nEndPixel;
4583 aScrPos.X() = nEndPixel + 1;
4586 long nScrX = aScrPos.X();
4587 long nScrY = aScrPos.Y();
4589 double nPPTX = pViewData->GetPPTX();
4590 double nPPTY = pViewData->GetPPTY();
4592 ScTableInfo aTabInfo;
4593 pDoc->FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nTab, nPPTX, nPPTY, false, false );
4595 Fraction aZoomX = pViewData->GetZoomX();
4596 Fraction aZoomY = pViewData->GetZoomY();
4597 ScOutputData aOutputData( this, OUTTYPE_WINDOW, aTabInfo, pDoc, nTab,
4598 nScrX, nScrY, nX1, nY1, nX2, nY2, nPPTX, nPPTY,
4599 &aZoomX, &aZoomY );
4600 aOutputData.SetMirrorWidth( nMirrorWidth );
4602 aOutputData.FindChanged();
4604 PolyPolygon aChangedPoly( aOutputData.GetChangedArea() ); // logic (PixelToLogic)
4605 if ( aChangedPoly.Count() )
4607 Invalidate(Region(aChangedPoly));
4610 CheckNeedsRepaint(); // #i90362# used to be called via Draw() - still needed here
4613 void ScGridWindow::UpdateAutoFillMark(bool bMarked, const ScRange& rMarkRange)
4615 if ( bMarked != bAutoMarkVisible || ( bMarked && rMarkRange.aEnd != aAutoMarkPos ) )
4617 bAutoMarkVisible = bMarked;
4618 if ( bMarked )
4619 aAutoMarkPos = rMarkRange.aEnd;
4621 UpdateAutoFillOverlay();
4625 void ScGridWindow::UpdateListValPos( bool bVisible, const ScAddress& rPos )
4627 bool bOldButton = bListValButton;
4628 ScAddress aOldPos = aListValPos;
4630 bListValButton = bVisible;
4631 aListValPos = rPos;
4633 if ( bListValButton )
4635 if ( !bOldButton || aListValPos != aOldPos )
4637 // paint area of new button
4638 Invalidate( PixelToLogic( GetListValButtonRect( aListValPos ) ) );
4641 if ( bOldButton )
4643 if ( !bListValButton || aListValPos != aOldPos )
4645 // paint area of old button
4646 Invalidate( PixelToLogic( GetListValButtonRect( aOldPos ) ) );
4651 void ScGridWindow::HideCursor()
4653 ++nCursorHideCount;
4656 void ScGridWindow::ShowCursor()
4658 --nCursorHideCount;
4661 void ScGridWindow::GetFocus()
4663 ScTabViewShell* pViewShell = pViewData->GetViewShell();
4664 pViewShell->GotFocus();
4665 pViewShell->SetFormShellAtTop( false ); // focus in GridWindow -> FormShell no longer on top
4667 if (pViewShell->HasAccessibilityObjects())
4668 pViewShell->BroadcastAccessibility(ScAccGridWinFocusGotHint(eWhich, GetAccessible()));
4671 if ( !SC_MOD()->IsFormulaMode() )
4673 pViewShell->UpdateInputHandler();
4674 // StopMarking(); // falls Dialog (Fehler), weil dann kein ButtonUp
4675 // MO: nur wenn nicht im RefInput-Modus
4676 // -> GetFocus/MouseButtonDown-Reihenfolge
4677 // auf dem Mac
4680 pViewData->GetDocShell()->CheckConfigOptions();
4681 Window::GetFocus();
4684 void ScGridWindow::LoseFocus()
4686 ScTabViewShell* pViewShell = pViewData->GetViewShell();
4687 pViewShell->LostFocus();
4689 if (pViewShell->HasAccessibilityObjects())
4690 pViewShell->BroadcastAccessibility(ScAccGridWinFocusLostHint(eWhich, GetAccessible()));
4692 Window::LoseFocus();
4695 Point ScGridWindow::GetMousePosPixel() const { return aCurMousePos; }
4697 //------------------------------------------------------------------------
4699 bool ScGridWindow::HitRangeFinder( const Point& rMouse, bool& rCorner,
4700 sal_uInt16* pIndex, SCsCOL* pAddX, SCsROW* pAddY )
4702 bool bFound = false;
4703 ScInputHandler* pHdl = SC_MOD()->GetInputHdl( pViewData->GetViewShell() );
4704 if (pHdl)
4706 ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList();
4707 if ( pRangeFinder && !pRangeFinder->IsHidden() &&
4708 pRangeFinder->GetDocName() == pViewData->GetDocShell()->GetTitle() )
4710 ScDocument* pDoc = pViewData->GetDocument();
4711 SCTAB nTab = pViewData->GetTabNo();
4712 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
4713 long nLayoutSign = bLayoutRTL ? -1 : 1;
4715 SCsCOL nPosX;
4716 SCsROW nPosY;
4717 pViewData->GetPosFromPixel( rMouse.X(), rMouse.Y(), eWhich, nPosX, nPosY );
4718 // zusammengefasste (einzeln/Bereich) ???
4719 ScAddress aAddr( nPosX, nPosY, nTab );
4721 Point aNext = pViewData->GetScrPos( nPosX, nPosY, eWhich, true );
4722 long nSizeXPix;
4723 long nSizeYPix;
4724 pViewData->GetMergeSizePixel( nPosX, nPosY, nSizeXPix, nSizeYPix );
4725 aNext.X() += nSizeXPix * nLayoutSign;
4726 aNext.Y() += nSizeYPix;
4728 bool bCornerHor;
4729 if ( bLayoutRTL )
4730 bCornerHor = ( rMouse.X() >= aNext.X() && rMouse.X() <= aNext.X() + 8 );
4731 else
4732 bCornerHor = ( rMouse.X() >= aNext.X() - 8 && rMouse.X() <= aNext.X() );
4734 bool bCellCorner = ( bCornerHor &&
4735 rMouse.Y() >= aNext.Y() - 8 && rMouse.Y() <= aNext.Y() );
4736 // corner is hit only if the mouse is within the cell
4738 sal_uInt16 nCount = (sal_uInt16)pRangeFinder->Count();
4739 for (sal_uInt16 i=nCount; i;)
4741 // rueckwaerts suchen, damit der zuletzt gepaintete Rahmen gefunden wird
4742 --i;
4743 ScRangeFindData* pData = pRangeFinder->GetObject(i);
4744 if ( pData->aRef.In(aAddr) )
4746 if (pIndex) *pIndex = i;
4747 if (pAddX) *pAddX = nPosX - pData->aRef.aStart.Col();
4748 if (pAddY) *pAddY = nPosY - pData->aRef.aStart.Row();
4749 bFound = sal_True;
4750 rCorner = ( bCellCorner && aAddr == pData->aRef.aEnd );
4751 break;
4756 return bFound;
4759 #define SCE_TOP 1
4760 #define SCE_BOTTOM 2
4761 #define SCE_LEFT 4
4762 #define SCE_RIGHT 8
4763 #define SCE_ALL 15
4765 static void lcl_PaintOneRange( ScDocShell* pDocSh, const ScRange& rRange, sal_uInt16 nEdges )
4767 // der Range ist immer richtigherum
4769 SCCOL nCol1 = rRange.aStart.Col();
4770 SCROW nRow1 = rRange.aStart.Row();
4771 SCTAB nTab1 = rRange.aStart.Tab();
4772 SCCOL nCol2 = rRange.aEnd.Col();
4773 SCROW nRow2 = rRange.aEnd.Row();
4774 SCTAB nTab2 = rRange.aEnd.Tab();
4775 sal_Bool bHiddenEdge = false;
4776 SCROW nTmp;
4778 ScDocument* pDoc = pDocSh->GetDocument();
4779 while ( nCol1 > 0 && pDoc->ColHidden(nCol1, nTab1) )
4781 --nCol1;
4782 bHiddenEdge = sal_True;
4784 while ( nCol2 < MAXCOL && pDoc->ColHidden(nCol2, nTab1) )
4786 ++nCol2;
4787 bHiddenEdge = sal_True;
4789 nTmp = pDoc->FirstVisibleRow(0, nRow1, nTab1);
4790 if (!ValidRow(nTmp))
4791 nTmp = 0;
4792 if (nTmp < nRow1)
4794 nRow1 = nTmp;
4795 bHiddenEdge = sal_True;
4797 nTmp = pDoc->FirstVisibleRow(nRow2, MAXROW, nTab1);
4798 if (!ValidRow(nTmp))
4799 nTmp = MAXROW;
4800 if (nTmp > nRow2)
4802 nRow2 = nTmp;
4803 bHiddenEdge = sal_True;
4806 if ( nCol2 > nCol1 + 1 && nRow2 > nRow1 + 1 && !bHiddenEdge )
4808 // nur an den Raendern entlang
4809 // (die Ecken werden evtl. zweimal getroffen)
4811 if ( nEdges & SCE_TOP )
4812 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol2, nRow1, nTab2, PAINT_MARKS );
4813 if ( nEdges & SCE_LEFT )
4814 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol1, nRow2, nTab2, PAINT_MARKS );
4815 if ( nEdges & SCE_RIGHT )
4816 pDocSh->PostPaint( nCol2, nRow1, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
4817 if ( nEdges & SCE_BOTTOM )
4818 pDocSh->PostPaint( nCol1, nRow2, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
4820 else // everything in one call
4821 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
4824 static void lcl_PaintRefChanged( ScDocShell* pDocSh, const ScRange& rOldUn, const ScRange& rNewUn )
4826 // Repaint fuer die Teile des Rahmens in Old, die bei New nicht mehr da sind
4828 ScRange aOld = rOldUn;
4829 ScRange aNew = rNewUn;
4830 aOld.Justify();
4831 aNew.Justify();
4833 if ( aOld.aStart == aOld.aEnd ) //! Tab ignorieren?
4834 pDocSh->GetDocument()->ExtendMerge(aOld);
4835 if ( aNew.aStart == aNew.aEnd ) //! Tab ignorieren?
4836 pDocSh->GetDocument()->ExtendMerge(aNew);
4838 SCCOL nOldCol1 = aOld.aStart.Col();
4839 SCROW nOldRow1 = aOld.aStart.Row();
4840 SCCOL nOldCol2 = aOld.aEnd.Col();
4841 SCROW nOldRow2 = aOld.aEnd.Row();
4842 SCCOL nNewCol1 = aNew.aStart.Col();
4843 SCROW nNewRow1 = aNew.aStart.Row();
4844 SCCOL nNewCol2 = aNew.aEnd.Col();
4845 SCROW nNewRow2 = aNew.aEnd.Row();
4846 SCTAB nTab1 = aOld.aStart.Tab(); // Tab aendert sich nicht
4847 SCTAB nTab2 = aOld.aEnd.Tab();
4849 if ( nNewRow2 < nOldRow1 || nNewRow1 > nOldRow2 ||
4850 nNewCol2 < nOldCol1 || nNewCol1 > nOldCol2 ||
4851 ( nNewCol1 != nOldCol1 && nNewRow1 != nOldRow1 &&
4852 nNewCol2 != nOldCol2 && nNewRow2 != nOldRow2 ) )
4854 // komplett weggeschoben oder alle Seiten veraendert
4855 // (Abfrage <= statt < geht schief bei einzelnen Zeilen/Spalten)
4857 lcl_PaintOneRange( pDocSh, aOld, SCE_ALL );
4859 else // alle vier Kanten einzeln testen
4861 // oberer Teil
4862 if ( nNewRow1 < nOldRow1 ) // nur obere Linie loeschen
4863 lcl_PaintOneRange( pDocSh, ScRange(
4864 nOldCol1, nOldRow1, nTab1, nOldCol2, nOldRow1, nTab2 ), SCE_ALL );
4865 else if ( nNewRow1 > nOldRow1 ) // den Teil, der oben wegkommt
4866 lcl_PaintOneRange( pDocSh, ScRange(
4867 nOldCol1, nOldRow1, nTab1, nOldCol2, nNewRow1-1, nTab2 ),
4868 SCE_ALL &~ SCE_BOTTOM );
4870 // unterer Teil
4871 if ( nNewRow2 > nOldRow2 ) // nur untere Linie loeschen
4872 lcl_PaintOneRange( pDocSh, ScRange(
4873 nOldCol1, nOldRow2, nTab1, nOldCol2, nOldRow2, nTab2 ), SCE_ALL );
4874 else if ( nNewRow2 < nOldRow2 ) // den Teil, der unten wegkommt
4875 lcl_PaintOneRange( pDocSh, ScRange(
4876 nOldCol1, nNewRow2+1, nTab1, nOldCol2, nOldRow2, nTab2 ),
4877 SCE_ALL &~ SCE_TOP );
4879 // linker Teil
4880 if ( nNewCol1 < nOldCol1 ) // nur linke Linie loeschen
4881 lcl_PaintOneRange( pDocSh, ScRange(
4882 nOldCol1, nOldRow1, nTab1, nOldCol1, nOldRow2, nTab2 ), SCE_ALL );
4883 else if ( nNewCol1 > nOldCol1 ) // den Teil, der links wegkommt
4884 lcl_PaintOneRange( pDocSh, ScRange(
4885 nOldCol1, nOldRow1, nTab1, nNewCol1-1, nOldRow2, nTab2 ),
4886 SCE_ALL &~ SCE_RIGHT );
4888 // rechter Teil
4889 if ( nNewCol2 > nOldCol2 ) // nur rechte Linie loeschen
4890 lcl_PaintOneRange( pDocSh, ScRange(
4891 nOldCol2, nOldRow1, nTab1, nOldCol2, nOldRow2, nTab2 ), SCE_ALL );
4892 else if ( nNewCol2 < nOldCol2 ) // den Teil, der rechts wegkommt
4893 lcl_PaintOneRange( pDocSh, ScRange(
4894 nNewCol2+1, nOldRow1, nTab1, nOldCol2, nOldRow2, nTab2 ),
4895 SCE_ALL &~ SCE_LEFT );
4899 void ScGridWindow::RFMouseMove( const MouseEvent& rMEvt, sal_Bool bUp )
4901 ScInputHandler* pHdl = SC_MOD()->GetInputHdl( pViewData->GetViewShell() );
4902 if (!pHdl)
4903 return;
4904 ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList();
4905 if (!pRangeFinder || nRFIndex >= pRangeFinder->Count())
4906 return;
4907 ScRangeFindData* pData = pRangeFinder->GetObject( nRFIndex );
4909 // Mauszeiger
4911 if (bRFSize)
4912 SetPointer( Pointer( POINTER_CROSS ) );
4913 else
4914 SetPointer( Pointer( POINTER_HAND ) );
4916 // Scrolling
4918 sal_Bool bTimer = false;
4919 Point aPos = rMEvt.GetPosPixel();
4920 SCsCOL nDx = 0;
4921 SCsROW nDy = 0;
4922 if ( aPos.X() < 0 ) nDx = -1;
4923 if ( aPos.Y() < 0 ) nDy = -1;
4924 Size aSize = GetOutputSizePixel();
4925 if ( aPos.X() >= aSize.Width() )
4926 nDx = 1;
4927 if ( aPos.Y() >= aSize.Height() )
4928 nDy = 1;
4929 if ( nDx != 0 || nDy != 0 )
4931 if ( nDx != 0) pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) );
4932 if ( nDy != 0 ) pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) );
4933 bTimer = sal_True;
4936 // Umschalten bei Fixierung (damit Scrolling funktioniert)
4938 if ( eWhich == pViewData->GetActivePart() ) //??
4940 if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX )
4941 if ( nDx > 0 )
4943 if ( eWhich == SC_SPLIT_TOPLEFT )
4944 pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT );
4945 else if ( eWhich == SC_SPLIT_BOTTOMLEFT )
4946 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT );
4949 if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX )
4950 if ( nDy > 0 )
4952 if ( eWhich == SC_SPLIT_TOPLEFT )
4953 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT );
4954 else if ( eWhich == SC_SPLIT_TOPRIGHT )
4955 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT );
4959 // Verschieben
4961 SCsCOL nPosX;
4962 SCsROW nPosY;
4963 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
4965 ScRange aOld = pData->aRef;
4966 ScRange aNew = aOld;
4967 if ( bRFSize )
4969 aNew.aEnd.SetCol((SCCOL)nPosX);
4970 aNew.aEnd.SetRow((SCROW)nPosY);
4972 else
4974 long nStartX = nPosX - nRFAddX;
4975 if ( nStartX < 0 ) nStartX = 0;
4976 long nStartY = nPosY - nRFAddY;
4977 if ( nStartY < 0 ) nStartY = 0;
4978 long nEndX = nStartX + aOld.aEnd.Col() - aOld.aStart.Col();
4979 if ( nEndX > MAXCOL )
4981 nStartX -= ( nEndX - MAXROW );
4982 nEndX = MAXCOL;
4984 long nEndY = nStartY + aOld.aEnd.Row() - aOld.aStart.Row();
4985 if ( nEndY > MAXROW )
4987 nStartY -= ( nEndY - MAXROW );
4988 nEndY = MAXROW;
4991 aNew.aStart.SetCol((SCCOL)nStartX);
4992 aNew.aStart.SetRow((SCROW)nStartY);
4993 aNew.aEnd.SetCol((SCCOL)nEndX);
4994 aNew.aEnd.SetRow((SCROW)nEndY);
4997 if ( bUp )
4998 aNew.Justify(); // beim ButtonUp wieder richtigherum
5000 if ( aNew != aOld )
5002 pHdl->UpdateRange( nRFIndex, aNew );
5004 ScDocShell* pDocSh = pViewData->GetDocShell();
5006 // nur das neuzeichnen, was sich veraendert hat...
5007 lcl_PaintRefChanged( pDocSh, aOld, aNew );
5009 // neuen Rahmen nur drueberzeichnen (synchron)
5010 pDocSh->Broadcast( ScIndexHint( SC_HINT_SHOWRANGEFINDER, nRFIndex ) );
5012 Update(); // was man bewegt, will man auch sofort sehen
5015 // Timer fuer Scrolling
5017 if (bTimer)
5018 pViewData->GetView()->SetTimer( this, rMEvt ); // Event wiederholen
5019 else
5020 pViewData->GetView()->ResetTimer();
5023 //------------------------------------------------------------------------
5025 bool ScGridWindow::GetEditUrl( const Point& rPos,
5026 String* pName, String* pUrl, String* pTarget )
5028 return GetEditUrlOrError( false, rPos, pName, pUrl, pTarget );
5031 bool ScGridWindow::GetEditUrlOrError( bool bSpellErr, const Point& rPos,
5032 String* pName, String* pUrl, String* pTarget )
5034 //! nPosX/Y mit uebergeben?
5035 SCsCOL nPosX;
5036 SCsROW nPosY;
5037 pViewData->GetPosFromPixel( rPos.X(), rPos.Y(), eWhich, nPosX, nPosY );
5039 SCTAB nTab = pViewData->GetTabNo();
5040 ScDocShell* pDocSh = pViewData->GetDocShell();
5041 ScDocument* pDoc = pDocSh->GetDocument();
5042 OUString sURL;
5043 ScRefCellValue aCell;
5044 bool bFound = lcl_GetHyperlinkCell(pDoc, nPosX, nPosY, nTab, aCell, sURL);
5045 if( !bFound )
5046 return false;
5048 const ScPatternAttr* pPattern = pDoc->GetPattern( nPosX, nPosY, nTab );
5049 // bForceToTop = sal_False, use the cell's real position
5050 Rectangle aEditRect = pViewData->GetEditArea( eWhich, nPosX, nPosY, this, pPattern, false );
5051 if (rPos.Y() < aEditRect.Top())
5052 return false;
5054 // vertikal kann (noch) nicht angeklickt werden:
5056 if (pPattern->GetCellOrientation() != SVX_ORIENTATION_STANDARD)
5057 return false;
5059 sal_Bool bBreak = ((SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK)).GetValue() ||
5060 ((SvxCellHorJustify)((const SvxHorJustifyItem&)pPattern->
5061 GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_BLOCK);
5062 SvxCellHorJustify eHorJust = (SvxCellHorJustify)((SvxHorJustifyItem&)pPattern->
5063 GetItem(ATTR_HOR_JUSTIFY)).GetValue();
5065 // EditEngine
5067 ScFieldEditEngine aEngine(pDoc, pDoc->GetEditPool());
5068 ScSizeDeviceProvider aProv(pDocSh);
5069 aEngine.SetRefDevice( aProv.GetDevice() );
5070 aEngine.SetRefMapMode( MAP_100TH_MM );
5071 SfxItemSet aDefault( aEngine.GetEmptyItemSet() );
5072 pPattern->FillEditItemSet( &aDefault );
5073 SvxAdjust eSvxAdjust = SVX_ADJUST_LEFT;
5074 switch (eHorJust)
5076 case SVX_HOR_JUSTIFY_LEFT:
5077 case SVX_HOR_JUSTIFY_REPEAT: // nicht implementiert
5078 case SVX_HOR_JUSTIFY_STANDARD: // always Text if an EditCell type
5079 eSvxAdjust = SVX_ADJUST_LEFT;
5080 break;
5081 case SVX_HOR_JUSTIFY_RIGHT:
5082 eSvxAdjust = SVX_ADJUST_RIGHT;
5083 break;
5084 case SVX_HOR_JUSTIFY_CENTER:
5085 eSvxAdjust = SVX_ADJUST_CENTER;
5086 break;
5087 case SVX_HOR_JUSTIFY_BLOCK:
5088 eSvxAdjust = SVX_ADJUST_BLOCK;
5089 break;
5091 aDefault.Put( SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) );
5092 aEngine.SetDefaults( aDefault );
5093 if (bSpellErr)
5094 aEngine.SetControlWord( aEngine.GetControlWord() | EE_CNTRL_ONLINESPELLING );
5096 MapMode aEditMode = pViewData->GetLogicMode(eWhich); // ohne Drawing-Skalierung
5097 Rectangle aLogicEdit = PixelToLogic( aEditRect, aEditMode );
5098 long nThisColLogic = aLogicEdit.Right() - aLogicEdit.Left() + 1;
5099 Size aPaperSize = Size( 1000000, 1000000 );
5100 if (aCell.meType == CELLTYPE_FORMULA)
5102 long nSizeX = 0;
5103 long nSizeY = 0;
5104 pViewData->GetMergeSizePixel( nPosX, nPosY, nSizeX, nSizeY );
5105 aPaperSize = Size(nSizeX, nSizeY );
5106 aPaperSize = PixelToLogic(aPaperSize);
5109 if (bBreak)
5110 aPaperSize.Width() = nThisColLogic;
5111 aEngine.SetPaperSize( aPaperSize );
5113 boost::scoped_ptr<EditTextObject> pTextObj;
5114 if (aCell.meType == CELLTYPE_EDIT)
5116 if (aCell.mpEditText)
5117 aEngine.SetText(*aCell.mpEditText);
5119 else // Not an Edit cell and is a formula cell with 'Hyperlink'
5120 // function if we have no URL, otherwise it could be a formula
5121 // cell ( or other type ? ) with a hyperlink associated with it.
5123 if (sURL.isEmpty())
5124 pTextObj.reset(aCell.mpFormula->CreateURLObject());
5125 else
5126 pTextObj.reset(ScEditUtil::CreateURLObjectFromURL(*pDoc, sURL, sURL));
5128 if (pTextObj.get())
5129 aEngine.SetText(*pTextObj);
5132 long nStartX = aLogicEdit.Left();
5134 long nTextWidth = aEngine.CalcTextWidth();
5135 long nTextHeight = aEngine.GetTextHeight();
5136 if ( nTextWidth < nThisColLogic )
5138 if (eHorJust == SVX_HOR_JUSTIFY_RIGHT)
5139 nStartX += nThisColLogic - nTextWidth;
5140 else if (eHorJust == SVX_HOR_JUSTIFY_CENTER)
5141 nStartX += (nThisColLogic - nTextWidth) / 2;
5144 aLogicEdit.Left() = nStartX;
5145 if (!bBreak)
5146 aLogicEdit.Right() = nStartX + nTextWidth;
5148 // There is one glitch when dealing with a hyperlink cell and
5149 // the cell content is NUMERIC. This defaults to right aligned and
5150 // we need to adjust accordingly.
5151 if (aCell.meType == CELLTYPE_FORMULA && aCell.mpFormula->IsValue() &&
5152 eHorJust == SVX_HOR_JUSTIFY_STANDARD)
5154 aLogicEdit.Right() = aLogicEdit.Left() + nThisColLogic - 1;
5155 aLogicEdit.Left() = aLogicEdit.Right() - nTextWidth;
5157 aLogicEdit.Bottom() = aLogicEdit.Top() + nTextHeight;
5160 Point aLogicClick = PixelToLogic(rPos,aEditMode);
5161 if ( aLogicEdit.IsInside(aLogicClick) )
5163 EditView aTempView( &aEngine, this );
5164 aTempView.SetOutputArea( aLogicEdit );
5166 sal_Bool bRet = false;
5167 MapMode aOld = GetMapMode();
5168 SetMapMode(aEditMode); // kein return mehr
5170 if (bSpellErr) // Spelling-Fehler suchen
5172 bRet = aTempView.IsWrongSpelledWordAtPos( rPos );
5173 if ( bRet )
5174 pViewData->GetView()->SetCursor( nPosX, nPosY ); // Cursor setzen
5176 else // URL suchen
5178 const SvxFieldItem* pFieldItem = aTempView.GetFieldUnderMousePointer();
5180 if (pFieldItem)
5182 const SvxFieldData* pField = pFieldItem->GetField();
5183 if ( pField && pField->ISA(SvxURLField) )
5185 if ( pName || pUrl || pTarget )
5187 const SvxURLField* pURLField = (const SvxURLField*)pField;
5188 if (pName)
5189 *pName = pURLField->GetRepresentation();
5190 if (pUrl)
5191 *pUrl = pURLField->GetURL();
5192 if (pTarget)
5193 *pTarget = pURLField->GetTargetFrame();
5195 bRet = sal_True;
5200 SetMapMode(aOld);
5202 return bRet;
5204 return false;
5207 bool ScGridWindow::HasScenarioButton( const Point& rPosPixel, ScRange& rScenRange )
5209 ScDocument* pDoc = pViewData->GetDocument();
5210 SCTAB nTab = pViewData->GetTabNo();
5211 SCTAB nTabCount = pDoc->GetTableCount();
5212 if ( nTab+1<nTabCount && pDoc->IsScenario(nTab+1) && !pDoc->IsScenario(nTab) )
5214 bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5216 Size aButSize = pViewData->GetScenButSize();
5217 long nBWidth = aButSize.Width();
5218 if (!nBWidth)
5219 return false; // noch kein Button gezeichnet -> da ist auch keiner
5220 long nBHeight = aButSize.Height();
5221 long nHSpace = (long)( SC_SCENARIO_HSPACE * pViewData->GetPPTX() );
5223 //! Ranges an der Table cachen!!!!
5225 ScMarkData aMarks;
5226 for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
5227 pDoc->MarkScenario( i, nTab, aMarks, false, SC_SCENARIO_SHOWFRAME );
5228 ScRangeList aRanges;
5229 aMarks.FillRangeListWithMarks( &aRanges, false );
5232 size_t nRangeCount = aRanges.size();
5233 for (size_t j=0; j< nRangeCount; ++j)
5235 ScRange aRange = *aRanges[j];
5236 // Szenario-Rahmen immer dann auf zusammengefasste Zellen erweitern, wenn
5237 // dadurch keine neuen nicht-ueberdeckten Zellen mit umrandet werden
5238 pDoc->ExtendTotalMerge( aRange );
5240 bool bTextBelow = ( aRange.aStart.Row() == 0 );
5242 Point aButtonPos;
5243 if ( bTextBelow )
5245 aButtonPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aEnd.Row()+1,
5246 eWhich, sal_True );
5248 else
5250 aButtonPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aStart.Row(),
5251 eWhich, sal_True );
5252 aButtonPos.Y() -= nBHeight;
5254 if ( bLayoutRTL )
5255 aButtonPos.X() -= nHSpace - 1;
5256 else
5257 aButtonPos.X() -= nBWidth - nHSpace; // same for top or bottom
5259 Rectangle aButRect( aButtonPos, Size(nBWidth,nBHeight) );
5260 if ( aButRect.IsInside( rPosPixel ) )
5262 rScenRange = aRange;
5263 return true;
5268 return false;
5271 // #114409#
5272 void ScGridWindow::DrawLayerCreated()
5274 SetMapMode( GetDrawMapMode() );
5276 // initially create overlay objects
5277 ImpCreateOverlayObjects();
5280 // #114409#
5281 void ScGridWindow::CursorChanged()
5283 // here the created OverlayObjects may be transformed in later versions. For
5284 // now, just re-create them
5286 UpdateCursorOverlay();
5289 // #114409#
5290 void ScGridWindow::ImpCreateOverlayObjects()
5292 UpdateCursorOverlay();
5293 UpdateCopySourceOverlay();
5294 UpdateSelectionOverlay();
5295 UpdateAutoFillOverlay();
5296 UpdateDragRectOverlay();
5297 UpdateHeaderOverlay();
5298 UpdateShrinkOverlay();
5301 // #114409#
5302 void ScGridWindow::ImpDestroyOverlayObjects()
5304 DeleteCursorOverlay();
5305 DeleteCopySourceOverlay();
5306 DeleteSelectionOverlay();
5307 DeleteAutoFillOverlay();
5308 DeleteDragRectOverlay();
5309 DeleteHeaderOverlay();
5310 DeleteShrinkOverlay();
5313 void ScGridWindow::UpdateAllOverlays()
5315 // delete and re-allocate all overlay objects
5317 ImpDestroyOverlayObjects();
5318 ImpCreateOverlayObjects();
5321 void ScGridWindow::DeleteCursorOverlay()
5323 DELETEZ( mpOOCursors );
5326 void ScGridWindow::DeleteCopySourceOverlay()
5328 DELETEZ( mpOOSelectionBorder );
5331 void ScGridWindow::UpdateCopySourceOverlay()
5333 MapMode aDrawMode = GetDrawMapMode();
5334 MapMode aOldMode = GetMapMode();
5335 if ( aOldMode != aDrawMode )
5336 SetMapMode( aDrawMode );
5338 DeleteCopySourceOverlay();
5340 if (!pViewData->ShowPasteSource())
5341 return;
5342 rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager = getOverlayManager();
5343 if (!xOverlayManager.is())
5344 return;
5345 ScTransferObj* pTransObj = ScTransferObj::GetOwnClipboard( pViewData->GetActiveWin() );
5346 if (!pTransObj)
5347 return;
5348 ScDocument* pClipDoc = pTransObj->GetDocument();
5349 if (!pClipDoc)
5350 return;
5352 SCTAB nCurTab = pViewData->GetCurPos().Tab();
5354 ScClipParam& rClipParam = pClipDoc->GetClipParam();
5355 mpOOSelectionBorder = new ::sdr::overlay::OverlayObjectList;
5356 for ( size_t i = 0; i < rClipParam.maRanges.size(); ++i )
5358 ScRange* p = rClipParam.maRanges[i];
5359 if (p->aStart.Tab() != nCurTab)
5360 continue;
5362 SCCOL nClipStartX = p->aStart.Col();
5363 SCROW nClipStartY = p->aStart.Row();
5364 SCCOL nClipEndX = p->aEnd.Col();
5365 SCROW nClipEndY = p->aEnd.Row();
5367 Point aClipStartScrPos = pViewData->GetScrPos( nClipStartX, nClipStartY, eWhich );
5368 Point aClipEndScrPos = pViewData->GetScrPos( nClipEndX + 1, nClipEndY + 1, eWhich );
5369 aClipStartScrPos -= Point(1, 1);
5370 long nSizeXPix = aClipEndScrPos.X() - aClipStartScrPos.X();
5371 long nSizeYPix = aClipEndScrPos.Y() - aClipStartScrPos.Y();
5373 Rectangle aRect( aClipStartScrPos, Size(nSizeXPix, nSizeYPix) );
5376 Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
5378 Rectangle aLogic = PixelToLogic(aRect, aDrawMode);
5379 ::basegfx::B2DRange aRange(aLogic.Left(), aLogic.Top(), aLogic.Right(), aLogic.Bottom());
5380 ScOverlayDashedBorder* pDashedBorder = new ScOverlayDashedBorder(aRange, aHighlight);
5381 xOverlayManager->add(*pDashedBorder);
5382 mpOOSelectionBorder->append(*pDashedBorder);
5385 if ( aOldMode != aDrawMode )
5386 SetMapMode( aOldMode );
5389 void ScGridWindow::UpdateCursorOverlay()
5391 MapMode aDrawMode = GetDrawMapMode();
5392 MapMode aOldMode = GetMapMode();
5393 if ( aOldMode != aDrawMode )
5394 SetMapMode( aDrawMode );
5396 // Existing OverlayObjects may be transformed in later versions.
5397 // For now, just re-create them.
5399 DeleteCursorOverlay();
5401 std::vector<Rectangle> aPixelRects;
5404 // determine the cursor rectangles in pixels (moved from ScGridWindow::DrawCursor)
5407 SCTAB nTab = pViewData->GetTabNo();
5408 SCCOL nX = pViewData->GetCurX();
5409 SCROW nY = pViewData->GetCurY();
5411 if (!maVisibleRange.isInside(nX, nY))
5412 return;
5414 // don't show the cursor in overlapped cells
5416 ScDocument* pDoc = pViewData->GetDocument();
5417 const ScPatternAttr* pPattern = pDoc->GetPattern(nX,nY,nTab);
5418 const ScMergeFlagAttr& rMergeFlag = (const ScMergeFlagAttr&) pPattern->GetItem(ATTR_MERGE_FLAG);
5419 sal_Bool bOverlapped = rMergeFlag.IsOverlapped();
5421 // left or above of the screen?
5423 sal_Bool bVis = ( nX>=pViewData->GetPosX(eHWhich) && nY>=pViewData->GetPosY(eVWhich) );
5424 if (!bVis)
5426 SCCOL nEndX = nX;
5427 SCROW nEndY = nY;
5428 const ScMergeAttr& rMerge = (const ScMergeAttr&) pPattern->GetItem(ATTR_MERGE);
5429 if (rMerge.GetColMerge() > 1)
5430 nEndX += rMerge.GetColMerge()-1;
5431 if (rMerge.GetRowMerge() > 1)
5432 nEndY += rMerge.GetRowMerge()-1;
5433 bVis = ( nEndX>=pViewData->GetPosX(eHWhich) && nEndY>=pViewData->GetPosY(eVWhich) );
5436 if ( bVis && !bOverlapped && !pViewData->HasEditView(eWhich) && pViewData->IsActive() )
5438 Point aScrPos = pViewData->GetScrPos( nX, nY, eWhich, sal_True );
5439 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5441 // completely right of/below the screen?
5442 // (test with logical start position in aScrPos)
5443 sal_Bool bMaybeVisible;
5444 if ( bLayoutRTL )
5445 bMaybeVisible = ( aScrPos.X() >= -2 && aScrPos.Y() >= -2 );
5446 else
5448 Size aOutSize = GetOutputSizePixel();
5449 bMaybeVisible = ( aScrPos.X() <= aOutSize.Width() + 2 && aScrPos.Y() <= aOutSize.Height() + 2 );
5451 if ( bMaybeVisible )
5453 long nSizeXPix;
5454 long nSizeYPix;
5455 pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix );
5457 if ( bLayoutRTL )
5458 aScrPos.X() -= nSizeXPix - 2; // move instead of mirroring
5460 // Now, draw the cursor.
5462 aScrPos.X() -= 2;
5463 aScrPos.Y() -= 2;
5464 Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) );
5466 aPixelRects.push_back(Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() ));
5467 aPixelRects.push_back(Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() ));
5468 aPixelRects.push_back(Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 ));
5469 aPixelRects.push_back(Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() ));
5473 if ( !aPixelRects.empty() )
5475 // #i70788# get the OverlayManager safely
5476 rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager = getOverlayManager();
5478 if (xOverlayManager.is())
5480 Color aCursorColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
5481 if (pViewData->GetActivePart() != eWhich)
5482 // non-active pane uses a different color.
5483 aCursorColor = SC_MOD()->GetColorConfig().GetColorValue(svtools::CALCPAGEBREAKAUTOMATIC).nColor;
5484 std::vector< basegfx::B2DRange > aRanges;
5485 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5487 for(sal_uInt32 a(0); a < aPixelRects.size(); a++)
5489 const Rectangle aRA(aPixelRects[a]);
5490 basegfx::B2DRange aRB(aRA.Left(), aRA.Top(), aRA.Right() + 1, aRA.Bottom() + 1);
5491 aRB.transform(aTransform);
5492 aRanges.push_back(aRB);
5495 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5496 sdr::overlay::OVERLAY_SOLID,
5497 aCursorColor,
5498 aRanges,
5499 false);
5501 xOverlayManager->add(*pOverlay);
5502 mpOOCursors = new ::sdr::overlay::OverlayObjectList;
5503 mpOOCursors->append(*pOverlay);
5507 if ( aOldMode != aDrawMode )
5508 SetMapMode( aOldMode );
5511 void ScGridWindow::DeleteSelectionOverlay()
5513 DELETEZ( mpOOSelection );
5516 void ScGridWindow::UpdateSelectionOverlay()
5518 MapMode aDrawMode = GetDrawMapMode();
5519 MapMode aOldMode = GetMapMode();
5520 if ( aOldMode != aDrawMode )
5521 SetMapMode( aDrawMode );
5523 DeleteSelectionOverlay();
5524 std::vector<Rectangle> aPixelRects;
5525 GetSelectionRects( aPixelRects );
5527 if ( aPixelRects.size() && pViewData->IsActive() )
5529 // #i70788# get the OverlayManager safely
5530 rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager = getOverlayManager();
5532 if (xOverlayManager.is())
5534 std::vector< basegfx::B2DRange > aRanges;
5535 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5537 for(sal_uInt32 a(0); a < aPixelRects.size(); a++)
5539 const Rectangle aRA(aPixelRects[a]);
5540 basegfx::B2DRange aRB(aRA.Left() - 1, aRA.Top() - 1, aRA.Right(), aRA.Bottom());
5541 aRB.transform(aTransform);
5542 aRanges.push_back(aRB);
5545 // #i97672# get the system's hilight color and limit it to the maximum
5546 // allowed luminance. This is needed to react on too bright hilight colors
5547 // which would otherwise vive a bad visualisation
5548 Color aHighlight(GetSettings().GetStyleSettings().GetHighlightColor());
5549 const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
5550 const basegfx::BColor aSelection(aHighlight.getBColor());
5551 const double fLuminance(aSelection.luminance());
5552 const double fMaxLum(aSvtOptionsDrawinglayer.GetSelectionMaximumLuminancePercent() / 100.0);
5554 if(fLuminance > fMaxLum)
5556 const double fFactor(fMaxLum / fLuminance);
5557 const basegfx::BColor aNewSelection(
5558 aSelection.getRed() * fFactor,
5559 aSelection.getGreen() * fFactor,
5560 aSelection.getBlue() * fFactor);
5562 aHighlight = Color(aNewSelection);
5565 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5566 sdr::overlay::OVERLAY_TRANSPARENT,
5567 aHighlight,
5568 aRanges,
5569 true);
5571 xOverlayManager->add(*pOverlay);
5572 mpOOSelection = new ::sdr::overlay::OverlayObjectList;
5573 mpOOSelection->append(*pOverlay);
5577 if ( aOldMode != aDrawMode )
5578 SetMapMode( aOldMode );
5581 void ScGridWindow::DeleteAutoFillOverlay()
5583 DELETEZ( mpOOAutoFill );
5584 mpAutoFillRect.reset();
5587 void ScGridWindow::UpdateAutoFillOverlay()
5589 MapMode aDrawMode = GetDrawMapMode();
5590 MapMode aOldMode = GetMapMode();
5591 if ( aOldMode != aDrawMode )
5592 SetMapMode( aDrawMode );
5594 DeleteAutoFillOverlay();
5597 // get the AutoFill handle rectangle in pixels
5600 if ( bAutoMarkVisible && aAutoMarkPos.Tab() == pViewData->GetTabNo() &&
5601 !pViewData->HasEditView(eWhich) && pViewData->IsActive() )
5603 SCCOL nX = aAutoMarkPos.Col();
5604 SCROW nY = aAutoMarkPos.Row();
5606 if (!maVisibleRange.isInside(nX, nY))
5607 // Autofill mark is not visible. Bail out.
5608 return;
5610 SCTAB nTab = pViewData->GetTabNo();
5611 ScDocument* pDoc = pViewData->GetDocument();
5612 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5614 Point aFillPos = pViewData->GetScrPos( nX, nY, eWhich, sal_True );
5615 long nSizeXPix;
5616 long nSizeYPix;
5617 pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix );
5618 if ( bLayoutRTL )
5619 aFillPos.X() -= nSizeXPix + 3;
5620 else
5621 aFillPos.X() += nSizeXPix - 2;
5623 aFillPos.Y() += nSizeYPix;
5624 aFillPos.Y() -= 2;
5625 mpAutoFillRect.reset(new Rectangle(aFillPos, Size(6, 6)));
5627 // #i70788# get the OverlayManager safely
5628 rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager = getOverlayManager();
5630 if (xOverlayManager.is())
5632 Color aHandleColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
5633 if (pViewData->GetActivePart() != eWhich)
5634 // non-active pane uses a different color.
5635 aHandleColor = SC_MOD()->GetColorConfig().GetColorValue(svtools::CALCPAGEBREAKAUTOMATIC).nColor;
5636 std::vector< basegfx::B2DRange > aRanges;
5637 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5638 basegfx::B2DRange aRB(mpAutoFillRect->Left(), mpAutoFillRect->Top(), mpAutoFillRect->Right() + 1, mpAutoFillRect->Bottom() + 1);
5640 aRB.transform(aTransform);
5641 aRanges.push_back(aRB);
5643 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5644 sdr::overlay::OVERLAY_SOLID,
5645 aHandleColor,
5646 aRanges,
5647 false);
5649 xOverlayManager->add(*pOverlay);
5650 mpOOAutoFill = new ::sdr::overlay::OverlayObjectList;
5651 mpOOAutoFill->append(*pOverlay);
5654 if ( aOldMode != aDrawMode )
5655 SetMapMode( aOldMode );
5659 void ScGridWindow::DeleteDragRectOverlay()
5661 DELETEZ( mpOODragRect );
5664 void ScGridWindow::UpdateDragRectOverlay()
5666 MapMode aDrawMode = GetDrawMapMode();
5667 MapMode aOldMode = GetMapMode();
5668 if ( aOldMode != aDrawMode )
5669 SetMapMode( aDrawMode );
5671 DeleteDragRectOverlay();
5674 // get the rectangles in pixels (moved from DrawDragRect)
5677 if ( bDragRect || bPagebreakDrawn )
5679 std::vector<Rectangle> aPixelRects;
5681 SCCOL nX1 = bDragRect ? nDragStartX : aPagebreakDrag.aStart.Col();
5682 SCROW nY1 = bDragRect ? nDragStartY : aPagebreakDrag.aStart.Row();
5683 SCCOL nX2 = bDragRect ? nDragEndX : aPagebreakDrag.aEnd.Col();
5684 SCROW nY2 = bDragRect ? nDragEndY : aPagebreakDrag.aEnd.Row();
5686 SCTAB nTab = pViewData->GetTabNo();
5688 SCCOL nPosX = pViewData->GetPosX(WhichH(eWhich));
5689 SCROW nPosY = pViewData->GetPosY(WhichV(eWhich));
5690 if (nX1 < nPosX) nX1 = nPosX;
5691 if (nX2 < nPosX) nX2 = nPosX;
5692 if (nY1 < nPosY) nY1 = nPosY;
5693 if (nY2 < nPosY) nY2 = nPosY;
5695 Point aScrPos( pViewData->GetScrPos( nX1, nY1, eWhich ) );
5697 long nSizeXPix=0;
5698 long nSizeYPix=0;
5699 ScDocument* pDoc = pViewData->GetDocument();
5700 double nPPTX = pViewData->GetPPTX();
5701 double nPPTY = pViewData->GetPPTY();
5702 SCCOLROW i;
5704 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5705 long nLayoutSign = bLayoutRTL ? -1 : 1;
5707 if (ValidCol(nX2) && nX2>=nX1)
5708 for (i=nX1; i<=nX2; i++)
5709 nSizeXPix += ScViewData::ToPixel( pDoc->GetColWidth( static_cast<SCCOL>(i), nTab ), nPPTX );
5710 else
5712 aScrPos.X() -= nLayoutSign;
5713 nSizeXPix += 2;
5716 if (ValidRow(nY2) && nY2>=nY1)
5717 for (i=nY1; i<=nY2; i++)
5718 nSizeYPix += ScViewData::ToPixel( pDoc->GetRowHeight( i, nTab ), nPPTY );
5719 else
5721 aScrPos.Y() -= 1;
5722 nSizeYPix += 2;
5725 aScrPos.X() -= 2 * nLayoutSign;
5726 aScrPos.Y() -= 2;
5727 Rectangle aRect( aScrPos.X(), aScrPos.Y(),
5728 aScrPos.X() + ( nSizeXPix + 2 ) * nLayoutSign, aScrPos.Y() + nSizeYPix + 2 );
5729 if ( bLayoutRTL )
5731 aRect.Left() = aRect.Right(); // end position is left
5732 aRect.Right() = aScrPos.X();
5735 if ( meDragInsertMode == INS_CELLSDOWN )
5737 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Top()+3, aRect.Left()+1, aRect.Bottom()-2 ) );
5738 aPixelRects.push_back( Rectangle( aRect.Right()-1, aRect.Top()+3, aRect.Right()-1, aRect.Bottom()-2 ) );
5739 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Top(), aRect.Right()-1, aRect.Top()+2 ) );
5740 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Bottom()-1, aRect.Right()-1, aRect.Bottom()-1 ) );
5742 else if ( meDragInsertMode == INS_CELLSRIGHT )
5744 aPixelRects.push_back( Rectangle( aRect.Left(), aRect.Top()+1, aRect.Left()+2, aRect.Bottom()-1 ) );
5745 aPixelRects.push_back( Rectangle( aRect.Right()-1, aRect.Top()+1, aRect.Right()-1, aRect.Bottom()-1 ) );
5746 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Top()+1, aRect.Right()-2, aRect.Top()+1 ) );
5747 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Bottom()-1, aRect.Right()-2, aRect.Bottom()-1 ) );
5749 else
5751 aPixelRects.push_back( Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() ) );
5752 aPixelRects.push_back( Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() ) );
5753 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 ) );
5754 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() ) );
5757 // #i70788# get the OverlayManager safely
5758 rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager = getOverlayManager();
5760 if (xOverlayManager.is())
5762 std::vector< basegfx::B2DRange > aRanges;
5763 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5765 for(sal_uInt32 a(0); a < aPixelRects.size(); a++)
5767 const Rectangle aRA(aPixelRects[a]);
5768 basegfx::B2DRange aRB(aRA.Left(), aRA.Top(), aRA.Right() + 1, aRA.Bottom() + 1);
5769 aRB.transform(aTransform);
5770 aRanges.push_back(aRB);
5773 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5774 sdr::overlay::OVERLAY_INVERT,
5775 Color(COL_BLACK),
5776 aRanges,
5777 false);
5779 xOverlayManager->add(*pOverlay);
5780 mpOODragRect = new ::sdr::overlay::OverlayObjectList;
5781 mpOODragRect->append(*pOverlay);
5785 if ( aOldMode != aDrawMode )
5786 SetMapMode( aOldMode );
5789 void ScGridWindow::DeleteHeaderOverlay()
5791 DELETEZ( mpOOHeader );
5794 void ScGridWindow::UpdateHeaderOverlay()
5796 MapMode aDrawMode = GetDrawMapMode();
5797 MapMode aOldMode = GetMapMode();
5798 if ( aOldMode != aDrawMode )
5799 SetMapMode( aDrawMode );
5801 DeleteHeaderOverlay();
5803 // Pixel rectangle is in aInvertRect
5804 if ( !aInvertRect.IsEmpty() )
5806 // #i70788# get the OverlayManager safely
5807 rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager = getOverlayManager();
5809 if (xOverlayManager.is())
5811 // Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
5812 std::vector< basegfx::B2DRange > aRanges;
5813 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5814 basegfx::B2DRange aRB(aInvertRect.Left(), aInvertRect.Top(), aInvertRect.Right() + 1, aInvertRect.Bottom() + 1);
5816 aRB.transform(aTransform);
5817 aRanges.push_back(aRB);
5819 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5820 sdr::overlay::OVERLAY_INVERT,
5821 Color(COL_BLACK),
5822 aRanges,
5823 false);
5825 xOverlayManager->add(*pOverlay);
5826 mpOOHeader = new ::sdr::overlay::OverlayObjectList;
5827 mpOOHeader->append(*pOverlay);
5831 if ( aOldMode != aDrawMode )
5832 SetMapMode( aOldMode );
5835 void ScGridWindow::DeleteShrinkOverlay()
5837 DELETEZ( mpOOShrink );
5840 void ScGridWindow::UpdateShrinkOverlay()
5842 MapMode aDrawMode = GetDrawMapMode();
5843 MapMode aOldMode = GetMapMode();
5844 if ( aOldMode != aDrawMode )
5845 SetMapMode( aDrawMode );
5847 DeleteShrinkOverlay();
5850 // get the rectangle in pixels
5853 Rectangle aPixRect;
5854 ScRange aRange;
5855 SCTAB nTab = pViewData->GetTabNo();
5856 if ( pViewData->IsRefMode() && nTab >= pViewData->GetRefStartZ() && nTab <= pViewData->GetRefEndZ() &&
5857 pViewData->GetDelMark( aRange ) )
5859 //! limit to visible area
5860 if ( aRange.aStart.Col() <= aRange.aEnd.Col() &&
5861 aRange.aStart.Row() <= aRange.aEnd.Row() )
5863 Point aStart = pViewData->GetScrPos( aRange.aStart.Col(),
5864 aRange.aStart.Row(), eWhich );
5865 Point aEnd = pViewData->GetScrPos( aRange.aEnd.Col()+1,
5866 aRange.aEnd.Row()+1, eWhich );
5867 aEnd.X() -= 1;
5868 aEnd.Y() -= 1;
5870 aPixRect = Rectangle( aStart,aEnd );
5874 if ( !aPixRect.IsEmpty() )
5876 // #i70788# get the OverlayManager safely
5877 rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager = getOverlayManager();
5879 if (xOverlayManager.is())
5881 std::vector< basegfx::B2DRange > aRanges;
5882 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5883 basegfx::B2DRange aRB(aPixRect.Left(), aPixRect.Top(), aPixRect.Right() + 1, aPixRect.Bottom() + 1);
5885 aRB.transform(aTransform);
5886 aRanges.push_back(aRB);
5888 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5889 sdr::overlay::OVERLAY_INVERT,
5890 Color(COL_BLACK),
5891 aRanges,
5892 false);
5894 xOverlayManager->add(*pOverlay);
5895 mpOOShrink = new ::sdr::overlay::OverlayObjectList;
5896 mpOOShrink->append(*pOverlay);
5900 if ( aOldMode != aDrawMode )
5901 SetMapMode( aOldMode );
5904 // #i70788# central method to get the OverlayManager safely
5905 rtl::Reference<sdr::overlay::OverlayManager> ScGridWindow::getOverlayManager()
5907 SdrPageView* pPV = pViewData->GetView()->GetScDrawView()->GetSdrPageView();
5909 if(pPV)
5911 SdrPageWindow* pPageWin = pPV->FindPageWindow( *this );
5913 if ( pPageWin )
5915 return (pPageWin->GetOverlayManager());
5919 return rtl::Reference<sdr::overlay::OverlayManager>();
5922 void ScGridWindow::flushOverlayManager()
5924 // #i70788# get the OverlayManager safely
5925 rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager = getOverlayManager();
5927 if (xOverlayManager.is())
5928 xOverlayManager->flush();
5931 void ScGridWindow::SetInRefMode( bool bInRefMode )
5933 WinBits nBits = GetStyle();
5934 if(bInRefMode)
5935 nBits |= WB_REFMODE;
5936 else
5937 nBits &= ~WB_REFMODE;
5939 SetStyle( nBits );
5942 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */