xref: /trunk/main/sc/source/ui/view/gridwin5.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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