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