Bump version to 4.3-4
[LibreOffice.git] / sc / source / ui / view / gridwin.cxx
blobcc1e2a79f9eee0ce65d34ba2fcd3e709549db071
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>
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 <editeng/unolingu.hxx>
31 #include <editeng/langitem.hxx>
32 #include <editeng/misspellrange.hxx>
33 #include <svx/svdetc.hxx>
34 #include <editeng/editobj.hxx>
35 #include <sfx2/dispatch.hxx>
36 #include <sfx2/viewfrm.hxx>
37 #include <sfx2/docfile.hxx>
38 #include <svl/stritem.hxx>
39 #include <svtools/svtabbx.hxx>
40 #include <svl/urlbmk.hxx>
41 #include <svl/sharedstringpool.hxx>
42 #include <vcl/cursor.hxx>
43 #include <vcl/graph.hxx>
44 #include <vcl/hatch.hxx>
45 #include <vcl/settings.hxx>
46 #include <sot/formats.hxx>
47 #include <comphelper/classids.hxx>
48 #include <sal/macros.h>
50 #include <svx/svdview.hxx>
51 #include <editeng/outliner.hxx>
52 #include <svx/svditer.hxx>
53 #include <svx/svdocapt.hxx>
54 #include <svx/svdpagv.hxx>
56 #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
57 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
58 #include <com/sun/star/sheet/DataPilotTableHeaderData.hpp>
59 #include <com/sun/star/sheet/DataPilotTableResultData.hpp>
60 #include <com/sun/star/sheet/DataPilotTablePositionData.hpp>
61 #include <com/sun/star/sheet/DataPilotTablePositionType.hpp>
62 #include <com/sun/star/sheet/MemberResultFlags.hpp>
63 #include <com/sun/star/awt/KeyModifier.hpp>
64 #include <com/sun/star/awt/MouseButton.hpp>
65 #include <com/sun/star/script/vba/VBAEventId.hpp>
66 #include <com/sun/star/script/vba/XVBAEventProcessor.hpp>
67 #include <com/sun/star/text/textfield/Type.hpp>
69 #include "gridwin.hxx"
70 #include "tabvwsh.hxx"
71 #include "docsh.hxx"
72 #include "viewdata.hxx"
73 #include "tabview.hxx"
74 #include "select.hxx"
75 #include "scmod.hxx"
76 #include "document.hxx"
77 #include "attrib.hxx"
78 #include "dbdata.hxx"
79 #include "stlpool.hxx"
80 #include "printfun.hxx"
81 #include "cbutton.hxx"
82 #include "sc.hrc"
83 #include "globstr.hrc"
84 #include "editutil.hxx"
85 #include "scresid.hxx"
86 #include "inputhdl.hxx"
87 #include "uiitems.hxx"
88 #include "filtdlg.hxx"
89 #include "impex.hxx"
90 #include "formulacell.hxx"
91 #include "patattr.hxx"
92 #include "notemark.hxx"
93 #include "rfindlst.hxx"
94 #include "docpool.hxx"
95 #include "output.hxx"
96 #include "docfunc.hxx"
97 #include "dbdocfun.hxx"
98 #include "dpobject.hxx"
99 #include "dpoutput.hxx"
100 #include "transobj.hxx"
101 #include "drwtrans.hxx"
102 #include "seltrans.hxx"
103 #include "sizedev.hxx"
104 #include "AccessibilityHints.hxx"
105 #include "dpsave.hxx"
106 #include "viewuno.hxx"
107 #include "compiler.hxx"
108 #include "editable.hxx"
109 #include "fillinfo.hxx"
110 #include "userdat.hxx"
111 #include "drwlayer.hxx"
112 #include "validat.hxx"
113 #include "tabprotection.hxx"
114 #include "postit.hxx"
115 #include "dpcontrol.hxx"
116 #include "checklistmenu.hxx"
117 #include "clipparam.hxx"
118 #include "cellsh.hxx"
119 #include "overlayobject.hxx"
120 #include "cellsuno.hxx"
121 #include "drawview.hxx"
122 #include "dragdata.hxx"
123 #include "cliputil.hxx"
124 #include "queryentry.hxx"
125 #include "markdata.hxx"
126 #include "checklistmenu.hrc"
127 #include "strload.hxx"
128 #include "externalrefmgr.hxx"
129 #include "dociter.hxx"
130 #include "hints.hxx"
131 #include "spellcheckcontext.hxx"
133 #include <svx/sdrpagewindow.hxx>
134 #include <svx/sdr/overlay/overlaymanager.hxx>
135 #include <vcl/svapp.hxx>
136 #include <svx/sdr/overlay/overlayselection.hxx>
138 #include <vector>
139 #include <boost/scoped_ptr.hpp>
140 #include <boost/shared_ptr.hpp>
142 using namespace com::sun::star;
143 using ::com::sun::star::uno::Sequence;
144 using ::com::sun::star::uno::Any;
146 const sal_uInt8 SC_NESTEDBUTTON_NONE = 0;
147 const sal_uInt8 SC_NESTEDBUTTON_DOWN = 1;
148 const sal_uInt8 SC_NESTEDBUTTON_UP = 2;
150 #define SC_AUTOFILTER_ALL 0
151 #define SC_AUTOFILTER_TOP10 1
152 #define SC_AUTOFILTER_CUSTOM 2
153 #define SC_AUTOFILTER_EMPTY 3
154 #define SC_AUTOFILTER_NOTEMPTY 4
156 // Modi fuer die FilterListBox
157 enum ScFilterBoxMode
159 SC_FILTERBOX_FILTER,
160 SC_FILTERBOX_DATASELECT,
161 SC_FILTERBOX_SCENARIO,
162 SC_FILTERBOX_PAGEFIELD
165 extern SfxViewShell* pScActiveViewShell; // global.cxx
166 extern sal_uInt16 nScClickMouseModifier; // global.cxx
167 extern sal_uInt16 nScFillModeMouseModifier; // global.cxx
169 struct ScGridWindow::MouseEventState
171 bool mbActivatePart;
173 MouseEventState() : mbActivatePart(false) {}
176 #define SC_FILTERLISTBOX_LINES 12
178 ScGridWindow::VisibleRange::VisibleRange() :
179 mnCol1(0), mnCol2(MAXCOL), mnRow1(0), mnRow2(MAXROW)
183 bool ScGridWindow::VisibleRange::isInside(SCCOL nCol, SCROW nRow) const
185 return mnCol1 <= nCol && nCol <= mnCol2 && mnRow1 <= nRow && nRow <= mnRow2;
188 bool ScGridWindow::VisibleRange::set(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
190 bool bChanged = mnCol1 != nCol1 || mnRow1 != nRow1 || mnCol2 != nCol2 || mnRow2 != nRow2;
192 mnCol1 = nCol1;
193 mnRow1 = nRow1;
194 mnCol2 = nCol2;
195 mnRow2 = nRow2;
197 return bChanged;
200 class ScFilterListBox : public ListBox
202 private:
203 ScGridWindow* pGridWin;
204 SCCOL nCol;
205 SCROW nRow;
206 bool bButtonDown;
207 bool bInit;
208 bool bCancelled;
209 bool bInSelect;
210 bool mbListHasDates;
211 sal_uLong nSel;
212 ScFilterBoxMode eMode;
214 protected:
215 virtual void LoseFocus() SAL_OVERRIDE;
216 void SelectHdl();
218 public:
219 ScFilterListBox( Window* pParent, ScGridWindow* pGrid,
220 SCCOL nNewCol, SCROW nNewRow, ScFilterBoxMode eNewMode );
221 virtual ~ScFilterListBox();
223 virtual bool PreNotify( NotifyEvent& rNEvt ) SAL_OVERRIDE;
224 virtual void Select() SAL_OVERRIDE;
226 SCCOL GetCol() const { return nCol; }
227 SCROW GetRow() const { return nRow; }
228 ScFilterBoxMode GetMode() const { return eMode; }
229 void EndInit();
230 bool IsInInit() const { return bInit; }
231 void SetCancelled() { bCancelled = true; }
232 bool IsInSelect() const { return bInSelect; }
233 void SetListHasDates(bool b) { mbListHasDates = b; }
234 bool HasDates() const { return mbListHasDates; }
237 // ListBox in einem FloatingWindow (pParent)
238 ScFilterListBox::ScFilterListBox( Window* pParent, ScGridWindow* pGrid,
239 SCCOL nNewCol, SCROW nNewRow, ScFilterBoxMode eNewMode ) :
240 ListBox( pParent, WB_AUTOHSCROLL ),
241 pGridWin( pGrid ),
242 nCol( nNewCol ),
243 nRow( nNewRow ),
244 bButtonDown( false ),
245 bInit( true ),
246 bCancelled( false ),
247 bInSelect( false ),
248 mbListHasDates(false),
249 nSel( 0 ),
250 eMode( eNewMode )
254 ScFilterListBox::~ScFilterListBox()
256 if (IsMouseCaptured())
257 ReleaseMouse();
260 void ScFilterListBox::EndInit()
262 sal_Int32 nPos = GetSelectEntryPos();
263 if ( LISTBOX_ENTRY_NOTFOUND == nPos )
264 nSel = 0;
265 else
266 nSel = nPos;
268 bInit = false;
271 void ScFilterListBox::LoseFocus()
273 #ifndef UNX
274 Hide();
275 #endif
278 bool ScFilterListBox::PreNotify( NotifyEvent& rNEvt )
280 bool nDone = false;
281 if ( rNEvt.GetType() == EVENT_KEYINPUT )
283 KeyEvent aKeyEvt = *rNEvt.GetKeyEvent();
284 KeyCode aCode = aKeyEvt.GetKeyCode();
285 if ( !aCode.GetModifier() ) // ohne alle Modifiers
287 sal_uInt16 nKey = aCode.GetCode();
288 if ( nKey == KEY_RETURN )
290 SelectHdl(); // auswaehlen
291 nDone = true;
293 else if ( nKey == KEY_ESCAPE )
295 pGridWin->ClickExtern(); // loescht die List-Box !!!
296 nDone = true;
301 return nDone || ListBox::PreNotify( rNEvt );
304 void ScFilterListBox::Select()
306 ListBox::Select();
307 SelectHdl();
310 void ScFilterListBox::SelectHdl()
312 if ( !IsTravelSelect() && !bInit && !bCancelled )
314 sal_Int32 nPos = GetSelectEntryPos();
315 if ( LISTBOX_ENTRY_NOTFOUND != nPos )
317 nSel = nPos;
318 if (!bButtonDown)
320 // #i81298# set bInSelect flag, so the box isn't deleted from modifications within FilterSelect
321 bInSelect = true;
322 pGridWin->FilterSelect( nSel );
323 bInSelect = false;
329 // use a System floating window for the above filter listbox
330 class ScFilterFloatingWindow : public FloatingWindow
332 public:
333 ScFilterFloatingWindow( Window* pParent, WinBits nStyle = WB_STDFLOATWIN );
334 virtual ~ScFilterFloatingWindow();
335 // required for System FloatingWindows that will not process KeyInput by themselves
336 virtual Window* GetPreferredKeyInputWindow() SAL_OVERRIDE;
339 ScFilterFloatingWindow::ScFilterFloatingWindow( Window* pParent, WinBits nStyle ) :
340 FloatingWindow( pParent, nStyle|WB_SYSTEMWINDOW ) // make it a system floater
343 ScFilterFloatingWindow::~ScFilterFloatingWindow()
345 EndPopupMode();
348 Window* ScFilterFloatingWindow::GetPreferredKeyInputWindow()
350 // redirect keyinput in the child window
351 return GetWindow(WINDOW_FIRSTCHILD) ? GetWindow(WINDOW_FIRSTCHILD)->GetPreferredKeyInputWindow() : NULL; // will be the FilterBox
354 static bool lcl_IsEditableMatrix( ScDocument* pDoc, const ScRange& rRange )
356 // wenn es ein editierbarer Bereich ist, und rechts unten eine Matrix-Zelle
357 // mit Origin links oben liegt, enthaelt der Bereich genau die Matrix.
358 //! Direkt die MatrixEdges Funktionen von der Column herausreichen ???
360 if ( !pDoc->IsBlockEditable( rRange.aStart.Tab(), rRange.aStart.Col(),rRange.aStart.Row(),
361 rRange.aEnd.Col(),rRange.aEnd.Row() ) )
362 return false;
364 ScRefCellValue aCell;
365 aCell.assign(*pDoc, rRange.aEnd);
366 ScAddress aPos;
367 return (aCell.meType == CELLTYPE_FORMULA && aCell.mpFormula->GetMatrixOrigin(aPos) && aPos == rRange.aStart);
370 static void lcl_UnLockComment( ScDrawView* pView, const Point& rPos, ScViewData* pViewData )
372 if (!pView || !pViewData)
373 return;
375 ScDocument& rDoc = *pViewData->GetDocument();
376 ScAddress aCellPos( pViewData->GetCurX(), pViewData->GetCurY(), pViewData->GetTabNo() );
377 ScPostIt* pNote = rDoc.GetNote( aCellPos );
378 SdrObject* pObj = pNote ? pNote->GetCaption() : 0;
379 if( pObj && pObj->GetLogicRect().IsInside( rPos ) && ScDrawLayer::IsNoteCaption( pObj ) )
381 const ScProtectionAttr* pProtAttr = static_cast< const ScProtectionAttr* > (rDoc.GetAttr( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab(), ATTR_PROTECTION ) );
382 bool bProtectAttr = pProtAttr->GetProtection() || pProtAttr->GetHideCell() ;
383 bool bProtectDoc = rDoc.IsTabProtected( aCellPos.Tab() ) || pViewData->GetSfxDocShell()->IsReadOnly() ;
384 // unlock internal layer (if not protected), will be relocked in ScDrawView::MarkListHasChanged()
385 pView->LockInternalLayer( bProtectDoc && bProtectAttr );
389 static bool lcl_GetHyperlinkCell(
390 ScDocument* pDoc, SCCOL& rPosX, SCROW& rPosY, SCTAB nTab, ScRefCellValue& rCell, OUString& rURL )
392 bool bFound = false;
395 ScAddress aPos(rPosX, rPosY, nTab);
396 rCell.assign(*pDoc, aPos);
397 if (rCell.isEmpty())
399 if ( rPosX <= 0 )
400 return false; // alles leer bis links
401 else
402 --rPosX; // weitersuchen
404 else
406 const ScPatternAttr* pPattern = pDoc->GetPattern(aPos);
407 if ( !((SfxStringItem&)pPattern->GetItem(ATTR_HYPERLINK)).GetValue().isEmpty() )
409 rURL = ((SfxStringItem&)pPattern->GetItem(ATTR_HYPERLINK)).GetValue();
410 bFound = true;
412 else if (rCell.meType == CELLTYPE_EDIT)
413 bFound = true;
414 else if (rCell.meType == CELLTYPE_FORMULA && rCell.mpFormula->IsHyperLinkCell())
415 bFound = true;
416 else
417 return false; // andere Zelle
420 while ( !bFound );
422 return bFound;
426 // WB_DIALOGCONTROL noetig fuer UNO-Controls
427 ScGridWindow::ScGridWindow( Window* pParent, ScViewData* pData, ScSplitPos eWhichPos )
428 : Window( pParent, WB_CLIPCHILDREN | WB_DIALOGCONTROL ),
429 DropTargetHelper( this ),
430 DragSourceHelper( this ),
431 mpOOCursors( NULL ),
432 mpOOSelection( NULL ),
433 mpOOSelectionBorder( NULL ),
434 mpOOAutoFill( NULL ),
435 mpOODragRect( NULL ),
436 mpOOHeader( NULL ),
437 mpOOShrink( NULL ),
438 mpAutoFillRect(static_cast<Rectangle*>(NULL)),
439 pViewData( pData ),
440 eWhich( eWhichPos ),
441 pNoteMarker( NULL ),
442 pFilterBox( NULL ),
443 pFilterFloat( NULL ),
444 mpAutoFilterPopup(NULL),
445 mpDPFieldPopup(NULL),
446 mpFilterButton(NULL),
447 nCursorHideCount( 0 ),
448 nButtonDown( 0 ),
449 nMouseStatus( SC_GM_NONE ),
450 nNestedButtonState( SC_NESTEDBUTTON_NONE ),
451 nDPField( 0 ),
452 pDragDPObj( NULL ),
453 nRFIndex( 0 ),
454 nRFAddX( 0 ),
455 nRFAddY( 0 ),
456 nPagebreakMouse( SC_PD_NONE ),
457 nPagebreakBreak( 0 ),
458 nPagebreakPrev( 0 ),
459 nPageScript( 0 ),
460 nLastClickX( 0 ),
461 nLastClickY( 0 ),
462 nDragStartX( -1 ),
463 nDragStartY( -1 ),
464 nDragEndX( -1 ),
465 nDragEndY( -1 ),
466 meDragInsertMode( INS_NONE ),
467 nCurrentPointer( 0 ),
468 aComboButton( this ),
469 aCurMousePos( 0,0 ),
470 nPaintCount( 0 ),
471 aRFSelectedCorned( NONE ),
472 bEEMouse( false ),
473 bDPMouse( false ),
474 bRFMouse( false ),
475 bRFSize( false ),
476 bPagebreakDrawn( false ),
477 bDragRect( false ),
478 bIsInScroll( false ),
479 bIsInPaint( false ),
480 bNeedsRepaint( false ),
481 bAutoMarkVisible( false ),
482 bListValButton( false )
484 switch(eWhich)
486 case SC_SPLIT_TOPLEFT:
487 eHWhich = SC_SPLIT_LEFT;
488 eVWhich = SC_SPLIT_TOP;
489 break;
490 case SC_SPLIT_TOPRIGHT:
491 eHWhich = SC_SPLIT_RIGHT;
492 eVWhich = SC_SPLIT_TOP;
493 break;
494 case SC_SPLIT_BOTTOMLEFT:
495 eHWhich = SC_SPLIT_LEFT;
496 eVWhich = SC_SPLIT_BOTTOM;
497 break;
498 case SC_SPLIT_BOTTOMRIGHT:
499 eHWhich = SC_SPLIT_RIGHT;
500 eVWhich = SC_SPLIT_BOTTOM;
501 break;
502 default:
503 OSL_FAIL("GridWindow: falsche Position");
506 SetBackground();
508 SetMapMode(pViewData->GetLogicMode(eWhich));
509 EnableChildTransparentMode();
510 SetDialogControlFlags( WINDOW_DLGCTRL_RETURN | WINDOW_DLGCTRL_WANTFOCUS );
512 SetHelpId( HID_SC_WIN_GRIDWIN );
513 SetUniqueId( HID_SC_WIN_GRIDWIN );
515 SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
516 EnableRTL( false );
519 ScGridWindow::~ScGridWindow()
521 // #114409#
522 ImpDestroyOverlayObjects();
524 delete pFilterBox;
525 delete pFilterFloat;
526 delete pNoteMarker;
529 void ScGridWindow::Resize( const Size& )
531 // gar nix
534 void ScGridWindow::ClickExtern()
538 // #i81298# don't delete the filter box when called from its select handler
539 // (possible through row header size update)
540 // #i84277# when initializing the filter box, a Basic error can deactivate the view
541 if ( pFilterBox && ( pFilterBox->IsInSelect() || pFilterBox->IsInInit() ) )
543 break;
546 DELETEZ(pFilterBox);
547 DELETEZ(pFilterFloat);
549 while (false);
551 if (mpDPFieldPopup)
553 mpDPFieldPopup->close(false);
554 mpDPFieldPopup.reset();
558 IMPL_LINK_NOARG(ScGridWindow, PopupModeEndHdl)
560 if (pFilterBox)
561 pFilterBox->SetCancelled(); // nicht mehr auswaehlen
562 GrabFocus();
563 return 0;
566 IMPL_LINK( ScGridWindow, PopupSpellingHdl, SpellCallbackInfo*, pInfo )
568 if( pInfo->nCommand == SPELLCMD_STARTSPELLDLG )
569 pViewData->GetDispatcher().Execute( SID_SPELL_DIALOG, SFX_CALLMODE_ASYNCHRON );
570 return 0;
573 void ScGridWindow::ExecPageFieldSelect( SCCOL nCol, SCROW nRow, bool bHasSelection, const OUString& rStr )
575 //! gridwin2 ?
577 ScDocument* pDoc = pViewData->GetDocument();
578 SCTAB nTab = pViewData->GetTabNo();
579 ScDPObject* pDPObj = pDoc->GetDPAtCursor(nCol, nRow, nTab);
580 if ( pDPObj && nCol > 0 )
582 // look for the dimension header left of the drop-down arrow
583 sal_uInt16 nOrient = sheet::DataPilotFieldOrientation_HIDDEN;
584 long nField = pDPObj->GetHeaderDim( ScAddress( nCol-1, nRow, nTab ), nOrient );
585 if ( nField >= 0 && nOrient == sheet::DataPilotFieldOrientation_PAGE )
587 ScDPSaveData aSaveData( *pDPObj->GetSaveData() );
589 bool bIsDataLayout;
590 OUString aDimName = pDPObj->GetDimName( nField, bIsDataLayout );
591 if ( !bIsDataLayout )
593 ScDPSaveDimension* pDim = aSaveData.GetDimensionByName(aDimName);
595 if ( bHasSelection )
597 const OUString aName = rStr;
598 pDim->SetCurrentPage( &aName );
600 else
601 pDim->SetCurrentPage( NULL );
603 ScDPObject aNewObj( *pDPObj );
604 aNewObj.SetSaveData( aSaveData );
605 ScDBDocFunc aFunc( *pViewData->GetDocShell() );
606 aFunc.DataPilotUpdate( pDPObj, &aNewObj, true, false );
607 pViewData->GetView()->CursorPosChanged(); // shells may be switched
613 namespace {
615 struct AutoFilterData : public ScCheckListMenuWindow::ExtendedData
617 ScAddress maPos;
618 ScDBData* mpData;
621 class AutoFilterAction : public ScMenuFloatingWindow::Action
623 ScGridWindow* mpWindow;
624 ScGridWindow::AutoFilterMode meMode;
625 public:
626 AutoFilterAction(ScGridWindow* p, ScGridWindow::AutoFilterMode eMode) :
627 mpWindow(p), meMode(eMode) {}
628 virtual void execute() SAL_OVERRIDE
630 mpWindow->UpdateAutoFilterFromMenu(meMode);
634 class AutoFilterPopupEndAction : public ScMenuFloatingWindow::Action
636 ScGridWindow* mpWindow;
637 ScAddress maPos;
638 public:
639 AutoFilterPopupEndAction(ScGridWindow* p, const ScAddress& rPos) :
640 mpWindow(p), maPos(rPos) {}
641 virtual void execute() SAL_OVERRIDE
643 mpWindow->RefreshAutoFilterButton(maPos);
647 class AddItemToEntry : public std::unary_function<OUString, void>
649 ScQueryEntry::QueryItemsType& mrItems;
650 svl::SharedStringPool& mrPool;
651 public:
652 AddItemToEntry(ScQueryEntry::QueryItemsType& rItems, svl::SharedStringPool& rPool) :
653 mrItems(rItems), mrPool(rPool) {}
654 void operator() (const OUString& rSelected)
656 ScQueryEntry::Item aNew;
657 aNew.maString = mrPool.intern(rSelected);
658 aNew.meType = ScQueryEntry::ByString;
659 aNew.mfVal = 0.0;
660 mrItems.push_back(aNew);
664 class AddSelectedItemString : public std::unary_function<ScQueryEntry::Item, void>
666 boost::unordered_set<OUString, OUStringHash>& mrSet;
667 public:
668 AddSelectedItemString(boost::unordered_set<OUString, OUStringHash>& r) :
669 mrSet(r) {}
671 void operator() (const ScQueryEntry::Item& rItem)
673 mrSet.insert(rItem.maString.getString());
679 void ScGridWindow::LaunchAutoFilterMenu(SCCOL nCol, SCROW nRow)
681 SCTAB nTab = pViewData->GetTabNo();
682 ScDocument* pDoc = pViewData->GetDocument();
684 mpAutoFilterPopup.reset(new ScCheckListMenuWindow(this, pDoc));
685 mpAutoFilterPopup->setOKAction(new AutoFilterAction(this, Normal));
686 mpAutoFilterPopup->setPopupEndAction(
687 new AutoFilterPopupEndAction(this, ScAddress(nCol, nRow, nTab)));
688 std::auto_ptr<AutoFilterData> pData(new AutoFilterData);
689 pData->maPos = ScAddress(nCol, nRow, nTab);
691 Point aPos = pViewData->GetScrPos(nCol, nRow, eWhich);
692 long nSizeX = 0;
693 long nSizeY = 0;
694 pViewData->GetMergeSizePixel(nCol, nRow, nSizeX, nSizeY);
695 Rectangle aCellRect(OutputToScreenPixel(aPos), Size(nSizeX, nSizeY));
697 ScDBData* pDBData = pDoc->GetDBAtCursor(nCol, nRow, nTab);
698 if (!pDBData)
699 return;
701 pData->mpData = pDBData;
702 mpAutoFilterPopup->setExtendedData(pData.release());
704 ScQueryParam aParam;
705 pDBData->GetQueryParam(aParam);
706 ScQueryEntry* pEntry = aParam.FindEntryByField(nCol, false);
707 boost::unordered_set<OUString, OUStringHash> aSelected;
708 if (pEntry && pEntry->bDoQuery)
710 if (pEntry->eOp == SC_EQUAL)
712 ScQueryEntry::QueryItemsType& rItems = pEntry->GetQueryItems();
713 std::for_each(rItems.begin(), rItems.end(), AddSelectedItemString(aSelected));
717 // Populate the check box list.
718 bool bHasDates = false;
719 std::vector<ScTypedStrData> aStrings;
720 pDoc->GetFilterEntries(nCol, nRow, nTab, true, aStrings, bHasDates);
722 mpAutoFilterPopup->setMemberSize(aStrings.size());
723 std::vector<ScTypedStrData>::const_iterator it = aStrings.begin(), itEnd = aStrings.end();
724 for (; it != itEnd; ++it)
726 const OUString& aVal = it->GetString();
727 bool bSelected = true;
728 if (!aSelected.empty())
729 bSelected = aSelected.count(aVal) > 0;
730 if ( it->IsDate() )
731 mpAutoFilterPopup->addDateMember( aVal, it->GetValue(), bSelected );
732 else
733 mpAutoFilterPopup->addMember(aVal, bSelected);
735 mpAutoFilterPopup->initMembers();
737 // Populate the menu.
738 mpAutoFilterPopup->addMenuItem(
739 SC_STRLOAD(RID_POPUP_FILTER, STR_MENU_SORT_ASC),
740 true, new AutoFilterAction(this, SortAscending));
741 mpAutoFilterPopup->addMenuItem(
742 SC_STRLOAD(RID_POPUP_FILTER, STR_MENU_SORT_DESC),
743 true, new AutoFilterAction(this, SortDescending));
744 mpAutoFilterPopup->addSeparator();
745 mpAutoFilterPopup->addMenuItem(
746 SC_RESSTR(SCSTR_TOP10FILTER), true, new AutoFilterAction(this, Top10));
747 mpAutoFilterPopup->addMenuItem(
748 SC_RESSTR(SCSTR_FILTER_EMPTY), true, new AutoFilterAction(this, Empty));
749 mpAutoFilterPopup->addMenuItem(
750 SC_RESSTR(SCSTR_FILTER_NOTEMPTY), true, new AutoFilterAction(this, NonEmpty));
751 mpAutoFilterPopup->addSeparator();
752 mpAutoFilterPopup->addMenuItem(
753 SC_RESSTR(SCSTR_STDFILTER), true, new AutoFilterAction(this, Custom));
755 ScCheckListMenuWindow::Config aConfig;
756 aConfig.mbAllowEmptySet = false;
757 aConfig.mbRTL = pViewData->GetDocument()->IsLayoutRTL(pViewData->GetTabNo());
758 mpAutoFilterPopup->setConfig(aConfig);
759 mpAutoFilterPopup->launch(aCellRect);
762 void ScGridWindow::RefreshAutoFilterButton(const ScAddress& rPos)
764 if (mpFilterButton)
766 bool bFilterActive = IsAutoFilterActive(rPos.Col(), rPos.Row(), rPos.Tab());
767 mpFilterButton->setHasHiddenMember(bFilterActive);
768 mpFilterButton->setPopupPressed(false);
769 mpFilterButton->draw();
773 void ScGridWindow::UpdateAutoFilterFromMenu(AutoFilterMode eMode)
775 const AutoFilterData* pData =
776 static_cast<const AutoFilterData*>(mpAutoFilterPopup->getExtendedData());
778 if (!pData)
779 return;
781 const ScAddress& rPos = pData->maPos;
782 ScDBData* pDBData = pData->mpData;
783 if (!pDBData)
784 return;
786 ScDocument* pDoc = pViewData->GetDocument();
787 svl::SharedStringPool& rPool = pDoc->GetSharedStringPool();
788 switch (eMode)
790 case SortAscending:
791 case SortDescending:
793 SCTAB nTab = pViewData->GetTabNo();
794 SCCOL nCol = rPos.Col();
795 ScSortParam aSortParam;
796 pDBData->GetSortParam(aSortParam);
797 if (nCol < aSortParam.nCol1 || nCol > aSortParam.nCol2)
798 // out of bound
799 return;
801 bool bHasHeader = pDoc->HasColHeader(
802 aSortParam.nCol1, aSortParam.nRow1, aSortParam.nCol2, aSortParam.nRow2, nTab);
804 aSortParam.bHasHeader = bHasHeader;
805 aSortParam.bByRow = true;
806 aSortParam.bCaseSens = false;
807 aSortParam.bNaturalSort = false;
808 aSortParam.bIncludePattern = true;
809 aSortParam.bInplace = true;
810 aSortParam.maKeyState[0].bDoSort = true;
811 aSortParam.maKeyState[0].nField = nCol;
812 aSortParam.maKeyState[0].bAscending = (eMode == SortAscending);
814 for (size_t i = 1; i < aSortParam.GetSortKeyCount(); ++i)
815 aSortParam.maKeyState[i].bDoSort = false;
817 pViewData->GetViewShell()->UISort(aSortParam);
818 return;
820 default:
824 if (eMode == Custom)
826 ScRange aRange;
827 pDBData->GetArea(aRange);
828 pViewData->GetView()->MarkRange(aRange);
829 pViewData->GetView()->SetCursor(rPos.Col(), rPos.Row());
830 pViewData->GetDispatcher().Execute(SID_FILTER, SFX_CALLMODE_SLOT|SFX_CALLMODE_RECORD);
831 return;
834 ScQueryParam aParam;
835 pDBData->GetQueryParam(aParam);
837 if (eMode == Normal && mpAutoFilterPopup->isAllSelected())
839 // Remove this entry.
840 aParam.RemoveEntryByField(rPos.Col());
842 else
844 // Try to use the existing entry for the column (if one exists).
845 ScQueryEntry* pEntry = aParam.FindEntryByField(rPos.Col(), true);
847 if (!pEntry)
848 // Something went terribly wrong!
849 return;
851 pEntry->bDoQuery = true;
852 pEntry->nField = rPos.Col();
853 pEntry->eConnect = SC_AND;
855 switch (eMode)
857 case Normal:
859 pEntry->eOp = SC_EQUAL;
861 ScCheckListMenuWindow::ResultType aResult;
862 mpAutoFilterPopup->getResult(aResult);
863 std::vector<OUString> aSelected;
864 ScCheckListMenuWindow::ResultType::const_iterator itr = aResult.begin(), itrEnd = aResult.end();
865 for (; itr != itrEnd; ++itr)
867 if (itr->second)
868 aSelected.push_back(itr->first);
871 ScQueryEntry::QueryItemsType& rItems = pEntry->GetQueryItems();
872 rItems.clear();
873 std::for_each(aSelected.begin(), aSelected.end(), AddItemToEntry(rItems, rPool));
875 break;
876 case Top10:
877 pEntry->eOp = SC_TOPVAL;
878 pEntry->GetQueryItem().meType = ScQueryEntry::ByString;
879 pEntry->GetQueryItem().maString = rPool.intern("10");
880 break;
881 case Empty:
882 pEntry->SetQueryByEmpty();
883 break;
884 case NonEmpty:
885 pEntry->SetQueryByNonEmpty();
886 break;
887 default:
888 // We don't know how to handle this!
889 return;
893 pViewData->GetView()->Query(aParam, NULL, true);
894 pDBData->SetQueryParam(aParam);
897 namespace {
899 void getCellGeometry(Point& rScrPos, Size& rScrSize, const ScViewData* pViewData, SCCOL nCol, SCROW nRow, ScSplitPos eWhich)
901 // Get the screen position of the cell.
902 rScrPos = pViewData->GetScrPos(nCol, nRow, eWhich);
904 // Get the screen size of the cell.
905 long nSizeX, nSizeY;
906 pViewData->GetMergeSizePixel(nCol, nRow, nSizeX, nSizeY);
907 rScrSize = Size(nSizeX-1, nSizeY-1);
912 void ScGridWindow::LaunchPageFieldMenu( SCCOL nCol, SCROW nRow )
914 if (nCol == 0)
915 // We assume that the page field button is located in cell to the immediate left.
916 return;
918 SCTAB nTab = pViewData->GetTabNo();
919 ScDPObject* pDPObj = pViewData->GetDocument()->GetDPAtCursor(nCol, nRow, nTab);
920 if (!pDPObj)
921 return;
923 Point aScrPos;
924 Size aScrSize;
925 getCellGeometry(aScrPos, aScrSize, pViewData, nCol, nRow, eWhich);
926 DPLaunchFieldPopupMenu(OutputToScreenPixel(aScrPos), aScrSize, ScAddress(nCol-1, nRow, nTab), pDPObj);
929 void ScGridWindow::LaunchDPFieldMenu( SCCOL nCol, SCROW nRow )
931 SCTAB nTab = pViewData->GetTabNo();
932 ScDPObject* pDPObj = pViewData->GetDocument()->GetDPAtCursor(nCol, nRow, nTab);
933 if (!pDPObj)
934 return;
936 Point aScrPos;
937 Size aScrSize;
938 getCellGeometry(aScrPos, aScrSize, pViewData, nCol, nRow, eWhich);
939 DPLaunchFieldPopupMenu(OutputToScreenPixel(aScrPos), aScrSize, ScAddress(nCol, nRow, nTab), pDPObj);
942 void ScGridWindow::DoScenarioMenu( const ScRange& rScenRange )
944 delete pFilterBox;
945 delete pFilterFloat;
947 SCCOL nCol = rScenRange.aEnd.Col(); // Zelle unterhalb des Buttons
948 SCROW nRow = rScenRange.aStart.Row();
949 if (nRow == 0)
951 nRow = rScenRange.aEnd.Row() + 1; // Bereich ganz oben -> Button unterhalb
952 if (nRow>MAXROW) nRow = MAXROW;
953 //! Texthoehe addieren (wenn sie an der View gespeichert ist...)
956 ScDocument* pDoc = pViewData->GetDocument();
957 SCTAB nTab = pViewData->GetTabNo();
958 bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
960 long nSizeX = 0;
961 long nSizeY = 0;
962 long nHeight = 0;
963 pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
964 // The button height should not use the merged cell height, should still use single row height
965 nSizeY = pViewData->ToPixel(pDoc->GetRowHeight(nRow, nTab), pViewData->GetPPTY());
966 Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich );
967 if ( bLayoutRTL )
968 aPos.X() -= nSizeX;
969 Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) );
970 aCellRect.Top() -= nSizeY;
971 aCellRect.Bottom() -= nSizeY - 1;
972 // Die ListBox direkt unter der schwarzen Linie auf dem Zellgitter
973 // (wenn die Linie verdeckt wird, sieht es komisch aus...)
975 pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) ); // nicht resizable etc.
976 pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) );
977 pFilterBox = new ScFilterListBox( pFilterFloat, this, nCol, nRow, SC_FILTERBOX_SCENARIO );
978 if ( bLayoutRTL )
979 pFilterBox->EnableMirroring();
981 nSizeX += 1;
984 Font aOldFont = GetFont(); SetFont( pFilterBox->GetFont() );
985 MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL );
987 nHeight = GetTextHeight();
988 nHeight *= SC_FILTERLISTBOX_LINES;
990 SetMapMode( aOldMode );
991 SetFont( aOldFont );
994 // SetSize spaeter
996 // ParentSize Abfrage fehlt
997 Size aSize( nSizeX, nHeight );
998 pFilterBox->SetSizePixel( aSize );
999 pFilterBox->Show(); // Show muss vor SetUpdateMode kommen !!!
1000 pFilterBox->SetUpdateMode(false);
1002 // SetOutputSizePixel/StartPopupMode erst unten, wenn die Groesse feststeht
1004 // Listbox fuellen
1006 long nMaxText = 0;
1007 OUString aCurrent;
1008 OUString aTabName;
1009 SCTAB nTabCount = pDoc->GetTableCount();
1010 SCTAB nEntryCount = 0;
1011 for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
1013 if (pDoc->HasScenarioRange( i, rScenRange ))
1014 if (pDoc->GetName( i, aTabName ))
1016 pFilterBox->InsertEntry( aTabName );
1017 if (pDoc->IsActiveScenario(i))
1018 aCurrent = aTabName;
1019 long nTextWidth = pFilterBox->GetTextWidth( aTabName );
1020 if ( nTextWidth > nMaxText )
1021 nMaxText = nTextWidth;
1022 ++nEntryCount;
1025 if (nEntryCount > SC_FILTERLISTBOX_LINES)
1026 nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize();
1027 nMaxText += 4; // fuer Rand
1028 if ( nMaxText > 300 )
1029 nMaxText = 300; // auch nicht uebertreiben (Pixel)
1031 if (nMaxText > nSizeX) // Groesse auf benoetigte Groesse anpassen
1033 long nDiff = nMaxText - nSizeX;
1034 aSize = Size( nMaxText, nHeight );
1035 pFilterBox->SetSizePixel( aSize );
1036 pFilterFloat->SetOutputSizePixel( aSize );
1038 if ( !bLayoutRTL )
1040 // also move popup position
1041 long nNewX = aCellRect.Left() - nDiff;
1042 if ( nNewX < 0 )
1043 nNewX = 0;
1044 aCellRect.Left() = nNewX;
1048 pFilterFloat->SetOutputSizePixel( aSize );
1049 pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS );
1051 pFilterBox->SetUpdateMode(true);
1052 pFilterBox->GrabFocus();
1054 sal_Int32 nPos = LISTBOX_ENTRY_NOTFOUND;
1055 if (!aCurrent.isEmpty())
1057 nPos = pFilterBox->GetEntryPos(aCurrent);
1059 if (LISTBOX_ENTRY_NOTFOUND == nPos && pFilterBox->GetEntryCount() > 0 )
1060 nPos = 0;
1061 if (LISTBOX_ENTRY_NOTFOUND != nPos )
1062 pFilterBox->SelectEntryPos(nPos);
1064 pFilterBox->EndInit();
1066 // Szenario-Auswahl kommt aus MouseButtonDown:
1067 // der naechste MouseMove auf die Filterbox ist wie ein ButtonDown
1069 nMouseStatus = SC_GM_FILTER;
1070 CaptureMouse();
1073 void ScGridWindow::LaunchDataSelectMenu( SCCOL nCol, SCROW nRow, bool bDataSelect )
1075 delete pFilterBox;
1076 delete pFilterFloat;
1078 sal_uInt16 i;
1079 ScDocument* pDoc = pViewData->GetDocument();
1080 SCTAB nTab = pViewData->GetTabNo();
1081 bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1083 long nSizeX = 0;
1084 long nSizeY = 0;
1085 long nHeight = 0;
1086 pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY );
1087 Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich );
1088 if ( bLayoutRTL )
1089 aPos.X() -= nSizeX;
1091 Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) );
1093 aPos.X() -= 1;
1094 aPos.Y() += nSizeY - 1;
1096 pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) ); // nicht resizable etc.
1097 pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) );
1098 pFilterBox = new ScFilterListBox(
1099 pFilterFloat, this, nCol, nRow, bDataSelect ? SC_FILTERBOX_DATASELECT : SC_FILTERBOX_FILTER );
1100 // Fix for bug fdo#44925
1101 if (Application::GetSettings().GetLayoutRTL() != bLayoutRTL)
1102 pFilterBox->EnableMirroring();
1104 nSizeX += 1;
1107 Font aOldFont = GetFont(); SetFont( pFilterBox->GetFont() );
1108 MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL );
1110 nHeight = GetTextHeight();
1111 nHeight *= SC_FILTERLISTBOX_LINES;
1113 SetMapMode( aOldMode );
1114 SetFont( aOldFont );
1117 // SetSize spaeter
1119 bool bEmpty = false;
1120 std::vector<ScTypedStrData> aStrings; // case sensitive
1121 if ( bDataSelect ) // Auswahl-Liste
1123 // Liste fuellen
1124 pDoc->GetDataEntries(nCol, nRow, nTab, true, aStrings);
1125 if (aStrings.empty())
1126 bEmpty = true;
1128 else // AutoFilter
1130 //! wird der Titel ueberhaupt ausgewertet ???
1131 OUString aString = pDoc->GetString(nCol, nRow, nTab);
1132 pFilterBox->SetText( aString );
1134 long nMaxText = 0;
1136 // default entries
1137 static const sal_uInt16 nDefIDs[] = { SCSTR_TOP10FILTER, SCSTR_STDFILTER, SCSTR_FILTER_EMPTY, SCSTR_FILTER_NOTEMPTY };
1138 const size_t nDefCount = SAL_N_ELEMENTS(nDefIDs);
1139 for (i=0; i<nDefCount; i++)
1141 OUString aEntry( (ScResId) nDefIDs[i] );
1142 pFilterBox->InsertEntry( aEntry );
1143 long nTextWidth = pFilterBox->GetTextWidth( aEntry );
1144 if ( nTextWidth > nMaxText )
1145 nMaxText = nTextWidth;
1147 pFilterBox->SetSeparatorPos( nDefCount - 1 );
1149 // get list entries
1150 bool bHasDates = false;
1151 pDoc->GetFilterEntries( nCol, nRow, nTab, true, aStrings, bHasDates);
1152 pFilterBox->SetListHasDates(bHasDates);
1154 // check widths of numerical entries (string entries are not included)
1155 // so all numbers are completely visible
1156 std::vector<ScTypedStrData>::const_iterator it = aStrings.begin(), itEnd = aStrings.end();
1157 for (; it != itEnd; ++it)
1159 if (!it->IsStrData()) // only numerical entries
1161 long nTextWidth = pFilterBox->GetTextWidth(it->GetString());
1162 if ( nTextWidth > nMaxText )
1163 nMaxText = nTextWidth;
1167 // add scrollbar width if needed (string entries are counted here)
1168 // (scrollbar is shown if the box is exactly full?)
1169 if (aStrings.size() + nDefCount >= SC_FILTERLISTBOX_LINES)
1170 nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize();
1172 nMaxText += 4; // for borders
1174 if ( nMaxText > nSizeX )
1175 nSizeX = nMaxText; // just modify width - starting position is unchanged
1178 if (!bEmpty)
1180 // Position und Groesse an Fenster anpassen
1181 //! vorher Abfrage, ob die Eintraege hineinpassen (Breite)
1183 Size aParentSize = GetParent()->GetOutputSizePixel();
1184 Size aSize( nSizeX, nHeight );
1186 if ( aSize.Height() > aParentSize.Height() )
1187 aSize.Height() = aParentSize.Height();
1188 if ( aPos.Y() + aSize.Height() > aParentSize.Height() )
1189 aPos.Y() = aParentSize.Height() - aSize.Height();
1191 pFilterBox->SetSizePixel( aSize );
1192 pFilterBox->Show(); // Show muss vor SetUpdateMode kommen !!!
1193 pFilterBox->SetUpdateMode(false);
1195 pFilterFloat->SetOutputSizePixel( aSize );
1196 pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS);
1198 // Listbox fuellen
1199 bool bWait = aStrings.size() > 100;
1201 if (bWait)
1202 EnterWait();
1204 std::vector<ScTypedStrData>::const_iterator it = aStrings.begin(), itEnd = aStrings.end();
1205 for (; it != itEnd; ++it)
1206 pFilterBox->InsertEntry(it->GetString());
1208 if (bWait)
1209 LeaveWait();
1211 pFilterBox->SetUpdateMode(true);
1214 sal_Int32 nSelPos = LISTBOX_ENTRY_NOTFOUND;
1216 if (!bDataSelect) // AutoFilter: aktiven Eintrag selektieren
1218 ScDBData* pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab );
1219 if (pDBData)
1221 ScQueryParam aParam;
1222 pDBData->GetQueryParam( aParam ); // kann nur MAXQUERY Eintraege ergeben
1224 bool bValid = true;
1225 SCSIZE nCount = aParam.GetEntryCount();
1226 for (SCSIZE j = 0; j < nCount && bValid; ++j) // bisherige Filter-Einstellungen
1227 if (aParam.GetEntry(j).bDoQuery)
1229 //! Abfrage mit DrawButtons zusammenfassen!
1231 ScQueryEntry& rEntry = aParam.GetEntry(j);
1232 if (j>0)
1233 if (rEntry.eConnect != SC_AND)
1234 bValid = false;
1235 if (rEntry.nField == nCol)
1237 OUString aQueryStr = rEntry.GetQueryItem().maString.getString();
1238 if (rEntry.eOp == SC_EQUAL)
1240 if (!aQueryStr.isEmpty())
1242 nSelPos = pFilterBox->GetEntryPos(aQueryStr);
1245 else if ( rEntry.eOp == SC_TOPVAL && aQueryStr == "10" )
1246 nSelPos = SC_AUTOFILTER_TOP10;
1247 else
1248 nSelPos = SC_AUTOFILTER_CUSTOM;
1252 if (!bValid)
1253 nSelPos = SC_AUTOFILTER_CUSTOM;
1256 else
1259 sal_uLong nIndex = ((SfxUInt32Item*)pDoc->GetAttr(
1260 nCol, nRow, nTab, ATTR_VALIDDATA ))->GetValue();
1261 if ( nIndex )
1263 const ScValidationData* pData = pDoc->GetValidationEntry( nIndex );
1264 if (pData)
1266 boost::scoped_ptr<ScTypedStrData> pNew;
1267 OUString aDocStr = pDoc->GetString(nCol, nRow, nTab);
1268 if ( pDoc->HasValueData( nCol, nRow, nTab ) )
1270 double fVal = pDoc->GetValue(ScAddress(nCol, nRow, nTab));
1271 pNew.reset(new ScTypedStrData(aDocStr, fVal, ScTypedStrData::Value));
1273 else
1274 pNew.reset(new ScTypedStrData(aDocStr, 0.0, ScTypedStrData::Standard));
1276 bool bSortList = ( pData->GetListType() == ValidListType::SORTEDASCENDING);
1277 if ( bSortList )
1279 std::vector<ScTypedStrData>::const_iterator itBeg = aStrings.begin(), itEnd = aStrings.end();
1280 std::vector<ScTypedStrData>::const_iterator it =
1281 std::find_if(itBeg, itEnd, FindTypedStrData(*pNew, true));
1282 if (it != itEnd)
1283 // Found!
1284 nSelPos = std::distance(itBeg, it);
1286 else
1288 ScTypedStrData::EqualCaseSensitive aHdl;
1289 std::vector<ScTypedStrData>::const_iterator itBeg = aStrings.begin(), itEnd = aStrings.end();
1290 std::vector<ScTypedStrData>::const_iterator it = itBeg;
1291 for (; it != itEnd && LISTBOX_ENTRY_NOTFOUND == nSelPos; ++it)
1293 if (aHdl(*it, *pNew))
1294 nSelPos = std::distance(itBeg, it);
1301 // neu (309): irgendwas muss immer selektiert sein:
1302 if ( LISTBOX_ENTRY_NOTFOUND == nSelPos && pFilterBox->GetEntryCount() > 0 && !bDataSelect)
1303 nSelPos = 0;
1305 // keine leere Auswahl-Liste anzeigen:
1307 if ( bEmpty )
1309 DELETEZ(pFilterBox); // war nix
1310 DELETEZ(pFilterFloat);
1312 else
1314 pFilterBox->GrabFocus();
1316 // Select erst nach GrabFocus, damit das Focus-Rechteck richtig landet
1317 if ( LISTBOX_ENTRY_NOTFOUND != nSelPos )
1318 pFilterBox->SelectEntryPos( nSelPos );
1319 else
1321 if (bDataSelect)
1322 pFilterBox->SetNoSelection();
1325 pFilterBox->EndInit();
1327 if (!bDataSelect)
1329 // AutoFilter (aus MouseButtonDown):
1330 // der naechste MouseMove auf die Filterbox ist wie ein ButtonDown
1332 nMouseStatus = SC_GM_FILTER;
1333 CaptureMouse();
1338 void ScGridWindow::FilterSelect( sal_uLong nSel )
1340 OUString aString = pFilterBox->GetEntry( static_cast< sal_Int32 >( nSel ) );
1342 SCCOL nCol = pFilterBox->GetCol();
1343 SCROW nRow = pFilterBox->GetRow();
1344 switch ( pFilterBox->GetMode() )
1346 case SC_FILTERBOX_DATASELECT:
1347 ExecDataSelect( nCol, nRow, aString );
1348 break;
1349 case SC_FILTERBOX_FILTER:
1350 ExecFilter( nSel, nCol, nRow, aString, pFilterBox->HasDates() );
1351 break;
1352 case SC_FILTERBOX_SCENARIO:
1353 pViewData->GetView()->UseScenario( aString );
1354 break;
1355 case SC_FILTERBOX_PAGEFIELD:
1356 // first entry is "all"
1357 ExecPageFieldSelect( nCol, nRow, (nSel != 0), aString );
1358 break;
1361 if (pFilterFloat)
1362 pFilterFloat->EndPopupMode();
1364 GrabFocus(); // unter OS/2 stimmt der Focus sonst nicht
1367 void ScGridWindow::ExecDataSelect( SCCOL nCol, SCROW nRow, const OUString& rStr )
1369 if ( !rStr.isEmpty() )
1371 SCTAB nTab = pViewData->GetTabNo();
1372 ScViewFunc* pView = pViewData->GetView();
1373 pView->EnterData( nCol, nRow, nTab, rStr );
1375 // #i52307# CellContentChanged is not in EnterData so it isn't called twice
1376 // if the cursor is moved afterwards.
1377 pView->CellContentChanged();
1381 void ScGridWindow::ExecFilter( sal_uLong nSel,
1382 SCCOL nCol, SCROW nRow,
1383 const OUString& aValue, bool bCheckForDates )
1385 SCTAB nTab = pViewData->GetTabNo();
1386 ScDocument* pDoc = pViewData->GetDocument();
1387 svl::SharedStringPool& rPool = pDoc->GetSharedStringPool();
1389 ScDBData* pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab );
1390 if (pDBData)
1392 ScQueryParam aParam;
1393 pDBData->GetQueryParam( aParam ); // kann nur MAXQUERY Eintraege ergeben
1395 if (SC_AUTOFILTER_CUSTOM == nSel)
1397 SCTAB nAreaTab;
1398 SCCOL nStartCol;
1399 SCROW nStartRow;
1400 SCCOL nEndCol;
1401 SCROW nEndRow;
1402 pDBData->GetArea( nAreaTab, nStartCol,nStartRow,nEndCol,nEndRow );
1403 pViewData->GetView()->MarkRange( ScRange( nStartCol,nStartRow,nAreaTab,nEndCol,nEndRow,nAreaTab));
1404 pViewData->GetView()->SetCursor(nCol,nRow); //! auch ueber Slot ??
1405 pViewData->GetDispatcher().Execute( SID_FILTER, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD );
1407 else
1409 bool bDeleteOld = false;
1410 SCSIZE nQueryPos = 0;
1411 bool bFound = false;
1412 if (!aParam.bInplace)
1413 bDeleteOld = true;
1414 if (aParam.bRegExp)
1415 bDeleteOld = true;
1416 SCSIZE nCount = aParam.GetEntryCount();
1417 for (SCSIZE i = 0; i < nCount && !bDeleteOld; ++i) // bisherige Filter-Einstellungen
1418 if (aParam.GetEntry(i).bDoQuery)
1420 //! Abfrage mit DrawButtons zusammenfassen!
1422 ScQueryEntry& rEntry = aParam.GetEntry(i);
1423 if (i>0)
1424 if (rEntry.eConnect != SC_AND)
1425 bDeleteOld = true;
1427 if (rEntry.nField == nCol)
1429 if (bFound) // diese Spalte zweimal?
1430 bDeleteOld = true;
1431 nQueryPos = i;
1432 bFound = true;
1434 if (!bFound)
1435 nQueryPos = i + 1;
1438 if (bDeleteOld)
1440 SCSIZE nEC = aParam.GetEntryCount();
1441 for (SCSIZE i=0; i<nEC; i++)
1442 aParam.GetEntry(i).Clear();
1443 nQueryPos = 0;
1444 aParam.bInplace = true;
1445 aParam.bRegExp = false;
1448 if ( nQueryPos < nCount || SC_AUTOFILTER_ALL == nSel ) // loeschen geht immer
1450 if (nSel)
1452 ScQueryEntry& rNewEntry = aParam.GetEntry(nQueryPos);
1453 ScQueryEntry::Item& rItem = rNewEntry.GetQueryItem();
1454 rNewEntry.bDoQuery = true;
1455 rNewEntry.nField = nCol;
1456 rItem.meType = bCheckForDates ? ScQueryEntry::ByDate : ScQueryEntry::ByString;
1458 if ( nSel == SC_AUTOFILTER_TOP10 )
1460 rNewEntry.eOp = SC_TOPVAL;
1461 rItem.maString = rPool.intern("10");
1463 else if (nSel == SC_AUTOFILTER_EMPTY)
1465 rNewEntry.SetQueryByEmpty();
1467 else if (nSel == SC_AUTOFILTER_NOTEMPTY)
1469 rNewEntry.SetQueryByNonEmpty();
1471 else
1473 rNewEntry.eOp = SC_EQUAL;
1474 rItem.maString = rPool.intern(aValue);
1476 if (nQueryPos > 0)
1477 rNewEntry.eConnect = SC_AND;
1479 else
1481 if (bFound)
1482 aParam.RemoveEntryByField(nCol);
1485 // end edit mode - like in ScCellShell::ExecuteDB
1486 if ( pViewData->HasEditView( pViewData->GetActivePart() ) )
1488 SC_MOD()->InputEnterHandler();
1489 pViewData->GetViewShell()->UpdateInputHandler();
1492 pViewData->GetView()->Query( aParam, NULL, true );
1493 pDBData->SetQueryParam( aParam ); // speichern
1495 else // "Zuviele Bedingungen"
1496 pViewData->GetView()->ErrorMessage( STR_FILTER_TOOMANY );
1499 else
1501 OSL_FAIL("Wo ist der Datenbankbereich?");
1505 void ScGridWindow::SetPointer( const Pointer& rPointer )
1507 nCurrentPointer = 0;
1508 Window::SetPointer( rPointer );
1511 void ScGridWindow::MoveMouseStatus( ScGridWindow& rDestWin )
1513 if (nButtonDown)
1515 rDestWin.nButtonDown = nButtonDown;
1516 rDestWin.nMouseStatus = nMouseStatus;
1519 if (bRFMouse)
1521 rDestWin.bRFMouse = bRFMouse;
1522 rDestWin.bRFSize = bRFSize;
1523 rDestWin.nRFIndex = nRFIndex;
1524 rDestWin.nRFAddX = nRFAddX;
1525 rDestWin.nRFAddY = nRFAddY;
1526 bRFMouse = false;
1529 if (nPagebreakMouse)
1531 rDestWin.nPagebreakMouse = nPagebreakMouse;
1532 rDestWin.nPagebreakBreak = nPagebreakBreak;
1533 rDestWin.nPagebreakPrev = nPagebreakPrev;
1534 rDestWin.aPagebreakSource = aPagebreakSource;
1535 rDestWin.aPagebreakDrag = aPagebreakDrag;
1536 nPagebreakMouse = SC_PD_NONE;
1540 bool ScGridWindow::TestMouse( const MouseEvent& rMEvt, bool bAction )
1542 // MouseEvent buttons must only be checked if bAction==TRUE
1543 // to allow changing the mouse pointer in MouseMove,
1544 // but not start AutoFill with right button (#74229#).
1545 // with bAction==sal_True, SetFillMode / SetDragMode is called
1547 if ( bAction && !rMEvt.IsLeft() )
1548 return false;
1550 bool bNewPointer = false;
1552 SfxInPlaceClient* pClient = pViewData->GetViewShell()->GetIPClient();
1553 bool bOleActive = ( pClient && pClient->IsObjectInPlaceActive() );
1555 if ( pViewData->IsActive() && !bOleActive )
1557 ScDocument* pDoc = pViewData->GetDocument();
1558 SCTAB nTab = pViewData->GetTabNo();
1559 bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
1561 // Auto-Fill
1563 ScRange aMarkRange;
1564 if (pViewData->GetSimpleArea( aMarkRange ) == SC_MARK_SIMPLE)
1566 if (aMarkRange.aStart.Tab() == pViewData->GetTabNo() && mpAutoFillRect)
1568 Point aMousePos = rMEvt.GetPosPixel();
1569 if (mpAutoFillRect->IsInside(aMousePos))
1571 SetPointer( Pointer( POINTER_CROSS ) ); //! dickeres Kreuz ?
1572 if (bAction)
1574 SCCOL nX = aMarkRange.aEnd.Col();
1575 SCROW nY = aMarkRange.aEnd.Row();
1577 if ( lcl_IsEditableMatrix( pViewData->GetDocument(), aMarkRange ) )
1578 pViewData->SetDragMode(
1579 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nX, nY, SC_FILL_MATRIX );
1580 else
1581 pViewData->SetFillMode(
1582 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nX, nY );
1584 // The simple selection must also be recognized when dragging,
1585 // where the Marking flag is set and MarkToSimple won't work anymore.
1586 pViewData->GetMarkData().MarkToSimple();
1588 bNewPointer = true;
1593 // Embedded-Rechteck
1595 if (pDoc->IsEmbedded())
1597 ScRange aRange;
1598 pDoc->GetEmbedded( aRange );
1599 if ( pViewData->GetTabNo() == aRange.aStart.Tab() )
1601 Point aStartPos = pViewData->GetScrPos( aRange.aStart.Col(), aRange.aStart.Row(), eWhich );
1602 Point aEndPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aEnd.Row()+1, eWhich );
1603 Point aMousePos = rMEvt.GetPosPixel();
1604 if ( bLayoutRTL )
1606 aStartPos.X() += 2;
1607 aEndPos.X() += 2;
1609 bool bTop = ( aMousePos.X() >= aStartPos.X()-3 && aMousePos.X() <= aStartPos.X()+1 &&
1610 aMousePos.Y() >= aStartPos.Y()-3 && aMousePos.Y() <= aStartPos.Y()+1 );
1611 bool bBottom = ( aMousePos.X() >= aEndPos.X()-3 && aMousePos.X() <= aEndPos.X()+1 &&
1612 aMousePos.Y() >= aEndPos.Y()-3 && aMousePos.Y() <= aEndPos.Y()+1 );
1613 if ( bTop || bBottom )
1615 SetPointer( Pointer( POINTER_CROSS ) );
1616 if (bAction)
1618 sal_uInt8 nMode = bTop ? SC_FILL_EMBED_LT : SC_FILL_EMBED_RB;
1619 pViewData->SetDragMode(
1620 aRange.aStart.Col(), aRange.aStart.Row(),
1621 aRange.aEnd.Col(), aRange.aEnd.Row(), nMode );
1623 bNewPointer = true;
1629 if (!bNewPointer && bAction)
1631 pViewData->ResetFillMode();
1634 return bNewPointer;
1637 void ScGridWindow::MouseButtonDown( const MouseEvent& rMEvt )
1639 if(!maChildWindows.empty())
1641 const Point& rPos = rMEvt.GetPosPixel();
1642 for(boost::ptr_vector<Window>::iterator itr = maChildWindows.begin(),
1643 itrEnd = maChildWindows.end(); itr != itrEnd; ++itr)
1645 if(!itr->IsVisible())
1646 continue;
1648 Point aPoint = itr->GetPosPixel();
1649 Size aSize = itr->GetSizePixel();
1651 if(rPos.X() >= aPoint.X() && rPos.X() <= (aPoint.X() + aSize.Width())
1652 && rPos.Y() >= aPoint.Y() && rPos.Y() <= (aPoint.Y() + aSize.Height()))
1654 // we found a mouse event for the child window
1655 // we need to recalculate the position based on the child window
1657 Point aNewPos = rPos - aPoint;
1658 sal_uInt16 nClicks = rMEvt.GetClicks();
1659 sal_uInt16 nMode = rMEvt.GetMode();
1660 sal_uInt16 nButtons = rMEvt.GetButtons();
1661 sal_uInt16 nModifier = rMEvt.GetModifier();
1663 MouseEvent aEvent(aNewPos, nClicks, nMode, nButtons, nModifier);
1664 itr->MouseButtonDown(aEvent);
1665 return;
1669 nNestedButtonState = SC_NESTEDBUTTON_DOWN;
1671 MouseEventState aState;
1672 HandleMouseButtonDown(rMEvt, aState);
1673 if (aState.mbActivatePart)
1674 pViewData->GetView()->ActivatePart(eWhich);
1676 if ( nNestedButtonState == SC_NESTEDBUTTON_UP )
1678 // #i41690# If an object is deactivated from MouseButtonDown, it might reschedule,
1679 // so MouseButtonUp comes before the MouseButtonDown call is finished. In this case,
1680 // simulate another MouseButtonUp call, so the selection state is consistent.
1682 nButtonDown = rMEvt.GetButtons();
1683 FakeButtonUp();
1685 if ( IsTracking() )
1686 EndTracking(); // normally done in VCL as part of MouseButtonUp handling
1688 nNestedButtonState = SC_NESTEDBUTTON_NONE;
1691 void ScGridWindow::HandleMouseButtonDown( const MouseEvent& rMEvt, MouseEventState& rState )
1693 // We have to check if a context menu is shown and we have an UI
1694 // active inplace client. In that case we have to ignore the event.
1695 // Otherwise we would crash (context menu has been
1696 // opened by inplace client and we would deactivate the inplace client,
1697 // the contex menu is closed by VCL asynchronously which in the end
1698 // would work on deleted objects or the context menu has no parent anymore)
1699 SfxViewShell* pViewSh = pViewData->GetViewShell();
1700 SfxInPlaceClient* pClient = pViewSh->GetIPClient();
1701 if ( pClient &&
1702 pClient->IsObjectInPlaceActive() &&
1703 PopupMenu::IsInExecute() )
1704 return;
1706 aCurMousePos = rMEvt.GetPosPixel();
1708 // Filter-Popup beendet sich mit eigenem Mausklick, nicht erst beim Klick
1709 // in das GridWindow, darum ist die folgende Abfrage nicht mehr noetig:
1710 ClickExtern(); // loescht FilterBox, wenn vorhanden
1712 HideNoteMarker(); // Notiz-Anzeige
1714 bEEMouse = false;
1716 ScModule* pScMod = SC_MOD();
1717 if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
1718 return;
1720 pScActiveViewShell = pViewData->GetViewShell(); // falls auf Link geklickt wird
1721 nScClickMouseModifier = rMEvt.GetModifier(); // um Control-Klick immer zu erkennen
1723 bool bDetective = pViewData->GetViewShell()->IsAuditShell();
1724 bool bRefMode = pViewData->IsRefMode(); // Referenz angefangen
1725 bool bFormulaMode = pScMod->IsFormulaMode(); // naechster Klick -> Referenz
1726 bool bEditMode = pViewData->HasEditView(eWhich); // auch bei Mode==SC_INPUT_TYPE
1727 bool bDouble = (rMEvt.GetClicks() == 2);
1729 // DeactivateIP passiert nur noch bei MarkListHasChanged
1731 // im GrabFocus Aufruf kann eine Fehlermeldung hochkommen
1732 // (z.B. beim Umbenennen von Tabellen per Tab-Reiter)
1734 if ( !nButtonDown || !bDouble ) // single (first) click is always valid
1735 nButtonDown = rMEvt.GetButtons(); // set nButtonDown first, so StopMarking works
1737 if ( ( bEditMode && pViewData->GetActivePart() == eWhich ) || !bFormulaMode )
1738 GrabFocus();
1740 // #i31846# need to cancel a double click if the first click has set the "ignore" state,
1741 // but a single (first) click is always valid
1742 if ( nMouseStatus == SC_GM_IGNORE && bDouble )
1744 nButtonDown = 0;
1745 nMouseStatus = SC_GM_NONE;
1746 return;
1749 if ( bDetective ) // Detektiv-Fuell-Modus
1751 if ( rMEvt.IsLeft() && !rMEvt.GetModifier() )
1753 Point aPos = rMEvt.GetPosPixel();
1754 SCsCOL nPosX;
1755 SCsROW nPosY;
1756 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
1758 SfxInt16Item aPosXItem( SID_RANGE_COL, nPosX );
1759 SfxInt32Item aPosYItem( SID_RANGE_ROW, nPosY );
1760 pViewData->GetDispatcher().Execute( SID_FILL_SELECT, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD,
1761 &aPosXItem, &aPosYItem, (void*)0L );
1764 nButtonDown = 0;
1765 nMouseStatus = SC_GM_NONE;
1766 return;
1769 if (!bDouble)
1770 nMouseStatus = SC_GM_NONE;
1772 rState.mbActivatePart = !bFormulaMode; // Don't activate when in formula mode.
1774 if (bFormulaMode)
1776 ScViewSelectionEngine* pSelEng = pViewData->GetView()->GetSelEngine();
1777 pSelEng->SetWindow(this);
1778 pSelEng->SetWhich(eWhich);
1779 pSelEng->SetVisibleArea( Rectangle(Point(), GetOutputSizePixel()) );
1782 if (bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()))
1784 Point aPos = rMEvt.GetPosPixel();
1785 SCsCOL nPosX;
1786 SCsROW nPosY;
1787 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
1789 EditView* pEditView;
1790 SCCOL nEditCol;
1791 SCROW nEditRow;
1792 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
1793 SCCOL nEndCol = pViewData->GetEditEndCol();
1794 SCROW nEndRow = pViewData->GetEditEndRow();
1796 if ( nPosX >= (SCsCOL) nEditCol && nPosX <= (SCsCOL) nEndCol &&
1797 nPosY >= (SCsROW) nEditRow && nPosY <= (SCsROW) nEndRow )
1799 // beim Klick in die Tabellen-EditView immer den Focus umsetzen
1800 if (bFormulaMode) // sonst ist es oben schon passiert
1801 GrabFocus();
1803 pScMod->SetInputMode( SC_INPUT_TABLE );
1804 bEEMouse = true;
1805 bEditMode = pEditView->MouseButtonDown( rMEvt );
1806 return;
1810 if (pScMod->GetIsWaterCan())
1812 //! was is mit'm Mac ???
1813 if ( rMEvt.GetModifier() + rMEvt.GetButtons() == MOUSE_RIGHT )
1815 nMouseStatus = SC_GM_WATERUNDO;
1816 return;
1820 // Reihenfolge passend zum angezeigten Cursor:
1821 // RangeFinder, AutoFill, PageBreak, Drawing
1823 RfCorner rCorner = NONE;
1824 bool bFound = HitRangeFinder(rMEvt.GetPosPixel(), rCorner, &nRFIndex, &nRFAddX, &nRFAddY);
1825 bRFSize = (rCorner != NONE);
1826 aRFSelectedCorned = rCorner;
1828 if (bFound)
1830 bRFMouse = true; // die anderen Variablen sind oben initialisiert
1832 rState.mbActivatePart = true; // always activate ?
1833 StartTracking();
1834 return;
1837 bool bCrossPointer = TestMouse( rMEvt, true );
1838 if ( bCrossPointer )
1840 if ( bDouble )
1841 pViewData->GetView()->FillCrossDblClick();
1842 else
1843 pScMod->InputEnterHandler(); // Autofill etc.
1846 if ( !bCrossPointer )
1848 nPagebreakMouse = HitPageBreak( rMEvt.GetPosPixel(), &aPagebreakSource,
1849 &nPagebreakBreak, &nPagebreakPrev );
1850 if (nPagebreakMouse)
1852 bPagebreakDrawn = false;
1853 StartTracking();
1854 PagebreakMove( rMEvt, false );
1855 return;
1859 if (!bFormulaMode && !bEditMode && rMEvt.IsLeft())
1861 if ( !bCrossPointer && DrawMouseButtonDown(rMEvt) )
1863 return;
1866 pViewData->GetViewShell()->SetDrawShell( false ); // kein Draw-Objekt selektiert
1868 // TestMouse schon oben passiert
1871 Point aPos = rMEvt.GetPosPixel();
1872 SCsCOL nPosX;
1873 SCsROW nPosY;
1874 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
1875 SCTAB nTab = pViewData->GetTabNo();
1876 ScDocument* pDoc = pViewData->GetDocument();
1878 // Auto filter / pivot table / data select popup. This shouldn't activate the part.
1880 if ( !bDouble && !bFormulaMode && rMEvt.IsLeft() )
1882 SCsCOL nRealPosX;
1883 SCsROW nRealPosY;
1884 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nRealPosX, nRealPosY, false );//the real row/col
1885 ScMergeFlagAttr* pRealPosAttr = (ScMergeFlagAttr*)
1886 pDoc->GetAttr( nRealPosX, nRealPosY, nTab, ATTR_MERGE_FLAG );
1887 ScMergeFlagAttr* pAttr = (ScMergeFlagAttr*)
1888 pDoc->GetAttr( nPosX, nPosY, nTab, ATTR_MERGE_FLAG );
1889 if( pRealPosAttr->HasAutoFilter() )
1891 SC_MOD()->InputEnterHandler();
1892 if (DoAutoFilterButton( nRealPosX, nRealPosY, rMEvt))
1893 return;
1895 if (pAttr->HasAutoFilter())
1897 if (DoAutoFilterButton(nPosX, nPosY, rMEvt))
1899 rState.mbActivatePart = false;
1900 return;
1904 if (pAttr->HasPivotButton() || pAttr->HasPivotPopupButton())
1906 DoPushPivotButton(nPosX, nPosY, rMEvt, pAttr->HasPivotButton(), pAttr->HasPivotPopupButton());
1907 rState.mbActivatePart = false;
1908 return;
1911 // List Validity drop-down button
1913 if ( bListValButton )
1915 Rectangle aButtonRect = GetListValButtonRect( aListValPos );
1916 if ( aButtonRect.IsInside( aPos ) )
1918 LaunchDataSelectMenu( aListValPos.Col(), aListValPos.Row(), true );
1920 nMouseStatus = SC_GM_FILTER; // not set in DoAutoFilterMenue for bDataSelect
1921 CaptureMouse();
1922 rState.mbActivatePart = false;
1923 return;
1929 // scenario selection
1932 ScRange aScenRange;
1933 if ( rMEvt.IsLeft() && HasScenarioButton( aPos, aScenRange ) )
1935 DoScenarioMenu( aScenRange );
1936 return;
1940 // Doppelklick angefangen ?
1943 // StopMarking kann aus DrawMouseButtonDown gerufen werden
1945 if ( nMouseStatus != SC_GM_IGNORE && !bRefMode )
1947 if ( bDouble && !bCrossPointer )
1949 if (nMouseStatus == SC_GM_TABDOWN)
1950 nMouseStatus = SC_GM_DBLDOWN;
1952 else
1953 nMouseStatus = SC_GM_TABDOWN;
1957 // Links in Edit-Zellen
1960 bool bAlt = rMEvt.IsMod2();
1961 if ( !bAlt && rMEvt.IsLeft() &&
1962 GetEditUrl(rMEvt.GetPosPixel()) ) // Klick auf Link: Cursor nicht bewegen
1964 SetPointer( Pointer( POINTER_REFHAND ) );
1965 nMouseStatus = SC_GM_URLDOWN; // auch nur dann beim ButtonUp ausfuehren
1966 return;
1970 // Gridwin - SelectionEngine
1973 if ( rMEvt.IsLeft() )
1975 ScViewSelectionEngine* pSelEng = pViewData->GetView()->GetSelEngine();
1976 pSelEng->SetWindow(this);
1977 pSelEng->SetWhich(eWhich);
1978 pSelEng->SetVisibleArea( Rectangle(Point(), GetOutputSizePixel()) );
1980 // SelMouseButtonDown an der View setzt noch das bMoveIsShift Flag
1981 if ( pViewData->GetView()->SelMouseButtonDown( rMEvt ) )
1983 if (IsMouseCaptured())
1985 // Tracking statt CaptureMouse, damit sauber abgebrochen werden kann
1986 //! Irgendwann sollte die SelectionEngine selber StartTracking rufen!?!
1987 ReleaseMouse();
1988 StartTracking();
1990 pViewData->GetMarkData().SetMarking(true);
1991 return;
1996 void ScGridWindow::MouseButtonUp( const MouseEvent& rMEvt )
1998 aCurMousePos = rMEvt.GetPosPixel();
1999 ScDocument* pDoc = pViewData->GetDocument();
2000 ScMarkData& rMark = pViewData->GetMarkData();
2002 // #i41690# detect a MouseButtonUp call from within MouseButtonDown
2003 // (possible through Reschedule from storing an OLE object that is deselected)
2005 if ( nNestedButtonState == SC_NESTEDBUTTON_DOWN )
2006 nNestedButtonState = SC_NESTEDBUTTON_UP;
2008 if (nButtonDown != rMEvt.GetButtons())
2009 nMouseStatus = SC_GM_IGNORE; // reset und return
2011 nButtonDown = 0;
2013 if (nMouseStatus == SC_GM_IGNORE)
2015 nMouseStatus = SC_GM_NONE;
2016 // Selection-Engine: Markieren abbrechen
2017 pViewData->GetView()->GetSelEngine()->Reset();
2018 rMark.SetMarking(false);
2019 if (pViewData->IsAnyFillMode())
2021 pViewData->GetView()->StopRefMode();
2022 pViewData->ResetFillMode();
2024 StopMarking();
2025 DrawEndAction(); // Markieren/Verschieben auf Drawing-Layer abbrechen
2026 ReleaseMouse();
2027 return;
2030 if (nMouseStatus == SC_GM_FILTER)
2032 nMouseStatus = SC_GM_NONE;
2033 ReleaseMouse();
2034 return; // da muss nix mehr passieren
2037 ScModule* pScMod = SC_MOD();
2038 if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
2039 return;
2041 SfxBindings& rBindings = pViewData->GetBindings();
2042 if (bEEMouse && pViewData->HasEditView( eWhich ))
2044 EditView* pEditView;
2045 SCCOL nEditCol;
2046 SCROW nEditRow;
2047 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
2048 pEditView->MouseButtonUp( rMEvt );
2050 if ( rMEvt.IsMiddle() &&
2051 GetSettings().GetMouseSettings().GetMiddleButtonAction() == MOUSE_MIDDLE_PASTESELECTION )
2053 // EditView may have pasted from selection
2054 pScMod->InputChanged( pEditView );
2056 else
2057 pScMod->InputSelection( pEditView ); // parentheses etc.
2059 pViewData->GetView()->InvalidateAttribs();
2060 rBindings.Invalidate( SID_HYPERLINK_GETLINK );
2061 bEEMouse = false;
2062 return;
2065 if (bDPMouse)
2067 DPMouseButtonUp( rMEvt ); // resets bDPMouse
2068 return;
2071 if (bRFMouse)
2073 RFMouseMove( rMEvt, true ); // Range wieder richtigherum
2074 bRFMouse = false;
2075 SetPointer( Pointer( POINTER_ARROW ) );
2076 ReleaseMouse();
2077 return;
2080 if (nPagebreakMouse)
2082 PagebreakMove( rMEvt, true );
2083 nPagebreakMouse = SC_PD_NONE;
2084 SetPointer( Pointer( POINTER_ARROW ) );
2085 ReleaseMouse();
2086 return;
2089 if (nMouseStatus == SC_GM_WATERUNDO) // Undo im Giesskannenmodus
2091 ::svl::IUndoManager* pMgr = pViewData->GetDocShell()->GetUndoManager();
2092 if ( pMgr->GetUndoActionCount() && pMgr->GetUndoActionId() == STR_UNDO_APPLYCELLSTYLE )
2093 pMgr->Undo();
2094 return;
2097 if (DrawMouseButtonUp(rMEvt)) // includes format paint brush handling for drawing objects
2099 ScTabViewShell* pViewShell = pViewData->GetViewShell();
2100 SfxBindings& rFrmBindings=pViewShell->GetViewFrame()->GetBindings();
2101 rFrmBindings.Invalidate(SID_ATTR_TRANSFORM_WIDTH);
2102 rFrmBindings.Invalidate(SID_ATTR_TRANSFORM_HEIGHT);
2103 rFrmBindings.Invalidate(SID_ATTR_TRANSFORM_POS_X);
2104 rFrmBindings.Invalidate(SID_ATTR_TRANSFORM_POS_Y);
2105 rFrmBindings.Invalidate(SID_ATTR_TRANSFORM_ANGLE);
2106 rFrmBindings.Invalidate(SID_ATTR_TRANSFORM_ROT_X);
2107 rFrmBindings.Invalidate(SID_ATTR_TRANSFORM_ROT_Y);
2108 rFrmBindings.Invalidate(SID_ATTR_TRANSFORM_AUTOWIDTH);
2109 rFrmBindings.Invalidate(SID_ATTR_TRANSFORM_AUTOHEIGHT);
2110 return;
2113 rMark.SetMarking(false);
2115 SetPointer( Pointer( POINTER_ARROW ) );
2117 if (pViewData->IsFillMode() ||
2118 ( pViewData->GetFillMode() == SC_FILL_MATRIX && rMEvt.IsMod1() ))
2120 nScFillModeMouseModifier = rMEvt.GetModifier();
2121 SCCOL nStartCol;
2122 SCROW nStartRow;
2123 SCCOL nEndCol;
2124 SCROW nEndRow;
2125 pViewData->GetFillData( nStartCol, nStartRow, nEndCol, nEndRow );
2126 ScRange aDelRange;
2127 bool bIsDel = pViewData->GetDelMark( aDelRange );
2129 ScViewFunc* pView = pViewData->GetView();
2130 pView->StopRefMode();
2131 pViewData->ResetFillMode();
2132 pView->GetFunctionSet()->SetAnchorFlag( false ); // #i5819# don't use AutoFill anchor flag for selection
2134 if ( bIsDel )
2136 pView->MarkRange( aDelRange, false );
2137 pView->DeleteContents( IDF_CONTENTS );
2138 SCTAB nTab = pViewData->GetTabNo();
2139 ScRange aBlockRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab );
2140 if ( aBlockRange != aDelRange )
2142 if ( aDelRange.aStart.Row() == nStartRow )
2143 aBlockRange.aEnd.SetCol( aDelRange.aStart.Col() - 1 );
2144 else
2145 aBlockRange.aEnd.SetRow( aDelRange.aStart.Row() - 1 );
2146 pView->MarkRange( aBlockRange, false );
2149 else
2150 pViewData->GetDispatcher().Execute( FID_FILL_AUTO, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD );
2152 else if (pViewData->GetFillMode() == SC_FILL_MATRIX)
2154 SCTAB nTab = pViewData->GetTabNo();
2155 SCCOL nStartCol;
2156 SCROW nStartRow;
2157 SCCOL nEndCol;
2158 SCROW nEndRow;
2159 pViewData->GetFillData( nStartCol, nStartRow, nEndCol, nEndRow );
2160 ScRange aBlockRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab );
2161 SCCOL nFillCol = pViewData->GetRefEndX();
2162 SCROW nFillRow = pViewData->GetRefEndY();
2163 ScAddress aEndPos( nFillCol, nFillRow, nTab );
2165 ScTabView* pView = pViewData->GetView();
2166 pView->StopRefMode();
2167 pViewData->ResetFillMode();
2168 pView->GetFunctionSet()->SetAnchorFlag( false );
2170 if ( aEndPos != aBlockRange.aEnd )
2172 pViewData->GetDocShell()->GetDocFunc().ResizeMatrix( aBlockRange, aEndPos, false );
2173 pViewData->GetView()->MarkRange( ScRange( aBlockRange.aStart, aEndPos ) );
2176 else if (pViewData->IsAnyFillMode())
2178 // Embedded-Area has been changed
2179 ScTabView* pView = pViewData->GetView();
2180 pView->StopRefMode();
2181 pViewData->ResetFillMode();
2182 pView->GetFunctionSet()->SetAnchorFlag( false );
2183 pViewData->GetDocShell()->UpdateOle(pViewData);
2186 bool bRefMode = pViewData->IsRefMode();
2187 if (bRefMode)
2188 pScMod->EndReference();
2191 // Giesskannen-Modus (Gestalter)
2194 if (pScMod->GetIsWaterCan())
2196 // Abfrage auf Undo schon oben
2198 ScStyleSheetPool* pStylePool = (ScStyleSheetPool*)
2199 (pViewData->GetDocument()->
2200 GetStyleSheetPool());
2201 if ( pStylePool )
2203 SfxStyleSheet* pStyleSheet = (SfxStyleSheet*)
2204 pStylePool->GetActualStyleSheet();
2206 if ( pStyleSheet )
2208 SfxStyleFamily eFamily = pStyleSheet->GetFamily();
2210 switch ( eFamily )
2212 case SFX_STYLE_FAMILY_PARA:
2213 pViewData->GetView()->SetStyleSheetToMarked( pStyleSheet );
2214 pViewData->GetView()->DoneBlockMode();
2215 break;
2217 case SFX_STYLE_FAMILY_PAGE:
2218 pViewData->GetDocument()->SetPageStyle( pViewData->GetTabNo(),
2219 pStyleSheet->GetName() );
2221 ScPrintFunc( pViewData->GetDocShell(),
2222 pViewData->GetViewShell()->GetPrinter(true),
2223 pViewData->GetTabNo() ).UpdatePages();
2225 rBindings.Invalidate( SID_STATUS_PAGESTYLE );
2226 break;
2228 default:
2229 break;
2235 ScDBFunc* pView = pViewData->GetView();
2236 ScDocument* pBrushDoc = pView->GetBrushDocument();
2237 if ( pBrushDoc )
2239 pView->PasteFromClip( IDF_ATTRIB, pBrushDoc );
2240 if ( !pView->IsPaintBrushLocked() )
2241 pView->ResetBrushDocument(); // invalidates pBrushDoc pointer
2245 // double click (only left button)
2248 bool bDouble = ( rMEvt.GetClicks() == 2 && rMEvt.IsLeft() );
2249 if ( bDouble && !bRefMode && nMouseStatus == SC_GM_DBLDOWN && !pScMod->IsRefDialogOpen() )
2251 // data pilot table
2252 Point aPos = rMEvt.GetPosPixel();
2253 SCsCOL nPosX;
2254 SCsROW nPosY;
2255 SCTAB nTab = pViewData->GetTabNo();
2256 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
2257 ScDPObject* pDPObj = pDoc->GetDPAtCursor( nPosX, nPosY, nTab );
2258 if ( pDPObj && pDPObj->GetSaveData()->GetDrillDown() )
2260 ScAddress aCellPos( nPosX, nPosY, pViewData->GetTabNo() );
2262 // Check for header drill-down first.
2263 sheet::DataPilotTableHeaderData aData;
2264 pDPObj->GetHeaderPositionData(aCellPos, aData);
2266 if ( ( aData.Flags & sheet::MemberResultFlags::HASMEMBER ) &&
2267 ! ( aData.Flags & sheet::MemberResultFlags::SUBTOTAL ) )
2269 sal_uInt16 nDummy;
2270 if ( pView->HasSelectionForDrillDown( nDummy ) )
2272 // execute slot to show dialog
2273 pViewData->GetDispatcher().Execute( SID_OUTLINE_SHOW, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD );
2275 else
2277 // toggle single entry
2278 ScDPObject aNewObj( *pDPObj );
2279 pDPObj->ToggleDetails( aData, &aNewObj );
2280 ScDBDocFunc aFunc( *pViewData->GetDocShell() );
2281 aFunc.DataPilotUpdate( pDPObj, &aNewObj, true, false );
2282 pViewData->GetView()->CursorPosChanged(); // shells may be switched
2285 else
2287 // Check if the data area is double-clicked.
2289 Sequence<sheet::DataPilotFieldFilter> aFilters;
2290 if ( pDPObj->GetDataFieldPositionData(aCellPos, aFilters) )
2291 pViewData->GetView()->ShowDataPilotSourceData( *pDPObj, aFilters );
2294 return;
2297 // Check for cell protection attribute.
2298 ScTableProtection* pProtect = pDoc->GetTabProtection( nTab );
2299 bool bEditAllowed = true;
2300 if ( pProtect && pProtect->isProtected() )
2302 bool bCellProtected = pDoc->HasAttrib(nPosX, nPosY, nTab, nPosX, nPosY, nTab, HASATTR_PROTECTED);
2303 bool bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
2304 bool bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
2306 if ( bSkipProtected && bSkipUnprotected )
2307 bEditAllowed = false;
2308 else if ( (bCellProtected && bSkipProtected) || (!bCellProtected && bSkipUnprotected) )
2309 bEditAllowed = false;
2312 if ( bEditAllowed )
2314 // edit cell contents
2315 pViewData->GetViewShell()->UpdateInputHandler();
2316 pScMod->SetInputMode( SC_INPUT_TABLE );
2317 if (pViewData->HasEditView(eWhich))
2319 // Text-Cursor gleich an die geklickte Stelle setzen
2320 EditView* pEditView = pViewData->GetEditView( eWhich );
2321 MouseEvent aEditEvt( rMEvt.GetPosPixel(), 1, MOUSE_SYNTHETIC, MOUSE_LEFT, 0 );
2322 pEditView->MouseButtonDown( aEditEvt );
2323 pEditView->MouseButtonUp( aEditEvt );
2326 return;
2330 // Links in edit cells
2333 bool bAlt = rMEvt.IsMod2();
2334 if ( !bAlt && !bRefMode && !bDouble && nMouseStatus == SC_GM_URLDOWN )
2336 // beim ButtonUp nur ausfuehren, wenn ButtonDown auch ueber einer URL war
2338 OUString aName, aUrl, aTarget;
2339 if ( GetEditUrl( rMEvt.GetPosPixel(), &aName, &aUrl, &aTarget ) )
2341 nMouseStatus = SC_GM_NONE; // keinen Doppelklick anfangen
2343 // ScGlobal::OpenURL() only understands Calc A1 style syntax.
2344 // Convert it to Calc A1 before calling OpenURL().
2346 if (pDoc->GetAddressConvention() == formula::FormulaGrammar::CONV_OOO)
2347 ScGlobal::OpenURL(aUrl, aTarget);
2348 else
2350 ScAddress aTempAddr;
2351 ScAddress::ExternalInfo aExtInfo;
2352 sal_uInt16 nRes = aTempAddr.Parse(aUrl, pDoc, pDoc->GetAddressConvention(), &aExtInfo);
2353 if (!(nRes & SCA_VALID))
2355 // Not a reference string. Pass it through unmodified.
2356 ScGlobal::OpenURL(aUrl, aTarget);
2357 return;
2360 OUStringBuffer aBuf;
2361 if (aExtInfo.mbExternal)
2363 // External reference.
2364 ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
2365 const OUString* pStr = pRefMgr->getExternalFileName(aExtInfo.mnFileId);
2366 if (pStr)
2367 aBuf.append(*pStr);
2369 aBuf.append('#');
2370 aBuf.append(aExtInfo.maTabName);
2371 aBuf.append('.');
2372 OUString aRefCalcA1(aTempAddr.Format(SCA_ABS, NULL, formula::FormulaGrammar::CONV_OOO));
2373 aBuf.append(aRefCalcA1);
2374 ScGlobal::OpenURL(aBuf.makeStringAndClear(), aTarget);
2376 else
2378 // Internal reference.
2379 aBuf.append('#');
2380 OUString aUrlCalcA1(aTempAddr.Format(SCA_ABS_3D, pDoc, formula::FormulaGrammar::CONV_OOO));
2381 aBuf.append(aUrlCalcA1);
2382 ScGlobal::OpenURL(aBuf.makeStringAndClear(), aTarget);
2386 // fire worksheet_followhyperlink event
2387 uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents = pDoc->GetVbaEventProcessor();
2388 if( xVbaEvents.is() ) try
2390 Point aPos = rMEvt.GetPosPixel();
2391 SCsCOL nPosX;
2392 SCsROW nPosY;
2393 SCTAB nTab = pViewData->GetTabNo();
2394 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
2395 OUString sURL;
2396 ScRefCellValue aCell;
2397 if (lcl_GetHyperlinkCell(pDoc, nPosX, nPosY, nTab, aCell, sURL))
2399 ScAddress aCellPos( nPosX, nPosY, nTab );
2400 uno::Reference< table::XCell > xCell( new ScCellObj( pViewData->GetDocShell(), aCellPos ) );
2401 uno::Sequence< uno::Any > aArgs(1);
2402 aArgs[0] <<= xCell;
2403 xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKSHEET_FOLLOWHYPERLINK, aArgs );
2406 catch( uno::Exception& )
2410 return;
2415 // Gridwin - SelectionEngine
2418 // SelMouseButtonDown is called only for left button, but SelMouseButtonUp would return
2419 // sal_True for any call, so IsLeft must be checked here, too.
2421 if ( rMEvt.IsLeft() && pViewData->GetView()->GetSelEngine()->SelMouseButtonUp( rMEvt ) )
2423 pViewData->GetView()->SelectionChanged();
2425 SfxDispatcher* pDisp = pViewData->GetViewShell()->GetDispatcher();
2426 bool bFormulaMode = pScMod->IsFormulaMode();
2427 OSL_ENSURE( pDisp || bFormulaMode, "Cursor auf nicht aktiver View bewegen ?" );
2429 // #i14927# execute SID_CURRENTCELL (for macro recording) only if there is no
2430 // multiple selection, so the argument string completely describes the selection,
2431 // and executing the slot won't change the existing selection (executing the slot
2432 // here and from a recorded macro is treated equally)
2434 if ( pDisp && !bFormulaMode && !rMark.IsMultiMarked() )
2436 OUString aAddr; // CurrentCell
2437 if( rMark.IsMarked() )
2439 ScRange aScRange;
2440 rMark.GetMarkArea( aScRange );
2441 aAddr = aScRange.Format(SCR_ABS);
2442 if ( aScRange.aStart == aScRange.aEnd )
2444 // make sure there is a range selection string even for a single cell
2445 aAddr = aAddr + ":" + aAddr;
2448 //! SID_MARKAREA gibts nicht mehr ???
2449 //! was passiert beim Markieren mit dem Cursor ???
2451 else // nur Cursor bewegen
2453 ScAddress aScAddress( pViewData->GetCurX(), pViewData->GetCurY(), 0 );
2454 aAddr = aScAddress.Format(SCA_ABS);
2457 SfxStringItem aPosItem( SID_CURRENTCELL, aAddr );
2458 // We don't want to align to the cursor position because if the
2459 // cell cursor isn't visible after making selection, it would jump
2460 // back to the origin of the selection where the cell cursor is.
2461 SfxBoolItem aAlignCursorItem( FN_PARAM_2, false );
2462 pDisp->Execute( SID_CURRENTCELL, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD,
2463 &aPosItem, &aAlignCursorItem, (void*)0L );
2465 pViewData->GetView()->InvalidateAttribs();
2467 pViewData->GetViewShell()->SelectionChanged();
2468 return;
2472 void ScGridWindow::FakeButtonUp()
2474 if ( nButtonDown )
2476 MouseEvent aEvent( aCurMousePos ); // nButtons = 0 -> ignore
2477 MouseButtonUp( aEvent );
2481 void ScGridWindow::MouseMove( const MouseEvent& rMEvt )
2483 aCurMousePos = rMEvt.GetPosPixel();
2485 if ( rMEvt.IsLeaveWindow() && pNoteMarker && !pNoteMarker->IsByKeyboard() )
2486 HideNoteMarker();
2488 ScModule* pScMod = SC_MOD();
2489 if (pScMod->IsModalMode(pViewData->GetSfxDocShell()))
2490 return;
2492 // Ob aus dem Edit-Modus Drag&Drop gestartet wurde, bekommt man leider
2493 // nicht anders mit:
2495 if (bEEMouse && nButtonDown && !rMEvt.GetButtons())
2497 bEEMouse = false;
2498 nButtonDown = 0;
2499 nMouseStatus = SC_GM_NONE;
2500 return;
2503 if (nMouseStatus == SC_GM_IGNORE)
2504 return;
2506 if (nMouseStatus == SC_GM_WATERUNDO) // Undo im Giesskannenmodus -> nur auf Up warten
2507 return;
2509 if ( pViewData->GetViewShell()->IsAuditShell() ) // Detektiv-Fuell-Modus
2511 SetPointer( Pointer( POINTER_FILL ) );
2512 return;
2515 if (nMouseStatus == SC_GM_FILTER && pFilterBox)
2517 Point aRelPos = pFilterBox->ScreenToOutputPixel( OutputToScreenPixel( rMEvt.GetPosPixel() ) );
2518 if ( Rectangle(Point(),pFilterBox->GetOutputSizePixel()).IsInside(aRelPos) )
2520 nButtonDown = 0;
2521 nMouseStatus = SC_GM_NONE;
2522 ReleaseMouse();
2523 pFilterBox->MouseButtonDown( MouseEvent( aRelPos, 1, MOUSE_SIMPLECLICK, MOUSE_LEFT ) );
2524 return;
2528 bool bFormulaMode = pScMod->IsFormulaMode(); // naechster Klick -> Referenz
2530 if (bEEMouse && pViewData->HasEditView( eWhich ))
2532 EditView* pEditView;
2533 SCCOL nEditCol;
2534 SCROW nEditRow;
2535 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
2536 pEditView->MouseMove( rMEvt );
2537 return;
2540 if (bDPMouse)
2542 DPMouseMove( rMEvt );
2543 return;
2546 if (bRFMouse)
2548 RFMouseMove( rMEvt, false );
2549 return;
2552 if (nPagebreakMouse)
2554 PagebreakMove( rMEvt, false );
2555 return;
2558 // anderen Mauszeiger anzeigen?
2560 bool bEditMode = pViewData->HasEditView(eWhich);
2562 //! Testen ob RefMode-Dragging !!!
2563 if ( bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()) )
2565 Point aPos = rMEvt.GetPosPixel();
2566 SCsCOL nPosX;
2567 SCsROW nPosY;
2568 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
2570 EditView* pEditView;
2571 SCCOL nEditCol;
2572 SCROW nEditRow;
2573 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
2574 SCCOL nEndCol = pViewData->GetEditEndCol();
2575 SCROW nEndRow = pViewData->GetEditEndRow();
2577 if ( nPosX >= (SCsCOL) nEditCol && nPosX <= (SCsCOL) nEndCol &&
2578 nPosY >= (SCsROW) nEditRow && nPosY <= (SCsROW) nEndRow )
2580 // Field can only be URL field
2581 bool bAlt = rMEvt.IsMod2();
2582 if ( !bAlt && !nButtonDown && pEditView && pEditView->GetFieldUnderMousePointer() )
2583 SetPointer( Pointer( POINTER_REFHAND ) );
2584 else if ( pEditView && pEditView->GetEditEngine()->IsVertical() )
2585 SetPointer( Pointer( POINTER_TEXT_VERTICAL ) );
2586 else
2587 SetPointer( Pointer( POINTER_TEXT ) );
2588 return;
2592 bool bWater = SC_MOD()->GetIsWaterCan() || pViewData->GetView()->HasPaintBrush();
2593 if (bWater)
2594 SetPointer( Pointer(POINTER_FILL) );
2596 if (!bWater)
2598 bool bCross = false;
2600 // Range-Finder
2602 RfCorner rCorner = NONE;
2603 if ( HitRangeFinder( rMEvt.GetPosPixel(), rCorner ) )
2605 if (rCorner != NONE)
2606 SetPointer( Pointer( POINTER_CROSS ) );
2607 else
2608 SetPointer( Pointer( POINTER_HAND ) );
2609 bCross = true;
2612 // Page-Break-Modus
2614 sal_uInt16 nBreakType;
2615 if ( !nButtonDown && pViewData->IsPagebreakMode() &&
2616 ( nBreakType = HitPageBreak( rMEvt.GetPosPixel() ) ) != 0 )
2618 PointerStyle eNew = POINTER_ARROW;
2619 switch ( nBreakType )
2621 case SC_PD_RANGE_L:
2622 case SC_PD_RANGE_R:
2623 case SC_PD_BREAK_H:
2624 eNew = POINTER_ESIZE;
2625 break;
2626 case SC_PD_RANGE_T:
2627 case SC_PD_RANGE_B:
2628 case SC_PD_BREAK_V:
2629 eNew = POINTER_SSIZE;
2630 break;
2631 case SC_PD_RANGE_TL:
2632 case SC_PD_RANGE_BR:
2633 eNew = POINTER_SESIZE;
2634 break;
2635 case SC_PD_RANGE_TR:
2636 case SC_PD_RANGE_BL:
2637 eNew = POINTER_NESIZE;
2638 break;
2640 SetPointer( Pointer( eNew ) );
2641 bCross = true;
2644 // Fill-Cursor anzeigen ?
2646 if ( !bFormulaMode && !nButtonDown )
2647 if (TestMouse( rMEvt, false ))
2648 bCross = true;
2650 if ( nButtonDown && pViewData->IsAnyFillMode() )
2652 SetPointer( Pointer( POINTER_CROSS ) );
2653 bCross = true;
2654 nScFillModeMouseModifier = rMEvt.GetModifier(); // ausgewertet bei AutoFill und Matrix
2657 if (!bCross)
2659 bool bAlt = rMEvt.IsMod2();
2661 if (bEditMode) // Edit-Mode muss zuerst kommen!
2662 SetPointer( Pointer( POINTER_ARROW ) );
2663 else if ( !bAlt && !nButtonDown &&
2664 GetEditUrl(rMEvt.GetPosPixel()) )
2665 SetPointer( Pointer( POINTER_REFHAND ) );
2666 else if ( DrawMouseMove(rMEvt) ) // setzt Pointer um
2667 return;
2671 if ( pViewData->GetView()->GetSelEngine()->SelMouseMove( rMEvt ) )
2672 return;
2675 static void lcl_InitMouseEvent( ::com::sun::star::awt::MouseEvent& rEvent, const MouseEvent& rEvt )
2677 rEvent.Modifiers = 0;
2678 if ( rEvt.IsShift() )
2679 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::SHIFT;
2680 if ( rEvt.IsMod1() )
2681 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD1;
2682 if ( rEvt.IsMod2() )
2683 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD2;
2684 if ( rEvt.IsMod3() )
2685 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD3;
2687 rEvent.Buttons = 0;
2688 if ( rEvt.IsLeft() )
2689 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::LEFT;
2690 if ( rEvt.IsRight() )
2691 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::RIGHT;
2692 if ( rEvt.IsMiddle() )
2693 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::MIDDLE;
2695 rEvent.X = rEvt.GetPosPixel().X();
2696 rEvent.Y = rEvt.GetPosPixel().Y();
2697 rEvent.ClickCount = rEvt.GetClicks();
2698 rEvent.PopupTrigger = false;
2701 bool ScGridWindow::PreNotify( NotifyEvent& rNEvt )
2703 bool bDone = false;
2704 sal_uInt16 nType = rNEvt.GetType();
2705 if ( nType == EVENT_MOUSEBUTTONUP || nType == EVENT_MOUSEBUTTONDOWN )
2707 Window* pWindow = rNEvt.GetWindow();
2708 if (pWindow == this && pViewData)
2710 SfxViewFrame* pViewFrame = pViewData->GetViewShell()->GetViewFrame();
2711 if (pViewFrame)
2713 com::sun::star::uno::Reference<com::sun::star::frame::XController> xController = pViewFrame->GetFrame().GetController();
2714 if (xController.is())
2716 ScTabViewObj* pImp = ScTabViewObj::getImplementation( xController );
2717 if (pImp && pImp->IsMouseListening())
2719 ::com::sun::star::awt::MouseEvent aEvent;
2720 lcl_InitMouseEvent( aEvent, *rNEvt.GetMouseEvent() );
2721 if ( rNEvt.GetWindow() )
2722 aEvent.Source = rNEvt.GetWindow()->GetComponentInterface();
2723 if ( nType == EVENT_MOUSEBUTTONDOWN)
2724 bDone = pImp->MousePressed( aEvent );
2725 else
2726 bDone = pImp->MouseReleased( aEvent );
2732 if (bDone) // event consumed by a listener
2734 if ( nType == EVENT_MOUSEBUTTONDOWN )
2736 const MouseEvent* pMouseEvent = rNEvt.GetMouseEvent();
2737 if ( pMouseEvent->IsRight() && pMouseEvent->GetClicks() == 1 )
2739 // If a listener returned true for a right-click call, also prevent opening the context menu
2740 // (this works only if the context menu is opened on mouse-down)
2741 nMouseStatus = SC_GM_IGNORE;
2745 return true;
2747 else
2748 return Window::PreNotify( rNEvt );
2751 void ScGridWindow::Tracking( const TrackingEvent& rTEvt )
2753 // Weil die SelectionEngine kein Tracking kennt, die Events nur auf
2754 // die verschiedenen MouseHandler verteilen...
2756 const MouseEvent& rMEvt = rTEvt.GetMouseEvent();
2758 if ( rTEvt.IsTrackingCanceled() ) // alles abbrechen...
2760 if (!pViewData->GetView()->IsInActivatePart() && !SC_MOD()->IsRefDialogOpen())
2762 if (bDPMouse)
2763 bDPMouse = false; // gezeichnet wird per bDragRect
2764 if (bDragRect)
2766 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich );
2767 bDragRect = false;
2768 UpdateDragRectOverlay();
2770 if (bRFMouse)
2772 RFMouseMove( rMEvt, true ); // richtig abbrechen geht dabei nicht...
2773 bRFMouse = false;
2775 if (nPagebreakMouse)
2777 // if (bPagebreakDrawn)
2778 // DrawDragRect( aPagebreakDrag.aStart.Col(), aPagebreakDrag.aStart.Row(),
2779 // aPagebreakDrag.aEnd.Col(), aPagebreakDrag.aEnd.Row(), sal_False );
2780 bPagebreakDrawn = false;
2781 UpdateDragRectOverlay();
2782 nPagebreakMouse = SC_PD_NONE;
2785 SetPointer( Pointer( POINTER_ARROW ) );
2786 StopMarking();
2787 MouseButtonUp( rMEvt ); // mit Status SC_GM_IGNORE aus StopMarking
2789 bool bRefMode = pViewData->IsRefMode();
2790 if (bRefMode)
2791 SC_MOD()->EndReference(); // Dialog nicht verkleinert lassen
2794 else if ( rTEvt.IsTrackingEnded() )
2796 // MouseButtonUp immer mit passenden Buttons (z.B. wegen Testtool, #63148#)
2797 // Schliesslich behauptet der Tracking-Event ja, dass normal beendet und nicht
2798 // abgebrochen wurde.
2800 MouseEvent aUpEvt( rMEvt.GetPosPixel(), rMEvt.GetClicks(),
2801 rMEvt.GetMode(), nButtonDown, rMEvt.GetModifier() );
2802 MouseButtonUp( aUpEvt );
2804 else
2805 MouseMove( rMEvt );
2808 void ScGridWindow::StartDrag( sal_Int8 /* nAction */, const Point& rPosPixel )
2810 if ( pFilterBox || nPagebreakMouse )
2811 return;
2813 HideNoteMarker();
2815 CommandEvent aDragEvent( rPosPixel, COMMAND_STARTDRAG, true );
2817 if (bEEMouse && pViewData->HasEditView( eWhich ))
2819 EditView* pEditView;
2820 SCCOL nEditCol;
2821 SCROW nEditRow;
2822 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow );
2824 // don't remove the edit view while switching views
2825 ScModule* pScMod = SC_MOD();
2826 pScMod->SetInEditCommand( true );
2828 pEditView->Command( aDragEvent );
2830 ScInputHandler* pHdl = pScMod->GetInputHdl();
2831 if (pHdl)
2832 pHdl->DataChanged();
2834 pScMod->SetInEditCommand( false );
2835 if (!pViewData->IsActive()) // dropped to different view?
2837 ScInputHandler* pViewHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
2838 if ( pViewHdl && pViewData->HasEditView( eWhich ) )
2840 pViewHdl->CancelHandler();
2841 ShowCursor(); // missing from KillEditView
2845 else
2846 if ( !DrawCommand(aDragEvent) )
2847 pViewData->GetView()->GetSelEngine()->Command( aDragEvent );
2850 static void lcl_SetTextCursorPos( ScViewData* pViewData, ScSplitPos eWhich, Window* pWin )
2852 SCCOL nCol = pViewData->GetCurX();
2853 SCROW nRow = pViewData->GetCurY();
2854 Rectangle aEditArea = pViewData->GetEditArea( eWhich, nCol, nRow, pWin, NULL, true );
2855 aEditArea.Right() = aEditArea.Left();
2856 aEditArea = pWin->PixelToLogic( aEditArea );
2857 pWin->SetCursorRect( &aEditArea );
2860 void ScGridWindow::Command( const CommandEvent& rCEvt )
2862 // The command event is send to the window after a possible context
2863 // menu from an inplace client is closed. Now we have the chance to
2864 // deactivate the inplace client without any problem regarding parent
2865 // windows and code on the stack.
2866 sal_uInt16 nCmd = rCEvt.GetCommand();
2867 ScTabViewShell* pTabViewSh = pViewData->GetViewShell();
2868 SfxInPlaceClient* pClient = pTabViewSh->GetIPClient();
2869 if ( pClient &&
2870 pClient->IsObjectInPlaceActive() &&
2871 nCmd == COMMAND_CONTEXTMENU )
2873 pTabViewSh->DeactivateOle();
2874 return;
2877 ScModule* pScMod = SC_MOD();
2878 OSL_ENSURE( nCmd != COMMAND_STARTDRAG, "ScGridWindow::Command called with COMMAND_STARTDRAG" );
2880 if ( nCmd == COMMAND_STARTEXTTEXTINPUT ||
2881 nCmd == COMMAND_ENDEXTTEXTINPUT ||
2882 nCmd == COMMAND_EXTTEXTINPUT ||
2883 nCmd == COMMAND_CURSORPOS ||
2884 nCmd == COMMAND_QUERYCHARPOSITION )
2886 bool bEditView = pViewData->HasEditView( eWhich );
2887 if (!bEditView)
2889 // only if no cell editview is active, look at drawview
2890 SdrView* pSdrView = pViewData->GetView()->GetSdrView();
2891 if ( pSdrView )
2893 OutlinerView* pOlView = pSdrView->GetTextEditOutlinerView();
2894 if ( pOlView && pOlView->GetWindow() == this )
2896 pOlView->Command( rCEvt );
2897 return; // done
2902 if ( nCmd == COMMAND_CURSORPOS && !bEditView )
2904 // CURSORPOS may be called without following text input,
2905 // to set the input method window position
2906 // -> input mode must not be started,
2907 // manually calculate text insert position if not in input mode
2909 lcl_SetTextCursorPos( pViewData, eWhich, this );
2910 return;
2913 ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() );
2914 if ( pHdl )
2916 pHdl->InputCommand( rCEvt, true );
2917 return; // done
2920 Window::Command( rCEvt );
2921 return;
2924 if ( nCmd == COMMAND_PASTESELECTION )
2926 if ( bEEMouse )
2928 // EditEngine handles selection in MouseButtonUp - no action
2929 // needed in command handler
2931 else
2933 PasteSelection( rCEvt.GetMousePosPixel() );
2935 return;
2938 if ( nCmd == COMMAND_INPUTLANGUAGECHANGE )
2940 // #i55929# Font and font size state depends on input language if nothing is selected,
2941 // so the slots have to be invalidated when the input language is changed.
2943 SfxBindings& rBindings = pViewData->GetBindings();
2944 rBindings.Invalidate( SID_ATTR_CHAR_FONT );
2945 rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT );
2946 return;
2949 if ( nCmd == COMMAND_WHEEL || nCmd == COMMAND_STARTAUTOSCROLL || nCmd == COMMAND_AUTOSCROLL )
2951 bool bDone = pViewData->GetView()->ScrollCommand( rCEvt, eWhich );
2952 if (!bDone)
2953 Window::Command(rCEvt);
2954 return;
2956 // #i7560# FormulaMode check is below scrolling - scrolling is allowed during formula input
2957 bool bDisable = pScMod->IsFormulaMode() ||
2958 pScMod->IsModalMode(pViewData->GetSfxDocShell());
2959 if (bDisable)
2960 return;
2962 if ( nCmd == COMMAND_CONTEXTMENU && !SC_MOD()->GetIsWaterCan() )
2964 bool bMouse = rCEvt.IsMouseEvent();
2965 if ( bMouse && nMouseStatus == SC_GM_IGNORE )
2966 return;
2968 if (pViewData->IsAnyFillMode())
2970 pViewData->GetView()->StopRefMode();
2971 pViewData->ResetFillMode();
2973 ReleaseMouse();
2974 StopMarking();
2976 Point aPosPixel = rCEvt.GetMousePosPixel();
2977 Point aMenuPos = aPosPixel;
2979 SCsCOL nCellX = -1;
2980 SCsROW nCellY = -1;
2981 pViewData->GetPosFromPixel(aPosPixel.X(), aPosPixel.Y(), eWhich, nCellX, nCellY);
2983 bool bSpellError = false;
2984 SCCOL nColSpellError = nCellX;
2985 ScRefCellValue aSpellCheckCell;
2987 if ( bMouse )
2989 ScDocument* pDoc = pViewData->GetDocument();
2990 SCTAB nTab = pViewData->GetTabNo();
2991 const ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
2992 bool bSelectAllowed = true;
2993 if ( pProtect && pProtect->isProtected() )
2995 // This sheet is protected. Check if a context menu is allowed on this cell.
2996 bool bCellProtected = pDoc->HasAttrib(nCellX, nCellY, nTab, nCellX, nCellY, nTab, HASATTR_PROTECTED);
2997 bool bSelProtected = pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
2998 bool bSelUnprotected = pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
3000 if (bCellProtected)
3001 bSelectAllowed = bSelProtected;
3002 else
3003 bSelectAllowed = bSelUnprotected;
3005 if (!bSelectAllowed)
3006 // Selecting this cell is not allowed, neither is context menu.
3007 return;
3009 if (mpSpellCheckCxt)
3011 // Find the first string to the left for spell checking in case the current cell is empty.
3012 ScAddress aPos(nCellX, nCellY, nTab);
3013 aSpellCheckCell.assign(*pDoc, aPos);
3014 while (aSpellCheckCell.meType == CELLTYPE_NONE)
3016 // Loop until we get the first non-empty cell in the row.
3017 aPos.IncCol(-1);
3018 if (aPos.Col() < 0)
3019 break;
3021 aSpellCheckCell.assign(*pDoc, aPos);
3024 if (aPos.Col() >= 0 && (aSpellCheckCell.meType == CELLTYPE_STRING || aSpellCheckCell.meType == CELLTYPE_EDIT))
3025 nColSpellError = aPos.Col();
3027 bSpellError = (mpSpellCheckCxt->isMisspelled(nColSpellError, nCellY));
3028 if (bSpellError)
3030 // Check and see if a misspelled word is under the mouse pointer.
3031 bSpellError = IsSpellErrorAtPos(aPosPixel, nColSpellError, nCellX, nCellY);
3035 // #i18735# First select the item under the mouse pointer.
3036 // This can change the selection, and the view state (edit mode, etc).
3037 SelectForContextMenu(aPosPixel, bSpellError ? nColSpellError : nCellX, nCellY);
3040 bool bDone = false;
3041 bool bEdit = pViewData->HasEditView(eWhich);
3043 if ( !bEdit )
3045 // Edit-Zelle mit Spelling-Errors ?
3046 if (bMouse && (GetEditUrl(aPosPixel) || bSpellError))
3048 // GetEditUrlOrError hat den Cursor schon bewegt
3050 pScMod->SetInputMode( SC_INPUT_TABLE );
3051 bEdit = pViewData->HasEditView(eWhich); // hat's geklappt ?
3053 OSL_ENSURE( bEdit, "kann nicht in Edit-Modus schalten" );
3056 if ( bEdit )
3058 EditView* pEditView = pViewData->GetEditView( eWhich ); // ist dann nicht 0
3060 if ( !bMouse )
3062 Cursor* pCur = pEditView->GetCursor();
3063 if ( pCur )
3065 Point aLogicPos = pCur->GetPos();
3066 // use the position right of the cursor (spell popup is opened if
3067 // the cursor is before the word, but not if behind it)
3068 aLogicPos.X() += pCur->GetWidth();
3069 aLogicPos.Y() += pCur->GetHeight() / 2; // center vertically
3070 aMenuPos = LogicToPixel( aLogicPos );
3074 // if edit mode was just started above, online spelling may be incomplete
3075 pEditView->GetEditEngine()->CompleteOnlineSpelling();
3077 // IsCursorAtWrongSpelledWord could be used for !bMouse
3078 // if there was a corresponding ExecuteSpellPopup call
3080 if (bSpellError)
3082 // Wenn man unter OS/2 neben das Popupmenue klickt, kommt MouseButtonDown
3083 // vor dem Ende des Menue-Execute, darum muss SetModified vorher kommen
3084 // (Bug #40968#)
3085 ScInputHandler* pHdl = pScMod->GetInputHdl();
3086 if (pHdl)
3087 pHdl->SetModified();
3089 Link aLink = LINK( this, ScGridWindow, PopupSpellingHdl );
3090 pEditView->ExecuteSpellPopup( aMenuPos, &aLink );
3092 bDone = true;
3095 else if ( !bMouse )
3097 // non-edit menu by keyboard -> use lower right of cell cursor position
3098 ScDocument* aDoc = pViewData->GetDocument();
3099 SCTAB nTabNo = pViewData->GetTabNo();
3100 bool bLayoutIsRTL = aDoc->IsLayoutRTL(nTabNo);
3102 SCCOL nCurX = pViewData->GetCurX();
3103 SCROW nCurY = pViewData->GetCurY();
3104 aMenuPos = pViewData->GetScrPos( nCurX, nCurY, eWhich, true );
3105 long nSizeXPix;
3106 long nSizeYPix;
3107 pViewData->GetMergeSizePixel( nCurX, nCurY, nSizeXPix, nSizeYPix );
3108 // fdo#55432 take the correct position for RTL sheet
3109 aMenuPos.X() += bLayoutIsRTL ? -nSizeXPix : nSizeXPix;
3110 aMenuPos.Y() += nSizeYPix;
3112 ScTabViewShell* pViewSh = pViewData->GetViewShell();
3113 if (pViewSh)
3115 // Is a draw object selected?
3117 SdrView* pDrawView = pViewSh->GetSdrView();
3118 if (pDrawView && pDrawView->AreObjectsMarked())
3120 // #100442#; the conext menu should open in the middle of the selected objects
3121 Rectangle aSelectRect(LogicToPixel(pDrawView->GetAllMarkedBoundRect()));
3122 aMenuPos = aSelectRect.Center();
3127 if (!bDone)
3129 SfxDispatcher::ExecutePopup( 0, this, &aMenuPos );
3134 void ScGridWindow::SelectForContextMenu( const Point& rPosPixel, SCsCOL nCellX, SCsROW nCellY )
3136 // #i18735# if the click was outside of the current selection,
3137 // the cursor is moved or an object at the click position selected.
3138 // (see SwEditWin::SelectMenuPosition in Writer)
3140 ScTabView* pView = pViewData->GetView();
3141 ScDrawView* pDrawView = pView->GetScDrawView();
3143 // check cell edit mode
3145 if ( pViewData->HasEditView(eWhich) )
3147 ScModule* pScMod = SC_MOD();
3148 SCCOL nEditStartCol = pViewData->GetEditViewCol(); //! change to GetEditStartCol after calcrtl is integrated
3149 SCROW nEditStartRow = pViewData->GetEditViewRow();
3150 SCCOL nEditEndCol = pViewData->GetEditEndCol();
3151 SCROW nEditEndRow = pViewData->GetEditEndRow();
3153 if ( nCellX >= (SCsCOL) nEditStartCol && nCellX <= (SCsCOL) nEditEndCol &&
3154 nCellY >= (SCsROW) nEditStartRow && nCellY <= (SCsROW) nEditEndRow )
3156 // handle selection within the EditView
3158 EditView* pEditView = pViewData->GetEditView( eWhich ); // not NULL (HasEditView)
3159 EditEngine* pEditEngine = pEditView->GetEditEngine();
3160 Rectangle aOutputArea = pEditView->GetOutputArea();
3161 Rectangle aVisArea = pEditView->GetVisArea();
3163 Point aTextPos = PixelToLogic( rPosPixel );
3164 if ( pEditEngine->IsVertical() ) // have to manually transform position
3166 aTextPos -= aOutputArea.TopRight();
3167 long nTemp = -aTextPos.X();
3168 aTextPos.X() = aTextPos.Y();
3169 aTextPos.Y() = nTemp;
3171 else
3172 aTextPos -= aOutputArea.TopLeft();
3173 aTextPos += aVisArea.TopLeft(); // position in the edit document
3175 EPosition aDocPosition = pEditEngine->FindDocPosition(aTextPos);
3176 ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex);
3177 ESelection aSelection = pEditView->GetSelection();
3178 aSelection.Adjust(); // needed for IsLess/IsGreater
3179 if ( aCompare.IsLess(aSelection) || aCompare.IsGreater(aSelection) )
3181 // clicked outside the selected text - deselect and move text cursor
3182 MouseEvent aEvent( rPosPixel );
3183 pEditView->MouseButtonDown( aEvent );
3184 pEditView->MouseButtonUp( aEvent );
3185 pScMod->InputSelection( pEditView );
3188 return; // clicked within the edit view - keep edit mode
3190 else
3192 // outside of the edit view - end edit mode, regardless of cell selection, then continue
3193 pScMod->InputEnterHandler();
3197 // check draw text edit mode
3199 Point aLogicPos = PixelToLogic( rPosPixel ); // after cell edit mode is ended
3200 if ( pDrawView && pDrawView->GetTextEditObject() && pDrawView->GetTextEditOutlinerView() )
3202 OutlinerView* pOlView = pDrawView->GetTextEditOutlinerView();
3203 Rectangle aOutputArea = pOlView->GetOutputArea();
3204 if ( aOutputArea.IsInside( aLogicPos ) )
3206 // handle selection within the OutlinerView
3208 Outliner* pOutliner = pOlView->GetOutliner();
3209 const EditEngine& rEditEngine = pOutliner->GetEditEngine();
3210 Rectangle aVisArea = pOlView->GetVisArea();
3212 Point aTextPos = aLogicPos;
3213 if ( pOutliner->IsVertical() ) // have to manually transform position
3215 aTextPos -= aOutputArea.TopRight();
3216 long nTemp = -aTextPos.X();
3217 aTextPos.X() = aTextPos.Y();
3218 aTextPos.Y() = nTemp;
3220 else
3221 aTextPos -= aOutputArea.TopLeft();
3222 aTextPos += aVisArea.TopLeft(); // position in the edit document
3224 EPosition aDocPosition = rEditEngine.FindDocPosition(aTextPos);
3225 ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex);
3226 ESelection aSelection = pOlView->GetSelection();
3227 aSelection.Adjust(); // needed for IsLess/IsGreater
3228 if ( aCompare.IsLess(aSelection) || aCompare.IsGreater(aSelection) )
3230 // clicked outside the selected text - deselect and move text cursor
3231 // use DrawView to allow extra handling there (none currently)
3232 MouseEvent aEvent( rPosPixel );
3233 pDrawView->MouseButtonDown( aEvent, this );
3234 pDrawView->MouseButtonUp( aEvent, this );
3237 return; // clicked within the edit area - keep edit mode
3239 else
3241 // Outside of the edit area - end text edit mode, then continue.
3242 // DrawDeselectAll also ends text edit mode and updates the shells.
3243 // If the click was on the edited object, it will be selected again below.
3244 pView->DrawDeselectAll();
3248 // look for existing selection
3250 bool bHitSelected = false;
3251 if ( pDrawView && pDrawView->IsMarkedObjHit( aLogicPos ) )
3253 // clicked on selected object -> don't change anything
3254 bHitSelected = true;
3256 else if ( pViewData->GetMarkData().IsCellMarked(nCellX, nCellY) )
3258 // clicked on selected cell -> don't change anything
3259 bHitSelected = true;
3262 // select drawing object or move cell cursor
3264 if ( !bHitSelected )
3266 bool bWasDraw = ( pDrawView && pDrawView->AreObjectsMarked() );
3267 bool bHitDraw = false;
3268 if ( pDrawView )
3270 pDrawView->UnmarkAllObj();
3271 // Unlock the Internal Layer in order to activate the context menu.
3272 // re-lock in ScDrawView::MarkListHasChanged()
3273 lcl_UnLockComment( pDrawView, aLogicPos ,pViewData);
3274 bHitDraw = pDrawView->MarkObj( aLogicPos );
3275 // draw shell is activated in MarkListHasChanged
3277 if ( !bHitDraw )
3279 pView->Unmark();
3280 pView->SetCursor(nCellX, nCellY);
3281 if ( bWasDraw )
3282 pViewData->GetViewShell()->SetDrawShell( false ); // switch shells
3287 void ScGridWindow::KeyInput(const KeyEvent& rKEvt)
3289 // Cursor control for ref input dialog
3290 const KeyCode& rKeyCode = rKEvt.GetKeyCode();
3291 if( SC_MOD()->IsRefDialogOpen() )
3293 if( !rKeyCode.GetModifier() && (rKeyCode.GetCode() == KEY_F2) )
3295 SC_MOD()->EndReference();
3297 else if( pViewData->GetViewShell()->MoveCursorKeyInput( rKEvt ) )
3299 ScRange aRef(
3300 pViewData->GetRefStartX(), pViewData->GetRefStartY(), pViewData->GetRefStartZ(),
3301 pViewData->GetRefEndX(), pViewData->GetRefEndY(), pViewData->GetRefEndZ() );
3302 SC_MOD()->SetReference( aRef, pViewData->GetDocument() );
3304 pViewData->GetViewShell()->SelectionChanged();
3305 return ;
3307 else if( rKeyCode.GetCode() == KEY_RETURN && pViewData->IsPasteMode() )
3309 ScTabViewShell* pTabViewShell = pViewData->GetViewShell();
3310 ScClipUtil::PasteFromClipboard( pViewData, pTabViewShell, false );
3312 // Clear clipboard content.
3313 uno::Reference<datatransfer::clipboard::XClipboard> xSystemClipboard =
3314 TransferableHelper::GetSystemClipboard();
3315 if (xSystemClipboard.is())
3317 xSystemClipboard->setContents(
3318 uno::Reference<datatransfer::XTransferable>(),
3319 uno::Reference<datatransfer::clipboard::XClipboardOwner>());
3322 // hide the border around the copy source
3323 pViewData->SetPasteMode( SC_PASTE_NONE );
3324 // Clear CopySourceOverlay in each window of a split/frozen tabview
3325 pViewData->GetView()->UpdateCopySourceOverlay();
3326 return;
3328 // wenn semi-Modeless-SfxChildWindow-Dialog oben, keine KeyInputs:
3329 else if( !pViewData->IsAnyFillMode() )
3331 if (rKeyCode.GetCode() == KEY_ESCAPE)
3333 pViewData->SetPasteMode( SC_PASTE_NONE );
3334 // Clear CopySourceOverlay in each window of a split/frozen tabview
3335 pViewData->GetView()->UpdateCopySourceOverlay();
3337 // query for existing note marker before calling ViewShell's keyboard handling
3338 // which may remove the marker
3339 bool bHadKeyMarker = ( pNoteMarker && pNoteMarker->IsByKeyboard() );
3340 ScTabViewShell* pViewSh = pViewData->GetViewShell();
3342 if (pViewData->GetDocShell()->GetProgress())
3343 return;
3345 if (DrawKeyInput(rKEvt))
3347 const KeyCode& rLclKeyCode = rKEvt.GetKeyCode();
3348 if (rLclKeyCode.GetCode() == KEY_DOWN
3349 || rLclKeyCode.GetCode() == KEY_UP
3350 || rLclKeyCode.GetCode() == KEY_LEFT
3351 || rLclKeyCode.GetCode() == KEY_RIGHT)
3353 ScTabViewShell* pViewShell = pViewData->GetViewShell();
3354 SfxBindings& rBindings = pViewShell->GetViewFrame()->GetBindings();
3355 rBindings.Invalidate(SID_ATTR_TRANSFORM_POS_X);
3356 rBindings.Invalidate(SID_ATTR_TRANSFORM_POS_Y);
3358 return;
3361 if (!pViewData->GetView()->IsDrawSelMode() && !DrawHasMarkedObj()) // keine Eingaben im Zeichenmodus
3362 { //! DrawShell abfragen !!!
3363 if (pViewSh->TabKeyInput(rKEvt))
3364 return;
3366 else
3367 if (pViewSh->SfxViewShell::KeyInput(rKEvt)) // von SfxViewShell
3368 return;
3370 KeyCode aCode = rKEvt.GetKeyCode();
3371 if ( aCode.GetCode() == KEY_ESCAPE && aCode.GetModifier() == 0 )
3373 if ( bHadKeyMarker )
3374 HideNoteMarker();
3375 else
3376 pViewSh->Escape();
3377 return;
3379 if ( aCode.GetCode() == KEY_F1 && aCode.GetModifier() == KEY_MOD1 )
3381 // ctrl-F1 shows or hides the note or redlining info for the cursor position
3382 // (hard-coded because F1 can't be configured)
3384 if ( bHadKeyMarker )
3385 HideNoteMarker(); // hide when previously visible
3386 else
3387 ShowNoteMarker( pViewData->GetCurX(), pViewData->GetCurY(), true );
3388 return;
3390 if (aCode.GetCode() == KEY_BRACKETLEFT && aCode.GetModifier() == KEY_MOD1)
3392 pViewSh->DetectiveMarkPred();
3393 return;
3395 if (aCode.GetCode() == KEY_BRACKETRIGHT && aCode.GetModifier() == KEY_MOD1)
3397 pViewSh->DetectiveMarkSucc();
3398 return;
3403 Window::KeyInput(rKEvt);
3406 void ScGridWindow::StopMarking()
3408 DrawEndAction(); // Markieren/Verschieben auf Drawing-Layer abbrechen
3410 if (nButtonDown)
3412 pViewData->GetMarkData().SetMarking(false);
3413 nMouseStatus = SC_GM_IGNORE;
3417 void ScGridWindow::UpdateInputContext()
3419 bool bReadOnly = pViewData->GetDocShell()->IsReadOnly();
3420 sal_uLong nOptions = bReadOnly ? 0 : ( INPUTCONTEXT_TEXT | INPUTCONTEXT_EXTTEXTINPUT );
3422 // when font from InputContext is used,
3423 // it must be taken from the cursor position's cell attributes
3425 InputContext aContext;
3426 aContext.SetOptions( nOptions );
3427 SetInputContext( aContext );
3430 // sensitiver Bereich (Pixel)
3431 #define SCROLL_SENSITIVE 20
3433 bool ScGridWindow::DropScroll( const Point& rMousePos )
3435 SCsCOL nDx = 0;
3436 SCsROW nDy = 0;
3437 Size aSize = GetOutputSizePixel();
3439 if (aSize.Width() > SCROLL_SENSITIVE * 3)
3441 if ( rMousePos.X() < SCROLL_SENSITIVE && pViewData->GetPosX(WhichH(eWhich)) > 0 )
3442 nDx = -1;
3443 if ( rMousePos.X() >= aSize.Width() - SCROLL_SENSITIVE
3444 && pViewData->GetPosX(WhichH(eWhich)) < MAXCOL )
3445 nDx = 1;
3447 if (aSize.Height() > SCROLL_SENSITIVE * 3)
3449 if ( rMousePos.Y() < SCROLL_SENSITIVE && pViewData->GetPosY(WhichV(eWhich)) > 0 )
3450 nDy = -1;
3451 if ( rMousePos.Y() >= aSize.Height() - SCROLL_SENSITIVE
3452 && pViewData->GetPosY(WhichV(eWhich)) < MAXROW )
3453 nDy = 1;
3456 if ( nDx != 0 || nDy != 0 )
3458 if ( nDx != 0 )
3459 pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) );
3460 if ( nDy != 0 )
3461 pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) );
3464 return false;
3467 static bool lcl_TestScenarioRedliningDrop( ScDocument* pDoc, const ScRange& aDragRange)
3469 // Testet, ob bei eingeschalteten RedLining,
3470 // bei einem Drop ein Scenario betroffen ist.
3472 bool bReturn = false;
3473 SCTAB nTab = aDragRange.aStart.Tab();
3474 SCTAB nTabCount = pDoc->GetTableCount();
3476 if(pDoc->GetChangeTrack()!=NULL)
3478 if( pDoc->IsScenario(nTab) && pDoc->HasScenarioRange(nTab, aDragRange))
3480 bReturn = true;
3482 else
3484 for(SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
3486 if(pDoc->HasScenarioRange(i, aDragRange))
3488 bReturn = true;
3489 break;
3494 return bReturn;
3497 static ScRange lcl_MakeDropRange( SCCOL nPosX, SCROW nPosY, SCTAB nTab, const ScRange& rSource )
3499 SCCOL nCol1 = nPosX;
3500 SCCOL nCol2 = nCol1 + ( rSource.aEnd.Col() - rSource.aStart.Col() );
3501 if ( nCol2 > MAXCOL )
3503 nCol1 -= nCol2 - MAXCOL;
3504 nCol2 = MAXCOL;
3506 SCROW nRow1 = nPosY;
3507 SCROW nRow2 = nRow1 + ( rSource.aEnd.Row() - rSource.aStart.Row() );
3508 if ( nRow2 > MAXROW )
3510 nRow1 -= nRow2 - MAXROW;
3511 nRow2 = MAXROW;
3514 return ScRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab );
3517 extern bool bPasteIsDrop; // viewfun4 -> move to header
3518 extern bool bPasteIsMove; // viewfun7 -> move to header
3520 sal_Int8 ScGridWindow::AcceptPrivateDrop( const AcceptDropEvent& rEvt )
3522 if ( rEvt.mbLeaving )
3524 bDragRect = false;
3525 UpdateDragRectOverlay();
3526 return rEvt.mnAction;
3529 const ScDragData& rData = SC_MOD()->GetDragData();
3530 if ( rData.pCellTransfer )
3532 // Don't move source that would include filtered rows.
3533 if ((rEvt.mnAction & DND_ACTION_MOVE) && rData.pCellTransfer->HasFilteredRows())
3535 if (bDragRect)
3537 bDragRect = false;
3538 UpdateDragRectOverlay();
3540 return DND_ACTION_NONE;
3543 Point aPos = rEvt.maPosPixel;
3545 ScDocument* pSourceDoc = rData.pCellTransfer->GetSourceDocument();
3546 ScDocument* pThisDoc = pViewData->GetDocument();
3547 if (pSourceDoc == pThisDoc)
3549 OUString aName;
3550 if ( pThisDoc->HasChartAtPoint(pViewData->GetTabNo(), PixelToLogic(aPos), aName ))
3552 if (bDragRect) // Rechteck loeschen
3554 bDragRect = false;
3555 UpdateDragRectOverlay();
3558 //! highlight chart? (selection border?)
3560 sal_Int8 nRet = rEvt.mnAction;
3561 return nRet;
3565 if ( rData.pCellTransfer->GetDragSourceFlags() & SC_DROP_TABLE ) // whole sheet?
3567 bool bOk = pThisDoc->IsDocEditable();
3568 return bOk ? rEvt.mnAction : 0; // don't draw selection frame
3571 SCsCOL nPosX;
3572 SCsROW nPosY;
3573 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
3575 ScRange aSourceRange = rData.pCellTransfer->GetRange();
3576 SCCOL nSourceStartX = aSourceRange.aStart.Col();
3577 SCROW nSourceStartY = aSourceRange.aStart.Row();
3578 SCCOL nSourceEndX = aSourceRange.aEnd.Col();
3579 SCROW nSourceEndY = aSourceRange.aEnd.Row();
3580 SCCOL nSizeX = nSourceEndX - nSourceStartX + 1;
3581 SCROW nSizeY = nSourceEndY - nSourceStartY + 1;
3583 if ( rEvt.mnAction != DND_ACTION_MOVE )
3584 nSizeY = rData.pCellTransfer->GetNonFilteredRows(); // copy/link: no filtered rows
3586 SCsCOL nNewDragX = nPosX - rData.pCellTransfer->GetDragHandleX();
3587 if (nNewDragX<0) nNewDragX=0;
3588 if (nNewDragX+(nSizeX-1) > MAXCOL)
3589 nNewDragX = MAXCOL-(nSizeX-1);
3590 SCsROW nNewDragY = nPosY - rData.pCellTransfer->GetDragHandleY();
3591 if (nNewDragY<0) nNewDragY=0;
3592 if (nNewDragY+(nSizeY-1) > MAXROW)
3593 nNewDragY = MAXROW-(nSizeY-1);
3595 // don't break scenario ranges, don't drop on filtered
3596 SCTAB nTab = pViewData->GetTabNo();
3597 ScRange aDropRange = lcl_MakeDropRange( nNewDragX, nNewDragY, nTab, aSourceRange );
3598 if ( lcl_TestScenarioRedliningDrop( pThisDoc, aDropRange ) ||
3599 lcl_TestScenarioRedliningDrop( pSourceDoc, aSourceRange ) ||
3600 ScViewUtil::HasFiltered( aDropRange, pThisDoc) )
3602 if (bDragRect)
3604 bDragRect = false;
3605 UpdateDragRectOverlay();
3607 return DND_ACTION_NONE;
3610 InsCellCmd eDragInsertMode = INS_NONE;
3611 Window::PointerState aState = GetPointerState();
3613 // check for datapilot item sorting
3614 ScDPObject* pDPObj = NULL;
3615 if ( pThisDoc == pSourceDoc && ( pDPObj = pThisDoc->GetDPAtCursor( nNewDragX, nNewDragY, nTab ) ) != NULL )
3617 // drop on DataPilot table: sort or nothing
3619 bool bDPSort = false;
3620 if ( pThisDoc->GetDPAtCursor( nSourceStartX, nSourceStartY, aSourceRange.aStart.Tab() ) == pDPObj )
3622 sheet::DataPilotTableHeaderData aDestData;
3623 pDPObj->GetHeaderPositionData( ScAddress(nNewDragX, nNewDragY, nTab), aDestData );
3624 bool bValid = ( aDestData.Dimension >= 0 ); // dropping onto a field
3626 // look through the source range
3627 for (SCROW nRow = aSourceRange.aStart.Row(); bValid && nRow <= aSourceRange.aEnd.Row(); ++nRow )
3628 for (SCCOL nCol = aSourceRange.aStart.Col(); bValid && nCol <= aSourceRange.aEnd.Col(); ++nCol )
3630 sheet::DataPilotTableHeaderData aSourceData;
3631 pDPObj->GetHeaderPositionData( ScAddress( nCol, nRow, aSourceRange.aStart.Tab() ), aSourceData );
3632 if ( aSourceData.Dimension != aDestData.Dimension || aSourceData.MemberName.isEmpty() )
3633 bValid = false; // empty (subtotal) or different field
3636 if ( bValid )
3638 bool bIsDataLayout;
3639 OUString aDimName = pDPObj->GetDimName( aDestData.Dimension, bIsDataLayout );
3640 const ScDPSaveDimension* pDim = pDPObj->GetSaveData()->GetExistingDimensionByName( aDimName );
3641 if ( pDim )
3643 ScRange aOutRange = pDPObj->GetOutRange();
3645 sal_uInt16 nOrient = pDim->GetOrientation();
3646 if ( nOrient == sheet::DataPilotFieldOrientation_COLUMN )
3648 eDragInsertMode = INS_CELLSRIGHT;
3649 nSizeY = aOutRange.aEnd.Row() - nNewDragY + 1;
3650 bDPSort = true;
3652 else if ( nOrient == sheet::DataPilotFieldOrientation_ROW )
3654 eDragInsertMode = INS_CELLSDOWN;
3655 nSizeX = aOutRange.aEnd.Col() - nNewDragX + 1;
3656 bDPSort = true;
3662 if ( !bDPSort )
3664 // no valid sorting in a DataPilot table -> disallow
3665 if ( bDragRect )
3667 bDragRect = false;
3668 UpdateDragRectOverlay();
3670 return DND_ACTION_NONE;
3673 else if ( aState.mnState & KEY_MOD2 )
3675 if ( pThisDoc == pSourceDoc && nTab == aSourceRange.aStart.Tab() )
3677 long nDeltaX = labs( static_cast< long >( nNewDragX - nSourceStartX ) );
3678 long nDeltaY = labs( static_cast< long >( nNewDragY - nSourceStartY ) );
3679 if ( nDeltaX <= nDeltaY )
3681 eDragInsertMode = INS_CELLSDOWN;
3683 else
3685 eDragInsertMode = INS_CELLSRIGHT;
3688 if ( ( eDragInsertMode == INS_CELLSDOWN && nNewDragY <= nSourceEndY &&
3689 ( nNewDragX + nSizeX - 1 ) >= nSourceStartX && nNewDragX <= nSourceEndX &&
3690 ( nNewDragX != nSourceStartX || nNewDragY >= nSourceStartY ) ) ||
3691 ( eDragInsertMode == INS_CELLSRIGHT && nNewDragX <= nSourceEndX &&
3692 ( nNewDragY + nSizeY - 1 ) >= nSourceStartY && nNewDragY <= nSourceEndY &&
3693 ( nNewDragY != nSourceStartY || nNewDragX >= nSourceStartX ) ) )
3695 if ( bDragRect )
3697 bDragRect = false;
3698 UpdateDragRectOverlay();
3700 return DND_ACTION_NONE;
3703 else
3705 if ( static_cast< long >( nSizeX ) >= static_cast< long >( nSizeY ) )
3707 eDragInsertMode = INS_CELLSDOWN;
3710 else
3712 eDragInsertMode = INS_CELLSRIGHT;
3717 if ( nNewDragX != (SCsCOL) nDragStartX || nNewDragY != (SCsROW) nDragStartY ||
3718 nDragStartX+nSizeX-1 != nDragEndX || nDragStartY+nSizeY-1 != nDragEndY ||
3719 !bDragRect || eDragInsertMode != meDragInsertMode )
3721 nDragStartX = nNewDragX;
3722 nDragStartY = nNewDragY;
3723 nDragEndX = nDragStartX+nSizeX-1;
3724 nDragEndY = nDragStartY+nSizeY-1;
3725 bDragRect = true;
3726 meDragInsertMode = eDragInsertMode;
3728 UpdateDragRectOverlay();
3732 return rEvt.mnAction;
3735 sal_Int8 ScGridWindow::AcceptDrop( const AcceptDropEvent& rEvt )
3737 const ScDragData& rData = SC_MOD()->GetDragData();
3738 if ( rEvt.mbLeaving )
3740 DrawMarkDropObj( NULL );
3741 if ( rData.pCellTransfer )
3742 return AcceptPrivateDrop( rEvt ); // hide drop marker for internal D&D
3743 else
3744 return rEvt.mnAction;
3747 if ( pViewData->GetDocShell()->IsReadOnly() )
3748 return DND_ACTION_NONE;
3751 sal_Int8 nRet = DND_ACTION_NONE;
3753 if (rData.pCellTransfer)
3755 ScRange aSource = rData.pCellTransfer->GetRange();
3756 if ( aSource.aStart.Col() != 0 || aSource.aEnd.Col() != MAXCOL ||
3757 aSource.aStart.Row() != 0 || aSource.aEnd.Row() != MAXROW )
3758 DropScroll( rEvt.maPosPixel );
3760 nRet = AcceptPrivateDrop( rEvt );
3762 else
3764 if ( !rData.aLinkDoc.isEmpty() )
3766 OUString aThisName;
3767 ScDocShell* pDocSh = pViewData->GetDocShell();
3768 if (pDocSh && pDocSh->HasName())
3769 aThisName = pDocSh->GetMedium()->GetName();
3771 if ( !rData.aLinkDoc.equals(aThisName) )
3772 nRet = rEvt.mnAction;
3774 else if (!rData.aJumpTarget.isEmpty())
3776 // internal bookmarks (from Navigator)
3777 // local jumps from an unnamed document are possible only within a document
3779 if ( !rData.pJumpLocalDoc || rData.pJumpLocalDoc == pViewData->GetDocument() )
3780 nRet = rEvt.mnAction;
3782 else
3784 sal_Int8 nMyAction = rEvt.mnAction;
3786 // clear DND_ACTION_LINK when other actions are set. The usage below cannot handle
3787 // multiple set values
3788 if((nMyAction & DND_ACTION_LINK) && (nMyAction & (DND_ACTION_COPYMOVE)))
3790 nMyAction &= ~DND_ACTION_LINK;
3793 if ( !rData.pDrawTransfer ||
3794 !IsMyModel(rData.pDrawTransfer->GetDragSourceView()) ) // drawing within the document
3795 if ( rEvt.mbDefault && nMyAction == DND_ACTION_MOVE )
3796 nMyAction = DND_ACTION_COPY;
3798 ScDocument* pThisDoc = pViewData->GetDocument();
3799 SdrObject* pHitObj = pThisDoc->GetObjectAtPoint(
3800 pViewData->GetTabNo(), PixelToLogic(rEvt.maPosPixel) );
3801 if ( pHitObj && nMyAction == DND_ACTION_LINK ) // && !rData.pDrawTransfer )
3803 if ( IsDropFormatSupported(SOT_FORMATSTR_ID_SVXB)
3804 || IsDropFormatSupported(SOT_FORMAT_GDIMETAFILE)
3805 || IsDropFormatSupported(SOT_FORMATSTR_ID_PNG)
3806 || IsDropFormatSupported(SOT_FORMAT_BITMAP) )
3808 // graphic dragged onto drawing object
3809 DrawMarkDropObj( pHitObj );
3810 nRet = nMyAction;
3813 if (!nRet)
3814 DrawMarkDropObj( NULL );
3816 if (!nRet)
3818 switch ( nMyAction )
3820 case DND_ACTION_COPY:
3821 case DND_ACTION_MOVE:
3822 case DND_ACTION_COPYMOVE:
3824 bool bMove = ( nMyAction == DND_ACTION_MOVE );
3825 if ( IsDropFormatSupported( SOT_FORMATSTR_ID_EMBED_SOURCE ) ||
3826 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE ) ||
3827 IsDropFormatSupported( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) ||
3828 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ||
3829 IsDropFormatSupported( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) ||
3830 IsDropFormatSupported( SOT_FORMAT_STRING ) ||
3831 IsDropFormatSupported( SOT_FORMATSTR_ID_SYLK ) ||
3832 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK ) ||
3833 IsDropFormatSupported( SOT_FORMATSTR_ID_HTML ) ||
3834 IsDropFormatSupported( SOT_FORMATSTR_ID_HTML_SIMPLE ) ||
3835 IsDropFormatSupported( SOT_FORMATSTR_ID_DIF ) ||
3836 IsDropFormatSupported( SOT_FORMATSTR_ID_DRAWING ) ||
3837 IsDropFormatSupported( SOT_FORMATSTR_ID_SVXB ) ||
3838 IsDropFormatSupported( SOT_FORMAT_RTF ) ||
3839 IsDropFormatSupported( SOT_FORMAT_GDIMETAFILE ) ||
3840 IsDropFormatSupported( SOT_FORMATSTR_ID_PNG ) ||
3841 IsDropFormatSupported( SOT_FORMAT_BITMAP ) ||
3842 IsDropFormatSupported( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) ||
3843 IsDropFormatSupported( SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE ) ||
3844 ( !bMove && (
3845 IsDropFormatSupported( SOT_FORMAT_FILE_LIST ) ||
3846 IsDropFormatSupported( SOT_FORMAT_FILE ) ||
3847 IsDropFormatSupported( SOT_FORMATSTR_ID_SOLK ) ||
3848 IsDropFormatSupported( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) ||
3849 IsDropFormatSupported( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) ||
3850 IsDropFormatSupported( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) ) ) )
3852 nRet = nMyAction;
3855 break;
3856 case DND_ACTION_LINK:
3857 if ( IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE ) ||
3858 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ||
3859 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK ) ||
3860 IsDropFormatSupported( SOT_FORMAT_FILE_LIST ) ||
3861 IsDropFormatSupported( SOT_FORMAT_FILE ) ||
3862 IsDropFormatSupported( SOT_FORMATSTR_ID_SOLK ) ||
3863 IsDropFormatSupported( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) ||
3864 IsDropFormatSupported( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) ||
3865 IsDropFormatSupported( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
3867 nRet = nMyAction;
3869 break;
3872 if ( nRet )
3874 // Simple check for protection: It's not known here if the drop will result
3875 // in cells or drawing objects (some formats can be both) and how many cells
3876 // the result will be. But if IsFormatEditable for the drop cell position
3877 // is sal_False (ignores matrix formulas), nothing can be pasted, so the drop
3878 // can already be rejected here.
3880 Point aPos = rEvt.maPosPixel;
3881 SCsCOL nPosX;
3882 SCsROW nPosY;
3883 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
3884 SCTAB nTab = pViewData->GetTabNo();
3885 ScDocument* pDoc = pViewData->GetDocument();
3887 ScEditableTester aTester( pDoc, nTab, nPosX,nPosY, nPosX,nPosY );
3888 if ( !aTester.IsFormatEditable() )
3889 nRet = DND_ACTION_NONE; // forbidden
3894 // scroll only for accepted formats
3895 if (nRet)
3896 DropScroll( rEvt.maPosPixel );
3899 return nRet;
3902 static sal_uLong lcl_GetDropFormatId( const uno::Reference<datatransfer::XTransferable>& xTransfer, bool bPreferText = false )
3904 TransferableDataHelper aDataHelper( xTransfer );
3906 if ( !aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) )
3908 // use bookmark formats if no sba is present
3910 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SOLK ) )
3911 return SOT_FORMATSTR_ID_SOLK;
3912 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) )
3913 return SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR;
3914 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) )
3915 return SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK;
3916 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
3917 return SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR;
3920 sal_uLong nFormatId = 0;
3921 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING ) )
3922 nFormatId = SOT_FORMATSTR_ID_DRAWING;
3923 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ) )
3924 nFormatId = SOT_FORMATSTR_ID_SVXB;
3925 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ) )
3927 // If it's a Writer object, insert RTF instead of OLE
3929 bool bDoRtf = false;
3930 SotStorageStreamRef xStm;
3931 TransferableObjectDescriptor aObjDesc;
3932 if( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) &&
3933 aDataHelper.GetSotStorageStream( SOT_FORMATSTR_ID_EMBED_SOURCE, xStm ) )
3935 SotStorageRef xStore( new SotStorage( *xStm ) );
3936 bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) ||
3937 aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) )
3938 && aDataHelper.HasFormat( SOT_FORMAT_RTF ) );
3940 if ( bDoRtf )
3941 nFormatId = FORMAT_RTF;
3942 else
3943 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE;
3945 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) )
3946 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE;
3947 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) )
3948 nFormatId = SOT_FORMATSTR_ID_SBA_DATAEXCHANGE;
3949 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE ) )
3950 nFormatId = SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE;
3951 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_BIFF_8 ) )
3952 nFormatId = SOT_FORMATSTR_ID_BIFF_8;
3953 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_BIFF_5 ) )
3954 nFormatId = SOT_FORMATSTR_ID_BIFF_5;
3955 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) )
3956 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE_OLE;
3957 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) )
3958 nFormatId = SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE;
3959 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) )
3960 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE;
3961 else if ( aDataHelper.HasFormat( SOT_FORMAT_RTF ) )
3962 nFormatId = SOT_FORMAT_RTF;
3963 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_HTML ) )
3964 nFormatId = SOT_FORMATSTR_ID_HTML;
3965 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_HTML_SIMPLE ) )
3966 nFormatId = SOT_FORMATSTR_ID_HTML_SIMPLE;
3967 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SYLK ) )
3968 nFormatId = SOT_FORMATSTR_ID_SYLK;
3969 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK ) )
3970 nFormatId = SOT_FORMATSTR_ID_LINK;
3971 else if ( bPreferText && aDataHelper.HasFormat( SOT_FORMAT_STRING ) ) // #i86734# the behaviour introduced in #i62773# is wrong when pasting
3972 nFormatId = SOT_FORMAT_STRING;
3973 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) )
3974 nFormatId = SOT_FORMAT_FILE_LIST;
3975 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE ) ) // #i62773# FILE_LIST/FILE before STRING (Unix file managers)
3976 nFormatId = SOT_FORMAT_FILE;
3977 else if ( aDataHelper.HasFormat( SOT_FORMAT_STRING ) )
3978 nFormatId = SOT_FORMAT_STRING;
3979 else if ( aDataHelper.HasFormat( SOT_FORMAT_GDIMETAFILE ) )
3980 nFormatId = SOT_FORMAT_GDIMETAFILE;
3981 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_PNG ) )
3982 nFormatId = SOT_FORMATSTR_ID_PNG;
3983 else if ( aDataHelper.HasFormat( SOT_FORMAT_BITMAP ) )
3984 nFormatId = SOT_FORMAT_BITMAP;
3986 return nFormatId;
3989 static sal_uLong lcl_GetDropLinkId( const uno::Reference<datatransfer::XTransferable>& xTransfer )
3991 TransferableDataHelper aDataHelper( xTransfer );
3993 sal_uLong nFormatId = 0;
3994 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) )
3995 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE;
3996 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) )
3997 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE;
3998 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK ) )
3999 nFormatId = SOT_FORMATSTR_ID_LINK;
4000 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) )
4001 nFormatId = SOT_FORMAT_FILE_LIST;
4002 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE ) )
4003 nFormatId = SOT_FORMAT_FILE;
4004 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SOLK ) )
4005 nFormatId = SOT_FORMATSTR_ID_SOLK;
4006 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) )
4007 nFormatId = SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR;
4008 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) )
4009 nFormatId = SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK;
4010 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) )
4011 nFormatId = SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR;
4013 return nFormatId;
4017 sal_Int8 ScGridWindow::ExecutePrivateDrop( const ExecuteDropEvent& rEvt )
4019 // hide drop marker
4020 bDragRect = false;
4021 UpdateDragRectOverlay();
4023 ScModule* pScMod = SC_MOD();
4024 const ScDragData& rData = pScMod->GetDragData();
4026 return DropTransferObj( rData.pCellTransfer, nDragStartX, nDragStartY,
4027 PixelToLogic(rEvt.maPosPixel), rEvt.mnAction );
4030 sal_Int8 ScGridWindow::DropTransferObj( ScTransferObj* pTransObj, SCCOL nDestPosX, SCROW nDestPosY,
4031 const Point& rLogicPos, sal_Int8 nDndAction )
4033 if ( !pTransObj )
4034 return 0;
4036 ScDocument* pSourceDoc = pTransObj->GetSourceDocument();
4037 ScDocShell* pDocSh = pViewData->GetDocShell();
4038 ScDocument* pThisDoc = pViewData->GetDocument();
4039 ScViewFunc* pView = pViewData->GetView();
4040 SCTAB nThisTab = pViewData->GetTabNo();
4041 sal_uInt16 nFlags = pTransObj->GetDragSourceFlags();
4043 bool bIsNavi = ( nFlags & SC_DROP_NAVIGATOR ) != 0;
4044 bool bIsMove = ( nDndAction == DND_ACTION_MOVE && !bIsNavi );
4046 // workaround for wrong nDndAction on Windows when pressing solely
4047 // the Alt key during drag and drop;
4048 // can be removed after #i79215# has been fixed
4049 if ( meDragInsertMode != INS_NONE )
4051 bIsMove = ( nDndAction & DND_ACTION_MOVE && !bIsNavi );
4054 bool bIsLink = ( nDndAction == DND_ACTION_LINK );
4056 ScRange aSource = pTransObj->GetRange();
4058 // only use visible tab from source range - when dragging within one table,
4059 // all selected tables at the time of dropping are used (handled in MoveBlockTo)
4060 SCTAB nSourceTab = pTransObj->GetVisibleTab();
4061 aSource.aStart.SetTab( nSourceTab );
4062 aSource.aEnd.SetTab( nSourceTab );
4064 SCCOL nSizeX = aSource.aEnd.Col() - aSource.aStart.Col() + 1;
4065 SCROW nSizeY = (bIsMove ? (aSource.aEnd.Row() - aSource.aStart.Row() + 1) :
4066 pTransObj->GetNonFilteredRows()); // copy/link: no filtered rows
4067 ScRange aDest( nDestPosX, nDestPosY, nThisTab,
4068 nDestPosX + nSizeX - 1, nDestPosY + nSizeY - 1, nThisTab );
4071 /* NOTE: AcceptPrivateDrop() already checked for filtered conditions during
4072 * dragging and adapted drawing of the selection frame. We check here
4073 * (again) because this may actually also be called from PasteSelection(),
4074 * we would have to duplicate determination of flags and destination range
4075 * and would lose the context of the "filtered destination is OK" cases
4076 * below, which is already awkward enough as is. */
4078 // Don't move filtered source.
4079 bool bFiltered = (bIsMove && pTransObj->HasFilteredRows());
4080 if (!bFiltered)
4082 if (pSourceDoc != pThisDoc && ((nFlags & SC_DROP_TABLE) ||
4083 (!bIsLink && meDragInsertMode == INS_NONE)))
4085 // Nothing. Either entire sheet to be dropped, or the one case
4086 // where PasteFromClip() is to be called that handles a filtered
4087 // destination itself. Drag-copy from another document without
4088 // inserting cells.
4090 else
4091 // Don't copy or move to filtered destination.
4092 bFiltered = ScViewUtil::HasFiltered( aDest, pThisDoc);
4095 bool bDone = false;
4097 if (!bFiltered && pSourceDoc == pThisDoc)
4099 if ( nFlags & SC_DROP_TABLE ) // whole sheet?
4101 if ( pThisDoc->IsDocEditable() )
4103 SCTAB nSrcTab = aSource.aStart.Tab();
4104 pViewData->GetDocShell()->MoveTable( nSrcTab, nThisTab, !bIsMove, true ); // with Undo
4105 pView->SetTabNo( nThisTab, true );
4106 bDone = true;
4109 else // move/copy block
4111 OUString aChartName;
4112 if (pThisDoc->HasChartAtPoint( nThisTab, rLogicPos, aChartName ))
4114 OUString aRangeName(aSource.Format(SCR_ABS_3D, pThisDoc));
4115 SfxStringItem aNameItem( SID_CHART_NAME, aChartName );
4116 SfxStringItem aRangeItem( SID_CHART_SOURCE, aRangeName );
4117 sal_uInt16 nId = bIsMove ? SID_CHART_SOURCE : SID_CHART_ADDSOURCE;
4118 pViewData->GetDispatcher().Execute( nId, SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD,
4119 &aRangeItem, &aNameItem, (void*) NULL );
4120 bDone = true;
4122 else if ( pThisDoc->GetDPAtCursor( nDestPosX, nDestPosY, nThisTab ) )
4124 // drop on DataPilot table: try to sort, fail if that isn't possible
4126 ScAddress aDestPos( nDestPosX, nDestPosY, nThisTab );
4127 if ( aDestPos != aSource.aStart )
4128 bDone = pViewData->GetView()->DataPilotMove( aSource, aDestPos );
4129 else
4130 bDone = true; // same position: nothing
4132 else if ( nDestPosX != aSource.aStart.Col() || nDestPosY != aSource.aStart.Row() ||
4133 nSourceTab != nThisTab )
4135 OUString aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY );
4136 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
4138 SCsCOL nCorrectCursorPosCol = 0;
4139 SCsROW nCorrectCursorPosRow = 0;
4141 bDone = true;
4142 if ( meDragInsertMode != INS_NONE )
4144 // call with bApi = sal_True to avoid error messages in drop handler
4145 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, true /*bRecord*/, true /*bApi*/, true /*bPartOfPaste*/ );
4146 if ( bDone )
4148 if ( nThisTab == nSourceTab )
4150 if ( meDragInsertMode == INS_CELLSDOWN &&
4151 nDestPosX == aSource.aStart.Col() && nDestPosY < aSource.aStart.Row() )
4153 bDone = aSource.Move( 0, nSizeY, 0, pSourceDoc );
4154 nCorrectCursorPosRow = nSizeY;
4156 else if ( meDragInsertMode == INS_CELLSRIGHT &&
4157 nDestPosY == aSource.aStart.Row() && nDestPosX < aSource.aStart.Col() )
4159 bDone = aSource.Move( nSizeX, 0, 0, pSourceDoc );
4160 nCorrectCursorPosCol = nSizeX;
4163 pDocSh->UpdateOle( pViewData );
4164 pView->CellContentChanged();
4168 if ( bDone )
4170 if ( bIsLink )
4172 // call with bApi = sal_True to avoid error messages in drop handler
4173 bDone = pView->LinkBlock( aSource, aDest.aStart, true /*bApi*/ );
4175 else
4177 // call with bApi = sal_True to avoid error messages in drop handler
4178 bDone = pView->MoveBlockTo( aSource, aDest.aStart, bIsMove, true /*bRecord*/, true /*bPaint*/, true /*bApi*/ );
4182 if ( bDone && meDragInsertMode != INS_NONE && bIsMove && nThisTab == nSourceTab )
4184 DelCellCmd eCmd = DEL_NONE;
4185 if ( meDragInsertMode == INS_CELLSDOWN )
4187 eCmd = DEL_CELLSUP;
4189 else if ( meDragInsertMode == INS_CELLSRIGHT )
4191 eCmd = DEL_CELLSLEFT;
4194 if ( ( eCmd == DEL_CELLSUP && nDestPosX == aSource.aStart.Col() ) ||
4195 ( eCmd == DEL_CELLSLEFT && nDestPosY == aSource.aStart.Row() ) )
4197 // call with bApi = sal_True to avoid error messages in drop handler
4198 bDone = pDocSh->GetDocFunc().DeleteCells( aSource, NULL, eCmd, true /*bRecord*/, true /*bApi*/ );
4199 if ( bDone )
4201 if ( eCmd == DEL_CELLSUP && nDestPosY > aSource.aEnd.Row() )
4203 bDone = aDest.Move( 0, -nSizeY, 0, pThisDoc );
4205 else if ( eCmd == DEL_CELLSLEFT && nDestPosX > aSource.aEnd.Col() )
4207 bDone = aDest.Move( -nSizeX, 0, 0, pThisDoc );
4209 pDocSh->UpdateOle( pViewData );
4210 pView->CellContentChanged();
4215 if ( bDone )
4217 pView->MarkRange( aDest, false, false );
4219 SCCOL nDCol = pViewData->GetCurX() - aSource.aStart.Col() + nCorrectCursorPosCol;
4220 SCROW nDRow = pViewData->GetCurY() - aSource.aStart.Row() + nCorrectCursorPosRow;
4221 pView->SetCursor( aDest.aStart.Col() + nDCol, aDest.aStart.Row() + nDRow );
4224 pDocSh->GetUndoManager()->LeaveListAction();
4227 else
4228 bDone = true; // nothing to do
4231 if (bDone)
4232 pTransObj->SetDragWasInternal(); // don't delete source in DragFinished
4234 else if ( !bFiltered && pSourceDoc ) // between documents
4236 if ( nFlags & SC_DROP_TABLE ) // copy/link sheets between documents
4238 if ( pThisDoc->IsDocEditable() )
4240 ScDocShell* pSrcShell = pTransObj->GetSourceDocShell();
4242 std::vector<SCTAB> nTabs;
4244 ScMarkData aMark = pTransObj->GetSourceMarkData();
4245 SCTAB nTabCount = pSourceDoc->GetTableCount();
4247 for(SCTAB i=0; i<nTabCount; i++)
4249 if(aMark.GetTableSelect(i))
4251 nTabs.push_back(i);
4252 for(SCTAB j=i+1;j<nTabCount;j++)
4254 if((!pSourceDoc->IsVisible(j))&&(pSourceDoc->IsScenario(j)))
4256 nTabs.push_back( j );
4257 i=j;
4259 else break;
4264 pView->ImportTables( pSrcShell,static_cast<SCTAB>(nTabs.size()), &nTabs[0], bIsLink, nThisTab );
4265 bDone = true;
4268 else if ( bIsLink )
4270 // as in PasteDDE
4271 // (external references might be used instead?)
4273 SfxObjectShell* pSourceSh = pSourceDoc->GetDocumentShell();
4274 OSL_ENSURE(pSourceSh, "drag document has no shell");
4275 if (pSourceSh)
4277 OUString aUndo = ScGlobal::GetRscString( STR_UNDO_COPY );
4278 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
4280 bDone = true;
4281 if ( meDragInsertMode != INS_NONE )
4283 // call with bApi = sal_True to avoid error messages in drop handler
4284 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, true /*bRecord*/, true /*bApi*/, true /*bPartOfPaste*/ );
4285 if ( bDone )
4287 pDocSh->UpdateOle( pViewData );
4288 pView->CellContentChanged();
4292 if ( bDone )
4294 OUString aApp = Application::GetAppName();
4295 OUString aTopic = pSourceSh->GetTitle( SFX_TITLE_FULLNAME );
4296 OUString aItem(aSource.Format(SCA_VALID | SCA_TAB_3D, pSourceDoc));
4298 // TODO: we could define ocQuote for "
4299 const OUString aQuote('"');
4300 const OUString& sSep = ScCompiler::GetNativeSymbol( ocSep);
4301 OUStringBuffer aFormula;
4302 aFormula.append('=');
4303 aFormula.append(ScCompiler::GetNativeSymbol(ocDde));
4304 aFormula.append(ScCompiler::GetNativeSymbol(ocOpen));
4305 aFormula.append(aQuote);
4306 aFormula.append(aApp);
4307 aFormula.append(aQuote);
4308 aFormula.append(sSep);
4309 aFormula.append(aQuote);
4310 aFormula.append(aTopic);
4311 aFormula.append(aQuote);
4312 aFormula.append(sSep);
4313 aFormula.append(aQuote);
4314 aFormula.append(aItem);
4315 aFormula.append(aQuote);
4316 aFormula.append(ScCompiler::GetNativeSymbol(ocClose));
4318 pView->DoneBlockMode();
4319 pView->InitBlockMode( nDestPosX, nDestPosY, nThisTab );
4320 pView->MarkCursor( nDestPosX + nSizeX - 1,
4321 nDestPosY + nSizeY - 1, nThisTab );
4323 pView->EnterMatrix( aFormula.makeStringAndClear(), ::formula::FormulaGrammar::GRAM_NATIVE );
4325 pView->MarkRange( aDest, false, false );
4326 pView->SetCursor( aDest.aStart.Col(), aDest.aStart.Row() );
4329 pDocSh->GetUndoManager()->LeaveListAction();
4332 else
4334 //! HasSelectedBlockMatrixFragment without selected sheet?
4335 //! or don't start dragging on a part of a matrix
4337 OUString aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY );
4338 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
4340 bDone = true;
4341 if ( meDragInsertMode != INS_NONE )
4343 // call with bApi = sal_True to avoid error messages in drop handler
4344 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, true /*bRecord*/, true /*bApi*/, true /*bPartOfPaste*/ );
4345 if ( bDone )
4347 pDocSh->UpdateOle( pViewData );
4348 pView->CellContentChanged();
4352 if ( bDone )
4354 pView->Unmark(); // before SetCursor, so CheckSelectionTransfer isn't called with a selection
4355 pView->SetCursor( nDestPosX, nDestPosY );
4356 bDone = pView->PasteFromClip( IDF_ALL, pTransObj->GetDocument() ); // clip-doc
4357 if ( bDone )
4359 pView->MarkRange( aDest, false, false );
4360 pView->SetCursor( aDest.aStart.Col(), aDest.aStart.Row() );
4364 pDocSh->GetUndoManager()->LeaveListAction();
4366 // no longer call ResetMark here - the inserted block has been selected
4367 // and may have been copied to primary selection
4371 sal_Int8 nRet = bDone ? nDndAction : DND_ACTION_NONE;
4372 return nRet;
4375 sal_Int8 ScGridWindow::ExecuteDrop( const ExecuteDropEvent& rEvt )
4377 DrawMarkDropObj( NULL ); // drawing layer
4379 ScModule* pScMod = SC_MOD();
4380 const ScDragData& rData = pScMod->GetDragData();
4381 if (rData.pCellTransfer)
4382 return ExecutePrivateDrop( rEvt );
4384 Point aPos = rEvt.maPosPixel;
4386 if ( !rData.aLinkDoc.isEmpty() )
4388 // try to insert a link
4390 bool bOk = true;
4391 OUString aThisName;
4392 ScDocShell* pDocSh = pViewData->GetDocShell();
4393 if (pDocSh && pDocSh->HasName())
4394 aThisName = pDocSh->GetMedium()->GetName();
4396 if ( rData.aLinkDoc.equals(aThisName) ) // error - no link within a document
4397 bOk = false;
4398 else
4400 ScViewFunc* pView = pViewData->GetView();
4401 if ( !rData.aLinkTable.isEmpty() )
4402 pView->InsertTableLink( rData.aLinkDoc, EMPTY_OUSTRING, EMPTY_OUSTRING,
4403 rData.aLinkTable );
4404 else if ( !rData.aLinkArea.isEmpty() )
4406 SCsCOL nPosX;
4407 SCsROW nPosY;
4408 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
4409 pView->MoveCursorAbs( nPosX, nPosY, SC_FOLLOW_NONE, false, false );
4411 pView->InsertAreaLink( rData.aLinkDoc, EMPTY_OUSTRING, EMPTY_OUSTRING,
4412 rData.aLinkArea, 0 );
4414 else
4416 OSL_FAIL("drop with link: no sheet nor area");
4417 bOk = false;
4421 return bOk ? rEvt.mnAction : DND_ACTION_NONE; // don't try anything else
4424 Point aLogicPos = PixelToLogic(aPos);
4425 bool bIsLink = ( rEvt.mnAction == DND_ACTION_LINK );
4427 if (!bIsLink && rData.pDrawTransfer)
4429 sal_uInt16 nFlags = rData.pDrawTransfer->GetDragSourceFlags();
4431 bool bIsNavi = ( nFlags & SC_DROP_NAVIGATOR ) != 0;
4432 bool bIsMove = ( rEvt.mnAction == DND_ACTION_MOVE && !bIsNavi );
4434 bPasteIsMove = bIsMove;
4436 pViewData->GetView()->PasteDraw(
4437 aLogicPos, rData.pDrawTransfer->GetModel(), false, "A", "B");
4439 if (bPasteIsMove)
4440 rData.pDrawTransfer->SetDragWasInternal();
4441 bPasteIsMove = false;
4443 return rEvt.mnAction;
4447 SCsCOL nPosX;
4448 SCsROW nPosY;
4449 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
4451 if (!rData.aJumpTarget.isEmpty())
4453 // internal bookmark (from Navigator)
4454 // bookmark clipboard formats are in PasteScDataObject
4456 if ( !rData.pJumpLocalDoc || rData.pJumpLocalDoc == pViewData->GetDocument() )
4458 pViewData->GetViewShell()->InsertBookmark( rData.aJumpText, rData.aJumpTarget,
4459 nPosX, nPosY );
4460 return rEvt.mnAction;
4464 ScDocument* pThisDoc = pViewData->GetDocument();
4465 SdrObject* pHitObj = pThisDoc->GetObjectAtPoint( pViewData->GetTabNo(), PixelToLogic(aPos) );
4466 if ( pHitObj && bIsLink )
4468 // dropped on drawing object
4469 // PasteOnDrawObjectLinked checks for valid formats
4470 if ( pViewData->GetView()->PasteOnDrawObjectLinked( rEvt.maDropEvent.Transferable, *pHitObj ) )
4471 return rEvt.mnAction;
4474 bool bDone = false;
4476 sal_uLong nFormatId = bIsLink ?
4477 lcl_GetDropLinkId( rEvt.maDropEvent.Transferable ) :
4478 lcl_GetDropFormatId( rEvt.maDropEvent.Transferable );
4479 if ( nFormatId )
4481 pScMod->SetInExecuteDrop( true ); // #i28468# prevent error messages from PasteDataFormat
4482 bPasteIsDrop = true;
4483 bDone = pViewData->GetView()->PasteDataFormat(
4484 nFormatId, rEvt.maDropEvent.Transferable, nPosX, nPosY, &aLogicPos, bIsLink );
4485 bPasteIsDrop = false;
4486 pScMod->SetInExecuteDrop( false );
4489 sal_Int8 nRet = bDone ? rEvt.mnAction : DND_ACTION_NONE;
4490 return nRet;
4493 void ScGridWindow::PasteSelection( const Point& rPosPixel )
4495 Point aLogicPos = PixelToLogic( rPosPixel );
4497 SCsCOL nPosX;
4498 SCsROW nPosY;
4499 pViewData->GetPosFromPixel( rPosPixel.X(), rPosPixel.Y(), eWhich, nPosX, nPosY );
4501 // If the mouse down was inside a visible note window, ignore it and
4502 // leave it up to the ScPostIt to handle it
4503 SdrView* pDrawView = pViewData->GetViewShell()->GetSdrView();
4504 if (pDrawView)
4506 sal_uLong nCount = pDrawView->GetMarkedObjectCount();
4507 for (sal_uLong i = 0; i < nCount; ++i)
4509 SdrObject* pObj = pDrawView->GetMarkedObjectByIndex(i);
4510 if (pObj && pObj->GetLogicRect().IsInside(aLogicPos))
4512 // Inside an active drawing object. Bail out.
4513 return;
4518 ScSelectionTransferObj* pOwnSelection = SC_MOD()->GetSelectionTransfer();
4519 if ( pOwnSelection )
4521 // within Calc
4523 ScTransferObj* pCellTransfer = pOwnSelection->GetCellData();
4524 if ( pCellTransfer )
4526 // keep a reference to the data in case the selection is changed during paste
4527 uno::Reference<datatransfer::XTransferable> xRef( pCellTransfer );
4528 DropTransferObj( pCellTransfer, nPosX, nPosY, aLogicPos, DND_ACTION_COPY );
4530 else
4532 ScDrawTransferObj* pDrawTransfer = pOwnSelection->GetDrawData();
4533 if ( pDrawTransfer )
4535 // keep a reference to the data in case the selection is changed during paste
4536 uno::Reference<datatransfer::XTransferable> xRef( pDrawTransfer );
4538 // bSameDocClipboard argument for PasteDraw is needed
4539 // because only DragData is checked directly inside PasteDraw
4540 pViewData->GetView()->PasteDraw(
4541 aLogicPos, pDrawTransfer->GetModel(), false,
4542 pDrawTransfer->GetShellID(), SfxObjectShell::CreateShellID(pViewData->GetDocShell()));
4546 else
4548 // get selection from system
4550 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSelection( this ) );
4551 uno::Reference<datatransfer::XTransferable> xTransferable = aDataHelper.GetTransferable();
4552 if ( xTransferable.is() )
4554 sal_uLong nFormatId = lcl_GetDropFormatId( xTransferable, true );
4555 if ( nFormatId )
4557 bPasteIsDrop = true;
4558 pViewData->GetView()->PasteDataFormat( nFormatId, xTransferable, nPosX, nPosY, &aLogicPos );
4559 bPasteIsDrop = false;
4565 void ScGridWindow::UpdateEditViewPos()
4567 if (pViewData->HasEditView(eWhich))
4569 EditView* pView;
4570 SCCOL nCol;
4571 SCROW nRow;
4572 pViewData->GetEditView( eWhich, pView, nCol, nRow );
4573 SCCOL nEndCol = pViewData->GetEditEndCol();
4574 SCROW nEndRow = pViewData->GetEditEndRow();
4576 // hide EditView?
4578 bool bHide = ( nEndCol<pViewData->GetPosX(eHWhich) || nEndRow<pViewData->GetPosY(eVWhich) );
4579 if ( SC_MOD()->IsFormulaMode() )
4580 if ( pViewData->GetTabNo() != pViewData->GetRefTabNo() )
4581 bHide = true;
4583 if (bHide)
4585 Rectangle aRect = pView->GetOutputArea();
4586 long nHeight = aRect.Bottom() - aRect.Top();
4587 aRect.Top() = PixelToLogic(GetOutputSizePixel(), pViewData->GetLogicMode()).
4588 Height() * 2;
4589 aRect.Bottom() = aRect.Top() + nHeight;
4590 pView->SetOutputArea( aRect );
4591 pView->HideCursor();
4593 else
4595 // bForceToTop = sal_True for editing
4596 Rectangle aPixRect = pViewData->GetEditArea( eWhich, nCol, nRow, this, NULL, true );
4597 Point aScrPos = PixelToLogic( aPixRect.TopLeft(), pViewData->GetLogicMode() );
4599 Rectangle aRect = pView->GetOutputArea();
4600 aRect.SetPos( aScrPos );
4601 pView->SetOutputArea( aRect );
4602 pView->ShowCursor();
4607 void ScGridWindow::ScrollPixel( long nDifX, long nDifY )
4609 ClickExtern();
4610 HideNoteMarker();
4612 bIsInScroll = true;
4614 SetMapMode(MAP_PIXEL);
4615 Scroll( nDifX, nDifY, SCROLL_CHILDREN );
4616 SetMapMode( GetDrawMapMode() ); // verschobenen MapMode erzeugen
4618 UpdateEditViewPos();
4620 DrawAfterScroll();
4621 bIsInScroll = false;
4624 // Formeln neu zeichnen -------------------------------------------------
4626 void ScGridWindow::UpdateFormulas()
4628 if (pViewData->GetView()->IsMinimized())
4629 return;
4631 if ( nPaintCount )
4633 // nicht anfangen, verschachtelt zu painten
4634 // (dann wuerde zumindest der MapMode nicht mehr stimmen)
4636 bNeedsRepaint = true; // -> am Ende vom Paint nochmal Invalidate auf alles
4637 aRepaintPixel = Rectangle(); // alles
4638 return;
4641 SCCOL nX1 = pViewData->GetPosX( eHWhich );
4642 SCROW nY1 = pViewData->GetPosY( eVWhich );
4643 SCCOL nX2 = nX1 + pViewData->VisibleCellsX( eHWhich );
4644 SCROW nY2 = nY1 + pViewData->VisibleCellsY( eVWhich );
4646 if (nX2 > MAXCOL) nX2 = MAXCOL;
4647 if (nY2 > MAXROW) nY2 = MAXROW;
4649 // Draw( nX1, nY1, nX2, nY2, SC_UPDATE_CHANGED );
4651 // don't draw directly - instead use OutputData to find changed area and invalidate
4653 SCROW nPosY = nY1;
4655 ScDocShell* pDocSh = pViewData->GetDocShell();
4656 ScDocument* pDoc = pDocSh->GetDocument();
4657 SCTAB nTab = pViewData->GetTabNo();
4659 pDoc->ExtendHidden( nX1, nY1, nX2, nY2, nTab );
4661 Point aScrPos = pViewData->GetScrPos( nX1, nY1, eWhich );
4662 long nMirrorWidth = GetSizePixel().Width();
4663 bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
4664 if ( bLayoutRTL )
4666 long nEndPixel = pViewData->GetScrPos( nX2+1, nPosY, eWhich ).X();
4667 nMirrorWidth = aScrPos.X() - nEndPixel;
4668 aScrPos.X() = nEndPixel + 1;
4671 long nScrX = aScrPos.X();
4672 long nScrY = aScrPos.Y();
4674 double nPPTX = pViewData->GetPPTX();
4675 double nPPTY = pViewData->GetPPTY();
4677 ScTableInfo aTabInfo;
4678 pDoc->FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nTab, nPPTX, nPPTY, false, false );
4680 Fraction aZoomX = pViewData->GetZoomX();
4681 Fraction aZoomY = pViewData->GetZoomY();
4682 ScOutputData aOutputData( this, OUTTYPE_WINDOW, aTabInfo, pDoc, nTab,
4683 nScrX, nScrY, nX1, nY1, nX2, nY2, nPPTX, nPPTY,
4684 &aZoomX, &aZoomY );
4685 aOutputData.SetMirrorWidth( nMirrorWidth );
4687 aOutputData.FindChanged();
4689 // #i122149# do not use old GetChangedArea() which used polygon-based Regions, but use
4690 // the region-band based new version; anyways, only rectangles are added
4691 Region aChangedRegion( aOutputData.GetChangedAreaRegion() ); // logic (PixelToLogic)
4692 if(!aChangedRegion.IsEmpty())
4694 Invalidate(aChangedRegion);
4697 CheckNeedsRepaint(); // #i90362# used to be called via Draw() - still needed here
4700 void ScGridWindow::UpdateAutoFillMark(bool bMarked, const ScRange& rMarkRange)
4702 if ( bMarked != bAutoMarkVisible || ( bMarked && rMarkRange.aEnd != aAutoMarkPos ) )
4704 bAutoMarkVisible = bMarked;
4705 if ( bMarked )
4706 aAutoMarkPos = rMarkRange.aEnd;
4708 UpdateAutoFillOverlay();
4712 void ScGridWindow::UpdateListValPos( bool bVisible, const ScAddress& rPos )
4714 bool bOldButton = bListValButton;
4715 ScAddress aOldPos = aListValPos;
4717 bListValButton = bVisible;
4718 aListValPos = rPos;
4720 if ( bListValButton )
4722 if ( !bOldButton || aListValPos != aOldPos )
4724 // paint area of new button
4725 Invalidate( PixelToLogic( GetListValButtonRect( aListValPos ) ) );
4728 if ( bOldButton )
4730 if ( !bListValButton || aListValPos != aOldPos )
4732 // paint area of old button
4733 Invalidate( PixelToLogic( GetListValButtonRect( aOldPos ) ) );
4738 void ScGridWindow::HideCursor()
4740 ++nCursorHideCount;
4743 void ScGridWindow::ShowCursor()
4745 --nCursorHideCount;
4748 void ScGridWindow::GetFocus()
4750 ScTabViewShell* pViewShell = pViewData->GetViewShell();
4751 pViewShell->GotFocus();
4752 pViewShell->SetFormShellAtTop( false ); // focus in GridWindow -> FormShell no longer on top
4754 if (pViewShell->HasAccessibilityObjects())
4755 pViewShell->BroadcastAccessibility(ScAccGridWinFocusGotHint(eWhich, GetAccessible()));
4758 if ( !SC_MOD()->IsFormulaMode() )
4760 pViewShell->UpdateInputHandler();
4761 // StopMarking(); // falls Dialog (Fehler), weil dann kein ButtonUp
4762 // MO: nur wenn nicht im RefInput-Modus
4763 // -> GetFocus/MouseButtonDown-Reihenfolge
4764 // auf dem Mac
4767 pViewData->GetDocShell()->CheckConfigOptions();
4768 Window::GetFocus();
4771 void ScGridWindow::LoseFocus()
4773 ScTabViewShell* pViewShell = pViewData->GetViewShell();
4774 pViewShell->LostFocus();
4776 if (pViewShell->HasAccessibilityObjects())
4777 pViewShell->BroadcastAccessibility(ScAccGridWinFocusLostHint(eWhich, GetAccessible()));
4779 Window::LoseFocus();
4782 Point ScGridWindow::GetMousePosPixel() const { return aCurMousePos; }
4784 bool ScGridWindow::HitRangeFinder( const Point& rMouse, RfCorner& rCorner,
4785 sal_uInt16* pIndex, SCsCOL* pAddX, SCsROW* pAddY)
4787 bool bFound = false;
4788 ScInputHandler* pHdl = SC_MOD()->GetInputHdl( pViewData->GetViewShell() );
4789 if (pHdl)
4791 ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList();
4792 if ( pRangeFinder && !pRangeFinder->IsHidden() &&
4793 pRangeFinder->GetDocName() == pViewData->GetDocShell()->GetTitle() )
4795 ScDocument* pDoc = pViewData->GetDocument();
4796 SCTAB nTab = pViewData->GetTabNo();
4797 bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
4798 long nLayoutSign = bLayoutRTL ? -1 : 1;
4800 SCsCOL nPosX;
4801 SCsROW nPosY;
4802 pViewData->GetPosFromPixel( rMouse.X(), rMouse.Y(), eWhich, nPosX, nPosY );
4803 // zusammengefasste (einzeln/Bereich) ???
4804 ScAddress aAddr( nPosX, nPosY, nTab );
4806 Point aCellStart = pViewData->GetScrPos( nPosX, nPosY, eWhich, true );
4807 Point aCellEnd = aCellStart;
4808 long nSizeXPix;
4809 long nSizeYPix;
4810 pViewData->GetMergeSizePixel( nPosX, nPosY, nSizeXPix, nSizeYPix );
4812 aCellEnd.X() += nSizeXPix * nLayoutSign;
4813 aCellEnd.Y() += nSizeYPix;
4815 bool bCornerHorizontalRight;
4816 bool bCornerHorizontalLeft;
4817 if ( bLayoutRTL )
4819 bCornerHorizontalRight = ( rMouse.X() >= aCellEnd.X() && rMouse.X() <= aCellEnd.X() + 8 );
4820 bCornerHorizontalLeft = ( rMouse.X() >= aCellStart.X() - 8 && rMouse.X() <= aCellStart.X() );
4822 else
4824 bCornerHorizontalRight = ( rMouse.X() >= aCellEnd.X() - 8 && rMouse.X() <= aCellEnd.X() );
4825 bCornerHorizontalLeft = ( rMouse.X() >= aCellStart.X() && rMouse.X() <= aCellStart.X() + 8 );
4828 bool bCornerVerticalDown = rMouse.Y() >= aCellEnd.Y() - 8 && rMouse.Y() <= aCellEnd.Y();
4829 bool bCornerVerticalUp = rMouse.Y() >= aCellStart.Y() && rMouse.Y() <= aCellStart.Y() + 8;
4831 // corner is hit only if the mouse is within the cell
4832 sal_uInt16 nCount = (sal_uInt16)pRangeFinder->Count();
4833 for (sal_uInt16 i=nCount; i;)
4835 // search backwards so that the last repainted frame is found
4836 --i;
4837 ScRangeFindData* pData = pRangeFinder->GetObject(i);
4838 if ( pData->aRef.In(aAddr) )
4840 if (pIndex)
4841 *pIndex = i;
4842 if (pAddX)
4843 *pAddX = nPosX - pData->aRef.aStart.Col();
4844 if (pAddY)
4845 *pAddY = nPosY - pData->aRef.aStart.Row();
4847 bFound = true;
4849 rCorner = NONE;
4851 ScAddress aEnd = pData->aRef.aEnd;
4852 ScAddress aStart = pData->aRef.aStart;
4854 if ( bCornerHorizontalLeft && bCornerVerticalUp &&
4855 aAddr == aStart)
4857 rCorner = LEFT_UP;
4859 else if (bCornerHorizontalRight && bCornerVerticalDown &&
4860 aAddr == aEnd)
4862 rCorner = RIGHT_DOWN;
4864 else if (bCornerHorizontalRight && bCornerVerticalUp &&
4865 aAddr == ScAddress(aEnd.Col(), aStart.Row(), aStart.Tab()))
4867 rCorner = RIGHT_UP;
4869 else if (bCornerHorizontalLeft && bCornerVerticalDown &&
4870 aAddr == ScAddress(aStart.Col(), aEnd.Row(), aStart.Tab()))
4872 rCorner = LEFT_DOWN;
4874 break;
4879 return bFound;
4882 #define SCE_TOP 1
4883 #define SCE_BOTTOM 2
4884 #define SCE_LEFT 4
4885 #define SCE_RIGHT 8
4886 #define SCE_ALL 15
4888 static void lcl_PaintOneRange( ScDocShell* pDocSh, const ScRange& rRange, sal_uInt16 nEdges )
4890 // der Range ist immer richtigherum
4892 SCCOL nCol1 = rRange.aStart.Col();
4893 SCROW nRow1 = rRange.aStart.Row();
4894 SCTAB nTab1 = rRange.aStart.Tab();
4895 SCCOL nCol2 = rRange.aEnd.Col();
4896 SCROW nRow2 = rRange.aEnd.Row();
4897 SCTAB nTab2 = rRange.aEnd.Tab();
4898 bool bHiddenEdge = false;
4899 SCROW nTmp;
4901 ScDocument* pDoc = pDocSh->GetDocument();
4902 while ( nCol1 > 0 && pDoc->ColHidden(nCol1, nTab1) )
4904 --nCol1;
4905 bHiddenEdge = true;
4907 while ( nCol2 < MAXCOL && pDoc->ColHidden(nCol2, nTab1) )
4909 ++nCol2;
4910 bHiddenEdge = true;
4912 nTmp = pDoc->FirstVisibleRow(0, nRow1, nTab1);
4913 if (!ValidRow(nTmp))
4914 nTmp = 0;
4915 if (nTmp < nRow1)
4917 nRow1 = nTmp;
4918 bHiddenEdge = true;
4920 nTmp = pDoc->FirstVisibleRow(nRow2, MAXROW, nTab1);
4921 if (!ValidRow(nTmp))
4922 nTmp = MAXROW;
4923 if (nTmp > nRow2)
4925 nRow2 = nTmp;
4926 bHiddenEdge = true;
4929 if ( nCol2 > nCol1 + 1 && nRow2 > nRow1 + 1 && !bHiddenEdge )
4931 // nur an den Raendern entlang
4932 // (die Ecken werden evtl. zweimal getroffen)
4934 if ( nEdges & SCE_TOP )
4935 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol2, nRow1, nTab2, PAINT_MARKS );
4936 if ( nEdges & SCE_LEFT )
4937 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol1, nRow2, nTab2, PAINT_MARKS );
4938 if ( nEdges & SCE_RIGHT )
4939 pDocSh->PostPaint( nCol2, nRow1, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
4940 if ( nEdges & SCE_BOTTOM )
4941 pDocSh->PostPaint( nCol1, nRow2, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
4943 else // everything in one call
4944 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS );
4947 static void lcl_PaintRefChanged( ScDocShell* pDocSh, const ScRange& rOldUn, const ScRange& rNewUn )
4949 // Repaint fuer die Teile des Rahmens in Old, die bei New nicht mehr da sind
4951 ScRange aOld = rOldUn;
4952 ScRange aNew = rNewUn;
4953 aOld.Justify();
4954 aNew.Justify();
4956 if ( aOld.aStart == aOld.aEnd ) //! Tab ignorieren?
4957 pDocSh->GetDocument()->ExtendMerge(aOld);
4958 if ( aNew.aStart == aNew.aEnd ) //! Tab ignorieren?
4959 pDocSh->GetDocument()->ExtendMerge(aNew);
4961 SCCOL nOldCol1 = aOld.aStart.Col();
4962 SCROW nOldRow1 = aOld.aStart.Row();
4963 SCCOL nOldCol2 = aOld.aEnd.Col();
4964 SCROW nOldRow2 = aOld.aEnd.Row();
4965 SCCOL nNewCol1 = aNew.aStart.Col();
4966 SCROW nNewRow1 = aNew.aStart.Row();
4967 SCCOL nNewCol2 = aNew.aEnd.Col();
4968 SCROW nNewRow2 = aNew.aEnd.Row();
4969 SCTAB nTab1 = aOld.aStart.Tab(); // Tab aendert sich nicht
4970 SCTAB nTab2 = aOld.aEnd.Tab();
4972 if ( nNewRow2 < nOldRow1 || nNewRow1 > nOldRow2 ||
4973 nNewCol2 < nOldCol1 || nNewCol1 > nOldCol2 ||
4974 ( nNewCol1 != nOldCol1 && nNewRow1 != nOldRow1 &&
4975 nNewCol2 != nOldCol2 && nNewRow2 != nOldRow2 ) )
4977 // komplett weggeschoben oder alle Seiten veraendert
4978 // (Abfrage <= statt < geht schief bei einzelnen Zeilen/Spalten)
4980 lcl_PaintOneRange( pDocSh, aOld, SCE_ALL );
4982 else // alle vier Kanten einzeln testen
4984 // oberer Teil
4985 if ( nNewRow1 < nOldRow1 ) // nur obere Linie loeschen
4986 lcl_PaintOneRange( pDocSh, ScRange(
4987 nOldCol1, nOldRow1, nTab1, nOldCol2, nOldRow1, nTab2 ), SCE_ALL );
4988 else if ( nNewRow1 > nOldRow1 ) // den Teil, der oben wegkommt
4989 lcl_PaintOneRange( pDocSh, ScRange(
4990 nOldCol1, nOldRow1, nTab1, nOldCol2, nNewRow1-1, nTab2 ),
4991 SCE_ALL &~ SCE_BOTTOM );
4993 // unterer Teil
4994 if ( nNewRow2 > nOldRow2 ) // nur untere Linie loeschen
4995 lcl_PaintOneRange( pDocSh, ScRange(
4996 nOldCol1, nOldRow2, nTab1, nOldCol2, nOldRow2, nTab2 ), SCE_ALL );
4997 else if ( nNewRow2 < nOldRow2 ) // den Teil, der unten wegkommt
4998 lcl_PaintOneRange( pDocSh, ScRange(
4999 nOldCol1, nNewRow2+1, nTab1, nOldCol2, nOldRow2, nTab2 ),
5000 SCE_ALL &~ SCE_TOP );
5002 // linker Teil
5003 if ( nNewCol1 < nOldCol1 ) // nur linke Linie loeschen
5004 lcl_PaintOneRange( pDocSh, ScRange(
5005 nOldCol1, nOldRow1, nTab1, nOldCol1, nOldRow2, nTab2 ), SCE_ALL );
5006 else if ( nNewCol1 > nOldCol1 ) // den Teil, der links wegkommt
5007 lcl_PaintOneRange( pDocSh, ScRange(
5008 nOldCol1, nOldRow1, nTab1, nNewCol1-1, nOldRow2, nTab2 ),
5009 SCE_ALL &~ SCE_RIGHT );
5011 // rechter Teil
5012 if ( nNewCol2 > nOldCol2 ) // nur rechte Linie loeschen
5013 lcl_PaintOneRange( pDocSh, ScRange(
5014 nOldCol2, nOldRow1, nTab1, nOldCol2, nOldRow2, nTab2 ), SCE_ALL );
5015 else if ( nNewCol2 < nOldCol2 ) // den Teil, der rechts wegkommt
5016 lcl_PaintOneRange( pDocSh, ScRange(
5017 nNewCol2+1, nOldRow1, nTab1, nOldCol2, nOldRow2, nTab2 ),
5018 SCE_ALL &~ SCE_LEFT );
5022 void ScGridWindow::RFMouseMove( const MouseEvent& rMEvt, bool bUp )
5024 ScInputHandler* pHdl = SC_MOD()->GetInputHdl( pViewData->GetViewShell() );
5025 if (!pHdl)
5026 return;
5027 ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList();
5028 if (!pRangeFinder || nRFIndex >= pRangeFinder->Count())
5029 return;
5030 ScRangeFindData* pData = pRangeFinder->GetObject( nRFIndex );
5032 // Mauszeiger
5034 if (bRFSize)
5035 SetPointer( Pointer( POINTER_CROSS ) );
5036 else
5037 SetPointer( Pointer( POINTER_HAND ) );
5039 // Scrolling
5041 bool bTimer = false;
5042 Point aPos = rMEvt.GetPosPixel();
5043 SCsCOL nDx = 0;
5044 SCsROW nDy = 0;
5045 if ( aPos.X() < 0 ) nDx = -1;
5046 if ( aPos.Y() < 0 ) nDy = -1;
5047 Size aSize = GetOutputSizePixel();
5048 if ( aPos.X() >= aSize.Width() )
5049 nDx = 1;
5050 if ( aPos.Y() >= aSize.Height() )
5051 nDy = 1;
5052 if ( nDx != 0 || nDy != 0 )
5054 if ( nDx != 0) pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) );
5055 if ( nDy != 0 ) pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) );
5056 bTimer = true;
5059 // Umschalten bei Fixierung (damit Scrolling funktioniert)
5061 if ( eWhich == pViewData->GetActivePart() ) //??
5063 if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX )
5064 if ( nDx > 0 )
5066 if ( eWhich == SC_SPLIT_TOPLEFT )
5067 pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT );
5068 else if ( eWhich == SC_SPLIT_BOTTOMLEFT )
5069 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT );
5072 if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX )
5073 if ( nDy > 0 )
5075 if ( eWhich == SC_SPLIT_TOPLEFT )
5076 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT );
5077 else if ( eWhich == SC_SPLIT_TOPRIGHT )
5078 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT );
5082 // Verschieben
5084 SCsCOL nPosX;
5085 SCsROW nPosY;
5086 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
5088 ScRange aOld = pData->aRef;
5089 ScRange aNew = aOld;
5090 if ( bRFSize )
5092 switch (aRFSelectedCorned)
5094 case LEFT_UP:
5095 aNew.aStart.SetCol((SCCOL)nPosX);
5096 aNew.aStart.SetRow((SCROW)nPosY);
5097 break;
5098 case LEFT_DOWN:
5099 aNew.aStart.SetCol((SCCOL)nPosX);
5100 aNew.aEnd.SetRow((SCROW)nPosY);
5101 break;
5102 case RIGHT_UP:
5103 aNew.aEnd.SetCol((SCCOL)nPosX);
5104 aNew.aStart.SetRow((SCROW)nPosY);
5105 break;
5106 case RIGHT_DOWN:
5107 aNew.aEnd.SetCol((SCCOL)nPosX);
5108 aNew.aEnd.SetRow((SCROW)nPosY);
5109 break;
5110 default:
5111 break;
5114 else
5116 long nStartX = nPosX - nRFAddX;
5117 if ( nStartX < 0 ) nStartX = 0;
5118 long nStartY = nPosY - nRFAddY;
5119 if ( nStartY < 0 ) nStartY = 0;
5120 long nEndX = nStartX + aOld.aEnd.Col() - aOld.aStart.Col();
5121 if ( nEndX > MAXCOL )
5123 nStartX -= ( nEndX - MAXROW );
5124 nEndX = MAXCOL;
5126 long nEndY = nStartY + aOld.aEnd.Row() - aOld.aStart.Row();
5127 if ( nEndY > MAXROW )
5129 nStartY -= ( nEndY - MAXROW );
5130 nEndY = MAXROW;
5133 aNew.aStart.SetCol((SCCOL)nStartX);
5134 aNew.aStart.SetRow((SCROW)nStartY);
5135 aNew.aEnd.SetCol((SCCOL)nEndX);
5136 aNew.aEnd.SetRow((SCROW)nEndY);
5139 if ( bUp )
5140 aNew.Justify(); // beim ButtonUp wieder richtigherum
5142 if ( aNew != aOld )
5144 pHdl->UpdateRange( nRFIndex, aNew );
5146 ScDocShell* pDocSh = pViewData->GetDocShell();
5148 // nur das neuzeichnen, was sich veraendert hat...
5149 lcl_PaintRefChanged( pDocSh, aOld, aNew );
5151 // neuen Rahmen nur drueberzeichnen (synchron)
5152 pDocSh->Broadcast( ScIndexHint( SC_HINT_SHOWRANGEFINDER, nRFIndex ) );
5154 Update(); // was man bewegt, will man auch sofort sehen
5157 // Timer fuer Scrolling
5159 if (bTimer)
5160 pViewData->GetView()->SetTimer( this, rMEvt ); // Event wiederholen
5161 else
5162 pViewData->GetView()->ResetTimer();
5165 namespace {
5167 SvxAdjust toSvxAdjust( const ScPatternAttr& rPat )
5169 SvxCellHorJustify eHorJust =
5170 static_cast<SvxCellHorJustify>(
5171 static_cast<const SvxHorJustifyItem&>(rPat.GetItem(ATTR_HOR_JUSTIFY)).GetValue());
5173 SvxAdjust eSvxAdjust = SVX_ADJUST_LEFT;
5174 switch (eHorJust)
5176 case SVX_HOR_JUSTIFY_LEFT:
5177 case SVX_HOR_JUSTIFY_REPEAT: // nicht implementiert
5178 case SVX_HOR_JUSTIFY_STANDARD: // always Text if an EditCell type
5179 eSvxAdjust = SVX_ADJUST_LEFT;
5180 break;
5181 case SVX_HOR_JUSTIFY_RIGHT:
5182 eSvxAdjust = SVX_ADJUST_RIGHT;
5183 break;
5184 case SVX_HOR_JUSTIFY_CENTER:
5185 eSvxAdjust = SVX_ADJUST_CENTER;
5186 break;
5187 case SVX_HOR_JUSTIFY_BLOCK:
5188 eSvxAdjust = SVX_ADJUST_BLOCK;
5189 break;
5192 return eSvxAdjust;
5195 boost::shared_ptr<ScFieldEditEngine> createEditEngine( ScDocShell* pDocSh, const ScPatternAttr& rPat )
5197 ScDocument* pDoc = pDocSh->GetDocument();
5199 boost::shared_ptr<ScFieldEditEngine> pEngine(new ScFieldEditEngine(pDoc, pDoc->GetEditPool()));
5200 ScSizeDeviceProvider aProv(pDocSh);
5201 pEngine->SetRefDevice(aProv.GetDevice());
5202 pEngine->SetRefMapMode(MAP_100TH_MM);
5203 SfxItemSet aDefault = pEngine->GetEmptyItemSet();
5204 rPat.FillEditItemSet(&aDefault);
5205 aDefault.Put( SvxAdjustItem(toSvxAdjust(rPat), EE_PARA_JUST) );
5206 pEngine->SetDefaults(aDefault);
5208 return pEngine;
5211 bool extractURLInfo( const SvxFieldItem* pFieldItem, OUString* pName, OUString* pUrl, OUString* pTarget )
5213 if (!pFieldItem)
5214 return false;
5216 const SvxFieldData* pField = pFieldItem->GetField();
5217 if (pField->GetClassId() != text::textfield::Type::URL)
5218 return false;
5220 const SvxURLField* pURLField = static_cast<const SvxURLField*>(pField);
5222 if (pName)
5223 *pName = pURLField->GetRepresentation();
5224 if (pUrl)
5225 *pUrl = pURLField->GetURL();
5226 if (pTarget)
5227 *pTarget = pURLField->GetTargetFrame();
5229 return true;
5234 bool ScGridWindow::GetEditUrl( const Point& rPos,
5235 OUString* pName, OUString* pUrl, OUString* pTarget )
5237 ScTabViewShell* pViewSh = pViewData->GetViewShell();
5238 ScInputHandler* pInputHdl = NULL;
5239 if (pViewSh)
5240 pInputHdl = pViewSh->GetInputHandler();
5241 EditView* pView = (pInputHdl && pInputHdl->IsInputMode()) ? pInputHdl->GetTableView() : NULL;
5242 if (pView)
5243 return extractURLInfo(pView->GetFieldUnderMousePointer(), pName, pUrl, pTarget);
5245 //! nPosX/Y mit uebergeben?
5246 SCsCOL nPosX;
5247 SCsROW nPosY;
5248 pViewData->GetPosFromPixel( rPos.X(), rPos.Y(), eWhich, nPosX, nPosY );
5250 SCTAB nTab = pViewData->GetTabNo();
5251 ScDocShell* pDocSh = pViewData->GetDocShell();
5252 ScDocument* pDoc = pDocSh->GetDocument();
5253 OUString sURL;
5254 ScRefCellValue aCell;
5255 bool bFound = lcl_GetHyperlinkCell(pDoc, nPosX, nPosY, nTab, aCell, sURL);
5256 if( !bFound )
5257 return false;
5259 const ScPatternAttr* pPattern = pDoc->GetPattern( nPosX, nPosY, nTab );
5260 // bForceToTop = sal_False, use the cell's real position
5261 Rectangle aEditRect = pViewData->GetEditArea( eWhich, nPosX, nPosY, this, pPattern, false );
5262 if (rPos.Y() < aEditRect.Top())
5263 return false;
5265 // vertikal kann (noch) nicht angeklickt werden:
5267 if (pPattern->GetCellOrientation() != SVX_ORIENTATION_STANDARD)
5268 return false;
5270 bool bBreak = ((SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK)).GetValue() ||
5271 ((SvxCellHorJustify)((const SvxHorJustifyItem&)pPattern->
5272 GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_BLOCK);
5273 SvxCellHorJustify eHorJust = (SvxCellHorJustify)((SvxHorJustifyItem&)pPattern->
5274 GetItem(ATTR_HOR_JUSTIFY)).GetValue();
5276 // EditEngine
5278 boost::shared_ptr<ScFieldEditEngine> pEngine = createEditEngine(pDocSh, *pPattern);
5280 MapMode aEditMode = pViewData->GetLogicMode(eWhich); // ohne Drawing-Skalierung
5281 Rectangle aLogicEdit = PixelToLogic( aEditRect, aEditMode );
5282 long nThisColLogic = aLogicEdit.Right() - aLogicEdit.Left() + 1;
5283 Size aPaperSize = Size( 1000000, 1000000 );
5284 if (aCell.meType == CELLTYPE_FORMULA)
5286 long nSizeX = 0;
5287 long nSizeY = 0;
5288 pViewData->GetMergeSizePixel( nPosX, nPosY, nSizeX, nSizeY );
5289 aPaperSize = Size(nSizeX, nSizeY );
5290 aPaperSize = PixelToLogic(aPaperSize);
5293 if (bBreak)
5294 aPaperSize.Width() = nThisColLogic;
5295 pEngine->SetPaperSize( aPaperSize );
5297 boost::scoped_ptr<EditTextObject> pTextObj;
5298 if (aCell.meType == CELLTYPE_EDIT)
5300 if (aCell.mpEditText)
5301 pEngine->SetText(*aCell.mpEditText);
5303 else // Not an Edit cell and is a formula cell with 'Hyperlink'
5304 // function if we have no URL, otherwise it could be a formula
5305 // cell ( or other type ? ) with a hyperlink associated with it.
5307 if (sURL.isEmpty())
5308 pTextObj.reset(aCell.mpFormula->CreateURLObject());
5309 else
5310 pTextObj.reset(ScEditUtil::CreateURLObjectFromURL(*pDoc, sURL, sURL));
5312 if (pTextObj.get())
5313 pEngine->SetText(*pTextObj);
5316 long nStartX = aLogicEdit.Left();
5318 long nTextWidth = pEngine->CalcTextWidth();
5319 long nTextHeight = pEngine->GetTextHeight();
5320 if ( nTextWidth < nThisColLogic )
5322 if (eHorJust == SVX_HOR_JUSTIFY_RIGHT)
5323 nStartX += nThisColLogic - nTextWidth;
5324 else if (eHorJust == SVX_HOR_JUSTIFY_CENTER)
5325 nStartX += (nThisColLogic - nTextWidth) / 2;
5328 aLogicEdit.Left() = nStartX;
5329 if (!bBreak)
5330 aLogicEdit.Right() = nStartX + nTextWidth;
5332 // There is one glitch when dealing with a hyperlink cell and
5333 // the cell content is NUMERIC. This defaults to right aligned and
5334 // we need to adjust accordingly.
5335 if (aCell.meType == CELLTYPE_FORMULA && aCell.mpFormula->IsValue() &&
5336 eHorJust == SVX_HOR_JUSTIFY_STANDARD)
5338 aLogicEdit.Right() = aLogicEdit.Left() + nThisColLogic - 1;
5339 aLogicEdit.Left() = aLogicEdit.Right() - nTextWidth;
5341 aLogicEdit.Bottom() = aLogicEdit.Top() + nTextHeight;
5344 Point aLogicClick = PixelToLogic(rPos,aEditMode);
5345 if ( aLogicEdit.IsInside(aLogicClick) )
5347 EditView aTempView(pEngine.get(), this);
5348 aTempView.SetOutputArea( aLogicEdit );
5350 bool bRet = false;
5351 MapMode aOld = GetMapMode();
5352 SetMapMode(aEditMode); // kein return mehr
5353 bRet = extractURLInfo(aTempView.GetFieldUnderMousePointer(), pName, pUrl, pTarget);
5354 SetMapMode(aOld);
5356 return bRet;
5358 return false;
5361 bool ScGridWindow::IsSpellErrorAtPos( const Point& rPos, SCCOL nCol1, SCCOL nCol2, SCROW nRow )
5363 if (!mpSpellCheckCxt)
5364 return false;
5366 SCTAB nTab = pViewData->GetTabNo();
5367 ScDocShell* pDocSh = pViewData->GetDocShell();
5368 ScDocument* pDoc = pDocSh->GetDocument();
5370 ScAddress aCellPos(nCol1, nRow, nTab);
5371 ScRefCellValue aCell;
5372 aCell.assign(*pDoc, aCellPos);
5373 if (aCell.meType != CELLTYPE_STRING && aCell.meType != CELLTYPE_EDIT)
5374 return false;
5376 const std::vector<editeng::MisspellRanges>* pRanges = mpSpellCheckCxt->getMisspellRanges(nCol1, nRow);
5377 if (!pRanges)
5378 return false;
5380 const ScPatternAttr* pPattern = pDoc->GetPattern(nCol1, nRow, nTab);
5382 Rectangle aEditRect = pViewData->GetEditArea(eWhich, nCol1, nRow, this, pPattern, false);
5383 if (rPos.Y() < aEditRect.Top())
5384 return false;
5386 Rectangle aEditRect2 = pViewData->GetEditArea(eWhich, nCol2, nRow, this, pPattern, false);
5387 long nExt = aEditRect2.Left() - aEditRect.Right() + aEditRect2.GetWidth();
5388 aEditRect.setWidth(aEditRect.getWidth() + nExt);
5390 MapMode aEditMode = pViewData->GetLogicMode(eWhich);
5391 Rectangle aLogicEdit = PixelToLogic(aEditRect, aEditMode);
5392 Point aLogicClick = PixelToLogic(rPos, aEditMode);
5394 if (!aLogicEdit.IsInside(aLogicClick))
5395 return false;
5397 boost::shared_ptr<ScFieldEditEngine> pEngine = createEditEngine(pDocSh, *pPattern);
5399 Size aPaperSize = Size(1000000, 1000000);
5400 pEngine->SetPaperSize(aPaperSize);
5402 if (aCell.meType == CELLTYPE_EDIT)
5403 pEngine->SetText(*aCell.mpEditText);
5404 else
5405 pEngine->SetText(aCell.mpString->getString());
5407 pEngine->SetControlWord(pEngine->GetControlWord() | EE_CNTRL_ONLINESPELLING);
5408 pEngine->SetAllMisspellRanges(*pRanges);
5410 EditView aTempView(pEngine.get(), this);
5411 aTempView.SetOutputArea(aLogicEdit);
5413 return aTempView.IsWrongSpelledWordAtPos(rPos);
5416 bool ScGridWindow::HasScenarioButton( const Point& rPosPixel, ScRange& rScenRange )
5418 ScDocument* pDoc = pViewData->GetDocument();
5419 SCTAB nTab = pViewData->GetTabNo();
5420 SCTAB nTabCount = pDoc->GetTableCount();
5421 if ( nTab+1<nTabCount && pDoc->IsScenario(nTab+1) && !pDoc->IsScenario(nTab) )
5423 bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5425 Size aButSize = pViewData->GetScenButSize();
5426 long nBWidth = aButSize.Width();
5427 if (!nBWidth)
5428 return false; // noch kein Button gezeichnet -> da ist auch keiner
5429 long nBHeight = aButSize.Height();
5430 long nHSpace = (long)( SC_SCENARIO_HSPACE * pViewData->GetPPTX() );
5432 //! Ranges an der Table cachen!!!!
5434 ScMarkData aMarks;
5435 for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++)
5436 pDoc->MarkScenario( i, nTab, aMarks, false, SC_SCENARIO_SHOWFRAME );
5437 ScRangeList aRanges;
5438 aMarks.FillRangeListWithMarks( &aRanges, false );
5441 size_t nRangeCount = aRanges.size();
5442 for (size_t j=0; j< nRangeCount; ++j)
5444 ScRange aRange = *aRanges[j];
5445 // Szenario-Rahmen immer dann auf zusammengefasste Zellen erweitern, wenn
5446 // dadurch keine neuen nicht-ueberdeckten Zellen mit umrandet werden
5447 pDoc->ExtendTotalMerge( aRange );
5449 bool bTextBelow = ( aRange.aStart.Row() == 0 );
5451 Point aButtonPos;
5452 if ( bTextBelow )
5454 aButtonPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aEnd.Row()+1,
5455 eWhich, true );
5457 else
5459 aButtonPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aStart.Row(),
5460 eWhich, true );
5461 aButtonPos.Y() -= nBHeight;
5463 if ( bLayoutRTL )
5464 aButtonPos.X() -= nHSpace - 1;
5465 else
5466 aButtonPos.X() -= nBWidth - nHSpace; // same for top or bottom
5468 Rectangle aButRect( aButtonPos, Size(nBWidth,nBHeight) );
5469 if ( aButRect.IsInside( rPosPixel ) )
5471 rScenRange = aRange;
5472 return true;
5477 return false;
5480 // #114409#
5481 void ScGridWindow::DrawLayerCreated()
5483 SetMapMode( GetDrawMapMode() );
5485 // initially create overlay objects
5486 ImpCreateOverlayObjects();
5489 namespace {
5491 struct SpellCheckStatus
5493 bool mbModified;
5495 SpellCheckStatus() : mbModified(false) {};
5497 DECL_LINK (EventHdl, EditStatus*);
5500 IMPL_LINK(SpellCheckStatus, EventHdl, EditStatus*, pStatus)
5502 sal_uLong nStatus = pStatus->GetStatusWord();
5503 if (nStatus & EE_STAT_WRONGWORDCHANGED)
5504 mbModified = true;
5506 return 0;
5511 bool ScGridWindow::ContinueOnlineSpelling()
5513 if (!mpSpellCheckCxt)
5514 return false;
5516 if (!mpSpellCheckCxt->maPos.isValid())
5517 return false;
5519 ScDocument* pDoc = pViewData->GetDocument();
5520 ScDPCollection* pDPs = NULL;
5521 if (pDoc->HasPivotTable())
5522 pDPs = pDoc->GetDPCollection();
5524 SCTAB nTab = pViewData->GetTabNo();
5525 SpellCheckStatus aStatus;
5527 ScHorizontalCellIterator aIter(
5528 pDoc, nTab, maVisibleRange.mnCol1, mpSpellCheckCxt->maPos.mnRow, maVisibleRange.mnCol2, maVisibleRange.mnRow2);
5530 ScRangeList aPivotRanges;
5531 if (pDPs)
5532 aPivotRanges = pDPs->GetAllTableRanges(nTab);
5534 SCCOL nCol;
5535 SCROW nRow;
5536 ScRefCellValue* pCell = aIter.GetNext(nCol, nRow);
5537 while (pCell && nRow < mpSpellCheckCxt->maPos.mnRow)
5538 pCell = aIter.GetNext(nCol, nRow);
5540 while (pCell && nCol < mpSpellCheckCxt->maPos.mnCol)
5541 pCell = aIter.GetNext(nCol, nRow);
5543 boost::scoped_ptr<ScTabEditEngine> pEngine;
5545 // Check only up to 256 cells at a time.
5546 size_t nTotalCellCount = 0;
5547 size_t nTextCellCount = 0;
5548 bool bSpellCheckPerformed = false;
5550 while (pCell)
5552 ++nTotalCellCount;
5554 if (aPivotRanges.In(ScAddress(nCol, nRow, nTab)))
5556 // Don't spell check within pivot tables.
5557 if (nTotalCellCount >= 255)
5558 break;
5560 pCell = aIter.GetNext(nCol, nRow);
5561 continue;
5564 CellType eType = pCell->meType;
5565 if (eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT)
5567 ++nTextCellCount;
5569 if (!pEngine)
5571 // ScTabEditEngine is needed
5572 // because MapMode must be set for some old documents
5573 pEngine.reset(new ScTabEditEngine(pDoc));
5574 pEngine->SetControlWord(
5575 pEngine->GetControlWord() | (EE_CNTRL_ONLINESPELLING | EE_CNTRL_ALLOWBIGOBJS));
5576 pEngine->SetStatusEventHdl(LINK(&aStatus, SpellCheckStatus, EventHdl));
5577 // Delimiters hier wie in inputhdl.cxx !!!
5578 pEngine->SetWordDelimiters(
5579 ScEditUtil::ModifyDelimiters(pEngine->GetWordDelimiters()));
5581 uno::Reference<linguistic2::XSpellChecker1> xXSpellChecker1(LinguMgr::GetSpellChecker());
5582 pEngine->SetSpeller(xXSpellChecker1);
5585 const ScPatternAttr* pPattern = pDoc->GetPattern(nCol, nRow, nTab);
5586 sal_uInt16 nCellLang =
5587 static_cast<const SvxLanguageItem&>(pPattern->GetItem(ATTR_FONT_LANGUAGE)).GetValue();
5588 if (nCellLang == LANGUAGE_SYSTEM)
5589 nCellLang = Application::GetSettings().GetLanguageTag().getLanguageType(); // never use SYSTEM for spelling
5590 pEngine->SetDefaultLanguage(nCellLang);
5592 if (eType == CELLTYPE_STRING)
5593 pEngine->SetText(pCell->mpString->getString());
5594 else
5595 pEngine->SetText(*pCell->mpEditText);
5597 aStatus.mbModified = false;
5598 pEngine->CompleteOnlineSpelling();
5599 if (aStatus.mbModified)
5601 std::vector<editeng::MisspellRanges> aRanges;
5602 pEngine->GetAllMisspellRanges(aRanges);
5603 if (!aRanges.empty())
5605 sc::SpellCheckContext::CellPos aPos(nCol, nRow);
5606 mpSpellCheckCxt->maMisspellCells.insert(
5607 sc::SpellCheckContext::CellMapType::value_type(aPos, aRanges));
5610 // Broadcast for re-paint.
5611 ScPaintHint aHint(ScRange(nCol, nRow, nTab), PAINT_GRID);
5612 aHint.SetPrintFlag(false);
5613 pDoc->GetDocumentShell()->Broadcast(aHint);
5616 bSpellCheckPerformed = true;
5619 if (nTotalCellCount >= 255 || nTextCellCount >= 1)
5620 break;
5622 pCell = aIter.GetNext(nCol, nRow);
5625 if (pCell)
5626 // Move to the next cell position for the next iteration.
5627 pCell = aIter.GetNext(nCol, nRow);
5629 if (pCell)
5631 // This will become the first cell position for the next time.
5632 mpSpellCheckCxt->maPos.mnCol = nCol;
5633 mpSpellCheckCxt->maPos.mnRow = nRow;
5635 else
5637 // No more cells to spell check.
5638 mpSpellCheckCxt->maPos.setInvalid();
5641 return bSpellCheckPerformed;
5644 void ScGridWindow::EnableAutoSpell( bool bEnable )
5646 if (bEnable)
5647 mpSpellCheckCxt.reset(new sc::SpellCheckContext);
5648 else
5649 mpSpellCheckCxt.reset();
5652 void ScGridWindow::ResetAutoSpell()
5654 if (mpSpellCheckCxt)
5656 mpSpellCheckCxt->reset();
5657 mpSpellCheckCxt->maPos.mnCol = maVisibleRange.mnCol1;
5658 mpSpellCheckCxt->maPos.mnRow = maVisibleRange.mnRow1;
5662 void ScGridWindow::SetAutoSpellData( SCCOL nPosX, SCROW nPosY, const std::vector<editeng::MisspellRanges>* pRanges )
5664 if (!mpSpellCheckCxt)
5665 return;
5667 if (!maVisibleRange.isInside(nPosX, nPosY))
5668 return;
5670 mpSpellCheckCxt->setMisspellRanges(nPosX, nPosY, pRanges);
5673 // #114409#
5674 void ScGridWindow::CursorChanged()
5676 // here the created OverlayObjects may be transformed in later versions. For
5677 // now, just re-create them
5679 UpdateCursorOverlay();
5682 // #114409#
5683 void ScGridWindow::ImpCreateOverlayObjects()
5685 UpdateCursorOverlay();
5686 UpdateCopySourceOverlay();
5687 UpdateSelectionOverlay();
5688 UpdateAutoFillOverlay();
5689 UpdateDragRectOverlay();
5690 UpdateHeaderOverlay();
5691 UpdateShrinkOverlay();
5694 // #114409#
5695 void ScGridWindow::ImpDestroyOverlayObjects()
5697 DeleteCursorOverlay();
5698 DeleteCopySourceOverlay();
5699 DeleteSelectionOverlay();
5700 DeleteAutoFillOverlay();
5701 DeleteDragRectOverlay();
5702 DeleteHeaderOverlay();
5703 DeleteShrinkOverlay();
5706 void ScGridWindow::UpdateAllOverlays()
5708 // delete and re-allocate all overlay objects
5710 ImpDestroyOverlayObjects();
5711 ImpCreateOverlayObjects();
5714 void ScGridWindow::DeleteCursorOverlay()
5716 DELETEZ( mpOOCursors );
5719 void ScGridWindow::DeleteCopySourceOverlay()
5721 DELETEZ( mpOOSelectionBorder );
5724 void ScGridWindow::UpdateCopySourceOverlay()
5726 MapMode aDrawMode = GetDrawMapMode();
5727 MapMode aOldMode = GetMapMode();
5728 if ( aOldMode != aDrawMode )
5729 SetMapMode( aDrawMode );
5731 DeleteCopySourceOverlay();
5733 if (!pViewData->ShowPasteSource())
5734 return;
5735 rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager = getOverlayManager();
5736 if (!xOverlayManager.is())
5737 return;
5738 ScTransferObj* pTransObj = ScTransferObj::GetOwnClipboard( pViewData->GetActiveWin() );
5739 if (!pTransObj)
5740 return;
5741 ScDocument* pClipDoc = pTransObj->GetDocument();
5742 if (!pClipDoc)
5743 return;
5745 SCTAB nCurTab = pViewData->GetCurPos().Tab();
5747 ScClipParam& rClipParam = pClipDoc->GetClipParam();
5748 mpOOSelectionBorder = new ::sdr::overlay::OverlayObjectList;
5749 for ( size_t i = 0; i < rClipParam.maRanges.size(); ++i )
5751 ScRange* p = rClipParam.maRanges[i];
5752 if (p->aStart.Tab() != nCurTab)
5753 continue;
5755 SCCOL nClipStartX = p->aStart.Col();
5756 SCROW nClipStartY = p->aStart.Row();
5757 SCCOL nClipEndX = p->aEnd.Col();
5758 SCROW nClipEndY = p->aEnd.Row();
5760 Point aClipStartScrPos = pViewData->GetScrPos( nClipStartX, nClipStartY, eWhich );
5761 Point aClipEndScrPos = pViewData->GetScrPos( nClipEndX + 1, nClipEndY + 1, eWhich );
5762 aClipStartScrPos -= Point(1, 1);
5763 long nSizeXPix = aClipEndScrPos.X() - aClipStartScrPos.X();
5764 long nSizeYPix = aClipEndScrPos.Y() - aClipStartScrPos.Y();
5766 Rectangle aRect( aClipStartScrPos, Size(nSizeXPix, nSizeYPix) );
5769 Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
5771 Rectangle aLogic = PixelToLogic(aRect, aDrawMode);
5772 ::basegfx::B2DRange aRange(aLogic.Left(), aLogic.Top(), aLogic.Right(), aLogic.Bottom());
5773 ScOverlayDashedBorder* pDashedBorder = new ScOverlayDashedBorder(aRange, aHighlight);
5774 xOverlayManager->add(*pDashedBorder);
5775 mpOOSelectionBorder->append(*pDashedBorder);
5778 if ( aOldMode != aDrawMode )
5779 SetMapMode( aOldMode );
5782 void ScGridWindow::UpdateCursorOverlay()
5784 MapMode aDrawMode = GetDrawMapMode();
5785 MapMode aOldMode = GetMapMode();
5786 if ( aOldMode != aDrawMode )
5787 SetMapMode( aDrawMode );
5789 // Existing OverlayObjects may be transformed in later versions.
5790 // For now, just re-create them.
5792 DeleteCursorOverlay();
5794 std::vector<Rectangle> aPixelRects;
5797 // determine the cursor rectangles in pixels (moved from ScGridWindow::DrawCursor)
5800 SCTAB nTab = pViewData->GetTabNo();
5801 SCCOL nX = pViewData->GetCurX();
5802 SCROW nY = pViewData->GetCurY();
5804 if (!maVisibleRange.isInside(nX, nY))
5805 return;
5807 // don't show the cursor in overlapped cells
5809 ScDocument* pDoc = pViewData->GetDocument();
5810 const ScPatternAttr* pPattern = pDoc->GetPattern(nX,nY,nTab);
5811 const ScMergeFlagAttr& rMergeFlag = (const ScMergeFlagAttr&) pPattern->GetItem(ATTR_MERGE_FLAG);
5812 bool bOverlapped = rMergeFlag.IsOverlapped();
5814 // left or above of the screen?
5816 bool bVis = ( nX>=pViewData->GetPosX(eHWhich) && nY>=pViewData->GetPosY(eVWhich) );
5817 if (!bVis)
5819 SCCOL nEndX = nX;
5820 SCROW nEndY = nY;
5821 const ScMergeAttr& rMerge = (const ScMergeAttr&) pPattern->GetItem(ATTR_MERGE);
5822 if (rMerge.GetColMerge() > 1)
5823 nEndX += rMerge.GetColMerge()-1;
5824 if (rMerge.GetRowMerge() > 1)
5825 nEndY += rMerge.GetRowMerge()-1;
5826 bVis = ( nEndX>=pViewData->GetPosX(eHWhich) && nEndY>=pViewData->GetPosY(eVWhich) );
5829 if ( bVis && !bOverlapped && !pViewData->HasEditView(eWhich) && pViewData->IsActive() )
5831 Point aScrPos = pViewData->GetScrPos( nX, nY, eWhich, true );
5832 bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5834 // completely right of/below the screen?
5835 // (test with logical start position in aScrPos)
5836 bool bMaybeVisible;
5837 if ( bLayoutRTL )
5838 bMaybeVisible = ( aScrPos.X() >= -2 && aScrPos.Y() >= -2 );
5839 else
5841 Size aOutSize = GetOutputSizePixel();
5842 bMaybeVisible = ( aScrPos.X() <= aOutSize.Width() + 2 && aScrPos.Y() <= aOutSize.Height() + 2 );
5844 if ( bMaybeVisible )
5846 long nSizeXPix;
5847 long nSizeYPix;
5848 pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix );
5850 if ( bLayoutRTL )
5851 aScrPos.X() -= nSizeXPix - 2; // move instead of mirroring
5853 // Now, draw the cursor.
5855 aScrPos.X() -= 2;
5856 aScrPos.Y() -= 2;
5857 Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) );
5859 aPixelRects.push_back(Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() ));
5860 aPixelRects.push_back(Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() ));
5861 aPixelRects.push_back(Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 ));
5862 aPixelRects.push_back(Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() ));
5866 if ( !aPixelRects.empty() )
5868 // #i70788# get the OverlayManager safely
5869 rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager = getOverlayManager();
5871 if (xOverlayManager.is())
5873 Color aCursorColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
5874 if (pViewData->GetActivePart() != eWhich)
5875 // non-active pane uses a different color.
5876 aCursorColor = SC_MOD()->GetColorConfig().GetColorValue(svtools::CALCPAGEBREAKAUTOMATIC).nColor;
5877 std::vector< basegfx::B2DRange > aRanges;
5878 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5880 for(sal_uInt32 a(0); a < aPixelRects.size(); a++)
5882 const Rectangle aRA(aPixelRects[a]);
5883 basegfx::B2DRange aRB(aRA.Left(), aRA.Top(), aRA.Right() + 1, aRA.Bottom() + 1);
5884 aRB.transform(aTransform);
5885 aRanges.push_back(aRB);
5888 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5889 sdr::overlay::OVERLAY_SOLID,
5890 aCursorColor,
5891 aRanges,
5892 false);
5894 xOverlayManager->add(*pOverlay);
5895 mpOOCursors = new ::sdr::overlay::OverlayObjectList;
5896 mpOOCursors->append(*pOverlay);
5900 if ( aOldMode != aDrawMode )
5901 SetMapMode( aOldMode );
5904 void ScGridWindow::DeleteSelectionOverlay()
5906 DELETEZ( mpOOSelection );
5909 void ScGridWindow::UpdateSelectionOverlay()
5911 MapMode aDrawMode = GetDrawMapMode();
5912 MapMode aOldMode = GetMapMode();
5913 if ( aOldMode != aDrawMode )
5914 SetMapMode( aDrawMode );
5916 DeleteSelectionOverlay();
5917 std::vector<Rectangle> aPixelRects;
5918 GetSelectionRects( aPixelRects );
5920 if ( aPixelRects.size() && pViewData->IsActive() )
5922 // #i70788# get the OverlayManager safely
5923 rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager = getOverlayManager();
5925 if (xOverlayManager.is())
5927 std::vector< basegfx::B2DRange > aRanges;
5928 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
5930 for(sal_uInt32 a(0); a < aPixelRects.size(); a++)
5932 const Rectangle aRA(aPixelRects[a]);
5933 basegfx::B2DRange aRB(aRA.Left() - 1, aRA.Top() - 1, aRA.Right(), aRA.Bottom());
5934 aRB.transform(aTransform);
5935 aRanges.push_back(aRB);
5938 // get the system's highlight color
5939 const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
5940 const Color aHighlight(aSvtOptionsDrawinglayer.getHilightColor());
5942 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
5943 sdr::overlay::OVERLAY_TRANSPARENT,
5944 aHighlight,
5945 aRanges,
5946 true);
5948 xOverlayManager->add(*pOverlay);
5949 mpOOSelection = new ::sdr::overlay::OverlayObjectList;
5950 mpOOSelection->append(*pOverlay);
5954 if ( aOldMode != aDrawMode )
5955 SetMapMode( aOldMode );
5958 void ScGridWindow::DeleteAutoFillOverlay()
5960 DELETEZ( mpOOAutoFill );
5961 mpAutoFillRect.reset();
5964 void ScGridWindow::UpdateAutoFillOverlay()
5966 MapMode aDrawMode = GetDrawMapMode();
5967 MapMode aOldMode = GetMapMode();
5968 if ( aOldMode != aDrawMode )
5969 SetMapMode( aDrawMode );
5971 DeleteAutoFillOverlay();
5974 // get the AutoFill handle rectangle in pixels
5977 if ( bAutoMarkVisible && aAutoMarkPos.Tab() == pViewData->GetTabNo() &&
5978 !pViewData->HasEditView(eWhich) && pViewData->IsActive() )
5980 SCCOL nX = aAutoMarkPos.Col();
5981 SCROW nY = aAutoMarkPos.Row();
5983 if (!maVisibleRange.isInside(nX, nY))
5984 // Autofill mark is not visible. Bail out.
5985 return;
5987 SCTAB nTab = pViewData->GetTabNo();
5988 ScDocument* pDoc = pViewData->GetDocument();
5989 bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
5991 Point aFillPos = pViewData->GetScrPos( nX, nY, eWhich, true );
5992 long nSizeXPix;
5993 long nSizeYPix;
5994 pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix );
5995 if ( bLayoutRTL )
5996 aFillPos.X() -= nSizeXPix + 3;
5997 else
5998 aFillPos.X() += nSizeXPix - 2;
6000 aFillPos.Y() += nSizeYPix;
6001 aFillPos.Y() -= 2;
6002 mpAutoFillRect.reset(new Rectangle(aFillPos, Size(6, 6)));
6004 // #i70788# get the OverlayManager safely
6005 rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager = getOverlayManager();
6007 if (xOverlayManager.is())
6009 Color aHandleColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
6010 if (pViewData->GetActivePart() != eWhich)
6011 // non-active pane uses a different color.
6012 aHandleColor = SC_MOD()->GetColorConfig().GetColorValue(svtools::CALCPAGEBREAKAUTOMATIC).nColor;
6013 std::vector< basegfx::B2DRange > aRanges;
6014 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
6015 basegfx::B2DRange aRB(mpAutoFillRect->Left(), mpAutoFillRect->Top(), mpAutoFillRect->Right() + 1, mpAutoFillRect->Bottom() + 1);
6017 aRB.transform(aTransform);
6018 aRanges.push_back(aRB);
6020 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
6021 sdr::overlay::OVERLAY_SOLID,
6022 aHandleColor,
6023 aRanges,
6024 false);
6026 xOverlayManager->add(*pOverlay);
6027 mpOOAutoFill = new ::sdr::overlay::OverlayObjectList;
6028 mpOOAutoFill->append(*pOverlay);
6031 if ( aOldMode != aDrawMode )
6032 SetMapMode( aOldMode );
6036 void ScGridWindow::DeleteDragRectOverlay()
6038 DELETEZ( mpOODragRect );
6041 void ScGridWindow::UpdateDragRectOverlay()
6043 MapMode aDrawMode = GetDrawMapMode();
6044 MapMode aOldMode = GetMapMode();
6045 if ( aOldMode != aDrawMode )
6046 SetMapMode( aDrawMode );
6048 DeleteDragRectOverlay();
6051 // get the rectangles in pixels (moved from DrawDragRect)
6054 if ( bDragRect || bPagebreakDrawn )
6056 std::vector<Rectangle> aPixelRects;
6058 SCCOL nX1 = bDragRect ? nDragStartX : aPagebreakDrag.aStart.Col();
6059 SCROW nY1 = bDragRect ? nDragStartY : aPagebreakDrag.aStart.Row();
6060 SCCOL nX2 = bDragRect ? nDragEndX : aPagebreakDrag.aEnd.Col();
6061 SCROW nY2 = bDragRect ? nDragEndY : aPagebreakDrag.aEnd.Row();
6063 SCTAB nTab = pViewData->GetTabNo();
6065 SCCOL nPosX = pViewData->GetPosX(WhichH(eWhich));
6066 SCROW nPosY = pViewData->GetPosY(WhichV(eWhich));
6067 if (nX1 < nPosX) nX1 = nPosX;
6068 if (nX2 < nPosX) nX2 = nPosX;
6069 if (nY1 < nPosY) nY1 = nPosY;
6070 if (nY2 < nPosY) nY2 = nPosY;
6072 Point aScrPos( pViewData->GetScrPos( nX1, nY1, eWhich ) );
6074 long nSizeXPix=0;
6075 long nSizeYPix=0;
6076 ScDocument* pDoc = pViewData->GetDocument();
6077 double nPPTX = pViewData->GetPPTX();
6078 double nPPTY = pViewData->GetPPTY();
6079 SCCOLROW i;
6081 bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
6082 long nLayoutSign = bLayoutRTL ? -1 : 1;
6084 if (ValidCol(nX2) && nX2>=nX1)
6085 for (i=nX1; i<=nX2; i++)
6086 nSizeXPix += ScViewData::ToPixel( pDoc->GetColWidth( static_cast<SCCOL>(i), nTab ), nPPTX );
6087 else
6089 aScrPos.X() -= nLayoutSign;
6090 nSizeXPix += 2;
6093 if (ValidRow(nY2) && nY2>=nY1)
6094 for (i=nY1; i<=nY2; i++)
6095 nSizeYPix += ScViewData::ToPixel( pDoc->GetRowHeight( i, nTab ), nPPTY );
6096 else
6098 aScrPos.Y() -= 1;
6099 nSizeYPix += 2;
6102 aScrPos.X() -= 2 * nLayoutSign;
6103 aScrPos.Y() -= 2;
6104 Rectangle aRect( aScrPos.X(), aScrPos.Y(),
6105 aScrPos.X() + ( nSizeXPix + 2 ) * nLayoutSign, aScrPos.Y() + nSizeYPix + 2 );
6106 if ( bLayoutRTL )
6108 aRect.Left() = aRect.Right(); // end position is left
6109 aRect.Right() = aScrPos.X();
6112 if ( meDragInsertMode == INS_CELLSDOWN )
6114 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Top()+3, aRect.Left()+1, aRect.Bottom()-2 ) );
6115 aPixelRects.push_back( Rectangle( aRect.Right()-1, aRect.Top()+3, aRect.Right()-1, aRect.Bottom()-2 ) );
6116 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Top(), aRect.Right()-1, aRect.Top()+2 ) );
6117 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Bottom()-1, aRect.Right()-1, aRect.Bottom()-1 ) );
6119 else if ( meDragInsertMode == INS_CELLSRIGHT )
6121 aPixelRects.push_back( Rectangle( aRect.Left(), aRect.Top()+1, aRect.Left()+2, aRect.Bottom()-1 ) );
6122 aPixelRects.push_back( Rectangle( aRect.Right()-1, aRect.Top()+1, aRect.Right()-1, aRect.Bottom()-1 ) );
6123 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Top()+1, aRect.Right()-2, aRect.Top()+1 ) );
6124 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Bottom()-1, aRect.Right()-2, aRect.Bottom()-1 ) );
6126 else
6128 aPixelRects.push_back( Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() ) );
6129 aPixelRects.push_back( Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() ) );
6130 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 ) );
6131 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() ) );
6134 // #i70788# get the OverlayManager safely
6135 rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager = getOverlayManager();
6137 if (xOverlayManager.is())
6139 std::vector< basegfx::B2DRange > aRanges;
6140 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
6142 for(sal_uInt32 a(0); a < aPixelRects.size(); a++)
6144 const Rectangle aRA(aPixelRects[a]);
6145 basegfx::B2DRange aRB(aRA.Left(), aRA.Top(), aRA.Right() + 1, aRA.Bottom() + 1);
6146 aRB.transform(aTransform);
6147 aRanges.push_back(aRB);
6150 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
6151 sdr::overlay::OVERLAY_INVERT,
6152 Color(COL_BLACK),
6153 aRanges,
6154 false);
6156 xOverlayManager->add(*pOverlay);
6157 mpOODragRect = new ::sdr::overlay::OverlayObjectList;
6158 mpOODragRect->append(*pOverlay);
6162 if ( aOldMode != aDrawMode )
6163 SetMapMode( aOldMode );
6166 void ScGridWindow::DeleteHeaderOverlay()
6168 DELETEZ( mpOOHeader );
6171 void ScGridWindow::UpdateHeaderOverlay()
6173 MapMode aDrawMode = GetDrawMapMode();
6174 MapMode aOldMode = GetMapMode();
6175 if ( aOldMode != aDrawMode )
6176 SetMapMode( aDrawMode );
6178 DeleteHeaderOverlay();
6180 // Pixel rectangle is in aInvertRect
6181 if ( !aInvertRect.IsEmpty() )
6183 // #i70788# get the OverlayManager safely
6184 rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager = getOverlayManager();
6186 if (xOverlayManager.is())
6188 // Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
6189 std::vector< basegfx::B2DRange > aRanges;
6190 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
6191 basegfx::B2DRange aRB(aInvertRect.Left(), aInvertRect.Top(), aInvertRect.Right() + 1, aInvertRect.Bottom() + 1);
6193 aRB.transform(aTransform);
6194 aRanges.push_back(aRB);
6196 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
6197 sdr::overlay::OVERLAY_INVERT,
6198 Color(COL_BLACK),
6199 aRanges,
6200 false);
6202 xOverlayManager->add(*pOverlay);
6203 mpOOHeader = new ::sdr::overlay::OverlayObjectList;
6204 mpOOHeader->append(*pOverlay);
6208 if ( aOldMode != aDrawMode )
6209 SetMapMode( aOldMode );
6212 void ScGridWindow::DeleteShrinkOverlay()
6214 DELETEZ( mpOOShrink );
6217 void ScGridWindow::UpdateShrinkOverlay()
6219 MapMode aDrawMode = GetDrawMapMode();
6220 MapMode aOldMode = GetMapMode();
6221 if ( aOldMode != aDrawMode )
6222 SetMapMode( aDrawMode );
6224 DeleteShrinkOverlay();
6227 // get the rectangle in pixels
6230 Rectangle aPixRect;
6231 ScRange aRange;
6232 SCTAB nTab = pViewData->GetTabNo();
6233 if ( pViewData->IsRefMode() && nTab >= pViewData->GetRefStartZ() && nTab <= pViewData->GetRefEndZ() &&
6234 pViewData->GetDelMark( aRange ) )
6236 //! limit to visible area
6237 if ( aRange.aStart.Col() <= aRange.aEnd.Col() &&
6238 aRange.aStart.Row() <= aRange.aEnd.Row() )
6240 Point aStart = pViewData->GetScrPos( aRange.aStart.Col(),
6241 aRange.aStart.Row(), eWhich );
6242 Point aEnd = pViewData->GetScrPos( aRange.aEnd.Col()+1,
6243 aRange.aEnd.Row()+1, eWhich );
6244 aEnd.X() -= 1;
6245 aEnd.Y() -= 1;
6247 aPixRect = Rectangle( aStart,aEnd );
6251 if ( !aPixRect.IsEmpty() )
6253 // #i70788# get the OverlayManager safely
6254 rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager = getOverlayManager();
6256 if (xOverlayManager.is())
6258 std::vector< basegfx::B2DRange > aRanges;
6259 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation());
6260 basegfx::B2DRange aRB(aPixRect.Left(), aPixRect.Top(), aPixRect.Right() + 1, aPixRect.Bottom() + 1);
6262 aRB.transform(aTransform);
6263 aRanges.push_back(aRB);
6265 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection(
6266 sdr::overlay::OVERLAY_INVERT,
6267 Color(COL_BLACK),
6268 aRanges,
6269 false);
6271 xOverlayManager->add(*pOverlay);
6272 mpOOShrink = new ::sdr::overlay::OverlayObjectList;
6273 mpOOShrink->append(*pOverlay);
6277 if ( aOldMode != aDrawMode )
6278 SetMapMode( aOldMode );
6281 // #i70788# central method to get the OverlayManager safely
6282 rtl::Reference<sdr::overlay::OverlayManager> ScGridWindow::getOverlayManager()
6284 SdrPageView* pPV = pViewData->GetView()->GetScDrawView()->GetSdrPageView();
6286 if(pPV)
6288 SdrPageWindow* pPageWin = pPV->FindPageWindow( *this );
6290 if ( pPageWin )
6292 return (pPageWin->GetOverlayManager());
6296 return rtl::Reference<sdr::overlay::OverlayManager>();
6299 void ScGridWindow::flushOverlayManager()
6301 // #i70788# get the OverlayManager safely
6302 rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager = getOverlayManager();
6304 if (xOverlayManager.is())
6305 xOverlayManager->flush();
6308 void ScGridWindow::SetInRefMode( bool bInRefMode )
6310 WinBits nBits = GetStyle();
6311 if(bInRefMode)
6312 nBits |= WB_REFMODE;
6313 else
6314 nBits &= ~WB_REFMODE;
6316 SetStyle( nBits );
6319 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */