xref: /AOO41X/main/sc/source/ui/view/gridwin5.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
30 
31 // INCLUDE ---------------------------------------------------------------
32 
33 #include <editeng/eeitem.hxx>
34 
35 #include <editeng/flditem.hxx>
36 
37 #include <editeng/editview.hxx>
38 #include <svx/svdobj.hxx>
39 #include <svx/svdpagv.hxx>
40 #include <svtools/imapobj.hxx>
41 #include <vcl/cursor.hxx>
42 #include <vcl/help.hxx>
43 #include <tools/urlobj.hxx>
44 #include <sfx2/viewfrm.hxx>
45 
46 #include <unotools/localedatawrapper.hxx>
47 
48 #include "viewuno.hxx"
49 #include "AccessibleDocument.hxx"
50 #include <com/sun/star/accessibility/XAccessible.hpp>
51 
52 #include "gridwin.hxx"
53 #include "viewdata.hxx"
54 #include "drawview.hxx"
55 #include "drwlayer.hxx"
56 #include "drawpage.hxx"
57 #include "document.hxx"
58 #include "notemark.hxx"
59 #include "chgtrack.hxx"
60 #include "chgviset.hxx"
61 #include "dbfunc.hxx"
62 #include "tabvwsh.hxx"
63 #include "userdat.hxx"
64 #include "postit.hxx"
65 
66 // -----------------------------------------------------------------------
67 
68 ScHideTextCursor::ScHideTextCursor( ScViewData* pData, ScSplitPos eW ) :
69 	pViewData(pData),
70 	eWhich(eW)
71 {
72 	Window* pWin = pViewData->GetView()->GetWindowByPos( eWhich );
73 	if (pWin)
74 	{
75 		Cursor* pCur = pWin->GetCursor();
76 		if ( pCur && pCur->IsVisible() )
77 			pCur->Hide();
78 	}
79 }
80 
81 ScHideTextCursor::~ScHideTextCursor()
82 {
83 	Window* pWin = pViewData->GetView()->GetWindowByPos( eWhich );
84 	if (pWin)
85 	{
86 		//	restore text cursor
87 		if ( pViewData->HasEditView(eWhich) && pWin->HasFocus() )
88 			pViewData->GetEditView(eWhich)->ShowCursor( sal_False, sal_True );
89 	}
90 }
91 
92 // -----------------------------------------------------------------------
93 
94 sal_Bool ScGridWindow::ShowNoteMarker( SCsCOL nPosX, SCsROW nPosY, sal_Bool bKeyboard )
95 {
96 	sal_Bool bDone = sal_False;
97 
98 	ScDocument* pDoc = pViewData->GetDocument();
99 	SCTAB		nTab = pViewData->GetTabNo();
100 	ScAddress	aCellPos( nPosX, nPosY, nTab );
101 
102 	String aTrackText;
103 	sal_Bool bLeftEdge = sal_False;
104 
105 	//	Change-Tracking
106 
107 	ScChangeTrack* pTrack = pDoc->GetChangeTrack();
108 	ScChangeViewSettings* pSettings = pDoc->GetChangeViewSettings();
109 	if ( pTrack && pTrack->GetFirst() && pSettings && pSettings->ShowChanges())
110 	{
111 		const ScChangeAction* pFound = NULL;
112 		const ScChangeAction* pFoundContent = NULL;
113 		const ScChangeAction* pFoundMove = NULL;
114 		long nModified = 0;
115 		const ScChangeAction* pAction = pTrack->GetFirst();
116 		while (pAction)
117 		{
118 			if ( pAction->IsVisible() &&
119 				 ScViewUtil::IsActionShown( *pAction, *pSettings, *pDoc ) )
120 			{
121 				ScChangeActionType eType = pAction->GetType();
122 				const ScBigRange& rBig = pAction->GetBigRange();
123 				if ( rBig.aStart.Tab() == nTab )
124 				{
125 					ScRange aRange = rBig.MakeRange();
126 
127 					if ( eType == SC_CAT_DELETE_ROWS )
128 						aRange.aEnd.SetRow( aRange.aStart.Row() );
129 					else if ( eType == SC_CAT_DELETE_COLS )
130 						aRange.aEnd.SetCol( aRange.aStart.Col() );
131 
132 					if ( aRange.In( aCellPos ) )
133 					{
134 						pFound = pAction;		// der letzte gewinnt
135 						switch ( eType )
136 						{
137 							case SC_CAT_CONTENT :
138 								pFoundContent = pAction;
139 							break;
140 							case SC_CAT_MOVE :
141 								pFoundMove = pAction;
142 							break;
143                             default:
144                             {
145                                 // added to avoid warnings
146                             }
147 						}
148 						++nModified;
149 					}
150 				}
151 				if ( eType == SC_CAT_MOVE )
152 				{
153 					ScRange aRange =
154 						((const ScChangeActionMove*)pAction)->
155 						GetFromRange().MakeRange();
156 					if ( aRange.In( aCellPos ) )
157 					{
158 						pFound = pAction;
159 						++nModified;
160 					}
161 				}
162 			}
163 			pAction = pAction->GetNext();
164 		}
165 
166 		if ( pFound )
167 		{
168 			if ( pFoundContent && pFound->GetType() != SC_CAT_CONTENT )
169 				pFound = pFoundContent;		// Content gewinnt
170 			if ( pFoundMove && pFound->GetType() != SC_CAT_MOVE &&
171 					pFoundMove->GetActionNumber() >
172 					pFound->GetActionNumber() )
173 				pFound = pFoundMove;		// Move gewinnt
174 
175 			//	bei geloeschten Spalten: Pfeil auf die linke Seite der Zelle
176 			if ( pFound->GetType() == SC_CAT_DELETE_COLS )
177 				bLeftEdge = sal_True;
178 
179 			DateTime aDT = pFound->GetDateTime();
180 			aTrackText  = pFound->GetUser();
181 			aTrackText.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ", " ));
182             aTrackText += ScGlobal::pLocaleData->getDate(aDT);
183 			aTrackText += ' ';
184             aTrackText += ScGlobal::pLocaleData->getTime(aDT);
185 			aTrackText.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ":\n" ));
186 			String aComStr=pFound->GetComment();
187 			if(aComStr.Len()>0)
188 			{
189 				aTrackText += aComStr;
190 				aTrackText.AppendAscii(RTL_CONSTASCII_STRINGPARAM( "\n( " ));
191 			}
192 			pFound->GetDescription( aTrackText, pDoc );
193 			if(aComStr.Len()>0)
194 			{
195 				aTrackText +=')';
196 			}
197 		}
198 	}
199 
200 	//	Notiz nur, wenn sie nicht schon auf dem Drawing-Layer angezeigt wird:
201 	const ScPostIt* pNote = pDoc->GetNote( aCellPos );
202 	if ( (aTrackText.Len() > 0) || (pNote && !pNote->IsCaptionShown()) )
203 	{
204 		sal_Bool bNew = sal_True;
205 		sal_Bool bFast = sal_False;
206 		if ( pNoteMarker )			// schon eine Notiz angezeigt
207 		{
208 			if ( pNoteMarker->GetDocPos() == aCellPos )	// dieselbe
209 				bNew = sal_False;							// dann stehenlassen
210 			else
211 				bFast = sal_True;							// sonst sofort
212 
213 			//	marker which was shown for ctrl-F1 isn't removed by mouse events
214 			if ( pNoteMarker->IsByKeyboard() && !bKeyboard )
215 				bNew = sal_False;
216 		}
217 		if ( bNew )
218 		{
219 			if ( bKeyboard )
220 				bFast = sal_True;			// keyboard also shows the marker immediately
221 
222 			delete pNoteMarker;
223 
224             bool bHSplit = pViewData->GetHSplitMode() != SC_SPLIT_NONE;
225             bool bVSplit = pViewData->GetVSplitMode() != SC_SPLIT_NONE;
226 
227 			Window* pLeft = pViewData->GetView()->GetWindowByPos( bVSplit ? SC_SPLIT_TOPLEFT : SC_SPLIT_BOTTOMLEFT );
228 			Window* pRight = bHSplit ? pViewData->GetView()->GetWindowByPos( bVSplit ? SC_SPLIT_TOPRIGHT : SC_SPLIT_BOTTOMRIGHT ) : 0;
229 			Window* pBottom = bVSplit ? pViewData->GetView()->GetWindowByPos( SC_SPLIT_BOTTOMLEFT ) : 0;
230 			Window* pDiagonal = (bHSplit && bVSplit) ? pViewData->GetView()->GetWindowByPos( SC_SPLIT_BOTTOMRIGHT ) : 0;
231             DBG_ASSERT( pLeft, "ScGridWindow::ShowNoteMarker - missing top-left grid window" );
232 
233             /*  If caption is shown from right or bottom windows, adjust
234                 mapmode to include size of top-left window. */
235             MapMode aMapMode = GetDrawMapMode( sal_True );
236             Size aLeftSize = pLeft->PixelToLogic( pLeft->GetOutputSizePixel(), aMapMode );
237             Point aOrigin = aMapMode.GetOrigin();
238             if( (this == pRight) || (this == pDiagonal) )
239                 aOrigin.X() += aLeftSize.Width();
240             if( (this == pBottom) || (this == pDiagonal) )
241                 aOrigin.Y() += aLeftSize.Height();
242             aMapMode.SetOrigin( aOrigin );
243 
244 			pNoteMarker = new ScNoteMarker( pLeft, pRight, pBottom, pDiagonal,
245 											pDoc, aCellPos, aTrackText,
246 											aMapMode, bLeftEdge, bFast, bKeyboard );
247 		}
248 
249 		bDone = sal_True;		// something is shown (old or new)
250 	}
251 
252 	return bDone;
253 }
254 
255 // -----------------------------------------------------------------------
256 
257 void ScGridWindow::RequestHelp(const HelpEvent& rHEvt)
258 {
259 	sal_Bool bDone = sal_False;
260 	sal_Bool bHelpEnabled = ( rHEvt.GetMode() & ( HELPMODE_BALLOON | HELPMODE_QUICK ) ) != 0;
261 	SdrView* pDrView = pViewData->GetScDrawView();
262 
263 	sal_Bool bDrawTextEdit = sal_False;
264 	if (pDrView)
265 		bDrawTextEdit = pDrView->IsTextEdit();
266 
267 	//	notes or change tracking
268 
269 	if ( bHelpEnabled && !bDrawTextEdit )
270 	{
271 		Point		aPosPixel = ScreenToOutputPixel( rHEvt.GetMousePosPixel() );
272         SCsCOL nPosX;
273         SCsROW nPosY;
274         pViewData->GetPosFromPixel( aPosPixel.X(), aPosPixel.Y(), eWhich, nPosX, nPosY );
275 
276 		if ( ShowNoteMarker( nPosX, nPosY, sal_False ) )
277 		{
278 			Window::RequestHelp( rHEvt );	// alte Tip/Balloon ausschalten
279 			bDone = sal_True;
280 		}
281 	}
282 
283 	if ( !bDone && pNoteMarker )
284 	{
285 		if ( pNoteMarker->IsByKeyboard() )
286 		{
287 			//	marker which was shown for ctrl-F1 isn't removed by mouse events
288 		}
289 		else
290 			DELETEZ(pNoteMarker);
291 	}
292 
293 	//	Image-Map / Text-URL
294 
295 	if ( bHelpEnabled && !bDone && !nButtonDown )		// nur ohne gedrueckten Button
296 	{
297 		String aHelpText;
298 		Rectangle aPixRect;
299 		Point aPosPixel = ScreenToOutputPixel( rHEvt.GetMousePosPixel() );
300 
301 		if ( pDrView )										// URL / Image-Map
302 		{
303 			SdrViewEvent aVEvt;
304 			MouseEvent aMEvt( aPosPixel, 1, 0, MOUSE_LEFT );
305 			SdrHitKind eHit = pDrView->PickAnything( aMEvt, SDRMOUSEBUTTONDOWN, aVEvt );
306 
307 			if ( eHit != SDRHIT_NONE && aVEvt.pObj != NULL )
308 			{
309 				// URL fuer IMapObject unter Pointer ist Hilfetext
310 				if ( ScDrawLayer::GetIMapInfo( aVEvt.pObj ) )
311 				{
312 					Point aLogicPos = PixelToLogic( aPosPixel );
313 					IMapObject* pIMapObj = ScDrawLayer::GetHitIMapObject(
314 													aVEvt.pObj, aLogicPos, *this );
315 
316 					if ( pIMapObj )
317 					{
318 						//	#44990# Bei ImageMaps die Description anzeigen, wenn vorhanden
319 						aHelpText = pIMapObj->GetAltText();
320 						if (!aHelpText.Len())
321 							aHelpText = pIMapObj->GetURL();
322 						aPixRect = LogicToPixel(aVEvt.pObj->GetLogicRect());
323 					}
324 				}
325                 // URL in shape text or at shape itself (URL in text overrides object URL)
326                 if ( aHelpText.Len() == 0 )
327                 {
328                     if( aVEvt.eEvent == SDREVENT_EXECUTEURL )
329                     {
330                         aHelpText = aVEvt.pURLField->GetURL();
331                         aPixRect = LogicToPixel(aVEvt.pObj->GetLogicRect());
332                     }
333                     else
334                     {
335                         SdrObject* pObj = 0;
336                         SdrPageView* pPV = 0;
337                         Point aMDPos = PixelToLogic( aPosPixel );
338                         if ( pDrView->PickObj(aMDPos, pDrView->getHitTolLog(), pObj, pPV, SDRSEARCH_ALSOONMASTER) )
339                         {
340                             if ( pObj->IsGroupObject() )
341                             {
342                                     SdrObject* pHit = 0;
343                                     if ( pDrView->PickObj(aMDPos, pDrView->getHitTolLog(), pHit, pPV, SDRSEARCH_DEEP ) )
344                                         pObj = pHit;
345                             }
346 #ifdef ISSUE66550_HLINK_FOR_SHAPES
347                             ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( pObj );
348                             if ( pInfo && (pInfo->GetHlink().getLength() > 0) )
349                             {
350                                 aPixRect = LogicToPixel(aVEvt.pObj->GetLogicRect());
351                                 aHelpText = pInfo->GetHlink();
352                             }
353 #endif
354                         }
355                     }
356                 }
357 			}
358 		}
359 
360 		if ( !aHelpText.Len() )									// Text-URL
361 		{
362 			String aUrl;
363 			if ( GetEditUrl( aPosPixel, NULL, &aUrl, NULL ) )
364 			{
365 				aHelpText = INetURLObject::decode( aUrl, INET_HEX_ESCAPE,
366 					INetURLObject::DECODE_UNAMBIGUOUS );
367 
368 				ScDocument* pDoc = pViewData->GetDocument();
369                 SCsCOL nPosX;
370                 SCsROW nPosY;
371                 SCTAB		nTab = pViewData->GetTabNo();
372 				pViewData->GetPosFromPixel( aPosPixel.X(), aPosPixel.Y(), eWhich, nPosX, nPosY );
373 				const ScPatternAttr* pPattern = pDoc->GetPattern( nPosX, nPosY, nTab );
374 
375 				ScHideTextCursor aHideCursor( pViewData, eWhich );		// MapMode is changed in GetEditArea
376 
377 				// bForceToTop = sal_False, use the cell's real position
378 				aPixRect = pViewData->GetEditArea( eWhich, nPosX, nPosY, this, pPattern, sal_False );
379 			}
380 		}
381 
382 		if ( aHelpText.Len() )
383 		{
384 			Rectangle aScreenRect(OutputToScreenPixel(aPixRect.TopLeft()),
385 									OutputToScreenPixel(aPixRect.BottomRight()));
386 
387 			if ( rHEvt.GetMode() & HELPMODE_BALLOON )
388 				Help::ShowBalloon(this,rHEvt.GetMousePosPixel(), aScreenRect, aHelpText);
389 			else if ( rHEvt.GetMode() & HELPMODE_QUICK )
390 				Help::ShowQuickHelp(this,aScreenRect, aHelpText);
391 
392 			bDone = sal_True;
393 		}
394 	}
395 
396 	//	Basic-Controls
397 
398 	if ( pDrView && bHelpEnabled && !bDone )
399 	{
400 		SdrPageView* pPV = pDrView->GetSdrPageView();
401 		DBG_ASSERT( pPV, "SdrPageView* ist NULL" );
402 		if (pPV)
403 			bDone = ((ScDrawPage*)pPV->GetPage())->RequestHelp( this, pDrView, rHEvt );
404 	}
405 
406 	//	Wenn QuickHelp fuer AutoFill angezeigt wird, nicht wieder wegnehmen lassen
407 
408 	if ( nMouseStatus == SC_GM_TABDOWN && pViewData->GetRefType() == SC_REFTYPE_FILL &&
409 			Help::IsQuickHelpEnabled() )
410 		bDone = sal_True;
411 
412 	if (!bDone)
413 		Window::RequestHelp( rHEvt );
414 }
415 
416 sal_Bool ScGridWindow::IsMyModel(SdrEditView* pSdrView)
417 {
418 	return pSdrView &&
419 			pSdrView->GetModel() == pViewData->GetDocument()->GetDrawLayer();
420 }
421 
422 void ScGridWindow::HideNoteMarker()
423 {
424 	DELETEZ(pNoteMarker);
425 }
426 
427 com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
428 	ScGridWindow::CreateAccessible()
429 {
430 	ScAccessibleDocument* pAccessibleDocument =
431 		new ScAccessibleDocument(GetAccessibleParentWindow()->GetAccessible(),
432 			pViewData->GetViewShell(), eWhich);
433 
434 	com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessible > xAccessible = pAccessibleDocument;
435 
436 	pAccessibleDocument->Init();
437 
438 	return xAccessible;
439 }
440