1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20 #include <editeng/flditem.hxx>
21
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>
30
31 #include <AccessibleDocument.hxx>
32 #include <com/sun/star/accessibility/XAccessible.hpp>
33
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>
42 #include <dbfunc.hxx>
43 #include <userdat.hxx>
44 #include <postit.hxx>
45 #include <global.hxx>
46
ShowNoteMarker(SCCOL nPosX,SCROW nPosY,bool bKeyboard)47 bool ScGridWindow::ShowNoteMarker( SCCOL nPosX, SCROW nPosY, bool bKeyboard )
48 {
49 bool bDone = false;
50
51 ScDocument& rDoc = mrViewData.GetDocument();
52 SCTAB nTab = mrViewData.GetTabNo();
53 ScAddress aCellPos( nPosX, nPosY, nTab );
54
55 OUString aTrackText;
56 bool bLeftEdge = false;
57
58 // change tracking
59
60 ScChangeTrack* pTrack = rDoc.GetChangeTrack();
61 ScChangeViewSettings* pSettings = rDoc.GetChangeViewSettings();
62 if ( pTrack && pTrack->GetFirst() && pSettings && pSettings->ShowChanges())
63 {
64 const ScChangeAction* pFound = nullptr;
65 const ScChangeAction* pFoundContent = nullptr;
66 const ScChangeAction* pFoundMove = nullptr;
67 const ScChangeAction* pAction = pTrack->GetFirst();
68 while (pAction)
69 {
70 if ( pAction->IsVisible() &&
71 ScViewUtil::IsActionShown( *pAction, *pSettings, rDoc ) )
72 {
73 ScChangeActionType eType = pAction->GetType();
74 const ScBigRange& rBig = pAction->GetBigRange();
75 if ( rBig.aStart.Tab() == nTab )
76 {
77 ScRange aRange = rBig.MakeRange();
78
79 if ( eType == SC_CAT_DELETE_ROWS )
80 aRange.aEnd.SetRow( aRange.aStart.Row() );
81 else if ( eType == SC_CAT_DELETE_COLS )
82 aRange.aEnd.SetCol( aRange.aStart.Col() );
83
84 if ( aRange.In( aCellPos ) )
85 {
86 pFound = pAction; // the last one wins
87 switch ( eType )
88 {
89 case SC_CAT_CONTENT :
90 pFoundContent = pAction;
91 break;
92 case SC_CAT_MOVE :
93 pFoundMove = pAction;
94 break;
95 default:
96 {
97 // added to avoid warnings
98 }
99 }
100 }
101 }
102 if ( eType == SC_CAT_MOVE )
103 {
104 ScRange aRange =
105 static_cast<const ScChangeActionMove*>(pAction)->
106 GetFromRange().MakeRange();
107 if ( aRange.In( aCellPos ) )
108 {
109 pFound = pAction;
110 }
111 }
112 }
113 pAction = pAction->GetNext();
114 }
115
116 if ( pFound )
117 {
118 if ( pFoundContent && pFound->GetType() != SC_CAT_CONTENT )
119 pFound = pFoundContent; // content wins
120 if ( pFoundMove && pFound->GetType() != SC_CAT_MOVE &&
121 pFoundMove->GetActionNumber() >
122 pFound->GetActionNumber() )
123 pFound = pFoundMove; // move wins
124
125 // for deleted columns: Arrow on the left side of the cell
126 if ( pFound->GetType() == SC_CAT_DELETE_COLS )
127 bLeftEdge = true;
128
129 DateTime aDT = pFound->GetDateTime();
130 aTrackText = pFound->GetUser()
131 + ", "
132 + ScGlobal::getLocaleDataPtr()->getDate(aDT)
133 + " "
134 + ScGlobal::getLocaleDataPtr()->getTime(aDT)
135 + ":\n";
136 OUString aComStr=pFound->GetComment();
137 if(!aComStr.isEmpty())
138 {
139 aTrackText += aComStr + "\n( ";
140 }
141 OUString aTmp;
142 pFound->GetDescription(aTmp, rDoc);
143 aTrackText += aTmp;
144 if(!aComStr.isEmpty())
145 {
146 aTrackText += ")";
147 }
148 }
149 }
150
151 // Note, only if it is not already displayed on the Drawing Layer:
152 const ScPostIt* pNote = rDoc.GetNote( aCellPos );
153 if ( (!aTrackText.isEmpty()) || (pNote && !pNote->IsCaptionShown()) )
154 {
155 bool bNew = true;
156 bool bFast = false;
157 if (mpNoteMarker) // A note already shown
158 {
159 if (mpNoteMarker->GetDocPos() == aCellPos)
160 bNew = false; // then stop
161 else
162 bFast = true; // otherwise, at once
163
164 // marker which was shown for ctrl-F1 isn't removed by mouse events
165 if (mpNoteMarker->IsByKeyboard() && !bKeyboard)
166 bNew = false;
167 }
168 if (bNew)
169 {
170 if (bKeyboard)
171 bFast = true; // keyboard also shows the marker immediately
172
173 mpNoteMarker.reset();
174
175 bool bHSplit = mrViewData.GetHSplitMode() != SC_SPLIT_NONE;
176 bool bVSplit = mrViewData.GetVSplitMode() != SC_SPLIT_NONE;
177
178 vcl::Window* pLeft = mrViewData.GetView()->GetWindowByPos( bVSplit ? SC_SPLIT_TOPLEFT : SC_SPLIT_BOTTOMLEFT );
179 vcl::Window* pRight = bHSplit ? mrViewData.GetView()->GetWindowByPos( bVSplit ? SC_SPLIT_TOPRIGHT : SC_SPLIT_BOTTOMRIGHT ) : nullptr;
180 vcl::Window* pBottom = bVSplit ? mrViewData.GetView()->GetWindowByPos( SC_SPLIT_BOTTOMLEFT ) : nullptr;
181 vcl::Window* pDiagonal = (bHSplit && bVSplit) ? mrViewData.GetView()->GetWindowByPos( SC_SPLIT_BOTTOMRIGHT ) : nullptr;
182 OSL_ENSURE( pLeft, "ScGridWindow::ShowNoteMarker - missing top-left grid window" );
183
184 /* If caption is shown from right or bottom windows, adjust
185 mapmode to include size of top-left window. */
186 MapMode aMapMode = GetDrawMapMode( true );
187 Size aLeftSize = pLeft->PixelToLogic( pLeft->GetOutputSizePixel(), aMapMode );
188 Point aOrigin = aMapMode.GetOrigin();
189 if( (this == pRight) || (this == pDiagonal) )
190 aOrigin.AdjustX(aLeftSize.Width() );
191 if( (this == pBottom) || (this == pDiagonal) )
192 aOrigin.AdjustY(aLeftSize.Height() );
193 aMapMode.SetOrigin( aOrigin );
194
195 mpNoteMarker.reset(new ScNoteMarker(pLeft, pRight, pBottom, pDiagonal,
196 &rDoc, aCellPos, aTrackText,
197 aMapMode, bLeftEdge, bFast, bKeyboard));
198 }
199
200 bDone = true; // something is shown (old or new)
201 }
202
203 return bDone;
204 }
205
RequestHelp(const HelpEvent & rHEvt)206 void ScGridWindow::RequestHelp(const HelpEvent& rHEvt)
207 {
208 bool bDone = false;
209 bool bHelpEnabled = bool(rHEvt.GetMode() & ( HelpEventMode::BALLOON | HelpEventMode::QUICK ));
210 SdrView* pDrView = mrViewData.GetScDrawView();
211 bool bDrawTextEdit = false;
212 if (pDrView)
213 bDrawTextEdit = pDrView->IsTextEdit();
214 // notes or change tracking
215 if ( bHelpEnabled && !bDrawTextEdit )
216 {
217 Point aPosPixel = ScreenToOutputPixel( rHEvt.GetMousePosPixel() );
218 SCCOL nPosX;
219 SCROW nPosY;
220 mrViewData.GetPosFromPixel( aPosPixel.X(), aPosPixel.Y(), eWhich, nPosX, nPosY );
221
222 if ( ShowNoteMarker( nPosX, nPosY, false ) )
223 {
224 Window::RequestHelp( rHEvt ); // turn off old Tip/Balloon
225 bDone = true;
226 }
227 }
228
229 if (!bDone && mpNoteMarker)
230 {
231 if (mpNoteMarker->IsByKeyboard())
232 {
233 // marker which was shown for ctrl-F1 isn't removed by mouse events
234 }
235 else
236 {
237 mpNoteMarker.reset();
238 }
239 }
240
241 // Image-Map / Text-URL
242
243 if ( bHelpEnabled && !bDone && !nButtonDown ) // only without pressed button
244 {
245 OUString aHelpText;
246 tools::Rectangle aPixRect;
247 Point aPosPixel = ScreenToOutputPixel( rHEvt.GetMousePosPixel() );
248
249 if ( pDrView ) // URL / Image-Map
250 {
251 SdrViewEvent aVEvt;
252 MouseEvent aMEvt( aPosPixel, 1, MouseEventModifiers::NONE, MOUSE_LEFT );
253 SdrHitKind eHit = pDrView->PickAnything( aMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt );
254
255 if ( eHit != SdrHitKind::NONE && aVEvt.pObj != nullptr )
256 {
257 // URL for IMapObject below Pointer is help text
258 if ( SvxIMapInfo::GetIMapInfo( aVEvt.pObj ) )
259 {
260 Point aLogicPos = PixelToLogic( aPosPixel );
261 IMapObject* pIMapObj = SvxIMapInfo::GetHitIMapObject(
262 aVEvt.pObj, aLogicPos, GetOutDev() );
263
264 if ( pIMapObj )
265 {
266 // For image maps show the description, if available
267 aHelpText = pIMapObj->GetAltText();
268 if (aHelpText.isEmpty())
269 aHelpText = SfxHelp::GetURLHelpText(pIMapObj->GetURL());
270 aPixRect = LogicToPixel(aVEvt.pObj->GetLogicRect());
271 }
272 }
273 // URL in shape text or at shape itself (URL in text overrides object URL)
274 if ( aHelpText.isEmpty() )
275 {
276 if( aVEvt.eEvent == SdrEventKind::ExecuteUrl )
277 {
278 aHelpText = SfxHelp::GetURLHelpText(aVEvt.pURLField->GetURL());
279 aPixRect = LogicToPixel(aVEvt.pObj->GetLogicRect());
280 }
281 else
282 {
283 SdrPageView* pPV = nullptr;
284 Point aMDPos = PixelToLogic( aPosPixel );
285 SdrObject* pObj = pDrView->PickObj(aMDPos, pDrView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER);
286 if (pObj)
287 {
288 if ( pObj->IsGroupObject() )
289 {
290 SdrObject* pHit = pDrView->PickObj(aMDPos, pDrView->getHitTolLog(), pPV, SdrSearchOptions::DEEP);
291 if (pHit)
292 pObj = pHit;
293 }
294 ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( pObj );
295 if ( pInfo && (pInfo->GetHlink().getLength() > 0) )
296 {
297 aPixRect = LogicToPixel(aVEvt.pObj->GetLogicRect());
298 aHelpText = SfxHelp::GetURLHelpText(pInfo->GetHlink());
299 }
300 }
301 }
302 }
303 }
304 }
305
306 if ( aHelpText.isEmpty() ) // Text-URL
307 {
308 OUString aUrl;
309 if ( GetEditUrl( aPosPixel, nullptr, &aUrl ) )
310 {
311 aHelpText = SfxHelp::GetURLHelpText(
312 INetURLObject::decode(aUrl, INetURLObject::DecodeMechanism::Unambiguous));
313
314 ScDocument& rDoc = mrViewData.GetDocument();
315 SCCOL nPosX;
316 SCROW nPosY;
317 SCTAB nTab = mrViewData.GetTabNo();
318 mrViewData.GetPosFromPixel( aPosPixel.X(), aPosPixel.Y(), eWhich, nPosX, nPosY );
319 const ScPatternAttr* pPattern = rDoc.GetPattern( nPosX, nPosY, nTab );
320
321 // bForceToTop = sal_False, use the cell's real position
322 aPixRect = mrViewData.GetEditArea( eWhich, nPosX, nPosY, this, pPattern, false );
323 }
324 }
325
326 if ( !aHelpText.isEmpty() )
327 {
328 tools::Rectangle aScreenRect(OutputToScreenPixel(aPixRect.TopLeft()),
329 OutputToScreenPixel(aPixRect.BottomRight()));
330
331 if ( rHEvt.GetMode() & HelpEventMode::BALLOON )
332 Help::ShowBalloon(this,rHEvt.GetMousePosPixel(), aScreenRect, aHelpText);
333 else if ( rHEvt.GetMode() & HelpEventMode::QUICK )
334 Help::ShowQuickHelp(this,aScreenRect, aHelpText);
335
336 bDone = true;
337 }
338 }
339
340 // basic controls
341
342 if ( pDrView && bHelpEnabled && !bDone )
343 {
344 SdrPageView* pPV = pDrView->GetSdrPageView();
345 OSL_ENSURE( pPV, "SdrPageView* is NULL" );
346 if (pPV)
347 bDone = FmFormPage::RequestHelp( this, pDrView, rHEvt );
348 }
349
350 // If QuickHelp for AutoFill is shown, do not allow it to be removed
351
352 if ( nMouseStatus == SC_GM_TABDOWN && mrViewData.GetRefType() == SC_REFTYPE_FILL &&
353 Help::IsQuickHelpEnabled() )
354 bDone = true;
355
356 if (!bDone)
357 Window::RequestHelp( rHEvt );
358 }
359
IsMyModel(const SdrEditView * pSdrView)360 bool ScGridWindow::IsMyModel(const SdrEditView* pSdrView)
361 {
362 return pSdrView &&
363 pSdrView->GetModel() == mrViewData.GetDocument().GetDrawLayer();
364 }
365
HideNoteMarker()366 void ScGridWindow::HideNoteMarker()
367 {
368 mpNoteMarker.reset();
369 }
370
371 css::uno::Reference< css::accessibility::XAccessible >
CreateAccessible()372 ScGridWindow::CreateAccessible()
373 {
374 css::uno::Reference< css::accessibility::XAccessible > xAcc= GetAccessible(false);
375 if (xAcc.is())
376 {
377 return xAcc;
378 }
379
380 rtl::Reference<ScAccessibleDocument> pAccessibleDocument =
381 new ScAccessibleDocument(GetAccessibleParentWindow()->GetAccessible(),
382 mrViewData.GetViewShell(), eWhich);
383 pAccessibleDocument->PreInit();
384
385 xAcc = pAccessibleDocument;
386 SetAccessible(xAcc);
387
388 pAccessibleDocument->Init();
389
390 return xAcc;
391 }
392
393 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
394