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/eeitem.hxx>
22 #include <editeng/flditem.hxx>
24 #include <editeng/editview.hxx>
25 #include <svx/svdobj.hxx>
26 #include <svx/svdpagv.hxx>
27 #include <svtools/imapobj.hxx>
28 #include <vcl/cursor.hxx>
29 #include <vcl/help.hxx>
30 #include <vcl/svapp.hxx>
31 #include <tools/urlobj.hxx>
32 #include <sfx2/viewfrm.hxx>
34 #include <unotools/localedatawrapper.hxx>
35 #include <unotools/securityoptions.hxx>
37 #include <viewuno.hxx>
38 #include <AccessibleDocument.hxx>
39 #include <com/sun/star/accessibility/XAccessible.hpp>
41 #include <gridwin.hxx>
42 #include <viewdata.hxx>
43 #include <drawview.hxx>
44 #include <drwlayer.hxx>
45 #include <drawpage.hxx>
46 #include <document.hxx>
47 #include <notemark.hxx>
48 #include <chgtrack.hxx>
49 #include <chgviset.hxx>
51 #include <tabvwsh.hxx>
52 #include <userdat.hxx>
55 #include <globstr.hrc>
57 bool ScGridWindow::ShowNoteMarker( SCCOL nPosX
, SCROW nPosY
, bool bKeyboard
)
61 ScDocument
* pDoc
= pViewData
->GetDocument();
62 SCTAB nTab
= pViewData
->GetTabNo();
63 ScAddress
aCellPos( nPosX
, nPosY
, nTab
);
66 bool bLeftEdge
= false;
70 ScChangeTrack
* pTrack
= pDoc
->GetChangeTrack();
71 ScChangeViewSettings
* pSettings
= pDoc
->GetChangeViewSettings();
72 if ( pTrack
&& pTrack
->GetFirst() && pSettings
&& pSettings
->ShowChanges())
74 const ScChangeAction
* pFound
= nullptr;
75 const ScChangeAction
* pFoundContent
= nullptr;
76 const ScChangeAction
* pFoundMove
= nullptr;
78 const ScChangeAction
* pAction
= pTrack
->GetFirst();
81 if ( pAction
->IsVisible() &&
82 ScViewUtil::IsActionShown( *pAction
, *pSettings
, *pDoc
) )
84 ScChangeActionType eType
= pAction
->GetType();
85 const ScBigRange
& rBig
= pAction
->GetBigRange();
86 if ( rBig
.aStart
.Tab() == nTab
)
88 ScRange aRange
= rBig
.MakeRange();
90 if ( eType
== SC_CAT_DELETE_ROWS
)
91 aRange
.aEnd
.SetRow( aRange
.aStart
.Row() );
92 else if ( eType
== SC_CAT_DELETE_COLS
)
93 aRange
.aEnd
.SetCol( aRange
.aStart
.Col() );
95 if ( aRange
.In( aCellPos
) )
97 pFound
= pAction
; // the last one wins
100 case SC_CAT_CONTENT
:
101 pFoundContent
= pAction
;
104 pFoundMove
= pAction
;
108 // added to avoid warnings
114 if ( eType
== SC_CAT_MOVE
)
117 static_cast<const ScChangeActionMove
*>(pAction
)->
118 GetFromRange().MakeRange();
119 if ( aRange
.In( aCellPos
) )
126 pAction
= pAction
->GetNext();
131 if ( pFoundContent
&& pFound
->GetType() != SC_CAT_CONTENT
)
132 pFound
= pFoundContent
; // content wins
133 if ( pFoundMove
&& pFound
->GetType() != SC_CAT_MOVE
&&
134 pFoundMove
->GetActionNumber() >
135 pFound
->GetActionNumber() )
136 pFound
= pFoundMove
; // move wins
138 // for deleted columns: Arrow on the left side of the cell
139 if ( pFound
->GetType() == SC_CAT_DELETE_COLS
)
142 DateTime aDT
= pFound
->GetDateTime();
143 aTrackText
= pFound
->GetUser()
145 + ScGlobal::pLocaleData
->getDate(aDT
)
147 + ScGlobal::pLocaleData
->getTime(aDT
)
149 OUString aComStr
=pFound
->GetComment();
150 if(!aComStr
.isEmpty())
152 aTrackText
+= aComStr
+ "\n( ";
155 pFound
->GetDescription(aTmp
, pDoc
);
157 if(!aComStr
.isEmpty())
164 // Note, only if it is not already displayed on the Drawing Layer:
165 const ScPostIt
* pNote
= pDoc
->GetNote( aCellPos
);
166 if ( (!aTrackText
.isEmpty()) || (pNote
&& !pNote
->IsCaptionShown()) )
170 if (mpNoteMarker
) // A note already shown
172 if (mpNoteMarker
->GetDocPos() == aCellPos
)
173 bNew
= false; // then stop
175 bFast
= true; // otherwise, at once
177 // marker which was shown for ctrl-F1 isn't removed by mouse events
178 if (mpNoteMarker
->IsByKeyboard() && !bKeyboard
)
184 bFast
= true; // keyboard also shows the marker immediately
186 mpNoteMarker
.reset();
188 bool bHSplit
= pViewData
->GetHSplitMode() != SC_SPLIT_NONE
;
189 bool bVSplit
= pViewData
->GetVSplitMode() != SC_SPLIT_NONE
;
191 vcl::Window
* pLeft
= pViewData
->GetView()->GetWindowByPos( bVSplit
? SC_SPLIT_TOPLEFT
: SC_SPLIT_BOTTOMLEFT
);
192 vcl::Window
* pRight
= bHSplit
? pViewData
->GetView()->GetWindowByPos( bVSplit
? SC_SPLIT_TOPRIGHT
: SC_SPLIT_BOTTOMRIGHT
) : nullptr;
193 vcl::Window
* pBottom
= bVSplit
? pViewData
->GetView()->GetWindowByPos( SC_SPLIT_BOTTOMLEFT
) : nullptr;
194 vcl::Window
* pDiagonal
= (bHSplit
&& bVSplit
) ? pViewData
->GetView()->GetWindowByPos( SC_SPLIT_BOTTOMRIGHT
) : nullptr;
195 OSL_ENSURE( pLeft
, "ScGridWindow::ShowNoteMarker - missing top-left grid window" );
197 /* If caption is shown from right or bottom windows, adjust
198 mapmode to include size of top-left window. */
199 MapMode aMapMode
= GetDrawMapMode( true );
200 Size aLeftSize
= pLeft
->PixelToLogic( pLeft
->GetOutputSizePixel(), aMapMode
);
201 Point aOrigin
= aMapMode
.GetOrigin();
202 if( (this == pRight
) || (this == pDiagonal
) )
203 aOrigin
.X() += aLeftSize
.Width();
204 if( (this == pBottom
) || (this == pDiagonal
) )
205 aOrigin
.Y() += aLeftSize
.Height();
206 aMapMode
.SetOrigin( aOrigin
);
208 mpNoteMarker
.reset(new ScNoteMarker(pLeft
, pRight
, pBottom
, pDiagonal
,
209 pDoc
, aCellPos
, aTrackText
,
210 aMapMode
, bLeftEdge
, bFast
, bKeyboard
));
211 if ( pViewData
->GetScDrawView() )
213 // get position for aCellPos
214 // get draw position in hmm for aCellPos
215 Point
aOldPos( pDoc
->GetColOffset( aCellPos
.Col(), aCellPos
.Tab() ), pDoc
->GetRowOffset( aCellPos
.Row(), aCellPos
.Tab() ) );
216 aOldPos
.X() = sc::TwipsToHMM( aOldPos
.X() );
217 aOldPos
.Y() = sc::TwipsToHMM( aOldPos
.Y() );
218 // get screen pos in hmm for aCellPos
219 // and equiv screen pos
220 Point aScreenPos
= pViewData
->GetScrPos( aCellPos
.Col(), aCellPos
.Row(), eWhich
, true );
221 MapMode aDrawMode
= GetDrawMapMode();
222 Point aCurPosHmm
= PixelToLogic(aScreenPos
, aDrawMode
);
223 Point aGridOff
= aCurPosHmm
-aOldPos
;
224 // fdo#63323 fix the X Position for the showing comment when
225 // the mouse over the cell when the sheet are RTL
226 if ( pDoc
->IsNegativePage(nTab
))
227 aGridOff
.setX(aCurPosHmm
.getX() + aOldPos
.getX());
228 mpNoteMarker
->SetGridOff( aGridOff
);
232 bDone
= true; // something is shown (old or new)
238 void ScGridWindow::RequestHelp(const HelpEvent
& rHEvt
)
240 //To know whether to prefix STR_CTRLCLICKHYERLINK or STR_CLICKHYPERLINK
241 //to hyperlink tooltips/help text
242 SvtSecurityOptions aSecOpt
;
243 bool bCtrlClickHlink
= aSecOpt
.IsOptionSet( SvtSecurityOptions::EOption::CtrlClickHyperlink
);
244 //Global string STR_CTRLCLICKHYPERLINK i.e,
245 // "ctrl-click to follow link:" for not MacOS
246 // "⌘-click to follow link:" for MacOs
247 vcl::KeyCode
aCode( KEY_SPACE
);
248 vcl::KeyCode
aModifiedCode( KEY_SPACE
, KEY_MOD1
);
249 OUString
aModStr( aModifiedCode
.GetName() );
250 aModStr
= aModStr
.replaceFirst(aCode
.GetName(), "");
251 aModStr
= aModStr
.replaceAll("+", "");
252 OUString aCtrlClickHlinkStr
= ScGlobal::GetRscString( STR_CTRLCLICKHYPERLINK
);
254 aCtrlClickHlinkStr
= aCtrlClickHlinkStr
.replaceAll("%s", aModStr
);
255 //Global string STR_CLICKHYPERLINK i.e, "click to open hyperlink"
256 OUString aClickHlinkStr
= ScGlobal::GetRscString( STR_CLICKHYPERLINK
);
258 bool bHelpEnabled
= bool(rHEvt
.GetMode() & ( HelpEventMode::BALLOON
| HelpEventMode::QUICK
));
259 SdrView
* pDrView
= pViewData
->GetScDrawView();
260 bool bDrawTextEdit
= false;
262 bDrawTextEdit
= pDrView
->IsTextEdit();
263 // notes or change tracking
264 if ( bHelpEnabled
&& !bDrawTextEdit
)
266 Point aPosPixel
= ScreenToOutputPixel( rHEvt
.GetMousePosPixel() );
269 pViewData
->GetPosFromPixel( aPosPixel
.X(), aPosPixel
.Y(), eWhich
, nPosX
, nPosY
);
271 if ( ShowNoteMarker( nPosX
, nPosY
, false ) )
273 Window::RequestHelp( rHEvt
); // turn off old Tip/Balloon
278 if (!bDone
&& mpNoteMarker
)
280 if (mpNoteMarker
->IsByKeyboard())
282 // marker which was shown for ctrl-F1 isn't removed by mouse events
286 mpNoteMarker
.reset();
290 // Image-Map / Text-URL
292 if ( bHelpEnabled
&& !bDone
&& !nButtonDown
) // only without pressed button
295 tools::Rectangle aPixRect
;
296 Point aPosPixel
= ScreenToOutputPixel( rHEvt
.GetMousePosPixel() );
298 if ( pDrView
) // URL / Image-Map
301 MouseEvent
aMEvt( aPosPixel
, 1, MouseEventModifiers::NONE
, MOUSE_LEFT
);
302 SdrHitKind eHit
= pDrView
->PickAnything( aMEvt
, SdrMouseEventKind::BUTTONDOWN
, aVEvt
);
304 if ( eHit
!= SdrHitKind::NONE
&& aVEvt
.pObj
!= nullptr )
306 // URL for IMapObject below Pointer is help text
307 if ( ScDrawLayer::GetIMapInfo( aVEvt
.pObj
) )
309 Point aLogicPos
= PixelToLogic( aPosPixel
);
310 IMapObject
* pIMapObj
= ScDrawLayer::GetHitIMapObject(
311 aVEvt
.pObj
, aLogicPos
, *this );
315 // For image maps show the description, if available
316 aHelpText
= pIMapObj
->GetAltText();
317 if (aHelpText
.isEmpty())
318 aHelpText
= pIMapObj
->GetURL();
319 if( bCtrlClickHlink
)
321 //prefix STR_CTRLCLICKHYPERLINK to aHelpText
322 aHelpText
= aCtrlClickHlinkStr
+ aHelpText
;
326 //Option not set, so prefix STR_CLICKHYPERLINK
327 aHelpText
= aClickHlinkStr
+ aHelpText
;
329 aPixRect
= LogicToPixel(aVEvt
.pObj
->GetLogicRect());
332 // URL in shape text or at shape itself (URL in text overrides object URL)
333 if ( aHelpText
.isEmpty() )
335 if( aVEvt
.eEvent
== SdrEventKind::ExecuteUrl
)
337 aHelpText
= aVEvt
.pURLField
->GetURL();
338 aPixRect
= LogicToPixel(aVEvt
.pObj
->GetLogicRect());
342 SdrPageView
* pPV
= nullptr;
343 Point aMDPos
= PixelToLogic( aPosPixel
);
344 SdrObject
* pObj
= pDrView
->PickObj(aMDPos
, pDrView
->getHitTolLog(), pPV
, SdrSearchOptions::ALSOONMASTER
);
347 if ( pObj
->IsGroupObject() )
349 SdrObject
* pHit
= pDrView
->PickObj(aMDPos
, pDrView
->getHitTolLog(), pPV
, SdrSearchOptions::DEEP
);
353 ScMacroInfo
* pInfo
= ScDrawLayer::GetMacroInfo( pObj
);
354 if ( pInfo
&& (pInfo
->GetHlink().getLength() > 0) )
356 aPixRect
= LogicToPixel(aVEvt
.pObj
->GetLogicRect());
357 aHelpText
= pInfo
->GetHlink();
358 if( bCtrlClickHlink
)
360 //prefix STR_CTRLCLICKHYPERLINK to aHelpText
361 aHelpText
= aCtrlClickHlinkStr
+ aHelpText
;
365 //Option not set, so prefix STR_CLICKHYPERLINK
366 aHelpText
= aClickHlinkStr
+ aHelpText
;
376 if ( aHelpText
.isEmpty() ) // Text-URL
379 if ( GetEditUrl( aPosPixel
, nullptr, &aUrl
) )
381 aHelpText
= INetURLObject::decode( aUrl
,
382 INetURLObject::DecodeMechanism::Unambiguous
);
384 if( bCtrlClickHlink
)
386 //prefix STR_CTRLCLICKHYPERLINK to aHelpText
387 aHelpText
= aCtrlClickHlinkStr
+ aHelpText
;
391 //Option not set, so prefix STR_CLICKHYPERLINK
392 aHelpText
= aClickHlinkStr
+ aHelpText
;
395 ScDocument
* pDoc
= pViewData
->GetDocument();
398 SCTAB nTab
= pViewData
->GetTabNo();
399 pViewData
->GetPosFromPixel( aPosPixel
.X(), aPosPixel
.Y(), eWhich
, nPosX
, nPosY
);
400 const ScPatternAttr
* pPattern
= pDoc
->GetPattern( nPosX
, nPosY
, nTab
);
402 // bForceToTop = sal_False, use the cell's real position
403 aPixRect
= pViewData
->GetEditArea( eWhich
, nPosX
, nPosY
, this, pPattern
, false );
407 if ( !aHelpText
.isEmpty() )
409 tools::Rectangle
aScreenRect(OutputToScreenPixel(aPixRect
.TopLeft()),
410 OutputToScreenPixel(aPixRect
.BottomRight()));
412 if ( rHEvt
.GetMode() & HelpEventMode::BALLOON
)
413 Help::ShowBalloon(this,rHEvt
.GetMousePosPixel(), aScreenRect
, aHelpText
);
414 else if ( rHEvt
.GetMode() & HelpEventMode::QUICK
)
415 Help::ShowQuickHelp(this,aScreenRect
, aHelpText
);
423 if ( pDrView
&& bHelpEnabled
&& !bDone
)
425 SdrPageView
* pPV
= pDrView
->GetSdrPageView();
426 OSL_ENSURE( pPV
, "SdrPageView* is NULL" );
428 bDone
= FmFormPage::RequestHelp( this, pDrView
, rHEvt
);
431 // If QuickHelp for AutoFill is shown, do not allow it to be removed
433 if ( nMouseStatus
== SC_GM_TABDOWN
&& pViewData
->GetRefType() == SC_REFTYPE_FILL
&&
434 Help::IsQuickHelpEnabled() )
438 Window::RequestHelp( rHEvt
);
441 bool ScGridWindow::IsMyModel(const SdrEditView
* pSdrView
)
444 pSdrView
->GetModel() == pViewData
->GetDocument()->GetDrawLayer();
447 void ScGridWindow::HideNoteMarker()
449 mpNoteMarker
.reset();
452 css::uno::Reference
< css::accessibility::XAccessible
>
453 ScGridWindow::CreateAccessible()
455 css::uno::Reference
< css::accessibility::XAccessible
> xAcc
= GetAccessible(false);
461 ScAccessibleDocument
* pAccessibleDocument
=
462 new ScAccessibleDocument(GetAccessibleParentWindow()->GetAccessible(),
463 pViewData
->GetViewShell(), eWhich
);
464 pAccessibleDocument
->PreInit();
466 xAcc
= pAccessibleDocument
;
469 pAccessibleDocument
->Init();
474 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */