lok: calc: fix needed when position caching is disabled
[LibreOffice.git] / sc / source / ui / view / gridwin5.cxx
blob7e7503a6331cf2ecc35ec2d3e83777f1b732160c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
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>
50 #include <dbfunc.hxx>
51 #include <tabvwsh.hxx>
52 #include <userdat.hxx>
53 #include <postit.hxx>
54 #include <global.hxx>
55 #include <globstr.hrc>
57 bool ScGridWindow::ShowNoteMarker( SCCOL nPosX, SCROW nPosY, bool bKeyboard )
59 bool bDone = false;
61 ScDocument* pDoc = pViewData->GetDocument();
62 SCTAB nTab = pViewData->GetTabNo();
63 ScAddress aCellPos( nPosX, nPosY, nTab );
65 OUString aTrackText;
66 bool bLeftEdge = false;
68 // change tracking
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;
77 long nModified = 0;
78 const ScChangeAction* pAction = pTrack->GetFirst();
79 while (pAction)
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
98 switch ( eType )
100 case SC_CAT_CONTENT :
101 pFoundContent = pAction;
102 break;
103 case SC_CAT_MOVE :
104 pFoundMove = pAction;
105 break;
106 default:
108 // added to avoid warnings
111 ++nModified;
114 if ( eType == SC_CAT_MOVE )
116 ScRange aRange =
117 static_cast<const ScChangeActionMove*>(pAction)->
118 GetFromRange().MakeRange();
119 if ( aRange.In( aCellPos ) )
121 pFound = pAction;
122 ++nModified;
126 pAction = pAction->GetNext();
129 if ( pFound )
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 )
140 bLeftEdge = true;
142 DateTime aDT = pFound->GetDateTime();
143 aTrackText = pFound->GetUser()
144 + ", "
145 + ScGlobal::pLocaleData->getDate(aDT)
146 + " "
147 + ScGlobal::pLocaleData->getTime(aDT)
148 + ":\n";
149 OUString aComStr=pFound->GetComment();
150 if(!aComStr.isEmpty())
152 aTrackText += aComStr + "\n( ";
154 OUString aTmp;
155 pFound->GetDescription(aTmp, pDoc);
156 aTrackText += aTmp;
157 if(!aComStr.isEmpty())
159 aTrackText += ")";
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()) )
168 bool bNew = true;
169 bool bFast = false;
170 if (mpNoteMarker) // A note already shown
172 if (mpNoteMarker->GetDocPos() == aCellPos)
173 bNew = false; // then stop
174 else
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)
179 bNew = false;
181 if (bNew)
183 if (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)
235 return bDone;
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 );
257 bool bDone = false;
258 bool bHelpEnabled = bool(rHEvt.GetMode() & ( HelpEventMode::BALLOON | HelpEventMode::QUICK ));
259 SdrView* pDrView = pViewData->GetScDrawView();
260 bool bDrawTextEdit = false;
261 if (pDrView)
262 bDrawTextEdit = pDrView->IsTextEdit();
263 // notes or change tracking
264 if ( bHelpEnabled && !bDrawTextEdit )
266 Point aPosPixel = ScreenToOutputPixel( rHEvt.GetMousePosPixel() );
267 SCCOL nPosX;
268 SCROW nPosY;
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
274 bDone = true;
278 if (!bDone && mpNoteMarker)
280 if (mpNoteMarker->IsByKeyboard())
282 // marker which was shown for ctrl-F1 isn't removed by mouse events
284 else
286 mpNoteMarker.reset();
290 // Image-Map / Text-URL
292 if ( bHelpEnabled && !bDone && !nButtonDown ) // only without pressed button
294 OUString aHelpText;
295 tools::Rectangle aPixRect;
296 Point aPosPixel = ScreenToOutputPixel( rHEvt.GetMousePosPixel() );
298 if ( pDrView ) // URL / Image-Map
300 SdrViewEvent aVEvt;
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 );
313 if ( pIMapObj )
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;
324 else
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());
340 else
342 SdrPageView* pPV = nullptr;
343 Point aMDPos = PixelToLogic( aPosPixel );
344 SdrObject* pObj = pDrView->PickObj(aMDPos, pDrView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER);
345 if (pObj)
347 if ( pObj->IsGroupObject() )
349 SdrObject* pHit = pDrView->PickObj(aMDPos, pDrView->getHitTolLog(), pPV, SdrSearchOptions::DEEP);
350 if (pHit)
351 pObj = pHit;
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;
363 else
365 //Option not set, so prefix STR_CLICKHYPERLINK
366 aHelpText = aClickHlinkStr + aHelpText;
376 if ( aHelpText.isEmpty() ) // Text-URL
378 OUString aUrl;
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;
389 else
391 //Option not set, so prefix STR_CLICKHYPERLINK
392 aHelpText = aClickHlinkStr + aHelpText;
395 ScDocument* pDoc = pViewData->GetDocument();
396 SCCOL nPosX;
397 SCROW nPosY;
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);
417 bDone = true;
421 // basic controls
423 if ( pDrView && bHelpEnabled && !bDone )
425 SdrPageView* pPV = pDrView->GetSdrPageView();
426 OSL_ENSURE( pPV, "SdrPageView* is NULL" );
427 if (pPV)
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() )
435 bDone = true;
437 if (!bDone)
438 Window::RequestHelp( rHEvt );
441 bool ScGridWindow::IsMyModel(const SdrEditView* pSdrView)
443 return 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);
456 if (xAcc.is())
458 return xAcc;
461 ScAccessibleDocument* pAccessibleDocument =
462 new ScAccessibleDocument(GetAccessibleParentWindow()->GetAccessible(),
463 pViewData->GetViewShell(), eWhich);
464 pAccessibleDocument->PreInit();
466 xAcc = pAccessibleDocument;
467 SetAccessible(xAcc);
469 pAccessibleDocument->Init();
471 return xAcc;
474 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */