/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include bool ScGridWindow::ShowNoteMarker( SCCOL nPosX, SCROW nPosY, bool bKeyboard ) { bool bDone = false; ScDocument& rDoc = mrViewData.GetDocument(); SCTAB nTab = mrViewData.GetTabNo(); ScAddress aCellPos( nPosX, nPosY, nTab ); OUString aTrackText; bool bLeftEdge = false; // change tracking ScChangeTrack* pTrack = rDoc.GetChangeTrack(); ScChangeViewSettings* pSettings = rDoc.GetChangeViewSettings(); if ( pTrack && pTrack->GetFirst() && pSettings && pSettings->ShowChanges()) { const ScChangeAction* pFound = nullptr; const ScChangeAction* pFoundContent = nullptr; const ScChangeAction* pFoundMove = nullptr; const ScChangeAction* pAction = pTrack->GetFirst(); while (pAction) { if ( pAction->IsVisible() && ScViewUtil::IsActionShown( *pAction, *pSettings, rDoc ) ) { ScChangeActionType eType = pAction->GetType(); const ScBigRange& rBig = pAction->GetBigRange(); if ( rBig.aStart.Tab() == nTab ) { ScRange aRange = rBig.MakeRange( rDoc ); if ( eType == SC_CAT_DELETE_ROWS ) aRange.aEnd.SetRow( aRange.aStart.Row() ); else if ( eType == SC_CAT_DELETE_COLS ) aRange.aEnd.SetCol( aRange.aStart.Col() ); if ( aRange.Contains( aCellPos ) ) { pFound = pAction; // the last one wins switch ( eType ) { case SC_CAT_CONTENT : pFoundContent = pAction; break; case SC_CAT_MOVE : pFoundMove = pAction; break; default: { // added to avoid warnings } } } } if ( eType == SC_CAT_MOVE ) { ScRange aRange = static_cast(pAction)-> GetFromRange().MakeRange( rDoc ); if ( aRange.Contains( aCellPos ) ) { pFound = pAction; } } } pAction = pAction->GetNext(); } if ( pFound ) { if ( pFoundContent && pFound->GetType() != SC_CAT_CONTENT ) pFound = pFoundContent; // content wins if ( pFoundMove && pFound->GetType() != SC_CAT_MOVE && pFoundMove->GetActionNumber() > pFound->GetActionNumber() ) pFound = pFoundMove; // move wins // for deleted columns: Arrow on the left side of the cell if ( pFound->GetType() == SC_CAT_DELETE_COLS ) bLeftEdge = true; DateTime aDT = pFound->GetDateTime(); aTrackText = pFound->GetUser() + ", " + ScGlobal::getLocaleData().getDate(aDT) + " " + ScGlobal::getLocaleData().getTime(aDT) + ":\n"; OUString aComStr=pFound->GetComment(); if(!aComStr.isEmpty()) { aTrackText += aComStr + "\n( "; } OUString aTmp = pFound->GetDescription(rDoc); aTrackText += aTmp; if(!aComStr.isEmpty()) { aTrackText += ")"; } } } // Note, only if it is not already displayed on the Drawing Layer: const ScPostIt* pNote = rDoc.GetNote( aCellPos ); if ( (!aTrackText.isEmpty()) || (pNote && !pNote->IsCaptionShown()) ) { bool bNew = true; bool bFast = false; if (mpNoteMarker) // A note already shown { if (mpNoteMarker->GetDocPos() == aCellPos) bNew = false; // then stop else bFast = true; // otherwise, at once // marker which was shown for ctrl-F1 isn't removed by mouse events if (mpNoteMarker->IsByKeyboard() && !bKeyboard) bNew = false; } if (bNew) { if (bKeyboard) bFast = true; // keyboard also shows the marker immediately mpNoteMarker.reset(); bool bHSplit = mrViewData.GetHSplitMode() != SC_SPLIT_NONE; bool bVSplit = mrViewData.GetVSplitMode() != SC_SPLIT_NONE; vcl::Window* pLeft = mrViewData.GetView()->GetWindowByPos( bVSplit ? SC_SPLIT_TOPLEFT : SC_SPLIT_BOTTOMLEFT ); vcl::Window* pRight = bHSplit ? mrViewData.GetView()->GetWindowByPos( bVSplit ? SC_SPLIT_TOPRIGHT : SC_SPLIT_BOTTOMRIGHT ) : nullptr; vcl::Window* pBottom = bVSplit ? mrViewData.GetView()->GetWindowByPos( SC_SPLIT_BOTTOMLEFT ) : nullptr; vcl::Window* pDiagonal = (bHSplit && bVSplit) ? mrViewData.GetView()->GetWindowByPos( SC_SPLIT_BOTTOMRIGHT ) : nullptr; OSL_ENSURE( pLeft, "ScGridWindow::ShowNoteMarker - missing top-left grid window" ); /* If caption is shown from right or bottom windows, adjust mapmode to include size of top-left window. */ MapMode aMapMode = GetDrawMapMode( true ); Size aLeftSize = pLeft->PixelToLogic( pLeft->GetOutputSizePixel(), aMapMode ); Point aOrigin = aMapMode.GetOrigin(); if( (this == pRight) || (this == pDiagonal) ) aOrigin.AdjustX(aLeftSize.Width() ); if( (this == pBottom) || (this == pDiagonal) ) aOrigin.AdjustY(aLeftSize.Height() ); aMapMode.SetOrigin( aOrigin ); mpNoteMarker.reset(new ScNoteMarker(pLeft, pRight, pBottom, pDiagonal, &rDoc, aCellPos, aTrackText, aMapMode, bLeftEdge, bFast, bKeyboard)); } bDone = true; // something is shown (old or new) } return bDone; } void ScGridWindow::RequestHelp(const HelpEvent& rHEvt) { bool bDone = false; OUString aFormulaText; tools::Rectangle aFormulaPixRect; bool bHelpEnabled = bool(rHEvt.GetMode() & ( HelpEventMode::BALLOON | HelpEventMode::QUICK )); SdrView* pDrView = mrViewData.GetScDrawView(); bool bDrawTextEdit = false; if (pDrView) bDrawTextEdit = pDrView->IsTextEdit(); // notes or change tracking if ( bHelpEnabled && !bDrawTextEdit ) { Point aPosPixel = ScreenToOutputPixel( rHEvt.GetMousePosPixel() ); SCCOL nPosX; SCROW nPosY; ScDocument& rDoc = mrViewData.GetDocument(); SCTAB nTab = mrViewData.GetTabNo(); const ScViewOptions& rOpts = mrViewData.GetOptions(); mrViewData.GetPosFromPixel( aPosPixel.X(), aPosPixel.Y(), eWhich, nPosX, nPosY ); if ( ShowNoteMarker( nPosX, nPosY, false ) ) { Window::RequestHelp( rHEvt ); // turn off old Tip/Balloon bDone = true; } if ( rOpts.GetOption( VOPT_FORMULAS_MARKS ) ) { aFormulaText = rDoc.GetFormula( nPosX, nPosY, nTab ); if ( !aFormulaText.isEmpty() ) { const ScPatternAttr* pPattern = rDoc.GetPattern( nPosX, nPosY, nTab ); aFormulaPixRect = mrViewData.GetEditArea( eWhich, nPosX, nPosY, this, pPattern, true ); } } } if (!bDone && mpNoteMarker) { if (mpNoteMarker->IsByKeyboard()) { // marker which was shown for ctrl-F1 isn't removed by mouse events } else { mpNoteMarker.reset(); } } if ( !aFormulaText.isEmpty() ) { tools::Rectangle aScreenRect(OutputToScreenPixel(aFormulaPixRect.TopLeft()), OutputToScreenPixel(aFormulaPixRect.BottomRight())); if ( rHEvt.GetMode() & HelpEventMode::BALLOON ) Help::ShowBalloon(this, rHEvt.GetMousePosPixel(), aScreenRect, aFormulaText); else if ( rHEvt.GetMode() & HelpEventMode::QUICK ) Help::ShowQuickHelp(this, aScreenRect, aFormulaText); bDone = true; } // Image-Map / Text-URL if ( bHelpEnabled && !bDone && !nButtonDown ) // only without pressed button { OUString aHelpText; tools::Rectangle aPixRect; Point aPosPixel = ScreenToOutputPixel( rHEvt.GetMousePosPixel() ); if ( pDrView ) // URL / Image-Map { SdrViewEvent aVEvt; MouseEvent aMEvt( aPosPixel, 1, MouseEventModifiers::NONE, MOUSE_LEFT ); SdrHitKind eHit = pDrView->PickAnything( aMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt ); if ( eHit != SdrHitKind::NONE && aVEvt.mpObj != nullptr ) { // URL for IMapObject below Pointer is help text if (SvxIMapInfo::GetIMapInfo(aVEvt.mpObj)) { Point aLogicPos = PixelToLogic( aPosPixel ); IMapObject* pIMapObj = SvxIMapInfo::GetHitIMapObject( aVEvt.mpObj, aLogicPos, GetOutDev() ); if ( pIMapObj ) { // For image maps show the description, if available aHelpText = pIMapObj->GetAltText(); if (aHelpText.isEmpty()) aHelpText = SfxHelp::GetURLHelpText(pIMapObj->GetURL()); aPixRect = LogicToPixel(aVEvt.mpObj->GetLogicRect()); } } // URL in shape text or at shape itself (URL in text overrides object URL) if ( aHelpText.isEmpty() ) { if( aVEvt.meEvent == SdrEventKind::ExecuteUrl ) { aHelpText = SfxHelp::GetURLHelpText(aVEvt.mpURLField->GetURL()); aPixRect = LogicToPixel(aVEvt.mpObj->GetLogicRect()); } else { SdrPageView* pPV = nullptr; Point aMDPos = PixelToLogic( aPosPixel ); SdrObject* pObj = pDrView->PickObj(aMDPos, pDrView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER); if (pObj) { if ( pObj->IsGroupObject() ) { SdrObject* pHit = pDrView->PickObj(aMDPos, pDrView->getHitTolLog(), pPV, SdrSearchOptions::DEEP); if (pHit) pObj = pHit; } // Fragments pointing into the current document need no tooltip // describing the ctrl-click functionality. if ( !pObj->getHyperlink().isEmpty() && !pObj->getHyperlink().startsWith("#") ) { aPixRect = LogicToPixel(aVEvt.mpObj->GetLogicRect()); aHelpText = SfxHelp::GetURLHelpText(pObj->getHyperlink()); } } } } } } if ( aHelpText.isEmpty() ) // Text-URL { OUString aUrl; if ( GetEditUrl( aPosPixel, nullptr, &aUrl ) ) { aHelpText = SfxHelp::GetURLHelpText( INetURLObject::decode(aUrl, INetURLObject::DecodeMechanism::Unambiguous)); ScDocument& rDoc = mrViewData.GetDocument(); SCCOL nPosX; SCROW nPosY; SCTAB nTab = mrViewData.GetTabNo(); mrViewData.GetPosFromPixel( aPosPixel.X(), aPosPixel.Y(), eWhich, nPosX, nPosY ); const ScPatternAttr* pPattern = rDoc.GetPattern( nPosX, nPosY, nTab ); // bForceToTop = sal_False, use the cell's real position aPixRect = mrViewData.GetEditArea( eWhich, nPosX, nPosY, this, pPattern, false ); } } if ( !aHelpText.isEmpty() ) { tools::Rectangle aScreenRect(OutputToScreenPixel(aPixRect.TopLeft()), OutputToScreenPixel(aPixRect.BottomRight())); if ( rHEvt.GetMode() & HelpEventMode::BALLOON ) Help::ShowBalloon(this,rHEvt.GetMousePosPixel(), aScreenRect, aHelpText); else if ( rHEvt.GetMode() & HelpEventMode::QUICK ) Help::ShowQuickHelp(this,aScreenRect, aHelpText); bDone = true; } } // basic controls if ( pDrView && bHelpEnabled && !bDone ) { SdrPageView* pPV = pDrView->GetSdrPageView(); OSL_ENSURE( pPV, "SdrPageView* is NULL" ); if (pPV) bDone = FmFormPage::RequestHelp( this, pDrView, rHEvt ); } // If QuickHelp for AutoFill is shown, do not allow it to be removed if ( nMouseStatus == SC_GM_TABDOWN && mrViewData.GetRefType() == SC_REFTYPE_FILL && Help::IsQuickHelpEnabled() ) bDone = true; if (!bDone) Window::RequestHelp( rHEvt ); } bool ScGridWindow::IsMyModel(const SdrEditView* pSdrView) { return pSdrView && &pSdrView->GetModel() == mrViewData.GetDocument().GetDrawLayer(); } void ScGridWindow::HideNoteMarker() { mpNoteMarker.reset(); } css::uno::Reference< css::accessibility::XAccessible > ScGridWindow::CreateAccessible() { css::uno::Reference< css::accessibility::XAccessible > xAcc= GetAccessible(false); if (xAcc.is()) { return xAcc; } rtl::Reference pAccessibleDocument = new ScAccessibleDocument(GetAccessibleParentWindow()->GetAccessible(), mrViewData.GetViewShell(), eWhich); pAccessibleDocument->PreInit(); xAcc = pAccessibleDocument; SetAccessible(xAcc); pAccessibleDocument->Init(); return xAcc; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */