Line data Source code
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/eeitem.hxx>
21 :
22 : #include <editeng/flditem.hxx>
23 :
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>
33 :
34 : #include <unotools/localedatawrapper.hxx>
35 : #include <unotools/securityoptions.hxx>
36 :
37 : #include "viewuno.hxx"
38 : #include "AccessibleDocument.hxx"
39 : #include <com/sun/star/accessibility/XAccessible.hpp>
40 :
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"
56 :
57 0 : bool ScGridWindow::ShowNoteMarker( SCsCOL nPosX, SCsROW nPosY, bool bKeyboard )
58 : {
59 0 : bool bDone = false;
60 :
61 0 : ScDocument* pDoc = pViewData->GetDocument();
62 0 : SCTAB nTab = pViewData->GetTabNo();
63 0 : ScAddress aCellPos( nPosX, nPosY, nTab );
64 :
65 0 : OUString aTrackText;
66 0 : bool bLeftEdge = false;
67 :
68 : // Change-Tracking
69 :
70 0 : ScChangeTrack* pTrack = pDoc->GetChangeTrack();
71 0 : ScChangeViewSettings* pSettings = pDoc->GetChangeViewSettings();
72 0 : if ( pTrack && pTrack->GetFirst() && pSettings && pSettings->ShowChanges())
73 : {
74 0 : const ScChangeAction* pFound = NULL;
75 0 : const ScChangeAction* pFoundContent = NULL;
76 0 : const ScChangeAction* pFoundMove = NULL;
77 0 : long nModified = 0;
78 0 : const ScChangeAction* pAction = pTrack->GetFirst();
79 0 : while (pAction)
80 : {
81 0 : if ( pAction->IsVisible() &&
82 0 : ScViewUtil::IsActionShown( *pAction, *pSettings, *pDoc ) )
83 : {
84 0 : ScChangeActionType eType = pAction->GetType();
85 0 : const ScBigRange& rBig = pAction->GetBigRange();
86 0 : if ( rBig.aStart.Tab() == nTab )
87 : {
88 0 : ScRange aRange = rBig.MakeRange();
89 :
90 0 : if ( eType == SC_CAT_DELETE_ROWS )
91 0 : aRange.aEnd.SetRow( aRange.aStart.Row() );
92 0 : else if ( eType == SC_CAT_DELETE_COLS )
93 0 : aRange.aEnd.SetCol( aRange.aStart.Col() );
94 :
95 0 : if ( aRange.In( aCellPos ) )
96 : {
97 0 : pFound = pAction; // der letzte gewinnt
98 0 : switch ( eType )
99 : {
100 : case SC_CAT_CONTENT :
101 0 : pFoundContent = pAction;
102 0 : break;
103 : case SC_CAT_MOVE :
104 0 : pFoundMove = pAction;
105 0 : break;
106 : default:
107 : {
108 : // added to avoid warnings
109 : }
110 : }
111 0 : ++nModified;
112 : }
113 : }
114 0 : if ( eType == SC_CAT_MOVE )
115 : {
116 : ScRange aRange =
117 : static_cast<const ScChangeActionMove*>(pAction)->
118 0 : GetFromRange().MakeRange();
119 0 : if ( aRange.In( aCellPos ) )
120 : {
121 0 : pFound = pAction;
122 0 : ++nModified;
123 : }
124 : }
125 : }
126 0 : pAction = pAction->GetNext();
127 : }
128 :
129 0 : if ( pFound )
130 : {
131 0 : if ( pFoundContent && pFound->GetType() != SC_CAT_CONTENT )
132 0 : pFound = pFoundContent; // Content gewinnt
133 0 : if ( pFoundMove && pFound->GetType() != SC_CAT_MOVE &&
134 0 : pFoundMove->GetActionNumber() >
135 0 : pFound->GetActionNumber() )
136 0 : pFound = pFoundMove; // Move gewinnt
137 :
138 : // bei geloeschten Spalten: Pfeil auf die linke Seite der Zelle
139 0 : if ( pFound->GetType() == SC_CAT_DELETE_COLS )
140 0 : bLeftEdge = true;
141 :
142 0 : DateTime aDT = pFound->GetDateTime();
143 0 : aTrackText = pFound->GetUser();
144 0 : aTrackText += ", ";
145 0 : aTrackText += ScGlobal::pLocaleData->getDate(aDT);
146 0 : aTrackText += " ";
147 0 : aTrackText += ScGlobal::pLocaleData->getTime(aDT);
148 0 : aTrackText += ":\n";
149 0 : OUString aComStr=pFound->GetComment();
150 0 : if(!aComStr.isEmpty())
151 : {
152 0 : aTrackText += aComStr;
153 0 : aTrackText += "\n( ";
154 : }
155 0 : OUString aTmp;
156 0 : pFound->GetDescription(aTmp, pDoc);
157 0 : aTrackText += aTmp;
158 0 : if(!aComStr.isEmpty())
159 : {
160 0 : aTrackText += ")";
161 0 : }
162 : }
163 : }
164 :
165 : // Notiz nur, wenn sie nicht schon auf dem Drawing-Layer angezeigt wird:
166 0 : const ScPostIt* pNote = pDoc->GetNote( aCellPos );
167 0 : if ( (!aTrackText.isEmpty()) || (pNote && !pNote->IsCaptionShown()) )
168 : {
169 0 : bool bNew = true;
170 0 : bool bFast = false;
171 0 : if (mpNoteMarker) // schon eine Notiz angezeigt
172 : {
173 0 : if (mpNoteMarker->GetDocPos() == aCellPos)
174 0 : bNew = false; // dann stehenlassen
175 : else
176 0 : bFast = true; // sonst sofort
177 :
178 : // marker which was shown for ctrl-F1 isn't removed by mouse events
179 0 : if (mpNoteMarker->IsByKeyboard() && !bKeyboard)
180 0 : bNew = false;
181 : }
182 0 : if (bNew)
183 : {
184 0 : if (bKeyboard)
185 0 : bFast = true; // keyboard also shows the marker immediately
186 :
187 0 : mpNoteMarker.reset();
188 :
189 0 : bool bHSplit = pViewData->GetHSplitMode() != SC_SPLIT_NONE;
190 0 : bool bVSplit = pViewData->GetVSplitMode() != SC_SPLIT_NONE;
191 :
192 0 : vcl::Window* pLeft = pViewData->GetView()->GetWindowByPos( bVSplit ? SC_SPLIT_TOPLEFT : SC_SPLIT_BOTTOMLEFT );
193 0 : vcl::Window* pRight = bHSplit ? pViewData->GetView()->GetWindowByPos( bVSplit ? SC_SPLIT_TOPRIGHT : SC_SPLIT_BOTTOMRIGHT ) : 0;
194 0 : vcl::Window* pBottom = bVSplit ? pViewData->GetView()->GetWindowByPos( SC_SPLIT_BOTTOMLEFT ) : 0;
195 0 : vcl::Window* pDiagonal = (bHSplit && bVSplit) ? pViewData->GetView()->GetWindowByPos( SC_SPLIT_BOTTOMRIGHT ) : 0;
196 : OSL_ENSURE( pLeft, "ScGridWindow::ShowNoteMarker - missing top-left grid window" );
197 :
198 : /* If caption is shown from right or bottom windows, adjust
199 : mapmode to include size of top-left window. */
200 0 : MapMode aMapMode = GetDrawMapMode( true );
201 0 : Size aLeftSize = pLeft->PixelToLogic( pLeft->GetOutputSizePixel(), aMapMode );
202 0 : Point aOrigin = aMapMode.GetOrigin();
203 0 : if( (this == pRight) || (this == pDiagonal) )
204 0 : aOrigin.X() += aLeftSize.Width();
205 0 : if( (this == pBottom) || (this == pDiagonal) )
206 0 : aOrigin.Y() += aLeftSize.Height();
207 0 : aMapMode.SetOrigin( aOrigin );
208 :
209 : mpNoteMarker.reset(new ScNoteMarker(pLeft, pRight, pBottom, pDiagonal,
210 : pDoc, aCellPos, aTrackText,
211 0 : aMapMode, bLeftEdge, bFast, bKeyboard));
212 0 : if ( pViewData->GetScDrawView() )
213 : {
214 : // get position for aCellPos
215 : // get draw position in hmm for aCellPos
216 0 : Point aOldPos( pDoc->GetColOffset( aCellPos.Col(), aCellPos.Tab() ), pDoc->GetRowOffset( aCellPos.Row(), aCellPos.Tab() ) );
217 0 : aOldPos.X() = sc::TwipsToHMM( aOldPos.X() );
218 0 : aOldPos.Y() = sc::TwipsToHMM( aOldPos.Y() );
219 : // get screen pos in hmm for aCellPos
220 : // and equiv screen pos
221 0 : Point aScreenPos = pViewData->GetScrPos( aCellPos.Col(), aCellPos.Row(), eWhich, true );
222 0 : MapMode aDrawMode = GetDrawMapMode();
223 0 : Point aCurPosHmm = PixelToLogic(aScreenPos, aDrawMode );
224 0 : Point aGridOff = aCurPosHmm -aOldPos;
225 : // fdo#63323 fix the X Position for the showing comment when
226 : // the mouse over the cell when the sheet are RTL
227 0 : if ( pDoc->IsNegativePage(nTab))
228 0 : aGridOff.setX(aCurPosHmm.getX() + aOldPos.getX());
229 0 : mpNoteMarker->SetGridOff( aGridOff );
230 0 : }
231 : }
232 :
233 0 : bDone = true; // something is shown (old or new)
234 : }
235 :
236 0 : return bDone;
237 : }
238 :
239 0 : void ScGridWindow::RequestHelp(const HelpEvent& rHEvt)
240 : {
241 : //To know whether to prefix STR_CTRLCLICKHYERLINK or STR_CLICKHYPERLINK
242 : //to hyperlink tooltips/help text
243 0 : SvtSecurityOptions aSecOpt;
244 0 : bool bCtrlClickHlink = aSecOpt.IsOptionSet( SvtSecurityOptions::E_CTRLCLICK_HYPERLINK );
245 : //Global string STR_CTRLCLICKHYPERLINK i.e,
246 : // "ctrl-click to follow link:" for not MacOS
247 : // "⌘-click to follow link:" for MacOs
248 0 : vcl::KeyCode aCode( KEY_SPACE );
249 0 : vcl::KeyCode aModifiedCode( KEY_SPACE, KEY_MOD1 );
250 0 : OUString aModStr( aModifiedCode.GetName() );
251 0 : aModStr = aModStr.replaceFirst(aCode.GetName(), OUString());
252 0 : aModStr = aModStr.replaceAll("+", OUString());
253 0 : OUString aCtrlClickHlinkStr = ScGlobal::GetRscString( STR_CTRLCLICKHYPERLINK );
254 :
255 0 : aCtrlClickHlinkStr = aCtrlClickHlinkStr.replaceAll("%s", aModStr);
256 : //Global string STR_CLICKHYPERLINK i.e, "click to open hyperlink"
257 0 : OUString aClickHlinkStr = ScGlobal::GetRscString( STR_CLICKHYPERLINK );
258 0 : bool bDone = false;
259 0 : bool bHelpEnabled = bool(rHEvt.GetMode() & ( HelpEventMode::BALLOON | HelpEventMode::QUICK ));
260 0 : SdrView* pDrView = pViewData->GetScDrawView();
261 0 : bool bDrawTextEdit = false;
262 0 : if (pDrView)
263 0 : bDrawTextEdit = pDrView->IsTextEdit();
264 : // notes or change tracking
265 0 : if ( bHelpEnabled && !bDrawTextEdit )
266 : {
267 0 : Point aPosPixel = ScreenToOutputPixel( rHEvt.GetMousePosPixel() );
268 : SCsCOL nPosX;
269 : SCsROW nPosY;
270 0 : pViewData->GetPosFromPixel( aPosPixel.X(), aPosPixel.Y(), eWhich, nPosX, nPosY );
271 :
272 0 : if ( ShowNoteMarker( nPosX, nPosY, false ) )
273 : {
274 0 : Window::RequestHelp( rHEvt ); // alte Tip/Balloon ausschalten
275 0 : bDone = true;
276 : }
277 : }
278 :
279 0 : if (!bDone && mpNoteMarker)
280 : {
281 0 : if (mpNoteMarker->IsByKeyboard())
282 : {
283 : // marker which was shown for ctrl-F1 isn't removed by mouse events
284 : }
285 : else
286 : {
287 0 : mpNoteMarker.reset();
288 : }
289 : }
290 :
291 : // Image-Map / Text-URL
292 :
293 0 : if ( bHelpEnabled && !bDone && !nButtonDown ) // nur ohne gedrueckten Button
294 : {
295 0 : OUString aHelpText;
296 0 : Rectangle aPixRect;
297 0 : Point aPosPixel = ScreenToOutputPixel( rHEvt.GetMousePosPixel() );
298 :
299 0 : if ( pDrView ) // URL / Image-Map
300 : {
301 0 : SdrViewEvent aVEvt;
302 0 : MouseEvent aMEvt( aPosPixel, 1, MouseEventModifiers::NONE, MOUSE_LEFT );
303 0 : SdrHitKind eHit = pDrView->PickAnything( aMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt );
304 :
305 0 : if ( eHit != SDRHIT_NONE && aVEvt.pObj != NULL )
306 : {
307 : // URL fuer IMapObject unter Pointer ist Hilfetext
308 0 : if ( ScDrawLayer::GetIMapInfo( aVEvt.pObj ) )
309 : {
310 0 : Point aLogicPos = PixelToLogic( aPosPixel );
311 : IMapObject* pIMapObj = ScDrawLayer::GetHitIMapObject(
312 0 : aVEvt.pObj, aLogicPos, *this );
313 :
314 0 : if ( pIMapObj )
315 : {
316 : // Bei ImageMaps die Description anzeigen, wenn vorhanden
317 0 : aHelpText = pIMapObj->GetAltText();
318 0 : if (aHelpText.isEmpty())
319 0 : aHelpText = pIMapObj->GetURL();
320 0 : if( bCtrlClickHlink )
321 : {
322 : //prefix STR_CTRLCLICKHYPERLINK to aHelpText
323 0 : aHelpText = aCtrlClickHlinkStr + aHelpText;
324 : }
325 : else
326 : {
327 : //Option not set, so prefix STR_CLICKHYPERLINK
328 0 : aHelpText = aClickHlinkStr + aHelpText;
329 : }
330 0 : aPixRect = LogicToPixel(aVEvt.pObj->GetLogicRect());
331 : }
332 : }
333 : // URL in shape text or at shape itself (URL in text overrides object URL)
334 0 : if ( aHelpText.isEmpty() )
335 : {
336 0 : if( aVEvt.eEvent == SDREVENT_EXECUTEURL )
337 : {
338 0 : aHelpText = aVEvt.pURLField->GetURL();
339 0 : aPixRect = LogicToPixel(aVEvt.pObj->GetLogicRect());
340 : }
341 : else
342 : {
343 0 : SdrObject* pObj = 0;
344 0 : SdrPageView* pPV = 0;
345 0 : Point aMDPos = PixelToLogic( aPosPixel );
346 0 : if ( pDrView->PickObj(aMDPos, pDrView->getHitTolLog(), pObj, pPV, SdrSearchOptions::ALSOONMASTER) )
347 : {
348 0 : if ( pObj->IsGroupObject() )
349 : {
350 0 : SdrObject* pHit = 0;
351 0 : if ( pDrView->PickObj(aMDPos, pDrView->getHitTolLog(), pHit, pPV, SdrSearchOptions::DEEP ) )
352 0 : pObj = pHit;
353 : }
354 0 : ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( pObj );
355 0 : if ( pInfo && (pInfo->GetHlink().getLength() > 0) )
356 : {
357 0 : aPixRect = LogicToPixel(aVEvt.pObj->GetLogicRect());
358 0 : aHelpText = pInfo->GetHlink();
359 0 : if( bCtrlClickHlink )
360 : {
361 : //prefix STR_CTRLCLICKHYPERLINK to aHelpText
362 0 : aHelpText = aCtrlClickHlinkStr + aHelpText;
363 : }
364 : else
365 : {
366 : //Option not set, so prefix STR_CLICKHYPERLINK
367 0 : aHelpText = aClickHlinkStr + aHelpText;
368 : }
369 :
370 : }
371 : }
372 : }
373 : }
374 0 : }
375 : }
376 :
377 0 : if ( aHelpText.isEmpty() ) // Text-URL
378 : {
379 0 : OUString aUrl;
380 0 : if ( GetEditUrl( aPosPixel, NULL, &aUrl, NULL ) )
381 : {
382 0 : aHelpText = INetURLObject::decode( aUrl,
383 0 : INetURLObject::DECODE_UNAMBIGUOUS );
384 :
385 0 : if( bCtrlClickHlink )
386 : {
387 : //prefix STR_CTRLCLICKHYPERLINK to aHelpText
388 0 : aHelpText = aCtrlClickHlinkStr + aHelpText;
389 : }
390 : else
391 : {
392 : //Option not set, so prefix STR_CLICKHYPERLINK
393 0 : aHelpText = aClickHlinkStr + aHelpText;
394 : }
395 :
396 0 : ScDocument* pDoc = pViewData->GetDocument();
397 : SCsCOL nPosX;
398 : SCsROW nPosY;
399 0 : SCTAB nTab = pViewData->GetTabNo();
400 0 : pViewData->GetPosFromPixel( aPosPixel.X(), aPosPixel.Y(), eWhich, nPosX, nPosY );
401 0 : const ScPatternAttr* pPattern = pDoc->GetPattern( nPosX, nPosY, nTab );
402 :
403 : // bForceToTop = sal_False, use the cell's real position
404 0 : aPixRect = pViewData->GetEditArea( eWhich, nPosX, nPosY, this, pPattern, false );
405 0 : }
406 : }
407 :
408 0 : if ( !aHelpText.isEmpty() )
409 : {
410 0 : Rectangle aScreenRect(OutputToScreenPixel(aPixRect.TopLeft()),
411 0 : OutputToScreenPixel(aPixRect.BottomRight()));
412 :
413 0 : if ( rHEvt.GetMode() & HelpEventMode::BALLOON )
414 0 : Help::ShowBalloon(this,rHEvt.GetMousePosPixel(), aScreenRect, aHelpText);
415 0 : else if ( rHEvt.GetMode() & HelpEventMode::QUICK )
416 0 : Help::ShowQuickHelp(this,aScreenRect, aHelpText);
417 :
418 0 : bDone = true;
419 0 : }
420 : }
421 :
422 : // Basic-Controls
423 :
424 0 : if ( pDrView && bHelpEnabled && !bDone )
425 : {
426 0 : SdrPageView* pPV = pDrView->GetSdrPageView();
427 : OSL_ENSURE( pPV, "SdrPageView* ist NULL" );
428 0 : if (pPV)
429 0 : bDone = FmFormPage::RequestHelp( this, pDrView, rHEvt );
430 : }
431 :
432 : // Wenn QuickHelp fuer AutoFill angezeigt wird, nicht wieder wegnehmen lassen
433 :
434 0 : if ( nMouseStatus == SC_GM_TABDOWN && pViewData->GetRefType() == SC_REFTYPE_FILL &&
435 0 : Help::IsQuickHelpEnabled() )
436 0 : bDone = true;
437 :
438 0 : if (!bDone)
439 0 : Window::RequestHelp( rHEvt );
440 0 : }
441 :
442 0 : bool ScGridWindow::IsMyModel(SdrEditView* pSdrView)
443 : {
444 0 : return pSdrView &&
445 0 : pSdrView->GetModel() == pViewData->GetDocument()->GetDrawLayer();
446 : }
447 :
448 10475 : void ScGridWindow::HideNoteMarker()
449 : {
450 10475 : mpNoteMarker.reset();
451 10475 : }
452 :
453 : com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
454 2 : ScGridWindow::CreateAccessible()
455 : {
456 2 : com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > xAcc= GetAccessible(false);
457 2 : if (xAcc.is())
458 : {
459 0 : return xAcc;
460 : }
461 :
462 : ScAccessibleDocument* pAccessibleDocument =
463 : new ScAccessibleDocument(GetAccessibleParentWindow()->GetAccessible(),
464 2 : pViewData->GetViewShell(), eWhich);
465 :
466 2 : xAcc = pAccessibleDocument;
467 2 : SetAccessible(xAcc);
468 :
469 2 : pAccessibleDocument->Init();
470 :
471 2 : return xAcc;
472 156 : }
473 :
474 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|