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 #include <vcl/svapp.hxx> 62 63 // ----------------------------------------------------------------------- 64 65 ScHideTextCursor::ScHideTextCursor( ScViewData* pData, ScSplitPos eW ) : 66 pViewData(pData), 67 eWhich(eW) 68 { 69 Window* pWin = pViewData->GetView()->GetWindowByPos( eWhich ); 70 if (pWin) 71 { 72 Cursor* pCur = pWin->GetCursor(); 73 if ( pCur && pCur->IsVisible() ) 74 pCur->Hide(); 75 } 76 } 77 78 ScHideTextCursor::~ScHideTextCursor() 79 { 80 Window* pWin = pViewData->GetView()->GetWindowByPos( eWhich ); 81 if (pWin) 82 { 83 // restore text cursor 84 if ( pViewData->HasEditView(eWhich) && pWin->HasFocus() ) 85 pViewData->GetEditView(eWhich)->ShowCursor( sal_False, sal_True ); 86 } 87 } 88 89 // ----------------------------------------------------------------------- 90 91 sal_Bool ScGridWindow::ShowNoteMarker( SCsCOL nPosX, SCsROW nPosY, sal_Bool bKeyboard ) 92 { 93 sal_Bool bDone = sal_False; 94 95 ScDocument* pDoc = pViewData->GetDocument(); 96 SCTAB nTab = pViewData->GetTabNo(); 97 ScAddress aCellPos( nPosX, nPosY, nTab ); 98 99 String aTrackText; 100 sal_Bool bLeftEdge = sal_False; 101 102 // Change-Tracking 103 104 ScChangeTrack* pTrack = pDoc->GetChangeTrack(); 105 ScChangeViewSettings* pSettings = pDoc->GetChangeViewSettings(); 106 if ( pTrack && pTrack->GetFirst() && pSettings && pSettings->ShowChanges()) 107 { 108 const ScChangeAction* pFound = NULL; 109 const ScChangeAction* pFoundContent = NULL; 110 const ScChangeAction* pFoundMove = NULL; 111 long nModified = 0; 112 const ScChangeAction* pAction = pTrack->GetFirst(); 113 while (pAction) 114 { 115 if ( pAction->IsVisible() && 116 ScViewUtil::IsActionShown( *pAction, *pSettings, *pDoc ) ) 117 { 118 ScChangeActionType eType = pAction->GetType(); 119 const ScBigRange& rBig = pAction->GetBigRange(); 120 if ( rBig.aStart.Tab() == nTab ) 121 { 122 ScRange aRange = rBig.MakeRange(); 123 124 if ( eType == SC_CAT_DELETE_ROWS ) 125 aRange.aEnd.SetRow( aRange.aStart.Row() ); 126 else if ( eType == SC_CAT_DELETE_COLS ) 127 aRange.aEnd.SetCol( aRange.aStart.Col() ); 128 129 if ( aRange.In( aCellPos ) ) 130 { 131 pFound = pAction; // der letzte gewinnt 132 switch ( eType ) 133 { 134 case SC_CAT_CONTENT : 135 pFoundContent = pAction; 136 break; 137 case SC_CAT_MOVE : 138 pFoundMove = pAction; 139 break; 140 default: 141 { 142 // added to avoid warnings 143 } 144 } 145 ++nModified; 146 } 147 } 148 if ( eType == SC_CAT_MOVE ) 149 { 150 ScRange aRange = 151 ((const ScChangeActionMove*)pAction)-> 152 GetFromRange().MakeRange(); 153 if ( aRange.In( aCellPos ) ) 154 { 155 pFound = pAction; 156 ++nModified; 157 } 158 } 159 } 160 pAction = pAction->GetNext(); 161 } 162 163 if ( pFound ) 164 { 165 if ( pFoundContent && pFound->GetType() != SC_CAT_CONTENT ) 166 pFound = pFoundContent; // Content gewinnt 167 if ( pFoundMove && pFound->GetType() != SC_CAT_MOVE && 168 pFoundMove->GetActionNumber() > 169 pFound->GetActionNumber() ) 170 pFound = pFoundMove; // Move gewinnt 171 172 // bei geloeschten Spalten: Pfeil auf die linke Seite der Zelle 173 if ( pFound->GetType() == SC_CAT_DELETE_COLS ) 174 bLeftEdge = sal_True; 175 176 DateTime aDT = pFound->GetDateTime(); 177 aTrackText = pFound->GetUser(); 178 aTrackText.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ", " )); 179 aTrackText += ScGlobal::pLocaleData->getDate(aDT); 180 aTrackText += ' '; 181 aTrackText += ScGlobal::pLocaleData->getTime(aDT); 182 aTrackText.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ":\n" )); 183 String aComStr=pFound->GetComment(); 184 if(aComStr.Len()>0) 185 { 186 aTrackText += aComStr; 187 aTrackText.AppendAscii(RTL_CONSTASCII_STRINGPARAM( "\n( " )); 188 } 189 pFound->GetDescription( aTrackText, pDoc ); 190 if(aComStr.Len()>0) 191 { 192 aTrackText +=')'; 193 } 194 } 195 } 196 197 // Notiz nur, wenn sie nicht schon auf dem Drawing-Layer angezeigt wird: 198 const ScPostIt* pNote = pDoc->GetNote( aCellPos ); 199 if ( (aTrackText.Len() > 0) || (pNote && !pNote->IsCaptionShown()) ) 200 { 201 sal_Bool bNew = sal_True; 202 sal_Bool bFast = sal_False; 203 if ( pNoteMarker ) // schon eine Notiz angezeigt 204 { 205 if ( pNoteMarker->GetDocPos() == aCellPos ) // dieselbe 206 bNew = sal_False; // dann stehenlassen 207 else 208 bFast = sal_True; // sonst sofort 209 210 // marker which was shown for ctrl-F1 isn't removed by mouse events 211 if ( pNoteMarker->IsByKeyboard() && !bKeyboard ) 212 bNew = sal_False; 213 } 214 if ( bNew ) 215 { 216 if ( bKeyboard ) 217 bFast = sal_True; // keyboard also shows the marker immediately 218 219 delete pNoteMarker; 220 221 bool bHSplit = pViewData->GetHSplitMode() != SC_SPLIT_NONE; 222 bool bVSplit = pViewData->GetVSplitMode() != SC_SPLIT_NONE; 223 224 Window* pLeft = pViewData->GetView()->GetWindowByPos( bVSplit ? SC_SPLIT_TOPLEFT : SC_SPLIT_BOTTOMLEFT ); 225 Window* pRight = bHSplit ? pViewData->GetView()->GetWindowByPos( bVSplit ? SC_SPLIT_TOPRIGHT : SC_SPLIT_BOTTOMRIGHT ) : 0; 226 Window* pBottom = bVSplit ? pViewData->GetView()->GetWindowByPos( SC_SPLIT_BOTTOMLEFT ) : 0; 227 Window* pDiagonal = (bHSplit && bVSplit) ? pViewData->GetView()->GetWindowByPos( SC_SPLIT_BOTTOMRIGHT ) : 0; 228 DBG_ASSERT( pLeft, "ScGridWindow::ShowNoteMarker - missing top-left grid window" ); 229 230 /* If caption is shown from right or bottom windows, adjust 231 mapmode to include size of top-left window. */ 232 MapMode aMapMode = GetDrawMapMode( sal_True ); 233 Size aLeftSize = pLeft->PixelToLogic( pLeft->GetOutputSizePixel(), aMapMode ); 234 Point aOrigin = aMapMode.GetOrigin(); 235 if( (this == pRight) || (this == pDiagonal) ) 236 aOrigin.X() += aLeftSize.Width(); 237 if( (this == pBottom) || (this == pDiagonal) ) 238 aOrigin.Y() += aLeftSize.Height(); 239 aMapMode.SetOrigin( aOrigin ); 240 241 pNoteMarker = new ScNoteMarker( pLeft, pRight, pBottom, pDiagonal, 242 pDoc, aCellPos, aTrackText, 243 aMapMode, bLeftEdge, bFast, bKeyboard ); 244 } 245 246 bDone = sal_True; // something is shown (old or new) 247 } 248 249 return bDone; 250 } 251 252 // ----------------------------------------------------------------------- 253 254 void ScGridWindow::RequestHelp(const HelpEvent& rHEvt) 255 { 256 sal_Bool bDone = sal_False; 257 sal_Bool bHelpEnabled = ( rHEvt.GetMode() & ( HELPMODE_BALLOON | HELPMODE_QUICK ) ) != 0; 258 SdrView* pDrView = pViewData->GetScDrawView(); 259 260 sal_Bool bDrawTextEdit = sal_False; 261 if (pDrView) 262 bDrawTextEdit = pDrView->IsTextEdit(); 263 264 // notes or change tracking 265 266 if ( bHelpEnabled && !bDrawTextEdit ) 267 { 268 Point aPosPixel = ScreenToOutputPixel( rHEvt.GetMousePosPixel() ); 269 SCsCOL nPosX; 270 SCsROW nPosY; 271 pViewData->GetPosFromPixel( aPosPixel.X(), aPosPixel.Y(), eWhich, nPosX, nPosY ); 272 273 if ( ShowNoteMarker( nPosX, nPosY, sal_False ) ) 274 { 275 Window::RequestHelp( rHEvt ); // alte Tip/Balloon ausschalten 276 bDone = sal_True; 277 } 278 } 279 280 if ( !bDone && pNoteMarker ) 281 { 282 if ( pNoteMarker->IsByKeyboard() ) 283 { 284 // marker which was shown for ctrl-F1 isn't removed by mouse events 285 } 286 else 287 DELETEZ(pNoteMarker); 288 } 289 290 // Image-Map / Text-URL 291 292 if ( bHelpEnabled && !bDone && !nButtonDown ) // nur ohne gedrueckten Button 293 { 294 String aHelpText; 295 Rectangle aPixRect; 296 Point aPosPixel = ScreenToOutputPixel( rHEvt.GetMousePosPixel() ); 297 298 if ( pDrView ) // URL / Image-Map 299 { 300 SdrViewEvent aVEvt; 301 MouseEvent aMEvt( aPosPixel, 1, 0, MOUSE_LEFT ); 302 SdrHitKind eHit = pDrView->PickAnything( aMEvt, SDRMOUSEBUTTONDOWN, aVEvt ); 303 304 if ( eHit != SDRHIT_NONE && aVEvt.pObj != NULL ) 305 { 306 // URL fuer IMapObject unter Pointer ist Hilfetext 307 if ( ScDrawLayer::GetIMapInfo( aVEvt.pObj ) ) 308 { 309 Point aLogicPos = PixelToLogic( aPosPixel ); 310 IMapObject* pIMapObj = ScDrawLayer::GetHitIMapObject( 311 aVEvt.pObj, aLogicPos, *this ); 312 313 if ( pIMapObj ) 314 { 315 // #44990# Bei ImageMaps die Description anzeigen, wenn vorhanden 316 aHelpText = pIMapObj->GetAltText(); 317 if (!aHelpText.Len()) 318 aHelpText = pIMapObj->GetURL(); 319 aPixRect = LogicToPixel(aVEvt.pObj->GetLogicRect()); 320 } 321 } 322 // URL in shape text or at shape itself (URL in text overrides object URL) 323 if ( aHelpText.Len() == 0 ) 324 { 325 if( aVEvt.eEvent == SDREVENT_EXECUTEURL ) 326 { 327 aHelpText = aVEvt.pURLField->GetURL(); 328 aPixRect = LogicToPixel(aVEvt.pObj->GetLogicRect()); 329 } 330 else 331 { 332 SdrObject* pObj = 0; 333 SdrPageView* pPV = 0; 334 Point aMDPos = PixelToLogic( aPosPixel ); 335 if ( pDrView->PickObj(aMDPos, pDrView->getHitTolLog(), pObj, pPV, SDRSEARCH_ALSOONMASTER) ) 336 { 337 if ( pObj->IsGroupObject() ) 338 { 339 SdrObject* pHit = 0; 340 if ( pDrView->PickObj(aMDPos, pDrView->getHitTolLog(), pHit, pPV, SDRSEARCH_DEEP ) ) 341 pObj = pHit; 342 } 343 #ifdef ISSUE66550_HLINK_FOR_SHAPES 344 ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( pObj ); 345 if ( pInfo && (pInfo->GetHlink().getLength() > 0) ) 346 { 347 aPixRect = LogicToPixel(aVEvt.pObj->GetLogicRect()); 348 aHelpText = pInfo->GetHlink(); 349 } 350 #endif 351 } 352 } 353 } 354 } 355 } 356 357 if ( !aHelpText.Len() ) // Text-URL 358 { 359 String aUrl; 360 if ( GetEditUrl( aPosPixel, NULL, &aUrl, NULL ) ) 361 { 362 aHelpText = INetURLObject::decode( aUrl, INET_HEX_ESCAPE, 363 INetURLObject::DECODE_UNAMBIGUOUS ); 364 365 ScDocument* pDoc = pViewData->GetDocument(); 366 SCsCOL nPosX; 367 SCsROW nPosY; 368 SCTAB nTab = pViewData->GetTabNo(); 369 pViewData->GetPosFromPixel( aPosPixel.X(), aPosPixel.Y(), eWhich, nPosX, nPosY ); 370 const ScPatternAttr* pPattern = pDoc->GetPattern( nPosX, nPosY, nTab ); 371 372 ScHideTextCursor aHideCursor( pViewData, eWhich ); // MapMode is changed in GetEditArea 373 374 // bForceToTop = sal_False, use the cell's real position 375 aPixRect = pViewData->GetEditArea( eWhich, nPosX, nPosY, this, pPattern, sal_False ); 376 } 377 } 378 379 if ( aHelpText.Len() ) 380 { 381 Rectangle aScreenRect(OutputToScreenPixel(aPixRect.TopLeft()), 382 OutputToScreenPixel(aPixRect.BottomRight())); 383 384 if ( rHEvt.GetMode() & HELPMODE_BALLOON ) 385 Help::ShowBalloon(this,rHEvt.GetMousePosPixel(), aScreenRect, aHelpText); 386 else if ( rHEvt.GetMode() & HELPMODE_QUICK ) 387 Help::ShowQuickHelp(this,aScreenRect, aHelpText); 388 389 bDone = sal_True; 390 } 391 } 392 393 // Basic-Controls 394 395 if ( pDrView && bHelpEnabled && !bDone ) 396 { 397 SdrPageView* pPV = pDrView->GetSdrPageView(); 398 DBG_ASSERT( pPV, "SdrPageView* ist NULL" ); 399 if (pPV) 400 bDone = ((ScDrawPage*)pPV->GetPage())->RequestHelp( this, pDrView, rHEvt ); 401 } 402 403 // Wenn QuickHelp fuer AutoFill angezeigt wird, nicht wieder wegnehmen lassen 404 405 if ( nMouseStatus == SC_GM_TABDOWN && pViewData->GetRefType() == SC_REFTYPE_FILL && 406 Help::IsQuickHelpEnabled() ) 407 bDone = sal_True; 408 409 if (!bDone) 410 Window::RequestHelp( rHEvt ); 411 } 412 413 sal_Bool ScGridWindow::IsMyModel(SdrEditView* pSdrView) 414 { 415 return pSdrView && 416 pSdrView->GetModel() == pViewData->GetDocument()->GetDrawLayer(); 417 } 418 419 void ScGridWindow::HideNoteMarker() 420 { 421 DELETEZ(pNoteMarker); 422 } 423 424 com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > 425 ScGridWindow::CreateAccessible() 426 { 427 com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > xAcc= GetAccessible(sal_False); 428 if (xAcc.is()) 429 { 430 return xAcc; 431 } 432 ScAccessibleDocument* pAccessibleDocument = 433 new ScAccessibleDocument(GetAccessibleParentWindow()->GetAccessible(), 434 pViewData->GetViewShell(), eWhich); 435 //com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessible > xAccessible = pAccessibleDocument; 436 xAcc = pAccessibleDocument; 437 SetAccessible(xAcc); 438 439 pAccessibleDocument->Init(); 440 //return xAccessible; 441 return xAcc; 442 } 443 // MT: Removed Windows::SwitchView() introduced with IA2 CWS. 444 // There are other notifications for this when the active view has chnaged, so please update the code to use that event mechanism 445 void ScGridWindow::SwitchView() 446 { 447 if (!Application::IsAccessibilityEnabled()) 448 { 449 return ; 450 } 451 ScAccessibleDocumentBase* pAccDoc = static_cast<ScAccessibleDocumentBase*>(GetAccessible(sal_False).get()); 452 if (pAccDoc) 453 { 454 pAccDoc->SwitchViewFireFocus(); 455 } 456 } 457 458