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