/* -*- 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 .
*/
// Here static members are defined. They will get changed on alteration of the // MapMode. This is done so that on ShowCursor the same size does not have to be // expensively determined again and again.
if (SfxViewShell* pNotifyViewShell = comphelper::LibreOfficeKit::isActive() ? m_pCursorShell->GetSfxViewShell() : nullptr)
{ // notify about page number change (if that happened)
sal_uInt16 nPage, nVirtPage; // bCalcFrame=false is important to avoid calculating the layout when // we're in the middle of doing that already. const_cast<SwCursorShell*>(m_pCursorShell)->GetPageNum(nPage, nVirtPage, /*bAtCursorPos=*/true, /*bCalcFrame=*/false); if (nPage != m_nPageLastTime)
{
m_nPageLastTime = nPage;
OString aPayload = OString::number(nPage - 1);
pNotifyViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_SET_PART, aPayload);
}
// This may get called often, so instead of sending data on each update, just notify // that there's been an update, and the other side will pull the data using // getLOKPayload() when it decides to.
m_aLastLOKRect = aRect; if (pViewShell)
{ if (pViewShell == pNotifyViewShell)
{
SfxLokHelper::notifyUpdatePerViewId(pViewShell, LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR);
} else
{
SfxLokHelper::notifyUpdatePerViewId(pViewShell, pNotifyViewShell, pViewShell,
LOK_CALLBACK_INVALIDATE_VIEW_CURSOR);
}
} elseif ( bIsCursorPosChanged || m_pCursorShell->IsTableMode())
{
SfxLokHelper::notifyUpdatePerViewId(pNotifyViewShell, SfxViewShell::Current(),
pNotifyViewShell, LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR);
SfxLokHelper::notifyOtherViewsUpdatePerViewId(pNotifyViewShell, LOK_CALLBACK_INVALIDATE_VIEW_CURSOR);
}
}
if ( m_pCursorShell->IsCursorReadonly() && !m_pCursorShell->GetViewOptions()->IsSelectionInReadonly() ) return;
if ( m_pCursorShell->GetDrawView() ) const_cast<SwDrawView*>(static_cast<const SwDrawView*>(m_pCursorShell->GetDrawView()))->SetAnimationEnabled(
!m_pCursorShell->IsSelection() );
/** * Return a layout rectangle (typically with minimal width) that represents a * cursor at rPosition. * * @param rPoint layout position as a hint about what layout frame contains * rPosition (there might be multiple frames for a single node) * @param rPosition the doc model position (paragraph / character index)
*/ static SwRect lcl_getLayoutRect(const Point& rPoint, const SwPosition& rPosition)
{ const SwContentNode* pNode = rPosition.GetNode().GetContentNode();
std::pair<Point, bool> const tmp(rPoint, true); const SwContentFrame* pFrame = pNode->getLayoutFrame(
pNode->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(),
&rPosition, &tmp);
SwRect aRect;
pFrame->GetCharRect(aRect, rPosition); return aRect;
}
// Tiled editing does not expose the draw and writer cursor, it just // talks about "the" cursor at the moment. As long as that's true, // don't say anything about the Writer cursor till a draw object is // being edited. if (!comphelper::LibreOfficeKit::isActive() || pView->GetTextEditObject()) return;
// If pSelectionRectangles is set, we're just collecting the text selections -> don't emit start/end. if (!empty() && !pSelectionRectangles)
{
SwRect aStartRect;
SwRect aEndRect;
FillStartEnd(aStartRect, aEndRect);
if (aStartRect.HasArea())
SfxLokHelper::notifyUpdate(GetShell()->GetSfxViewShell(), LOK_CALLBACK_TEXT_SELECTION_START); if (aEndRect.HasArea())
SfxLokHelper::notifyUpdate(GetShell()->GetSfxViewShell(), LOK_CALLBACK_TEXT_SELECTION_END);
}
std::vector<OString> aRect;
aRect.reserve(size()); for (size_type i = 0; i < size(); ++i)
{ const SwRect& rRect = (*this)[i];
aRect.push_back(rRect.SVRect().toString());
}
OString sRect = comphelper::string::join("; ", aRect); if (!pSelectionRectangles)
{
SfxLokHelper::notifyUpdate(GetShell()->GetSfxViewShell(),LOK_CALLBACK_TEXT_SELECTION);
SfxLokHelper::notifyOtherViewsUpdatePerViewId(GetShell()->GetSfxViewShell(), LOK_CALLBACK_TEXT_VIEW_SELECTION);
} else
pSelectionRectangles->push_back(sRect);
}
std::optional<OString> SwSelPaintRects::getLOKPayload(int nType, int nViewId) const
{ switch( nType )
{ case LOK_CALLBACK_TEXT_SELECTION_START: case LOK_CALLBACK_TEXT_SELECTION_END:
{ // The selection may be a complex polygon, emit the logical // start/end cursor rectangle of the selection as separate // events, if there is a real selection. // This can be used to easily show selection handles on the // client side.
SwRect aStartRect;
SwRect aEndRect;
FillStartEnd(aStartRect, aEndRect);
if (xTargetOverlay.is())
{ // use system's highlight color with decreased luminance as highlight color
Color aHighlight(SvtOptionsDrawinglayer::getHilightColor());
aHighlight.DecreaseLuminance( 128 );
if (m_bShowContentControlOverlay)
{ const SwPosition* pStart = GetShell()->GetCursor()->Start();
SwTextNode* pTextNode = pStart->GetNode().GetTextNode();
SwTextContentControl* pCurContentControlAtCursor = nullptr; if (pTextNode)
{ // GetTextAttrMode::Parent because this way we highlight when the user will type inside the // content control, not outside of it.
SwTextAttr* pAttr = pTextNode->GetTextAttrAt(
pStart->GetContentIndex(), RES_TXTATR_CONTENTCONTROL, ::sw::GetTextAttrMode::Parent); if (pAttr)
{
pCurContentControlAtCursor = static_txtattr_cast<SwTextContentControl*>(pAttr);
}
} if (pCurContentControlAtCursor)
{
SwShellCursor aCursorForContentControl(
*GetShell(), SwPosition(*pTextNode, pCurContentControlAtCursor->GetStart()));
aCursorForContentControl.SetMark();
aCursorForContentControl.GetMark()->Assign(
*pTextNode, *(pCurContentControlAtCursor->End()));
// The layout knows if the text node is RTL (either set directly, or inherited from the // environment).
SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aFrames(*pTextNode);
SwTextFrame* pFrame = aFrames.First(); if (pFrame)
{
bRTL = pFrame->IsRightToLeft();
}
}
}
// clear an obsolete dropdown if the cursor has moved away from the content control if (m_pContentControlButton
&& (!pContentControl || m_pContentControlButton->GetContentControl() != pContentControl))
{
m_pContentControlButton.disposeAndClear();
}
auto pWrtShell = dynamic_cast<const SwWrtShell*>(GetShell()); if (!aContentControlRanges.empty())
{ if (comphelper::LibreOfficeKit::isActive())
{
OString aPayload = comphelper::string::join("; ", aLOKRectangles);
tools::JsonWriter aJson;
aJson.put("action", "show");
aJson.put("rectangles", aPayload);
if (pContentControl && (pContentControl->GetComboBox() || pContentControl->GetDropDown()))
{ auto aItems = aJson.startArray("items"); for (constauto& rItem : pContentControl->GetListItems())
{
aJson.putSimpleValue(rItem.ToString());
}
}
if (pContentControl && pContentControl->GetDate())
{
aJson.put("date", "true");
}
if (pContentControl && !pContentControl->GetAlias().isEmpty())
{
aJson.put("alias", pContentControl->GetAlias());
}
if (xTargetOverlay.is())
{ // Use the system's highlight color with decreased luminance as highlight color.
Color aHighlight(SvtOptionsDrawinglayer::getHilightColor());
aHighlight.DecreaseLuminance(128);
// If the selection is to the right or at the bottom, outside the // visible area, it is never aligned on one pixel at the right/bottom. // This has to be determined here and if that is the case the // rectangle has to be expanded. if( !(GetShell()->m_bVisPortChgd && 0 != ( nSz = size())) ) return;
// check current MapMode of the shell and set possibly the static members. // Optional set the parameters pX, pY void SwSelPaintRects::Get1PixelInLogic( const SwViewShell& rSh,
tools::Long* pX, tools::Long* pY )
{ const OutputDevice* pOut = rSh.GetWin()->GetOutDev(); if ( ! pOut )
pOut = rSh.GetOut();
// This rectangle gets painted anew, therefore the SSelection in this // area is invalid. void SwShellCursor::Invalidate( const SwRect& rRect )
{ for(SwPaM& rPaM : GetRingContainer())
{
SwShellCursor* pShCursor = dynamic_cast<SwShellCursor*>(&rPaM); // skip any non SwShellCursor objects in the ring // see also: SwAutoFormat::DeleteSel() if(pShCursor)
pShCursor->SwSelPaintRects::Invalidate(rRect);
}
}
// if <true> than the cursor can be set to the position. bool SwShellCursor::IsAtValidPos( bool bPoint ) const
{ if( GetShell() && ( GetShell()->IsAllProtect() ||
GetShell()->GetViewOptions()->IsReadonly() ||
( GetShell()->Imp()->GetDrawView() &&
GetShell()->Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() ))) returntrue;
void SwShellTableCursor::FillRects()
{ // Calculate the new rectangles. If the cursor is still "parked" do nothing if (m_SelectedBoxes.empty() || m_bParked || !GetPoint()->GetNodeIndex()) return;
// table in table // (see also lcl_FindTopLevelTable in unoobj2.cxx for a different // version to do this) const SwTableNode* pCurTableNd = pCNd ? pCNd->FindTableNode() : nullptr; while ( pSelTableNd != pCurTableNd && pCurTableNd )
{
aIdx = pCurTableNd->EndOfSectionIndex();
pCNd = SwNodes::GoNextSection(&aIdx, true, false);
pCurTableNd = pCNd->FindTableNode();
}
// Check if the SPoint is within the Table-SSelection. bool SwShellTableCursor::Contains( const Point& rPt ) const
{ // Calculate the new rectangles. If the cursor is still "parked" do nothing if (m_SelectedBoxes.empty() || m_bParked || !GetPoint()->GetNodeIndex()) returnfalse;
for (size_t n = 0; n < m_SelectedBoxes.size(); ++n)
{
SwNodeIndex aIdx( *m_SelectedBoxes[n]->GetSttNd() );
SwContentNode* pCNd = SwNodes::GoNextSection(&aIdx, true, false); if( !pCNd ) continue;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.