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 <editeng/flditem.hxx>
22 #include <svx/fmpage.hxx>
23 #include <svx/svdobj.hxx>
24 #include <svx/svdpagv.hxx>
25 #include <svx/ImageMapInfo.hxx>
26 #include <vcl/imapobj.hxx>
27 #include <vcl/help.hxx>
28 #include <tools/urlobj.hxx>
29 #include <sfx2/sfxhelp.hxx>
31 #include <AccessibleDocument.hxx>
32 #include <com/sun/star/accessibility/XAccessible.hpp>
34 #include <gridwin.hxx>
35 #include <viewdata.hxx>
36 #include <drawview.hxx>
37 #include <drwlayer.hxx>
38 #include <document.hxx>
39 #include <notemark.hxx>
40 #include <chgtrack.hxx>
41 #include <chgviset.hxx>
46 bool ScGridWindow::ShowNoteMarker( SCCOL nPosX
, SCROW nPosY
, bool bKeyboard
)
50 ScDocument
& rDoc
= mrViewData
.GetDocument();
51 SCTAB nTab
= mrViewData
.GetTabNo();
52 ScAddress
aCellPos( nPosX
, nPosY
, nTab
);
55 bool bLeftEdge
= false;
59 ScChangeTrack
* pTrack
= rDoc
.GetChangeTrack();
60 ScChangeViewSettings
* pSettings
= rDoc
.GetChangeViewSettings();
61 if ( pTrack
&& pTrack
->GetFirst() && pSettings
&& pSettings
->ShowChanges())
63 const ScChangeAction
* pFound
= nullptr;
64 const ScChangeAction
* pFoundContent
= nullptr;
65 const ScChangeAction
* pFoundMove
= nullptr;
66 const ScChangeAction
* pAction
= pTrack
->GetFirst();
69 if ( pAction
->IsVisible() &&
70 ScViewUtil::IsActionShown( *pAction
, *pSettings
, rDoc
) )
72 ScChangeActionType eType
= pAction
->GetType();
73 const ScBigRange
& rBig
= pAction
->GetBigRange();
74 if ( rBig
.aStart
.Tab() == nTab
)
76 ScRange aRange
= rBig
.MakeRange( rDoc
);
78 if ( eType
== SC_CAT_DELETE_ROWS
)
79 aRange
.aEnd
.SetRow( aRange
.aStart
.Row() );
80 else if ( eType
== SC_CAT_DELETE_COLS
)
81 aRange
.aEnd
.SetCol( aRange
.aStart
.Col() );
83 if ( aRange
.Contains( aCellPos
) )
85 pFound
= pAction
; // the last one wins
89 pFoundContent
= pAction
;
96 // added to avoid warnings
101 if ( eType
== SC_CAT_MOVE
)
104 static_cast<const ScChangeActionMove
*>(pAction
)->
105 GetFromRange().MakeRange( rDoc
);
106 if ( aRange
.Contains( aCellPos
) )
112 pAction
= pAction
->GetNext();
117 if ( pFoundContent
&& pFound
->GetType() != SC_CAT_CONTENT
)
118 pFound
= pFoundContent
; // content wins
119 if ( pFoundMove
&& pFound
->GetType() != SC_CAT_MOVE
&&
120 pFoundMove
->GetActionNumber() >
121 pFound
->GetActionNumber() )
122 pFound
= pFoundMove
; // move wins
124 // for deleted columns: Arrow on the left side of the cell
125 if ( pFound
->GetType() == SC_CAT_DELETE_COLS
)
128 DateTime aDT
= pFound
->GetDateTime();
129 aTrackText
= pFound
->GetUser()
131 + ScGlobal::getLocaleData().getDate(aDT
)
133 + ScGlobal::getLocaleData().getTime(aDT
)
135 OUString aComStr
=pFound
->GetComment();
136 if(!aComStr
.isEmpty())
138 aTrackText
+= aComStr
+ "\n( ";
140 OUString aTmp
= pFound
->GetDescription(rDoc
);
142 if(!aComStr
.isEmpty())
149 // Note, only if it is not already displayed on the Drawing Layer:
150 const ScPostIt
* pNote
= rDoc
.GetNote( aCellPos
);
151 if ( (!aTrackText
.isEmpty()) || (pNote
&& !pNote
->IsCaptionShown()) )
155 if (mpNoteMarker
) // A note already shown
157 if (mpNoteMarker
->GetDocPos() == aCellPos
)
158 bNew
= false; // then stop
160 bFast
= true; // otherwise, at once
162 // marker which was shown for ctrl-F1 isn't removed by mouse events
163 if (mpNoteMarker
->IsByKeyboard() && !bKeyboard
)
169 bFast
= true; // keyboard also shows the marker immediately
171 mpNoteMarker
.reset();
173 bool bHSplit
= mrViewData
.GetHSplitMode() != SC_SPLIT_NONE
;
174 bool bVSplit
= mrViewData
.GetVSplitMode() != SC_SPLIT_NONE
;
176 vcl::Window
* pLeft
= mrViewData
.GetView()->GetWindowByPos( bVSplit
? SC_SPLIT_TOPLEFT
: SC_SPLIT_BOTTOMLEFT
);
177 vcl::Window
* pRight
= bHSplit
? mrViewData
.GetView()->GetWindowByPos( bVSplit
? SC_SPLIT_TOPRIGHT
: SC_SPLIT_BOTTOMRIGHT
) : nullptr;
178 vcl::Window
* pBottom
= bVSplit
? mrViewData
.GetView()->GetWindowByPos( SC_SPLIT_BOTTOMLEFT
) : nullptr;
179 vcl::Window
* pDiagonal
= (bHSplit
&& bVSplit
) ? mrViewData
.GetView()->GetWindowByPos( SC_SPLIT_BOTTOMRIGHT
) : nullptr;
180 assert(pLeft
&& "ScGridWindow::ShowNoteMarker - missing top-left grid window");
182 /* If caption is shown from right or bottom windows, adjust
183 mapmode to include size of top-left window. */
184 MapMode aMapMode
= GetDrawMapMode( true );
185 Size aLeftSize
= pLeft
->PixelToLogic( pLeft
->GetOutputSizePixel(), aMapMode
);
186 Point aOrigin
= aMapMode
.GetOrigin();
187 if( (this == pRight
) || (this == pDiagonal
) )
188 aOrigin
.AdjustX(aLeftSize
.Width() );
189 if( (this == pBottom
) || (this == pDiagonal
) )
190 aOrigin
.AdjustY(aLeftSize
.Height() );
191 aMapMode
.SetOrigin( aOrigin
);
193 mpNoteMarker
.reset(new ScNoteMarker(pLeft
, pRight
, pBottom
, pDiagonal
,
194 &rDoc
, aCellPos
, aTrackText
,
195 aMapMode
, bLeftEdge
, bFast
, bKeyboard
));
198 bDone
= true; // something is shown (old or new)
204 void ScGridWindow::RequestHelp(const HelpEvent
& rHEvt
)
207 OUString aFormulaText
;
208 tools::Rectangle aFormulaPixRect
;
209 bool bHelpEnabled
= bool(rHEvt
.GetMode() & ( HelpEventMode::BALLOON
| HelpEventMode::QUICK
));
210 SdrView
* pDrView
= mrViewData
.GetScDrawView();
211 bool bDrawTextEdit
= false;
213 bDrawTextEdit
= pDrView
->IsTextEdit();
214 // notes or change tracking
215 if ( bHelpEnabled
&& !bDrawTextEdit
)
217 Point aPosPixel
= ScreenToOutputPixel( rHEvt
.GetMousePosPixel() );
220 ScDocument
& rDoc
= mrViewData
.GetDocument();
221 SCTAB nTab
= mrViewData
.GetTabNo();
222 const ScViewOptions
& rOpts
= mrViewData
.GetOptions();
223 mrViewData
.GetPosFromPixel( aPosPixel
.X(), aPosPixel
.Y(), eWhich
, nPosX
, nPosY
);
225 if ( ShowNoteMarker( nPosX
, nPosY
, false ) )
227 Window::RequestHelp( rHEvt
); // turn off old Tip/Balloon
231 if ( rOpts
.GetOption( VOPT_FORMULAS_MARKS
) )
233 aFormulaText
= rDoc
.GetFormula( nPosX
, nPosY
, nTab
);
234 if ( !aFormulaText
.isEmpty() ) {
235 const ScPatternAttr
* pPattern
= rDoc
.GetPattern( nPosX
, nPosY
, nTab
);
236 aFormulaPixRect
= mrViewData
.GetEditArea( eWhich
, nPosX
, nPosY
, this, pPattern
, true );
241 if (!bDone
&& mpNoteMarker
)
243 if (mpNoteMarker
->IsByKeyboard())
245 // marker which was shown for ctrl-F1 isn't removed by mouse events
249 mpNoteMarker
.reset();
253 if ( !aFormulaText
.isEmpty() )
255 tools::Rectangle
aScreenRect(OutputToScreenPixel(aFormulaPixRect
.TopLeft()),
256 OutputToScreenPixel(aFormulaPixRect
.BottomRight()));
257 if ( rHEvt
.GetMode() & HelpEventMode::BALLOON
)
258 Help::ShowBalloon(this, rHEvt
.GetMousePosPixel(), aScreenRect
, aFormulaText
);
259 else if ( rHEvt
.GetMode() & HelpEventMode::QUICK
)
260 Help::ShowQuickHelp(this, aScreenRect
, aFormulaText
);
264 // Image-Map / Text-URL
266 if ( bHelpEnabled
&& !bDone
&& !nButtonDown
) // only without pressed button
269 tools::Rectangle aPixRect
;
270 Point aPosPixel
= ScreenToOutputPixel( rHEvt
.GetMousePosPixel() );
272 if ( pDrView
) // URL / Image-Map
275 MouseEvent
aMEvt( aPosPixel
, 1, MouseEventModifiers::NONE
, MOUSE_LEFT
);
276 SdrHitKind eHit
= pDrView
->PickAnything( aMEvt
, SdrMouseEventKind::BUTTONDOWN
, aVEvt
);
278 if ( eHit
!= SdrHitKind::NONE
&& aVEvt
.mpObj
!= nullptr )
280 // URL for IMapObject below Pointer is help text
281 if (SvxIMapInfo::GetIMapInfo(aVEvt
.mpObj
))
283 Point aLogicPos
= PixelToLogic( aPosPixel
);
284 IMapObject
* pIMapObj
= SvxIMapInfo::GetHitIMapObject(
285 aVEvt
.mpObj
, aLogicPos
, GetOutDev() );
289 // For image maps show the description, if available
290 aHelpText
= pIMapObj
->GetAltText();
291 if (aHelpText
.isEmpty())
292 aHelpText
= SfxHelp::GetURLHelpText(pIMapObj
->GetURL());
293 aPixRect
= LogicToPixel(aVEvt
.mpObj
->GetLogicRect());
296 // URL in shape text or at shape itself (URL in text overrides object URL)
297 if ( aHelpText
.isEmpty() )
299 if( aVEvt
.meEvent
== SdrEventKind::ExecuteUrl
)
301 if (aVEvt
.mpURLField
&& !aVEvt
.mpURLField
->GetURL().startsWith("#"))
303 aHelpText
= SfxHelp::GetURLHelpText(aVEvt
.mpURLField
->GetURL());
304 aPixRect
= LogicToPixel(aVEvt
.mpObj
->GetLogicRect());
309 SdrPageView
* pPV
= nullptr;
310 Point aMDPos
= PixelToLogic( aPosPixel
);
311 SdrObject
* pObj
= pDrView
->PickObj(aMDPos
, pDrView
->getHitTolLog(), pPV
, SdrSearchOptions::ALSOONMASTER
);
314 if ( pObj
->IsGroupObject() )
316 SdrObject
* pHit
= pDrView
->PickObj(aMDPos
, pDrView
->getHitTolLog(), pPV
, SdrSearchOptions::DEEP
);
320 // Fragments pointing into the current document need no tooltip
321 // describing the ctrl-click functionality.
322 if ( !pObj
->getHyperlink().isEmpty() && !pObj
->getHyperlink().startsWith("#") )
324 aPixRect
= LogicToPixel(aVEvt
.mpObj
->GetLogicRect());
325 aHelpText
= SfxHelp::GetURLHelpText(pObj
->getHyperlink());
333 if ( aHelpText
.isEmpty() ) // Text-URL
336 if ( GetEditUrl( aPosPixel
, nullptr, &aUrl
) )
338 aHelpText
= SfxHelp::GetURLHelpText(
339 INetURLObject::decode(aUrl
, INetURLObject::DecodeMechanism::Unambiguous
));
341 ScDocument
& rDoc
= mrViewData
.GetDocument();
344 SCTAB nTab
= mrViewData
.GetTabNo();
345 mrViewData
.GetPosFromPixel( aPosPixel
.X(), aPosPixel
.Y(), eWhich
, nPosX
, nPosY
);
346 const ScPatternAttr
* pPattern
= rDoc
.GetPattern( nPosX
, nPosY
, nTab
);
348 // bForceToTop = sal_False, use the cell's real position
349 aPixRect
= mrViewData
.GetEditArea( eWhich
, nPosX
, nPosY
, this, pPattern
, false );
353 if ( !aHelpText
.isEmpty() )
355 tools::Rectangle
aScreenRect(OutputToScreenPixel(aPixRect
.TopLeft()),
356 OutputToScreenPixel(aPixRect
.BottomRight()));
358 if ( rHEvt
.GetMode() & HelpEventMode::BALLOON
)
359 Help::ShowBalloon(this,rHEvt
.GetMousePosPixel(), aScreenRect
, aHelpText
);
360 else if ( rHEvt
.GetMode() & HelpEventMode::QUICK
)
361 Help::ShowQuickHelp(this,aScreenRect
, aHelpText
);
369 if ( pDrView
&& bHelpEnabled
&& !bDone
)
371 SdrPageView
* pPV
= pDrView
->GetSdrPageView();
372 OSL_ENSURE( pPV
, "SdrPageView* is NULL" );
374 bDone
= FmFormPage::RequestHelp( this, pDrView
, rHEvt
);
377 // If QuickHelp for AutoFill is shown, do not allow it to be removed
379 if ( nMouseStatus
== SC_GM_TABDOWN
&& mrViewData
.GetRefType() == SC_REFTYPE_FILL
&&
380 Help::IsQuickHelpEnabled() )
384 Window::RequestHelp( rHEvt
);
387 bool ScGridWindow::IsMyModel(const SdrEditView
* pSdrView
)
390 &pSdrView
->GetModel() == mrViewData
.GetDocument().GetDrawLayer();
393 void ScGridWindow::HideNoteMarker()
395 mpNoteMarker
.reset();
398 css::uno::Reference
< css::accessibility::XAccessible
>
399 ScGridWindow::CreateAccessible()
401 css::uno::Reference
< css::accessibility::XAccessible
> xAcc
= GetAccessible(false);
407 rtl::Reference
<ScAccessibleDocument
> pAccessibleDocument
=
408 new ScAccessibleDocument(GetAccessibleParentWindow()->GetAccessible(),
409 mrViewData
.GetViewShell(), eWhich
);
410 pAccessibleDocument
->PreInit();
412 xAcc
= pAccessibleDocument
;
415 pAccessibleDocument
->Init();
420 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */