tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / ui / Accessibility / AccessibleText.cxx
blobcea5fd635b7a0796bd79ec029b1370a0546ec930
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <scitems.hxx>
21 #include <editeng/eeitem.hxx>
23 #include <memory>
24 #include <AccessibleText.hxx>
25 #include <AccessibleCell.hxx>
26 #include <attrib.hxx>
27 #include <tabvwsh.hxx>
28 #include <editutil.hxx>
29 #include <document.hxx>
30 #include <scmod.hxx>
31 #include <prevwsh.hxx>
32 #include <docsh.hxx>
33 #include <prevloc.hxx>
34 #include <patattr.hxx>
35 #include <inputwin.hxx>
36 #include <editeng/unofored.hxx>
37 #include <editeng/editview.hxx>
38 #include <editeng/unoedhlp.hxx>
39 #include <editeng/fhgtitem.hxx>
40 #include <editeng/adjustitem.hxx>
41 #include <editeng/justifyitem.hxx>
42 #include <svx/svdmodel.hxx>
43 #include <svx/algitem.hxx>
44 #include <utility>
45 #include <vcl/svapp.hxx>
47 class ScViewForwarder : public SvxViewForwarder
49 ScTabViewShell* mpViewShell;
50 ScSplitPos meSplitPos;
51 public:
52 ScViewForwarder(ScTabViewShell* pViewShell, ScSplitPos eSplitPos);
54 virtual bool IsValid() const override;
55 virtual Point LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const override;
56 virtual Point PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const override;
58 void SetInvalid();
61 ScViewForwarder::ScViewForwarder(ScTabViewShell* pViewShell, ScSplitPos eSplitPos)
63 mpViewShell(pViewShell),
64 meSplitPos(eSplitPos)
68 bool ScViewForwarder::IsValid() const
70 return mpViewShell != nullptr;
73 Point ScViewForwarder::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
75 if (mpViewShell)
77 vcl::Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
78 if (pWindow)
79 return pWindow->LogicToPixel( rPoint, rMapMode );
81 else
83 OSL_FAIL("this ViewForwarder is not valid");
85 return Point();
88 Point ScViewForwarder::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
90 if (mpViewShell)
92 vcl::Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
93 if (pWindow)
94 return pWindow->PixelToLogic( rPoint, rMapMode );
96 else
98 OSL_FAIL("this ViewForwarder is not valid");
100 return Point();
103 void ScViewForwarder::SetInvalid()
105 mpViewShell = nullptr;
108 class ScEditObjectViewForwarder : public SvxViewForwarder
110 VclPtr<OutputDevice> mpWindow;
111 // #i49561# EditView needed for access to its visible area.
112 const EditView* mpEditView;
113 public:
114 ScEditObjectViewForwarder( OutputDevice* pWindow,
115 const EditView* _pEditView);
117 virtual bool IsValid() const override;
118 virtual Point LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const override;
119 virtual Point PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const override;
121 void SetInvalid();
124 ScEditObjectViewForwarder::ScEditObjectViewForwarder( OutputDevice* pWindow,
125 const EditView* _pEditView )
126 : mpWindow(pWindow)
127 , mpEditView( _pEditView )
131 bool ScEditObjectViewForwarder::IsValid() const
133 return (mpWindow != nullptr);
136 Point ScEditObjectViewForwarder::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
138 if (mpWindow)
140 // #i49561# - consider offset of the visible area
141 // of the EditView before converting point to pixel.
142 Point aPoint( rPoint );
143 if ( mpEditView )
145 tools::Rectangle aEditViewVisArea( mpEditView->GetVisArea() );
146 aPoint += aEditViewVisArea.TopLeft();
148 return mpWindow->LogicToPixel( aPoint, rMapMode );
150 else
152 OSL_FAIL("this ViewForwarder is not valid");
154 return Point();
157 Point ScEditObjectViewForwarder::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
159 if (mpWindow)
161 // #i49561# - consider offset of the visible area
162 // of the EditView after converting point to logic.
163 Point aPoint( mpWindow->PixelToLogic( rPoint, rMapMode ) );
164 if ( mpEditView )
166 tools::Rectangle aEditViewVisArea( mpEditView->GetVisArea() );
167 aPoint -= aEditViewVisArea.TopLeft();
169 return aPoint;
171 else
173 OSL_FAIL("this ViewForwarder is not valid");
175 return Point();
178 void ScEditObjectViewForwarder::SetInvalid()
180 mpWindow = nullptr;
183 class ScPreviewViewForwarder : public SvxViewForwarder
185 protected:
186 ScPreviewShell* mpViewShell;
187 public:
188 explicit ScPreviewViewForwarder(ScPreviewShell* pViewShell);
190 virtual bool IsValid() const override;
191 virtual Point LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const override;
192 virtual Point PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const override;
194 void SetInvalid();
197 ScPreviewViewForwarder::ScPreviewViewForwarder(ScPreviewShell* pViewShell)
198 : mpViewShell(pViewShell)
202 bool ScPreviewViewForwarder::IsValid() const
204 return mpViewShell != nullptr;
207 Point ScPreviewViewForwarder::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
209 if (mpViewShell)
211 vcl::Window* pWindow = mpViewShell->GetWindow();
212 if (pWindow)
214 MapMode aMapMode(pWindow->GetMapMode().GetMapUnit());
215 Point aPoint2( OutputDevice::LogicToLogic( rPoint, rMapMode, aMapMode) );
216 return pWindow->LogicToPixel(aPoint2);
219 else
221 OSL_FAIL("this ViewForwarder is not valid");
223 return Point();
226 Point ScPreviewViewForwarder::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
228 if (mpViewShell)
230 vcl::Window* pWindow = mpViewShell->GetWindow();
231 if (pWindow)
233 MapMode aMapMode(pWindow->GetMapMode());
234 aMapMode.SetOrigin(Point());
235 Point aPoint1( pWindow->PixelToLogic( rPoint ) );
236 Point aPoint2( OutputDevice::LogicToLogic( aPoint1,
237 MapMode(aMapMode.GetMapUnit()),
238 rMapMode ) );
239 return aPoint2;
242 else
244 OSL_FAIL("this ViewForwarder is not valid");
246 return Point();
249 void ScPreviewViewForwarder::SetInvalid()
251 mpViewShell = nullptr;
254 namespace {
256 class ScPreviewHeaderFooterViewForwarder : public ScPreviewViewForwarder
258 public:
259 ScPreviewHeaderFooterViewForwarder(ScPreviewShell* pViewShell);
264 ScPreviewHeaderFooterViewForwarder::ScPreviewHeaderFooterViewForwarder(ScPreviewShell* pViewShell)
266 ScPreviewViewForwarder(pViewShell)
270 namespace {
272 class ScPreviewCellViewForwarder : public ScPreviewViewForwarder
274 public:
275 ScPreviewCellViewForwarder(ScPreviewShell* pViewShell);
280 ScPreviewCellViewForwarder::ScPreviewCellViewForwarder(ScPreviewShell* pViewShell)
282 ScPreviewViewForwarder(pViewShell)
286 namespace {
288 class ScPreviewHeaderCellViewForwarder : public ScPreviewViewForwarder
290 public:
291 ScPreviewHeaderCellViewForwarder(ScPreviewShell* pViewShell);
296 ScPreviewHeaderCellViewForwarder::ScPreviewHeaderCellViewForwarder(ScPreviewShell* pViewShell)
298 ScPreviewViewForwarder(pViewShell)
302 namespace {
304 class ScPreviewNoteViewForwarder : public ScPreviewViewForwarder
306 public:
307 ScPreviewNoteViewForwarder(ScPreviewShell* pViewShell);
312 ScPreviewNoteViewForwarder::ScPreviewNoteViewForwarder(ScPreviewShell* pViewShell)
314 ScPreviewViewForwarder(pViewShell)
318 class ScEditViewForwarder : public SvxEditViewForwarder
320 EditView* mpEditView;
321 VclPtr<OutputDevice> mpWindow;
322 public:
323 ScEditViewForwarder(EditView* pEditView, OutputDevice* pWin);
325 virtual bool IsValid() const override;
326 virtual Point LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const override;
327 virtual Point PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const override;
328 virtual bool GetSelection( ESelection& rSelection ) const override;
329 virtual bool SetSelection( const ESelection& rSelection ) override;
330 virtual bool Copy() override;
331 virtual bool Cut() override;
332 virtual bool Paste() override;
334 void SetInvalid();
337 ScEditViewForwarder::ScEditViewForwarder(EditView* pEditView, OutputDevice* pWin)
338 : mpEditView(pEditView)
339 , mpWindow(pWin)
343 bool ScEditViewForwarder::IsValid() const
345 return mpWindow && mpEditView;
348 Point ScEditViewForwarder::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
350 if (mpWindow)
351 return mpWindow->LogicToPixel( rPoint, rMapMode );
352 else
354 OSL_FAIL("this ViewForwarder is not valid");
356 return Point();
359 Point ScEditViewForwarder::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
361 if (mpWindow)
362 return mpWindow->PixelToLogic( rPoint, rMapMode );
363 else
365 OSL_FAIL("this ViewForwarder is not valid");
367 return Point();
370 bool ScEditViewForwarder::GetSelection( ESelection& rSelection ) const
372 bool bResult(false);
373 if (IsValid())
375 rSelection = mpEditView->GetSelection();
376 bResult = true;
378 else
380 OSL_FAIL("this ViewForwarder is not valid");
382 return bResult;
385 bool ScEditViewForwarder::SetSelection( const ESelection& rSelection )
387 bool bResult(false);
388 if (IsValid())
390 mpEditView->SetSelection(rSelection);
391 bResult = true;
393 else
395 OSL_FAIL("this ViewForwarder is not valid");
397 return bResult;
400 bool ScEditViewForwarder::Copy()
402 bool bResult(false);
403 if (IsValid())
405 mpEditView->Copy();
406 bResult = true;
408 else
410 OSL_FAIL("this ViewForwarder is not valid");
412 return bResult;
415 bool ScEditViewForwarder::Cut()
417 bool bResult(false);
418 if (IsValid())
420 mpEditView->Cut();
421 bResult = true;
423 else
425 OSL_FAIL("this ViewForwarder is not valid");
427 return bResult;
430 bool ScEditViewForwarder::Paste()
432 bool bResult(false);
433 if (IsValid())
435 mpEditView->Paste();
436 bResult = true;
438 else
440 OSL_FAIL("this ViewForwarder is not valid");
442 return bResult;
445 void ScEditViewForwarder::SetInvalid()
447 mpWindow = nullptr;
448 mpEditView = nullptr;
451 // ScAccessibleCellTextData: shared data between sub objects of an accessible cell text object
453 ScAccessibleCellTextData::ScAccessibleCellTextData(ScTabViewShell* pViewShell,
454 const ScAddress& rP, ScSplitPos eSplitPos, ScAccessibleCell* pAccCell)
455 : ScAccessibleCellBaseTextData(GetDocShell(pViewShell), rP),
456 mpViewShell(pViewShell),
457 meSplitPos(eSplitPos),
458 mpAccessibleCell( pAccCell )
462 ScAccessibleCellTextData::~ScAccessibleCellTextData()
464 if (pEditEngine)
465 pEditEngine->SetNotifyHdl(Link<EENotify&,void>());
466 mpViewForwarder.reset();
469 void ScAccessibleCellTextData::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
471 if ( rHint.GetId() == SfxHintId::Dying )
473 mpViewShell = nullptr; // invalid now
474 if (mpViewForwarder)
475 mpViewForwarder->SetInvalid();
477 ScAccessibleCellBaseTextData::Notify(rBC, rHint);
480 ScAccessibleTextData* ScAccessibleCellTextData::Clone() const
482 return new ScAccessibleCellTextData( mpViewShell, aCellPos, meSplitPos, mpAccessibleCell );
485 SvxTextForwarder* ScAccessibleCellTextData::GetTextForwarder()
487 ScCellTextData::GetTextForwarder(); // creates Forwarder and EditEngine
489 if ( pDocShell && pEditEngine && mpViewShell )
491 ScDocument& rDoc = pDocShell->GetDocument();
492 tools::Long nSizeX, nSizeY;
493 mpViewShell->GetViewData().GetMergeSizePixel(
494 aCellPos.Col(), aCellPos.Row(), nSizeX, nSizeY);
496 Size aSize(nSizeX, nSizeY);
498 // #i92143# text getRangeExtents reports incorrect 'x' values for spreadsheet cells
499 tools::Long nIndent = 0;
500 const SvxHorJustifyItem* pHorJustifyItem = rDoc.GetAttr( aCellPos, ATTR_HOR_JUSTIFY );
501 SvxCellHorJustify eHorJust = pHorJustifyItem ? pHorJustifyItem->GetValue() : SvxCellHorJustify::Standard;
502 if ( eHorJust == SvxCellHorJustify::Left )
504 const ScIndentItem* pIndentItem = rDoc.GetAttr( aCellPos, ATTR_INDENT );
505 if ( pIndentItem )
507 nIndent = static_cast< tools::Long >( pIndentItem->GetValue() );
511 const SvxMarginItem* pMarginItem = rDoc.GetAttr( aCellPos, ATTR_MARGIN );
512 ScViewData& rViewData = mpViewShell->GetViewData();
513 double nPPTX = rViewData.GetPPTX();
514 double nPPTY = rViewData.GetPPTY();
515 tools::Long nLeftM = ( pMarginItem ? static_cast< tools::Long >( ( pMarginItem->GetLeftMargin() + nIndent ) * nPPTX ) : 0 );
516 tools::Long nTopM = ( pMarginItem ? static_cast< tools::Long >( pMarginItem->GetTopMargin() * nPPTY ) : 0 );
517 tools::Long nRightM = ( pMarginItem ? static_cast< tools::Long >( pMarginItem->GetRightMargin() * nPPTX ) : 0 );
518 tools::Long nBottomM = ( pMarginItem ? static_cast< tools::Long >( pMarginItem->GetBottomMargin() * nPPTY ) : 0 );
519 tools::Long nWidth = aSize.getWidth() - nLeftM - nRightM;
520 aSize.setWidth( nWidth );
521 aSize.setHeight( aSize.getHeight() - nTopM - nBottomM );
523 vcl::Window* pWin = mpViewShell->GetWindowByPos( meSplitPos );
524 if ( pWin )
526 aSize = pWin->PixelToLogic( aSize, pEditEngine->GetRefMapMode() );
529 /* #i19430# Gnopernicus reads text partly if it sticks out of the cell
530 boundaries. This leads to wrong results in cases where the cell text
531 is rotated, because rotation is not taken into account when calcu-
532 lating the visible part of the text. In these cases we will expand
533 the cell size passed as paper size to the edit engine. The function
534 accessibility::AccessibleStaticTextBase::GetParagraphBoundingBox()
535 (see svx/source/accessibility/AccessibleStaticTextBase.cxx) will
536 return the size of the complete text then, which is used to expand
537 the cell bounding box in ScAccessibleCell::GetBoundingBox()
538 (see sc/source/ui/Accessibility/AccessibleCell.cxx). */
539 const ScRotateValueItem* pItem = rDoc.GetAttr( aCellPos, ATTR_ROTATE_VALUE );
540 if( pItem && (pItem->GetValue() != 0_deg100) )
542 pEditEngine->SetPaperSize( Size( LONG_MAX, aSize.getHeight() ) );
543 tools::Long nTxtWidth = static_cast< tools::Long >( pEditEngine->CalcTextWidth() );
544 aSize.setWidth( std::max( aSize.getWidth(), nTxtWidth + 2 ) );
546 else
548 // #i92143# text getRangeExtents reports incorrect 'x' values for spreadsheet cells
549 const ScLineBreakCell* pLineBreakItem = rDoc.GetAttr( aCellPos, ATTR_LINEBREAK );
550 bool bLineBreak = ( pLineBreakItem && pLineBreakItem->GetValue() );
551 if ( !bLineBreak )
553 tools::Long nTxtWidth = static_cast< tools::Long >( pEditEngine->CalcTextWidth() );
554 aSize.setWidth( ::std::max( aSize.getWidth(), nTxtWidth ) );
558 pEditEngine->SetPaperSize( aSize );
560 // #i92143# text getRangeExtents reports incorrect 'x' values for spreadsheet cells
561 if ( eHorJust == SvxCellHorJustify::Standard && rDoc.HasValueData( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab() ) )
563 pEditEngine->SetDefaultItem( SvxAdjustItem( SvxAdjust::Right, EE_PARA_JUST ) );
566 Size aTextSize;
567 if ( pWin )
569 aTextSize = pWin->LogicToPixel( Size( pEditEngine->CalcTextWidth(), pEditEngine->GetTextHeight() ), pEditEngine->GetRefMapMode() );
571 tools::Long nTextWidth = aTextSize.Width();
572 tools::Long nTextHeight = aTextSize.Height();
574 tools::Long nOffsetX = nLeftM;
575 tools::Long nDiffX = nTextWidth - nWidth;
576 if ( nDiffX > 0 )
578 switch ( eHorJust )
580 case SvxCellHorJustify::Right:
582 nOffsetX -= nDiffX;
584 break;
585 case SvxCellHorJustify::Center:
587 nOffsetX -= nDiffX / 2;
589 break;
590 default:
593 break;
597 tools::Long nOffsetY = 0;
598 const SvxVerJustifyItem* pVerJustifyItem = rDoc.GetAttr( aCellPos, ATTR_VER_JUSTIFY );
599 SvxCellVerJustify eVerJust = ( pVerJustifyItem ? pVerJustifyItem->GetValue() : SvxCellVerJustify::Standard );
600 switch ( eVerJust )
602 case SvxCellVerJustify::Standard:
603 case SvxCellVerJustify::Bottom:
605 nOffsetY = nSizeY - nBottomM - nTextHeight;
607 break;
608 case SvxCellVerJustify::Center:
610 nOffsetY = ( nSizeY - nTopM - nBottomM - nTextHeight ) / 2 + nTopM;
612 break;
613 default:
615 nOffsetY = nTopM;
617 break;
620 if ( mpAccessibleCell )
622 mpAccessibleCell->SetOffset( Point( nOffsetX, nOffsetY ) );
625 pEditEngine->SetNotifyHdl( LINK(this, ScAccessibleCellTextData, NotifyHdl) );
628 return pForwarder.get();
631 SvxViewForwarder* ScAccessibleCellTextData::GetViewForwarder()
633 if (!mpViewForwarder)
634 mpViewForwarder.reset(new ScViewForwarder(mpViewShell, meSplitPos));
635 return mpViewForwarder.get();
638 SvxEditViewForwarder* ScAccessibleCellTextData::GetEditViewForwarder( bool /* bCreate */ )
640 //#102219#; there should no EditViewForwarder be, because the cell is now readonly in this interface
641 return nullptr;
644 IMPL_LINK(ScAccessibleTextData, NotifyHdl, EENotify&, aNotify, void)
646 ::std::unique_ptr< SfxHint > aHint = SvxEditSourceHelper::EENotification2Hint( &aNotify );
648 if (aHint)
649 GetBroadcaster().Broadcast(*aHint);
652 ScDocShell* ScAccessibleCellTextData::GetDocShell(ScTabViewShell* pViewShell)
654 ScDocShell* pDocSh = nullptr;
655 if (pViewShell)
656 pDocSh = pViewShell->GetViewData().GetDocShell();
657 return pDocSh;
660 ScAccessibleEditObjectTextData::ScAccessibleEditObjectTextData(EditView* pEditView, OutputDevice* pWin, bool isClone)
661 : mpEditView(pEditView)
662 , mpEditEngine(pEditView ? &pEditView->getEditEngine() : nullptr)
663 , mpWindow(pWin)
665 // If the object is cloned, do NOT add notify hdl.
666 mbIsCloned = isClone;
667 if (mpEditEngine && !mbIsCloned)
668 mpEditEngine->SetNotifyHdl( LINK(this, ScAccessibleEditObjectTextData, NotifyHdl) );
671 ScAccessibleEditObjectTextData::~ScAccessibleEditObjectTextData()
673 // If the object is cloned, do NOT set notify hdl.
674 if (mpEditEngine && !mbIsCloned)
675 mpEditEngine->SetNotifyHdl(Link<EENotify&,void>());
676 mpViewForwarder.reset();
677 mpEditViewForwarder.reset();
678 mpForwarder.reset();
681 void ScAccessibleEditObjectTextData::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
683 if ( rHint.GetId() == SfxHintId::Dying )
685 mpWindow = nullptr;
686 mpEditView = nullptr;
687 mpEditEngine = nullptr;
688 mpForwarder.reset();
689 if (mpViewForwarder)
690 mpViewForwarder->SetInvalid();
691 if (mpEditViewForwarder)
692 mpEditViewForwarder->SetInvalid();
694 ScAccessibleTextData::Notify(rBC, rHint);
697 ScAccessibleTextData* ScAccessibleEditObjectTextData::Clone() const
699 // Add para to indicate the object is cloned
700 return new ScAccessibleEditObjectTextData(mpEditView, mpWindow, true);
703 SvxTextForwarder* ScAccessibleEditObjectTextData::GetTextForwarder()
705 if ((!mpForwarder && mpEditView) || (mpEditEngine && !mpEditEngine->GetNotifyHdl().IsSet()))
707 if (!mpEditEngine)
708 mpEditEngine = &mpEditView->getEditEngine();
709 // If the object is cloned, do NOT add notify hdl.
710 if (mpEditEngine && !mpEditEngine->GetNotifyHdl().IsSet()&&!mbIsCloned)
711 mpEditEngine->SetNotifyHdl( LINK(this, ScAccessibleEditObjectTextData, NotifyHdl) );
712 if(!mpForwarder)
713 mpForwarder.reset(new SvxEditEngineForwarder(*mpEditEngine));
715 return mpForwarder.get();
718 SvxViewForwarder* ScAccessibleEditObjectTextData::GetViewForwarder()
720 if (!mpViewForwarder)
722 // i#49561 Get right-aligned cell content to be read by screenreader.
723 mpViewForwarder.reset(new ScEditObjectViewForwarder( mpWindow, mpEditView ));
725 return mpViewForwarder.get();
728 SvxEditViewForwarder* ScAccessibleEditObjectTextData::GetEditViewForwarder( bool bCreate )
730 if (!mpEditViewForwarder && mpEditView)
731 mpEditViewForwarder.reset(new ScEditViewForwarder(mpEditView, mpWindow));
732 if (bCreate)
734 if (!mpEditView && mpEditViewForwarder)
736 mpEditViewForwarder.reset();
739 return mpEditViewForwarder.get();
742 IMPL_LINK(ScAccessibleEditObjectTextData, NotifyHdl, EENotify&, rNotify, void)
744 ::std::unique_ptr< SfxHint > aHint = SvxEditSourceHelper::EENotification2Hint( &rNotify );
746 if (aHint)
747 GetBroadcaster().Broadcast(*aHint);
750 ScAccessibleEditLineTextData::ScAccessibleEditLineTextData(EditView* pEditView,
751 OutputDevice* pWin,
752 ScTextWnd* pTxtWnd)
753 : ScAccessibleEditObjectTextData(pEditView, pWin)
754 , mpTxtWnd(pTxtWnd)
755 , mbEditEngineCreated(false)
757 if (mpTxtWnd)
758 mpTxtWnd->InsertAccessibleTextData( *this );
761 ScAccessibleEditLineTextData::~ScAccessibleEditLineTextData()
763 if (mpTxtWnd)
764 mpTxtWnd->RemoveAccessibleTextData( *this );
766 if (mbEditEngineCreated && mpEditEngine)
768 delete mpEditEngine;
769 mpEditEngine = nullptr; // don't access in ScAccessibleEditObjectTextData dtor!
771 else if (mpTxtWnd && mpTxtWnd->HasEditView())
773 // the NotifyHdl also has to be removed from the ScTextWnd's EditEngine
774 // (it's set in ScAccessibleEditLineTextData::GetTextForwarder, and mpEditEngine
775 // is reset there)
776 mpTxtWnd->GetEditView()->getEditEngine().SetNotifyHdl(Link<EENotify&,void>());
780 void ScAccessibleEditLineTextData::Dispose()
782 if (mpTxtWnd)
783 mpTxtWnd->RemoveAccessibleTextData( *this );
785 ResetEditMode();
786 mpWindow = nullptr;
787 mpTxtWnd = nullptr;
790 ScAccessibleTextData* ScAccessibleEditLineTextData::Clone() const
792 return new ScAccessibleEditLineTextData(mpEditView, mpWindow, mpTxtWnd);
795 SvxTextForwarder* ScAccessibleEditLineTextData::GetTextForwarder()
797 if (mpTxtWnd)
799 if (mpTxtWnd->HasEditView())
801 mpEditView = mpTxtWnd->GetEditView();
803 if (mbEditEngineCreated && mpEditEngine)
804 ResetEditMode();
805 mbEditEngineCreated = false;
807 mpEditView = mpTxtWnd->GetEditView();
808 ScAccessibleEditObjectTextData::GetTextForwarder(); // fill the mpForwarder
809 mpEditEngine = nullptr;
811 else
813 mpEditView = nullptr;
815 if (mpEditEngine && !mbEditEngineCreated)
816 ResetEditMode();
817 if (!mpEditEngine)
819 rtl::Reference<SfxItemPool> pEnginePool = EditEngine::CreatePool();
820 mpEditEngine = new ScFieldEditEngine(nullptr, pEnginePool.get(), nullptr, true);
821 mbEditEngineCreated = true;
822 mpEditEngine->EnableUndo( false );
823 mpEditEngine->SetRefMapMode(MapMode(MapUnit::Map100thMM));
824 mpForwarder.reset(new SvxEditEngineForwarder(*mpEditEngine));
826 mpEditEngine->SetText(mpTxtWnd->GetTextString());
828 #if 0
829 Size aSize(pTxtWnd->GetSizePixel());
830 aSize = pTxtWnd->PixelToLogic(aSize, mpEditEngine->GetRefMapMode());
831 mpEditEngine->SetPaperSize(aSize);
832 #else
833 OutputDevice& rDevice = mpTxtWnd->GetDrawingArea()->get_ref_device();
834 Size aSize(rDevice.GetOutputSizePixel());
835 aSize = rDevice.PixelToLogic(aSize, mpEditEngine->GetRefMapMode());
836 mpEditEngine->SetPaperSize(aSize);
837 #endif
839 mpEditEngine->SetNotifyHdl( LINK(this, ScAccessibleEditObjectTextData, NotifyHdl) );
843 return mpForwarder.get();
846 SvxEditViewForwarder* ScAccessibleEditLineTextData::GetEditViewForwarder( bool bCreate )
848 if (mpTxtWnd)
850 if (!mpTxtWnd->HasEditView() && bCreate)
852 if ( !mpTxtWnd->IsInputActive() )
854 mpTxtWnd->StartEditEngine();
855 mpTxtWnd->GrabFocus();
857 mpEditView = mpTxtWnd->GetEditView();
862 return ScAccessibleEditObjectTextData::GetEditViewForwarder(bCreate);
865 void ScAccessibleEditLineTextData::ResetEditMode()
867 if (mbEditEngineCreated && mpEditEngine)
868 delete mpEditEngine;
869 else if (mpTxtWnd && mpTxtWnd->HasEditView())
870 mpTxtWnd->GetEditView()->getEditEngine().SetNotifyHdl(Link<EENotify&,void>());
871 mpEditEngine = nullptr;
873 mpForwarder.reset();
874 mpEditViewForwarder.reset();
875 mpViewForwarder.reset();
876 mbEditEngineCreated = false;
879 void ScAccessibleEditLineTextData::TextChanged()
881 if (mbEditEngineCreated && mpEditEngine)
883 if (mpTxtWnd)
884 mpEditEngine->SetText(mpTxtWnd->GetTextString());
888 void ScAccessibleEditLineTextData::StartEdit()
890 ResetEditMode();
891 mpEditView = nullptr;
893 // send SdrHintKind::BeginEdit
894 SdrHint aHint(SdrHintKind::BeginEdit);
895 GetBroadcaster().Broadcast( aHint );
898 void ScAccessibleEditLineTextData::EndEdit()
900 // send SdrHintKind::EndEdit
901 SdrHint aHint(SdrHintKind::EndEdit);
902 GetBroadcaster().Broadcast( aHint );
904 ResetEditMode();
905 mpEditView = nullptr;
908 // ScAccessiblePreviewCellTextData: shared data between sub objects of an accessible cell text object
910 ScAccessiblePreviewCellTextData::ScAccessiblePreviewCellTextData(ScPreviewShell* pViewShell,
911 const ScAddress& rP)
912 : ScAccessibleCellBaseTextData(GetDocShell(pViewShell), rP),
913 mpViewShell(pViewShell)
917 ScAccessiblePreviewCellTextData::~ScAccessiblePreviewCellTextData()
919 if (pEditEngine)
920 pEditEngine->SetNotifyHdl(Link<EENotify&,void>());
921 mpViewForwarder.reset();
924 void ScAccessiblePreviewCellTextData::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
926 if ( rHint.GetId() == SfxHintId::Dying )
928 mpViewShell = nullptr; // invalid now
929 if (mpViewForwarder)
930 mpViewForwarder->SetInvalid();
932 ScAccessibleCellBaseTextData::Notify(rBC, rHint);
935 ScAccessibleTextData* ScAccessiblePreviewCellTextData::Clone() const
937 return new ScAccessiblePreviewCellTextData(mpViewShell, aCellPos);
940 SvxTextForwarder* ScAccessiblePreviewCellTextData::GetTextForwarder()
942 bool bEditEngineBefore(pEditEngine != nullptr);
944 ScCellTextData::GetTextForwarder(); // creates Forwarder and EditEngine
946 if (!bEditEngineBefore && pEditEngine)
948 Size aSize(mpViewShell->GetLocationData().GetCellOutputRect(aCellPos).GetSize());
949 vcl::Window* pWin = mpViewShell->GetWindow();
950 if (pWin)
951 aSize = pWin->PixelToLogic(aSize, pEditEngine->GetRefMapMode());
952 pEditEngine->SetPaperSize(aSize);
955 if (pEditEngine)
956 pEditEngine->SetNotifyHdl( LINK(this, ScAccessiblePreviewCellTextData, NotifyHdl) );
958 return pForwarder.get();
961 SvxViewForwarder* ScAccessiblePreviewCellTextData::GetViewForwarder()
963 if (!mpViewForwarder)
964 mpViewForwarder.reset(new ScPreviewCellViewForwarder(mpViewShell));
965 return mpViewForwarder.get();
968 ScDocShell* ScAccessiblePreviewCellTextData::GetDocShell(ScPreviewShell* pViewShell)
970 ScDocShell* pDocSh = nullptr;
971 if (pViewShell)
972 pDocSh = pViewShell->GetDocument().GetDocumentShell();
973 return pDocSh;
976 // ScAccessiblePreviewHeaderCellTextData: shared data between sub objects of an accessible cell text object
978 ScAccessiblePreviewHeaderCellTextData::ScAccessiblePreviewHeaderCellTextData(ScPreviewShell* pViewShell,
979 OUString aText, const ScAddress& rP, bool bColHeader, bool bRowHeader)
980 : ScAccessibleCellBaseTextData(GetDocShell(pViewShell), rP),
981 mpViewShell(pViewShell),
982 maText(std::move(aText)),
983 mbColHeader(bColHeader),
984 mbRowHeader(bRowHeader)
988 ScAccessiblePreviewHeaderCellTextData::~ScAccessiblePreviewHeaderCellTextData()
990 if (pEditEngine)
991 pEditEngine->SetNotifyHdl(Link<EENotify&,void>());
992 mpViewForwarder.reset();
995 void ScAccessiblePreviewHeaderCellTextData::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
997 if ( rHint.GetId() == SfxHintId::Dying )
999 mpViewShell = nullptr; // invalid now
1000 if (mpViewForwarder)
1001 mpViewForwarder->SetInvalid();
1003 ScAccessibleCellBaseTextData::Notify(rBC, rHint);
1006 ScAccessibleTextData* ScAccessiblePreviewHeaderCellTextData::Clone() const
1008 return new ScAccessiblePreviewHeaderCellTextData(mpViewShell, maText, aCellPos, mbColHeader, mbRowHeader);
1011 SvxTextForwarder* ScAccessiblePreviewHeaderCellTextData::GetTextForwarder()
1013 if (!pEditEngine)
1015 if ( pDocShell )
1017 ScDocument& rDoc = pDocShell->GetDocument();
1018 pEditEngine = rDoc.CreateFieldEditEngine();
1020 else
1022 rtl::Reference<SfxItemPool> pEnginePool = EditEngine::CreatePool();
1023 pEditEngine.reset( new ScFieldEditEngine(nullptr, pEnginePool.get(), nullptr, true) );
1025 pEditEngine->EnableUndo( false );
1026 if (pDocShell)
1027 pEditEngine->SetRefDevice(pDocShell->GetRefDevice());
1028 else
1029 pEditEngine->SetRefMapMode(MapMode(MapUnit::Map100thMM));
1030 pForwarder.reset( new SvxEditEngineForwarder(*pEditEngine) );
1033 if (bDataValid)
1034 return pForwarder.get();
1036 if (!maText.isEmpty())
1038 if ( mpViewShell )
1040 Size aOutputSize;
1041 vcl::Window* pWindow = mpViewShell->GetWindow();
1042 if ( pWindow )
1043 aOutputSize = pWindow->GetOutputSizePixel();
1044 tools::Rectangle aVisRect( Point(), aOutputSize );
1045 Size aSize(mpViewShell->GetLocationData().GetHeaderCellOutputRect(aVisRect, aCellPos, mbColHeader).GetSize());
1046 if (pWindow)
1047 aSize = pWindow->PixelToLogic(aSize, pEditEngine->GetRefMapMode());
1048 pEditEngine->SetPaperSize(aSize);
1050 pEditEngine->SetTextCurrentDefaults( maText );
1053 bDataValid = true;
1055 pEditEngine->SetNotifyHdl( LINK(this, ScAccessiblePreviewHeaderCellTextData, NotifyHdl) );
1057 return pForwarder.get();
1060 SvxViewForwarder* ScAccessiblePreviewHeaderCellTextData::GetViewForwarder()
1062 if (!mpViewForwarder)
1063 mpViewForwarder.reset(new ScPreviewHeaderCellViewForwarder(mpViewShell));
1064 return mpViewForwarder.get();
1067 ScDocShell* ScAccessiblePreviewHeaderCellTextData::GetDocShell(ScPreviewShell* pViewShell)
1069 ScDocShell* pDocSh = nullptr;
1070 if (pViewShell)
1071 pDocSh = pViewShell->GetDocument().GetDocumentShell();
1072 return pDocSh;
1075 ScAccessibleHeaderTextData::ScAccessibleHeaderTextData(ScPreviewShell* pViewShell,
1076 const EditTextObject* pEditObj, SvxAdjust eAdjust)
1078 mpViewShell(pViewShell),
1079 mpDocSh(nullptr),
1080 mpEditObj(pEditObj),
1081 mbDataValid(false),
1082 meAdjust(eAdjust)
1084 if (pViewShell)
1085 mpDocSh = pViewShell->GetDocument().GetDocumentShell();
1086 if (mpDocSh)
1087 mpDocSh->GetDocument().AddUnoObject(*this);
1090 ScAccessibleHeaderTextData::~ScAccessibleHeaderTextData()
1092 SolarMutexGuard aGuard; // needed for EditEngine dtor
1094 if (mpDocSh)
1095 mpDocSh->GetDocument().RemoveUnoObject(*this);
1096 if (mpEditEngine)
1097 mpEditEngine->SetNotifyHdl(Link<EENotify&,void>());
1098 mpEditEngine.reset();
1099 mpForwarder.reset();
1102 ScAccessibleTextData* ScAccessibleHeaderTextData::Clone() const
1104 return new ScAccessibleHeaderTextData(mpViewShell, mpEditObj, meAdjust);
1107 void ScAccessibleHeaderTextData::Notify( SfxBroadcaster&, const SfxHint& rHint )
1109 if ( rHint.GetId() == SfxHintId::Dying )
1111 mpViewShell = nullptr;// invalid now
1112 mpDocSh = nullptr;
1113 if (mxViewForwarder)
1114 mxViewForwarder->SetInvalid();
1118 SvxTextForwarder* ScAccessibleHeaderTextData::GetTextForwarder()
1120 if (!mpEditEngine)
1122 rtl::Reference<SfxItemPool> pEnginePool = EditEngine::CreatePool();
1123 std::unique_ptr<ScHeaderEditEngine> pHdrEngine(new ScHeaderEditEngine( pEnginePool.get() ));
1125 pHdrEngine->EnableUndo( false );
1126 pHdrEngine->SetRefMapMode(MapMode(MapUnit::MapTwip));
1128 // default font must be set, independently of document
1129 // -> use global pool from module
1130 std::unique_ptr<CellAttributeHelper> pTmp;
1131 const ScPatternAttr* pCellAttributeDefault(nullptr);
1133 if (nullptr != mpDocSh)
1135 // we can use default CellAttribute from ScDocument
1136 pCellAttributeDefault = &mpDocSh->GetDocument().getCellAttributeHelper().getDefaultCellAttribute();
1138 else
1140 // no access to ScDocument, use temporary CellAttributeHelper.
1141 // also see ScHeaderFooterTextData::GetTextForwarder for more comments
1142 pTmp.reset(new CellAttributeHelper(ScModule::get()->GetPool()));
1143 pCellAttributeDefault = &pTmp->getDefaultCellAttribute();
1146 auto pDefaults = std::make_unique<SfxItemSet>(pHdrEngine->GetEmptyItemSet());
1147 pCellAttributeDefault->FillEditItemSet(pDefaults.get());
1148 // FillEditItemSet adjusts font height to 1/100th mm,
1149 // but for header/footer twips is needed, as in the PatternAttr:
1150 pDefaults->Put( pCellAttributeDefault->GetItem(ATTR_FONT_HEIGHT).CloneSetWhich(EE_CHAR_FONTHEIGHT) );
1151 pDefaults->Put( pCellAttributeDefault->GetItem(ATTR_CJK_FONT_HEIGHT).CloneSetWhich(EE_CHAR_FONTHEIGHT_CJK) );
1152 pDefaults->Put( pCellAttributeDefault->GetItem(ATTR_CTL_FONT_HEIGHT).CloneSetWhich(EE_CHAR_FONTHEIGHT_CTL) );
1153 pDefaults->Put( SvxAdjustItem( meAdjust, EE_PARA_JUST ) );
1154 pHdrEngine->SetDefaults(std::move(pDefaults));
1156 ScHeaderFieldData aData;
1157 if (mpViewShell)
1158 mpViewShell->FillFieldData(aData);
1159 else
1160 ScHeaderFooterTextObj::FillDummyFieldData( aData );
1161 pHdrEngine->SetData( aData );
1163 mpEditEngine = std::move(pHdrEngine);
1164 mpForwarder.reset(new SvxEditEngineForwarder(*mpEditEngine));
1167 if (mbDataValid)
1168 return mpForwarder.get();
1170 if ( mpViewShell )
1172 tools::Rectangle aVisRect;
1173 mpViewShell->GetLocationData().GetHeaderPosition(aVisRect);
1174 Size aSize(aVisRect.GetSize());
1175 vcl::Window* pWin = mpViewShell->GetWindow();
1176 if (pWin)
1177 aSize = pWin->PixelToLogic(aSize, mpEditEngine->GetRefMapMode());
1178 mpEditEngine->SetPaperSize(aSize);
1180 if (mpEditObj)
1181 mpEditEngine->SetTextCurrentDefaults(*mpEditObj);
1183 mbDataValid = true;
1184 return mpForwarder.get();
1187 SvxViewForwarder* ScAccessibleHeaderTextData::GetViewForwarder()
1189 if (!mxViewForwarder)
1190 mxViewForwarder = std::make_unique<ScPreviewHeaderFooterViewForwarder>(mpViewShell);
1191 return mxViewForwarder.get();
1194 ScAccessibleNoteTextData::ScAccessibleNoteTextData(ScPreviewShell* pViewShell,
1195 OUString sText, const ScAddress& aCellPos, bool bMarkNote)
1197 mpViewShell(pViewShell),
1198 mpDocSh(nullptr),
1199 msText(std::move(sText)),
1200 maCellPos(aCellPos),
1201 mbMarkNote(bMarkNote),
1202 mbDataValid(false)
1204 if (pViewShell)
1205 mpDocSh = pViewShell->GetDocument().GetDocumentShell();
1206 if (mpDocSh)
1207 mpDocSh->GetDocument().AddUnoObject(*this);
1210 ScAccessibleNoteTextData::~ScAccessibleNoteTextData()
1212 SolarMutexGuard aGuard; // needed for EditEngine dtor
1214 if (mpDocSh)
1215 mpDocSh->GetDocument().RemoveUnoObject(*this);
1216 if (mpEditEngine)
1217 mpEditEngine->SetNotifyHdl(Link<EENotify&,void>());
1218 mpEditEngine.reset();
1219 mpForwarder.reset();
1222 ScAccessibleTextData* ScAccessibleNoteTextData::Clone() const
1224 return new ScAccessibleNoteTextData(mpViewShell, msText, maCellPos, mbMarkNote);
1227 void ScAccessibleNoteTextData::Notify( SfxBroadcaster&, const SfxHint& rHint )
1229 if ( rHint.GetId() == SfxHintId::Dying )
1231 mpViewShell = nullptr;// invalid now
1232 mpDocSh = nullptr;
1233 if (mxViewForwarder)
1234 mxViewForwarder->SetInvalid();
1238 SvxTextForwarder* ScAccessibleNoteTextData::GetTextForwarder()
1240 if (!mpEditEngine)
1242 if ( mpDocSh )
1244 ScDocument& rDoc = mpDocSh->GetDocument();
1245 mpEditEngine = rDoc.CreateFieldEditEngine();
1247 else
1249 rtl::Reference<SfxItemPool> pEnginePool = EditEngine::CreatePool();
1250 mpEditEngine.reset( new ScFieldEditEngine(nullptr, pEnginePool.get(), nullptr, true) );
1252 mpEditEngine->EnableUndo( false );
1253 if (mpDocSh)
1254 mpEditEngine->SetRefDevice(mpDocSh->GetRefDevice());
1255 else
1256 mpEditEngine->SetRefMapMode(MapMode(MapUnit::Map100thMM));
1257 mpForwarder.reset( new SvxEditEngineForwarder(*mpEditEngine) );
1260 if (mbDataValid)
1261 return mpForwarder.get();
1263 if (!msText.isEmpty())
1266 if ( mpViewShell )
1268 Size aOutputSize;
1269 vcl::Window* pWindow = mpViewShell->GetWindow();
1270 if ( pWindow )
1271 aOutputSize = pWindow->GetOutputSizePixel();
1272 tools::Rectangle aVisRect( Point(), aOutputSize );
1273 Size aSize(mpViewShell->GetLocationData().GetNoteInRangeOutputRect(aVisRect, mbMarkNote, maCellPos).GetSize());
1274 if (pWindow)
1275 aSize = pWindow->PixelToLogic(aSize, mpEditEngine->GetRefMapMode());
1276 mpEditEngine->SetPaperSize(aSize);
1278 mpEditEngine->SetTextCurrentDefaults( msText );
1281 mbDataValid = true;
1283 mpEditEngine->SetNotifyHdl( LINK(this, ScAccessibleNoteTextData, NotifyHdl) );
1285 return mpForwarder.get();
1288 SvxViewForwarder* ScAccessibleNoteTextData::GetViewForwarder()
1290 if (!mxViewForwarder)
1291 mxViewForwarder = std::make_unique<ScPreviewNoteViewForwarder>(mpViewShell);
1292 return mxViewForwarder.get();
1295 // CSV import =================================================================
1297 class ScCsvViewForwarder : public SvxViewForwarder
1299 VclPtr<OutputDevice> mpWindow;
1301 public:
1302 explicit ScCsvViewForwarder( OutputDevice* pWindow );
1304 virtual bool IsValid() const override;
1305 virtual Point LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const override;
1306 virtual Point PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const override;
1308 void SetInvalid();
1311 ScCsvViewForwarder::ScCsvViewForwarder( OutputDevice* pWindow ) :
1312 mpWindow( pWindow )
1316 bool ScCsvViewForwarder::IsValid() const
1318 return mpWindow != nullptr;
1321 Point ScCsvViewForwarder::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
1323 if( !mpWindow ) return Point();
1324 return mpWindow->LogicToPixel( rPoint, rMapMode );
1327 Point ScCsvViewForwarder::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
1329 if( !mpWindow ) return Point();
1330 return mpWindow->PixelToLogic( rPoint, rMapMode );
1333 void ScCsvViewForwarder::SetInvalid()
1335 mpWindow = nullptr;
1338 ScAccessibleCsvTextData::ScAccessibleCsvTextData(
1339 OutputDevice* pWindow, EditEngine* pEditEngine,
1340 OUString aCellText, const Size& rCellSize ) :
1341 mpWindow( pWindow ),
1342 mpEditEngine( pEditEngine ),
1343 maCellText(std::move( aCellText )),
1344 maCellSize( rCellSize )
1348 ScAccessibleCsvTextData::~ScAccessibleCsvTextData()
1352 void ScAccessibleCsvTextData::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
1354 if ( rHint.GetId() == SfxHintId::Dying )
1356 mpWindow = nullptr;
1357 mpEditEngine = nullptr;
1358 if (mpViewForwarder)
1359 mpViewForwarder->SetInvalid();
1361 ScAccessibleTextData::Notify( rBC, rHint );
1364 ScAccessibleTextData* ScAccessibleCsvTextData::Clone() const
1366 return new ScAccessibleCsvTextData( mpWindow, mpEditEngine, maCellText, maCellSize );
1369 SvxTextForwarder* ScAccessibleCsvTextData::GetTextForwarder()
1371 if( mpEditEngine )
1373 mpEditEngine->SetPaperSize( maCellSize );
1374 mpEditEngine->SetText( maCellText );
1375 if( !mpTextForwarder )
1376 mpTextForwarder.reset( new SvxEditEngineForwarder( *mpEditEngine ) );
1378 else
1379 mpTextForwarder.reset();
1380 return mpTextForwarder.get();
1383 SvxViewForwarder* ScAccessibleCsvTextData::GetViewForwarder()
1385 if( !mpViewForwarder )
1386 mpViewForwarder.reset( new ScCsvViewForwarder( mpWindow ) );
1387 return mpViewForwarder.get();
1390 SvxEditViewForwarder* ScAccessibleCsvTextData::GetEditViewForwarder( bool /* bCreate */ )
1392 return nullptr;
1395 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */