1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
20 #include <scitems.hxx>
24 #include <editeng/adjustitem.hxx>
25 #include <osl/diagnose.h>
26 #include <sal/log.hxx>
27 #include <sot/storage.hxx>
28 #include <editeng/eeitem.hxx>
29 #include <editeng/editobj.hxx>
30 #include <editeng/editstat.hxx>
31 #include <editeng/editview.hxx>
32 #include <editeng/flditem.hxx>
33 #include <editeng/justifyitem.hxx>
34 #include <editeng/outliner.hxx>
35 #include <editeng/misspellrange.hxx>
36 #include <o3tl/unit_conversion.hxx>
37 #include <sfx2/dispatch.hxx>
38 #include <sfx2/viewfrm.hxx>
39 #include <sfx2/docfile.hxx>
40 #include <sfx2/ipclient.hxx>
41 #include <svl/stritem.hxx>
42 #include <svl/sharedstringpool.hxx>
43 #include <vcl/canvastools.hxx>
44 #include <vcl/commandevent.hxx>
45 #include <vcl/cursor.hxx>
46 #include <vcl/dialoghelper.hxx>
47 #include <vcl/inputctx.hxx>
48 #include <vcl/settings.hxx>
49 #include <vcl/virdev.hxx>
50 #include <vcl/weldutils.hxx>
51 #include <sot/formats.hxx>
52 #include <comphelper/classids.hxx>
53 #include <comphelper/scopeguard.hxx>
55 #include <svx/svdview.hxx>
56 #include <svx/svdocapt.hxx>
57 #include <svx/svdpagv.hxx>
58 #include <svtools/optionsdrawinglayer.hxx>
60 #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
61 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
62 #include <com/sun/star/sheet/DataPilotTableHeaderData.hpp>
63 #include <com/sun/star/sheet/MemberResultFlags.hpp>
64 #include <com/sun/star/sheet/TableValidationVisibility.hpp>
65 #include <com/sun/star/awt/KeyModifier.hpp>
66 #include <com/sun/star/awt/MouseButton.hpp>
67 #include <com/sun/star/script/vba/VBAEventId.hpp>
68 #include <com/sun/star/script/vba/XVBAEventProcessor.hpp>
69 #include <com/sun/star/text/textfield/Type.hpp>
71 #include <com/sun/star/awt/XVclWindowPeer.hdl>
73 #include <gridwin.hxx>
74 #include <tabvwsh.hxx>
76 #include <viewdata.hxx>
77 #include <tabview.hxx>
80 #include <document.hxx>
83 #include <stlpool.hxx>
84 #include <printfun.hxx>
85 #include <cbutton.hxx>
88 #include <globstr.hrc>
89 #include <strings.hrc>
90 #include <editutil.hxx>
91 #include <scresid.hxx>
92 #include <inputhdl.hxx>
93 #include <uiitems.hxx>
94 #include <formulacell.hxx>
95 #include <patattr.hxx>
96 #include <notemark.hxx>
97 #include <rfindlst.hxx>
99 #include <docfunc.hxx>
100 #include <dbdocfun.hxx>
101 #include <dpobject.hxx>
102 #include <transobj.hxx>
103 #include <drwtrans.hxx>
104 #include <seltrans.hxx>
105 #include <sizedev.hxx>
106 #include <AccessibilityHints.hxx>
107 #include <dpsave.hxx>
108 #include <viewuno.hxx>
109 #include <compiler.hxx>
110 #include <editable.hxx>
111 #include <fillinfo.hxx>
112 #include <filterentries.hxx>
113 #include <drwlayer.hxx>
114 #include <validat.hxx>
115 #include <tabprotection.hxx>
116 #include <postit.hxx>
117 #include <dpcontrol.hxx>
118 #include <checklistmenu.hxx>
119 #include <clipparam.hxx>
120 #include <overlayobject.hxx>
121 #include <cellsuno.hxx>
122 #include <drawview.hxx>
123 #include <dragdata.hxx>
124 #include <cliputil.hxx>
125 #include <queryentry.hxx>
126 #include <markdata.hxx>
127 #include <externalrefmgr.hxx>
128 #include <spellcheckcontext.hxx>
129 #include <uiobject.hxx>
130 #include <undoblk.hxx>
131 #include <datamapper.hxx>
132 #include <inputopt.hxx>
133 #include <queryparam.hxx>
134 #include <SparklineList.hxx>
136 #include <officecfg/Office/Common.hxx>
138 #include <svx/PaletteManager.hxx>
139 #include <svx/sdrpagewindow.hxx>
140 #include <svx/sdr/overlay/overlaymanager.hxx>
141 #include <vcl/svapp.hxx>
142 #include <vcl/uitest/logger.hxx>
143 #include <vcl/uitest/eventdescription.hxx>
144 #include <svx/sdr/overlay/overlayselection.hxx>
145 #include <comphelper/lok.hxx>
146 #include <sfx2/lokhelper.hxx>
148 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
151 #include <boost/property_tree/json_parser.hpp>
153 #include <FilterListBox.hxx>
156 using namespace css::uno
;
158 struct ScGridWindow::MouseEventState
163 mbActivatePart(false)
167 #define SC_FILTERLISTBOX_LINES 12
169 ScGridWindow::VisibleRange::VisibleRange(const ScDocument
& rDoc
)
171 , mnCol2(rDoc
.MaxCol())
173 , mnRow2(rDoc
.MaxRow())
177 bool ScGridWindow::VisibleRange::isInside(SCCOL nCol
, SCROW nRow
) const
179 return mnCol1
<= nCol
&& nCol
<= mnCol2
&& mnRow1
<= nRow
&& nRow
<= mnRow2
;
182 bool ScGridWindow::VisibleRange::set(SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
)
184 bool bChanged
= mnCol1
!= nCol1
|| mnRow1
!= nRow1
|| mnCol2
!= nCol2
|| mnRow2
!= nRow2
;
194 // ListBox in a FloatingWindow (pParent)
195 ScFilterListBox::ScFilterListBox(weld::Window
* pParent
, ScGridWindow
* pGrid
,
196 SCCOL nNewCol
, SCROW nNewRow
, ScFilterBoxMode eNewMode
)
197 : xBuilder(Application::CreateBuilder(pParent
, u
"modules/scalc/ui/filterlist.ui"_ustr
))
198 , xPopover(xBuilder
->weld_popover(u
"FilterList"_ustr
))
199 , xTreeView(xBuilder
->weld_tree_view(u
"list"_ustr
))
205 , bGridHadMouseCaptured(pGrid
->IsMouseCaptured())
208 , nAsyncSelectHdl(nullptr)
210 xTreeView
->connect_row_activated(LINK(this, ScFilterListBox
, SelectHdl
));
211 xTreeView
->connect_key_press(LINK(this, ScFilterListBox
, KeyInputHdl
));
214 ScFilterListBox::~ScFilterListBox()
218 Application::RemoveUserEvent(nAsyncSelectHdl
);
219 nAsyncSelectHdl
= nullptr;
223 void ScFilterListBox::EndInit()
225 sal_Int32 nPos
= xTreeView
->get_selected_index();
234 IMPL_LINK(ScFilterListBox
, KeyInputHdl
, const KeyEvent
&, rKeyEvent
, bool)
238 vcl::KeyCode aCode
= rKeyEvent
.GetKeyCode();
239 // esc with no modifiers
240 if (!aCode
.GetModifier() && aCode
.GetCode() == KEY_ESCAPE
)
242 pGridWin
->ClickExtern(); // clears the listbox
247 if (aCode
.GetCode() == KEY_TAB
)
253 IMPL_LINK_NOARG(ScFilterListBox
, SelectHdl
, weld::TreeView
&, bool)
255 if (!bInit
&& !bCancelled
&& !nAsyncSelectHdl
)
257 int nPos
= xTreeView
->get_selected_index();
261 // #i81298# launch async so the box isn't deleted from modifications within FilterSelect
262 nAsyncSelectHdl
= Application::PostUserEvent(LINK(this, ScFilterListBox
, AsyncSelectHdl
));
268 IMPL_LINK_NOARG(ScFilterListBox
, AsyncSelectHdl
, void*, void)
270 nAsyncSelectHdl
= nullptr;
272 //tdf#133971 hold self-ref until we return
273 auto xThis(shared_from_this());
274 pGridWin
->FilterSelect(nSel
);
275 if (xThis
.use_count() == 1)
277 // tdf#133855 we got disposed by FilterSelect
280 pGridWin
->ClickExtern();
283 static bool lcl_IsEditableMatrix( ScDocument
& rDoc
, const ScRange
& rRange
)
285 // If it is an editable range and if there is a Matrix cell at the bottom right with an
286 // origin top left then the range will be set to contain the exact matrix.
287 //! Extract the MatrixEdges functions directly from the column ???
288 if ( !rDoc
.IsBlockEditable( rRange
.aStart
.Tab(), rRange
.aStart
.Col(),rRange
.aStart
.Row(),
289 rRange
.aEnd
.Col(),rRange
.aEnd
.Row() ) )
292 ScRefCellValue
aCell(rDoc
, rRange
.aEnd
);
294 return (aCell
.getType() == CELLTYPE_FORMULA
&& aCell
.getFormula()->GetMatrixOrigin(rDoc
, aPos
) && aPos
== rRange
.aStart
);
297 static void lcl_UnLockComment( ScDrawView
* pView
, const Point
& rPos
, const ScViewData
& rViewData
)
302 ScDocument
& rDoc
= rViewData
.GetDocument();
303 ScAddress
aCellPos( rViewData
.GetCurX(), rViewData
.GetCurY(), rViewData
.GetTabNo() );
304 ScPostIt
* pNote
= rDoc
.GetNote( aCellPos
);
305 SdrObject
* pObj
= pNote
? pNote
->GetCaption() : nullptr;
306 if( pObj
&& pObj
->GetLogicRect().Contains( rPos
) && ScDrawLayer::IsNoteCaption( pObj
) )
308 const ScProtectionAttr
* pProtAttr
= rDoc
.GetAttr( aCellPos
, ATTR_PROTECTION
);
309 bool bProtectAttr
= pProtAttr
->GetProtection() || pProtAttr
->GetHideCell() ;
310 bool bProtectDoc
= rDoc
.IsTabProtected( aCellPos
.Tab() ) || rViewData
.GetSfxDocShell()->IsReadOnly() ;
311 // unlock internal layer (if not protected), will be relocked in ScDrawView::MarkListHasChanged()
312 pView
->LockInternalLayer( bProtectDoc
&& bProtectAttr
);
316 static bool lcl_GetHyperlinkCell(
317 ScDocument
& rDoc
, SCCOL
& rPosX
, SCROW nPosY
, SCTAB nTab
, ScRefCellValue
& rCell
, OUString
& rURL
)
322 ScAddress
aPos(rPosX
, nPosY
, nTab
);
323 rCell
.assign(rDoc
, aPos
);
327 return false; // everything empty to the links
329 --rPosX
; // continue search
333 const ScPatternAttr
* pPattern
= rDoc
.GetPattern(aPos
);
334 if ( !pPattern
->GetItem(ATTR_HYPERLINK
).GetValue().isEmpty() )
336 rURL
= pPattern
->GetItem(ATTR_HYPERLINK
).GetValue();
339 else if (rCell
.getType() == CELLTYPE_EDIT
)
341 else if (rCell
.getType() == CELLTYPE_FORMULA
&& rCell
.getFormula()->IsHyperLinkCell())
344 return false; // other cell
352 static void lcl_GetMirror(Point
& rPoint
, tools::Rectangle
& rRect
, const tools::Long nWidth
)
354 tools::Long nLeft
= rRect
.Left();
355 tools::Long nRight
= rRect
.Right();
356 tools::Long nMirrorPX
= o3tl::convert(nWidth
, o3tl::Length::twip
, o3tl::Length::px
);
357 tools::Long nMirrorMM
= o3tl::convert(nWidth
, o3tl::Length::twip
, o3tl::Length::mm100
);
359 rPoint
.setX(nMirrorPX
- rPoint
.X());
360 rRect
.SetLeft(nMirrorMM
- nRight
);
361 rRect
.SetRight(nMirrorMM
- nLeft
);
364 // WB_DIALOGCONTROL needed for UNO-Controls
365 ScGridWindow::ScGridWindow( vcl::Window
* pParent
, ScViewData
& rData
, ScSplitPos eWhichPos
)
366 : DocWindow( pParent
, WB_CLIPCHILDREN
| WB_DIALOGCONTROL
),
367 DropTargetHelper( this ),
368 DragSourceHelper( this ),
369 maVisibleRange(rData
.GetDocument()),
372 nCursorHideCount( 0 ),
374 nMouseStatus( SC_GM_NONE
),
375 nNestedButtonState( ScNestedButtonState::NONE
),
377 pDragDPObj( nullptr ),
381 nPagebreakMouse( SC_PD_NONE
),
382 nPagebreakBreak( 0 ),
384 nPageScript( SvtScriptType::NONE
),
389 meDragInsertMode( INS_NONE
),
390 aComboButton( GetOutDev() ),
393 aRFSelectedCorned( NONE
),
394 maShowPageBreaksTimer("ScGridWindow maShowPageBreaksTimer"),
399 bPagebreakDrawn( false ),
402 bNeedsRepaint( false ),
403 bAutoMarkVisible( false ),
404 bListValButton( false ),
408 set_id(u
"grid_window"_ustr
);
411 case SC_SPLIT_TOPLEFT
:
412 eHWhich
= SC_SPLIT_LEFT
;
413 eVWhich
= SC_SPLIT_TOP
;
415 case SC_SPLIT_TOPRIGHT
:
416 eHWhich
= SC_SPLIT_RIGHT
;
417 eVWhich
= SC_SPLIT_TOP
;
419 case SC_SPLIT_BOTTOMLEFT
:
420 eHWhich
= SC_SPLIT_LEFT
;
421 eVWhich
= SC_SPLIT_BOTTOM
;
423 case SC_SPLIT_BOTTOMRIGHT
:
424 eHWhich
= SC_SPLIT_RIGHT
;
425 eVWhich
= SC_SPLIT_BOTTOM
;
428 OSL_FAIL("GridWindow: wrong position");
431 SetUseFrameData(comphelper::LibreOfficeKit::isActive());
434 SetMapMode(mrViewData
.GetLogicMode(eWhich
));
435 EnableChildTransparentMode();
436 SetDialogControlFlags( DialogControlFlags::Return
| DialogControlFlags::WantFocus
);
438 SetHelpId( HID_SC_WIN_GRIDWIN
);
440 GetOutDev()->SetDigitLanguage( ScModule::GetOptDigitLanguage() );
443 bInitialPageBreaks
= true;
444 maShowPageBreaksTimer
.SetInvokeHandler(LINK(this, ScGridWindow
, InitiatePageBreaksTimer
));
445 maShowPageBreaksTimer
.SetTimeout(1);
448 ScGridWindow::~ScGridWindow()
453 void ScGridWindow::dispose()
455 maShowPageBreaksTimer
.Stop();
457 ImpDestroyOverlayObjects();
460 mpNoteMarker
.reset();
461 mpAutoFilterPopup
.reset();
462 mpDPFieldPopup
.reset();
463 aComboButton
.SetOutputDevice(nullptr);
466 mpSpellCheckCxt
->reset();
467 mpSpellCheckCxt
.reset();
469 vcl::Window::dispose();
472 void ScGridWindow::ClickExtern()
476 // #i84277# when initializing the filter box, a Basic error can deactivate the view
477 if (mpFilterBox
&& mpFilterBox
->IsInInit())
485 mpDPFieldPopup
->close(false);
486 mpDPFieldPopup
.reset();
490 IMPL_LINK_NOARG(ScGridWindow
, PopupModeEndHdl
, weld::Popover
&, void)
494 bool bMouseWasCaptured
= mpFilterBox
->MouseWasCaptured();
495 mpFilterBox
->SetCancelled(); // cancel select
496 // restore the mouse capture state of the GridWindow to
497 // what it was at initial popup time
498 SAL_WARN_IF(bMouseWasCaptured
, "sc.ui", "Is there a scenario where the mouse was captured before mouse down?");
499 if (bMouseWasCaptured
)
505 IMPL_LINK( ScGridWindow
, PopupSpellingHdl
, SpellCallbackInfo
&, rInfo
, void )
507 if( rInfo
.nCommand
== SpellCallbackCommand::STARTSPELLDLG
)
508 mrViewData
.GetDispatcher().Execute( SID_SPELL_DIALOG
, SfxCallMode::ASYNCHRON
);
509 else if (rInfo
.nCommand
== SpellCallbackCommand::AUTOCORRECT_OPTIONS
)
510 mrViewData
.GetDispatcher().Execute( SID_AUTO_CORRECT_DLG
, SfxCallMode::ASYNCHRON
);
511 else //IGNOREWORD, ADDTODICTIONARY, WORDLANGUAGE, PARALANGUAGE
513 // The spelling status of the word has changed. Close the cell to reset the caches
514 ScInputHandler
* pHdl
= ScModule::get()->GetInputHdl(mrViewData
.GetViewShell());
516 pHdl
->EnterHandler();
522 struct AutoFilterData
: public ScCheckListMenuControl::ExtendedData
528 class AutoFilterAction
: public ScCheckListMenuControl::Action
531 VclPtr
<ScGridWindow
> mpWindow
;
532 ScGridWindow::AutoFilterMode meMode
;
534 AutoFilterAction(ScGridWindow
* p
, ScGridWindow::AutoFilterMode eMode
) :
535 mpWindow(p
), meMode(eMode
) {}
536 virtual bool execute() override
538 mpWindow
->UpdateAutoFilterFromMenu(meMode
);
539 // UpdateAutoFilterFromMenu manually closes the popup so return
540 // false to not attempt a second close
545 class AutoFilterPopupEndAction
: public ScCheckListMenuControl::Action
547 VclPtr
<ScGridWindow
> mpWindow
;
550 AutoFilterPopupEndAction(ScGridWindow
* p
, const ScAddress
& rPos
) :
551 mpWindow(p
), maPos(rPos
) {}
552 virtual bool execute() override
554 mpWindow
->RefreshAutoFilterButton(maPos
);
555 mpWindow
->GrabFocus();
556 return false; // this is called after the popup has been closed
560 class AutoFilterSubMenuAction
: public AutoFilterAction
563 ScListSubMenuControl
* m_pSubMenu
;
566 AutoFilterSubMenuAction(ScGridWindow
* p
, ScListSubMenuControl
* pSubMenu
, ScGridWindow::AutoFilterMode eMode
)
567 : AutoFilterAction(p
, eMode
)
568 , m_pSubMenu(pSubMenu
)
573 class AutoFilterColorAction
: public AutoFilterSubMenuAction
579 AutoFilterColorAction(ScGridWindow
* p
, ScListSubMenuControl
* pSubMenu
, ScGridWindow::AutoFilterMode eMode
, const Color
& rColor
)
580 : AutoFilterSubMenuAction(p
, pSubMenu
, eMode
)
585 virtual bool execute() override
587 const AutoFilterData
* pData
=
588 static_cast<const AutoFilterData
*>(m_pSubMenu
->getExtendedData());
593 ScDBData
* pDBData
= pData
->mpData
;
597 const ScAddress
& rPos
= pData
->maPos
;
599 ScViewData
& rViewData
= m_pSubMenu
->GetViewData();
600 ScDocument
& rDoc
= rViewData
.GetDocument();
603 pDBData
->GetQueryParam(aParam
);
605 // Try to use the existing entry for the column (if one exists).
606 ScQueryEntry
* pEntry
= aParam
.FindEntryByField(rPos
.Col(), true);
610 // Something went terribly wrong!
614 if (ScTabViewShell::isAnyEditViewInRange(rViewData
.GetViewShell(), /*bColumns*/ false, aParam
.nRow1
, aParam
.nRow2
))
617 pEntry
->bDoQuery
= true;
618 pEntry
->nField
= rPos
.Col();
619 pEntry
->eConnect
= SC_AND
;
621 ScFilterEntries aFilterEntries
;
622 rDoc
.GetFilterEntries(rPos
.Col(), rPos
.Row(), rPos
.Tab(), aFilterEntries
);
624 bool bActive
= false;
625 ScQueryEntry::Item
& rItem
= pEntry
->GetQueryItem();
626 if (rItem
.maColor
== m_aColor
627 && ((meMode
== ScGridWindow::AutoFilterMode::TextColor
628 && rItem
.meType
== ScQueryEntry::ByTextColor
)
629 || (meMode
== ScGridWindow::AutoFilterMode::BackgroundColor
630 && rItem
.meType
== ScQueryEntry::ByBackgroundColor
)))
635 // Disable color filter when active color was selected
638 aParam
.RemoveAllEntriesByField(rPos
.Col());
639 pEntry
= nullptr; // invalidated by RemoveAllEntriesByField call
641 // tdf#46184 reset filter options to default values
642 aParam
.eSearchType
= utl::SearchParam::SearchType::Normal
;
643 aParam
.bCaseSens
= false;
644 aParam
.bDuplicate
= true;
645 aParam
.bInplace
= true;
649 if (meMode
== ScGridWindow::AutoFilterMode::TextColor
)
650 pEntry
->SetQueryByTextColor(m_aColor
);
652 pEntry
->SetQueryByBackgroundColor(m_aColor
);
655 rViewData
.GetView()->Query(aParam
, nullptr, true);
656 pDBData
->SetQueryParam(aParam
);
662 class AutoFilterSortColorAction
: public AutoFilterSubMenuAction
666 ScViewData
& m_rViewData
;
669 AutoFilterSortColorAction(ScGridWindow
* p
, ScListSubMenuControl
* pSubMenu
, ScGridWindow::AutoFilterMode eMode
, const Color
& rColor
, ScViewData
& rViewData
)
670 : AutoFilterSubMenuAction(p
, pSubMenu
, eMode
)
672 , m_rViewData(rViewData
)
676 virtual bool execute() override
678 const AutoFilterData
* pData
=
679 static_cast<const AutoFilterData
*>(m_pSubMenu
->getExtendedData());
684 ScDBData
* pDBData
= pData
->mpData
;
688 const ScAddress
& rPos
= pData
->maPos
;
689 SCCOL nCol
= rPos
.Col();
690 ScSortParam aSortParam
;
691 pDBData
->GetSortParam(aSortParam
);
692 if (nCol
< aSortParam
.nCol1
|| nCol
> aSortParam
.nCol2
)
696 bool bHasHeader
= pDBData
->HasHeader();
698 aSortParam
.bHasHeader
= bHasHeader
;
699 aSortParam
.bByRow
= true;
700 aSortParam
.bCaseSens
= false;
701 aSortParam
.bNaturalSort
= false;
702 aSortParam
.aDataAreaExtras
.mbCellNotes
= false;
703 aSortParam
.aDataAreaExtras
.mbCellDrawObjects
= true;
704 aSortParam
.aDataAreaExtras
.mbCellFormats
= true;
705 aSortParam
.bInplace
= true;
706 aSortParam
.maKeyState
[0].bDoSort
= true;
707 aSortParam
.maKeyState
[0].nField
= nCol
;
708 aSortParam
.maKeyState
[0].bAscending
= true;
709 aSortParam
.maKeyState
[0].aColorSortMode
= meMode
== ScGridWindow::AutoFilterMode::TextColor
710 ? ScColorSortMode::TextColor
711 : ScColorSortMode::BackgroundColor
;
712 aSortParam
.maKeyState
[0].aColorSortColor
= m_aColor
;
714 for (size_t i
= 1; i
< aSortParam
.GetSortKeyCount(); ++i
)
715 aSortParam
.maKeyState
[i
].bDoSort
= false;
717 m_rViewData
.GetViewShell()->UISort(aSortParam
);
723 class AutoFilterColorPopupStartAction
: public AutoFilterSubMenuAction
728 AutoFilterColorPopupStartAction(ScGridWindow
* p
, ScListSubMenuControl
* pSubMenu
, bool bIsFilter
)
729 : AutoFilterSubMenuAction(p
, pSubMenu
, ScGridWindow::AutoFilterMode::Normal
),
730 mbIsFilter(bIsFilter
)
734 virtual bool execute() override
736 const AutoFilterData
* pData
=
737 static_cast<const AutoFilterData
*>(m_pSubMenu
->getExtendedData());
742 ScDBData
* pDBData
= pData
->mpData
;
746 ScViewData
& rViewData
= m_pSubMenu
->GetViewData();
747 ScDocument
& rDoc
= rViewData
.GetDocument();
748 const ScAddress
& rPos
= pData
->maPos
;
750 ScFilterEntries aFilterEntries
;
751 rDoc
.GetFilterEntries(rPos
.Col(), rPos
.Row(), rPos
.Tab(), aFilterEntries
);
753 m_pSubMenu
->clearMenuItems();
755 XColorListRef xUserColorList
;
757 OUString
aPaletteName(officecfg::Office::Common::UserColors::PaletteName::get());
758 PaletteManager aPaletteManager
;
759 std::vector
<OUString
> aPaletteNames
= aPaletteManager
.GetPaletteList();
760 for (size_t i
= 0, nLen
= aPaletteNames
.size(); i
< nLen
; ++i
)
762 if (aPaletteName
== aPaletteNames
[i
])
764 aPaletteManager
.SetPalette(i
);
765 xUserColorList
= XPropertyList::AsColorList(
766 XPropertyList::CreatePropertyListFromURL(
767 XPropertyListType::Color
, aPaletteManager
.GetSelectedPalettePath()));
768 if (!xUserColorList
->Load())
769 xUserColorList
= nullptr;
775 pDBData
->GetQueryParam(aParam
);
776 ScQueryEntry
* pEntry
= aParam
.FindEntryByField(rPos
.Col(), true);
779 for (auto eMode
: {ScGridWindow::AutoFilterMode::BackgroundColor
, ScGridWindow::AutoFilterMode::TextColor
})
781 std::set
<Color
> aColors
= eMode
== ScGridWindow::AutoFilterMode::TextColor
782 ? aFilterEntries
.getTextColors()
783 : aFilterEntries
.getBackgroundColors();
785 for (auto& rColor
: aColors
)
787 bool bActive
= false;
791 ScQueryEntry::Item
& rItem
= pEntry
->GetQueryItem();
792 if (rItem
.maColor
== rColor
793 && ((eMode
== ScGridWindow::AutoFilterMode::TextColor
794 && rItem
.meType
== ScQueryEntry::ByTextColor
)
795 || (eMode
== ScGridWindow::AutoFilterMode::BackgroundColor
796 && rItem
.meType
== ScQueryEntry::ByBackgroundColor
)))
802 const bool bAutoColor
= rColor
== COL_AUTO
;
804 // ColorListBox::ShowPreview is similar
805 ScopedVclPtr
<VirtualDevice
> xDev(m_pSubMenu
->create_virtual_device());
806 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
807 Size
aImageSize(rStyleSettings
.GetListBoxPreviewDefaultPixelSize());
808 xDev
->SetOutputSize(aImageSize
);
809 const tools::Rectangle
aRect(Point(0, 0), aImageSize
);
813 const Color
aW(COL_WHITE
);
814 const Color
aG(0xef, 0xef, 0xef);
815 int nMinDim
= std::min(aImageSize
.Width(), aImageSize
.Height()) + 1;
816 int nCheckSize
= nMinDim
/ 3;
817 xDev
->DrawCheckered(aRect
.TopLeft(), aRect
.GetSize(), std::min(nCheckSize
, 8), aW
, aG
);
818 xDev
->SetFillColor();
821 xDev
->SetFillColor(rColor
);
823 xDev
->SetLineColor(rStyleSettings
.GetDisableColor());
824 xDev
->DrawRect(aRect
);
828 OUString sText
= eMode
== ScGridWindow::AutoFilterMode::TextColor
829 ? ScResId(SCSTR_FILTER_AUTOMATIC_COLOR
)
830 : ScResId(SCSTR_FILTER_NO_FILL
);
833 m_pSubMenu
->addMenuColorItem(
834 sText
, bActive
, *xDev
, nMenu
,
835 new AutoFilterColorAction(mpWindow
, m_pSubMenu
, eMode
, rColor
));
839 m_pSubMenu
->addMenuColorItem(
840 sText
, bActive
, *xDev
, nMenu
,
841 new AutoFilterSortColorAction(mpWindow
, m_pSubMenu
, eMode
, rColor
, rViewData
));
848 bool bFoundColorName
= false;
851 sal_Int32 nPos
= xUserColorList
->GetIndexOfColor(rColor
);
854 XColorEntry
* pColorEntry
= xUserColorList
->GetColor(nPos
);
855 sName
= pColorEntry
->GetName();
856 bFoundColorName
= true;
859 if (!bFoundColorName
)
860 sName
= "#" + rColor
.AsRGBHexString().toAsciiUpperCase();
864 m_pSubMenu
->addMenuColorItem(
865 sName
, bActive
, *xDev
, nMenu
,
866 new AutoFilterColorAction(mpWindow
, m_pSubMenu
, eMode
, rColor
));
870 m_pSubMenu
->addMenuColorItem(
871 sName
, bActive
, *xDev
, nMenu
,
872 new AutoFilterSortColorAction(mpWindow
, m_pSubMenu
, eMode
, rColor
,
881 m_pSubMenu
->resizeToFitMenuItems();
889 ScQueryEntry::QueryItemsType
& mrItems
;
890 svl::SharedStringPool
& mrPool
;
892 AddItemToEntry(ScQueryEntry::QueryItemsType
& rItems
, svl::SharedStringPool
& rPool
) :
893 mrItems(rItems
), mrPool(rPool
) {}
894 void operator() (const ScCheckListMenuControl::ResultEntry
& rEntry
)
898 ScQueryEntry::Item aNew
;
899 aNew
.maString
= mrPool
.intern(rEntry
.aName
);
900 // set the filter type to ByValue, if the filter condition is value
901 aNew
.meType
= rEntry
.bDate
? ScQueryEntry::ByDate
: rEntry
.bValue
? ScQueryEntry::ByValue
: ScQueryEntry::ByString
;
902 aNew
.mfVal
= rEntry
.nValue
;
903 mrItems
.push_back(aNew
);
908 class AddSelectedItemString
910 std::unordered_set
<OUString
>& mrSetString
;
911 std::unordered_set
<double>& mrSetValue
;
913 explicit AddSelectedItemString(std::unordered_set
<OUString
>& rString
, std::unordered_set
<double>& rValue
) :
914 mrSetString(rString
), mrSetValue(rValue
) {}
916 void operator() (const ScQueryEntry::Item
& rItem
)
918 if( rItem
.meType
== ScQueryEntry::QueryType::ByValue
)
919 mrSetValue
.insert(rItem
.mfVal
);
921 mrSetString
.insert(rItem
.maString
.getString());
925 void collectUIInformation(const OUString
& aRow
, const OUString
& aCol
, const OUString
& aevent
)
927 EventDescription aDescription
;
928 aDescription
.aAction
= "LAUNCH";
929 aDescription
.aID
= "grid_window";
930 aDescription
.aParameters
= {{aevent
, ""},
931 {"ROW", aRow
}, {"COL", aCol
}};
932 aDescription
.aParent
= "MainWindow";
933 aDescription
.aKeyWord
= "ScGridWinUIObject";
935 UITestLogger::getInstance().logEvent(aDescription
);
940 void ScGridWindow::LaunchAutoFilterMenu(SCCOL nCol
, SCROW nRow
)
942 SCTAB nTab
= mrViewData
.GetTabNo();
943 ScDocument
& rDoc
= mrViewData
.GetDocument();
944 bool bLOKActive
= comphelper::LibreOfficeKit::isActive();
946 mpAutoFilterPopup
.reset();
948 // Estimate the width (in pixels) of the longest text in the list
949 ScFilterEntries aFilterEntries
;
950 rDoc
.GetFilterEntries(nCol
, nRow
, nTab
, aFilterEntries
);
952 weld::Window
* pPopupParent
= GetFrameWeld();
953 int nColWidth
= ScViewData::ToPixel(rDoc
.GetColWidth(nCol
, nTab
), mrViewData
.GetPPTX());
954 mpAutoFilterPopup
.reset(new ScCheckListMenuControl(pPopupParent
, mrViewData
,
955 aFilterEntries
.mbHasDates
, nColWidth
));
957 int nMaxTextWidth
= 0;
958 if (aFilterEntries
.size() <= 10)
960 // do pixel calculation for all elements of short lists
961 for (const auto& rEntry
: aFilterEntries
)
963 const OUString
& aText
= rEntry
.GetString();
964 nMaxTextWidth
= std::max
<int>(nMaxTextWidth
, mpAutoFilterPopup
->GetTextWidth(aText
) + aText
.getLength() * 2);
969 // find the longest string, probably it will be the longest rendered text, too
970 // (performance optimization for long lists)
971 auto itMax
= aFilterEntries
.begin();
972 for (auto it
= itMax
; it
!= aFilterEntries
.end(); ++it
)
974 int nTextWidth
= it
->GetString().getLength();
975 if (nMaxTextWidth
< nTextWidth
)
977 nMaxTextWidth
= nTextWidth
;
981 nMaxTextWidth
= mpAutoFilterPopup
->GetTextWidth(itMax
->GetString()) + nMaxTextWidth
* 2;
984 // window should be at least as wide as the column, or the longest text + checkbox, scrollbar ... (it is estimated with 70 pixel now)
985 // window should be maximum 1024 pixel wide.
986 int nWindowWidth
= std::min
<int>(1024, nMaxTextWidth
+ 70);
987 nWindowWidth
= mpAutoFilterPopup
->IncreaseWindowWidthToFitText(nWindowWidth
);
988 nMaxTextWidth
= std::max
<int>(nMaxTextWidth
, nWindowWidth
- 70);
990 mpAutoFilterPopup
->setOKAction(new AutoFilterAction(this, AutoFilterMode::Normal
));
991 mpAutoFilterPopup
->setPopupEndAction(
992 new AutoFilterPopupEndAction(this, ScAddress(nCol
, nRow
, nTab
)));
993 std::unique_ptr
<AutoFilterData
> pData(new AutoFilterData
);
994 pData
->maPos
= ScAddress(nCol
, nRow
, nTab
);
996 Point aPos
= mrViewData
.GetScrPos(nCol
, nRow
, eWhich
);
997 tools::Long nSizeX
= 0;
998 tools::Long nSizeY
= 0;
999 mrViewData
.GetMergeSizePixel(nCol
, nRow
, nSizeX
, nSizeY
);
1002 // Reverse the zoom factor from aPos and nSize[X|Y]
1003 // before letting the autofilter window convert the to twips
1004 // with no zoom information.
1005 double fZoomX(mrViewData
.GetZoomX());
1006 double fZoomY(mrViewData
.GetZoomY());
1007 aPos
.setX(aPos
.getX() / fZoomX
);
1008 aPos
.setY(aPos
.getY() / fZoomY
);
1009 nSizeX
= nSizeX
/ fZoomX
;
1010 nSizeY
= nSizeY
/ fZoomY
;
1012 tools::Rectangle
aCellRect(bLOKActive
? aPos
: OutputToScreenPixel(aPos
), Size(nSizeX
, nSizeY
));
1014 ScDBData
* pDBData
= rDoc
.GetDBAtCursor(nCol
, nRow
, nTab
, ScDBDataPortion::AREA
);
1018 pData
->mpData
= pDBData
;
1019 mpAutoFilterPopup
->setExtendedData(std::move(pData
));
1021 ScQueryParam aParam
;
1022 pDBData
->GetQueryParam(aParam
);
1023 std::vector
<ScQueryEntry
*> aEntries
= aParam
.FindAllEntriesByField(nCol
);
1024 std::unordered_set
<OUString
> aSelectedString
;
1025 std::unordered_set
<double> aSelectedValue
;
1026 bool bQueryByNonEmpty
= aEntries
.size() == 1 && aEntries
[0]->IsQueryByNonEmpty();
1028 if (!bQueryByNonEmpty
)
1030 for (ScQueryEntry
* pEntry
: aEntries
)
1032 if (pEntry
&& pEntry
->eOp
== SC_EQUAL
)
1034 ScQueryEntry::QueryItemsType
& rItems
= pEntry
->GetQueryItems();
1035 std::for_each(rItems
.begin(), rItems
.end(), AddSelectedItemString(aSelectedString
, aSelectedValue
));
1040 // Populate the check box list.
1041 mpAutoFilterPopup
->setMemberSize(aFilterEntries
.size());
1042 for (auto it
= aFilterEntries
.begin(); it
!= aFilterEntries
.end(); ++it
)
1044 // tdf#140745 show (empty) entry on top of the checkbox list if not hidden by filter
1045 if (it
->GetString().isEmpty() && !it
->IsHiddenByFilter())
1047 const OUString
& aStringVal
= it
->GetString();
1048 const double aDoubleVal
= it
->GetValue();
1049 bool bSelected
= true;
1050 if (!aSelectedValue
.empty() || !aSelectedString
.empty())
1051 bSelected
= aSelectedString
.count(aStringVal
) > 0;
1052 else if (bQueryByNonEmpty
)
1054 // it->IsHiddenByFilter() is always false here so no need to evaluate it
1055 mpAutoFilterPopup
->addMember(aStringVal
, aDoubleVal
, bSelected
, false);
1056 aFilterEntries
.maStrData
.erase(it
);
1060 for (const auto& rEntry
: aFilterEntries
)
1062 const OUString
& aStringVal
= rEntry
.GetString();
1063 const double aDoubleVal
= rEntry
.GetValue();
1064 const double aRDoubleVal
= rEntry
.GetRoundedValue();
1065 bool bSelected
= !rEntry
.IsHiddenByFilter();
1067 if (!aSelectedValue
.empty() || !aSelectedString
.empty())
1069 if (rEntry
.GetStringType() == ScTypedStrData::Value
)
1071 if (aDoubleVal
== aRDoubleVal
)
1072 bSelected
= aSelectedValue
.count(aDoubleVal
) > 0
1073 || aSelectedString
.count(aStringVal
) > 0;
1075 bSelected
= aSelectedValue
.count(aDoubleVal
) > 0
1076 || aSelectedValue
.count(aRDoubleVal
) > 0
1077 || aSelectedString
.count(aStringVal
) > 0;
1080 bSelected
= aSelectedString
.count(aStringVal
) > 0;
1083 if ( rEntry
.IsDate() )
1084 mpAutoFilterPopup
->addDateMember( aStringVal
, rEntry
.GetValue(), bSelected
, rEntry
.IsHiddenByFilter());
1086 mpAutoFilterPopup
->addMember( aStringVal
, aRDoubleVal
, bSelected
, rEntry
.IsHiddenByFilter(),
1087 rEntry
.GetStringType() == ScTypedStrData::Value
);
1090 // Populate the menu.
1091 mpAutoFilterPopup
->addMenuItem(
1092 ScResId(STR_MENU_SORT_ASC
),
1093 new AutoFilterAction(this, AutoFilterMode::SortAscending
));
1094 mpAutoFilterPopup
->addMenuItem(
1095 ScResId(STR_MENU_SORT_DESC
),
1096 new AutoFilterAction(this, AutoFilterMode::SortDescending
));
1097 if (ScListSubMenuControl
* pSubMenu
= mpAutoFilterPopup
->addSubMenuItem(ScResId(SCSTR_SORT_COLOR
), true, true))
1098 pSubMenu
->setPopupStartAction(new AutoFilterColorPopupStartAction(this, pSubMenu
, false));
1099 mpAutoFilterPopup
->addSeparator();
1100 if (ScListSubMenuControl
* pSubMenu
= mpAutoFilterPopup
->addSubMenuItem(ScResId(SCSTR_FILTER_COLOR
), true, true))
1101 pSubMenu
->setPopupStartAction(new AutoFilterColorPopupStartAction(this, pSubMenu
, true));
1102 if (ScListSubMenuControl
* pSubMenu
= mpAutoFilterPopup
->addSubMenuItem(ScResId(SCSTR_FILTER_CONDITION
), true, false))
1104 pSubMenu
->addMenuItem(
1105 ScResId(SCSTR_FILTER_EMPTY
), new AutoFilterAction(this, AutoFilterMode::Empty
));
1106 pSubMenu
->addMenuItem(
1107 ScResId(SCSTR_FILTER_NOTEMPTY
), new AutoFilterAction(this, AutoFilterMode::NonEmpty
));
1108 pSubMenu
->addMenuItem(
1109 ScResId(SCSTR_TOP10FILTER
), new AutoFilterAction(this, AutoFilterMode::Top10
));
1110 pSubMenu
->addMenuItem(
1111 ScResId(SCSTR_BOTTOM10FILTER
), new AutoFilterAction(this, AutoFilterMode::Bottom10
));
1112 pSubMenu
->addSeparator();
1113 pSubMenu
->addMenuItem(
1114 ScResId(SCSTR_STDFILTER
), new AutoFilterAction(this, AutoFilterMode::Custom
));
1115 pSubMenu
->resizeToFitMenuItems();
1117 if (aEntries
.size())
1118 mpAutoFilterPopup
->addMenuItem(
1119 ScResId(SCSTR_CLEAR_FILTER
), new AutoFilterAction(this, AutoFilterMode::Clear
));
1121 mpAutoFilterPopup
->initMembers(nMaxTextWidth
+ 20); // 20 pixel estimated for the checkbox
1123 ScCheckListMenuControl::Config aConfig
;
1124 aConfig
.mbAllowEmptySet
= false;
1125 aConfig
.mbRTL
= mrViewData
.GetDocument().IsLayoutRTL(mrViewData
.GetTabNo());
1126 mpAutoFilterPopup
->setConfig(aConfig
);
1127 if (IsMouseCaptured())
1129 mpAutoFilterPopup
->launch(pPopupParent
, aCellRect
);
1131 // remember filter rules before modification
1132 mpAutoFilterPopup
->getResult(aSaveAutoFilterResult
);
1134 collectUIInformation(OUString::number(nRow
), OUString::number(nCol
),u
"AUTOFILTER"_ustr
);
1137 void ScGridWindow::RefreshAutoFilterButton(const ScAddress
& rPos
)
1141 bool bFilterActive
= IsAutoFilterActive(rPos
.Col(), rPos
.Row(), rPos
.Tab());
1142 mpFilterButton
->setHasHiddenMember(bFilterActive
);
1143 mpFilterButton
->setPopupPressed(false);
1144 mpFilterButton
->draw();
1148 void ScGridWindow::UpdateAutoFilterFromMenu(AutoFilterMode eMode
)
1150 // Terminate autofilter popup now when there is no further user input needed
1151 bool bColorMode
= eMode
== AutoFilterMode::TextColor
|| eMode
== AutoFilterMode::BackgroundColor
;
1153 mpAutoFilterPopup
->terminateAllPopupMenus();
1155 const AutoFilterData
* pData
=
1156 static_cast<const AutoFilterData
*>(mpAutoFilterPopup
->getExtendedData());
1161 const ScAddress
& rPos
= pData
->maPos
;
1162 ScDBData
* pDBData
= pData
->mpData
;
1166 ScDocument
& rDoc
= mrViewData
.GetDocument();
1167 svl::SharedStringPool
& rPool
= rDoc
.GetSharedStringPool();
1170 case AutoFilterMode::SortAscending
:
1171 case AutoFilterMode::SortDescending
:
1173 SCCOL nCol
= rPos
.Col();
1174 ScSortParam aSortParam
;
1175 pDBData
->GetSortParam(aSortParam
);
1176 if (nCol
< aSortParam
.nCol1
|| nCol
> aSortParam
.nCol2
)
1180 bool bHasHeader
= pDBData
->HasHeader();
1182 aSortParam
.bHasHeader
= bHasHeader
;
1183 aSortParam
.bByRow
= true;
1184 aSortParam
.bCaseSens
= false;
1185 aSortParam
.bNaturalSort
= false;
1186 aSortParam
.aDataAreaExtras
.mbCellNotes
= false;
1187 aSortParam
.aDataAreaExtras
.mbCellDrawObjects
= true;
1188 aSortParam
.aDataAreaExtras
.mbCellFormats
= true;
1189 aSortParam
.bInplace
= true;
1190 aSortParam
.maKeyState
[0].bDoSort
= true;
1191 aSortParam
.maKeyState
[0].nField
= nCol
;
1192 aSortParam
.maKeyState
[0].bAscending
= (eMode
== AutoFilterMode::SortAscending
);
1193 aSortParam
.maKeyState
[0].aColorSortMode
= ScColorSortMode::None
;
1195 for (size_t i
= 1; i
< aSortParam
.GetSortKeyCount(); ++i
)
1196 aSortParam
.maKeyState
[i
].bDoSort
= false;
1198 mrViewData
.GetViewShell()->UISort(aSortParam
);
1201 case AutoFilterMode::Custom
:
1204 pDBData
->GetArea(aRange
);
1205 mrViewData
.GetView()->MarkRange(aRange
);
1206 mrViewData
.GetView()->SetCursor(rPos
.Col(), rPos
.Row());
1207 mrViewData
.GetDispatcher().Execute(SID_FILTER
, SfxCallMode::SLOT
| SfxCallMode::RECORD
);
1214 ScQueryParam aParam
;
1215 pDBData
->GetQueryParam(aParam
);
1217 if (eMode
== AutoFilterMode::Normal
)
1219 // Do not recreate autofilter rules if there are no changes from the user
1220 ScCheckListMenuControl::ResultType aResult
;
1221 mpAutoFilterPopup
->getResult(aResult
);
1223 if (aResult
== aSaveAutoFilterResult
)
1225 SAL_INFO("sc.ui", "Apply autofilter to data when entries are the same");
1227 if (!mpAutoFilterPopup
->isAllSelected())
1229 // Apply autofilter to data
1230 ScQueryEntry
* pEntry
= aParam
.FindEntryByField(rPos
.Col(), true);
1231 pEntry
->bDoQuery
= true;
1232 pEntry
->nField
= rPos
.Col();
1233 pEntry
->eConnect
= SC_AND
;
1234 pEntry
->eOp
= SC_EQUAL
;
1235 mrViewData
.GetView()->Query(aParam
, nullptr, true);
1242 // Remove old entries in auto-filter rules
1245 aParam
.RemoveAllEntriesByField(rPos
.Col());
1247 // tdf#46184 reset filter options to default values
1248 aParam
.eSearchType
= utl::SearchParam::SearchType::Normal
;
1249 aParam
.bCaseSens
= false;
1250 aParam
.bDuplicate
= true;
1251 aParam
.bInplace
= true;
1254 if (eMode
!= AutoFilterMode::Clear
1255 && !(eMode
== AutoFilterMode::Normal
&& mpAutoFilterPopup
->isAllSelected()))
1257 // Try to use the existing entry for the column (if one exists).
1258 ScQueryEntry
* pEntry
= aParam
.FindEntryByField(rPos
.Col(), true);
1261 // Something went terribly wrong!
1264 if (ScTabViewShell::isAnyEditViewInRange(mrViewData
.GetViewShell(), /*bColumns*/ false, aParam
.nRow1
, aParam
.nRow2
))
1267 pEntry
->bDoQuery
= true;
1268 pEntry
->nField
= rPos
.Col();
1269 pEntry
->eConnect
= SC_AND
;
1273 case AutoFilterMode::Normal
:
1275 pEntry
->eOp
= SC_EQUAL
;
1277 ScCheckListMenuControl::ResultType aResult
;
1278 mpAutoFilterPopup
->getResult(aResult
);
1280 ScQueryEntry::QueryItemsType
& rItems
= pEntry
->GetQueryItems();
1282 std::for_each(aResult
.begin(), aResult
.end(), AddItemToEntry(rItems
, rPool
));
1285 case AutoFilterMode::Top10
:
1286 pEntry
->eOp
= SC_TOPVAL
;
1287 pEntry
->GetQueryItem().meType
= ScQueryEntry::ByString
;
1288 pEntry
->GetQueryItem().maString
= rPool
.intern(u
"10"_ustr
);
1290 case AutoFilterMode::Bottom10
:
1291 pEntry
->eOp
= SC_BOTVAL
;
1292 pEntry
->GetQueryItem().meType
= ScQueryEntry::ByString
;
1293 pEntry
->GetQueryItem().maString
= rPool
.intern(u
"10"_ustr
);
1295 case AutoFilterMode::Empty
:
1296 pEntry
->SetQueryByEmpty();
1298 case AutoFilterMode::NonEmpty
:
1299 pEntry
->SetQueryByNonEmpty();
1301 case AutoFilterMode::TextColor
:
1302 case AutoFilterMode::BackgroundColor
:
1303 assert(false && "should be handled by AutoFilterColorAction::execute");
1307 // We don't know how to handle this!
1312 mrViewData
.GetView()->Query(aParam
, nullptr, true);
1313 pDBData
->SetQueryParam(aParam
);
1318 void getCellGeometry(Point
& rScrPos
, Size
& rScrSize
, const ScViewData
& rViewData
, SCCOL nCol
, SCROW nRow
, ScSplitPos eWhich
)
1320 // Get the screen position of the cell.
1321 rScrPos
= rViewData
.GetScrPos(nCol
, nRow
, eWhich
);
1323 // Get the screen size of the cell.
1324 tools::Long nSizeX
, nSizeY
;
1325 rViewData
.GetMergeSizePixel(nCol
, nRow
, nSizeX
, nSizeY
);
1326 rScrSize
= Size(nSizeX
-1, nSizeY
-1);
1331 void ScGridWindow::LaunchPageFieldMenu( SCCOL nCol
, SCROW nRow
)
1334 // We assume that the page field button is located in cell to the immediate left.
1337 SCTAB nTab
= mrViewData
.GetTabNo();
1338 ScDPObject
* pDPObj
= mrViewData
.GetDocument().GetDPAtCursor(nCol
, nRow
, nTab
);
1344 getCellGeometry(aScrPos
, aScrSize
, mrViewData
, nCol
, nRow
, eWhich
);
1345 bool bLOK
= comphelper::LibreOfficeKit::isActive();
1346 DPLaunchFieldPopupMenu(bLOK
? aScrPos
: OutputToScreenPixel(aScrPos
), aScrSize
, ScAddress(nCol
-1, nRow
, nTab
), pDPObj
);
1349 void ScGridWindow::LaunchDPFieldMenu( SCCOL nCol
, SCROW nRow
)
1351 SCTAB nTab
= mrViewData
.GetTabNo();
1352 ScDPObject
* pDPObj
= mrViewData
.GetDocument().GetDPAtCursor(nCol
, nRow
, nTab
);
1358 getCellGeometry(aScrPos
, aScrSize
, mrViewData
, nCol
, nRow
, eWhich
);
1359 bool bLOK
= comphelper::LibreOfficeKit::isActive();
1360 DPLaunchFieldPopupMenu(bLOK
? aScrPos
: OutputToScreenPixel(aScrPos
), aScrSize
, ScAddress(nCol
, nRow
, nTab
), pDPObj
);
1363 void ScGridWindow::ShowFilterMenu(weld::Window
* pParent
, const tools::Rectangle
& rCellRect
, bool bLayoutRTL
)
1365 auto nSizeX
= rCellRect
.GetWidth();
1367 // minimum width in pixel
1368 if (comphelper::LibreOfficeKit::isActive())
1370 const tools::Long nMinLOKWinWidth
= o3tl::convert(STD_COL_WIDTH
* 13 / 10, o3tl::Length::twip
, o3tl::Length::px
);
1371 if (nSizeX
< nMinLOKWinWidth
)
1372 nSizeX
= nMinLOKWinWidth
;
1375 weld::TreeView
& rFilterBox
= mpFilterBox
->get_widget();
1376 int nEntryCount
= rFilterBox
.n_children();
1377 if (nEntryCount
> SC_FILTERLISTBOX_LINES
)
1378 nEntryCount
= SC_FILTERLISTBOX_LINES
;
1379 auto nHeight
= rFilterBox
.get_height_rows(nEntryCount
);
1380 rFilterBox
.set_size_request(-1, nHeight
);
1381 Size
aSize(rFilterBox
.get_preferred_size());
1382 auto nMaxToExpandTo
= std::min(nSizeX
, static_cast<decltype(nSizeX
)>(300)); // do not over do it (Pixel)
1383 if (aSize
.Width() < nMaxToExpandTo
)
1384 aSize
.setWidth(nMaxToExpandTo
);
1386 aSize
.AdjustWidth(4); // add a little margin
1388 aSize
.AdjustHeight(4);
1390 tools::Rectangle
aCellRect(rCellRect
);
1391 aCellRect
.AdjustLeft(-2); // offset the little margin above
1393 if (!bLayoutRTL
&& aSize
.Width() > nSizeX
)
1395 // move popup position
1396 tools::Long nDiff
= aSize
.Width() - nSizeX
;
1397 tools::Long nNewX
= aCellRect
.Left() - nDiff
;
1400 aCellRect
.SetLeft( nNewX
);
1403 rFilterBox
.set_size_request(aSize
.Width(), aSize
.Height());
1405 if (IsMouseCaptured())
1407 mpFilterBox
->popup_at_rect(pParent
, aCellRect
);
1410 void ScGridWindow::DoScenarioMenu( const ScRange
& rScenRange
)
1412 bool bMenuAtTop
= true;
1414 ScDocument
& rDoc
= mrViewData
.GetDocument();
1415 mpFilterBox
.reset();
1417 SCCOL nCol
= rScenRange
.aEnd
.Col(); // Cell is below the Buttons
1418 SCROW nRow
= rScenRange
.aStart
.Row();
1421 nRow
= rScenRange
.aEnd
.Row() + 1; // Range at very the top -> Button below
1422 if (nRow
>rDoc
.MaxRow()) nRow
= rDoc
.MaxRow();
1426 SCTAB nTab
= mrViewData
.GetTabNo();
1427 bool bLayoutRTL
= rDoc
.IsLayoutRTL( nTab
);
1429 tools::Long nSizeX
= 0;
1430 tools::Long nSizeY
= 0;
1431 mrViewData
.GetMergeSizePixel( nCol
, nRow
, nSizeX
, nSizeY
);
1432 // The button height should not use the merged cell height, should still use single row height
1433 nSizeY
= ScViewData::ToPixel(rDoc
.GetRowHeight(nRow
, nTab
), mrViewData
.GetPPTY());
1434 Point aPos
= mrViewData
.GetScrPos( nCol
, nRow
, eWhich
);
1436 aPos
.AdjustX( -nSizeX
);
1437 tools::Rectangle
aCellRect(aPos
, Size(nSizeX
, nSizeY
));
1438 aCellRect
.AdjustTop( -nSizeY
);
1439 aCellRect
.AdjustBottom( -(nSizeY
- 1) );
1442 Size aButSize
= mrViewData
.GetScenButSize();
1443 aCellRect
.AdjustBottom(aButSize
.Height());
1446 // Place the ListBox directly below the black line of the cell grid
1447 // (It looks odd if the line gets hidden...)
1449 weld::Window
* pParent
= weld::GetPopupParent(*this, aCellRect
);
1450 mpFilterBox
= std::make_shared
<ScFilterListBox
>(pParent
, this, nCol
, nRow
, ScFilterBoxMode::Scenario
);
1451 mpFilterBox
->connect_closed(LINK(this, ScGridWindow
, PopupModeEndHdl
));
1452 weld::TreeView
& rFilterBox
= mpFilterBox
->get_widget();
1453 rFilterBox
.set_direction(bLayoutRTL
); // Fix for bug fdo#44925 use sheet direction for widget RTL/LTR
1456 rFilterBox
.freeze();
1459 SCTAB nTabCount
= rDoc
.GetTableCount();
1460 for (SCTAB i
=nTab
+1; i
<nTabCount
&& rDoc
.IsScenario(i
); i
++)
1462 if (rDoc
.HasScenarioRange( i
, rScenRange
))
1463 if (rDoc
.GetName( i
, aTabName
))
1465 rFilterBox
.append_text(aTabName
);
1466 if (rDoc
.IsActiveScenario(i
))
1467 aCurrent
= aTabName
;
1472 ShowFilterMenu(pParent
, aCellRect
, bLayoutRTL
);
1474 rFilterBox
.grab_focus();
1476 sal_Int32 nPos
= -1;
1477 if (!aCurrent
.isEmpty())
1479 nPos
= rFilterBox
.find_text(aCurrent
);
1481 if (nPos
== -1 && rFilterBox
.n_children() > 0 )
1487 rFilterBox
.set_cursor(nPos
);
1488 rFilterBox
.select(nPos
);
1490 mpFilterBox
->EndInit();
1493 void ScGridWindow::LaunchDataSelectMenu(const SCCOL nCol
, const SCROW nRow
)
1495 mpFilterBox
.reset();
1497 ScDocument
& rDoc
= mrViewData
.GetDocument();
1498 const SCTAB nTab
= mrViewData
.GetTabNo();
1499 bool bLayoutRTL
= rDoc
.IsLayoutRTL( nTab
);
1501 tools::Long nSizeX
= 0;
1502 tools::Long nSizeY
= 0;
1503 mrViewData
.GetMergeSizePixel( nCol
, nRow
, nSizeX
, nSizeY
);
1504 Point aPos
= mrViewData
.GetScrPos( nCol
, nRow
, eWhich
);
1505 bool bLOKActive
= comphelper::LibreOfficeKit::isActive();
1509 // aPos is now view-zoom adjusted and in pixels an more importantly this is pixel aligned to the view-zoom,
1510 // but once we use this to set the position of the floating window, it has no information of view-zoom level
1511 // so if we don't reverse the zoom now, a simple PixelToLogic(aPos, MapMode(MapUnit::MapTwip)) employed in
1512 // FloatingWindow::ImplCalcPos will produce a 'scaled' twips position which will again get zoom scaled in the
1513 // client (effective double scaling) causing wrong positioning/size.
1514 double fZoomX(mrViewData
.GetZoomX());
1515 double fZoomY(mrViewData
.GetZoomY());
1516 aPos
.setX(aPos
.getX() / fZoomX
);
1517 aPos
.setY(aPos
.getY() / fZoomY
);
1518 nSizeX
= nSizeX
/ fZoomX
;
1519 nSizeY
= nSizeY
/ fZoomY
;
1523 aPos
.AdjustX( -nSizeX
);
1524 tools::Rectangle
aCellRect(aPos
, Size(nSizeX
, nSizeY
));
1526 weld::Window
* pParent
= comphelper::LibreOfficeKit::isActive() ? GetFrameWeld() : weld::GetPopupParent(*this, aCellRect
);
1527 mpFilterBox
= std::make_shared
<ScFilterListBox
>(pParent
, this, nCol
, nRow
, ScFilterBoxMode::DataSelect
);
1528 mpFilterBox
->connect_closed(LINK(this, ScGridWindow
, PopupModeEndHdl
));
1529 weld::TreeView
& rFilterBox
= mpFilterBox
->get_widget();
1530 rFilterBox
.set_direction(bLayoutRTL
); // Fix for bug fdo#44925 use sheet direction for widget RTL/LTR
1534 const sal_uInt32 nIndex
= rDoc
.GetAttr(nCol
, nRow
, nTab
, ATTR_VALIDDATA
)->GetValue();
1535 const ScValidationData
* pData
= nIndex
? rDoc
.GetValidationEntry(nIndex
) : nullptr;
1537 bool bEmpty
= false;
1538 std::vector
<ScTypedStrData
> aStrings
; // case sensitive
1540 rDoc
.GetDataEntries(nCol
, nRow
, nTab
, aStrings
, true /* bValidation */);
1542 // IsIgnoreBlank allows blank values. Don't add empty string unless "Allow Empty Cells"
1543 if (pData
&& !pData
->IsIgnoreBlank())
1545 auto lambda
= [](const ScTypedStrData
& rStr
) { return rStr
.GetString().isEmpty(); };
1546 std::erase_if(aStrings
, lambda
);
1549 if (aStrings
.empty())
1554 rFilterBox
.freeze();
1557 bool bWait
= aStrings
.size() > 100;
1562 for (const auto& rString
: aStrings
)
1564 const OUString
& rFilterString
= rString
.GetString();
1565 rFilterBox
.append_text(rFilterString
);
1573 ShowFilterMenu(pParent
, aCellRect
, bLayoutRTL
);
1576 sal_Int32 nSelPos
= -1;
1582 std::unique_ptr
<ScTypedStrData
> pNew
;
1583 OUString aDocStr
= rDoc
.GetString(nCol
, nRow
, nTab
);
1584 if ( rDoc
.HasValueData( nCol
, nRow
, nTab
) )
1586 double fVal
= rDoc
.GetValue(ScAddress(nCol
, nRow
, nTab
));
1587 pNew
.reset(new ScTypedStrData(aDocStr
, fVal
, fVal
, ScTypedStrData::Value
));
1590 pNew
.reset(new ScTypedStrData(aDocStr
, 0.0, 0.0, ScTypedStrData::Standard
));
1592 if (pData
->GetListType() == css::sheet::TableValidationVisibility::SORTEDASCENDING
)
1594 auto it
= std::lower_bound(aStrings
.begin(), aStrings
.end(), *pNew
, ScTypedStrData::LessCaseSensitive());
1595 if (it
!= aStrings
.end() && ScTypedStrData::EqualCaseSensitive()(*it
, *pNew
))
1596 nSelPos
= static_cast<sal_Int32
>(std::distance(aStrings
.begin(), it
));
1600 auto it
= std::find_if(aStrings
.begin(), aStrings
.end(), FindTypedStrData(*pNew
, true));
1601 if (it
!= aStrings
.end())
1602 nSelPos
= static_cast<sal_Int32
>(std::distance(aStrings
.begin(), it
));
1607 // Do not show an empty selection List:
1611 mpFilterBox
.reset();
1615 rFilterBox
.grab_focus();
1617 if (rFilterBox
.n_children())
1620 rFilterBox
.set_cursor(nSelPos
);
1622 rFilterBox
.set_cursor(0);
1624 // Select only after GrabFocus, so that the focus rectangle gets correct
1626 rFilterBox
.select(nSelPos
);
1628 rFilterBox
.unselect_all();
1630 mpFilterBox
->EndInit();
1632 collectUIInformation(OUString::number(nRow
), OUString::number(nCol
),u
"SELECTMENU"_ustr
);
1635 void ScGridWindow::FilterSelect( sal_uLong nSel
)
1637 weld::TreeView
& rFilterBox
= mpFilterBox
->get_widget();
1638 OUString aString
= rFilterBox
.get_text(static_cast<sal_Int32
>(nSel
));
1640 SCCOL nCol
= mpFilterBox
->GetCol();
1641 SCROW nRow
= mpFilterBox
->GetRow();
1642 switch (mpFilterBox
->GetMode())
1644 case ScFilterBoxMode::DataSelect
:
1645 ExecDataSelect(nCol
, nRow
, aString
);
1647 case ScFilterBoxMode::Scenario
:
1648 mrViewData
.GetView()->UseScenario(aString
);
1652 // coverity[check_after_deref] - could be destroyed by ExecDataSelect
1654 mpFilterBox
->popdown();
1656 GrabFocus(); // Otherwise the focus would be wrong on OS/2
1659 void ScGridWindow::ExecDataSelect( SCCOL nCol
, SCROW nRow
, const OUString
& rStr
)
1661 ScInputHandler
* pViewHdl
= ScModule::get()->GetInputHdl(mrViewData
.GetViewShell());
1662 if (pViewHdl
&& mrViewData
.HasEditView(mrViewData
.GetActivePart()))
1663 pViewHdl
->CancelHandler();
1665 SCTAB nTab
= mrViewData
.GetTabNo();
1666 ScViewFunc
* pView
= mrViewData
.GetView();
1667 pView
->EnterData( nCol
, nRow
, nTab
, rStr
);
1669 // #i52307# CellContentChanged is not in EnterData so it isn't called twice
1670 // if the cursor is moved afterwards.
1671 pView
->CellContentChanged();
1674 void ScGridWindow::MoveMouseStatus( ScGridWindow
& rDestWin
)
1678 rDestWin
.nButtonDown
= nButtonDown
;
1679 rDestWin
.nMouseStatus
= nMouseStatus
;
1684 rDestWin
.bRFMouse
= bRFMouse
;
1685 rDestWin
.bRFSize
= bRFSize
;
1686 rDestWin
.nRFIndex
= nRFIndex
;
1687 rDestWin
.nRFAddX
= nRFAddX
;
1688 rDestWin
.nRFAddY
= nRFAddY
;
1692 if (nPagebreakMouse
)
1694 rDestWin
.nPagebreakMouse
= nPagebreakMouse
;
1695 rDestWin
.nPagebreakBreak
= nPagebreakBreak
;
1696 rDestWin
.nPagebreakPrev
= nPagebreakPrev
;
1697 rDestWin
.aPagebreakSource
= aPagebreakSource
;
1698 rDestWin
.aPagebreakDrag
= aPagebreakDrag
;
1699 nPagebreakMouse
= SC_PD_NONE
;
1703 bool ScGridWindow::TestMouse( const MouseEvent
& rMEvt
, bool bAction
)
1705 // MouseEvent buttons must only be checked if bAction==TRUE
1706 // to allow changing the mouse pointer in MouseMove,
1707 // but not start AutoFill with right button (#74229#).
1708 // with bAction==sal_True, SetFillMode / SetDragMode is called
1710 if ( bAction
&& !rMEvt
.IsLeft() )
1713 bool bNewPointer
= false;
1715 SfxInPlaceClient
* pClient
= mrViewData
.GetViewShell()->GetIPClient();
1716 bool bOleActive
= ( pClient
&& pClient
->IsObjectInPlaceActive() );
1718 if ( mrViewData
.IsActive() && !bOleActive
&& !mrViewData
.GetViewShell()->IsLokReadOnlyView())
1720 ScDocument
& rDoc
= mrViewData
.GetDocument();
1721 SCTAB nTab
= mrViewData
.GetTabNo();
1722 bool bLayoutRTL
= rDoc
.IsLayoutRTL( nTab
);
1727 if (mrViewData
.GetSimpleArea( aMarkRange
) == SC_MARK_SIMPLE
)
1729 if (aMarkRange
.aStart
.Tab() == mrViewData
.GetTabNo() && mpAutoFillRect
)
1731 Point aMousePos
= rMEvt
.GetPosPixel();
1732 if (mpAutoFillRect
->Contains(aMousePos
))
1734 SetPointer( PointerStyle::Cross
); //! bold cross ?
1737 SCCOL nX
= aMarkRange
.aEnd
.Col();
1738 SCROW nY
= aMarkRange
.aEnd
.Row();
1740 if ( lcl_IsEditableMatrix( mrViewData
.GetDocument(), aMarkRange
) )
1741 mrViewData
.SetDragMode(
1742 aMarkRange
.aStart
.Col(), aMarkRange
.aStart
.Row(), nX
, nY
, ScFillMode::MATRIX
);
1744 mrViewData
.SetFillMode(
1745 aMarkRange
.aStart
.Col(), aMarkRange
.aStart
.Row(), nX
, nY
);
1747 // The simple selection must also be recognized when dragging,
1748 // where the Marking flag is set and MarkToSimple won't work anymore.
1749 mrViewData
.GetMarkData().MarkToSimple();
1756 // Embedded rectangle
1758 if (rDoc
.IsEmbedded())
1761 rDoc
.GetEmbedded( aRange
);
1762 if ( mrViewData
.GetTabNo() == aRange
.aStart
.Tab() )
1764 Point aStartPos
= mrViewData
.GetScrPos( aRange
.aStart
.Col(), aRange
.aStart
.Row(), eWhich
);
1765 Point aEndPos
= mrViewData
.GetScrPos( aRange
.aEnd
.Col()+1, aRange
.aEnd
.Row()+1, eWhich
);
1766 Point aMousePos
= rMEvt
.GetPosPixel();
1769 aStartPos
.AdjustX(2 );
1770 aEndPos
.AdjustX(2 );
1772 bool bTop
= ( aMousePos
.X() >= aStartPos
.X()-3 && aMousePos
.X() <= aStartPos
.X()+1 &&
1773 aMousePos
.Y() >= aStartPos
.Y()-3 && aMousePos
.Y() <= aStartPos
.Y()+1 );
1774 bool bBottom
= ( aMousePos
.X() >= aEndPos
.X()-3 && aMousePos
.X() <= aEndPos
.X()+1 &&
1775 aMousePos
.Y() >= aEndPos
.Y()-3 && aMousePos
.Y() <= aEndPos
.Y()+1 );
1776 if ( bTop
|| bBottom
)
1778 SetPointer( PointerStyle::Cross
);
1781 ScFillMode nMode
= bTop
? ScFillMode::EMBED_LT
: ScFillMode::EMBED_RB
;
1782 mrViewData
.SetDragMode(
1783 aRange
.aStart
.Col(), aRange
.aStart
.Row(),
1784 aRange
.aEnd
.Col(), aRange
.aEnd
.Row(), nMode
);
1792 if (!bNewPointer
&& bAction
)
1794 mrViewData
.ResetFillMode();
1800 void ScGridWindow::MouseButtonDown( const MouseEvent
& rMEvt
)
1802 if (SfxLokHelper::getDeviceFormFactor() == LOKDeviceFormFactor::MOBILE
)
1804 ScViewFunc
* pView
= mrViewData
.GetView();
1805 ScTabViewShell
* pViewShell
= mrViewData
.GetViewShell();
1806 bool bRefMode
= pViewShell
&& pViewShell
->IsRefInputMode();
1808 Point
aPos(rMEvt
.GetPosPixel());
1811 mrViewData
.GetPosFromPixel(aPos
.X(), aPos
.Y(), eWhich
, nPosX
, nPosY
);
1813 if (bRefMode
&& pView
->GetFunctionSet().CheckRefBounds(nPosX
, nPosY
))
1817 nNestedButtonState
= ScNestedButtonState::Down
;
1819 MouseEventState aState
;
1820 HandleMouseButtonDown(rMEvt
, aState
);
1821 if (aState
.mbActivatePart
)
1822 mrViewData
.GetView()->ActivatePart(eWhich
);
1824 if ( nNestedButtonState
== ScNestedButtonState::Up
)
1826 // #i41690# If an object is deactivated from MouseButtonDown, it might reschedule,
1827 // so MouseButtonUp comes before the MouseButtonDown call is finished. In this case,
1828 // simulate another MouseButtonUp call, so the selection state is consistent.
1830 nButtonDown
= rMEvt
.GetButtons();
1834 EndTracking(); // normally done in VCL as part of MouseButtonUp handling
1836 nNestedButtonState
= ScNestedButtonState::NONE
;
1839 void ScGridWindow::HandleMouseButtonDown( const MouseEvent
& rMEvt
, MouseEventState
& rState
)
1841 // We have to check if a context menu is shown and we have an UI
1842 // active inplace client. In that case we have to ignore the event.
1843 // Otherwise we would crash (context menu has been
1844 // opened by inplace client and we would deactivate the inplace client,
1845 // the context menu is closed by VCL asynchronously which in the end
1846 // would work on deleted objects or the context menu has no parent anymore)
1847 SfxViewShell
* pViewSh
= mrViewData
.GetViewShell();
1848 SfxInPlaceClient
* pClient
= pViewSh
->GetIPClient();
1850 pClient
->IsObjectInPlaceActive() &&
1851 vcl::IsInPopupMenuExecute() )
1854 aCurMousePos
= rMEvt
.GetPosPixel();
1856 // Filter popup is ended with its own mouse click, not when clicking into the Grid Window,
1857 // so the following query is no longer necessary:
1858 ClickExtern(); // deletes FilterBox when available
1864 ScModule
* pScMod
= ScModule::get();
1865 if (pScMod
->IsModalMode(mrViewData
.GetSfxDocShell()))
1868 const bool bWasMouseCaptured
= IsMouseCaptured();
1869 SAL_WARN_IF(bWasMouseCaptured
, "sc.ui", "Is there a scenario where the mouse is captured before mouse down?");
1871 pScActiveViewShell
= mrViewData
.GetViewShell(); // if left is clicked
1872 nScClickMouseModifier
= rMEvt
.GetModifier(); // to always catch a control click
1874 bool bDetective
= mrViewData
.GetViewShell()->IsAuditShell();
1875 bool bRefMode
= mrViewData
.IsRefMode(); // Start reference
1876 bool bFormulaMode
= pScMod
->IsFormulaMode(); // next click -> reference
1877 bool bEditMode
= mrViewData
.HasEditView(eWhich
); // also in Mode==SC_INPUT_TYPE
1878 bool bDouble
= (rMEvt
.GetClicks() == 2);
1879 ScDocument
& rDoc
= mrViewData
.GetDocument();
1880 bool bIsTiledRendering
= comphelper::LibreOfficeKit::isActive();
1882 // DeactivateIP does only happen when MarkListHasChanged
1884 // An error message can show up during GrabFocus call
1885 // (for instance when renaming tables per sheet title)
1887 if ( !nButtonDown
|| !bDouble
) // single (first) click is always valid
1888 nButtonDown
= rMEvt
.GetButtons(); // set nButtonDown first, so StopMarking works
1890 if ( ( bEditMode
&& mrViewData
.GetActivePart() == eWhich
) || !bFormulaMode
)
1893 // #i31846# need to cancel a double click if the first click has set the "ignore" state,
1894 // but a single (first) click is always valid
1895 if ( nMouseStatus
== SC_GM_IGNORE
&& bDouble
)
1898 nMouseStatus
= SC_GM_NONE
;
1902 if ( bDetective
) // Detectiv fill mode
1904 if ( rMEvt
.IsLeft() && !rMEvt
.GetModifier() )
1906 Point aPos
= rMEvt
.GetPosPixel();
1909 mrViewData
.GetPosFromPixel( aPos
.X(), aPos
.Y(), eWhich
, nPosX
, nPosY
);
1911 SfxInt16Item
aPosXItem( SID_RANGE_COL
, nPosX
);
1912 SfxInt32Item
aPosYItem( SID_RANGE_ROW
, nPosY
);
1913 mrViewData
.GetDispatcher().ExecuteList(SID_FILL_SELECT
,
1914 SfxCallMode::SLOT
| SfxCallMode::RECORD
,
1915 { &aPosXItem
, &aPosYItem
});
1919 nMouseStatus
= SC_GM_NONE
;
1924 nMouseStatus
= SC_GM_NONE
;
1926 rState
.mbActivatePart
= !bFormulaMode
; // Don't activate when in formula mode.
1930 ScViewSelectionEngine
* pSelEng
= mrViewData
.GetView()->GetSelEngine();
1931 pSelEng
->SetWindow(this);
1932 pSelEng
->SetWhich(eWhich
);
1933 pSelEng
->SetVisibleArea( tools::Rectangle(Point(), GetOutputSizePixel()) );
1936 if (bEditMode
&& (mrViewData
.GetRefTabNo() == mrViewData
.GetTabNo()))
1938 Point aPos
= rMEvt
.GetPosPixel();
1941 mrViewData
.GetPosFromPixel( aPos
.X(), aPos
.Y(), eWhich
, nPosX
, nPosY
);
1943 EditView
* pEditView
;
1946 mrViewData
.GetEditView( eWhich
, pEditView
, nEditCol
, nEditRow
);
1947 SCCOL nEndCol
= mrViewData
.GetEditEndCol();
1948 SCROW nEndRow
= mrViewData
.GetEditEndRow();
1949 SCCOL nStartCol
= mrViewData
.GetEditStartCol();
1951 if ( nPosX
>= nStartCol
&& nPosX
<= nEndCol
&&
1952 nPosY
>= nEditRow
&& nPosY
<= nEndRow
)
1954 // when clicking in the table EditView, always reset the focus
1955 if (bFormulaMode
) // otherwise this has already happen above
1958 pScMod
->SetInputMode( SC_INPUT_TABLE
);
1961 if (comphelper::LibreOfficeKit::isActive() && rDoc
.IsLayoutRTL(mrViewData
.GetTabNo()))
1963 Point aMouse
= rMEvt
.GetPosPixel();
1964 tools::Rectangle aOutputArea
= pEditView
->GetOutputArea();
1965 comphelper::ScopeGuard
aOutputGuard(
1966 [pEditView
, aOutputArea
] {
1967 pEditView
->SetOutputArea(aOutputArea
);
1970 lcl_GetMirror(aMouse
, aOutputArea
, mrViewData
.getLOKVisibleArea().GetWidth());
1971 pEditView
->SetOutputArea(aOutputArea
);
1973 MouseEvent
aEvent(aMouse
, rMEvt
.GetClicks(), rMEvt
.GetMode(),
1974 rMEvt
.GetButtons(), rMEvt
.GetModifier());
1975 pEditView
->MouseButtonDown( aEvent
);
1978 pEditView
->MouseButtonDown( rMEvt
);
1983 if (pScMod
->GetIsWaterCan())
1985 //! what's up with the Mac ???
1986 if ( rMEvt
.GetModifier() + rMEvt
.GetButtons() == MOUSE_RIGHT
)
1988 nMouseStatus
= SC_GM_WATERUNDO
;
1993 // Order that matches the displayed Cursor:
1994 // RangeFinder, AutoFill, PageBreak, Drawing
1996 RfCorner rCorner
= NONE
;
1997 bool bFound
= HitRangeFinder(rMEvt
.GetPosPixel(), rCorner
, &nRFIndex
, &nRFAddX
, &nRFAddY
);
1998 bRFSize
= (rCorner
!= NONE
);
1999 aRFSelectedCorned
= rCorner
;
2003 bRFMouse
= true; // the other variables are initialized above
2005 rState
.mbActivatePart
= true; // always activate ?
2010 bool bCrossPointer
= TestMouse( rMEvt
, true );
2011 if ( bCrossPointer
)
2014 mrViewData
.GetView()->FillCrossDblClick();
2016 pScMod
->InputEnterHandler(); // Autofill etc.
2019 if ( !bCrossPointer
)
2021 nPagebreakMouse
= HitPageBreak( rMEvt
.GetPosPixel(), &aPagebreakSource
,
2022 &nPagebreakBreak
, &nPagebreakPrev
);
2023 if (nPagebreakMouse
)
2025 bPagebreakDrawn
= false;
2027 PagebreakMove( rMEvt
, false );
2032 // in the tiled rendering case, single clicks into drawing objects take
2033 // precedence over bEditMode
2034 if (((!bFormulaMode
&& !bEditMode
) || bIsTiledRendering
) && rMEvt
.IsLeft())
2036 if ( !bCrossPointer
&& DrawMouseButtonDown(rMEvt
) )
2041 mrViewData
.GetViewShell()->SetDrawShell( false ); // no Draw-object selected
2043 // TestMouse has already happened above
2046 Point aPos
= rMEvt
.GetPosPixel();
2049 mrViewData
.GetPosFromPixel( aPos
.X(), aPos
.Y(), eWhich
, nPosX
, nPosY
);
2050 SCTAB nTab
= mrViewData
.GetTabNo();
2051 m_nDownPosX
= nPosX
;
2052 m_nDownPosY
= nPosY
;
2054 // FIXME: this is to limit the number of rows handled in the Online
2055 // to 1000; this will be removed again when the performance
2056 // bottlenecks are sorted out
2057 if ( comphelper::LibreOfficeKit::isActive() && nPosY
> MAXTILEDROW
- 1 )
2060 nMouseStatus
= SC_GM_NONE
;
2064 // Auto filter / pivot table / data select popup. This shouldn't activate the part.
2066 if ( !bDouble
&& !bFormulaMode
&& rMEvt
.IsLeft() )
2070 mrViewData
.GetPosFromPixel( aPos
.X(), aPos
.Y(), eWhich
, nRealPosX
, nRealPosY
, false );//the real row/col
2072 bool bAutoFilterDisable
= false;
2073 bool bPivotDisable
= false;
2075 if (rDoc
.IsTabProtected(nTab
))
2077 const ScTableProtection
* pTabProtection
= rDoc
.GetTabProtection(nTab
);
2078 bAutoFilterDisable
= pTabProtection
&& !pTabProtection
->isOptionEnabled(ScTableProtection::AUTOFILTER
);//autofilter
2079 bPivotDisable
= pTabProtection
&& !pTabProtection
->isOptionEnabled(ScTableProtection::PIVOT_TABLES
);//pivot
2082 // show in the merged cells the filter of the first cell (nPosX instead of nRealPosX)
2083 const ScMergeFlagAttr
* pRealPosAttr
= rDoc
.GetAttr(nPosX
, nRealPosY
, nTab
, ATTR_MERGE_FLAG
);
2085 if (!bAutoFilterDisable
&& pRealPosAttr
->HasAutoFilter())
2087 pScMod
->InputEnterHandler();
2088 if (DoAutoFilterButton(nPosX
, nRealPosY
, rMEvt
))
2092 const ScMergeFlagAttr
* pAttr
= rDoc
.GetAttr(nPosX
, nPosY
, nTab
, ATTR_MERGE_FLAG
);
2093 if (!bAutoFilterDisable
&& pAttr
->HasAutoFilter())
2095 if (DoAutoFilterButton(nPosX
, nPosY
, rMEvt
))
2097 rState
.mbActivatePart
= false;
2102 if (!bPivotDisable
&& (pAttr
->HasPivotButton() || pAttr
->HasPivotPopupButton() ||
2103 pAttr
->HasPivotMultiFieldPopupButton()))
2105 DoPushPivotButton(nPosX
, nPosY
, rMEvt
, pAttr
->HasPivotButton(),
2106 pAttr
->HasPivotPopupButton(), pAttr
->HasPivotMultiFieldPopupButton());
2107 rState
.mbActivatePart
= false;
2111 if (!bPivotDisable
&& pAttr
->HasPivotToggle())
2113 DoPushPivotToggle(nPosX
, nPosY
, rMEvt
);
2114 rState
.mbActivatePart
= false;
2117 // List Validity drop-down button
2119 if ( bListValButton
)
2121 tools::Rectangle aButtonRect
= GetListValButtonRect( aListValPos
);
2122 if ( aButtonRect
.Contains( aPos
) )
2124 // tdf#149609 if we captured the mouse in the course of this function
2125 // release it before showing the data select menu to undo any unhelpful
2127 if (!bWasMouseCaptured
&& IsMouseCaptured())
2130 LaunchDataSelectMenu( aListValPos
.Col(), aListValPos
.Row() );
2132 nMouseStatus
= SC_GM_FILTER
; // not set in DoAutoFilterMenue for bDataSelect
2133 rState
.mbActivatePart
= false;
2139 // scenario selection
2142 if ( rMEvt
.IsLeft() && HasScenarioButton( aPos
, aScenRange
) )
2144 // tdf#149609 if we captured the mouse in the course of this function
2145 // release it before showing the data scenario menu to undo any unhelpful
2147 if (!bWasMouseCaptured
&& IsMouseCaptured())
2150 DoScenarioMenu( aScenRange
);
2152 // Scenario selection comes from MouseButtonDown:
2153 // The next MouseMove on the FilterBox is like a ButtonDown
2154 nMouseStatus
= SC_GM_FILTER
;
2158 // double click started ?
2160 // StopMarking can be called from DrawMouseButtonDown
2162 if ( nMouseStatus
!= SC_GM_IGNORE
&& !bRefMode
)
2164 if ( bDouble
&& !bCrossPointer
)
2166 if (nMouseStatus
== SC_GM_TABDOWN
)
2167 nMouseStatus
= SC_GM_DBLDOWN
;
2170 nMouseStatus
= SC_GM_TABDOWN
;
2173 // links in the edit cell
2175 bool bAlt
= rMEvt
.IsMod2();
2176 if ( !bAlt
&& rMEvt
.IsLeft() && ScGlobal::ShouldOpenURL() &&
2177 GetEditUrl(rMEvt
.GetPosPixel()) ) // click on link: do not move cursor
2179 SetPointer( PointerStyle::RefHand
);
2180 nMouseStatus
= SC_GM_URLDOWN
; // also only execute when ButtonUp
2184 // Gridwin - Selection Engine
2186 if ( !rMEvt
.IsLeft() )
2189 ScViewSelectionEngine
* pSelEng
= mrViewData
.GetView()->GetSelEngine();
2190 pSelEng
->SetWindow(this);
2191 pSelEng
->SetWhich(eWhich
);
2192 pSelEng
->SetVisibleArea( tools::Rectangle(Point(), GetOutputSizePixel()) );
2194 // SelMouseButtonDown on the View is still setting the bMoveIsShift flag
2195 if ( mrViewData
.GetView()->SelMouseButtonDown( rMEvt
) )
2197 if (IsMouseCaptured())
2199 // Tracking instead of CaptureMouse, so it can be canceled cleanly
2200 //! Someday SelectionEngine should call StartTracking on its own!?!
2204 mrViewData
.GetMarkData().SetMarking(true);
2209 void ScGridWindow::MouseButtonUp( const MouseEvent
& rMEvt
)
2211 aCurMousePos
= rMEvt
.GetPosPixel();
2212 ScDocument
& rDoc
= mrViewData
.GetDocument();
2213 ScMarkData
& rMark
= mrViewData
.GetMarkData();
2214 // #i41690# detect a MouseButtonUp call from within MouseButtonDown
2215 // (possible through Reschedule from storing an OLE object that is deselected)
2217 if ( nNestedButtonState
== ScNestedButtonState::Down
)
2218 nNestedButtonState
= ScNestedButtonState::Up
;
2220 if (nButtonDown
!= rMEvt
.GetButtons())
2221 nMouseStatus
= SC_GM_IGNORE
; // reset and return
2225 if (nMouseStatus
== SC_GM_IGNORE
)
2227 nMouseStatus
= SC_GM_NONE
;
2228 // Selection engine: cancel selection
2229 mrViewData
.GetView()->GetSelEngine()->Reset();
2230 rMark
.SetMarking(false);
2231 if (mrViewData
.IsAnyFillMode())
2233 mrViewData
.GetView()->StopRefMode();
2234 mrViewData
.ResetFillMode();
2237 DrawEndAction(); // cancel selection/moving in drawing layer
2242 if (nMouseStatus
== SC_GM_FILTER
)
2244 nMouseStatus
= SC_GM_NONE
;
2246 return; // nothing more should happen here
2249 ScModule
* pScMod
= ScModule::get();
2250 if (pScMod
->IsModalMode(mrViewData
.GetSfxDocShell()))
2253 SfxBindings
& rBindings
= mrViewData
.GetBindings();
2254 if (bEEMouse
&& mrViewData
.HasEditView( eWhich
))
2256 EditView
* pEditView
;
2259 mrViewData
.GetEditView( eWhich
, pEditView
, nEditCol
, nEditRow
);
2261 if (comphelper::LibreOfficeKit::isActive() && rDoc
.IsLayoutRTL(mrViewData
.GetTabNo()))
2263 Point aMouse
= rMEvt
.GetPosPixel();
2264 tools::Rectangle aOutputArea
= pEditView
->GetOutputArea();
2265 comphelper::ScopeGuard
aOutputGuard(
2266 [pEditView
, aOutputArea
] {
2267 pEditView
->SetOutputArea(aOutputArea
);
2270 lcl_GetMirror(aMouse
, aOutputArea
, mrViewData
.getLOKVisibleArea().GetWidth());
2271 pEditView
->SetOutputArea(aOutputArea
);
2273 MouseEvent
aEvent(aMouse
, rMEvt
.GetClicks(), rMEvt
.GetMode(),
2274 rMEvt
.GetButtons(), rMEvt
.GetModifier());
2275 pEditView
->MouseButtonUp( aEvent
);
2278 pEditView
->MouseButtonUp( rMEvt
);
2280 if ( rMEvt
.IsMiddle() &&
2281 GetSettings().GetMouseSettings().GetMiddleButtonAction() == MouseMiddleButtonAction::PasteSelection
)
2283 // EditView may have pasted from selection
2284 pScMod
->InputChanged( pEditView
);
2287 pScMod
->InputSelection( pEditView
); // parentheses etc.
2289 mrViewData
.GetView()->InvalidateAttribs();
2290 rBindings
.Invalidate( SID_HYPERLINK_GETLINK
);
2297 DPMouseButtonUp( rMEvt
); // resets bDPMouse
2303 RFMouseMove( rMEvt
, true ); // Again the proper range
2305 SetPointer( PointerStyle::Arrow
);
2310 if (nPagebreakMouse
)
2312 PagebreakMove( rMEvt
, true );
2313 nPagebreakMouse
= SC_PD_NONE
;
2314 SetPointer( PointerStyle::Arrow
);
2319 if (nMouseStatus
== SC_GM_WATERUNDO
) // Undo in format paintbrush mode
2321 SfxUndoManager
* pMgr
= mrViewData
.GetDocShell()->GetUndoManager();
2322 if ( pMgr
->GetUndoActionCount() && dynamic_cast<ScUndoSelectionStyle
*>(pMgr
->GetUndoAction()) )
2327 if (DrawMouseButtonUp(rMEvt
)) // includes format paint brush handling for drawing objects
2329 ScTabViewShell
* pViewShell
= mrViewData
.GetViewShell();
2330 SfxBindings
& rFrmBindings
=pViewShell
->GetViewFrame().GetBindings();
2331 rFrmBindings
.Invalidate(SID_ATTR_TRANSFORM_WIDTH
);
2332 rFrmBindings
.Invalidate(SID_ATTR_TRANSFORM_HEIGHT
);
2333 rFrmBindings
.Invalidate(SID_ATTR_TRANSFORM_POS_X
);
2334 rFrmBindings
.Invalidate(SID_ATTR_TRANSFORM_POS_Y
);
2335 rFrmBindings
.Invalidate(SID_ATTR_TRANSFORM_ANGLE
);
2336 rFrmBindings
.Invalidate(SID_ATTR_TRANSFORM_ROT_X
);
2337 rFrmBindings
.Invalidate(SID_ATTR_TRANSFORM_ROT_Y
);
2338 rFrmBindings
.Invalidate(SID_ATTR_TRANSFORM_AUTOWIDTH
);
2339 rFrmBindings
.Invalidate(SID_ATTR_TRANSFORM_AUTOHEIGHT
);
2343 rMark
.SetMarking(false);
2345 SetPointer( mrViewData
.IsThemedCursor() ? PointerStyle::FatCross
: PointerStyle::Arrow
);
2347 if (mrViewData
.IsFillMode() ||
2348 ( mrViewData
.GetFillMode() == ScFillMode::MATRIX
&& rMEvt
.IsMod1() ))
2350 nScFillModeMouseModifier
= rMEvt
.GetModifier();
2355 mrViewData
.GetFillData( nStartCol
, nStartRow
, nEndCol
, nEndRow
);
2357 bool bIsDel
= mrViewData
.GetDelMark( aDelRange
);
2359 ScViewFunc
* pView
= mrViewData
.GetView();
2360 pView
->StopRefMode();
2361 mrViewData
.ResetFillMode();
2362 pView
->GetFunctionSet().SetAnchorFlag( false ); // #i5819# don't use AutoFill anchor flag for selection
2366 pView
->MarkRange( aDelRange
, false );
2367 pView
->DeleteContents( InsertDeleteFlags::CONTENTS
);
2368 SCTAB nTab
= mrViewData
.GetTabNo();
2369 ScRange
aBlockRange( nStartCol
, nStartRow
, nTab
, nEndCol
, nEndRow
, nTab
);
2370 if ( aBlockRange
!= aDelRange
)
2372 if ( aDelRange
.aStart
.Row() == nStartRow
)
2373 aBlockRange
.aEnd
.SetCol( aDelRange
.aStart
.Col() - 1 );
2375 aBlockRange
.aEnd
.SetRow( aDelRange
.aStart
.Row() - 1 );
2376 pView
->MarkRange( aBlockRange
, false );
2381 mrViewData
.GetDispatcher().Execute( FID_FILL_AUTO
, SfxCallMode::SLOT
| SfxCallMode::RECORD
);
2383 if (comphelper::LibreOfficeKit::isActive())
2385 // prepare AutoFill menu items for "Copy Cells" and "Fill Series"
2386 ScTabViewShell
* pViewShell
= mrViewData
.GetViewShell();
2387 boost::property_tree::ptree aMenu
;
2388 boost::property_tree::ptree aItemTree
;
2390 aItemTree
.put("text", "~Copy Cells");
2391 aItemTree
.put("type", "command");
2392 aItemTree
.put("command", ".uno:AutoFill?Copy:bool=true");
2393 aItemTree
.put("enabled", "true");
2394 aMenu
.push_back(std::make_pair("", aItemTree
));
2396 aItemTree
.put("text", "~Fill Series");
2397 aItemTree
.put("type", "command");
2398 aItemTree
.put("command", ".uno:AutoFill?Copy:bool=false");
2399 aItemTree
.put("enabled", "true");
2400 aMenu
.push_back(std::make_pair("", aItemTree
));
2403 boost::property_tree::ptree aRoot
;
2404 aRoot
.add_child("menu", aMenu
);
2406 std::stringstream aStream
;
2407 boost::property_tree::write_json(aStream
, aRoot
, true);
2409 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_CONTEXT_MENU
,
2410 OString(aStream
.str()));
2414 else if (mrViewData
.GetFillMode() == ScFillMode::MATRIX
)
2416 SCTAB nTab
= mrViewData
.GetTabNo();
2421 mrViewData
.GetFillData( nStartCol
, nStartRow
, nEndCol
, nEndRow
);
2422 ScRange
aBlockRange( nStartCol
, nStartRow
, nTab
, nEndCol
, nEndRow
, nTab
);
2423 SCCOL nFillCol
= mrViewData
.GetRefEndX();
2424 SCROW nFillRow
= mrViewData
.GetRefEndY();
2425 ScAddress
aEndPos( nFillCol
, nFillRow
, nTab
);
2427 ScTabView
* pView
= mrViewData
.GetView();
2428 pView
->StopRefMode();
2429 mrViewData
.ResetFillMode();
2430 pView
->GetFunctionSet().SetAnchorFlag( false );
2432 if ( aEndPos
!= aBlockRange
.aEnd
)
2434 mrViewData
.GetDocShell()->GetDocFunc().ResizeMatrix( aBlockRange
, aEndPos
);
2435 mrViewData
.GetView()->MarkRange( ScRange( aBlockRange
.aStart
, aEndPos
) );
2438 else if (mrViewData
.IsAnyFillMode())
2440 // Embedded area has been changed
2441 ScTabView
* pView
= mrViewData
.GetView();
2442 pView
->StopRefMode();
2443 mrViewData
.ResetFillMode();
2444 pView
->GetFunctionSet().SetAnchorFlag( false );
2445 mrViewData
.GetDocShell()->UpdateOle(mrViewData
);
2448 bool bRefMode
= mrViewData
.IsRefMode();
2450 pScMod
->EndReference();
2452 // Format paintbrush mode (Switch)
2454 if (pScMod
->GetIsWaterCan())
2456 // Check on undo already done above
2458 ScStyleSheetPool
* pStylePool
= mrViewData
.GetDocument().
2459 GetStyleSheetPool();
2462 SfxStyleSheet
* pStyleSheet
= static_cast<SfxStyleSheet
*>(
2463 pStylePool
->GetActualStyleSheet());
2467 SfxStyleFamily eFamily
= pStyleSheet
->GetFamily();
2471 case SfxStyleFamily::Para
:
2472 mrViewData
.GetView()->SetStyleSheetToMarked( pStyleSheet
);
2473 mrViewData
.GetView()->DoneBlockMode();
2476 case SfxStyleFamily::Page
:
2477 mrViewData
.GetDocument().SetPageStyle( mrViewData
.GetTabNo(),
2478 pStyleSheet
->GetName() );
2480 ScPrintFunc( mrViewData
.GetDocShell(),
2481 mrViewData
.GetViewShell()->GetPrinter(true),
2482 mrViewData
.GetTabNo() ).UpdatePages();
2484 rBindings
.Invalidate( SID_STATUS_PAGESTYLE
);
2494 ScDBFunc
* pView
= mrViewData
.GetView();
2495 ScDocument
* pBrushDoc
= pView
->GetBrushDocument();
2498 pView
->PasteFromClip( InsertDeleteFlags::ATTRIB
, pBrushDoc
);
2499 if ( !pView
->IsPaintBrushLocked() )
2500 pView
->ResetBrushDocument(); // invalidates pBrushDoc pointer
2503 Point aPos
= rMEvt
.GetPosPixel();
2506 SCTAB nTab
= mrViewData
.GetTabNo();
2507 mrViewData
.GetPosFromPixel( aPos
.X(), aPos
.Y(), eWhich
, nPosX
, nPosY
);
2508 ScDPObject
* pDPObj
= rDoc
.GetDPAtCursor( nPosX
, nPosY
, nTab
);
2510 // double click (only left button)
2512 bool bIsTiledRendering
= comphelper::LibreOfficeKit::isActive();
2513 if ( (rMEvt
.GetClicks() == 2 && rMEvt
.IsLeft())
2515 && (nMouseStatus
== SC_GM_DBLDOWN
|| (bIsTiledRendering
&& nMouseStatus
!= SC_GM_URLDOWN
))
2516 && !pScMod
->IsRefDialogOpen())
2519 if ( pDPObj
&& pDPObj
->GetSaveData()->GetDrillDown() )
2521 ScAddress
aCellPos( nPosX
, nPosY
, mrViewData
.GetTabNo() );
2523 // Check for header drill-down first.
2524 sheet::DataPilotTableHeaderData aData
;
2525 pDPObj
->GetHeaderPositionData(aCellPos
, aData
);
2527 if ( ( aData
.Flags
& sheet::MemberResultFlags::HASMEMBER
) &&
2528 ! ( aData
.Flags
& sheet::MemberResultFlags::SUBTOTAL
) )
2530 css::sheet::DataPilotFieldOrientation nDummy
;
2531 if ( pView
->HasSelectionForDrillDown( nDummy
) )
2533 // execute slot to show dialog
2534 mrViewData
.GetDispatcher().Execute( SID_OUTLINE_SHOW
, SfxCallMode::SLOT
| SfxCallMode::RECORD
);
2538 // toggle single entry
2539 ScDPObject
aNewObj( *pDPObj
);
2540 pDPObj
->ToggleDetails( aData
, &aNewObj
);
2541 ScDBDocFunc
aFunc( *mrViewData
.GetDocShell() );
2542 aFunc
.DataPilotUpdate( pDPObj
, &aNewObj
, true, false );
2543 mrViewData
.GetView()->CursorPosChanged(); // shells may be switched
2548 // Check if the data area is double-clicked.
2550 Sequence
<sheet::DataPilotFieldFilter
> aFilters
;
2551 if ( pDPObj
->GetDataFieldPositionData(aCellPos
, aFilters
) )
2552 mrViewData
.GetView()->ShowDataPilotSourceData( *pDPObj
, aFilters
);
2558 // Check for cell protection attribute.
2559 const ScTableProtection
* pProtect
= rDoc
.GetTabProtection(nTab
);
2560 bool bEditAllowed
= true;
2561 if ( pProtect
&& pProtect
->isProtected() )
2563 bool bCellProtected
= rDoc
.HasAttrib(nPosX
, nPosY
, nTab
, nPosX
, nPosY
, nTab
, HasAttrFlags::Protected
);
2564 bool bSkipProtected
= !pProtect
->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS
);
2565 bool bSkipUnprotected
= !pProtect
->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS
);
2567 if ( bSkipProtected
&& bSkipUnprotected
)
2568 bEditAllowed
= false;
2569 else if ( (bCellProtected
&& bSkipProtected
) || (!bCellProtected
&& bSkipUnprotected
) )
2570 bEditAllowed
= false;
2575 // edit cell contents
2576 mrViewData
.GetViewShell()->UpdateInputHandler();
2577 pScMod
->SetInputMode( SC_INPUT_TABLE
);
2578 if (mrViewData
.HasEditView(eWhich
))
2580 // Set text cursor where clicked
2581 EditView
* pEditView
= mrViewData
.GetEditView( eWhich
);
2582 MouseEvent
aEditEvt( rMEvt
.GetPosPixel(), 1, MouseEventModifiers::SYNTHETIC
, MOUSE_LEFT
, 0 );
2583 pEditView
->MouseButtonDown( aEditEvt
);
2584 pEditView
->MouseButtonUp( aEditEvt
);
2588 if ( bIsTiledRendering
&& rMEvt
.IsLeft() && mrViewData
.GetView()->GetSelEngine()->SelMouseButtonUp( rMEvt
) )
2590 mrViewData
.GetView()->SelectionChanged();
2596 // Links in edit cells
2598 bool bAlt
= rMEvt
.IsMod2();
2599 if ( !bAlt
&& !bRefMode
&& nMouseStatus
== SC_GM_URLDOWN
)
2601 // Only execute on ButtonUp, if ButtonDown also was done on a URL
2603 OUString aName
, aUrl
, aTarget
;
2605 if (GetEditUrl(rMEvt
.GetPosPixel(), &aName
, &aUrl
, &aTarget
, &nUrlCellX
))
2607 nMouseStatus
= SC_GM_NONE
; // Ignore double-click
2608 bool isTiledRendering
= comphelper::LibreOfficeKit::isActive();
2609 // ScGlobal::OpenURL() only understands Calc A1 style syntax.
2610 // Convert it to Calc A1 before calling OpenURL().
2611 if (rDoc
.GetAddressConvention() == formula::FormulaGrammar::CONV_OOO
)
2613 if (aUrl
.startsWith("#")) {
2614 ScGlobal::OpenURL(aUrl
, aTarget
, isTiledRendering
);
2617 // On a mobile device view there is no ctrl+click and for hyperlink popup
2618 // the cell coordinates must be sent along with click position for elegance
2619 ScTabViewShell
* pViewShell
= mrViewData
.GetViewShell();
2620 if (isTiledRendering
&& pViewShell
&&
2621 (pViewShell
->isLOKMobilePhone() || pViewShell
->isLOKTablet()))
2623 aPos
= rMEvt
.GetPosPixel();
2624 mrViewData
.GetPosFromPixel( aPos
.X(), aPos
.Y(), eWhich
, nPosX
, nPosY
);
2626 = pViewShell
->GetViewData().describeCellCursorAt(nUrlCellX
, nPosY
);
2627 double fPPTX
= pViewShell
->GetViewData().GetPPTX();
2628 int mouseX
= aPos
.X() / fPPTX
;
2629 int mouseY
= aPos
.Y() / fPPTX
;
2630 OString
aMsg(aUrl
.toUtf8() + " coordinates: " + aCursor
+ ", "
2631 + OString::number(mouseX
) + ", " + OString::number(mouseY
));
2632 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_HYPERLINK_CLICKED
, aMsg
);
2634 ScGlobal::OpenURL(aUrl
, aTarget
);
2638 ScAddress aTempAddr
;
2639 ScAddress::ExternalInfo aExtInfo
;
2640 ScRefFlags nRes
= aTempAddr
.Parse(aUrl
, rDoc
, rDoc
.GetAddressConvention(), &aExtInfo
);
2641 if (!(nRes
& ScRefFlags::VALID
))
2643 // Not a reference string. Pass it through unmodified.
2644 ScGlobal::OpenURL(aUrl
, aTarget
);
2648 OUStringBuffer aBuf
;
2649 if (aExtInfo
.mbExternal
)
2651 // External reference.
2652 ScExternalRefManager
* pRefMgr
= rDoc
.GetExternalRefManager();
2653 const OUString
* pStr
= pRefMgr
->getExternalFileName(aExtInfo
.mnFileId
);
2657 OUString
aRefCalcA1(aTempAddr
.Format(ScRefFlags::ADDR_ABS
, nullptr, formula::FormulaGrammar::CONV_OOO
));
2658 aBuf
.append("#" + aExtInfo
.maTabName
+ "." + aRefCalcA1
);
2659 ScGlobal::OpenURL(aBuf
.makeStringAndClear(), aTarget
);
2663 // Internal reference.
2664 OUString
aUrlCalcA1(aTempAddr
.Format(ScRefFlags::ADDR_ABS_3D
, &rDoc
, formula::FormulaGrammar::CONV_OOO
));
2665 aBuf
.append("#" + aUrlCalcA1
);
2666 ScGlobal::OpenURL(aBuf
.makeStringAndClear(), aTarget
, isTiledRendering
);
2670 // fire worksheet_followhyperlink event
2671 uno::Reference
< script::vba::XVBAEventProcessor
> xVbaEvents
= rDoc
.GetVbaEventProcessor();
2672 if( xVbaEvents
.is() ) try
2674 aPos
= rMEvt
.GetPosPixel();
2675 nTab
= mrViewData
.GetTabNo();
2676 mrViewData
.GetPosFromPixel( aPos
.X(), aPos
.Y(), eWhich
, nPosX
, nPosY
);
2678 ScRefCellValue aCell
;
2679 if (lcl_GetHyperlinkCell(rDoc
, nPosX
, nPosY
, nTab
, aCell
, sURL
))
2681 ScAddress
aCellPos( nPosX
, nPosY
, nTab
);
2682 uno::Reference
< table::XCell
> xCell( new ScCellObj( mrViewData
.GetDocShell(), aCellPos
) );
2683 uno::Sequence
< uno::Any
> aArgs
{ uno::Any(xCell
) };
2684 xVbaEvents
->processVbaEvent( script::vba::VBAEventId::WORKSHEET_FOLLOWHYPERLINK
, aArgs
);
2687 catch( uno::Exception
& )
2695 // Gridwin - SelectionEngine
2697 // SelMouseButtonDown is called only for left button, but SelMouseButtonUp would return
2698 // sal_True for any call, so IsLeft must be checked here, too.
2700 if ( !(rMEvt
.IsLeft() && mrViewData
.GetView()->GetSelEngine()->SelMouseButtonUp( rMEvt
)) )
2703 mrViewData
.GetView()->SelectionChanged();
2705 SfxDispatcher
* pDisp
= mrViewData
.GetViewShell()->GetDispatcher();
2706 bool bFormulaMode
= pScMod
->IsFormulaMode();
2707 OSL_ENSURE( pDisp
|| bFormulaMode
, "Cursor moved on inactive View ?" );
2709 // #i14927# execute SID_CURRENTCELL (for macro recording) only if there is no
2710 // multiple selection, so the argument string completely describes the selection,
2711 // and executing the slot won't change the existing selection (executing the slot
2712 // here and from a recorded macro is treated equally)
2713 if ( pDisp
&& !bFormulaMode
&& !rMark
.IsMultiMarked() )
2715 OUString aAddr
; // CurrentCell
2716 if( rMark
.IsMarked() )
2718 const ScRange
& aScRange
= rMark
.GetMarkArea();
2719 aAddr
= aScRange
.Format(rDoc
, ScRefFlags::RANGE_ABS
);
2720 if ( aScRange
.aStart
== aScRange
.aEnd
)
2722 // make sure there is a range selection string even for a single cell
2723 aAddr
+= ":" + aAddr
;
2726 //! SID_MARKAREA does not exist anymore ???
2727 //! What happens when selecting with the cursor ???
2729 else // only move cursor
2731 ScAddress
aScAddress( mrViewData
.GetCurX(), mrViewData
.GetCurY(), 0 );
2732 aAddr
= aScAddress
.Format(ScRefFlags::ADDR_ABS
);
2735 SfxStringItem
aPosItem( SID_CURRENTCELL
, aAddr
);
2736 // We don't want to align to the cursor position because if the
2737 // cell cursor isn't visible after making selection, it would jump
2738 // back to the origin of the selection where the cell cursor is.
2739 SfxBoolItem
aAlignCursorItem( FN_PARAM_2
, false );
2740 pDisp
->ExecuteList(SID_CURRENTCELL
,
2741 SfxCallMode::SLOT
| SfxCallMode::RECORD
,
2742 { &aPosItem
, &aAlignCursorItem
});
2744 mrViewData
.GetView()->InvalidateAttribs();
2747 mrViewData
.GetViewShell()->SelectionChanged();
2749 if (bIsTiledRendering
&& !bRefMode
)
2751 OUString aName
, aUrl
, aTarget
;
2752 ScTabViewShell
* pViewShell
= mrViewData
.GetViewShell();
2753 if (pViewShell
&& nPosX
== m_nDownPosX
&& nPosY
== m_nDownPosY
2754 && GetEditUrl(aPos
, &aName
, &aUrl
, &aTarget
, &nPosX
))
2756 OString
aMsg(aUrl
.toUtf8() + " coordinates: "
2757 + pViewShell
->GetViewData().describeCellCursorAt(nPosX
, nPosY
) + ", "
2758 + OString::number(aPos
.X() / pViewShell
->GetViewData().GetPPTX()) + ", "
2759 + OString::number(aPos
.Y() / pViewShell
->GetViewData().GetPPTY()));
2760 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_HYPERLINK_CLICKED
, aMsg
);
2764 m_nDownPosX
= m_nDownPosY
= -1;
2769 void ScGridWindow::FakeButtonUp()
2773 MouseEvent
aEvent( aCurMousePos
); // nButtons = 0 -> ignore
2774 MouseButtonUp( aEvent
);
2778 void ScGridWindow::MouseMove( const MouseEvent
& rMEvt
)
2780 aCurMousePos
= rMEvt
.GetPosPixel();
2782 if (rMEvt
.IsLeaveWindow() && mpNoteMarker
&& !mpNoteMarker
->IsByKeyboard())
2785 ScModule
* pScMod
= ScModule::get();
2786 if (pScMod
->IsModalMode(mrViewData
.GetSfxDocShell()))
2789 // If the Drag&Drop is started in the edit mode then sadly nothing else is kept
2790 if (bEEMouse
&& nButtonDown
&& !rMEvt
.GetButtons())
2794 nMouseStatus
= SC_GM_NONE
;
2798 if (nMouseStatus
== SC_GM_IGNORE
)
2801 if (nMouseStatus
== SC_GM_WATERUNDO
) // Undo in format paintbrush mode -> only what for Up
2804 if ( mrViewData
.GetViewShell()->IsAuditShell() ) // Detective Fill Mode
2806 SetPointer( PointerStyle::Fill
);
2810 bool bFormulaMode
= pScMod
->IsFormulaMode(); // next click -> reference
2812 if (bEEMouse
&& mrViewData
.HasEditView( eWhich
))
2814 EditView
* pEditView
;
2817 mrViewData
.GetEditView( eWhich
, pEditView
, nEditCol
, nEditRow
);
2819 if (comphelper::LibreOfficeKit::isActive() && mrViewData
.GetDocument().IsLayoutRTL(mrViewData
.GetTabNo()))
2821 Point aMouse
= rMEvt
.GetPosPixel();
2822 tools::Rectangle aOutputArea
= pEditView
->GetOutputArea();
2823 comphelper::ScopeGuard
aOutputGuard(
2824 [pEditView
, aOutputArea
] {
2825 pEditView
->SetOutputArea(aOutputArea
);
2828 lcl_GetMirror(aMouse
, aOutputArea
, mrViewData
.getLOKVisibleArea().GetWidth());
2829 pEditView
->SetOutputArea(aOutputArea
);
2831 MouseEvent
aEvent(aMouse
, rMEvt
.GetClicks(), rMEvt
.GetMode(),
2832 rMEvt
.GetButtons(), rMEvt
.GetModifier());
2834 pEditView
->MouseMove( aEvent
);
2837 pEditView
->MouseMove( rMEvt
);
2843 DPMouseMove( rMEvt
);
2849 RFMouseMove( rMEvt
, false );
2853 if (nPagebreakMouse
)
2855 PagebreakMove( rMEvt
, false );
2859 // Show other mouse pointer?
2861 bool bEditMode
= mrViewData
.HasEditView(eWhich
);
2863 //! Test if refMode dragging !!!
2864 if ( bEditMode
&& (mrViewData
.GetRefTabNo() == mrViewData
.GetTabNo()) )
2866 Point aPos
= rMEvt
.GetPosPixel();
2869 mrViewData
.GetPosFromPixel( aPos
.X(), aPos
.Y(), eWhich
, nPosX
, nPosY
);
2871 EditView
* pEditView
;
2874 mrViewData
.GetEditView( eWhich
, pEditView
, nEditCol
, nEditRow
);
2875 SCCOL nEndCol
= mrViewData
.GetEditEndCol();
2876 SCROW nEndRow
= mrViewData
.GetEditEndRow();
2878 if ( nPosX
>= nEditCol
&& nPosX
<= nEndCol
&&
2879 nPosY
>= nEditRow
&& nPosY
<= nEndRow
)
2883 SetPointer( PointerStyle::Text
);
2887 const SvxFieldItem
* pFld
;
2888 if ( comphelper::LibreOfficeKit::isActive() )
2890 Point aLogicClick
= pEditView
->GetOutputDevice().PixelToLogic(aPos
);
2891 pFld
= pEditView
->GetField( aLogicClick
);
2895 pFld
= pEditView
->GetFieldUnderMousePointer();
2897 // Field can only be URL field
2898 bool bAlt
= rMEvt
.IsMod2();
2899 if ( !bAlt
&& !nButtonDown
&& ScGlobal::ShouldOpenURL() && pFld
)
2900 SetPointer( PointerStyle::RefHand
);
2901 else if (pEditView
->getEditEngine().IsEffectivelyVertical())
2902 SetPointer( PointerStyle::TextVertical
);
2904 SetPointer( PointerStyle::Text
);
2909 bool bWater
= pScMod
->GetIsWaterCan() || mrViewData
.GetView()->HasPaintBrush();
2911 SetPointer( PointerStyle::Fill
);
2915 bool bCross
= false;
2919 RfCorner rCorner
= NONE
;
2920 if ( HitRangeFinder( rMEvt
.GetPosPixel(), rCorner
, nullptr, nullptr, nullptr ) )
2922 if (rCorner
!= NONE
)
2923 SetPointer( PointerStyle::Cross
);
2925 SetPointer( PointerStyle::Hand
);
2931 if ( !nButtonDown
&& mrViewData
.IsPagebreakMode() )
2933 sal_uInt16 nBreakType
= HitPageBreak( rMEvt
.GetPosPixel(), nullptr, nullptr, nullptr );
2934 if (nBreakType
!= 0 )
2936 PointerStyle eNew
= PointerStyle::Arrow
;
2937 switch ( nBreakType
)
2942 eNew
= PointerStyle::ESize
;
2947 eNew
= PointerStyle::SSize
;
2949 case SC_PD_RANGE_TL
:
2950 case SC_PD_RANGE_BR
:
2951 eNew
= PointerStyle::SESize
;
2953 case SC_PD_RANGE_TR
:
2954 case SC_PD_RANGE_BL
:
2955 eNew
= PointerStyle::NESize
;
2963 // Show fill cursor?
2965 if ( !bFormulaMode
&& !nButtonDown
)
2966 if (TestMouse( rMEvt
, false ))
2969 if ( nButtonDown
&& mrViewData
.IsAnyFillMode() )
2971 SetPointer( PointerStyle::Cross
);
2973 nScFillModeMouseModifier
= rMEvt
.GetModifier(); // evaluated for AutoFill and Matrix
2978 bool bAlt
= rMEvt
.IsMod2();
2980 if (bEditMode
) // First has to be in edit mode!
2981 SetPointer( mrViewData
.IsThemedCursor() ? PointerStyle::FatCross
: PointerStyle::Arrow
);
2982 else if ( !bAlt
&& !nButtonDown
&& ScGlobal::ShouldOpenURL() &&
2983 GetEditUrl(rMEvt
.GetPosPixel()) )
2984 SetPointer( PointerStyle::RefHand
);
2985 else if ( DrawMouseMove(rMEvt
) ) // Reset pointer
2990 // In LOK case, avoid spurious "leavingwindow" mouse move events which has negative coordinates.
2991 // Such events occur for some reason when a user is selecting a range, (even when not leaving the view area)
2992 // with one or more other viewers in that sheet.
2993 bool bSkipSelectionUpdate
= comphelper::LibreOfficeKit::isActive() &&
2994 rMEvt
.IsLeaveWindow() && (aCurMousePos
.X() < 0 || aCurMousePos
.Y() < 0);
2996 if (!bSkipSelectionUpdate
)
2997 mrViewData
.GetView()->GetSelEngine()->SelMouseMove( rMEvt
);
3000 static void lcl_InitMouseEvent(css::awt::MouseEvent
& rEvent
, const MouseEvent
& rEvt
)
3002 rEvent
.Modifiers
= 0;
3003 if ( rEvt
.IsShift() )
3004 rEvent
.Modifiers
|= css::awt::KeyModifier::SHIFT
;
3005 if ( rEvt
.IsMod1() )
3006 rEvent
.Modifiers
|= css::awt::KeyModifier::MOD1
;
3007 if ( rEvt
.IsMod2() )
3008 rEvent
.Modifiers
|= css::awt::KeyModifier::MOD2
;
3009 if ( rEvt
.IsMod3() )
3010 rEvent
.Modifiers
|= css::awt::KeyModifier::MOD3
;
3013 if ( rEvt
.IsLeft() )
3014 rEvent
.Buttons
|= css::awt::MouseButton::LEFT
;
3015 if ( rEvt
.IsRight() )
3016 rEvent
.Buttons
|= css::awt::MouseButton::RIGHT
;
3017 if ( rEvt
.IsMiddle() )
3018 rEvent
.Buttons
|= css::awt::MouseButton::MIDDLE
;
3020 rEvent
.X
= rEvt
.GetPosPixel().X();
3021 rEvent
.Y
= rEvt
.GetPosPixel().Y();
3022 rEvent
.ClickCount
= rEvt
.GetClicks();
3023 rEvent
.PopupTrigger
= false;
3026 bool ScGridWindow::PreNotify( NotifyEvent
& rNEvt
)
3029 NotifyEventType nType
= rNEvt
.GetType();
3030 if ( nType
== NotifyEventType::MOUSEBUTTONUP
|| nType
== NotifyEventType::MOUSEBUTTONDOWN
)
3032 vcl::Window
* pWindow
= rNEvt
.GetWindow();
3033 if (pWindow
== this)
3035 SfxViewFrame
& rViewFrame
= mrViewData
.GetViewShell()->GetViewFrame();
3036 css::uno::Reference
<css::frame::XController
> xController
= rViewFrame
.GetFrame().GetController();
3037 if (xController
.is())
3039 ScTabViewObj
* pImp
= dynamic_cast<ScTabViewObj
*>( xController
.get() );
3040 if (pImp
&& pImp
->IsMouseListening())
3042 css::awt::MouseEvent aEvent
;
3043 lcl_InitMouseEvent( aEvent
, *rNEvt
.GetMouseEvent() );
3044 if ( rNEvt
.GetWindow() )
3045 aEvent
.Source
= rNEvt
.GetWindow()->GetComponentInterface();
3046 if ( nType
== NotifyEventType::MOUSEBUTTONDOWN
)
3047 bDone
= pImp
->MousePressed( aEvent
);
3049 bDone
= pImp
->MouseReleased( aEvent
);
3054 if (bDone
) // event consumed by a listener
3056 if ( nType
== NotifyEventType::MOUSEBUTTONDOWN
)
3058 const MouseEvent
* pMouseEvent
= rNEvt
.GetMouseEvent();
3059 if ( pMouseEvent
->IsRight() && pMouseEvent
->GetClicks() == 1 )
3061 // If a listener returned true for a right-click call, also prevent opening the context menu
3062 // (this works only if the context menu is opened on mouse-down)
3063 nMouseStatus
= SC_GM_IGNORE
;
3070 return Window::PreNotify( rNEvt
);
3073 void ScGridWindow::Tracking( const TrackingEvent
& rTEvt
)
3075 // Since the SelectionEngine does not track, the events have to be
3076 // handed to the different MouseHandler...
3078 const MouseEvent
& rMEvt
= rTEvt
.GetMouseEvent();
3080 if ( rTEvt
.IsTrackingCanceled() ) // Cancel everything...
3082 if (!mrViewData
.GetView()->IsInActivatePart() && !ScModule::get()->IsRefDialogOpen())
3085 bDPMouse
= false; // Paint for each bDragRect
3089 UpdateDragRectOverlay();
3093 RFMouseMove( rMEvt
, true ); // Not possible to cancel properly...
3096 if (nPagebreakMouse
)
3098 bPagebreakDrawn
= false;
3099 UpdateDragRectOverlay();
3100 nPagebreakMouse
= SC_PD_NONE
;
3103 SetPointer( PointerStyle::Arrow
);
3105 MouseButtonUp( rMEvt
); // With status SC_GM_IGNORE from StopMarking
3107 bool bRefMode
= mrViewData
.IsRefMode();
3109 ScModule::get()->EndReference(); // Do not let the Dialog remain minimized
3112 else if ( rTEvt
.IsTrackingEnded() )
3114 if (!comphelper::LibreOfficeKit::isActive())
3116 // MouseButtonUp always with matching buttons (eg for test tool, # 63148 #)
3117 // The tracking event will indicate if it was completed and not canceled.
3118 MouseEvent
aUpEvt( rMEvt
.GetPosPixel(), rMEvt
.GetClicks(),
3119 rMEvt
.GetMode(), nButtonDown
, rMEvt
.GetModifier() );
3120 MouseButtonUp( aUpEvt
);
3127 void ScGridWindow::StartDrag( sal_Int8
/* nAction */, const Point
& rPosPixel
)
3129 if (mpFilterBox
|| nPagebreakMouse
)
3134 CommandEvent
aDragEvent( rPosPixel
, CommandEventId::StartDrag
, true );
3136 if (bEEMouse
&& mrViewData
.HasEditView( eWhich
))
3138 EditView
* pEditView
;
3141 mrViewData
.GetEditView( eWhich
, pEditView
, nEditCol
, nEditRow
);
3143 // don't remove the edit view while switching views
3144 ScModule
* pScMod
= ScModule::get();
3145 pScMod
->SetInEditCommand( true );
3147 pEditView
->Command( aDragEvent
);
3149 ScInputHandler
* pHdl
= pScMod
->GetInputHdl();
3151 pHdl
->DataChanged();
3153 pScMod
->SetInEditCommand( false );
3154 if (!mrViewData
.IsActive()) // dropped to different view?
3156 ScInputHandler
* pViewHdl
= pScMod
->GetInputHdl( mrViewData
.GetViewShell() );
3157 if ( pViewHdl
&& mrViewData
.HasEditView( eWhich
) )
3159 pViewHdl
->CancelHandler();
3160 ShowCursor(); // missing from KillEditView
3165 if ( !DrawCommand(aDragEvent
) )
3166 mrViewData
.GetView()->GetSelEngine()->Command( aDragEvent
);
3169 static void lcl_SetTextCursorPos( ScViewData
& rViewData
, ScSplitPos eWhich
, vcl::Window
* pWin
)
3171 SCCOL nCol
= rViewData
.GetCurX();
3172 SCROW nRow
= rViewData
.GetCurY();
3173 tools::Rectangle aEditArea
= rViewData
.GetEditArea( eWhich
, nCol
, nRow
, pWin
, nullptr, true );
3174 aEditArea
.SetRight( aEditArea
.Left() );
3175 aEditArea
= pWin
->PixelToLogic( aEditArea
);
3176 pWin
->SetCursorRect( &aEditArea
);
3179 void ScGridWindow::Command( const CommandEvent
& rCEvt
)
3181 // The command event is send to the window after a possible context
3182 // menu from an inplace client is closed. Now we have the chance to
3183 // deactivate the inplace client without any problem regarding parent
3184 // windows and code on the stack.
3185 CommandEventId nCmd
= rCEvt
.GetCommand();
3186 ScTabViewShell
* pTabViewSh
= mrViewData
.GetViewShell();
3187 SfxInPlaceClient
* pClient
= pTabViewSh
->GetIPClient();
3189 pClient
->IsObjectInPlaceActive() &&
3190 nCmd
== CommandEventId::ContextMenu
)
3192 pTabViewSh
->DeactivateOle();
3196 ScModule
* pScMod
= ScModule::get();
3197 OSL_ENSURE( nCmd
!= CommandEventId::StartDrag
, "ScGridWindow::Command called with CommandEventId::StartDrag" );
3199 if (nCmd
== CommandEventId::ModKeyChange
)
3201 Window::Command(rCEvt
);
3205 if ( nCmd
== CommandEventId::StartExtTextInput
||
3206 nCmd
== CommandEventId::EndExtTextInput
||
3207 nCmd
== CommandEventId::ExtTextInput
||
3208 nCmd
== CommandEventId::CursorPos
||
3209 nCmd
== CommandEventId::QueryCharPosition
)
3211 bool bEditView
= mrViewData
.HasEditView( eWhich
);
3214 // only if no cell editview is active, look at drawview
3215 SdrView
* pSdrView
= mrViewData
.GetView()->GetScDrawView();
3218 OutlinerView
* pOlView
= pSdrView
->GetTextEditOutlinerView();
3219 if ( pOlView
&& pOlView
->GetWindow() == this )
3221 pOlView
->Command( rCEvt
);
3227 if ( nCmd
== CommandEventId::CursorPos
&& !bEditView
)
3229 // CURSORPOS may be called without following text input,
3230 // to set the input method window position
3231 // -> input mode must not be started,
3232 // manually calculate text insert position if not in input mode
3234 lcl_SetTextCursorPos( mrViewData
, eWhich
, this );
3238 ScInputHandler
* pHdl
= pScMod
->GetInputHdl( mrViewData
.GetViewShell() );
3241 pHdl
->InputCommand( rCEvt
);
3245 Window::Command( rCEvt
);
3249 if ( nCmd
== CommandEventId::PasteSelection
)
3253 // EditEngine handles selection in MouseButtonUp - no action
3254 // needed in command handler
3258 PasteSelection( rCEvt
.GetMousePosPixel() );
3263 if ( nCmd
== CommandEventId::InputLanguageChange
)
3265 // #i55929# Font and font size state depends on input language if nothing is selected,
3266 // so the slots have to be invalidated when the input language is changed.
3268 SfxBindings
& rBindings
= mrViewData
.GetBindings();
3269 rBindings
.Invalidate( SID_ATTR_CHAR_FONT
);
3270 rBindings
.Invalidate( SID_ATTR_CHAR_FONTHEIGHT
);
3274 if ( nCmd
== CommandEventId::Wheel
|| nCmd
== CommandEventId::StartAutoScroll
|| nCmd
== CommandEventId::AutoScroll
)
3276 bool bDone
= mrViewData
.GetView()->ScrollCommand( rCEvt
, eWhich
);
3278 Window::Command(rCEvt
);
3282 if (nCmd
== CommandEventId::GesturePan
)
3284 bool bDone
= mrViewData
.GetView()->GesturePanCommand(rCEvt
);
3286 Window::Command(rCEvt
);
3290 if (nCmd
== CommandEventId::GestureZoom
)
3292 bool bDone
= mrViewData
.GetView()->GestureZoomCommand(rCEvt
);
3294 Window::Command(rCEvt
);
3298 // #i7560# FormulaMode check is below scrolling - scrolling is allowed during formula input
3299 bool bDisable
= pScMod
->IsFormulaMode() ||
3300 pScMod
->IsModalMode(mrViewData
.GetSfxDocShell());
3304 if (nCmd
!= CommandEventId::ContextMenu
|| pScMod
->GetIsWaterCan())
3307 bool bMouse
= rCEvt
.IsMouseEvent();
3308 if ( bMouse
&& nMouseStatus
== SC_GM_IGNORE
)
3311 if (mrViewData
.IsAnyFillMode())
3313 mrViewData
.GetView()->StopRefMode();
3314 mrViewData
.ResetFillMode();
3319 Point aPosPixel
= rCEvt
.GetMousePosPixel();
3320 Point aMenuPos
= aPosPixel
;
3322 bool bPosIsInEditView
= mrViewData
.HasEditView(eWhich
);
3325 mrViewData
.GetPosFromPixel(aPosPixel
.X(), aPosPixel
.Y(), eWhich
, nCellX
, nCellY
);
3326 // GetPosFromPixel ignores the fact that when editing a cell, the cell might grow to cover
3327 // other rows/columns. In addition, the mouse might now be outside the edited cell.
3328 if (bPosIsInEditView
)
3330 if (nCellX
>= mrViewData
.GetEditViewCol() && nCellX
<= mrViewData
.GetEditEndCol())
3331 nCellX
= mrViewData
.GetEditViewCol();
3333 bPosIsInEditView
= false;
3335 if (nCellY
>= mrViewData
.GetEditViewRow() && nCellY
<= mrViewData
.GetEditEndRow())
3336 nCellY
= mrViewData
.GetEditViewRow();
3338 bPosIsInEditView
= false;
3340 if (!bPosIsInEditView
)
3342 // Close the edit view when moving outside of the edited cell
3343 // to avoid showing the edit popup, or providing the wrong EditView to spellcheck.
3344 ScInputHandler
* pHdl
= pScMod
->GetInputHdl();
3346 pHdl
->EnterHandler();
3350 bool bSpellError
= false;
3351 SCCOL nColSpellError
= nCellX
;
3355 ScDocument
& rDoc
= mrViewData
.GetDocument();
3356 SCTAB nTab
= mrViewData
.GetTabNo();
3357 const ScTableProtection
* pProtect
= rDoc
.GetTabProtection(nTab
);
3358 bool bSelectAllowed
= true;
3359 if ( pProtect
&& pProtect
->isProtected() )
3361 // This sheet is protected. Check if a context menu is allowed on this cell.
3362 bool bCellProtected
= rDoc
.HasAttrib(nCellX
, nCellY
, nTab
, nCellX
, nCellY
, nTab
, HasAttrFlags::Protected
);
3363 bool bSelProtected
= pProtect
->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS
);
3364 bool bSelUnprotected
= pProtect
->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS
);
3367 bSelectAllowed
= bSelProtected
;
3369 bSelectAllowed
= bSelUnprotected
;
3371 if (!bSelectAllowed
)
3372 // Selecting this cell is not allowed, neither is context menu.
3375 if (mpSpellCheckCxt
)
3377 // Find the first string to the left for spell checking in case the current cell is empty.
3378 ScAddress
aPos(nCellX
, nCellY
, nTab
);
3379 ScRefCellValue
aSpellCheckCell(rDoc
, aPos
);
3380 while (!bPosIsInEditView
&& aSpellCheckCell
.getType() == CELLTYPE_NONE
)
3382 // Loop until we get the first non-empty cell in the row.
3387 aSpellCheckCell
.assign(rDoc
, aPos
);
3390 if (aPos
.Col() >= 0 && (aSpellCheckCell
.getType() == CELLTYPE_STRING
|| aSpellCheckCell
.getType() == CELLTYPE_EDIT
))
3391 nColSpellError
= aPos
.Col();
3393 // Is there possibly a misspelled word somewhere in the cell?
3394 // A "yes" does not mean that the word under the mouse pointer is wrong though.
3395 bSpellError
= (mpSpellCheckCxt
->isMisspelled(nColSpellError
, nCellY
));
3396 // Avoid situations where selecting the cell-with-wrong-spelling would be bad
3399 // When the mouse is over an empty cell, text with spelling errors
3400 // potentially could have overflowed underneath the mouse pointer
3401 if (nColSpellError
!= nCellX
)
3403 // If the mouse is over a selected cell, only consider spell-checking
3404 // if the cell with the misspelling is also selected. tdf#157038
3405 if (mrViewData
.GetMarkData().IsCellMarked(nCellX
, nCellY
))
3406 bSpellError
= mrViewData
.GetMarkData().IsCellMarked(nColSpellError
, nCellY
);
3411 // #i18735# First select the item under the mouse pointer.
3412 // This can change the selection, and the view state (edit mode, etc).
3413 SelectForContextMenu(aPosPixel
, bSpellError
? nColSpellError
: nCellX
, nCellY
);
3417 bool bEdit
= mrViewData
.HasEditView(eWhich
);
3421 // Edit cell with spelling errors?
3422 // tdf#127341 the formerly used GetEditUrl(aPosPixel) additionally
3423 // to bSpellError activated EditMode here for right-click on URL
3424 // which prevents the regular context-menu from appearing. Since this
3425 // is more expected than the context-menu for editing an URL, I removed
3426 // this. If this was wanted and can be argued it might be re-activated.
3427 // For now, reduce to spelling errors - as the original comment above
3429 if (bMouse
&& bSpellError
)
3431 // GetEditUrlOrError has already moved the Cursor
3433 pScMod
->SetInputMode( SC_INPUT_TABLE
);
3434 bEdit
= mrViewData
.HasEditView(eWhich
); // Did it work?
3436 OSL_ENSURE( bEdit
, "Can not be switched in edit mode" );
3441 EditView
* pEditView
= mrViewData
.GetEditView( eWhich
); // is then not 0
3445 vcl::Cursor
* pCur
= pEditView
->GetCursor();
3448 Point aLogicPos
= pCur
->GetPos();
3449 // use the position right of the cursor (spell popup is opened if
3450 // the cursor is before the word, but not if behind it)
3451 aLogicPos
.AdjustX(pCur
->GetWidth() );
3452 aLogicPos
.AdjustY(pCur
->GetHeight() / 2 ); // center vertically
3453 aMenuPos
= LogicToPixel( aLogicPos
);
3457 // if edit mode was just started above, online spelling may be incomplete
3458 pEditView
->getEditEngine().CompleteOnlineSpelling();
3460 // IsCursorAtWrongSpelledWord could be used for !bMouse
3461 // if there was a corresponding ExecuteSpellPopup call
3465 // On OS/2 when clicking next to the Popup menu, the MouseButtonDown
3466 // comes before the end of menu execute, thus the SetModified has to
3467 // be done prior to this (Bug #40968#)
3468 ScInputHandler
* pHdl
= pScMod
->GetInputHdl();
3470 pHdl
->SetModified();
3472 const OUString sOldText
= pHdl
? pHdl
->GetEditString() : u
""_ustr
;
3474 // Only done/shown if a misspelled word is actually under the mouse pointer.
3475 Link
<SpellCallbackInfo
&,void> aLink
= LINK( this, ScGridWindow
, PopupSpellingHdl
);
3476 bDone
= pEditView
->ExecuteSpellPopup(aMenuPos
, aLink
);
3478 // If the spelling is corrected, stop editing to flush any cached spelling info.
3479 // Or, if no misspelled word at this position, and it wasn't initially in edit mode,
3480 // then exit the edit mode in order to get the full context popup (not edit popup).
3481 if (pHdl
&& (pHdl
->GetEditString() != sOldText
3482 || (!bDone
&& !bPosIsInEditView
)))
3484 pHdl
->EnterHandler();
3487 if (!bDone
&& nColSpellError
!= nCellX
)
3489 // NOTE: This call can change the selection, and the view state (edit mode, etc).
3490 SelectForContextMenu(aPosPixel
, nCellX
, nCellY
);
3496 // non-edit menu by keyboard -> use lower right of cell cursor position
3497 ScDocument
& rDoc
= mrViewData
.GetDocument();
3498 SCTAB nTabNo
= mrViewData
.GetTabNo();
3499 bool bLayoutIsRTL
= rDoc
.IsLayoutRTL(nTabNo
);
3501 SCCOL nCurX
= mrViewData
.GetCurX();
3502 SCROW nCurY
= mrViewData
.GetCurY();
3503 aMenuPos
= mrViewData
.GetScrPos( nCurX
, nCurY
, eWhich
, true );
3504 tools::Long nSizeXPix
;
3505 tools::Long nSizeYPix
;
3506 mrViewData
.GetMergeSizePixel( nCurX
, nCurY
, nSizeXPix
, nSizeYPix
);
3507 // fdo#55432 take the correct position for RTL sheet
3508 aMenuPos
.AdjustX(bLayoutIsRTL
? -nSizeXPix
: nSizeXPix
);
3509 aMenuPos
.AdjustY(nSizeYPix
);
3511 ScTabViewShell
* pViewSh
= mrViewData
.GetViewShell();
3514 // Is a draw object selected?
3516 SdrView
* pDrawView
= pViewSh
->GetScDrawView();
3517 if (pDrawView
&& pDrawView
->GetMarkedObjectList().GetMarkCount() != 0)
3519 // #100442#; the context menu should open in the middle of the selected objects
3520 tools::Rectangle
aSelectRect(LogicToPixel(pDrawView
->GetAllMarkedBoundRect()));
3521 aMenuPos
= aSelectRect
.Center();
3529 SfxDispatcher::ExecutePopup( this, &aMenuPos
);
3532 void ScGridWindow::SelectForContextMenu( const Point
& rPosPixel
, SCCOL nCellX
, SCROW nCellY
)
3534 // #i18735# if the click was outside of the current selection,
3535 // the cursor is moved or an object at the click position selected.
3536 // (see SwEditWin::SelectMenuPosition in Writer)
3538 ScTabView
* pView
= mrViewData
.GetView();
3539 ScDrawView
* pDrawView
= pView
->GetScDrawView();
3541 // check cell edit mode
3543 if ( mrViewData
.HasEditView(eWhich
) )
3545 ScModule
* pScMod
= ScModule::get();
3546 SCCOL nEditStartCol
= mrViewData
.GetEditViewCol(); //! change to GetEditStartCol after calcrtl is integrated
3547 SCROW nEditStartRow
= mrViewData
.GetEditViewRow();
3548 SCCOL nEditEndCol
= mrViewData
.GetEditEndCol();
3549 SCROW nEditEndRow
= mrViewData
.GetEditEndRow();
3551 if ( nCellX
>= nEditStartCol
&& nCellX
<= nEditEndCol
&&
3552 nCellY
>= nEditStartRow
&& nCellY
<= nEditEndRow
)
3554 // handle selection within the EditView
3556 EditView
* pEditView
= mrViewData
.GetEditView( eWhich
); // not NULL (HasEditView)
3557 EditEngine
& rEditEngine
= pEditView
->getEditEngine();
3558 tools::Rectangle aOutputArea
= pEditView
->GetOutputArea();
3559 tools::Rectangle aVisArea
= pEditView
->GetVisArea();
3561 Point aTextPos
= PixelToLogic( rPosPixel
);
3562 if (rEditEngine
.IsEffectivelyVertical()) // have to manually transform position
3564 aTextPos
-= aOutputArea
.TopRight();
3565 tools::Long nTemp
= -aTextPos
.X();
3566 aTextPos
.setX( aTextPos
.Y() );
3567 aTextPos
.setY( nTemp
);
3570 aTextPos
-= aOutputArea
.TopLeft();
3571 aTextPos
+= aVisArea
.TopLeft(); // position in the edit document
3573 ESelection
aCompare(rEditEngine
.FindDocPosition(aTextPos
));
3574 ESelection aSelection
= pEditView
->GetSelection();
3575 aSelection
.Adjust(); // needed for IsLess/IsGreater
3576 if ( aCompare
< aSelection
|| aCompare
> aSelection
)
3578 // clicked outside the selected text - deselect and move text cursor
3579 MouseEvent
aEvent( rPosPixel
);
3580 pEditView
->MouseButtonDown( aEvent
);
3581 pEditView
->MouseButtonUp( aEvent
);
3582 pScMod
->InputSelection( pEditView
);
3585 return; // clicked within the edit view - keep edit mode
3589 // outside of the edit view - end edit mode, regardless of cell selection, then continue
3590 pScMod
->InputEnterHandler();
3594 // check draw text edit mode
3596 Point aLogicPos
= PixelToLogic( rPosPixel
); // after cell edit mode is ended
3597 if ( pDrawView
&& pDrawView
->GetTextEditObject() && pDrawView
->GetTextEditOutlinerView() )
3599 OutlinerView
* pOlView
= pDrawView
->GetTextEditOutlinerView();
3600 tools::Rectangle aOutputArea
= pOlView
->GetOutputArea();
3601 if ( aOutputArea
.Contains( aLogicPos
) )
3603 // handle selection within the OutlinerView
3605 Outliner
* pOutliner
= pOlView
->GetOutliner();
3606 const EditEngine
& rEditEngine
= pOutliner
->GetEditEngine();
3607 tools::Rectangle aVisArea
= pOlView
->GetVisArea();
3609 Point aTextPos
= aLogicPos
;
3610 if ( pOutliner
->IsVertical() ) // have to manually transform position
3612 aTextPos
-= aOutputArea
.TopRight();
3613 tools::Long nTemp
= -aTextPos
.X();
3614 aTextPos
.setX( aTextPos
.Y() );
3615 aTextPos
.setY( nTemp
);
3618 aTextPos
-= aOutputArea
.TopLeft();
3619 aTextPos
+= aVisArea
.TopLeft(); // position in the edit document
3621 ESelection
aCompare(rEditEngine
.FindDocPosition(aTextPos
));
3622 ESelection aSelection
= pOlView
->GetSelection();
3623 aSelection
.Adjust(); // needed for IsLess/IsGreater
3624 if ( aCompare
< aSelection
|| aCompare
> aSelection
)
3626 // clicked outside the selected text - deselect and move text cursor
3627 // use DrawView to allow extra handling there (none currently)
3628 MouseEvent
aEvent( rPosPixel
);
3629 pDrawView
->MouseButtonDown( aEvent
, GetOutDev() );
3630 pDrawView
->MouseButtonUp( aEvent
, GetOutDev() );
3633 return; // clicked within the edit area - keep edit mode
3637 // Outside of the edit area - end text edit mode, then continue.
3638 // DrawDeselectAll also ends text edit mode and updates the shells.
3639 // If the click was on the edited object, it will be selected again below.
3640 pView
->DrawDeselectAll();
3644 // look for existing selection
3646 bool bHitSelected
= false;
3647 if ( pDrawView
&& pDrawView
->IsMarkedObjHit( aLogicPos
) )
3649 // clicked on selected object -> don't change anything
3650 bHitSelected
= true;
3652 else if ( mrViewData
.GetMarkData().IsCellMarked(nCellX
, nCellY
) )
3654 // clicked on selected cell -> don't change anything
3655 bHitSelected
= true;
3658 // select drawing object or move cell cursor
3663 bool bWasDraw
= ( pDrawView
&& pDrawView
->GetMarkedObjectList().GetMarkCount() != 0 );
3664 bool bHitDraw
= false;
3667 pDrawView
->UnmarkAllObj();
3668 // Unlock the Internal Layer in order to activate the context menu.
3669 // re-lock in ScDrawView::MarkListHasChanged()
3670 lcl_UnLockComment(pDrawView
, aLogicPos
, mrViewData
);
3671 bHitDraw
= pDrawView
->MarkObj( aLogicPos
);
3672 // draw shell is activated in MarkListHasChanged
3677 pView
->SetCursor(nCellX
, nCellY
);
3679 mrViewData
.GetViewShell()->SetDrawShell( false ); // switch shells
3683 void ScGridWindow::KeyInput(const KeyEvent
& rKEvt
)
3685 // Cursor control for ref input dialog
3686 const vcl::KeyCode
& rKeyCode
= rKEvt
.GetKeyCode();
3690 if (rKeyCode
.IsMod1() && rKeyCode
.IsShift())
3692 if (rKeyCode
.GetCode() == KEY_F12
)
3694 dumpColumnInformationPixel();
3696 else if (rKeyCode
.GetCode() == KEY_F11
)
3698 dumpGraphicInformation();
3700 else if (rKeyCode
.GetCode() == KEY_F10
)
3702 dumpColumnInformationHmm();
3704 else if (rKeyCode
.GetCode() == KEY_F6
)
3706 dumpCellProperties();
3708 else if (rKeyCode
.GetCode() == KEY_F8
)
3710 dumpColumnCellStorage();
3712 else if (rKeyCode
.GetCode() == KEY_F7
)
3714 ScDocument
& rDoc
= mrViewData
.GetDocument();
3715 auto& rMapper
= rDoc
.GetExternalDataMapper();
3716 for (auto& itr
: rMapper
.getDataSources())
3726 ScModule
* mod
= ScModule::get();
3727 if( mod
->IsRefDialogOpen() )
3729 if( !rKeyCode
.GetModifier() && (rKeyCode
.GetCode() == KEY_F2
) )
3731 mod
->EndReference();
3733 else if( mrViewData
.GetViewShell()->MoveCursorKeyInput( rKEvt
) )
3736 mrViewData
.GetRefStartX(), mrViewData
.GetRefStartY(), mrViewData
.GetRefStartZ(),
3737 mrViewData
.GetRefEndX(), mrViewData
.GetRefEndY(), mrViewData
.GetRefEndZ() );
3738 mod
->SetReference(aRef
, mrViewData
.GetDocument());
3740 mrViewData
.GetViewShell()->SelectionChanged();
3743 else if( rKeyCode
.GetCode() == KEY_RETURN
&& mrViewData
.IsPasteMode()
3744 && mod
->GetInputOptions().GetEnterPasteMode() )
3746 ScTabViewShell
* pTabViewShell
= mrViewData
.GetViewShell();
3747 ScClipUtil::PasteFromClipboard( mrViewData
, pTabViewShell
, true );
3749 // Clear clipboard content.
3750 uno::Reference
<datatransfer::clipboard::XClipboard
> xSystemClipboard
=
3752 if (xSystemClipboard
.is())
3754 xSystemClipboard
->setContents(
3755 uno::Reference
<datatransfer::XTransferable
>(),
3756 uno::Reference
<datatransfer::clipboard::XClipboardOwner
>());
3759 // hide the border around the copy source
3760 mrViewData
.SetPasteMode( ScPasteFlags::NONE
);
3761 // Clear CopySourceOverlay in each window of a split/frozen tabview
3762 mrViewData
.GetView()->UpdateCopySourceOverlay();
3765 // if semi-modeless SfxChildWindow dialog above, then no KeyInputs:
3766 else if( !mrViewData
.IsAnyFillMode() )
3768 if (rKeyCode
.GetCode() == KEY_ESCAPE
)
3770 mrViewData
.SetPasteMode( ScPasteFlags::NONE
);
3771 // Clear CopySourceOverlay in each window of a split/frozen tabview
3772 mrViewData
.GetView()->UpdateCopySourceOverlay();
3774 // query for existing note marker before calling ViewShell's keyboard handling
3775 // which may remove the marker
3776 bool bHadKeyMarker
= mpNoteMarker
&& mpNoteMarker
->IsByKeyboard();
3777 ScTabViewShell
* pViewSh
= mrViewData
.GetViewShell();
3779 if (mrViewData
.GetDocShell()->GetProgress())
3782 if (DrawKeyInput(rKEvt
, this))
3784 const vcl::KeyCode
& rLclKeyCode
= rKEvt
.GetKeyCode();
3785 if (rLclKeyCode
.GetCode() == KEY_DOWN
3786 || rLclKeyCode
.GetCode() == KEY_UP
3787 || rLclKeyCode
.GetCode() == KEY_LEFT
3788 || rLclKeyCode
.GetCode() == KEY_RIGHT
)
3790 ScTabViewShell
* pViewShell
= mrViewData
.GetViewShell();
3791 SfxBindings
& rBindings
= pViewShell
->GetViewFrame().GetBindings();
3792 rBindings
.Invalidate(SID_ATTR_TRANSFORM_POS_X
);
3793 rBindings
.Invalidate(SID_ATTR_TRANSFORM_POS_Y
);
3798 if (!mrViewData
.GetView()->IsDrawSelMode() && !DrawHasMarkedObj()) // No entries in draw mode
3799 { //! check DrawShell !!!
3800 if (pViewSh
->TabKeyInput(rKEvt
))
3804 if (pViewSh
->SfxViewShell::KeyInput(rKEvt
)) // from SfxViewShell
3807 vcl::KeyCode aCode
= rKEvt
.GetKeyCode();
3808 if ( aCode
.GetCode() == KEY_ESCAPE
&& aCode
.GetModifier() == 0 )
3810 if ( bHadKeyMarker
)
3816 if ( aCode
.GetCode() == KEY_F1
&& aCode
.GetModifier() == KEY_MOD1
)
3818 // ctrl-F1 shows or hides the note or redlining info for the cursor position
3819 // (hard-coded because F1 can't be configured)
3821 if ( bHadKeyMarker
)
3822 HideNoteMarker(); // hide when previously visible
3824 ShowNoteMarker( mrViewData
.GetCurX(), mrViewData
.GetCurY(), true );
3827 if (aCode
.GetCode() == KEY_BRACKETLEFT
&& aCode
.GetModifier() == KEY_MOD1
)
3829 pViewSh
->DetectiveMarkPred();
3832 if (aCode
.GetCode() == KEY_BRACKETRIGHT
&& aCode
.GetModifier() == KEY_MOD1
)
3834 pViewSh
->DetectiveMarkSucc();
3840 Window::KeyInput(rKEvt
);
3843 OUString
ScGridWindow::GetSurroundingText() const
3845 bool bEditView
= mrViewData
.HasEditView(eWhich
);
3848 ScInputHandler
* pHdl
= ScModule::get()->GetInputHdl(mrViewData
.GetViewShell());
3850 return pHdl
->GetSurroundingText();
3852 else if (SdrView
* pSdrView
= mrViewData
.GetView()->GetScDrawView())
3854 // if no cell editview is active, look at drawview
3855 OutlinerView
* pOlView
= pSdrView
->GetTextEditOutlinerView();
3856 if (pOlView
&& pOlView
->GetWindow() == this)
3857 return pOlView
->GetSurroundingText();
3860 return Window::GetSurroundingText();
3863 Selection
ScGridWindow::GetSurroundingTextSelection() const
3865 bool bEditView
= mrViewData
.HasEditView(eWhich
);
3868 ScInputHandler
* pHdl
= ScModule::get()->GetInputHdl(mrViewData
.GetViewShell());
3870 return pHdl
->GetSurroundingTextSelection();
3872 else if (SdrView
* pSdrView
= mrViewData
.GetView()->GetScDrawView())
3874 // if no cell editview is active, look at drawview
3875 OutlinerView
* pOlView
= pSdrView
->GetTextEditOutlinerView();
3876 if (pOlView
&& pOlView
->GetWindow() == this)
3877 return pOlView
->GetSurroundingTextSelection();
3880 return Window::GetSurroundingTextSelection();
3883 bool ScGridWindow::DeleteSurroundingText(const Selection
& rSelection
)
3885 bool bEditView
= mrViewData
.HasEditView(eWhich
);
3888 ScInputHandler
* pHdl
= ScModule::get()->GetInputHdl(mrViewData
.GetViewShell());
3890 return pHdl
->DeleteSurroundingText(rSelection
);
3892 else if (SdrView
* pSdrView
= mrViewData
.GetView()->GetScDrawView())
3894 // if no cell editview is active, look at drawview
3895 OutlinerView
* pOlView
= pSdrView
->GetTextEditOutlinerView();
3896 if (pOlView
&& pOlView
->GetWindow() == this)
3897 return pOlView
->DeleteSurroundingText(rSelection
);
3900 return Window::DeleteSurroundingText(rSelection
);
3903 void ScGridWindow::StopMarking()
3905 DrawEndAction(); // Cancel Select/move on Drawing-Layer
3909 mrViewData
.GetMarkData().SetMarking(false);
3910 nMouseStatus
= SC_GM_IGNORE
;
3914 void ScGridWindow::UpdateInputContext()
3916 bool bReadOnly
= mrViewData
.GetDocShell()->IsReadOnly();
3917 InputContextFlags nOptions
= bReadOnly
? InputContextFlags::NONE
: ( InputContextFlags::Text
| InputContextFlags::ExtText
);
3919 // when font from InputContext is used,
3920 // it must be taken from the cursor position's cell attributes
3922 InputContext aContext
;
3923 aContext
.SetOptions( nOptions
);
3924 SetInputContext( aContext
);
3927 // sensitive range (Pixel)
3928 #define SCROLL_SENSITIVE 20
3930 void ScGridWindow::DropScroll( const Point
& rMousePos
)
3932 ScDocument
& rDoc
= mrViewData
.GetDocument();
3935 Size aSize
= GetOutputSizePixel();
3937 if (aSize
.Width() > SCROLL_SENSITIVE
* 3)
3939 if ( rMousePos
.X() < SCROLL_SENSITIVE
&& mrViewData
.GetPosX(WhichH(eWhich
)) > 0 )
3941 if ( rMousePos
.X() >= aSize
.Width() - SCROLL_SENSITIVE
3942 && mrViewData
.GetPosX(WhichH(eWhich
)) < rDoc
.MaxCol() )
3945 if (aSize
.Height() > SCROLL_SENSITIVE
* 3)
3947 if ( rMousePos
.Y() < SCROLL_SENSITIVE
&& mrViewData
.GetPosY(WhichV(eWhich
)) > 0 )
3949 if ( rMousePos
.Y() >= aSize
.Height() - SCROLL_SENSITIVE
3950 && mrViewData
.GetPosY(WhichV(eWhich
)) < rDoc
.MaxRow() )
3954 if ( nDx
!= 0 || nDy
!= 0 )
3957 mrViewData
.GetView()->ScrollX( nDx
, WhichH(eWhich
) );
3959 mrViewData
.GetView()->ScrollY( nDy
, WhichV(eWhich
) );
3963 static bool lcl_TestScenarioRedliningDrop( const ScDocument
* pDoc
, const ScRange
& aDragRange
)
3965 // Test, if a scenario is affected by a drop when turing on RedLining,
3966 bool bReturn
= false;
3967 SCTAB nTab
= aDragRange
.aStart
.Tab();
3968 SCTAB nTabCount
= pDoc
->GetTableCount();
3970 if(pDoc
->GetChangeTrack()!=nullptr)
3972 if( pDoc
->IsScenario(nTab
) && pDoc
->HasScenarioRange(nTab
, aDragRange
))
3978 for(SCTAB i
=nTab
+1; i
<nTabCount
&& pDoc
->IsScenario(i
); i
++)
3980 if(pDoc
->HasScenarioRange(i
, aDragRange
))
3991 static ScRange
lcl_MakeDropRange( const ScDocument
& rDoc
, SCCOL nPosX
, SCROW nPosY
, SCTAB nTab
, const ScRange
& rSource
)
3993 SCCOL nCol1
= nPosX
;
3994 SCCOL nCol2
= nCol1
+ ( rSource
.aEnd
.Col() - rSource
.aStart
.Col() );
3995 if ( nCol2
> rDoc
.MaxCol() )
3997 nCol1
-= nCol2
- rDoc
.MaxCol();
3998 nCol2
= rDoc
.MaxCol();
4000 SCROW nRow1
= nPosY
;
4001 SCROW nRow2
= nRow1
+ ( rSource
.aEnd
.Row() - rSource
.aStart
.Row() );
4002 if ( nRow2
> rDoc
.MaxRow() )
4004 nRow1
-= nRow2
- rDoc
.MaxRow();
4005 nRow2
= rDoc
.MaxRow();
4008 return ScRange( nCol1
, nRow1
, nTab
, nCol2
, nRow2
, nTab
);
4011 sal_Int8
ScGridWindow::AcceptPrivateDrop( const AcceptDropEvent
& rEvt
, const ScDragData
& rData
)
4013 if ( rEvt
.mbLeaving
)
4016 UpdateDragRectOverlay();
4017 return rEvt
.mnAction
;
4020 if ( rData
.pCellTransfer
)
4022 // Don't move source that would include filtered rows.
4023 if ((rEvt
.mnAction
& DND_ACTION_MOVE
) && rData
.pCellTransfer
->HasFilteredRows())
4028 UpdateDragRectOverlay();
4030 return DND_ACTION_NONE
;
4033 Point aPos
= rEvt
.maPosPixel
;
4035 ScDocument
* pSourceDoc
= rData
.pCellTransfer
->GetSourceDocument();
4036 ScDocument
& rThisDoc
= mrViewData
.GetDocument();
4037 if (pSourceDoc
== &rThisDoc
)
4040 if ( rThisDoc
.HasChartAtPoint(mrViewData
.GetTabNo(), PixelToLogic(aPos
), aName
))
4042 if (bDragRect
) // Remove rectangle
4045 UpdateDragRectOverlay();
4048 //! highlight chart? (selection border?)
4050 sal_Int8 nRet
= rEvt
.mnAction
;
4055 if (rData
.pCellTransfer
->GetDragSourceFlags() & ScDragSrc::Table
) // whole sheet?
4057 bool bOk
= rThisDoc
.IsDocEditable();
4058 return bOk
? rEvt
.mnAction
: 0; // don't draw selection frame
4063 mrViewData
.GetPosFromPixel( aPos
.X(), aPos
.Y(), eWhich
, nPosX
, nPosY
);
4065 ScRange aSourceRange
= rData
.pCellTransfer
->GetRange();
4066 SCCOL nSourceStartX
= aSourceRange
.aStart
.Col();
4067 SCROW nSourceStartY
= aSourceRange
.aStart
.Row();
4068 SCCOL nSourceEndX
= aSourceRange
.aEnd
.Col();
4069 SCROW nSourceEndY
= aSourceRange
.aEnd
.Row();
4070 SCCOL nSizeX
= nSourceEndX
- nSourceStartX
+ 1;
4071 SCROW nSizeY
= nSourceEndY
- nSourceStartY
+ 1;
4073 if ( rEvt
.mnAction
!= DND_ACTION_MOVE
)
4074 nSizeY
= rData
.pCellTransfer
->GetNonFilteredRows(); // copy/link: no filtered rows
4076 SCCOL nNewDragX
= nPosX
- rData
.pCellTransfer
->GetDragHandleX();
4077 if (nNewDragX
<0) nNewDragX
=0;
4078 if (nNewDragX
+(nSizeX
-1) > rThisDoc
.MaxCol())
4079 nNewDragX
= rThisDoc
.MaxCol()-(nSizeX
-1);
4080 SCROW nNewDragY
= nPosY
- rData
.pCellTransfer
->GetDragHandleY();
4081 if (nNewDragY
<0) nNewDragY
=0;
4082 if (nNewDragY
+(nSizeY
-1) > rThisDoc
.MaxRow())
4083 nNewDragY
= rThisDoc
.MaxRow()-(nSizeY
-1);
4085 // don't break scenario ranges, don't drop on filtered
4086 SCTAB nTab
= mrViewData
.GetTabNo();
4087 ScRange aDropRange
= lcl_MakeDropRange( rThisDoc
, nNewDragX
, nNewDragY
, nTab
, aSourceRange
);
4088 if ( lcl_TestScenarioRedliningDrop( &rThisDoc
, aDropRange
) ||
4089 lcl_TestScenarioRedliningDrop( pSourceDoc
, aSourceRange
) ||
4090 ScViewUtil::HasFiltered( aDropRange
, rThisDoc
) )
4095 UpdateDragRectOverlay();
4097 return DND_ACTION_NONE
;
4100 InsCellCmd eDragInsertMode
= INS_NONE
;
4101 Window::PointerState aState
= GetPointerState();
4103 // check for datapilot item sorting
4104 ScDPObject
* pDPObj
= nullptr;
4105 if ( &rThisDoc
== pSourceDoc
&& ( pDPObj
= rThisDoc
.GetDPAtCursor( nNewDragX
, nNewDragY
, nTab
) ) != nullptr )
4107 // drop on DataPilot table: sort or nothing
4109 bool bDPSort
= false;
4110 if ( rThisDoc
.GetDPAtCursor( nSourceStartX
, nSourceStartY
, aSourceRange
.aStart
.Tab() ) == pDPObj
)
4112 sheet::DataPilotTableHeaderData aDestData
;
4113 pDPObj
->GetHeaderPositionData( ScAddress(nNewDragX
, nNewDragY
, nTab
), aDestData
);
4114 bool bValid
= ( aDestData
.Dimension
>= 0 ); // dropping onto a field
4116 // look through the source range
4117 for (SCROW nRow
= aSourceRange
.aStart
.Row(); bValid
&& nRow
<= aSourceRange
.aEnd
.Row(); ++nRow
)
4118 for (SCCOL nCol
= aSourceRange
.aStart
.Col(); bValid
&& nCol
<= aSourceRange
.aEnd
.Col(); ++nCol
)
4120 sheet::DataPilotTableHeaderData aSourceData
;
4121 pDPObj
->GetHeaderPositionData( ScAddress( nCol
, nRow
, aSourceRange
.aStart
.Tab() ), aSourceData
);
4122 if ( aSourceData
.Dimension
!= aDestData
.Dimension
|| aSourceData
.MemberName
.isEmpty() )
4123 bValid
= false; // empty (subtotal) or different field
4129 OUString aDimName
= pDPObj
->GetDimName( aDestData
.Dimension
, bIsDataLayout
);
4130 const ScDPSaveDimension
* pDim
= pDPObj
->GetSaveData()->GetExistingDimensionByName( aDimName
);
4133 ScRange aOutRange
= pDPObj
->GetOutRange();
4135 sheet::DataPilotFieldOrientation nOrient
= pDim
->GetOrientation();
4136 if ( nOrient
== sheet::DataPilotFieldOrientation_COLUMN
)
4138 eDragInsertMode
= INS_CELLSRIGHT
;
4139 nSizeY
= aOutRange
.aEnd
.Row() - nNewDragY
+ 1;
4142 else if ( nOrient
== sheet::DataPilotFieldOrientation_ROW
)
4144 eDragInsertMode
= INS_CELLSDOWN
;
4145 nSizeX
= aOutRange
.aEnd
.Col() - nNewDragX
+ 1;
4154 // no valid sorting in a DataPilot table -> disallow
4158 UpdateDragRectOverlay();
4160 return DND_ACTION_NONE
;
4163 else if ( aState
.mnState
& KEY_MOD2
)
4165 if ( &rThisDoc
== pSourceDoc
&& nTab
== aSourceRange
.aStart
.Tab() )
4167 tools::Long nDeltaX
= std::abs( static_cast< tools::Long
>( nNewDragX
- nSourceStartX
) );
4168 tools::Long nDeltaY
= std::abs( static_cast< tools::Long
>( nNewDragY
- nSourceStartY
) );
4169 if ( nDeltaX
<= nDeltaY
)
4171 eDragInsertMode
= INS_CELLSDOWN
;
4175 eDragInsertMode
= INS_CELLSRIGHT
;
4178 if ( ( eDragInsertMode
== INS_CELLSDOWN
&& nNewDragY
<= nSourceEndY
&&
4179 ( nNewDragX
+ nSizeX
- 1 ) >= nSourceStartX
&& nNewDragX
<= nSourceEndX
&&
4180 ( nNewDragX
!= nSourceStartX
|| nNewDragY
>= nSourceStartY
) ) ||
4181 ( eDragInsertMode
== INS_CELLSRIGHT
&& nNewDragX
<= nSourceEndX
&&
4182 ( nNewDragY
+ nSizeY
- 1 ) >= nSourceStartY
&& nNewDragY
<= nSourceEndY
&&
4183 ( nNewDragY
!= nSourceStartY
|| nNewDragX
>= nSourceStartX
) ) )
4188 UpdateDragRectOverlay();
4190 return DND_ACTION_NONE
;
4195 if ( static_cast< tools::Long
>( nSizeX
) >= static_cast< tools::Long
>( nSizeY
) )
4197 eDragInsertMode
= INS_CELLSDOWN
;
4202 eDragInsertMode
= INS_CELLSRIGHT
;
4207 if ( nNewDragX
!= nDragStartX
|| nNewDragY
!= nDragStartY
||
4208 nDragStartX
+nSizeX
-1 != nDragEndX
|| nDragStartY
+nSizeY
-1 != nDragEndY
||
4209 !bDragRect
|| eDragInsertMode
!= meDragInsertMode
)
4211 nDragStartX
= nNewDragX
;
4212 nDragStartY
= nNewDragY
;
4213 nDragEndX
= nDragStartX
+nSizeX
-1;
4214 nDragEndY
= nDragStartY
+nSizeY
-1;
4216 meDragInsertMode
= eDragInsertMode
;
4218 UpdateDragRectOverlay();
4222 return rEvt
.mnAction
;
4225 sal_Int8
ScGridWindow::AcceptDrop( const AcceptDropEvent
& rEvt
)
4227 const ScDragData
& rData
= ScModule::get()->GetDragData();
4228 if ( rEvt
.mbLeaving
)
4230 DrawMarkDropObj( nullptr );
4231 return AcceptPrivateDrop( rEvt
, rData
); // hide drop marker for internal D&D
4234 if ( mrViewData
.GetDocShell()->IsReadOnly() )
4235 return DND_ACTION_NONE
;
4237 ScDocument
& rThisDoc
= mrViewData
.GetDocument();
4238 sal_Int8 nRet
= DND_ACTION_NONE
;
4240 if (rData
.pCellTransfer
)
4242 ScRange aSource
= rData
.pCellTransfer
->GetRange();
4243 if ( aSource
.aStart
.Col() != 0 || aSource
.aEnd
.Col() != rThisDoc
.MaxCol() ||
4244 aSource
.aStart
.Row() != 0 || aSource
.aEnd
.Row() != rThisDoc
.MaxRow() )
4245 DropScroll( rEvt
.maPosPixel
);
4247 nRet
= AcceptPrivateDrop( rEvt
, rData
);
4251 if ( !rData
.aLinkDoc
.isEmpty() )
4254 ScDocShell
* pDocSh
= mrViewData
.GetDocShell();
4255 if (pDocSh
&& pDocSh
->HasName())
4256 aThisName
= pDocSh
->GetMedium()->GetName();
4258 if ( rData
.aLinkDoc
!= aThisName
)
4259 nRet
= rEvt
.mnAction
;
4261 else if (!rData
.aJumpTarget
.isEmpty())
4263 // internal bookmarks (from Navigator)
4264 // local jumps from an unnamed document are possible only within a document
4266 if ( !rData
.pJumpLocalDoc
|| rData
.pJumpLocalDoc
== &mrViewData
.GetDocument() )
4267 nRet
= rEvt
.mnAction
;
4271 sal_Int8 nMyAction
= rEvt
.mnAction
;
4273 // clear DND_ACTION_LINK when other actions are set. The usage below cannot handle
4274 // multiple set values
4275 if((nMyAction
& DND_ACTION_LINK
) && (nMyAction
& DND_ACTION_COPYMOVE
))
4277 nMyAction
&= ~DND_ACTION_LINK
;
4280 if ( !rData
.pDrawTransfer
||
4281 !IsMyModel(rData
.pDrawTransfer
->GetDragSourceView()) ) // drawing within the document
4282 if ( rEvt
.mbDefault
&& nMyAction
== DND_ACTION_MOVE
)
4283 nMyAction
= DND_ACTION_COPY
;
4285 SdrObject
* pHitObj
= rThisDoc
.GetObjectAtPoint(
4286 mrViewData
.GetTabNo(), PixelToLogic(rEvt
.maPosPixel
) );
4287 if ( pHitObj
&& nMyAction
== DND_ACTION_LINK
)
4289 if ( IsDropFormatSupported(SotClipboardFormatId::SVXB
)
4290 || IsDropFormatSupported(SotClipboardFormatId::GDIMETAFILE
)
4291 || IsDropFormatSupported(SotClipboardFormatId::PNG
)
4292 || IsDropFormatSupported(SotClipboardFormatId::BITMAP
) )
4294 // graphic dragged onto drawing object
4295 DrawMarkDropObj( pHitObj
);
4301 DrawMarkDropObj(nullptr);
4303 switch ( nMyAction
)
4305 case DND_ACTION_COPY
:
4306 case DND_ACTION_MOVE
:
4307 case DND_ACTION_COPYMOVE
:
4309 bool bMove
= ( nMyAction
== DND_ACTION_MOVE
);
4310 if ( IsDropFormatSupported( SotClipboardFormatId::EMBED_SOURCE
) ||
4311 IsDropFormatSupported( SotClipboardFormatId::LINK_SOURCE
) ||
4312 IsDropFormatSupported( SotClipboardFormatId::EMBED_SOURCE_OLE
) ||
4313 IsDropFormatSupported( SotClipboardFormatId::LINK_SOURCE_OLE
) ||
4314 IsDropFormatSupported( SotClipboardFormatId::EMBEDDED_OBJ_OLE
) ||
4315 IsDropFormatSupported( SotClipboardFormatId::STRING
) ||
4316 IsDropFormatSupported( SotClipboardFormatId::STRING_TSVC
) ||
4317 IsDropFormatSupported( SotClipboardFormatId::SYLK
) ||
4318 IsDropFormatSupported( SotClipboardFormatId::LINK
) ||
4319 IsDropFormatSupported( SotClipboardFormatId::HTML
) ||
4320 IsDropFormatSupported( SotClipboardFormatId::HTML_SIMPLE
) ||
4321 IsDropFormatSupported( SotClipboardFormatId::DIF
) ||
4322 IsDropFormatSupported( SotClipboardFormatId::DRAWING
) ||
4323 IsDropFormatSupported( SotClipboardFormatId::SVXB
) ||
4324 IsDropFormatSupported( SotClipboardFormatId::RTF
) ||
4325 IsDropFormatSupported( SotClipboardFormatId::RICHTEXT
) ||
4326 IsDropFormatSupported( SotClipboardFormatId::GDIMETAFILE
) ||
4327 IsDropFormatSupported( SotClipboardFormatId::PNG
) ||
4328 IsDropFormatSupported( SotClipboardFormatId::BITMAP
) ||
4329 IsDropFormatSupported( SotClipboardFormatId::SBA_DATAEXCHANGE
) ||
4330 IsDropFormatSupported( SotClipboardFormatId::SBA_FIELDDATAEXCHANGE
) ||
4332 IsDropFormatSupported( SotClipboardFormatId::FILE_LIST
) ||
4333 IsDropFormatSupported( SotClipboardFormatId::SIMPLE_FILE
) ||
4334 IsDropFormatSupported( SotClipboardFormatId::SOLK
) ||
4335 IsDropFormatSupported( SotClipboardFormatId::UNIFORMRESOURCELOCATOR
) ||
4336 IsDropFormatSupported( SotClipboardFormatId::NETSCAPE_BOOKMARK
) ||
4337 IsDropFormatSupported( SotClipboardFormatId::FILEGRPDESCRIPTOR
) ) ) )
4343 case DND_ACTION_LINK
:
4344 if ( IsDropFormatSupported( SotClipboardFormatId::LINK_SOURCE
) ||
4345 IsDropFormatSupported( SotClipboardFormatId::LINK_SOURCE_OLE
) ||
4346 IsDropFormatSupported( SotClipboardFormatId::LINK
) ||
4347 IsDropFormatSupported( SotClipboardFormatId::FILE_LIST
) ||
4348 IsDropFormatSupported( SotClipboardFormatId::SIMPLE_FILE
) ||
4349 IsDropFormatSupported( SotClipboardFormatId::SOLK
) ||
4350 IsDropFormatSupported( SotClipboardFormatId::UNIFORMRESOURCELOCATOR
) ||
4351 IsDropFormatSupported( SotClipboardFormatId::NETSCAPE_BOOKMARK
) ||
4352 IsDropFormatSupported( SotClipboardFormatId::FILEGRPDESCRIPTOR
) )
4361 // Simple check for protection: It's not known here if the drop will result
4362 // in cells or drawing objects (some formats can be both) and how many cells
4363 // the result will be. But if IsFormatEditable for the drop cell position
4364 // is sal_False (ignores matrix formulas), nothing can be pasted, so the drop
4365 // can already be rejected here.
4367 Point aPos
= rEvt
.maPosPixel
;
4370 mrViewData
.GetPosFromPixel( aPos
.X(), aPos
.Y(), eWhich
, nPosX
, nPosY
);
4371 SCTAB nTab
= mrViewData
.GetTabNo();
4372 ScDocument
& rDoc
= mrViewData
.GetDocument();
4374 ScEditableTester
aTester( rDoc
, nTab
, nPosX
,nPosY
, nPosX
,nPosY
);
4375 if ( !aTester
.IsFormatEditable() )
4376 nRet
= DND_ACTION_NONE
; // forbidden
4381 // scroll only for accepted formats
4383 DropScroll( rEvt
.maPosPixel
);
4389 static SotClipboardFormatId
lcl_GetDropFormatId( const uno::Reference
<datatransfer::XTransferable
>& xTransfer
, bool bPreferText
)
4391 TransferableDataHelper
aDataHelper( xTransfer
);
4393 if ( !aDataHelper
.HasFormat( SotClipboardFormatId::SBA_DATAEXCHANGE
) )
4395 // use bookmark formats if no sba is present
4397 if ( aDataHelper
.HasFormat( SotClipboardFormatId::SOLK
) )
4398 return SotClipboardFormatId::SOLK
;
4399 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR
) )
4400 return SotClipboardFormatId::UNIFORMRESOURCELOCATOR
;
4401 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK
) )
4402 return SotClipboardFormatId::NETSCAPE_BOOKMARK
;
4403 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR
) )
4404 return SotClipboardFormatId::FILEGRPDESCRIPTOR
;
4407 SotClipboardFormatId nFormatId
= SotClipboardFormatId::NONE
;
4408 if ( aDataHelper
.HasFormat( SotClipboardFormatId::DRAWING
) )
4409 nFormatId
= SotClipboardFormatId::DRAWING
;
4410 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::SVXB
) )
4411 nFormatId
= SotClipboardFormatId::SVXB
;
4412 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::EMBED_SOURCE
) )
4414 // If it's a Writer object, insert RTF instead of OLE
4416 bool bDoRtf
= false;
4417 std::unique_ptr
<SvStream
> xStm
;
4418 TransferableObjectDescriptor aObjDesc
;
4419 if( aDataHelper
.GetTransferableObjectDescriptor( SotClipboardFormatId::OBJECTDESCRIPTOR
, aObjDesc
) &&
4420 (xStm
= aDataHelper
.GetSotStorageStream( SotClipboardFormatId::EMBED_SOURCE
)) )
4422 bDoRtf
= ( ( aObjDesc
.maClassName
== SvGlobalName( SO3_SW_CLASSID
) ||
4423 aObjDesc
.maClassName
== SvGlobalName( SO3_SWWEB_CLASSID
) )
4424 && ( aDataHelper
.HasFormat( SotClipboardFormatId::RTF
) || aDataHelper
.HasFormat( SotClipboardFormatId::RICHTEXT
) ) );
4427 nFormatId
= aDataHelper
.HasFormat( SotClipboardFormatId::RTF
) ? SotClipboardFormatId::RTF
: SotClipboardFormatId::RICHTEXT
;
4429 nFormatId
= SotClipboardFormatId::EMBED_SOURCE
;
4431 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::LINK_SOURCE
) )
4432 nFormatId
= SotClipboardFormatId::LINK_SOURCE
;
4433 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::SBA_DATAEXCHANGE
) )
4434 nFormatId
= SotClipboardFormatId::SBA_DATAEXCHANGE
;
4435 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::SBA_FIELDDATAEXCHANGE
) )
4436 nFormatId
= SotClipboardFormatId::SBA_FIELDDATAEXCHANGE
;
4437 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::BIFF_8
) )
4438 nFormatId
= SotClipboardFormatId::BIFF_8
;
4439 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::BIFF_5
) )
4440 nFormatId
= SotClipboardFormatId::BIFF_5
;
4441 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::EMBED_SOURCE_OLE
) )
4442 nFormatId
= SotClipboardFormatId::EMBED_SOURCE_OLE
;
4443 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::EMBEDDED_OBJ_OLE
) )
4444 nFormatId
= SotClipboardFormatId::EMBEDDED_OBJ_OLE
;
4445 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::LINK_SOURCE_OLE
) )
4446 nFormatId
= SotClipboardFormatId::LINK_SOURCE_OLE
;
4447 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::RTF
) )
4448 nFormatId
= SotClipboardFormatId::RTF
;
4449 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::RICHTEXT
) )
4450 nFormatId
= SotClipboardFormatId::RICHTEXT
;
4451 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::HTML
) )
4452 nFormatId
= SotClipboardFormatId::HTML
;
4453 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::HTML_SIMPLE
) )
4454 nFormatId
= SotClipboardFormatId::HTML_SIMPLE
;
4455 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::SYLK
) )
4456 nFormatId
= SotClipboardFormatId::SYLK
;
4457 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::LINK
) )
4458 nFormatId
= SotClipboardFormatId::LINK
;
4459 else if ( bPreferText
&& aDataHelper
.HasFormat( SotClipboardFormatId::STRING
) ) // #i86734# the behaviour introduced in #i62773# is wrong when pasting
4460 nFormatId
= SotClipboardFormatId::STRING
;
4461 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::FILE_LIST
) )
4462 nFormatId
= SotClipboardFormatId::FILE_LIST
;
4463 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::SIMPLE_FILE
) ) // #i62773# FILE_LIST/FILE before STRING (Unix file managers)
4464 nFormatId
= SotClipboardFormatId::SIMPLE_FILE
;
4465 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::STRING_TSVC
) )
4466 nFormatId
= SotClipboardFormatId::STRING_TSVC
;
4467 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::STRING
) )
4468 nFormatId
= SotClipboardFormatId::STRING
;
4469 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::GDIMETAFILE
) )
4470 nFormatId
= SotClipboardFormatId::GDIMETAFILE
;
4471 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::PNG
) )
4472 nFormatId
= SotClipboardFormatId::PNG
;
4473 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::BITMAP
) )
4474 nFormatId
= SotClipboardFormatId::BITMAP
;
4479 static SotClipboardFormatId
lcl_GetDropLinkId( const uno::Reference
<datatransfer::XTransferable
>& xTransfer
)
4481 TransferableDataHelper
aDataHelper( xTransfer
);
4483 SotClipboardFormatId nFormatId
= SotClipboardFormatId::NONE
;
4484 if ( aDataHelper
.HasFormat( SotClipboardFormatId::LINK_SOURCE
) )
4485 nFormatId
= SotClipboardFormatId::LINK_SOURCE
;
4486 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::LINK_SOURCE_OLE
) )
4487 nFormatId
= SotClipboardFormatId::LINK_SOURCE_OLE
;
4488 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::LINK
) )
4489 nFormatId
= SotClipboardFormatId::LINK
;
4490 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::FILE_LIST
) )
4491 nFormatId
= SotClipboardFormatId::FILE_LIST
;
4492 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::SIMPLE_FILE
) )
4493 nFormatId
= SotClipboardFormatId::SIMPLE_FILE
;
4494 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::SOLK
) )
4495 nFormatId
= SotClipboardFormatId::SOLK
;
4496 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR
) )
4497 nFormatId
= SotClipboardFormatId::UNIFORMRESOURCELOCATOR
;
4498 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK
) )
4499 nFormatId
= SotClipboardFormatId::NETSCAPE_BOOKMARK
;
4500 else if ( aDataHelper
.HasFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR
) )
4501 nFormatId
= SotClipboardFormatId::FILEGRPDESCRIPTOR
;
4506 sal_Int8
ScGridWindow::ExecutePrivateDrop( const ExecuteDropEvent
& rEvt
, const ScDragData
& rData
)
4510 UpdateDragRectOverlay();
4512 return DropTransferObj( rData
.pCellTransfer
, nDragStartX
, nDragStartY
,
4513 PixelToLogic(rEvt
.maPosPixel
), rEvt
.mnAction
);
4516 sal_Int8
ScGridWindow::DropTransferObj( ScTransferObj
* pTransObj
, SCCOL nDestPosX
, SCROW nDestPosY
,
4517 const Point
& rLogicPos
, sal_Int8 nDndAction
)
4522 ScDocument
* pSourceDoc
= pTransObj
->GetSourceDocument();
4523 ScDocShell
* pDocSh
= mrViewData
.GetDocShell();
4524 ScDocument
& rThisDoc
= mrViewData
.GetDocument();
4525 ScViewFunc
* pView
= mrViewData
.GetView();
4526 SCTAB nThisTab
= mrViewData
.GetTabNo();
4527 ScDragSrc nFlags
= pTransObj
->GetDragSourceFlags();
4529 bool bIsNavi
= (nFlags
& ScDragSrc::Navigator
) == ScDragSrc::Navigator
;
4530 bool bIsMove
= ( nDndAction
== DND_ACTION_MOVE
&& !bIsNavi
);
4532 // workaround for wrong nDndAction on Windows when pressing solely
4533 // the Alt key during drag and drop;
4534 // can be removed after #i79215# has been fixed
4535 if ( meDragInsertMode
!= INS_NONE
)
4537 bIsMove
= ( nDndAction
& DND_ACTION_MOVE
&& !bIsNavi
);
4540 bool bIsLink
= ( nDndAction
== DND_ACTION_LINK
);
4542 ScRange aSource
= pTransObj
->GetRange();
4544 // only use visible tab from source range - when dragging within one table,
4545 // all selected tables at the time of dropping are used (handled in MoveBlockTo)
4546 SCTAB nSourceTab
= pTransObj
->GetVisibleTab();
4547 aSource
.aStart
.SetTab( nSourceTab
);
4548 aSource
.aEnd
.SetTab( nSourceTab
);
4550 SCCOL nSizeX
= aSource
.aEnd
.Col() - aSource
.aStart
.Col() + 1;
4551 SCROW nSizeY
= (bIsMove
? (aSource
.aEnd
.Row() - aSource
.aStart
.Row() + 1) :
4552 pTransObj
->GetNonFilteredRows()); // copy/link: no filtered rows
4553 ScRange
aDest( nDestPosX
, nDestPosY
, nThisTab
,
4554 nDestPosX
+ nSizeX
- 1, nDestPosY
+ nSizeY
- 1, nThisTab
);
4556 /* NOTE: AcceptPrivateDrop() already checked for filtered conditions during
4557 * dragging and adapted drawing of the selection frame. We check here
4558 * (again) because this may actually also be called from PasteSelection(),
4559 * we would have to duplicate determination of flags and destination range
4560 * and would lose the context of the "filtered destination is OK" cases
4561 * below, which is already awkward enough as is. */
4563 // Don't move filtered source.
4564 bool bFiltered
= (bIsMove
&& pTransObj
->HasFilteredRows());
4567 if (pSourceDoc
!= &rThisDoc
&& ((nFlags
& ScDragSrc::Table
) ||
4568 (!bIsLink
&& meDragInsertMode
== INS_NONE
)))
4570 // Nothing. Either entire sheet to be dropped, or the one case
4571 // where PasteFromClip() is to be called that handles a filtered
4572 // destination itself. Drag-copy from another document without
4576 // Don't copy or move to filtered destination.
4577 bFiltered
= ScViewUtil::HasFiltered(aDest
, rThisDoc
);
4582 if (!bFiltered
&& pSourceDoc
== &rThisDoc
)
4584 if (nFlags
& ScDragSrc::Table
) // whole sheet?
4586 if ( rThisDoc
.IsDocEditable() )
4588 SCTAB nSrcTab
= aSource
.aStart
.Tab();
4589 mrViewData
.GetDocShell()->MoveTable( nSrcTab
, nThisTab
, !bIsMove
, true ); // with Undo
4590 pView
->SetTabNo( nThisTab
, true );
4594 else // move/copy block
4596 OUString aChartName
;
4597 if (rThisDoc
.HasChartAtPoint( nThisTab
, rLogicPos
, aChartName
))
4599 OUString
aRangeName(aSource
.Format(rThisDoc
, ScRefFlags::RANGE_ABS_3D
,
4600 rThisDoc
.GetAddressConvention()));
4601 SfxStringItem
aNameItem( SID_CHART_NAME
, aChartName
);
4602 SfxStringItem
aRangeItem( SID_CHART_SOURCE
, aRangeName
);
4603 sal_uInt16 nId
= bIsMove
? SID_CHART_SOURCE
: SID_CHART_ADDSOURCE
;
4604 mrViewData
.GetDispatcher().ExecuteList(nId
,
4605 SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
,
4606 { &aRangeItem
, &aNameItem
});
4609 else if ( rThisDoc
.GetDPAtCursor( nDestPosX
, nDestPosY
, nThisTab
) )
4611 // drop on DataPilot table: try to sort, fail if that isn't possible
4613 ScAddress
aDestPos( nDestPosX
, nDestPosY
, nThisTab
);
4614 if ( aDestPos
!= aSource
.aStart
)
4615 bDone
= mrViewData
.GetView()->DataPilotMove( aSource
, aDestPos
);
4617 bDone
= true; // same position: nothing
4619 else if ( nDestPosX
!= aSource
.aStart
.Col() || nDestPosY
!= aSource
.aStart
.Row() ||
4620 nSourceTab
!= nThisTab
)
4622 OUString aUndo
= ScResId( bIsMove
? STR_UNDO_MOVE
: STR_UNDO_COPY
);
4623 pDocSh
->GetUndoManager()->EnterListAction( aUndo
, aUndo
, 0, mrViewData
.GetViewShell()->GetViewShellId() );
4625 SCCOL nCorrectCursorPosCol
= 0;
4626 SCROW nCorrectCursorPosRow
= 0;
4629 if ( meDragInsertMode
!= INS_NONE
)
4631 // call with bApi = sal_True to avoid error messages in drop handler
4632 bDone
= pDocSh
->GetDocFunc().InsertCells( aDest
, nullptr, meDragInsertMode
, true /*bRecord*/, true /*bApi*/, true /*bPartOfPaste*/ );
4635 if ( nThisTab
== nSourceTab
)
4637 if ( meDragInsertMode
== INS_CELLSDOWN
&&
4638 nDestPosX
== aSource
.aStart
.Col() && nDestPosY
< aSource
.aStart
.Row() )
4640 ScRange
aErrorRange( ScAddress::UNINITIALIZED
);
4641 bDone
= aSource
.Move( 0, nSizeY
, 0, aErrorRange
, *pSourceDoc
);
4642 nCorrectCursorPosRow
= nSizeY
;
4644 else if ( meDragInsertMode
== INS_CELLSRIGHT
&&
4645 nDestPosY
== aSource
.aStart
.Row() && nDestPosX
< aSource
.aStart
.Col() )
4647 ScRange
aErrorRange( ScAddress::UNINITIALIZED
);
4648 bDone
= aSource
.Move( nSizeX
, 0, 0, aErrorRange
, *pSourceDoc
);
4649 nCorrectCursorPosCol
= nSizeX
;
4652 pDocSh
->UpdateOle(mrViewData
);
4653 pView
->CellContentChanged();
4661 bDone
= pView
->LinkBlock( aSource
, aDest
.aStart
);
4665 bDone
= pView
->MoveBlockTo( aSource
, aDest
.aStart
, bIsMove
);
4669 if ( bDone
&& meDragInsertMode
!= INS_NONE
&& bIsMove
&& nThisTab
== nSourceTab
)
4671 DelCellCmd eCmd
= DelCellCmd::NONE
;
4672 if ( meDragInsertMode
== INS_CELLSDOWN
)
4674 eCmd
= DelCellCmd::CellsUp
;
4676 else if ( meDragInsertMode
== INS_CELLSRIGHT
)
4678 eCmd
= DelCellCmd::CellsLeft
;
4681 if ( ( eCmd
== DelCellCmd::CellsUp
&& nDestPosX
== aSource
.aStart
.Col() ) ||
4682 ( eCmd
== DelCellCmd::CellsLeft
&& nDestPosY
== aSource
.aStart
.Row() ) )
4684 // call with bApi = sal_True to avoid error messages in drop handler
4685 bDone
= pDocSh
->GetDocFunc().DeleteCells( aSource
, nullptr, eCmd
, true /*bApi*/ );
4688 if ( eCmd
== DelCellCmd::CellsUp
&& nDestPosY
> aSource
.aEnd
.Row() )
4690 ScRange
aErrorRange( ScAddress::UNINITIALIZED
);
4691 bDone
= aDest
.Move( 0, -nSizeY
, 0, aErrorRange
, rThisDoc
);
4693 else if ( eCmd
== DelCellCmd::CellsLeft
&& nDestPosX
> aSource
.aEnd
.Col() )
4695 ScRange
aErrorRange( ScAddress::UNINITIALIZED
);
4696 bDone
= aDest
.Move( -nSizeX
, 0, 0, aErrorRange
, rThisDoc
);
4698 pDocSh
->UpdateOle(mrViewData
);
4699 pView
->CellContentChanged();
4706 pView
->MarkRange( aDest
, false );
4710 if (pTransObj
->WasSourceCursorInSelection())
4712 nDCol
= pTransObj
->GetSourceCursorX() - aSource
.aStart
.Col() + nCorrectCursorPosCol
;
4713 nDRow
= pTransObj
->GetSourceCursorY() - aSource
.aStart
.Row() + nCorrectCursorPosRow
;
4720 pView
->SetCursor( aDest
.aStart
.Col() + nDCol
, aDest
.aStart
.Row() + nDRow
);
4723 pDocSh
->GetUndoManager()->LeaveListAction();
4727 bDone
= true; // nothing to do
4731 pTransObj
->SetDragWasInternal(); // don't delete source in DragFinished
4733 else if ( !bFiltered
&& pSourceDoc
) // between documents
4735 if (nFlags
& ScDragSrc::Table
) // copy/link sheets between documents
4737 if ( rThisDoc
.IsDocEditable() )
4739 ScDocShell
* pSrcShell
= pTransObj
->GetSourceDocShell();
4741 std::vector
<SCTAB
> nTabs
;
4743 ScMarkData aMark
= pTransObj
->GetSourceMarkData();
4744 SCTAB nTabCount
= pSourceDoc
->GetTableCount();
4746 for(SCTAB i
=0; i
<nTabCount
; i
++)
4748 if(aMark
.GetTableSelect(i
))
4751 for(SCTAB j
=i
+1;j
<nTabCount
;j
++)
4753 if((!pSourceDoc
->IsVisible(j
))&&(pSourceDoc
->IsScenario(j
)))
4755 nTabs
.push_back( j
);
4763 pView
->ImportTables( pSrcShell
,static_cast<SCTAB
>(nTabs
.size()), nTabs
.data(), bIsLink
, nThisTab
);
4770 // (external references might be used instead?)
4772 ScDocShell
* pSourceSh
= pSourceDoc
->GetDocumentShell();
4773 OSL_ENSURE(pSourceSh
, "drag document has no shell");
4776 OUString aUndo
= ScResId( STR_UNDO_COPY
);
4777 pDocSh
->GetUndoManager()->EnterListAction( aUndo
, aUndo
, 0, mrViewData
.GetViewShell()->GetViewShellId() );
4780 if ( meDragInsertMode
!= INS_NONE
)
4782 // call with bApi = sal_True to avoid error messages in drop handler
4783 bDone
= pDocSh
->GetDocFunc().InsertCells( aDest
, nullptr, meDragInsertMode
, true /*bRecord*/, true /*bApi*/, true /*bPartOfPaste*/ );
4786 pDocSh
->UpdateOle(mrViewData
);
4787 pView
->CellContentChanged();
4793 OUString aApp
= Application::GetAppName();
4794 OUString aTopic
= pSourceSh
->GetTitle( SFX_TITLE_FULLNAME
);
4795 OUString
aItem(aSource
.Format(*pSourceDoc
, ScRefFlags::VALID
| ScRefFlags::TAB_3D
));
4797 // TODO: we could define ocQuote for "
4798 const OUString
aQuote('"');
4799 const OUString
& sSep
= ScCompiler::GetNativeSymbol( ocSep
);
4802 ScCompiler::GetNativeSymbol(ocDde
) +
4803 ScCompiler::GetNativeSymbol(ocOpen
) +
4815 ScCompiler::GetNativeSymbol(ocClose
);
4817 pView
->DoneBlockMode();
4818 pView
->InitBlockMode( nDestPosX
, nDestPosY
, nThisTab
);
4819 pView
->MarkCursor( nDestPosX
+ nSizeX
- 1,
4820 nDestPosY
+ nSizeY
- 1, nThisTab
);
4822 pView
->EnterMatrix( aFormula
, ::formula::FormulaGrammar::GRAM_NATIVE
);
4824 pView
->MarkRange( aDest
, false );
4825 pView
->SetCursor( aDest
.aStart
.Col(), aDest
.aStart
.Row() );
4828 pDocSh
->GetUndoManager()->LeaveListAction();
4833 //! HasSelectedBlockMatrixFragment without selected sheet?
4834 //! or don't start dragging on a part of a matrix
4836 OUString aUndo
= ScResId( bIsMove
? STR_UNDO_MOVE
: STR_UNDO_COPY
);
4837 pDocSh
->GetUndoManager()->EnterListAction( aUndo
, aUndo
, 0, mrViewData
.GetViewShell()->GetViewShellId() );
4840 if ( meDragInsertMode
!= INS_NONE
)
4842 // call with bApi = sal_True to avoid error messages in drop handler
4843 bDone
= pDocSh
->GetDocFunc().InsertCells( aDest
, nullptr, meDragInsertMode
, true /*bRecord*/, true /*bApi*/, true /*bPartOfPaste*/ );
4846 pDocSh
->UpdateOle(mrViewData
);
4847 pView
->CellContentChanged();
4853 pView
->Unmark(); // before SetCursor, so CheckSelectionTransfer isn't called with a selection
4854 pView
->SetCursor( nDestPosX
, nDestPosY
);
4855 bDone
= pView
->PasteFromClip( InsertDeleteFlags::ALL
, pTransObj
->GetDocument() ); // clip-doc
4858 pView
->MarkRange( aDest
, false );
4859 pView
->SetCursor( aDest
.aStart
.Col(), aDest
.aStart
.Row() );
4863 pDocSh
->GetUndoManager()->LeaveListAction();
4865 // no longer call ResetMark here - the inserted block has been selected
4866 // and may have been copied to primary selection
4870 sal_Int8 nRet
= bDone
? nDndAction
: DND_ACTION_NONE
;
4874 sal_Int8
ScGridWindow::ExecuteDrop( const ExecuteDropEvent
& rEvt
)
4876 DrawMarkDropObj( nullptr ); // drawing layer
4878 ScModule
* pScMod
= ScModule::get();
4879 const ScDragData
& rData
= pScMod
->GetDragData();
4880 if (rData
.pCellTransfer
)
4881 return ExecutePrivateDrop( rEvt
, rData
);
4883 Point aPos
= rEvt
.maPosPixel
;
4885 if ( !rData
.aLinkDoc
.isEmpty() )
4887 // try to insert a link
4891 ScDocShell
* pDocSh
= mrViewData
.GetDocShell();
4892 if (pDocSh
&& pDocSh
->HasName())
4893 aThisName
= pDocSh
->GetMedium()->GetName();
4895 if ( rData
.aLinkDoc
== aThisName
) // error - no link within a document
4899 ScViewFunc
* pView
= mrViewData
.GetView();
4900 if ( !rData
.aLinkTable
.isEmpty() )
4901 pView
->InsertTableLink( rData
.aLinkDoc
, OUString(), OUString(),
4903 else if ( !rData
.aLinkArea
.isEmpty() )
4907 mrViewData
.GetPosFromPixel( aPos
.X(), aPos
.Y(), eWhich
, nPosX
, nPosY
);
4908 pView
->MoveCursorAbs( nPosX
, nPosY
, SC_FOLLOW_NONE
, false, false );
4910 pView
->InsertAreaLink( rData
.aLinkDoc
, OUString(), OUString(),
4915 OSL_FAIL("drop with link: no sheet nor area");
4920 return bOk
? rEvt
.mnAction
: DND_ACTION_NONE
; // don't try anything else
4923 Point aLogicPos
= PixelToLogic(aPos
);
4924 bool bIsLink
= ( rEvt
.mnAction
== DND_ACTION_LINK
);
4926 if (!bIsLink
&& rData
.pDrawTransfer
)
4928 ScDragSrc nFlags
= rData
.pDrawTransfer
->GetDragSourceFlags();
4930 bool bIsNavi
= (nFlags
& ScDragSrc::Navigator
) == ScDragSrc::Navigator
;
4931 bool bIsMove
= ( rEvt
.mnAction
== DND_ACTION_MOVE
&& !bIsNavi
);
4933 bPasteIsMove
= bIsMove
;
4935 mrViewData
.GetView()->PasteDraw(
4936 aLogicPos
, rData
.pDrawTransfer
->GetModel(), false, u
"A", u
"B");
4939 rData
.pDrawTransfer
->SetDragWasInternal();
4940 bPasteIsMove
= false;
4942 return rEvt
.mnAction
;
4947 mrViewData
.GetPosFromPixel( aPos
.X(), aPos
.Y(), eWhich
, nPosX
, nPosY
);
4949 if (!rData
.aJumpTarget
.isEmpty())
4951 // internal bookmark (from Navigator)
4952 // bookmark clipboard formats are in PasteScDataObject
4954 if ( !rData
.pJumpLocalDoc
|| rData
.pJumpLocalDoc
== &mrViewData
.GetDocument() )
4956 mrViewData
.GetViewShell()->InsertBookmark( rData
.aJumpText
, rData
.aJumpTarget
,
4958 return rEvt
.mnAction
;
4962 ScDocument
& rThisDoc
= mrViewData
.GetDocument();
4963 SdrObject
* pHitObj
= rThisDoc
.GetObjectAtPoint( mrViewData
.GetTabNo(), PixelToLogic(aPos
) );
4964 if ( pHitObj
&& bIsLink
)
4966 // dropped on drawing object
4967 // PasteOnDrawObjectLinked checks for valid formats
4968 if ( mrViewData
.GetView()->PasteOnDrawObjectLinked( rEvt
.maDropEvent
.Transferable
, *pHitObj
) )
4969 return rEvt
.mnAction
;
4974 SotClipboardFormatId nFormatId
= bIsLink
?
4975 lcl_GetDropLinkId( rEvt
.maDropEvent
.Transferable
) :
4976 lcl_GetDropFormatId( rEvt
.maDropEvent
.Transferable
, false );
4977 if ( nFormatId
!= SotClipboardFormatId::NONE
)
4979 pScMod
->SetInExecuteDrop( true ); // #i28468# prevent error messages from PasteDataFormat
4980 bDone
= mrViewData
.GetView()->PasteDataFormat(
4981 nFormatId
, rEvt
.maDropEvent
.Transferable
, nPosX
, nPosY
, &aLogicPos
, bIsLink
);
4982 pScMod
->SetInExecuteDrop( false );
4985 sal_Int8 nRet
= bDone
? rEvt
.mnAction
: DND_ACTION_NONE
;
4989 void ScGridWindow::PasteSelection( const Point
& rPosPixel
)
4991 Point aLogicPos
= PixelToLogic( rPosPixel
);
4995 mrViewData
.GetPosFromPixel( rPosPixel
.X(), rPosPixel
.Y(), eWhich
, nPosX
, nPosY
);
4997 // If the mouse down was inside a visible note window, ignore it and
4998 // leave it up to the ScPostIt to handle it
4999 SdrView
* pDrawView
= mrViewData
.GetViewShell()->GetScDrawView();
5002 const SdrMarkList
& rMarkList
= pDrawView
->GetMarkedObjectList();
5003 const size_t nCount
= rMarkList
.GetMarkCount();
5004 for (size_t i
= 0; i
< nCount
; ++i
)
5006 SdrObject
* pObj
= rMarkList
.GetMark(i
)->GetMarkedSdrObj();
5007 if (pObj
&& pObj
->GetLogicRect().Contains(aLogicPos
))
5009 // Inside an active drawing object. Bail out.
5015 ScSelectionTransferObj
* pOwnSelection
= ScModule::get()->GetSelectionTransfer();
5016 if ( pOwnSelection
)
5020 // keep a reference to the data in case the selection is changed during paste
5021 rtl::Reference
<ScTransferObj
> pCellTransfer
= pOwnSelection
->GetCellData();
5022 if ( pCellTransfer
)
5024 DropTransferObj( pCellTransfer
.get(), nPosX
, nPosY
, aLogicPos
, DND_ACTION_COPY
);
5028 // keep a reference to the data in case the selection is changed during paste
5029 rtl::Reference
<ScDrawTransferObj
> pDrawTransfer
= pOwnSelection
->GetDrawData();
5030 if ( pDrawTransfer
)
5032 // bSameDocClipboard argument for PasteDraw is needed
5033 // because only DragData is checked directly inside PasteDraw
5034 mrViewData
.GetView()->PasteDraw(
5035 aLogicPos
, pDrawTransfer
->GetModel(), false,
5036 pDrawTransfer
->GetShellID(), SfxObjectShell::CreateShellID(mrViewData
.GetDocShell()));
5042 // get selection from system
5043 TransferableDataHelper
aDataHelper(TransferableDataHelper::CreateFromPrimarySelection());
5044 const uno::Reference
<datatransfer::XTransferable
>& xTransferable
= aDataHelper
.GetTransferable();
5045 if ( xTransferable
.is() )
5047 SotClipboardFormatId nFormatId
= lcl_GetDropFormatId( xTransferable
, true );
5048 if ( nFormatId
!= SotClipboardFormatId::NONE
)
5049 mrViewData
.GetView()->PasteDataFormat( nFormatId
, xTransferable
, nPosX
, nPosY
, &aLogicPos
);
5054 void ScGridWindow::UpdateEditViewPos()
5056 if (!mrViewData
.HasEditView(eWhich
))
5062 mrViewData
.GetEditView( eWhich
, pView
, nCol
, nRow
);
5063 SCCOL nEndCol
= mrViewData
.GetEditEndCol();
5064 SCROW nEndRow
= mrViewData
.GetEditEndRow();
5068 bool bHide
= ( nEndCol
<mrViewData
.GetPosX(eHWhich
) || nEndRow
<mrViewData
.GetPosY(eVWhich
) );
5069 if (ScModule::get()->IsFormulaMode())
5070 if ( mrViewData
.GetTabNo() != mrViewData
.GetRefTabNo() )
5075 tools::Rectangle aRect
= pView
->GetOutputArea();
5076 tools::Long nHeight
= aRect
.Bottom() - aRect
.Top();
5077 aRect
.SetTop( PixelToLogic(GetOutputSizePixel(), mrViewData
.GetLogicMode()).
5079 aRect
.SetBottom( aRect
.Top() + nHeight
);
5080 pView
->SetOutputArea( aRect
);
5081 pView
->HideCursor();
5085 // bForceToTop = sal_True for editing
5086 tools::Rectangle aPixRect
= mrViewData
.GetEditArea( eWhich
, nCol
, nRow
, this, nullptr, true );
5088 if (comphelper::LibreOfficeKit::isActive() &&
5089 comphelper::LibreOfficeKit::isCompatFlagSet(
5090 comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs
))
5092 tools::Rectangle aPTwipsRect
= mrViewData
.GetEditArea(eWhich
, nCol
, nRow
, this, nullptr,
5093 true, true /* bInPrintTwips */);
5094 tools::Rectangle aOutputAreaPTwips
= pView
->GetLOKSpecialOutputArea();
5095 aOutputAreaPTwips
.SetPos(aPTwipsRect
.TopLeft());
5096 pView
->SetLOKSpecialOutputArea(aOutputAreaPTwips
);
5099 Point aScrPos
= PixelToLogic( aPixRect
.TopLeft(), mrViewData
.GetLogicMode() );
5101 tools::Rectangle aRect
= pView
->GetOutputArea();
5102 aRect
.SetPos( aScrPos
);
5103 pView
->SetOutputArea( aRect
);
5104 pView
->ShowCursor();
5108 void ScGridWindow::ScrollPixel( tools::Long nDifX
, tools::Long nDifY
)
5113 SetMapMode(MapMode(MapUnit::MapPixel
));
5114 Scroll( nDifX
, nDifY
, ScrollFlags::Children
);
5115 SetMapMode( GetDrawMapMode() ); // generated shifted MapMode
5117 UpdateEditViewPos();
5122 // Update Formulas ------------------------------------------------------
5124 void ScGridWindow::UpdateFormulas(SCCOL nX1
, SCROW nY1
, SCCOL nX2
, SCROW nY2
)
5126 if (mrViewData
.GetView()->IsMinimized())
5131 // Do not start, switched to paint
5132 // (then at least the MapMode would no longer be right)
5134 bNeedsRepaint
= true; // -> at end of paint run Invalidate on all
5135 aRepaintPixel
= tools::Rectangle(); // All
5139 if ( comphelper::LibreOfficeKit::isActive() )
5141 ScTabViewShell
* pViewShell
= mrViewData
.GetViewShell();
5144 nX1
= pViewShell
->GetLOKStartHeaderCol() + 1;
5146 nY1
= pViewShell
->GetLOKStartHeaderRow() + 1;
5148 nX2
= pViewShell
->GetLOKEndHeaderCol();
5150 nY2
= pViewShell
->GetLOKEndHeaderRow();
5152 if (nX1
< 0 || nY1
< 0) return;
5154 // Consider frozen ranges not in main pane range as candidates
5156 SCCOLROW nFreezeCol
= mrViewData
.GetLOKSheetFreezeIndex(true);
5157 SCCOLROW nFreezeRow
= mrViewData
.GetLOKSheetFreezeIndex(false);
5158 if ((nFreezeCol
|| nFreezeRow
) && (nX1
|| nY1
))
5161 if (nFreezeCol
&& nFreezeRow
)
5162 UpdateFormulaRange(0, 0, nFreezeCol
, nFreezeRow
);
5164 if (nFreezeCol
&& nX1
)
5165 UpdateFormulaRange(0, nY1
, nFreezeCol
, nY2
);
5167 if (nFreezeRow
&& nY1
)
5168 UpdateFormulaRange(nX1
, 0, nX2
, nFreezeRow
);
5173 nX1
= mrViewData
.GetPosX( eHWhich
);
5174 nY1
= mrViewData
.GetPosY( eVWhich
);
5175 nX2
= nX1
+ mrViewData
.VisibleCellsX( eHWhich
);
5176 nY2
= nY1
+ mrViewData
.VisibleCellsY( eVWhich
);
5179 UpdateFormulaRange(nX1
, nY1
, nX2
, nY2
);
5182 void ScGridWindow::UpdateFormulaRange(SCCOL nX1
, SCROW nY1
, SCCOL nX2
, SCROW nY2
)
5184 if (nX2
< nX1
) nX2
= nX1
;
5185 if (nY2
< nY1
) nY2
= nY1
;
5187 ScDocument
& rDoc
= mrViewData
.GetDocument();
5189 if (nX2
> rDoc
.MaxCol()) nX2
= rDoc
.MaxCol();
5190 if (nY2
> rDoc
.MaxRow()) nY2
= rDoc
.MaxRow();
5192 // Draw( nX1, nY1, nX2, nY2, SC_UPDATE_CHANGED );
5194 // don't draw directly - instead use OutputData to find changed area and invalidate
5198 SCTAB nTab
= mrViewData
.GetTabNo();
5200 if ( !comphelper::LibreOfficeKit::isActive() )
5202 rDoc
.ExtendHidden( nX1
, nY1
, nX2
, nY2
, nTab
);
5205 Point aScrPos
= mrViewData
.GetScrPos( nX1
, nY1
, eWhich
);
5206 tools::Long nMirrorWidth
= GetSizePixel().Width();
5207 bool bLayoutRTL
= rDoc
.IsLayoutRTL( nTab
);
5210 tools::Long nEndPixel
= mrViewData
.GetScrPos( nX2
+1, nPosY
, eWhich
).X();
5211 nMirrorWidth
= aScrPos
.X() - nEndPixel
;
5212 aScrPos
.setX( nEndPixel
+ 1 );
5215 tools::Long nScrX
= aScrPos
.X();
5216 tools::Long nScrY
= aScrPos
.Y();
5218 double nPPTX
= mrViewData
.GetPPTX();
5219 double nPPTY
= mrViewData
.GetPPTY();
5221 ScTableInfo
aTabInfo(nY1
, nY2
, true);
5222 rDoc
.FillInfo( aTabInfo
, nX1
, nY1
, nX2
, nY2
, nTab
, nPPTX
, nPPTY
, false, false );
5224 Fraction aZoomX
= mrViewData
.GetZoomX();
5225 Fraction aZoomY
= mrViewData
.GetZoomY();
5226 ScOutputData
aOutputData( GetOutDev(), OUTTYPE_WINDOW
, aTabInfo
, &rDoc
, nTab
,
5227 nScrX
, nScrY
, nX1
, nY1
, nX2
, nY2
, nPPTX
, nPPTY
,
5229 aOutputData
.SetMirrorWidth( nMirrorWidth
);
5231 aOutputData
.FindChanged();
5233 // #i122149# do not use old GetChangedArea() which used polygon-based Regions, but use
5234 // the region-band based new version; anyways, only rectangles are added
5235 vcl::Region
aChangedRegion( aOutputData
.GetChangedAreaRegion() ); // logic (PixelToLogic)
5236 if(!aChangedRegion
.IsEmpty())
5238 Invalidate(aChangedRegion
);
5241 CheckNeedsRepaint(); // #i90362# used to be called via Draw() - still needed here
5244 void ScGridWindow::UpdateAutoFillMark(bool bMarked
, const ScRange
& rMarkRange
)
5246 if ( bMarked
!= bAutoMarkVisible
|| ( bMarked
&& rMarkRange
.aEnd
!= aAutoMarkPos
) )
5248 bAutoMarkVisible
= bMarked
;
5250 aAutoMarkPos
= rMarkRange
.aEnd
;
5252 UpdateAutoFillOverlay();
5256 void ScGridWindow::updateLOKInputHelp(const OUString
& title
, const OUString
& content
) const
5258 ScTabViewShell
* pViewShell
= mrViewData
.GetViewShell();
5260 boost::property_tree::ptree aTree
;
5261 aTree
.put("title", title
);
5262 aTree
.put("content", content
);
5264 std::stringstream aStream
;
5265 boost::property_tree::write_json(aStream
, aTree
);
5266 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_VALIDITY_INPUT_HELP
, OString(aStream
.str()));
5269 void ScGridWindow::updateLOKValListButton( bool bVisible
, const ScAddress
& rPos
) const
5271 SCCOL nX
= rPos
.Col();
5272 SCROW nY
= rPos
.Row();
5273 std::stringstream ss
;
5274 ss
<< nX
<< ", " << nY
<< ", " << static_cast<unsigned int>(bVisible
);
5275 ScTabViewShell
* pViewShell
= mrViewData
.GetViewShell();
5276 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_VALIDITY_LIST_BUTTON
, OString(ss
.str()));
5279 void ScGridWindow::notifyKitCellFollowJump( ) const
5281 ScTabViewShell
* pViewShell
= mrViewData
.GetViewShell();
5283 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_SC_FOLLOW_JUMP
, getCellCursor());
5286 void ScGridWindow::UpdateListValPos( bool bVisible
, const ScAddress
& rPos
)
5288 bool bOldButton
= bListValButton
;
5289 ScAddress aOldPos
= aListValPos
;
5291 bListValButton
= bVisible
;
5294 if ( bListValButton
)
5296 if ( !bOldButton
|| aListValPos
!= aOldPos
)
5298 // paint area of new button
5299 if ( comphelper::LibreOfficeKit::isActive() )
5301 updateLOKValListButton( true, aListValPos
);
5305 Invalidate( PixelToLogic( GetListValButtonRect( aListValPos
) ) );
5312 if ( !bListValButton
|| aListValPos
!= aOldPos
)
5314 // paint area of old button
5315 if ( comphelper::LibreOfficeKit::isActive() )
5317 updateLOKValListButton( false, aOldPos
);
5321 Invalidate( PixelToLogic( GetListValButtonRect( aOldPos
) ) );
5326 void ScGridWindow::HideCursor()
5331 void ScGridWindow::ShowCursor()
5336 void ScGridWindow::GetFocus()
5338 ScTabViewShell
* pViewShell
= mrViewData
.GetViewShell();
5339 pViewShell
->SetFormShellAtTop( false ); // focus in GridWindow -> FormShell no longer on top
5341 if (pViewShell
->HasAccessibilityObjects())
5342 pViewShell
->BroadcastAccessibility(ScAccGridWinFocusGotHint(eWhich
));
5344 if (!ScModule::get()->IsFormulaMode())
5346 pViewShell
->UpdateInputHandler();
5347 // StopMarking(); // If Dialog (error), because then no ButtonUp
5348 // MO: only when not in RefInput mode
5349 // -> GetFocus/MouseButtonDown order on Mac
5352 mrViewData
.GetDocShell()->CheckConfigOptions();
5356 void ScGridWindow::LoseFocus()
5358 ScTabViewShell
* pViewShell
= mrViewData
.GetViewShell();
5360 if (pViewShell
&& pViewShell
->HasAccessibilityObjects())
5361 pViewShell
->BroadcastAccessibility(ScAccGridWinFocusLostHint(eWhich
));
5363 Window::LoseFocus();
5366 bool ScGridWindow::HitRangeFinder( const Point
& rMouse
, RfCorner
& rCorner
,
5367 sal_uInt16
* pIndex
, SCCOL
* pAddX
, SCROW
* pAddY
)
5369 bool bFound
= false;
5370 ScInputHandler
* pHdl
= ScModule::get()->GetInputHdl(mrViewData
.GetViewShell());
5373 ScRangeFindList
* pRangeFinder
= pHdl
->GetRangeFindList();
5374 if ( pRangeFinder
&& !pRangeFinder
->IsHidden() &&
5375 pRangeFinder
->GetDocName() == mrViewData
.GetDocShell()->GetTitle() )
5377 ScDocument
& rDoc
= mrViewData
.GetDocument();
5378 SCTAB nTab
= mrViewData
.GetTabNo();
5379 bool bLayoutRTL
= rDoc
.IsLayoutRTL( nTab
);
5380 tools::Long nLayoutSign
= bLayoutRTL
? -1 : 1;
5384 mrViewData
.GetPosFromPixel( rMouse
.X(), rMouse
.Y(), eWhich
, nPosX
, nPosY
);
5385 // merged (single/Range) ???
5386 ScAddress
aAddr( nPosX
, nPosY
, nTab
);
5388 Point aCellStart
= mrViewData
.GetScrPos( nPosX
, nPosY
, eWhich
, true );
5389 Point aCellEnd
= aCellStart
;
5390 tools::Long nSizeXPix
;
5391 tools::Long nSizeYPix
;
5392 mrViewData
.GetMergeSizePixel( nPosX
, nPosY
, nSizeXPix
, nSizeYPix
);
5394 aCellEnd
.AdjustX(nSizeXPix
* nLayoutSign
);
5395 aCellEnd
.AdjustY(nSizeYPix
);
5397 bool bCornerHorizontalRight
;
5398 bool bCornerHorizontalLeft
;
5401 bCornerHorizontalRight
= ( rMouse
.X() >= aCellEnd
.X() && rMouse
.X() <= aCellEnd
.X() + 8 );
5402 bCornerHorizontalLeft
= ( rMouse
.X() >= aCellStart
.X() - 8 && rMouse
.X() <= aCellStart
.X() );
5406 bCornerHorizontalRight
= ( rMouse
.X() >= aCellEnd
.X() - 8 && rMouse
.X() <= aCellEnd
.X() );
5407 bCornerHorizontalLeft
= ( rMouse
.X() >= aCellStart
.X() && rMouse
.X() <= aCellStart
.X() + 8 );
5410 bool bCornerVerticalDown
= rMouse
.Y() >= aCellEnd
.Y() - 8 && rMouse
.Y() <= aCellEnd
.Y();
5411 bool bCornerVerticalUp
= rMouse
.Y() >= aCellStart
.Y() && rMouse
.Y() <= aCellStart
.Y() + 8;
5413 // corner is hit only if the mouse is within the cell
5414 sal_uInt16 nCount
= static_cast<sal_uInt16
>(pRangeFinder
->Count());
5415 for (sal_uInt16 i
=nCount
; i
;)
5417 // search backwards so that the last repainted frame is found
5419 ScRangeFindData
& rData
= pRangeFinder
->GetObject(i
);
5420 if ( rData
.aRef
.Contains(aAddr
) )
5425 *pAddX
= nPosX
- rData
.aRef
.aStart
.Col();
5427 *pAddY
= nPosY
- rData
.aRef
.aStart
.Row();
5433 ScAddress aEnd
= rData
.aRef
.aEnd
;
5434 ScAddress aStart
= rData
.aRef
.aStart
;
5436 if ( bCornerHorizontalLeft
&& bCornerVerticalUp
&&
5441 else if (bCornerHorizontalRight
&& bCornerVerticalDown
&&
5444 rCorner
= RIGHT_DOWN
;
5446 else if (bCornerHorizontalRight
&& bCornerVerticalUp
&&
5447 aAddr
== ScAddress(aEnd
.Col(), aStart
.Row(), aStart
.Tab()))
5451 else if (bCornerHorizontalLeft
&& bCornerVerticalDown
&&
5452 aAddr
== ScAddress(aStart
.Col(), aEnd
.Row(), aStart
.Tab()))
5454 rCorner
= LEFT_DOWN
;
5465 #define SCE_BOTTOM 2
5470 static void lcl_PaintOneRange( ScDocShell
* pDocSh
, const ScRange
& rRange
, sal_uInt16 nEdges
)
5472 // the range is always properly oriented
5474 SCCOL nCol1
= rRange
.aStart
.Col();
5475 SCROW nRow1
= rRange
.aStart
.Row();
5476 SCTAB nTab1
= rRange
.aStart
.Tab();
5477 SCCOL nCol2
= rRange
.aEnd
.Col();
5478 SCROW nRow2
= rRange
.aEnd
.Row();
5479 SCTAB nTab2
= rRange
.aEnd
.Tab();
5480 bool bHiddenEdge
= false;
5483 ScDocument
& rDoc
= pDocSh
->GetDocument();
5484 while ( nCol1
> 0 && rDoc
.ColHidden(nCol1
, nTab1
) )
5489 while ( nCol2
< rDoc
.MaxCol() && rDoc
.ColHidden(nCol2
, nTab1
) )
5494 nTmp
= rDoc
.FirstVisibleRow(0, nRow1
, nTab1
);
5495 if (!rDoc
.ValidRow(nTmp
))
5502 nTmp
= rDoc
.FirstVisibleRow(nRow2
, rDoc
.MaxRow(), nTab1
);
5503 if (!rDoc
.ValidRow(nTmp
))
5504 nTmp
= rDoc
.MaxRow();
5511 if ( nCol2
> nCol1
+ 1 && nRow2
> nRow1
+ 1 && !bHiddenEdge
)
5513 // Only along the edges (The corners are hit twice)
5514 if ( nEdges
& SCE_TOP
)
5515 pDocSh
->PostPaint( nCol1
, nRow1
, nTab1
, nCol2
, nRow1
, nTab2
, PaintPartFlags::Marks
);
5516 if ( nEdges
& SCE_LEFT
)
5517 pDocSh
->PostPaint( nCol1
, nRow1
, nTab1
, nCol1
, nRow2
, nTab2
, PaintPartFlags::Marks
);
5518 if ( nEdges
& SCE_RIGHT
)
5519 pDocSh
->PostPaint( nCol2
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
, PaintPartFlags::Marks
);
5520 if ( nEdges
& SCE_BOTTOM
)
5521 pDocSh
->PostPaint( nCol1
, nRow2
, nTab1
, nCol2
, nRow2
, nTab2
, PaintPartFlags::Marks
);
5523 else // everything in one call
5524 pDocSh
->PostPaint( nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
, PaintPartFlags::Marks
);
5527 static void lcl_PaintRefChanged( ScDocShell
* pDocSh
, const ScRange
& rOldUn
, const ScRange
& rNewUn
)
5529 // Repaint for the parts of the frame in old, which in are no more in New
5531 ScRange aOld
= rOldUn
;
5532 ScRange aNew
= rNewUn
;
5536 if ( aOld
.aStart
== aOld
.aEnd
) //! Ignore sheet ?
5537 pDocSh
->GetDocument().ExtendMerge(aOld
);
5538 if ( aNew
.aStart
== aNew
.aEnd
) //! Ignore sheet ?
5539 pDocSh
->GetDocument().ExtendMerge(aNew
);
5541 SCCOL nOldCol1
= aOld
.aStart
.Col();
5542 SCROW nOldRow1
= aOld
.aStart
.Row();
5543 SCCOL nOldCol2
= aOld
.aEnd
.Col();
5544 SCROW nOldRow2
= aOld
.aEnd
.Row();
5545 SCCOL nNewCol1
= aNew
.aStart
.Col();
5546 SCROW nNewRow1
= aNew
.aStart
.Row();
5547 SCCOL nNewCol2
= aNew
.aEnd
.Col();
5548 SCROW nNewRow2
= aNew
.aEnd
.Row();
5549 SCTAB nTab1
= aOld
.aStart
.Tab(); // sheet is not changed
5550 SCTAB nTab2
= aOld
.aEnd
.Tab();
5552 if ( nNewRow2
< nOldRow1
|| nNewRow1
> nOldRow2
||
5553 nNewCol2
< nOldCol1
|| nNewCol1
> nOldCol2
||
5554 ( nNewCol1
!= nOldCol1
&& nNewRow1
!= nOldRow1
&&
5555 nNewCol2
!= nOldCol2
&& nNewRow2
!= nOldRow2
) )
5557 // Completely removed or changed all sides
5558 // (check <= instead of < goes wrong for single rows/columns)
5560 lcl_PaintOneRange( pDocSh
, aOld
, SCE_ALL
);
5562 else // Test all four corners separately
5565 if ( nNewRow1
< nOldRow1
) // only delete upper line
5566 lcl_PaintOneRange( pDocSh
, ScRange(
5567 nOldCol1
, nOldRow1
, nTab1
, nOldCol2
, nOldRow1
, nTab2
), SCE_ALL
);
5568 else if ( nNewRow1
> nOldRow1
) // the upper part which is will be removed
5569 lcl_PaintOneRange( pDocSh
, ScRange(
5570 nOldCol1
, nOldRow1
, nTab1
, nOldCol2
, nNewRow1
-1, nTab2
),
5571 SCE_ALL
&~ SCE_BOTTOM
);
5574 if ( nNewRow2
> nOldRow2
) // only delete bottom line
5575 lcl_PaintOneRange( pDocSh
, ScRange(
5576 nOldCol1
, nOldRow2
, nTab1
, nOldCol2
, nOldRow2
, nTab2
), SCE_ALL
);
5577 else if ( nNewRow2
< nOldRow2
) // the bottom part which is will be removed
5578 lcl_PaintOneRange( pDocSh
, ScRange(
5579 nOldCol1
, nNewRow2
+1, nTab1
, nOldCol2
, nOldRow2
, nTab2
),
5580 SCE_ALL
&~ SCE_TOP
);
5583 if ( nNewCol1
< nOldCol1
) // only delete left line
5584 lcl_PaintOneRange( pDocSh
, ScRange(
5585 nOldCol1
, nOldRow1
, nTab1
, nOldCol1
, nOldRow2
, nTab2
), SCE_ALL
);
5586 else if ( nNewCol1
> nOldCol1
) // the left part which is will be removed
5587 lcl_PaintOneRange( pDocSh
, ScRange(
5588 nOldCol1
, nOldRow1
, nTab1
, nNewCol1
-1, nOldRow2
, nTab2
),
5589 SCE_ALL
&~ SCE_RIGHT
);
5592 if ( nNewCol2
> nOldCol2
) // only delete right line
5593 lcl_PaintOneRange( pDocSh
, ScRange(
5594 nOldCol2
, nOldRow1
, nTab1
, nOldCol2
, nOldRow2
, nTab2
), SCE_ALL
);
5595 else if ( nNewCol2
< nOldCol2
) // the right part which is will be removed
5596 lcl_PaintOneRange( pDocSh
, ScRange(
5597 nNewCol2
+1, nOldRow1
, nTab1
, nOldCol2
, nOldRow2
, nTab2
),
5598 SCE_ALL
&~ SCE_LEFT
);
5602 void ScGridWindow::RFMouseMove( const MouseEvent
& rMEvt
, bool bUp
)
5604 ScInputHandler
* pHdl
= ScModule::get()->GetInputHdl(mrViewData
.GetViewShell());
5607 ScRangeFindList
* pRangeFinder
= pHdl
->GetRangeFindList();
5608 if (!pRangeFinder
|| nRFIndex
>= pRangeFinder
->Count())
5610 ScRangeFindData
& rData
= pRangeFinder
->GetObject( nRFIndex
);
5615 SetPointer( PointerStyle::Cross
);
5617 SetPointer( PointerStyle::Hand
);
5621 bool bTimer
= false;
5622 Point aPos
= rMEvt
.GetPosPixel();
5625 if ( aPos
.X() < 0 ) nDx
= -1;
5626 if ( aPos
.Y() < 0 ) nDy
= -1;
5627 Size aSize
= GetOutputSizePixel();
5628 if ( aPos
.X() >= aSize
.Width() )
5630 if ( aPos
.Y() >= aSize
.Height() )
5632 if ( nDx
!= 0 || nDy
!= 0 )
5634 if ( nDx
!= 0) mrViewData
.GetView()->ScrollX( nDx
, WhichH(eWhich
) );
5635 if ( nDy
!= 0 ) mrViewData
.GetView()->ScrollY( nDy
, WhichV(eWhich
) );
5639 // Switching when fixating (so Scrolling works)
5641 if ( eWhich
== mrViewData
.GetActivePart() ) //??
5643 if ( mrViewData
.GetHSplitMode() == SC_SPLIT_FIX
)
5646 if ( eWhich
== SC_SPLIT_TOPLEFT
)
5647 mrViewData
.GetView()->ActivatePart( SC_SPLIT_TOPRIGHT
);
5648 else if ( eWhich
== SC_SPLIT_BOTTOMLEFT
)
5649 mrViewData
.GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT
);
5652 if ( mrViewData
.GetVSplitMode() == SC_SPLIT_FIX
)
5655 if ( eWhich
== SC_SPLIT_TOPLEFT
)
5656 mrViewData
.GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT
);
5657 else if ( eWhich
== SC_SPLIT_TOPRIGHT
)
5658 mrViewData
.GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT
);
5666 mrViewData
.GetPosFromPixel( aPos
.X(), aPos
.Y(), eWhich
, nPosX
, nPosY
);
5668 ScRange aOld
= rData
.aRef
;
5669 ScRange aNew
= aOld
;
5672 switch (aRFSelectedCorned
)
5675 aNew
.aStart
.SetCol(nPosX
);
5676 aNew
.aStart
.SetRow(nPosY
);
5679 aNew
.aStart
.SetCol(nPosX
);
5680 aNew
.aEnd
.SetRow(nPosY
);
5683 aNew
.aEnd
.SetCol(nPosX
);
5684 aNew
.aStart
.SetRow(nPosY
);
5687 aNew
.aEnd
.SetCol(nPosX
);
5688 aNew
.aEnd
.SetRow(nPosY
);
5696 ScDocument
& rDoc
= mrViewData
.GetDocument();
5697 tools::Long nStartX
= nPosX
- nRFAddX
;
5698 if ( nStartX
< 0 ) nStartX
= 0;
5699 tools::Long nStartY
= nPosY
- nRFAddY
;
5700 if ( nStartY
< 0 ) nStartY
= 0;
5701 tools::Long nEndX
= nStartX
+ aOld
.aEnd
.Col() - aOld
.aStart
.Col();
5702 if ( nEndX
> rDoc
.MaxCol() )
5704 nStartX
-= ( nEndX
- rDoc
.MaxRow() );
5705 nEndX
= rDoc
.MaxCol();
5707 tools::Long nEndY
= nStartY
+ aOld
.aEnd
.Row() - aOld
.aStart
.Row();
5708 if ( nEndY
> rDoc
.MaxRow() )
5710 nStartY
-= ( nEndY
- rDoc
.MaxRow() );
5711 nEndY
= rDoc
.MaxRow();
5714 aNew
.aStart
.SetCol(static_cast<SCCOL
>(nStartX
));
5715 aNew
.aStart
.SetRow(static_cast<SCROW
>(nStartY
));
5716 aNew
.aEnd
.SetCol(static_cast<SCCOL
>(nEndX
));
5717 aNew
.aEnd
.SetRow(static_cast<SCROW
>(nEndY
));
5721 aNew
.PutInOrder(); // For ButtonUp again in the proper order
5725 pHdl
->UpdateRange( nRFIndex
, aNew
);
5727 ScDocShell
* pDocSh
= mrViewData
.GetDocShell();
5729 pHdl
->UpdateLokReferenceMarks();
5731 // only redrawing what has been changed...
5732 lcl_PaintRefChanged( pDocSh
, aOld
, aNew
);
5734 // only redraw new frame (synchronously)
5735 pDocSh
->Broadcast( ScIndexHint( SfxHintId::ScShowRangeFinder
, nRFIndex
) );
5737 PaintImmediately(); // what you move, will be seen immediately
5740 // Timer for Scrolling
5743 mrViewData
.GetView()->SetTimer( this, rMEvt
); // repeat event
5745 mrViewData
.GetView()->ResetTimer();
5750 SvxAdjust
toSvxAdjust( const ScPatternAttr
& rPat
)
5752 SvxCellHorJustify eHorJust
=
5753 rPat
.GetItem(ATTR_HOR_JUSTIFY
).GetValue();
5755 SvxAdjust eSvxAdjust
= SvxAdjust::Left
;
5758 case SvxCellHorJustify::Left
:
5759 case SvxCellHorJustify::Repeat
: // not implemented
5760 case SvxCellHorJustify::Standard
: // always Text if an EditCell type
5761 eSvxAdjust
= SvxAdjust::Left
;
5763 case SvxCellHorJustify::Right
:
5764 eSvxAdjust
= SvxAdjust::Right
;
5766 case SvxCellHorJustify::Center
:
5767 eSvxAdjust
= SvxAdjust::Center
;
5769 case SvxCellHorJustify::Block
:
5770 eSvxAdjust
= SvxAdjust::Block
;
5777 std::shared_ptr
<ScFieldEditEngine
> createEditEngine( ScDocShell
* pDocSh
, const ScPatternAttr
& rPat
)
5779 ScDocument
& rDoc
= pDocSh
->GetDocument();
5781 auto pEngine
= std::make_shared
<ScFieldEditEngine
>(&rDoc
, rDoc
.GetEditPool());
5782 ScSizeDeviceProvider
aProv(pDocSh
);
5783 pEngine
->SetRefDevice(aProv
.GetDevice());
5784 pEngine
->SetRefMapMode(MapMode(MapUnit::Map100thMM
));
5785 auto pDefault
= std::make_unique
<SfxItemSet
>(pEngine
->GetEmptyItemSet());
5786 rPat
.FillEditItemSet(pDefault
.get());
5787 pDefault
->Put(SvxAdjustItem(toSvxAdjust(rPat
), EE_PARA_JUST
));
5788 pEngine
->SetDefaults(std::move(pDefault
));
5793 bool extractURLInfo( const SvxFieldItem
* pFieldItem
, OUString
* pName
, OUString
* pUrl
, OUString
* pTarget
)
5798 const SvxFieldData
* pField
= pFieldItem
->GetField();
5799 if (pField
->GetClassId() != text::textfield::Type::URL
)
5802 const SvxURLField
* pURLField
= static_cast<const SvxURLField
*>(pField
);
5805 *pName
= pURLField
->GetRepresentation();
5807 *pUrl
= pURLField
->GetURL();
5809 *pTarget
= pURLField
->GetTargetFrame();
5816 static void lcl_SetEngineTextKeepingDefaults(const std::shared_ptr
<ScFieldEditEngine
>& pEngine
,
5817 ScDocument
& rDoc
, ScRefCellValue
& rCell
, const OUString
& rURL
)
5819 std::unique_ptr
<EditTextObject
> pTextObj
;
5820 if (rCell
.getType() == CELLTYPE_EDIT
)
5822 if (rCell
.getEditText())
5823 pEngine
->SetTextCurrentDefaults(*rCell
.getEditText());
5825 else // Not an Edit cell and is a formula cell with 'Hyperlink'
5826 // function if we have no URL, otherwise it could be a formula
5827 // cell ( or other type ? ) with a hyperlink associated with it.
5830 pTextObj
= rCell
.getFormula()->CreateURLObject();
5833 OUString aRepres
= rURL
;
5835 // TODO: text content of formatted numbers can be different
5836 if (rCell
.hasNumeric())
5837 aRepres
= OUString::number(rCell
.getValue());
5838 else if (rCell
.getType() == CELLTYPE_FORMULA
)
5839 aRepres
= rCell
.getFormula()->GetString().getString();
5841 pTextObj
= ScEditUtil::CreateURLObjectFromURL(rDoc
, rURL
, aRepres
);
5845 pEngine
->SetTextCurrentDefaults(*pTextObj
);
5849 static std::vector
<std::unique_ptr
<SvxFieldItem
>> lcl_GetEditEngineFields(const ScFieldEditEngine
& rEditEngine
)
5851 std::vector
<std::unique_ptr
<SvxFieldItem
>> vFieldVect
;
5853 sal_Int32 nPara
= rEditEngine
.GetParagraphCount();
5854 for (sal_Int32 nCurrPara
= 0; nCurrPara
< nPara
; ++nCurrPara
)
5856 for (EFieldInfo
& rFieldInfo
: rEditEngine
.GetFieldInfo(nCurrPara
))
5858 vFieldVect
.push_back(std::move(rFieldInfo
.pFieldItem
));
5865 std::vector
<UrlData
> ScGridWindow::GetEditUrls(const ScAddress
& rSelectedCell
)
5867 ScDocShell
* pDocSh
= mrViewData
.GetDocShell();
5868 ScDocument
& rDoc
= pDocSh
->GetDocument();
5870 SCCOL nPosX
= rSelectedCell
.Col();
5871 SCROW nPosY
= rSelectedCell
.Row();
5872 SCTAB nTab
= rSelectedCell
.Tab();
5875 ScRefCellValue aCell
;
5876 std::vector
<UrlData
> vUrls
;
5877 if (!lcl_GetHyperlinkCell(rDoc
, nPosX
, nPosY
, nTab
, aCell
, sURL
))
5880 if (nPosX
!= rSelectedCell
.Col())
5883 const ScPatternAttr
* pPattern
= rDoc
.GetPattern( nPosX
, nPosY
, nTab
);
5885 std::shared_ptr
<ScFieldEditEngine
> pEngine
= createEditEngine(pDocSh
, *pPattern
);
5887 lcl_SetEngineTextKeepingDefaults(pEngine
, rDoc
, aCell
, sURL
);
5889 std::vector
<std::unique_ptr
<SvxFieldItem
>> vFieldItems
= lcl_GetEditEngineFields(*pEngine
);
5890 for (auto& pFieldItem
: vFieldItems
)
5893 bool bIsUrl
= extractURLInfo(pFieldItem
.get(), &aData
.aName
, &aData
.aUrl
, &aData
.aTarget
);
5894 if (bIsUrl
&& !aData
.aUrl
.isEmpty())
5895 vUrls
.push_back(aData
);
5900 bool ScGridWindow::GetEditUrl(const Point
& rPos
, OUString
* pName
, OUString
* pUrl
, OUString
* pTarget
,
5903 ScTabViewShell
* pViewSh
= mrViewData
.GetViewShell();
5904 ScInputHandler
* pInputHdl
= nullptr;
5906 pInputHdl
= pViewSh
->GetInputHandler();
5907 EditView
* pView
= (pInputHdl
&& pInputHdl
->IsInputMode()) ? pInputHdl
->GetTableView() : nullptr;
5909 return extractURLInfo(pView
->GetFieldUnderMousePointer(), pName
, pUrl
, pTarget
);
5911 //! Pass on nPosX/Y?
5914 mrViewData
.GetPosFromPixel( rPos
.X(), rPos
.Y(), eWhich
, nPosX
, nPosY
);
5916 SCTAB nTab
= mrViewData
.GetTabNo();
5917 ScDocShell
* pDocSh
= mrViewData
.GetDocShell();
5918 ScDocument
& rDoc
= pDocSh
->GetDocument();
5920 ScRefCellValue aCell
;
5921 bool bFound
= lcl_GetHyperlinkCell(rDoc
, nPosX
, nPosY
, nTab
, aCell
, sURL
);
5927 const ScPatternAttr
* pPattern
= rDoc
.GetPattern( nPosX
, nPosY
, nTab
);
5928 // bForceToTop = sal_False, use the cell's real position
5929 tools::Rectangle aEditRect
= mrViewData
.GetEditArea( eWhich
, nPosX
, nPosY
, this, pPattern
, false );
5930 if (rPos
.Y() < aEditRect
.Top())
5933 // vertical can not (yet) be clicked:
5935 if (pPattern
->GetCellOrientation() != SvxCellOrientation::Standard
)
5938 bool bBreak
= pPattern
->GetItem(ATTR_LINEBREAK
).GetValue() ||
5939 (pPattern
->GetItem( ATTR_HOR_JUSTIFY
).GetValue() == SvxCellHorJustify::Block
);
5940 SvxCellHorJustify eHorJust
= pPattern
->GetItem(ATTR_HOR_JUSTIFY
).GetValue();
5944 std::shared_ptr
<ScFieldEditEngine
> pEngine
= createEditEngine(pDocSh
, *pPattern
);
5946 MapMode aEditMode
= mrViewData
.GetLogicMode(eWhich
); // without draw scaling
5947 tools::Rectangle aLogicEdit
= PixelToLogic( aEditRect
, aEditMode
);
5948 tools::Long nThisColLogic
= aLogicEdit
.Right() - aLogicEdit
.Left() + 1;
5949 Size
aPaperSize( 1000000, 1000000 );
5950 if (aCell
.getType() == CELLTYPE_FORMULA
)
5952 tools::Long nSizeX
= 0;
5953 tools::Long nSizeY
= 0;
5954 mrViewData
.GetMergeSizePixel( nPosX
, nPosY
, nSizeX
, nSizeY
);
5955 aPaperSize
= Size(nSizeX
, nSizeY
);
5956 aPaperSize
= PixelToLogic(aPaperSize
);
5960 aPaperSize
.setWidth( nThisColLogic
);
5961 pEngine
->SetPaperSize( aPaperSize
);
5963 lcl_SetEngineTextKeepingDefaults(pEngine
, rDoc
, aCell
, sURL
);
5965 tools::Long nStartX
= aLogicEdit
.Left();
5967 tools::Long nTextWidth
= pEngine
->CalcTextWidth();
5968 tools::Long nTextHeight
= pEngine
->GetTextHeight();
5969 if ( nTextWidth
< nThisColLogic
)
5971 if (eHorJust
== SvxCellHorJustify::Right
)
5972 nStartX
+= nThisColLogic
- nTextWidth
;
5973 else if (eHorJust
== SvxCellHorJustify::Center
)
5974 nStartX
+= (nThisColLogic
- nTextWidth
) / 2;
5977 aLogicEdit
.SetLeft( nStartX
);
5979 aLogicEdit
.SetRight( nStartX
+ nTextWidth
);
5981 // There is one glitch when dealing with a hyperlink cell and
5982 // the cell content is NUMERIC. This defaults to right aligned and
5983 // we need to adjust accordingly.
5984 if (aCell
.hasNumeric() && eHorJust
== SvxCellHorJustify::Standard
)
5986 aLogicEdit
.SetRight( aLogicEdit
.Left() + nThisColLogic
- 1 );
5987 aLogicEdit
.SetLeft( aLogicEdit
.Right() - nTextWidth
);
5989 aLogicEdit
.SetBottom( aLogicEdit
.Top() + nTextHeight
);
5991 Point aLogicClick
= PixelToLogic(rPos
,aEditMode
);
5992 if ( aLogicEdit
.Contains(aLogicClick
) )
5994 EditView
aTempView(pEngine
.get(), this);
5995 aTempView
.SetOutputArea( aLogicEdit
);
5998 if (comphelper::LibreOfficeKit::isActive())
6000 bRet
= extractURLInfo(aTempView
.GetField(aLogicClick
), pName
, pUrl
, pTarget
);
6004 MapMode aOld
= GetMapMode();
6005 SetMapMode(aEditMode
); // no return anymore
6006 bRet
= extractURLInfo(aTempView
.GetFieldUnderMousePointer(), pName
, pUrl
, pTarget
);
6014 bool ScGridWindow::HasScenarioButton( const Point
& rPosPixel
, ScRange
& rScenRange
)
6016 ScDocument
& rDoc
= mrViewData
.GetDocument();
6017 SCTAB nTab
= mrViewData
.GetTabNo();
6018 SCTAB nTabCount
= rDoc
.GetTableCount();
6019 if ( nTab
+1<nTabCount
&& rDoc
.IsScenario(nTab
+1) && !rDoc
.IsScenario(nTab
) )
6021 bool bLayoutRTL
= rDoc
.IsLayoutRTL( nTab
);
6023 Size aButSize
= mrViewData
.GetScenButSize();
6024 tools::Long nBWidth
= aButSize
.Width();
6026 return false; // No Button drawn yet -> there is none
6027 tools::Long nBHeight
= aButSize
.Height();
6028 tools::Long nHSpace
= static_cast<tools::Long
>( SC_SCENARIO_HSPACE
* mrViewData
.GetPPTX() );
6030 //! cache the Ranges in Table!!!!
6032 ScMarkData
aMarks(rDoc
.GetSheetLimits());
6033 for (SCTAB i
=nTab
+1; i
<nTabCount
&& rDoc
.IsScenario(i
); i
++)
6034 rDoc
.MarkScenario( i
, nTab
, aMarks
, false, ScScenarioFlags::ShowFrame
);
6035 ScRangeList aRanges
;
6036 aMarks
.FillRangeListWithMarks( &aRanges
, false );
6038 size_t nRangeCount
= aRanges
.size();
6039 for (size_t j
=0; j
< nRangeCount
; ++j
)
6041 ScRange aRange
= aRanges
[j
];
6042 // Always extend scenario frame to merged cells where no new non-covered cells
6044 rDoc
.ExtendTotalMerge( aRange
);
6046 bool bTextBelow
= ( aRange
.aStart
.Row() == 0 );
6051 aButtonPos
= mrViewData
.GetScrPos( aRange
.aEnd
.Col()+1, aRange
.aEnd
.Row()+1,
6056 aButtonPos
= mrViewData
.GetScrPos( aRange
.aEnd
.Col()+1, aRange
.aStart
.Row(),
6058 aButtonPos
.AdjustY( -nBHeight
);
6061 aButtonPos
.AdjustX( -(nHSpace
- 1) );
6063 aButtonPos
.AdjustX( -(nBWidth
- nHSpace
) ); // same for top or bottom
6065 tools::Rectangle
aButRect( aButtonPos
, Size(nBWidth
,nBHeight
) );
6066 if ( aButRect
.Contains( rPosPixel
) )
6068 rScenRange
= aRange
;
6077 void ScGridWindow::DrawLayerCreated()
6079 SetMapMode( GetDrawMapMode() );
6081 // initially create overlay objects
6082 ImpCreateOverlayObjects();
6085 void ScGridWindow::SetAutoSpellContext( const std::shared_ptr
<sc::SpellCheckContext
> &ctx
)
6087 mpSpellCheckCxt
= ctx
;
6090 void ScGridWindow::ResetAutoSpell()
6092 if (mpSpellCheckCxt
)
6093 mpSpellCheckCxt
->reset();
6096 void ScGridWindow::ResetAutoSpellForContentChange()
6098 if (mpSpellCheckCxt
)
6099 mpSpellCheckCxt
->resetForContentChange();
6102 void ScGridWindow::SetAutoSpellData( SCCOL nPosX
, SCROW nPosY
, const std::vector
<editeng::MisspellRanges
>* pRanges
)
6104 if (!mpSpellCheckCxt
)
6107 mpSpellCheckCxt
->setMisspellRanges(nPosX
, nPosY
, pRanges
);
6110 const std::vector
<editeng::MisspellRanges
>* ScGridWindow::GetAutoSpellData( SCCOL nPosX
, SCROW nPosY
)
6112 if (!mpSpellCheckCxt
)
6115 if (!maVisibleRange
.isInside(nPosX
, nPosY
))
6118 return mpSpellCheckCxt
->getMisspellRanges(nPosX
, nPosY
);
6121 bool ScGridWindow::InsideVisibleRange( SCCOL nPosX
, SCROW nPosY
)
6123 return maVisibleRange
.isInside(nPosX
, nPosY
);
6126 OString
ScGridWindow::getCellCursor() const
6128 // GridWindow stores a shown cell cursor in mpOOCursors, hence
6129 // we can use that to determine whether we would want to be showing
6130 // one (client-side) for tiled rendering too.
6132 return "EMPTY"_ostr
;
6134 if (comphelper::LibreOfficeKit::isCompatFlagSet(
6135 comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs
))
6136 return mrViewData
.describeCellCursorInPrintTwips();
6138 return mrViewData
.describeCellCursor();
6141 void ScGridWindow::notifyKitCellCursor() const
6143 ScTabViewShell
* pViewShell
= mrViewData
.GetViewShell();
6145 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_CELL_CURSOR
, getCellCursor());
6146 if (bListValButton
&& aListValPos
== mrViewData
.GetCurPos())
6147 updateLOKValListButton(true, aListValPos
);
6148 std::vector
<tools::Rectangle
> aRects
;
6149 GetSelectionRects(aRects
);
6150 if (aRects
.empty() || !mrViewData
.IsActive())
6152 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION
, ""_ostr
);
6153 SfxLokHelper::notifyOtherViews(pViewShell
, LOK_CALLBACK_TEXT_VIEW_SELECTION
, "selection", "EMPTY"_ostr
);
6157 void ScGridWindow::notifyKitCellViewCursor(const SfxViewShell
* pForShell
) const
6159 ScTabViewShell
* pViewShell
= mrViewData
.GetViewShell();
6161 if (pViewShell
->GetDocId() != pForShell
->GetDocId())
6164 OString
aCursor("EMPTY"_ostr
);
6165 if (mpOOCursors
) // cf. getCellCursor above
6167 auto pForTabView
= dynamic_cast<const ScTabViewShell
*>(pForShell
);
6171 if (comphelper::LibreOfficeKit::isCompatFlagSet(
6172 comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs
))
6173 aCursor
= mrViewData
.describeCellCursorInPrintTwips();
6175 aCursor
= pForTabView
->GetViewData().describeCellCursorAt(
6176 mrViewData
.GetCurX(), mrViewData
.GetCurY()); // our position.
6178 SfxLokHelper::notifyOtherView(pViewShell
, pForShell
, LOK_CALLBACK_CELL_VIEW_CURSOR
, "rectangle", aCursor
);
6181 // Send our cursor details to a view described by @pForShell, or all views
6182 // if @pForShell is null. In each case send the current view a cell-cursor
6183 // event, and others a cell_view_cursor event.
6185 // NB. we need to re-construct the cursor details for each other view in their
6186 // own zoomed co-ordinate system (but not in scPrintTwipsMsgs mode).
6187 void ScGridWindow::updateKitCellCursor(const SfxViewShell
* pForShell
) const
6189 if (comphelper::LibreOfficeKit::isCompatFlagSet(
6190 comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs
))
6192 ScTabViewShell
* pViewShell
= mrViewData
.GetViewShell();
6193 // Generate the cursor info string just once and directly send to all.
6194 // Calling notifyKitCellViewCursor() would regenerate the
6195 // cursor-string unnecessarily.
6196 OString aCursor
= getCellCursor();
6200 SfxLokHelper::notifyOtherView(pViewShell
, pForShell
,
6201 LOK_CALLBACK_CELL_VIEW_CURSOR
, "rectangle", aCursor
);
6205 notifyKitCellCursor();
6206 SfxLokHelper::notifyOtherViews(pViewShell
,
6207 LOK_CALLBACK_CELL_VIEW_CURSOR
, "rectangle", aCursor
);
6215 for (SfxViewShell
* it
= SfxViewShell::GetFirst(); it
;
6216 it
= SfxViewShell::GetNext(*it
))
6217 updateKitCellCursor(it
);
6221 if (pForShell
== mrViewData
.GetViewShell())
6222 notifyKitCellCursor();
6224 notifyKitCellViewCursor(pForShell
);
6227 void ScGridWindow::updateKitOtherCursors() const
6229 for (SfxViewShell
* it
= SfxViewShell::GetFirst(); it
;
6230 it
= SfxViewShell::GetNext(*it
))
6232 auto pOther
= dynamic_cast<const ScTabViewShell
*>(it
);
6235 const ScGridWindow
*pGrid
= pOther
->GetViewData().GetActiveWin();
6238 notifyKitCellCursor();
6240 pGrid
->notifyKitCellViewCursor(mrViewData
.GetViewShell());
6244 void ScGridWindow::CursorChanged()
6246 // here the created OverlayObjects may be transformed in later versions. For
6247 // now, just re-create them
6249 UpdateCursorOverlay();
6250 UpdateAutoFillOverlay();
6251 UpdateSparklineGroupOverlay();
6254 void ScGridWindow::ImpCreateOverlayObjects()
6256 UpdateHighlightOverlay();
6257 UpdateSelectionOverlay();
6258 UpdateCursorOverlay();
6259 UpdateAutoFillOverlay();
6260 UpdateCopySourceOverlay();
6261 UpdateDragRectOverlay();
6262 UpdateHeaderOverlay();
6263 UpdateShrinkOverlay();
6264 UpdateSparklineGroupOverlay();
6267 void ScGridWindow::ImpDestroyOverlayObjects()
6269 DeleteCursorOverlay();
6270 DeleteCopySourceOverlay();
6271 DeleteSelectionOverlay();
6272 mpOOHighlight
.reset(); // DeleteHighlightOverlay
6273 DeleteAutoFillOverlay();
6274 DeleteDragRectOverlay();
6275 DeleteHeaderOverlay();
6276 DeleteShrinkOverlay();
6277 DeleteSparklineGroupOverlay();
6280 void ScGridWindow::UpdateAllOverlays()
6282 // delete and re-allocate all overlay objects
6284 ImpDestroyOverlayObjects();
6285 ImpCreateOverlayObjects();
6288 void ScGridWindow::DeleteCursorOverlay()
6290 if (comphelper::LibreOfficeKit::isActive() && mrViewData
.HasEditView(eWhich
))
6292 ScTabViewShell
* pViewShell
= mrViewData
.GetViewShell();
6293 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_CELL_CURSOR
, "EMPTY"_ostr
);
6294 SfxLokHelper::notifyOtherViews(pViewShell
, LOK_CALLBACK_CELL_VIEW_CURSOR
, "rectangle", "EMPTY"_ostr
);
6295 mpOOCursors
.reset();
6298 void ScGridWindow::DeleteCopySourceOverlay()
6300 mpOOSelectionBorder
.reset();
6303 void ScGridWindow::UpdateCopySourceOverlay()
6305 const MapMode aDrawMode
= GetDrawMapMode();
6306 const MapMode aOldMode
= GetMapMode();
6307 comphelper::ScopeGuard
aMapModeGuard(
6308 [&aOldMode
, &aDrawMode
, this] {
6309 if (aOldMode
!= aDrawMode
)
6310 SetMapMode(aOldMode
);
6313 if (aOldMode
!= aDrawMode
)
6314 SetMapMode(aDrawMode
);
6316 DeleteCopySourceOverlay();
6318 if (comphelper::LibreOfficeKit::isActive())
6320 if (!mrViewData
.ShowPasteSource())
6322 if (!ScModule::get()->GetInputOptions().GetEnterPasteMode())
6324 rtl::Reference
<sdr::overlay::OverlayManager
> xOverlayManager
= getOverlayManager();
6325 if (!xOverlayManager
.is())
6327 const ScTransferObj
* pTransObj
= ScTransferObj::GetOwnClipboard(ScTabViewShell::GetClipData(mrViewData
.GetActiveWin()));
6330 ScDocument
* pClipDoc
= pTransObj
->GetDocument();
6334 SCTAB nCurTab
= mrViewData
.GetCurPos().Tab();
6336 ScClipParam
& rClipParam
= pClipDoc
->GetClipParam();
6337 mpOOSelectionBorder
.reset(new sdr::overlay::OverlayObjectList
);
6338 for ( size_t i
= 0; i
< rClipParam
.maRanges
.size(); ++i
)
6340 ScRange
const & r
= rClipParam
.maRanges
[i
];
6341 if (r
.aStart
.Tab() != nCurTab
)
6344 SCCOL nClipStartX
= r
.aStart
.Col();
6345 SCROW nClipStartY
= r
.aStart
.Row();
6346 SCCOL nClipEndX
= r
.aEnd
.Col();
6347 SCROW nClipEndY
= r
.aEnd
.Row();
6349 Point aClipStartScrPos
= mrViewData
.GetScrPos( nClipStartX
, nClipStartY
, eWhich
);
6350 Point aClipEndScrPos
= mrViewData
.GetScrPos( nClipEndX
+ 1, nClipEndY
+ 1, eWhich
);
6351 aClipStartScrPos
-= Point(1, 1);
6352 tools::Long nSizeXPix
= aClipEndScrPos
.X() - aClipStartScrPos
.X();
6353 tools::Long nSizeYPix
= aClipEndScrPos
.Y() - aClipStartScrPos
.Y();
6355 tools::Rectangle
aRect( aClipStartScrPos
, Size(nSizeXPix
, nSizeYPix
) );
6357 Color aHighlight
= GetSettings().GetStyleSettings().GetHighlightColor();
6359 tools::Rectangle aLogic
= PixelToLogic(aRect
, aDrawMode
);
6360 ::basegfx::B2DRange aRange
= vcl::unotools::b2DRectangleFromRectangle(aLogic
);
6361 std::unique_ptr
<ScOverlayDashedBorder
> pDashedBorder(new ScOverlayDashedBorder(aRange
, aHighlight
));
6362 xOverlayManager
->add(*pDashedBorder
);
6363 mpOOSelectionBorder
->append(std::move(pDashedBorder
));
6367 static std::vector
<tools::Rectangle
> convertPixelToLogical(
6368 const ScViewData
& rViewData
,
6369 const std::vector
<tools::Rectangle
>& rRectangles
,
6370 tools::Rectangle
&rBoundingBox
)
6372 std::vector
<tools::Rectangle
> aLogicRects
;
6374 double nPPTX
= rViewData
.GetPPTX();
6375 double nPPTY
= rViewData
.GetPPTY();
6377 for (const auto& rRectangle
: rRectangles
)
6379 // We explicitly create a copy, since we need to expand
6380 // the rectangle before coordinate conversion
6381 tools::Rectangle
aRectangle(rRectangle
);
6382 aRectangle
.AdjustRight(1 );
6383 aRectangle
.AdjustBottom(1 );
6385 tools::Rectangle
aRect(aRectangle
.Left() / nPPTX
, aRectangle
.Top() / nPPTY
,
6386 aRectangle
.Right() / nPPTX
, aRectangle
.Bottom() / nPPTY
);
6388 rBoundingBox
.Union(aRect
);
6389 aLogicRects
.push_back(aRect
);
6394 static OString
rectanglesToString(const std::vector
<tools::Rectangle
> &rLogicRects
)
6397 OStringBuffer aRects
;
6398 for (const auto &rRect
: rLogicRects
)
6401 aRects
.append("; ");
6403 aRects
.append(rRect
.toString());
6405 return aRects
.makeStringAndClear();
6409 * Turn the selection ranges rRectangles into the LibreOfficeKit selection, and send to other views.
6411 * @param pLogicRects - if set then don't invoke the callback, just collect the rectangles in the pointed vector.
6413 void ScGridWindow::UpdateKitSelection(const std::vector
<tools::Rectangle
>& rRectangles
, std::vector
<tools::Rectangle
>* pLogicRects
)
6415 if (!comphelper::LibreOfficeKit::isActive())
6418 // If this is true, rRectangles should already in print twips.
6419 // If false, rRectangles are in pixels.
6420 bool bInPrintTwips
= comphelper::LibreOfficeKit::isCompatFlagSet(
6421 comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs
);
6423 tools::Rectangle aBoundingBox
;
6424 std::vector
<tools::Rectangle
> aConvertedRects
;
6427 std::for_each(rRectangles
.begin(), rRectangles
.end(),
6428 [&aBoundingBox
](const tools::Rectangle
& rRect
) { aBoundingBox
.Union(rRect
); });
6430 aConvertedRects
= convertPixelToLogical(mrViewData
, rRectangles
, aBoundingBox
);
6432 const std::vector
<tools::Rectangle
>& rLogicRects
= bInPrintTwips
? rRectangles
: aConvertedRects
;
6435 *pLogicRects
= rLogicRects
;
6439 ScTabViewShell
* pViewShell
= mrViewData
.GetViewShell();
6440 pViewShell
->UpdateInputHandler();
6441 OString sBoundingBoxString
= "EMPTY"_ostr
;
6442 if (!aBoundingBox
.IsEmpty())
6443 sBoundingBoxString
= aBoundingBox
.toString();
6444 OString aRectListString
= rectanglesToString(rLogicRects
);
6445 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_CELL_SELECTION_AREA
, sBoundingBoxString
);
6446 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION
, aRectListString
);
6450 SfxLokHelper::notifyOtherViews(pViewShell
, LOK_CALLBACK_TEXT_VIEW_SELECTION
,
6451 "selection", aRectListString
);
6455 for (SfxViewShell
* it
= SfxViewShell::GetFirst(); it
;
6456 it
= SfxViewShell::GetNext(*it
))
6458 if (it
== pViewShell
)
6460 auto pOther
= dynamic_cast<const ScTabViewShell
*>(it
);
6464 const ScGridWindow
*pGrid
= pOther
->GetViewData().GetActiveWin();
6467 // Fetch pixels & convert for each view separately.
6468 tools::Rectangle aDummyBBox
;
6469 std::vector
<tools::Rectangle
> aPixelRects
;
6470 pGrid
->GetPixelRectsFor(mrViewData
.GetMarkData() /* ours */, aPixelRects
);
6471 auto aOtherLogicRects
= convertPixelToLogical(pOther
->GetViewData(), aPixelRects
, aDummyBBox
);
6472 SfxLokHelper::notifyOtherView(pViewShell
, pOther
, LOK_CALLBACK_TEXT_VIEW_SELECTION
,
6473 "selection", rectanglesToString(aOtherLogicRects
));
6478 * Fetch the selection ranges for other views into the LibreOfficeKit selection,
6479 * map them into our view co-ordinates and send to our view.
6481 void ScGridWindow::updateOtherKitSelections() const
6483 ScTabViewShell
* pViewShell
= mrViewData
.GetViewShell();
6484 bool bInPrintTwips
= comphelper::LibreOfficeKit::isCompatFlagSet(
6485 comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs
);
6487 for (SfxViewShell
* it
= SfxViewShell::GetFirst(); it
;
6488 it
= SfxViewShell::GetNext(*it
))
6490 auto pOther
= dynamic_cast<const ScTabViewShell
*>(it
);
6494 // Fetch pixels & convert for each view separately.
6495 tools::Rectangle aBoundingBox
;
6496 std::vector
<tools::Rectangle
> aRects
;
6497 OString aRectsString
;
6498 GetRectsAnyFor(pOther
->GetViewData().GetMarkData() /* theirs */, aRects
, bInPrintTwips
);
6501 std::for_each(aRects
.begin(), aRects
.end(),
6502 [&aBoundingBox
](const tools::Rectangle
& rRect
) { aBoundingBox
.Union(rRect
); });
6503 aRectsString
= rectanglesToString(aRects
);
6506 aRectsString
= rectanglesToString(
6507 convertPixelToLogical(pViewShell
->GetViewData(), aRects
, aBoundingBox
));
6509 if (it
== pViewShell
)
6511 OString sBoundingBoxString
= "EMPTY"_ostr
;
6512 if (!aBoundingBox
.IsEmpty())
6513 sBoundingBoxString
= aBoundingBox
.toString();
6515 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_CELL_SELECTION_AREA
, sBoundingBoxString
);
6516 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION
, aRectsString
);
6519 SfxLokHelper::notifyOtherView(it
, pViewShell
, LOK_CALLBACK_TEXT_VIEW_SELECTION
,
6520 "selection", aRectsString
);
6527 void updateLibreOfficeKitAutoFill(const ScViewData
& rViewData
, tools::Rectangle
const & rRectangle
)
6529 if (!comphelper::LibreOfficeKit::isActive())
6532 double nPPTX
= rViewData
.GetPPTX();
6533 double nPPTY
= rViewData
.GetPPTY();
6535 OString sRectangleString
= "EMPTY"_ostr
;
6536 if (!rRectangle
.IsEmpty())
6538 // selection start handle
6539 tools::Rectangle
aLogicRectangle(
6540 rRectangle
.Left() / nPPTX
, rRectangle
.Top() / nPPTY
,
6541 rRectangle
.Right() / nPPTX
, rRectangle
.Bottom() / nPPTY
);
6542 sRectangleString
= aLogicRectangle
.toString();
6545 ScTabViewShell
* pViewShell
= rViewData
.GetViewShell();
6546 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_CELL_AUTO_FILL_AREA
, sRectangleString
);
6549 } //end anonymous namespace
6551 void ScGridWindow::UpdateCursorOverlay()
6553 ScDocument
& rDoc
= mrViewData
.GetDocument();
6555 const MapMode aDrawMode
= GetDrawMapMode();
6556 const MapMode aOldMode
= GetMapMode();
6557 comphelper::ScopeGuard
aMapModeGuard(
6558 [&aOldMode
, &aDrawMode
, this] {
6559 if (aOldMode
!= aDrawMode
)
6560 SetMapMode(aOldMode
);
6563 if (aOldMode
!= aDrawMode
)
6564 SetMapMode(aDrawMode
);
6566 // Existing OverlayObjects may be transformed in later versions.
6567 // For now, just re-create them.
6569 DeleteCursorOverlay();
6571 std::vector
<tools::Rectangle
> aPixelRects
;
6573 // determine the cursor rectangles in pixels (moved from ScGridWindow::DrawCursor)
6575 SCTAB nTab
= mrViewData
.GetTabNo();
6576 SCCOL nX
= mrViewData
.GetCurX();
6577 SCROW nY
= mrViewData
.GetCurY();
6579 const ScPatternAttr
* pPattern
= rDoc
.GetPattern(nX
,nY
,nTab
);
6581 if (!comphelper::LibreOfficeKit::isActive() && !maVisibleRange
.isInside(nX
, nY
))
6583 if (maVisibleRange
.mnCol2
< nX
|| maVisibleRange
.mnRow2
< nY
)
6584 return; // no further check needed, nothing visible
6586 // fdo#87382 Also display the cell cursor for the visible part of
6587 // merged cells if the view position is part of merged cells.
6588 const ScMergeAttr
& rMerge
= pPattern
->GetItem(ATTR_MERGE
);
6589 if (rMerge
.GetColMerge() <= 1 && rMerge
.GetRowMerge() <= 1)
6590 return; // not merged and invisible
6592 SCCOL nX2
= nX
+ rMerge
.GetColMerge() - 1;
6593 SCROW nY2
= nY
+ rMerge
.GetRowMerge() - 1;
6594 // Check if the middle or tail of the merged range is visible.
6595 if (maVisibleRange
.mnCol1
> nX2
|| maVisibleRange
.mnRow1
> nY2
)
6596 return; // no visible part
6599 // don't show the cursor in overlapped cells
6600 const ScMergeFlagAttr
& rMergeFlag
= pPattern
->GetItem(ATTR_MERGE_FLAG
);
6601 bool bOverlapped
= rMergeFlag
.IsOverlapped();
6603 // left or above of the screen?
6604 bool bVis
= comphelper::LibreOfficeKit::isActive() || ( nX
>=mrViewData
.GetPosX(eHWhich
) && nY
>=mrViewData
.GetPosY(eVWhich
) );
6609 const ScMergeAttr
& rMerge
= pPattern
->GetItem(ATTR_MERGE
);
6610 if (rMerge
.GetColMerge() > 1)
6611 nEndX
+= rMerge
.GetColMerge()-1;
6612 if (rMerge
.GetRowMerge() > 1)
6613 nEndY
+= rMerge
.GetRowMerge()-1;
6614 bVis
= ( nEndX
>=mrViewData
.GetPosX(eHWhich
) && nEndY
>=mrViewData
.GetPosY(eVWhich
) );
6617 if ( bVis
&& !bOverlapped
&& !mrViewData
.HasEditView(eWhich
) && mrViewData
.IsActive() )
6619 Point aScrPos
= mrViewData
.GetScrPos( nX
, nY
, eWhich
, true );
6620 bool bLayoutRTL
= rDoc
.IsLayoutRTL( nTab
);
6622 // completely right of/below the screen?
6623 // (test with logical start position in aScrPos)
6626 bMaybeVisible
= ( aScrPos
.X() >= -2 && aScrPos
.Y() >= -2 );
6629 Size aOutSize
= GetOutputSizePixel();
6630 bMaybeVisible
= ( aScrPos
.X() <= aOutSize
.Width() + 2 && aScrPos
.Y() <= aOutSize
.Height() + 2 );
6633 // in the tiled rendering case, don't limit to the screen size
6634 if (bMaybeVisible
|| comphelper::LibreOfficeKit::isActive())
6636 tools::Long nSizeXPix
;
6637 tools::Long nSizeYPix
;
6638 mrViewData
.GetMergeSizePixel( nX
, nY
, nSizeXPix
, nSizeYPix
);
6641 aScrPos
.AdjustX( -(nSizeXPix
- 2) ); // move instead of mirroring
6643 // show the cursor as 4 (thin) rectangles
6644 tools::Rectangle
aRect(aScrPos
, Size(nSizeXPix
, nSizeYPix
));
6646 float fScaleFactor
= GetDPIScaleFactor();
6648 tools::Long aCursorWidth
= 1 * fScaleFactor
;
6650 tools::Rectangle aLeft
= aRect
;
6651 aLeft
.AdjustTop( -aCursorWidth
);
6652 aLeft
.AdjustBottom(aCursorWidth
);
6653 aLeft
.SetRight( aLeft
.Left() );
6654 aLeft
.AdjustLeft( -aCursorWidth
);
6656 tools::Rectangle aRight
= aRect
;
6657 aRight
.AdjustTop( -aCursorWidth
);
6658 aRight
.AdjustBottom(aCursorWidth
);
6659 aRight
.SetLeft( aRight
.Right() );
6660 aRight
.AdjustRight(aCursorWidth
);
6662 tools::Rectangle aTop
= aRect
;
6663 aTop
.SetBottom( aTop
.Top() );
6664 aTop
.AdjustTop( -aCursorWidth
);
6666 tools::Rectangle aBottom
= aRect
;
6667 aBottom
.SetTop( aBottom
.Bottom() );
6668 aBottom
.AdjustBottom(aCursorWidth
);
6670 aPixelRects
.push_back(aLeft
);
6671 aPixelRects
.push_back(aRight
);
6672 aPixelRects
.push_back(aTop
);
6673 aPixelRects
.push_back(aBottom
);
6677 if ( !aPixelRects
.empty() )
6679 if (comphelper::LibreOfficeKit::isActive())
6681 mpOOCursors
.reset(new sdr::overlay::OverlayObjectList
);
6682 updateKitCellCursor(nullptr);
6686 // #i70788# get the OverlayManager safely
6687 rtl::Reference
<sdr::overlay::OverlayManager
> xOverlayManager
= getOverlayManager();
6689 if (xOverlayManager
.is())
6691 ScModule
* mod
= ScModule::get();
6692 Color aCursorColor
= mod
->GetColorConfig().GetColorValue(svtools::CALCCELLFOCUS
).nColor
;
6693 if (mrViewData
.GetActivePart() != eWhich
)
6694 // non-active pane uses a different color.
6695 aCursorColor
= mod
->GetColorConfig().GetColorValue(svtools::CALCPAGEBREAKAUTOMATIC
).nColor
;
6696 std::vector
< basegfx::B2DRange
> aRanges
;
6697 const basegfx::B2DHomMatrix
aTransform(GetOutDev()->GetInverseViewTransformation());
6699 // tdf#143733, tdf#145080 - improve border visibility
6700 // constants picked for maximum consistency at 100% and adequate response on zoom
6701 // line width = 1.5 at 100% (0.75 left +/- 0.75 right), 50% = 1, 200% = 1.25, 400% = 2.25
6702 const double fCurZoom(mrViewData
.GetZoomX());
6703 const double fMinSize
= 0.25 * GetDPIScaleFactor();
6704 const double fAdjust(fMinSize
+ mrViewData
.GetZoomX() * 0.5);
6705 int nAdjustPixel(o3tl::convert(fAdjust
, o3tl::Length::pt
, o3tl::Length::px
));
6706 // If zoom level is 50% or greater the rectangles must be at least 1 pixel thick
6707 if (fCurZoom
>= 0.5)
6708 nAdjustPixel
= std::max(1, nAdjustPixel
);
6710 // Below each rectangle is adjusted so that they have thickness of nAdjustPixel
6712 basegfx::B2DRange
aRBLeft(aPixelRects
[0].Left() - nAdjustPixel
, aPixelRects
[0].Top() - nAdjustPixel
,
6713 aPixelRects
[0].Right(), aPixelRects
[0].Bottom() + nAdjustPixel
);
6714 aRBLeft
.transform(aTransform
);
6715 aRanges
.push_back(aRBLeft
);
6717 basegfx::B2DRange
aRBRight(aPixelRects
[1].Left(), aPixelRects
[1].Top() - nAdjustPixel
,
6718 aPixelRects
[1].Right() + nAdjustPixel
, aPixelRects
[1].Bottom() + nAdjustPixel
);
6719 aRBRight
.transform(aTransform
);
6720 aRanges
.push_back(aRBRight
);
6722 basegfx::B2DRange
aRBTop(aPixelRects
[2].Left() - nAdjustPixel
, aPixelRects
[2].Top() - nAdjustPixel
,
6723 aPixelRects
[2].Right() + nAdjustPixel
, aPixelRects
[2].Bottom());
6724 aRBTop
.transform(aTransform
);
6725 aRanges
.push_back(aRBTop
);
6727 basegfx::B2DRange
aRBBottom(aPixelRects
[3].Left() - nAdjustPixel
, aPixelRects
[3].Top(),
6728 aPixelRects
[3].Right() + nAdjustPixel
, aPixelRects
[3].Bottom() + nAdjustPixel
);
6729 aRBBottom
.transform(aTransform
);
6730 aRanges
.push_back(aRBBottom
);
6732 std::unique_ptr
<sdr::overlay::OverlayObject
> pOverlay(new sdr::overlay::OverlaySelection(
6733 sdr::overlay::OverlayType::Solid
,
6738 // Internal white contrast rectangle
6739 std::vector
< basegfx::B2DRange
> aRangesInternal
;
6740 basegfx::B2DRange
aRBInternal(aPixelRects
[0].Right(), aPixelRects
[2].Bottom(),
6741 aPixelRects
[1].Left() - 1, aPixelRects
[3].Top() - 1);
6742 aRBInternal
.transform(aTransform
);
6743 aRangesInternal
.push_back(aRBInternal
);
6745 std::unique_ptr
<sdr::overlay::OverlayObject
> pOverlayInternal(new sdr::overlay::OverlaySelection(
6746 sdr::overlay::OverlayType::NoFill
,
6748 std::move(aRangesInternal
),
6751 xOverlayManager
->add(*pOverlay
);
6752 xOverlayManager
->add(*pOverlayInternal
);
6753 mpOOCursors
.reset(new sdr::overlay::OverlayObjectList
);
6754 mpOOCursors
->append(std::move(pOverlay
));
6755 mpOOCursors
->append(std::move(pOverlayInternal
));
6761 void ScGridWindow::GetCellSelection(std::vector
<tools::Rectangle
>& rLogicRects
)
6763 std::vector
<tools::Rectangle
> aRects
;
6764 if (comphelper::LibreOfficeKit::isActive() &&
6765 comphelper::LibreOfficeKit::isCompatFlagSet(
6766 comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs
))
6767 GetSelectionRectsPrintTwips(aRects
);
6769 GetSelectionRects(aRects
);
6770 UpdateKitSelection(aRects
, &rLogicRects
);
6773 void ScGridWindow::DeleteSelectionOverlay()
6775 mpOOSelection
.reset();
6778 void ScGridWindow::UpdateSelectionOverlay()
6780 const MapMode aDrawMode
= GetDrawMapMode();
6781 const MapMode aOldMode
= GetMapMode();
6782 comphelper::ScopeGuard
aMapModeGuard(
6783 [&aOldMode
, &aDrawMode
, this] {
6784 if (aOldMode
!= aDrawMode
)
6785 SetMapMode(aOldMode
);
6788 if (aOldMode
!= aDrawMode
)
6789 SetMapMode(aDrawMode
);
6791 DeleteSelectionOverlay();
6792 std::vector
<tools::Rectangle
> aRects
;
6793 if (comphelper::LibreOfficeKit::isActive() &&
6794 comphelper::LibreOfficeKit::isCompatFlagSet(
6795 comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs
))
6796 GetSelectionRectsPrintTwips(aRects
);
6798 GetSelectionRects(aRects
);
6800 if (!aRects
.empty() && mrViewData
.IsActive())
6802 // #i70788# get the OverlayManager safely
6803 rtl::Reference
<sdr::overlay::OverlayManager
> xOverlayManager
= getOverlayManager();
6804 if (comphelper::LibreOfficeKit::isActive())
6806 // notify the LibreOfficeKit too
6807 UpdateKitSelection(aRects
);
6809 else if (xOverlayManager
.is())
6811 std::vector
< basegfx::B2DRange
> aRanges
;
6812 const basegfx::B2DHomMatrix
aTransform(GetOutDev()->GetInverseViewTransformation());
6813 ScDocument
& rDoc
= mrViewData
.GetDocument();
6814 SCTAB nTab
= mrViewData
.GetTabNo();
6815 bool bLayoutRTL
= rDoc
.IsLayoutRTL( nTab
);
6817 for(const tools::Rectangle
& rRA
: aRects
)
6821 basegfx::B2DRange
aRB(rRA
.Left(), rRA
.Top() - 1, rRA
.Right() + 1, rRA
.Bottom());
6822 aRB
.transform(aTransform
);
6823 aRanges
.push_back(aRB
);
6827 basegfx::B2DRange
aRB(rRA
.Left() - 1, rRA
.Top() - 1, rRA
.Right(), rRA
.Bottom());
6828 aRB
.transform(aTransform
);
6829 aRanges
.push_back(aRB
);
6833 // get the system's highlight color
6834 const Color
aHighlight(SvtOptionsDrawinglayer::getHilightColor());
6836 std::unique_ptr
<sdr::overlay::OverlayObject
> pOverlay(new sdr::overlay::OverlaySelection(
6837 sdr::overlay::OverlayType::Transparent
,
6842 xOverlayManager
->add(*pOverlay
);
6843 mpOOSelection
.reset(new sdr::overlay::OverlayObjectList
);
6844 mpOOSelection
->append(std::move(pOverlay
));
6849 ScTabViewShell
* pViewShell
= mrViewData
.GetViewShell();
6850 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION
, "EMPTY"_ostr
);
6851 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_CELL_SELECTION_AREA
, "EMPTY"_ostr
);
6852 SfxLokHelper::notifyOtherViews(pViewShell
, LOK_CALLBACK_TEXT_VIEW_SELECTION
, "selection", "EMPTY"_ostr
);
6854 ScInputHandler
* pViewHdl
= ScModule::get()->GetInputHdl(pViewShell
);
6855 if (!pViewHdl
|| !pViewHdl
->IsEditMode())
6857 std::vector
<ReferenceMark
> aReferenceMarks
;
6858 ScInputHandler::SendReferenceMarks(pViewShell
, aReferenceMarks
);
6863 void ScGridWindow::UpdateHighlightOverlay()
6865 mpOOHighlight
.reset(); // DeleteHighlightOverlay
6866 std::vector
<tools::Rectangle
> aRects
;
6867 if (comphelper::LibreOfficeKit::isActive() &&
6868 comphelper::LibreOfficeKit::isCompatFlagSet(
6869 comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs
))
6870 GetRectsAnyFor(mrViewData
.GetHighlightData(), aRects
, true);
6872 GetPixelRectsFor(mrViewData
.GetHighlightData(), aRects
);
6874 if (!aRects
.empty() && mrViewData
.IsActive())
6876 // #i70788# get the OverlayManager safely
6877 if (rtl::Reference
<sdr::overlay::OverlayManager
> xOverlayManager
= getOverlayManager())
6879 std::vector
< basegfx::B2DRange
> aRanges
;
6880 const basegfx::B2DHomMatrix
aTransform(GetOutDev()->GetInverseViewTransformation());
6881 ScDocument
& rDoc
= mrViewData
.GetDocument();
6882 SCTAB nTab
= mrViewData
.GetTabNo();
6883 bool bLayoutRTL
= rDoc
.IsLayoutRTL( nTab
);
6885 for(const tools::Rectangle
& rRA
: aRects
)
6889 basegfx::B2DRange
aRB(rRA
.Left(), rRA
.Top() - 1, rRA
.Right() + 1, rRA
.Bottom());
6890 aRB
.transform(aTransform
);
6891 aRanges
.push_back(aRB
);
6895 basegfx::B2DRange
aRB(rRA
.Left() - 1, rRA
.Top() - 1, rRA
.Right(), rRA
.Bottom());
6896 aRB
.transform(aTransform
);
6897 aRanges
.push_back(aRB
);
6901 ScModule
* mod
= ScModule::get();
6902 const Color aBackgroundColor
= mod
->GetColorConfig().GetColorValue(svtools::DOCCOLOR
).nColor
;
6903 Color aHighlightColor
= mod
->GetColorConfig().GetColorValue(svtools::CALCCELLFOCUS
).nColor
;
6904 aHighlightColor
.Merge(aBackgroundColor
, 100);
6906 std::unique_ptr
<sdr::overlay::OverlayObject
> pOverlay(new sdr::overlay::OverlaySelection(
6907 sdr::overlay::OverlayType::Transparent
,
6912 xOverlayManager
->add(*pOverlay
);
6913 mpOOHighlight
.reset(new sdr::overlay::OverlayObjectList
);
6914 mpOOHighlight
->append(std::move(pOverlay
));
6919 void ScGridWindow::DeleteAutoFillOverlay()
6921 mpOOAutoFill
.reset();
6922 mpAutoFillRect
.reset();
6925 void ScGridWindow::UpdateAutoFillOverlay()
6927 const MapMode aDrawMode
= GetDrawMapMode();
6928 const MapMode aOldMode
= GetMapMode();
6929 comphelper::ScopeGuard
aMapModeGuard(
6930 [&aOldMode
, &aDrawMode
, this] {
6931 if (aOldMode
!= aDrawMode
)
6932 SetMapMode(aOldMode
);
6935 if (aOldMode
!= aDrawMode
)
6936 SetMapMode(aDrawMode
);
6938 DeleteAutoFillOverlay();
6940 // get the AutoFill handle rectangle in pixels
6942 if ( !(bAutoMarkVisible
&& aAutoMarkPos
.Tab() == mrViewData
.GetTabNo() &&
6943 !mrViewData
.HasEditView(eWhich
) && mrViewData
.IsActive()) )
6946 SCCOL nX
= aAutoMarkPos
.Col();
6947 SCROW nY
= aAutoMarkPos
.Row();
6949 if (!maVisibleRange
.isInside(nX
, nY
) && !comphelper::LibreOfficeKit::isActive())
6951 // Autofill mark is not visible. Bail out.
6955 SCTAB nTab
= mrViewData
.GetTabNo();
6956 ScDocument
& rDoc
= mrViewData
.GetDocument();
6957 bool bLayoutRTL
= rDoc
.IsLayoutRTL( nTab
);
6959 // tdf#162006 Ensures the AutoFill handle is visible at any zoom level
6960 // At 100% = Total Size 8 (2px for the external white line; 6px for the handle itself)
6961 const double fScaleFactor(2 + 2 * GetDPIScaleFactor());
6962 const double fZoom(2 + 2 * mrViewData
.GetZoomX());
6963 Size
aFillHandleSize(fScaleFactor
+ fZoom
, fScaleFactor
+ fZoom
);
6965 Point aFillPos
= mrViewData
.GetScrPos( nX
, nY
, eWhich
, true );
6966 tools::Long nSizeXPix
;
6967 tools::Long nSizeYPix
;
6968 mrViewData
.GetMergeSizePixel( nX
, nY
, nSizeXPix
, nSizeYPix
);
6970 // Consider the case of merged cells to determine where to place the AutoFill handle
6971 SCCOL nX2
= mrViewData
.GetCurX();
6972 SCCOL nY2
= mrViewData
.GetCurY();
6973 const ScMergeAttr
* pMerge
= rDoc
.GetAttr(nX2
, nY2
, nTab
, ATTR_MERGE
);
6974 if (pMerge
->GetColMerge() >= 1 || pMerge
->GetRowMerge() >= 1)
6976 nX2
+= pMerge
->GetColMerge() - 1;
6977 nY2
+= pMerge
->GetRowMerge() - 1;
6980 if (bLayoutRTL
&& !comphelper::LibreOfficeKit::isActive())
6981 aFillPos
.AdjustX( -(nSizeXPix
+ (aFillHandleSize
.Width() / 2)) );
6983 aFillPos
.AdjustX(nSizeXPix
- (aFillHandleSize
.Width() / 2) );
6985 aFillPos
.AdjustY(nSizeYPix
);
6986 aFillPos
.AdjustY( -(aFillHandleSize
.Height() / 2) );
6988 tools::Rectangle
aFillRect(aFillPos
, aFillHandleSize
);
6990 // expand rect to increase hit area
6991 mpAutoFillRect
= aFillRect
;
6992 mpAutoFillRect
->expand(fScaleFactor
);
6994 // #i70788# get the OverlayManager safely
6995 rtl::Reference
<sdr::overlay::OverlayManager
> xOverlayManager
= getOverlayManager();
6996 if (comphelper::LibreOfficeKit::isActive()) // notify the LibreOfficeKit
6998 updateLibreOfficeKitAutoFill(mrViewData
, aFillRect
);
7000 else if (xOverlayManager
.is())
7002 const basegfx::B2DHomMatrix
aTransform(GetOutDev()->GetInverseViewTransformation());
7004 // Outer rectangle (always white for contrast)
7005 std::vector
< basegfx::B2DRange
> aRangesOuter
;
7006 basegfx::B2DRange aRBOuter
= vcl::unotools::b2DRectangleFromRectangle(aFillRect
);
7007 aRBOuter
.transform(aTransform
);
7008 aRangesOuter
.push_back(aRBOuter
);
7010 std::unique_ptr
<sdr::overlay::OverlayObject
> pOverlayOuter(new sdr::overlay::OverlaySelection(
7011 sdr::overlay::OverlayType::Solid
,
7013 std::move(aRangesOuter
),
7017 std::vector
< basegfx::B2DRange
> aRangesInner
;
7018 tools::Rectangle
aRectInner(aFillRect
);
7019 aRectInner
.AdjustTop(1);
7020 aRectInner
.AdjustBottom(-1);
7021 aRectInner
.AdjustLeft(1);
7022 aRectInner
.AdjustRight(-1);
7023 basegfx::B2DRange aRBInner
= vcl::unotools::b2DRectangleFromRectangle(aRectInner
);
7024 aRBInner
.transform(aTransform
);
7025 aRangesInner
.push_back(aRBInner
);
7027 ScModule
* mod
= ScModule::get();
7028 Color aHandleColor
= mod
->GetColorConfig().GetColorValue(svtools::CALCCELLFOCUS
).nColor
;
7029 if (mrViewData
.GetActivePart() != eWhich
)
7030 // non-active pane uses a different color.
7031 aHandleColor
= mod
->GetColorConfig().GetColorValue(svtools::CALCPAGEBREAKAUTOMATIC
).nColor
;
7033 std::unique_ptr
<sdr::overlay::OverlayObject
> pOverlayInner(new sdr::overlay::OverlaySelection(
7034 sdr::overlay::OverlayType::Solid
,
7036 std::move(aRangesInner
),
7039 xOverlayManager
->add(*pOverlayOuter
);
7040 xOverlayManager
->add(*pOverlayInner
);
7041 mpOOAutoFill
.reset(new sdr::overlay::OverlayObjectList
);
7042 mpOOAutoFill
->append(std::move(pOverlayOuter
));
7043 mpOOAutoFill
->append(std::move(pOverlayInner
));
7047 void ScGridWindow::DeleteDragRectOverlay()
7049 mpOODragRect
.reset();
7052 void ScGridWindow::UpdateDragRectOverlay()
7054 bool bInPrintTwips
= comphelper::LibreOfficeKit::isCompatFlagSet(
7055 comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs
);
7057 const MapMode aDrawMode
= GetDrawMapMode();
7058 const MapMode aOldMode
= GetMapMode();
7059 comphelper::ScopeGuard
aMapModeGuard(
7060 [&aOldMode
, &aDrawMode
, this] {
7061 if (aOldMode
!= aDrawMode
)
7062 SetMapMode(aOldMode
);
7065 if (aOldMode
!= aDrawMode
)
7066 SetMapMode(aDrawMode
);
7068 DeleteDragRectOverlay();
7070 // get the rectangles in pixels (moved from DrawDragRect)
7072 if ( bDragRect
|| bPagebreakDrawn
)
7074 std::vector
<tools::Rectangle
> aPixelRects
;
7076 SCCOL nX1
= bDragRect
? nDragStartX
: aPagebreakDrag
.aStart
.Col();
7077 SCROW nY1
= bDragRect
? nDragStartY
: aPagebreakDrag
.aStart
.Row();
7078 SCCOL nX2
= bDragRect
? nDragEndX
: aPagebreakDrag
.aEnd
.Col();
7079 SCROW nY2
= bDragRect
? nDragEndY
: aPagebreakDrag
.aEnd
.Row();
7081 SCTAB nTab
= mrViewData
.GetTabNo();
7083 SCCOL nPosX
= mrViewData
.GetPosX(WhichH(eWhich
));
7084 SCROW nPosY
= mrViewData
.GetPosY(WhichV(eWhich
));
7085 if (nX1
< nPosX
) nX1
= nPosX
;
7086 if (nX2
< nPosX
) nX2
= nPosX
;
7087 if (nY1
< nPosY
) nY1
= nPosY
;
7088 if (nY2
< nPosY
) nY2
= nPosY
;
7090 Point
aScrPos(bInPrintTwips
? mrViewData
.GetPrintTwipsPos( nX1
, nY1
)
7091 : mrViewData
.GetScrPos( nX1
, nY1
, eWhich
) );
7093 tools::Long nSizeXPix
=0;
7094 tools::Long nSizeYPix
=0;
7095 ScDocument
& rDoc
= mrViewData
.GetDocument();
7096 double nPPTX
= mrViewData
.GetPPTX();
7097 double nPPTY
= mrViewData
.GetPPTY();
7100 bool bLayoutRTL
= rDoc
.IsLayoutRTL( nTab
);
7101 tools::Long nLayoutSign
= bLayoutRTL
? -1 : 1;
7102 tools::Long nAdjust
= comphelper::LibreOfficeKit::isActive() ? 0 : 2;
7104 if (rDoc
.ValidCol(nX2
) && nX2
>=nX1
)
7105 for (i
=nX1
; i
<=nX2
; i
++)
7107 tools::Long nWidth
= rDoc
.GetColWidth( static_cast<SCCOL
>(i
), nTab
);
7108 nSizeXPix
+= bInPrintTwips
? nWidth
: ScViewData::ToPixel( nWidth
, nPPTX
);
7112 aScrPos
.AdjustX( -nLayoutSign
);
7113 nSizeXPix
+= nAdjust
;
7116 if (rDoc
.ValidRow(nY2
) && nY2
>=nY1
)
7117 for (i
=nY1
; i
<=nY2
; i
++)
7119 tools::Long nHeight
= rDoc
.GetRowHeight( i
, nTab
);
7120 nSizeYPix
+= bInPrintTwips
? nHeight
: ScViewData::ToPixel( nHeight
, nPPTY
);
7124 aScrPos
.AdjustY( -1 );
7125 nSizeYPix
+= nAdjust
;
7128 if (comphelper::LibreOfficeKit::isActive())
7134 aScrPos
.AdjustX( -(nAdjust
* nLayoutSign
) );
7135 aScrPos
.AdjustY( -1 * nAdjust
);
7136 tools::Rectangle
aRect( aScrPos
.X(), aScrPos
.Y(),
7137 aScrPos
.X() + ( nSizeXPix
+ nAdjust
) * nLayoutSign
, aScrPos
.Y() + nSizeYPix
+ nAdjust
);
7140 aRect
.SetLeft( aRect
.Right() ); // end position is left
7141 aRect
.SetRight( aScrPos
.X() );
7144 if ( meDragInsertMode
== INS_CELLSDOWN
)
7146 aPixelRects
.emplace_back( aRect
.Left()+1, aRect
.Top()+3, aRect
.Left()+1, aRect
.Bottom()-2 );
7147 aPixelRects
.emplace_back( aRect
.Right()-1, aRect
.Top()+3, aRect
.Right()-1, aRect
.Bottom()-2 );
7148 aPixelRects
.emplace_back( aRect
.Left()+1, aRect
.Top(), aRect
.Right()-1, aRect
.Top()+2 );
7149 aPixelRects
.emplace_back( aRect
.Left()+1, aRect
.Bottom()-1, aRect
.Right()-1, aRect
.Bottom()-1 );
7151 else if ( meDragInsertMode
== INS_CELLSRIGHT
)
7153 aPixelRects
.emplace_back( aRect
.Left(), aRect
.Top()+1, aRect
.Left()+2, aRect
.Bottom()-1 );
7154 aPixelRects
.emplace_back( aRect
.Right()-1, aRect
.Top()+1, aRect
.Right()-1, aRect
.Bottom()-1 );
7155 aPixelRects
.emplace_back( aRect
.Left()+3, aRect
.Top()+1, aRect
.Right()-2, aRect
.Top()+1 );
7156 aPixelRects
.emplace_back( aRect
.Left()+3, aRect
.Bottom()-1, aRect
.Right()-2, aRect
.Bottom()-1 );
7160 aPixelRects
.emplace_back( aRect
.Left(), aRect
.Top(), aRect
.Left()+2, aRect
.Bottom() );
7161 aPixelRects
.emplace_back( aRect
.Right()-2, aRect
.Top(), aRect
.Right(), aRect
.Bottom() );
7162 aPixelRects
.emplace_back( aRect
.Left()+3, aRect
.Top(), aRect
.Right()-3, aRect
.Top()+2 );
7163 aPixelRects
.emplace_back( aRect
.Left()+3, aRect
.Bottom()-2, aRect
.Right()-3, aRect
.Bottom() );
7166 // #i70788# get the OverlayManager safely
7167 rtl::Reference
<sdr::overlay::OverlayManager
> xOverlayManager
= getOverlayManager();
7169 if (xOverlayManager
.is() && !comphelper::LibreOfficeKit::isActive())
7171 std::vector
< basegfx::B2DRange
> aRanges
;
7172 const basegfx::B2DHomMatrix
aTransform(GetOutDev()->GetInverseViewTransformation());
7174 for(const tools::Rectangle
& rRA
: aPixelRects
)
7176 basegfx::B2DRange
aRB(rRA
.Left(), rRA
.Top(), rRA
.Right() + 1, rRA
.Bottom() + 1);
7177 aRB
.transform(aTransform
);
7178 aRanges
.push_back(aRB
);
7181 std::unique_ptr
<sdr::overlay::OverlayObject
> pOverlay(new sdr::overlay::OverlaySelection(
7182 sdr::overlay::OverlayType::Invert
,
7187 xOverlayManager
->add(*pOverlay
);
7188 mpOODragRect
.reset(new sdr::overlay::OverlayObjectList
);
7189 mpOODragRect
->append(std::move(pOverlay
));
7192 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
7193 if (comphelper::LibreOfficeKit::isActive() && pViewShell
)
7195 OString aRectsString
;
7196 tools::Rectangle aBoundingBox
;
7198 std::vector
<tools::Rectangle
> aRectangles
;
7199 aRectangles
.push_back(aRect
);
7203 aBoundingBox
= aRect
;
7204 aRectsString
= rectanglesToString(aRectangles
);
7208 aRectsString
= rectanglesToString(convertPixelToLogical(pViewShell
->GetViewData(), aRectangles
, aBoundingBox
));
7211 OString sBoundingBoxString
= "EMPTY"_ostr
;
7212 if (!aBoundingBox
.IsEmpty())
7213 sBoundingBoxString
= aBoundingBox
.toString();
7215 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_CELL_SELECTION_AREA
, sBoundingBoxString
);
7216 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION
, aRectsString
);
7221 void ScGridWindow::DeleteHeaderOverlay()
7226 void ScGridWindow::UpdateHeaderOverlay()
7228 const MapMode aDrawMode
= GetDrawMapMode();
7229 const MapMode aOldMode
= GetMapMode();
7230 comphelper::ScopeGuard
aMapModeGuard(
7231 [&aOldMode
, &aDrawMode
, this] {
7232 if (aOldMode
!= aDrawMode
)
7233 SetMapMode(aOldMode
);
7236 if (aOldMode
!= aDrawMode
)
7237 SetMapMode(aDrawMode
);
7239 DeleteHeaderOverlay();
7241 // Pixel rectangle is in aInvertRect
7242 if ( !aInvertRect
.IsEmpty() )
7244 // #i70788# get the OverlayManager safely
7245 rtl::Reference
<sdr::overlay::OverlayManager
> xOverlayManager
= getOverlayManager();
7247 if (xOverlayManager
.is() && !comphelper::LibreOfficeKit::isActive())
7249 // Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor();
7250 std::vector
< basegfx::B2DRange
> aRanges
;
7251 const basegfx::B2DHomMatrix
aTransform(GetOutDev()->GetInverseViewTransformation());
7252 basegfx::B2DRange
aRB(aInvertRect
.Left(), aInvertRect
.Top(), aInvertRect
.Right() + 1, aInvertRect
.Bottom() + 1);
7254 aRB
.transform(aTransform
);
7255 aRanges
.push_back(aRB
);
7257 std::unique_ptr
<sdr::overlay::OverlayObject
> pOverlay(new sdr::overlay::OverlaySelection(
7258 sdr::overlay::OverlayType::Invert
,
7263 xOverlayManager
->add(*pOverlay
);
7264 mpOOHeader
.reset(new sdr::overlay::OverlayObjectList
);
7265 mpOOHeader
->append(std::move(pOverlay
));
7270 void ScGridWindow::DeleteShrinkOverlay()
7275 void ScGridWindow::UpdateShrinkOverlay()
7277 const MapMode aDrawMode
= GetDrawMapMode();
7278 const MapMode aOldMode
= GetMapMode();
7279 comphelper::ScopeGuard
aMapModeGuard(
7280 [&aOldMode
, &aDrawMode
, this] {
7281 if (aOldMode
!= aDrawMode
)
7282 SetMapMode(aOldMode
);
7285 if (aOldMode
!= aDrawMode
)
7286 SetMapMode(aDrawMode
);
7288 DeleteShrinkOverlay();
7290 // get the rectangle in pixels
7292 tools::Rectangle aPixRect
;
7294 SCTAB nTab
= mrViewData
.GetTabNo();
7295 if ( mrViewData
.IsRefMode() && nTab
>= mrViewData
.GetRefStartZ() && nTab
<= mrViewData
.GetRefEndZ() &&
7296 mrViewData
.GetDelMark( aRange
) )
7298 //! limit to visible area
7299 if ( aRange
.aStart
.Col() <= aRange
.aEnd
.Col() &&
7300 aRange
.aStart
.Row() <= aRange
.aEnd
.Row() )
7302 Point aStart
= mrViewData
.GetScrPos( aRange
.aStart
.Col(),
7303 aRange
.aStart
.Row(), eWhich
);
7304 Point aEnd
= mrViewData
.GetScrPos( aRange
.aEnd
.Col()+1,
7305 aRange
.aEnd
.Row()+1, eWhich
);
7309 aPixRect
= tools::Rectangle( aStart
,aEnd
);
7313 if ( !aPixRect
.IsEmpty() )
7315 // #i70788# get the OverlayManager safely
7316 rtl::Reference
<sdr::overlay::OverlayManager
> xOverlayManager
= getOverlayManager();
7318 if (xOverlayManager
.is() && !comphelper::LibreOfficeKit::isActive())
7320 std::vector
< basegfx::B2DRange
> aRanges
;
7321 const basegfx::B2DHomMatrix
aTransform(GetOutDev()->GetInverseViewTransformation());
7322 basegfx::B2DRange
aRB(aPixRect
.Left(), aPixRect
.Top(), aPixRect
.Right() + 1, aPixRect
.Bottom() + 1);
7324 aRB
.transform(aTransform
);
7325 aRanges
.push_back(aRB
);
7327 std::unique_ptr
<sdr::overlay::OverlayObject
> pOverlay(new sdr::overlay::OverlaySelection(
7328 sdr::overlay::OverlayType::Invert
,
7333 xOverlayManager
->add(*pOverlay
);
7334 mpOOShrink
.reset(new sdr::overlay::OverlayObjectList
);
7335 mpOOShrink
->append(std::move(pOverlay
));
7340 void ScGridWindow::DeleteSparklineGroupOverlay()
7342 mpOOSparklineGroup
.reset();
7345 void ScGridWindow::UpdateSparklineGroupOverlay()
7347 const MapMode aDrawMode
= GetDrawMapMode();
7348 const MapMode aOldMode
= GetMapMode();
7349 comphelper::ScopeGuard
aMapModeGuard(
7350 [&aOldMode
, &aDrawMode
, this] {
7351 if (aOldMode
!= aDrawMode
)
7352 SetMapMode(aOldMode
);
7355 if (aOldMode
!= aDrawMode
)
7356 SetMapMode(aDrawMode
);
7358 DeleteSparklineGroupOverlay();
7360 ScAddress aCurrentAddress
= mrViewData
.GetCurPos();
7362 ScDocument
& rDocument
= mrViewData
.GetDocument();
7363 if (auto pSparkline
= rDocument
.GetSparkline(aCurrentAddress
))
7365 mpOOSparklineGroup
.reset(new sdr::overlay::OverlayObjectList
);
7367 rtl::Reference
<sdr::overlay::OverlayManager
> xOverlayManager
= getOverlayManager();
7368 if (xOverlayManager
.is())
7370 auto* pList
= rDocument
.GetSparklineList(aCurrentAddress
.Tab());
7373 auto const aSparklines
= pList
->getSparklinesFor(pSparkline
->getSparklineGroup());
7375 Color aColor
= SvtOptionsDrawinglayer::getHilightColor();
7377 std::vector
<basegfx::B2DRange
> aRanges
;
7378 const basegfx::B2DHomMatrix
aTransform(GetOutDev()->GetInverseViewTransformation());
7380 for (auto const& pCurrentSparkline
: aSparklines
)
7382 SCCOL nColumn
= pCurrentSparkline
->getColumn();
7383 SCROW nRow
= pCurrentSparkline
->getRow();
7385 Point aStart
= mrViewData
.GetScrPos(nColumn
, nRow
, eWhich
);
7386 Point aEnd
= mrViewData
.GetScrPos(nColumn
+ 1, nRow
+ 1, eWhich
);
7388 basegfx::B2DRange
aRange(aStart
.X(), aStart
.Y(), aEnd
.X(), aEnd
.Y());
7390 aRange
.transform(aTransform
);
7391 aRanges
.push_back(aRange
);
7394 std::unique_ptr
<sdr::overlay::OverlayObject
> pOverlay(new sdr::overlay::OverlaySelection(
7395 sdr::overlay::OverlayType::Transparent
,
7396 aColor
, std::move(aRanges
), true, false));
7398 xOverlayManager
->add(*pOverlay
);
7399 mpOOSparklineGroup
->append(std::move(pOverlay
));
7405 // #i70788# central method to get the OverlayManager safely
7406 rtl::Reference
<sdr::overlay::OverlayManager
> ScGridWindow::getOverlayManager() const
7408 SdrPageView
* pPV
= mrViewData
.GetView()->GetScDrawView()->GetSdrPageView();
7412 SdrPageWindow
* pPageWin
= pPV
->FindPageWindow( *GetOutDev() );
7416 return pPageWin
->GetOverlayManager();
7420 return rtl::Reference
<sdr::overlay::OverlayManager
>();
7423 void ScGridWindow::flushOverlayManager()
7425 // #i70788# get the OverlayManager safely
7426 rtl::Reference
<sdr::overlay::OverlayManager
> xOverlayManager
= getOverlayManager();
7428 if (xOverlayManager
.is())
7429 xOverlayManager
->flush();
7432 ScViewData
& ScGridWindow::getViewData()
7437 FactoryFunction
ScGridWindow::GetUITestFactory() const
7439 return ScGridWinUIObject::create
;
7442 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */