diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /sw/source/uibase/docvw/edtwin2.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.tar.xz libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sw/source/uibase/docvw/edtwin2.cxx')
-rw-r--r-- | sw/source/uibase/docvw/edtwin2.cxx | 441 |
1 files changed, 441 insertions, 0 deletions
diff --git a/sw/source/uibase/docvw/edtwin2.cxx b/sw/source/uibase/docvw/edtwin2.cxx new file mode 100644 index 000000000..b48b18ec4 --- /dev/null +++ b/sw/source/uibase/docvw/edtwin2.cxx @@ -0,0 +1,441 @@ +/* -*- 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 <doc.hxx> +#include <osl/thread.h> +#include <vcl/help.hxx> +#include <tools/urlobj.hxx> +#include <fmtrfmrk.hxx> +#include <svl/urihelper.hxx> +#include <sfx2/sfxhelp.hxx> +#include <svx/svdview.hxx> +#include <svx/svdpagv.hxx> +#include <swmodule.hxx> +#include <modcfg.hxx> +#include <view.hxx> +#include <wrtsh.hxx> +#include <docsh.hxx> +#include <edtwin.hxx> +#include <dpage.hxx> +#include <docufld.hxx> +#include <reffld.hxx> +#include <cellatr.hxx> +#include <shdwcrsr.hxx> +#include <fmtinfmt.hxx> +#include <fmtftn.hxx> +#include <redline.hxx> +#include <tox.hxx> +#include <txatbase.hxx> +#include <uitool.hxx> +#include <viewopt.hxx> +#include <strings.hrc> + +#include <IDocumentMarkAccess.hxx> +#include <txtfrm.hxx> +#include <ndtxt.hxx> + +static OUString lcl_GetRedlineHelp( const SwRangeRedline& rRedl, bool bBalloon ) +{ + const char* pResId = nullptr; + switch( rRedl.GetType() ) + { + case RedlineType::Insert: pResId = STR_REDLINE_INSERT; break; + case RedlineType::Delete: pResId = STR_REDLINE_DELETE; break; + case RedlineType::Format: pResId = STR_REDLINE_FORMAT; break; + case RedlineType::Table: pResId = STR_REDLINE_TABLE; break; + case RedlineType::FmtColl: pResId = STR_REDLINE_FMTCOLL; break; + case RedlineType::ParagraphFormat: pResId = STR_REDLINE_PARAGRAPH_FORMAT; break; + case RedlineType::TableRowInsert: pResId = STR_REDLINE_TABLE_ROW_INSERT; break; + case RedlineType::TableRowDelete: pResId = STR_REDLINE_TABLE_ROW_DELETE; break; + case RedlineType::TableCellInsert: pResId = STR_REDLINE_TABLE_CELL_INSERT; break; + case RedlineType::TableCellDelete: pResId = STR_REDLINE_TABLE_CELL_DELETE; break; + default: break; + } + + OUStringBuffer sBuf; + if (pResId) + { + sBuf.append(SwResId(pResId)); + sBuf.append(": "); + sBuf.append(rRedl.GetAuthorString()); + sBuf.append(" - "); + sBuf.append(GetAppLangDateTimeString(rRedl.GetTimeStamp())); + if( bBalloon && !rRedl.GetComment().isEmpty() ) + sBuf.append('\n').append(rRedl.GetComment()); + } + return sBuf.makeStringAndClear(); +} + +OUString SwEditWin::ClipLongToolTip(const OUString& rText) +{ + OUString sDisplayText(rText); + long nTextWidth = GetTextWidth(sDisplayText); + long nMaxWidth = GetDesktopRectPixel().GetWidth() * 2 / 3; + nMaxWidth = PixelToLogic(Size(nMaxWidth, 0)).Width(); + if (nTextWidth > nMaxWidth) + sDisplayText = GetEllipsisString(sDisplayText, nMaxWidth, DrawTextFlags::CenterEllipsis); + return sDisplayText; +} + +void SwEditWin::RequestHelp(const HelpEvent &rEvt) +{ + SwWrtShell &rSh = m_rView.GetWrtShell(); + bool bQuickBalloon = bool(rEvt.GetMode() & ( HelpEventMode::QUICK | HelpEventMode::BALLOON )); + if(bQuickBalloon && !rSh.GetViewOptions()->IsShowContentTips()) + return; + bool bContinue = true; + SET_CURR_SHELL(&rSh); + OUString sText; + Point aPos( PixelToLogic( ScreenToOutputPixel( rEvt.GetMousePosPixel() ) )); + bool bBalloon = bool(rEvt.GetMode() & HelpEventMode::BALLOON); + + SdrView *pSdrView = rSh.GetDrawView(); + + if( bQuickBalloon && pSdrView ) + { + SdrPageView* pPV = pSdrView->GetSdrPageView(); + SwDPage* pPage = pPV ? static_cast<SwDPage*>(pPV->GetPage()) : nullptr; + bContinue = pPage && pPage->RequestHelp(this, pSdrView, rEvt); + } + + if( bContinue && bQuickBalloon) + { + SwRect aFieldRect; + SwContentAtPos aContentAtPos( IsAttrAtPos::Field | + IsAttrAtPos::InetAttr | + IsAttrAtPos::Ftn | + IsAttrAtPos::Redline | + IsAttrAtPos::ToxMark | + IsAttrAtPos::RefMark | + IsAttrAtPos::SmartTag | +#ifdef DBG_UTIL + IsAttrAtPos::TableBoxValue | + ( bBalloon ? IsAttrAtPos::CurrAttrs : IsAttrAtPos::NONE) | +#endif + IsAttrAtPos::TableBoxFml ); + + if( rSh.GetContentAtPos( aPos, aContentAtPos, false, &aFieldRect ) ) + { + QuickHelpFlags nStyle = QuickHelpFlags::NONE; // style of quick help + switch( aContentAtPos.eContentAtPos ) + { + case IsAttrAtPos::TableBoxFml: + sText = "= " + static_cast<const SwTableBoxFormula*>(aContentAtPos.aFnd.pAttr)->GetFormula(); + break; +#ifdef DBG_UTIL + case IsAttrAtPos::TableBoxValue: + { + sText = OStringToOUString(OString::number( + static_cast<const SwTableBoxValue*>(aContentAtPos.aFnd.pAttr)->GetValue()), + osl_getThreadTextEncoding()); + break; + } + case IsAttrAtPos::CurrAttrs: + sText = aContentAtPos.sStr; + break; +#endif + + case IsAttrAtPos::InetAttr: + { + sText = static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr)->GetValue(); + sText = URIHelper::removePassword( sText, + INetURLObject::EncodeMechanism::WasEncoded, + INetURLObject::DecodeMechanism::Unambiguous); + //#i63832# remove the link target type + sal_Int32 nFound = sText.indexOf(cMarkSeparator); + if( nFound != -1 && (++nFound) < sText.getLength() ) + { + OUString sSuffix( sText.copy(nFound) ); + if( sSuffix == "table" || + sSuffix == "frame" || + sSuffix == "region" || + sSuffix == "outline" || + sSuffix == "text" || + sSuffix == "graphic" || + sSuffix == "ole" ) + sText = sText.copy( 0, nFound - 1); + } + // #i104300# + // special handling if target is a cross-reference bookmark + { + OUString sTmpSearchStr = sText.copy( 1 ); + IDocumentMarkAccess* pMarkAccess = rSh.getIDocumentMarkAccess(); + IDocumentMarkAccess::const_iterator_t ppBkmk = + pMarkAccess->findBookmark( sTmpSearchStr ); + if ( ppBkmk != pMarkAccess->getBookmarksEnd() && + IDocumentMarkAccess::GetType(**ppBkmk) + == IDocumentMarkAccess::MarkType::CROSSREF_HEADING_BOOKMARK ) + { + SwTextNode* pTextNode = (*ppBkmk)->GetMarkStart().nNode.GetNode().GetTextNode(); + if ( pTextNode ) + { + sText = sw::GetExpandTextMerged(rSh.GetLayout(), *pTextNode, true, false, ExpandMode(0)); + + if( !sText.isEmpty() ) + { + OUStringBuffer sTmp(sText.replaceAll(u"\u00ad", "")); + for (sal_Int32 i = 0; i < sTmp.getLength(); ++i) + { + if (sTmp[i] < 0x20) + sTmp[i] = 0x20; + else if (sTmp[i] == 0x2011) + sTmp[i] = '-'; + } + sText = sTmp.makeStringAndClear(); + } + } + } + } + // #i80029# + bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly(); + if ( !bExecHyperlinks ) + { + sText = SfxHelp::GetURLHelpText(sText); + } + break; + } + case IsAttrAtPos::SmartTag: + { + vcl::KeyCode aCode( KEY_SPACE ); + vcl::KeyCode aModifiedCode( KEY_SPACE, KEY_MOD1 ); + OUString aModStr( aModifiedCode.GetName() ); + aModStr = aModStr.replaceFirst(aCode.GetName(), ""); + aModStr = aModStr.replaceAll("+", ""); + sText = SwResId(STR_SMARTTAG_CLICK).replaceAll("%s", aModStr); + break; + } + + case IsAttrAtPos::Ftn: + if( aContentAtPos.pFndTextAttr && aContentAtPos.aFnd.pAttr ) + { + const SwFormatFootnote* pFootnote = static_cast<const SwFormatFootnote*>(aContentAtPos.aFnd.pAttr); + OUString sTmp(pFootnote->GetFootnoteText(*rSh.GetLayout())); + sText = SwResId( pFootnote->IsEndNote() + ? STR_ENDNOTE : STR_FTNNOTE ) + sTmp; + bBalloon = true; + if( aContentAtPos.IsInRTLText() ) + nStyle |= QuickHelpFlags::BiDiRtl; + } + break; + + case IsAttrAtPos::Redline: + { + const bool bShowTrackChanges = IDocumentRedlineAccess::IsShowChanges( m_rView.GetDocShell()->GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags() ); + const bool bShowInlineTooltips = rSh.GetViewOptions()->IsShowInlineTooltips(); + if ( bShowTrackChanges && bShowInlineTooltips ) + sText = lcl_GetRedlineHelp(*aContentAtPos.aFnd.pRedl, bBalloon); + break; + } + + case IsAttrAtPos::ToxMark: + sText = aContentAtPos.sStr; + if( !sText.isEmpty() && aContentAtPos.pFndTextAttr ) + { + const SwTOXType* pTType = aContentAtPos.pFndTextAttr-> + GetTOXMark().GetTOXType(); + if( pTType && !pTType->GetTypeName().isEmpty() ) + { + sText = ": " + sText; + sText = pTType->GetTypeName() + sText; + } + } + break; + + case IsAttrAtPos::RefMark: + if(aContentAtPos.aFnd.pAttr) + { + sText = SwResId(STR_CONTENT_TYPE_SINGLE_REFERENCE) + ": "; + sText += static_cast<const SwFormatRefMark*>(aContentAtPos.aFnd.pAttr)->GetRefName(); + } + break; + + default: + { + SwModuleOptions* pModOpt = SW_MOD()->GetModuleConfig(); + if(!pModOpt->IsHideFieldTips()) + { + const SwField* pField = aContentAtPos.aFnd.pField; + switch( pField->Which() ) + { + case SwFieldIds::SetExp: + case SwFieldIds::Table: + case SwFieldIds::GetExp: + { + sal_uInt16 nOldSubType = pField->GetSubType(); + const_cast<SwField*>(pField)->SetSubType(nsSwExtendedSubType::SUB_CMD); + sText = pField->ExpandField(true, rSh.GetLayout()); + const_cast<SwField*>(pField)->SetSubType(nOldSubType); + } + break; + + case SwFieldIds::Postit: + { + break; + } + case SwFieldIds::Input: // BubbleHelp, because the suggestion could be quite long + bBalloon = true; + [[fallthrough]]; + case SwFieldIds::Dropdown: + case SwFieldIds::JumpEdit: + sText = pField->GetPar2(); + break; + + case SwFieldIds::Database: + sText = pField->GetFieldName(); + break; + + case SwFieldIds::User: + case SwFieldIds::HiddenText: + sText = pField->GetPar1(); + break; + + case SwFieldIds::DocStat: + break; + + case SwFieldIds::Macro: + sText = static_cast<const SwMacroField*>(pField)->GetMacro(); + break; + + case SwFieldIds::GetRef: + { + // #i85090# + const SwGetRefField* pRefField( dynamic_cast<const SwGetRefField*>(pField) ); + OSL_ENSURE( pRefField, + "<SwEditWin::RequestHelp(..)> - unexpected type of <pField>" ); + if ( pRefField ) + { + if ( pRefField->IsRefToHeadingCrossRefBookmark() || + pRefField->IsRefToNumItemCrossRefBookmark() ) + { + sText = pRefField->GetExpandedTextOfReferencedTextNode(*rSh.GetLayout()); + if ( sText.getLength() > 80 ) + { + sText = sText.copy(0, 80) + "..."; + } + } + else + { + sText = static_cast<const SwGetRefField*>(pField)->GetSetRefName(); + } + } + break; + } + + default: break; + } + } + + if( sText.isEmpty() ) + { + const bool bShowTrackChanges = IDocumentRedlineAccess::IsShowChanges( m_rView.GetDocShell()->GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags() ); + const bool bShowInlineTooltips = rSh.GetViewOptions()->IsShowInlineTooltips(); + if ( bShowTrackChanges && bShowInlineTooltips ) + { + aContentAtPos.eContentAtPos = IsAttrAtPos::Redline; + if( rSh.GetContentAtPos( aPos, aContentAtPos, false, &aFieldRect ) ) + sText = lcl_GetRedlineHelp(*aContentAtPos.aFnd.pRedl, bBalloon); + } + } + } + } + if (!sText.isEmpty()) + { + tools::Rectangle aRect( aFieldRect.SVRect() ); + Point aPt( OutputToScreenPixel( LogicToPixel( aRect.TopLeft() ))); + aRect.SetLeft( aPt.X() ); + aRect.SetTop( aPt.Y() ); + aPt = OutputToScreenPixel( LogicToPixel( aRect.BottomRight() )); + aRect.SetRight( aPt.X() ); + aRect.SetBottom( aPt.Y() ); + + // tdf#136336 ensure tooltip area surrounds the current mouse position with at least a pixel margin + aRect.Union(tools::Rectangle(rEvt.GetMousePosPixel(), Size(1, 1))); + aRect.AdjustLeft(-1); + aRect.AdjustRight(1); + aRect.AdjustTop(-1); + aRect.AdjustBottom(1); + + if( bBalloon ) + Help::ShowBalloon( this, rEvt.GetMousePosPixel(), aRect, sText ); + else + { + // the show the help + OUString sDisplayText(ClipLongToolTip(sText)); + Help::ShowQuickHelp(this, aRect, sDisplayText, nStyle); + } + } + + bContinue = false; + } + + } + + if( bContinue ) + Window::RequestHelp( rEvt ); +} + +void SwEditWin::PrePaint(vcl::RenderContext& /*rRenderContext*/) +{ + SwWrtShell* pWrtShell = GetView().GetWrtShellPtr(); + + if(pWrtShell) + { + pWrtShell->PrePaint(); + } +} + +void SwEditWin::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) +{ + SwWrtShell* pWrtShell = GetView().GetWrtShellPtr(); + if(!pWrtShell) + return; + bool bPaintShadowCursor = false; + if( m_pShadCursor ) + { + tools::Rectangle aRect( m_pShadCursor->GetRect()); + // fully resides inside? + if( rRect.IsInside( aRect ) ) + { + // then cancel + m_pShadCursor.reset(); + } + else if( rRect.IsOver( aRect )) + { + // resides somewhat above, then everything is clipped outside + // and we have to make the "inner part" at the end of the + // Paint visible again. Otherwise Paint errors occur! + bPaintShadowCursor = true; + } + } + + if ( GetView().GetVisArea().GetWidth() <= 0 || + GetView().GetVisArea().GetHeight() <= 0 ) + Invalidate( rRect ); + else + { + pWrtShell->setOutputToWindow(true); + pWrtShell->Paint(rRenderContext, rRect); + pWrtShell->setOutputToWindow(false); + } + + if( bPaintShadowCursor ) + m_pShadCursor->Paint(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |