summaryrefslogtreecommitdiffstats
path: root/sc/source/ui/Accessibility/AccessibleText.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/ui/Accessibility/AccessibleText.cxx')
-rw-r--r--sc/source/ui/Accessibility/AccessibleText.cxx1399
1 files changed, 1399 insertions, 0 deletions
diff --git a/sc/source/ui/Accessibility/AccessibleText.cxx b/sc/source/ui/Accessibility/AccessibleText.cxx
new file mode 100644
index 000000000..1d37e821b
--- /dev/null
+++ b/sc/source/ui/Accessibility/AccessibleText.cxx
@@ -0,0 +1,1399 @@
+/* -*- 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 <scitems.hxx>
+#include <editeng/eeitem.hxx>
+
+#include <memory>
+#include <AccessibleText.hxx>
+#include <AccessibleCell.hxx>
+#include <attrib.hxx>
+#include <tabvwsh.hxx>
+#include <editutil.hxx>
+#include <document.hxx>
+#include <scmod.hxx>
+#include <prevwsh.hxx>
+#include <docsh.hxx>
+#include <prevloc.hxx>
+#include <patattr.hxx>
+#include <inputwin.hxx>
+#include <editeng/unofored.hxx>
+#include <editeng/editview.hxx>
+#include <editeng/unoedhlp.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/adjustitem.hxx>
+#include <editeng/justifyitem.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/algitem.hxx>
+#include <vcl/svapp.hxx>
+
+class ScViewForwarder : public SvxViewForwarder
+{
+ ScTabViewShell* mpViewShell;
+ ScSplitPos meSplitPos;
+public:
+ ScViewForwarder(ScTabViewShell* pViewShell, ScSplitPos eSplitPos);
+
+ virtual bool IsValid() const override;
+ virtual Point LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const override;
+ virtual Point PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const override;
+
+ void SetInvalid();
+};
+
+ScViewForwarder::ScViewForwarder(ScTabViewShell* pViewShell, ScSplitPos eSplitPos)
+ :
+ mpViewShell(pViewShell),
+ meSplitPos(eSplitPos)
+{
+}
+
+bool ScViewForwarder::IsValid() const
+{
+ return mpViewShell != nullptr;
+}
+
+Point ScViewForwarder::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
+{
+ if (mpViewShell)
+ {
+ vcl::Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
+ if (pWindow)
+ return pWindow->LogicToPixel( rPoint, rMapMode );
+ }
+ else
+ {
+ OSL_FAIL("this ViewForwarder is not valid");
+ }
+ return Point();
+}
+
+Point ScViewForwarder::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
+{
+ if (mpViewShell)
+ {
+ vcl::Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
+ if (pWindow)
+ return pWindow->PixelToLogic( rPoint, rMapMode );
+ }
+ else
+ {
+ OSL_FAIL("this ViewForwarder is not valid");
+ }
+ return Point();
+}
+
+void ScViewForwarder::SetInvalid()
+{
+ mpViewShell = nullptr;
+}
+
+class ScEditObjectViewForwarder : public SvxViewForwarder
+{
+ VclPtr<OutputDevice> mpWindow;
+ // #i49561# EditView needed for access to its visible area.
+ const EditView* mpEditView;
+public:
+ ScEditObjectViewForwarder( OutputDevice* pWindow,
+ const EditView* _pEditView);
+
+ virtual bool IsValid() const override;
+ virtual Point LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const override;
+ virtual Point PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const override;
+
+ void SetInvalid();
+};
+
+ScEditObjectViewForwarder::ScEditObjectViewForwarder( OutputDevice* pWindow,
+ const EditView* _pEditView )
+ : mpWindow(pWindow)
+ , mpEditView( _pEditView )
+{
+}
+
+bool ScEditObjectViewForwarder::IsValid() const
+{
+ return (mpWindow != nullptr);
+}
+
+Point ScEditObjectViewForwarder::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
+{
+ if (mpWindow)
+ {
+ // #i49561# - consider offset of the visible area
+ // of the EditView before converting point to pixel.
+ Point aPoint( rPoint );
+ if ( mpEditView )
+ {
+ tools::Rectangle aEditViewVisArea( mpEditView->GetVisArea() );
+ aPoint += aEditViewVisArea.TopLeft();
+ }
+ return mpWindow->LogicToPixel( aPoint, rMapMode );
+ }
+ else
+ {
+ OSL_FAIL("this ViewForwarder is not valid");
+ }
+ return Point();
+}
+
+Point ScEditObjectViewForwarder::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
+{
+ if (mpWindow)
+ {
+ // #i49561# - consider offset of the visible area
+ // of the EditView after converting point to logic.
+ Point aPoint( mpWindow->PixelToLogic( rPoint, rMapMode ) );
+ if ( mpEditView )
+ {
+ tools::Rectangle aEditViewVisArea( mpEditView->GetVisArea() );
+ aPoint -= aEditViewVisArea.TopLeft();
+ }
+ return aPoint;
+ }
+ else
+ {
+ OSL_FAIL("this ViewForwarder is not valid");
+ }
+ return Point();
+}
+
+void ScEditObjectViewForwarder::SetInvalid()
+{
+ mpWindow = nullptr;
+}
+
+class ScPreviewViewForwarder : public SvxViewForwarder
+{
+protected:
+ ScPreviewShell* mpViewShell;
+public:
+ explicit ScPreviewViewForwarder(ScPreviewShell* pViewShell);
+
+ virtual bool IsValid() const override;
+ virtual Point LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const override;
+ virtual Point PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const override;
+
+ void SetInvalid();
+};
+
+ScPreviewViewForwarder::ScPreviewViewForwarder(ScPreviewShell* pViewShell)
+ : mpViewShell(pViewShell)
+{
+}
+
+bool ScPreviewViewForwarder::IsValid() const
+{
+ return mpViewShell != nullptr;
+}
+
+Point ScPreviewViewForwarder::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
+{
+ if (mpViewShell)
+ {
+ vcl::Window* pWindow = mpViewShell->GetWindow();
+ if (pWindow)
+ {
+ MapMode aMapMode(pWindow->GetMapMode().GetMapUnit());
+ Point aPoint2( OutputDevice::LogicToLogic( rPoint, rMapMode, aMapMode) );
+ return pWindow->LogicToPixel(aPoint2);
+ }
+ }
+ else
+ {
+ OSL_FAIL("this ViewForwarder is not valid");
+ }
+ return Point();
+}
+
+Point ScPreviewViewForwarder::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
+{
+ if (mpViewShell)
+ {
+ vcl::Window* pWindow = mpViewShell->GetWindow();
+ if (pWindow)
+ {
+ MapMode aMapMode(pWindow->GetMapMode());
+ aMapMode.SetOrigin(Point());
+ Point aPoint1( pWindow->PixelToLogic( rPoint ) );
+ Point aPoint2( OutputDevice::LogicToLogic( aPoint1,
+ MapMode(aMapMode.GetMapUnit()),
+ rMapMode ) );
+ return aPoint2;
+ }
+ }
+ else
+ {
+ OSL_FAIL("this ViewForwarder is not valid");
+ }
+ return Point();
+}
+
+void ScPreviewViewForwarder::SetInvalid()
+{
+ mpViewShell = nullptr;
+}
+
+namespace {
+
+class ScPreviewHeaderFooterViewForwarder : public ScPreviewViewForwarder
+{
+public:
+ ScPreviewHeaderFooterViewForwarder(ScPreviewShell* pViewShell);
+};
+
+}
+
+ScPreviewHeaderFooterViewForwarder::ScPreviewHeaderFooterViewForwarder(ScPreviewShell* pViewShell)
+ :
+ ScPreviewViewForwarder(pViewShell)
+{
+}
+
+namespace {
+
+class ScPreviewCellViewForwarder : public ScPreviewViewForwarder
+{
+public:
+ ScPreviewCellViewForwarder(ScPreviewShell* pViewShell);
+};
+
+}
+
+ScPreviewCellViewForwarder::ScPreviewCellViewForwarder(ScPreviewShell* pViewShell)
+ :
+ ScPreviewViewForwarder(pViewShell)
+{
+}
+
+namespace {
+
+class ScPreviewHeaderCellViewForwarder : public ScPreviewViewForwarder
+{
+public:
+ ScPreviewHeaderCellViewForwarder(ScPreviewShell* pViewShell);
+};
+
+}
+
+ScPreviewHeaderCellViewForwarder::ScPreviewHeaderCellViewForwarder(ScPreviewShell* pViewShell)
+ :
+ ScPreviewViewForwarder(pViewShell)
+{
+}
+
+namespace {
+
+class ScPreviewNoteViewForwarder : public ScPreviewViewForwarder
+{
+public:
+ ScPreviewNoteViewForwarder(ScPreviewShell* pViewShell);
+};
+
+}
+
+ScPreviewNoteViewForwarder::ScPreviewNoteViewForwarder(ScPreviewShell* pViewShell)
+ :
+ ScPreviewViewForwarder(pViewShell)
+{
+}
+
+class ScEditViewForwarder : public SvxEditViewForwarder
+{
+ EditView* mpEditView;
+ VclPtr<OutputDevice> mpWindow;
+public:
+ ScEditViewForwarder(EditView* pEditView, OutputDevice* pWin);
+
+ virtual bool IsValid() const override;
+ virtual Point LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const override;
+ virtual Point PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const override;
+ virtual bool GetSelection( ESelection& rSelection ) const override;
+ virtual bool SetSelection( const ESelection& rSelection ) override;
+ virtual bool Copy() override;
+ virtual bool Cut() override;
+ virtual bool Paste() override;
+
+ void SetInvalid();
+};
+
+ScEditViewForwarder::ScEditViewForwarder(EditView* pEditView, OutputDevice* pWin)
+ : mpEditView(pEditView)
+ , mpWindow(pWin)
+{
+}
+
+bool ScEditViewForwarder::IsValid() const
+{
+ return mpWindow && mpEditView;
+}
+
+Point ScEditViewForwarder::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
+{
+ if (mpWindow)
+ return mpWindow->LogicToPixel( rPoint, rMapMode );
+ else
+ {
+ OSL_FAIL("this ViewForwarder is not valid");
+ }
+ return Point();
+}
+
+Point ScEditViewForwarder::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
+{
+ if (mpWindow)
+ return mpWindow->PixelToLogic( rPoint, rMapMode );
+ else
+ {
+ OSL_FAIL("this ViewForwarder is not valid");
+ }
+ return Point();
+}
+
+bool ScEditViewForwarder::GetSelection( ESelection& rSelection ) const
+{
+ bool bResult(false);
+ if (IsValid())
+ {
+ rSelection = mpEditView->GetSelection();
+ bResult = true;
+ }
+ else
+ {
+ OSL_FAIL("this ViewForwarder is not valid");
+ }
+ return bResult;
+}
+
+bool ScEditViewForwarder::SetSelection( const ESelection& rSelection )
+{
+ bool bResult(false);
+ if (IsValid())
+ {
+ mpEditView->SetSelection(rSelection);
+ bResult = true;
+ }
+ else
+ {
+ OSL_FAIL("this ViewForwarder is not valid");
+ }
+ return bResult;
+}
+
+bool ScEditViewForwarder::Copy()
+{
+ bool bResult(false);
+ if (IsValid())
+ {
+ mpEditView->Copy();
+ bResult = true;
+ }
+ else
+ {
+ OSL_FAIL("this ViewForwarder is not valid");
+ }
+ return bResult;
+}
+
+bool ScEditViewForwarder::Cut()
+{
+ bool bResult(false);
+ if (IsValid())
+ {
+ mpEditView->Cut();
+ bResult = true;
+ }
+ else
+ {
+ OSL_FAIL("this ViewForwarder is not valid");
+ }
+ return bResult;
+}
+
+bool ScEditViewForwarder::Paste()
+{
+ bool bResult(false);
+ if (IsValid())
+ {
+ mpEditView->Paste();
+ bResult = true;
+ }
+ else
+ {
+ OSL_FAIL("this ViewForwarder is not valid");
+ }
+ return bResult;
+}
+
+void ScEditViewForwarder::SetInvalid()
+{
+ mpWindow = nullptr;
+ mpEditView = nullptr;
+}
+
+// ScAccessibleCellTextData: shared data between sub objects of an accessible cell text object
+
+ScAccessibleCellTextData::ScAccessibleCellTextData(ScTabViewShell* pViewShell,
+ const ScAddress& rP, ScSplitPos eSplitPos, ScAccessibleCell* pAccCell)
+ : ScAccessibleCellBaseTextData(GetDocShell(pViewShell), rP),
+ mpViewShell(pViewShell),
+ meSplitPos(eSplitPos),
+ mpAccessibleCell( pAccCell )
+{
+}
+
+ScAccessibleCellTextData::~ScAccessibleCellTextData()
+{
+ if (pEditEngine)
+ pEditEngine->SetNotifyHdl(Link<EENotify&,void>());
+ mpViewForwarder.reset();
+}
+
+void ScAccessibleCellTextData::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
+{
+ if ( rHint.GetId() == SfxHintId::Dying )
+ {
+ mpViewShell = nullptr; // invalid now
+ if (mpViewForwarder)
+ mpViewForwarder->SetInvalid();
+ }
+ ScAccessibleCellBaseTextData::Notify(rBC, rHint);
+}
+
+ScAccessibleTextData* ScAccessibleCellTextData::Clone() const
+{
+ return new ScAccessibleCellTextData( mpViewShell, aCellPos, meSplitPos, mpAccessibleCell );
+}
+
+SvxTextForwarder* ScAccessibleCellTextData::GetTextForwarder()
+{
+ ScCellTextData::GetTextForwarder(); // creates Forwarder and EditEngine
+
+ if ( pDocShell && pEditEngine && mpViewShell )
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ long nSizeX, nSizeY;
+ mpViewShell->GetViewData().GetMergeSizePixel(
+ aCellPos.Col(), aCellPos.Row(), nSizeX, nSizeY);
+
+ Size aSize(nSizeX, nSizeY);
+
+ // #i92143# text getRangeExtents reports incorrect 'x' values for spreadsheet cells
+ long nIndent = 0;
+ const SvxHorJustifyItem* pHorJustifyItem = rDoc.GetAttr( aCellPos, ATTR_HOR_JUSTIFY );
+ SvxCellHorJustify eHorJust = pHorJustifyItem ? pHorJustifyItem->GetValue() : SvxCellHorJustify::Standard;
+ if ( eHorJust == SvxCellHorJustify::Left )
+ {
+ const ScIndentItem* pIndentItem = rDoc.GetAttr( aCellPos, ATTR_INDENT );
+ if ( pIndentItem )
+ {
+ nIndent = static_cast< long >( pIndentItem->GetValue() );
+ }
+ }
+
+ const SvxMarginItem* pMarginItem = rDoc.GetAttr( aCellPos, ATTR_MARGIN );
+ ScViewData& rViewData = mpViewShell->GetViewData();
+ double nPPTX = rViewData.GetPPTX();
+ double nPPTY = rViewData.GetPPTY();
+ long nLeftM = ( pMarginItem ? static_cast< long >( ( pMarginItem->GetLeftMargin() + nIndent ) * nPPTX ) : 0 );
+ long nTopM = ( pMarginItem ? static_cast< long >( pMarginItem->GetTopMargin() * nPPTY ) : 0 );
+ long nRightM = ( pMarginItem ? static_cast< long >( pMarginItem->GetRightMargin() * nPPTX ) : 0 );
+ long nBottomM = ( pMarginItem ? static_cast< long >( pMarginItem->GetBottomMargin() * nPPTY ) : 0 );
+ long nWidth = aSize.getWidth() - nLeftM - nRightM;
+ aSize.setWidth( nWidth );
+ aSize.setHeight( aSize.getHeight() - nTopM - nBottomM );
+
+ vcl::Window* pWin = mpViewShell->GetWindowByPos( meSplitPos );
+ if ( pWin )
+ {
+ aSize = pWin->PixelToLogic( aSize, pEditEngine->GetRefMapMode() );
+ }
+
+ /* #i19430# Gnopernicus reads text partly if it sticks out of the cell
+ boundaries. This leads to wrong results in cases where the cell text
+ is rotated, because rotation is not taken into account when calcu-
+ lating the visible part of the text. In these cases we will expand
+ the cell size passed as paper size to the edit engine. The function
+ accessibility::AccessibleStaticTextBase::GetParagraphBoundingBox()
+ (see svx/source/accessibility/AccessibleStaticTextBase.cxx) will
+ return the size of the complete text then, which is used to expand
+ the cell bounding box in ScAccessibleCell::GetBoundingBox()
+ (see sc/source/ui/Accessibility/AccessibleCell.cxx). */
+ const ScRotateValueItem* pItem = rDoc.GetAttr( aCellPos, ATTR_ROTATE_VALUE );
+ if( pItem && (pItem->GetValue() != 0) )
+ {
+ pEditEngine->SetPaperSize( Size( LONG_MAX, aSize.getHeight() ) );
+ long nTxtWidth = static_cast< long >( pEditEngine->CalcTextWidth() );
+ aSize.setWidth( std::max( aSize.getWidth(), nTxtWidth + 2 ) );
+ }
+ else
+ {
+ // #i92143# text getRangeExtents reports incorrect 'x' values for spreadsheet cells
+ const ScLineBreakCell* pLineBreakItem = rDoc.GetAttr( aCellPos, ATTR_LINEBREAK );
+ bool bLineBreak = ( pLineBreakItem && pLineBreakItem->GetValue() );
+ if ( !bLineBreak )
+ {
+ long nTxtWidth = static_cast< long >( pEditEngine->CalcTextWidth() );
+ aSize.setWidth( ::std::max( aSize.getWidth(), nTxtWidth ) );
+ }
+ }
+
+ pEditEngine->SetPaperSize( aSize );
+
+ // #i92143# text getRangeExtents reports incorrect 'x' values for spreadsheet cells
+ if ( eHorJust == SvxCellHorJustify::Standard && rDoc.HasValueData( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab() ) )
+ {
+ pEditEngine->SetDefaultItem( SvxAdjustItem( SvxAdjust::Right, EE_PARA_JUST ) );
+ }
+
+ Size aTextSize;
+ if ( pWin )
+ {
+ aTextSize = pWin->LogicToPixel( Size( pEditEngine->CalcTextWidth(), pEditEngine->GetTextHeight() ), pEditEngine->GetRefMapMode() );
+ }
+ long nTextWidth = aTextSize.Width();
+ long nTextHeight = aTextSize.Height();
+
+ long nOffsetX = nLeftM;
+ long nDiffX = nTextWidth - nWidth;
+ if ( nDiffX > 0 )
+ {
+ switch ( eHorJust )
+ {
+ case SvxCellHorJustify::Right:
+ {
+ nOffsetX -= nDiffX;
+ }
+ break;
+ case SvxCellHorJustify::Center:
+ {
+ nOffsetX -= nDiffX / 2;
+ }
+ break;
+ default:
+ {
+ }
+ break;
+ }
+ }
+
+ long nOffsetY = 0;
+ const SvxVerJustifyItem* pVerJustifyItem = rDoc.GetAttr( aCellPos, ATTR_VER_JUSTIFY );
+ SvxCellVerJustify eVerJust = ( pVerJustifyItem ? pVerJustifyItem->GetValue() : SvxCellVerJustify::Standard );
+ switch ( eVerJust )
+ {
+ case SvxCellVerJustify::Standard:
+ case SvxCellVerJustify::Bottom:
+ {
+ nOffsetY = nSizeY - nBottomM - nTextHeight;
+ }
+ break;
+ case SvxCellVerJustify::Center:
+ {
+ nOffsetY = ( nSizeY - nTopM - nBottomM - nTextHeight ) / 2 + nTopM;
+ }
+ break;
+ default:
+ {
+ nOffsetY = nTopM;
+ }
+ break;
+ }
+
+ if ( mpAccessibleCell )
+ {
+ mpAccessibleCell->SetOffset( Point( nOffsetX, nOffsetY ) );
+ }
+
+ pEditEngine->SetNotifyHdl( LINK(this, ScAccessibleCellTextData, NotifyHdl) );
+ }
+
+ return pForwarder.get();
+}
+
+SvxViewForwarder* ScAccessibleCellTextData::GetViewForwarder()
+{
+ if (!mpViewForwarder)
+ mpViewForwarder.reset(new ScViewForwarder(mpViewShell, meSplitPos));
+ return mpViewForwarder.get();
+}
+
+SvxEditViewForwarder* ScAccessibleCellTextData::GetEditViewForwarder( bool /* bCreate */ )
+{
+ //#102219#; there should no EditViewForwarder be, because the cell is now readonly in this interface
+ return nullptr;
+}
+
+IMPL_LINK(ScAccessibleTextData, NotifyHdl, EENotify&, aNotify, void)
+{
+ ::std::unique_ptr< SfxHint > aHint = SvxEditSourceHelper::EENotification2Hint( &aNotify );
+
+ if (aHint)
+ GetBroadcaster().Broadcast(*aHint);
+}
+
+ScDocShell* ScAccessibleCellTextData::GetDocShell(ScTabViewShell* pViewShell)
+{
+ ScDocShell* pDocSh = nullptr;
+ if (pViewShell)
+ pDocSh = pViewShell->GetViewData().GetDocShell();
+ return pDocSh;
+}
+
+ScAccessibleEditObjectTextData::ScAccessibleEditObjectTextData(EditView* pEditView, OutputDevice* pWin, bool isClone)
+ :
+ mpEditView(pEditView),
+ mpEditEngine(pEditView ? pEditView->GetEditEngine() : nullptr),
+ mpWindow(pWin)
+{
+ // If the object is cloned, do NOT add notify hdl.
+ mbIsCloned = isClone;
+ if (mpEditEngine && !mbIsCloned)
+ mpEditEngine->SetNotifyHdl( LINK(this, ScAccessibleEditObjectTextData, NotifyHdl) );
+}
+
+ScAccessibleEditObjectTextData::~ScAccessibleEditObjectTextData()
+{
+ // If the object is cloned, do NOT set notify hdl.
+ if (mpEditEngine && !mbIsCloned)
+ mpEditEngine->SetNotifyHdl(Link<EENotify&,void>());
+ mpViewForwarder.reset();
+ mpEditViewForwarder.reset();
+ mpForwarder.reset();
+}
+
+void ScAccessibleEditObjectTextData::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
+{
+ if ( rHint.GetId() == SfxHintId::Dying )
+ {
+ mpWindow = nullptr;
+ mpEditView = nullptr;
+ mpEditEngine = nullptr;
+ mpForwarder.reset();
+ if (mpViewForwarder)
+ mpViewForwarder->SetInvalid();
+ if (mpEditViewForwarder)
+ mpEditViewForwarder->SetInvalid();
+ }
+ ScAccessibleTextData::Notify(rBC, rHint);
+}
+
+ScAccessibleTextData* ScAccessibleEditObjectTextData::Clone() const
+{
+ // Add para to indicate the object is cloned
+ return new ScAccessibleEditObjectTextData(mpEditView, mpWindow, true);
+}
+
+SvxTextForwarder* ScAccessibleEditObjectTextData::GetTextForwarder()
+{
+ if ((!mpForwarder && mpEditView) || (mpEditEngine && !mpEditEngine->GetNotifyHdl().IsSet()))
+ {
+ if (!mpEditEngine)
+ mpEditEngine = mpEditView->GetEditEngine();
+ // If the object is cloned, do NOT add notify hdl.
+ if (mpEditEngine && !mpEditEngine->GetNotifyHdl().IsSet()&&!mbIsCloned)
+ mpEditEngine->SetNotifyHdl( LINK(this, ScAccessibleEditObjectTextData, NotifyHdl) );
+ if(!mpForwarder)
+ mpForwarder.reset(new SvxEditEngineForwarder(*mpEditEngine));
+ }
+ return mpForwarder.get();
+}
+
+SvxViewForwarder* ScAccessibleEditObjectTextData::GetViewForwarder()
+{
+ if (!mpViewForwarder)
+ {
+ // i#49561 Get right-aligned cell content to be read by screenreader.
+ mpViewForwarder.reset(new ScEditObjectViewForwarder( mpWindow, mpEditView ));
+ }
+ return mpViewForwarder.get();
+}
+
+SvxEditViewForwarder* ScAccessibleEditObjectTextData::GetEditViewForwarder( bool bCreate )
+{
+ if (!mpEditViewForwarder && mpEditView)
+ mpEditViewForwarder.reset(new ScEditViewForwarder(mpEditView, mpWindow));
+ if (bCreate)
+ {
+ if (!mpEditView && mpEditViewForwarder)
+ {
+ mpEditViewForwarder.reset();
+ }
+ }
+ return mpEditViewForwarder.get();
+}
+
+IMPL_LINK(ScAccessibleEditObjectTextData, NotifyHdl, EENotify&, rNotify, void)
+{
+ ::std::unique_ptr< SfxHint > aHint = SvxEditSourceHelper::EENotification2Hint( &rNotify );
+
+ if (aHint)
+ GetBroadcaster().Broadcast(*aHint);
+}
+
+ScAccessibleEditLineTextData::ScAccessibleEditLineTextData(EditView* pEditView, OutputDevice* pWin)
+ :
+ ScAccessibleEditObjectTextData(pEditView, pWin),
+ mbEditEngineCreated(false)
+{
+ ScTextWnd* pTxtWnd = dynamic_cast<ScTextWnd*>( pWin );
+
+ if (pTxtWnd)
+ pTxtWnd->InsertAccessibleTextData( *this );
+}
+
+ScAccessibleEditLineTextData::~ScAccessibleEditLineTextData()
+{
+ ScTextWnd* pTxtWnd = dynamic_cast< ScTextWnd* >(mpWindow.get());
+
+ if (pTxtWnd)
+ {
+ assert(!pTxtWnd->IsDisposed());
+ pTxtWnd->RemoveAccessibleTextData( *this );
+ }
+
+ if (mbEditEngineCreated && mpEditEngine)
+ {
+ delete mpEditEngine;
+ mpEditEngine = nullptr; // don't access in ScAccessibleEditObjectTextData dtor!
+ }
+ else if (pTxtWnd && pTxtWnd->HasEditView() && pTxtWnd->GetEditView()->GetEditEngine())
+ {
+ // the NotifyHdl also has to be removed from the ScTextWnd's EditEngine
+ // (it's set in ScAccessibleEditLineTextData::GetTextForwarder, and mpEditEngine
+ // is reset there)
+ pTxtWnd->GetEditView()->GetEditEngine()->SetNotifyHdl(Link<EENotify&,void>());
+ }
+}
+
+void ScAccessibleEditLineTextData::Dispose()
+{
+ ScTextWnd* pTxtWnd = dynamic_cast<ScTextWnd*>(mpWindow.get());
+
+ if (pTxtWnd)
+ {
+ assert(!pTxtWnd->IsDisposed());
+ pTxtWnd->RemoveAccessibleTextData( *this );
+ }
+
+ ResetEditMode();
+ mpWindow = nullptr;
+}
+
+ScAccessibleTextData* ScAccessibleEditLineTextData::Clone() const
+{
+ return new ScAccessibleEditLineTextData(mpEditView, mpWindow);
+}
+
+SvxTextForwarder* ScAccessibleEditLineTextData::GetTextForwarder()
+{
+ ScTextWnd* pTxtWnd = dynamic_cast<ScTextWnd*>(mpWindow.get());
+
+ if (pTxtWnd)
+ {
+ if (pTxtWnd->HasEditView())
+ {
+ mpEditView = pTxtWnd->GetEditView();
+
+ if (mbEditEngineCreated && mpEditEngine)
+ ResetEditMode();
+ mbEditEngineCreated = false;
+
+ mpEditView = pTxtWnd->GetEditView();
+ ScAccessibleEditObjectTextData::GetTextForwarder(); // fill the mpForwarder
+ mpEditEngine = nullptr;
+ }
+ else
+ {
+ mpEditView = nullptr;
+
+ if (mpEditEngine && !mbEditEngineCreated)
+ ResetEditMode();
+ if (!mpEditEngine)
+ {
+ SfxItemPool* pEnginePool = EditEngine::CreatePool();
+ pEnginePool->FreezeIdRanges();
+ mpEditEngine = new ScFieldEditEngine(nullptr, pEnginePool, nullptr, true);
+ mbEditEngineCreated = true;
+ mpEditEngine->EnableUndo( false );
+ mpEditEngine->SetRefMapMode(MapMode(MapUnit::Map100thMM));
+ mpForwarder.reset(new SvxEditEngineForwarder(*mpEditEngine));
+
+ mpEditEngine->SetText(pTxtWnd->GetTextString());
+
+ Size aSize(pTxtWnd->GetSizePixel());
+
+ aSize = pTxtWnd->PixelToLogic(aSize, mpEditEngine->GetRefMapMode());
+
+ mpEditEngine->SetPaperSize(aSize);
+
+ mpEditEngine->SetNotifyHdl( LINK(this, ScAccessibleEditObjectTextData, NotifyHdl) );
+ }
+ }
+ }
+ return mpForwarder.get();
+}
+
+SvxEditViewForwarder* ScAccessibleEditLineTextData::GetEditViewForwarder( bool bCreate )
+{
+ ScTextWnd* pTxtWnd = dynamic_cast<ScTextWnd*>(mpWindow.get());
+
+ if (pTxtWnd)
+ {
+ if (!pTxtWnd->HasEditView() && bCreate)
+ {
+ if ( !pTxtWnd->IsInputActive() )
+ {
+ pTxtWnd->StartEditEngine();
+ pTxtWnd->GrabFocus();
+
+ mpEditView = pTxtWnd->GetEditView();
+ }
+ }
+ }
+
+ return ScAccessibleEditObjectTextData::GetEditViewForwarder(bCreate);
+}
+
+void ScAccessibleEditLineTextData::ResetEditMode()
+{
+ ScTextWnd* pTxtWnd = dynamic_cast<ScTextWnd*>(mpWindow.get());
+
+ if (mbEditEngineCreated && mpEditEngine)
+ delete mpEditEngine;
+ else if (pTxtWnd && pTxtWnd->HasEditView() && pTxtWnd->GetEditView()->GetEditEngine())
+ pTxtWnd->GetEditView()->GetEditEngine()->SetNotifyHdl(Link<EENotify&,void>());
+ mpEditEngine = nullptr;
+
+ mpForwarder.reset();
+ mpEditViewForwarder.reset();
+ mpViewForwarder.reset();
+ mbEditEngineCreated = false;
+}
+
+void ScAccessibleEditLineTextData::TextChanged()
+{
+ if (mbEditEngineCreated && mpEditEngine)
+ {
+ ScTextWnd* pTxtWnd = dynamic_cast<ScTextWnd*>(mpWindow.get());
+
+ if (pTxtWnd)
+ mpEditEngine->SetText(pTxtWnd->GetTextString());
+ }
+}
+
+void ScAccessibleEditLineTextData::StartEdit()
+{
+ ResetEditMode();
+ mpEditView = nullptr;
+
+ // send SdrHintKind::BeginEdit
+ SdrHint aHint(SdrHintKind::BeginEdit);
+ GetBroadcaster().Broadcast( aHint );
+}
+
+void ScAccessibleEditLineTextData::EndEdit()
+{
+ // send SdrHintKind::EndEdit
+ SdrHint aHint(SdrHintKind::EndEdit);
+ GetBroadcaster().Broadcast( aHint );
+
+ ResetEditMode();
+ mpEditView = nullptr;
+}
+
+// ScAccessiblePreviewCellTextData: shared data between sub objects of an accessible cell text object
+
+ScAccessiblePreviewCellTextData::ScAccessiblePreviewCellTextData(ScPreviewShell* pViewShell,
+ const ScAddress& rP)
+ : ScAccessibleCellBaseTextData(GetDocShell(pViewShell), rP),
+ mpViewShell(pViewShell)
+{
+}
+
+ScAccessiblePreviewCellTextData::~ScAccessiblePreviewCellTextData()
+{
+ if (pEditEngine)
+ pEditEngine->SetNotifyHdl(Link<EENotify&,void>());
+ mpViewForwarder.reset();
+}
+
+void ScAccessiblePreviewCellTextData::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
+{
+ if ( rHint.GetId() == SfxHintId::Dying )
+ {
+ mpViewShell = nullptr; // invalid now
+ if (mpViewForwarder)
+ mpViewForwarder->SetInvalid();
+ }
+ ScAccessibleCellBaseTextData::Notify(rBC, rHint);
+}
+
+ScAccessibleTextData* ScAccessiblePreviewCellTextData::Clone() const
+{
+ return new ScAccessiblePreviewCellTextData(mpViewShell, aCellPos);
+}
+
+SvxTextForwarder* ScAccessiblePreviewCellTextData::GetTextForwarder()
+{
+ bool bEditEngineBefore(pEditEngine != nullptr);
+
+ ScCellTextData::GetTextForwarder(); // creates Forwarder and EditEngine
+
+ if (!bEditEngineBefore && pEditEngine)
+ {
+ Size aSize(mpViewShell->GetLocationData().GetCellOutputRect(aCellPos).GetSize());
+ vcl::Window* pWin = mpViewShell->GetWindow();
+ if (pWin)
+ aSize = pWin->PixelToLogic(aSize, pEditEngine->GetRefMapMode());
+ pEditEngine->SetPaperSize(aSize);
+ }
+
+ if (pEditEngine)
+ pEditEngine->SetNotifyHdl( LINK(this, ScAccessiblePreviewCellTextData, NotifyHdl) );
+
+ return pForwarder.get();
+}
+
+SvxViewForwarder* ScAccessiblePreviewCellTextData::GetViewForwarder()
+{
+ if (!mpViewForwarder)
+ mpViewForwarder.reset(new ScPreviewCellViewForwarder(mpViewShell));
+ return mpViewForwarder.get();
+}
+
+ScDocShell* ScAccessiblePreviewCellTextData::GetDocShell(ScPreviewShell* pViewShell)
+{
+ ScDocShell* pDocSh = nullptr;
+ if (pViewShell)
+ pDocSh = static_cast<ScDocShell*>( pViewShell->GetDocument().GetDocumentShell());
+ return pDocSh;
+}
+
+// ScAccessiblePreviewHeaderCellTextData: shared data between sub objects of an accessible cell text object
+
+ScAccessiblePreviewHeaderCellTextData::ScAccessiblePreviewHeaderCellTextData(ScPreviewShell* pViewShell,
+ const OUString& rText, const ScAddress& rP, bool bColHeader, bool bRowHeader)
+ : ScAccessibleCellBaseTextData(GetDocShell(pViewShell), rP),
+ mpViewShell(pViewShell),
+ maText(rText),
+ mbColHeader(bColHeader),
+ mbRowHeader(bRowHeader)
+{
+}
+
+ScAccessiblePreviewHeaderCellTextData::~ScAccessiblePreviewHeaderCellTextData()
+{
+ if (pEditEngine)
+ pEditEngine->SetNotifyHdl(Link<EENotify&,void>());
+ mpViewForwarder.reset();
+}
+
+void ScAccessiblePreviewHeaderCellTextData::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
+{
+ if ( rHint.GetId() == SfxHintId::Dying )
+ {
+ mpViewShell = nullptr; // invalid now
+ if (mpViewForwarder)
+ mpViewForwarder->SetInvalid();
+ }
+ ScAccessibleCellBaseTextData::Notify(rBC, rHint);
+}
+
+ScAccessibleTextData* ScAccessiblePreviewHeaderCellTextData::Clone() const
+{
+ return new ScAccessiblePreviewHeaderCellTextData(mpViewShell, maText, aCellPos, mbColHeader, mbRowHeader);
+}
+
+SvxTextForwarder* ScAccessiblePreviewHeaderCellTextData::GetTextForwarder()
+{
+ if (!pEditEngine)
+ {
+ if ( pDocShell )
+ {
+ ScDocument& rDoc = pDocShell->GetDocument();
+ pEditEngine = rDoc.CreateFieldEditEngine();
+ }
+ else
+ {
+ SfxItemPool* pEnginePool = EditEngine::CreatePool();
+ pEnginePool->FreezeIdRanges();
+ pEditEngine.reset( new ScFieldEditEngine(nullptr, pEnginePool, nullptr, true) );
+ }
+ pEditEngine->EnableUndo( false );
+ if (pDocShell)
+ pEditEngine->SetRefDevice(pDocShell->GetRefDevice());
+ else
+ pEditEngine->SetRefMapMode(MapMode(MapUnit::Map100thMM));
+ pForwarder.reset( new SvxEditEngineForwarder(*pEditEngine) );
+ }
+
+ if (bDataValid)
+ return pForwarder.get();
+
+ if (!maText.isEmpty())
+ {
+ if ( mpViewShell )
+ {
+ Size aOutputSize;
+ vcl::Window* pWindow = mpViewShell->GetWindow();
+ if ( pWindow )
+ aOutputSize = pWindow->GetOutputSizePixel();
+ tools::Rectangle aVisRect( Point(), aOutputSize );
+ Size aSize(mpViewShell->GetLocationData().GetHeaderCellOutputRect(aVisRect, aCellPos, mbColHeader).GetSize());
+ if (pWindow)
+ aSize = pWindow->PixelToLogic(aSize, pEditEngine->GetRefMapMode());
+ pEditEngine->SetPaperSize(aSize);
+ }
+ pEditEngine->SetTextCurrentDefaults( maText );
+ }
+
+ bDataValid = true;
+
+ pEditEngine->SetNotifyHdl( LINK(this, ScAccessiblePreviewHeaderCellTextData, NotifyHdl) );
+
+ return pForwarder.get();
+}
+
+SvxViewForwarder* ScAccessiblePreviewHeaderCellTextData::GetViewForwarder()
+{
+ if (!mpViewForwarder)
+ mpViewForwarder.reset(new ScPreviewHeaderCellViewForwarder(mpViewShell));
+ return mpViewForwarder.get();
+}
+
+ScDocShell* ScAccessiblePreviewHeaderCellTextData::GetDocShell(ScPreviewShell* pViewShell)
+{
+ ScDocShell* pDocSh = nullptr;
+ if (pViewShell)
+ pDocSh = static_cast<ScDocShell*>(pViewShell->GetDocument().GetDocumentShell());
+ return pDocSh;
+}
+
+ScAccessibleHeaderTextData::ScAccessibleHeaderTextData(ScPreviewShell* pViewShell,
+ const EditTextObject* pEditObj, SvxAdjust eAdjust)
+ :
+ mpViewForwarder(nullptr),
+ mpViewShell(pViewShell),
+ mpDocSh(nullptr),
+ mpEditObj(pEditObj),
+ mbDataValid(false),
+ meAdjust(eAdjust)
+{
+ if (pViewShell)
+ mpDocSh = static_cast<ScDocShell*>(pViewShell->GetDocument().GetDocumentShell());
+ if (mpDocSh)
+ mpDocSh->GetDocument().AddUnoObject(*this);
+}
+
+ScAccessibleHeaderTextData::~ScAccessibleHeaderTextData()
+{
+ SolarMutexGuard aGuard; // needed for EditEngine dtor
+
+ if (mpDocSh)
+ mpDocSh->GetDocument().RemoveUnoObject(*this);
+ if (mpEditEngine)
+ mpEditEngine->SetNotifyHdl(Link<EENotify&,void>());
+ mpEditEngine.reset();
+ mpForwarder.reset();
+}
+
+ScAccessibleTextData* ScAccessibleHeaderTextData::Clone() const
+{
+ return new ScAccessibleHeaderTextData(mpViewShell, mpEditObj, meAdjust);
+}
+
+void ScAccessibleHeaderTextData::Notify( SfxBroadcaster&, const SfxHint& rHint )
+{
+ if ( rHint.GetId() == SfxHintId::Dying )
+ {
+ mpViewShell = nullptr;// invalid now
+ mpDocSh = nullptr;
+ if (mpViewForwarder)
+ mpViewForwarder->SetInvalid();
+ }
+}
+
+SvxTextForwarder* ScAccessibleHeaderTextData::GetTextForwarder()
+{
+ if (!mpEditEngine)
+ {
+ SfxItemPool* pEnginePool = EditEngine::CreatePool();
+ pEnginePool->FreezeIdRanges();
+ std::unique_ptr<ScHeaderEditEngine> pHdrEngine(new ScHeaderEditEngine( pEnginePool ));
+
+ pHdrEngine->EnableUndo( false );
+ pHdrEngine->SetRefMapMode(MapMode(MapUnit::MapTwip));
+
+ // default font must be set, independently of document
+ // -> use global pool from module
+
+ SfxItemSet aDefaults( pHdrEngine->GetEmptyItemSet() );
+ const ScPatternAttr& rPattern = SC_MOD()->GetPool().GetDefaultItem(ATTR_PATTERN);
+ rPattern.FillEditItemSet( &aDefaults );
+ // FillEditItemSet adjusts font height to 1/100th mm,
+ // but for header/footer twips is needed, as in the PatternAttr:
+ aDefaults.Put( rPattern.GetItem(ATTR_FONT_HEIGHT).CloneSetWhich(EE_CHAR_FONTHEIGHT) );
+ aDefaults.Put( rPattern.GetItem(ATTR_CJK_FONT_HEIGHT).CloneSetWhich(EE_CHAR_FONTHEIGHT_CJK) );
+ aDefaults.Put( rPattern.GetItem(ATTR_CTL_FONT_HEIGHT).CloneSetWhich(EE_CHAR_FONTHEIGHT_CTL) );
+ aDefaults.Put( SvxAdjustItem( meAdjust, EE_PARA_JUST ) );
+ pHdrEngine->SetDefaults( aDefaults );
+
+ ScHeaderFieldData aData;
+ if (mpViewShell)
+ mpViewShell->FillFieldData(aData);
+ else
+ ScHeaderFooterTextObj::FillDummyFieldData( aData );
+ pHdrEngine->SetData( aData );
+
+ mpEditEngine = std::move(pHdrEngine);
+ mpForwarder.reset(new SvxEditEngineForwarder(*mpEditEngine));
+ }
+
+ if (mbDataValid)
+ return mpForwarder.get();
+
+ if ( mpViewShell )
+ {
+ tools::Rectangle aVisRect;
+ mpViewShell->GetLocationData().GetHeaderPosition(aVisRect);
+ Size aSize(aVisRect.GetSize());
+ vcl::Window* pWin = mpViewShell->GetWindow();
+ if (pWin)
+ aSize = pWin->PixelToLogic(aSize, mpEditEngine->GetRefMapMode());
+ mpEditEngine->SetPaperSize(aSize);
+ }
+ if (mpEditObj)
+ mpEditEngine->SetTextCurrentDefaults(*mpEditObj);
+
+ mbDataValid = true;
+ return mpForwarder.get();
+}
+
+SvxViewForwarder* ScAccessibleHeaderTextData::GetViewForwarder()
+{
+ if (!mpViewForwarder)
+ mpViewForwarder = new ScPreviewHeaderFooterViewForwarder(mpViewShell);
+ return mpViewForwarder;
+}
+
+ScAccessibleNoteTextData::ScAccessibleNoteTextData(ScPreviewShell* pViewShell,
+ const OUString& sText, const ScAddress& aCellPos, bool bMarkNote)
+ :
+ mpViewForwarder(nullptr),
+ mpViewShell(pViewShell),
+ mpDocSh(nullptr),
+ msText(sText),
+ maCellPos(aCellPos),
+ mbMarkNote(bMarkNote),
+ mbDataValid(false)
+{
+ if (pViewShell)
+ mpDocSh = static_cast<ScDocShell*>(pViewShell->GetDocument().GetDocumentShell());
+ if (mpDocSh)
+ mpDocSh->GetDocument().AddUnoObject(*this);
+}
+
+ScAccessibleNoteTextData::~ScAccessibleNoteTextData()
+{
+ SolarMutexGuard aGuard; // needed for EditEngine dtor
+
+ if (mpDocSh)
+ mpDocSh->GetDocument().RemoveUnoObject(*this);
+ if (mpEditEngine)
+ mpEditEngine->SetNotifyHdl(Link<EENotify&,void>());
+ mpEditEngine.reset();
+ mpForwarder.reset();
+}
+
+ScAccessibleTextData* ScAccessibleNoteTextData::Clone() const
+{
+ return new ScAccessibleNoteTextData(mpViewShell, msText, maCellPos, mbMarkNote);
+}
+
+void ScAccessibleNoteTextData::Notify( SfxBroadcaster&, const SfxHint& rHint )
+{
+ if ( rHint.GetId() == SfxHintId::Dying )
+ {
+ mpViewShell = nullptr;// invalid now
+ mpDocSh = nullptr;
+ if (mpViewForwarder)
+ mpViewForwarder->SetInvalid();
+ }
+}
+
+SvxTextForwarder* ScAccessibleNoteTextData::GetTextForwarder()
+{
+ if (!mpEditEngine)
+ {
+ if ( mpDocSh )
+ {
+ ScDocument& rDoc = mpDocSh->GetDocument();
+ mpEditEngine = rDoc.CreateFieldEditEngine();
+ }
+ else
+ {
+ SfxItemPool* pEnginePool = EditEngine::CreatePool();
+ pEnginePool->FreezeIdRanges();
+ mpEditEngine.reset( new ScFieldEditEngine(nullptr, pEnginePool, nullptr, true) );
+ }
+ mpEditEngine->EnableUndo( false );
+ if (mpDocSh)
+ mpEditEngine->SetRefDevice(mpDocSh->GetRefDevice());
+ else
+ mpEditEngine->SetRefMapMode(MapMode(MapUnit::Map100thMM));
+ mpForwarder.reset( new SvxEditEngineForwarder(*mpEditEngine) );
+ }
+
+ if (mbDataValid)
+ return mpForwarder.get();
+
+ if (!msText.isEmpty())
+ {
+
+ if ( mpViewShell )
+ {
+ Size aOutputSize;
+ vcl::Window* pWindow = mpViewShell->GetWindow();
+ if ( pWindow )
+ aOutputSize = pWindow->GetOutputSizePixel();
+ tools::Rectangle aVisRect( Point(), aOutputSize );
+ Size aSize(mpViewShell->GetLocationData().GetNoteInRangeOutputRect(aVisRect, mbMarkNote, maCellPos).GetSize());
+ if (pWindow)
+ aSize = pWindow->PixelToLogic(aSize, mpEditEngine->GetRefMapMode());
+ mpEditEngine->SetPaperSize(aSize);
+ }
+ mpEditEngine->SetTextCurrentDefaults( msText );
+ }
+
+ mbDataValid = true;
+
+ mpEditEngine->SetNotifyHdl( LINK(this, ScAccessibleNoteTextData, NotifyHdl) );
+
+ return mpForwarder.get();
+}
+
+SvxViewForwarder* ScAccessibleNoteTextData::GetViewForwarder()
+{
+ if (!mpViewForwarder)
+ mpViewForwarder = new ScPreviewNoteViewForwarder(mpViewShell);
+ return mpViewForwarder;
+}
+
+// CSV import =================================================================
+
+class ScCsvViewForwarder : public SvxViewForwarder
+{
+ VclPtr<OutputDevice> mpWindow;
+
+public:
+ explicit ScCsvViewForwarder( OutputDevice* pWindow );
+
+ virtual bool IsValid() const override;
+ virtual Point LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const override;
+ virtual Point PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const override;
+
+ void SetInvalid();
+};
+
+ScCsvViewForwarder::ScCsvViewForwarder( OutputDevice* pWindow ) :
+ mpWindow( pWindow )
+{
+}
+
+bool ScCsvViewForwarder::IsValid() const
+{
+ return mpWindow != nullptr;
+}
+
+Point ScCsvViewForwarder::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
+{
+ if( !mpWindow ) return Point();
+ return mpWindow->LogicToPixel( rPoint, rMapMode );
+}
+
+Point ScCsvViewForwarder::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
+{
+ if( !mpWindow ) return Point();
+ return mpWindow->PixelToLogic( rPoint, rMapMode );
+}
+
+void ScCsvViewForwarder::SetInvalid()
+{
+ mpWindow = nullptr;
+}
+
+ScAccessibleCsvTextData::ScAccessibleCsvTextData(
+ OutputDevice* pWindow, EditEngine* pEditEngine,
+ const OUString& rCellText, const Size& rCellSize ) :
+ mpWindow( pWindow ),
+ mpEditEngine( pEditEngine ),
+ maCellText( rCellText ),
+ maCellSize( rCellSize )
+{
+}
+
+ScAccessibleCsvTextData::~ScAccessibleCsvTextData()
+{
+}
+
+void ScAccessibleCsvTextData::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
+{
+ if ( rHint.GetId() == SfxHintId::Dying )
+ {
+ mpWindow = nullptr;
+ mpEditEngine = nullptr;
+ if (mpViewForwarder)
+ mpViewForwarder->SetInvalid();
+ }
+ ScAccessibleTextData::Notify( rBC, rHint );
+}
+
+ScAccessibleTextData* ScAccessibleCsvTextData::Clone() const
+{
+ return new ScAccessibleCsvTextData( mpWindow, mpEditEngine, maCellText, maCellSize );
+}
+
+SvxTextForwarder* ScAccessibleCsvTextData::GetTextForwarder()
+{
+ if( mpEditEngine )
+ {
+ mpEditEngine->SetPaperSize( maCellSize );
+ mpEditEngine->SetText( maCellText );
+ if( !mpTextForwarder )
+ mpTextForwarder.reset( new SvxEditEngineForwarder( *mpEditEngine ) );
+ }
+ else
+ mpTextForwarder.reset();
+ return mpTextForwarder.get();
+}
+
+SvxViewForwarder* ScAccessibleCsvTextData::GetViewForwarder()
+{
+ if( !mpViewForwarder )
+ mpViewForwarder.reset( new ScCsvViewForwarder( mpWindow ) );
+ return mpViewForwarder.get();
+}
+
+SvxEditViewForwarder* ScAccessibleCsvTextData::GetEditViewForwarder( bool /* bCreate */ )
+{
+ return nullptr;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */