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