Update git submodules
[LibreOffice.git] / svx / source / dialog / weldeditview.cxx
blob18539c449b5b40cf812276158dc633b86f74e240
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 <config_wasm_strip.h>
22 #include <basegfx/matrix/b2dhommatrix.hxx>
23 #include <com/sun/star/accessibility/AccessibleRole.hpp>
24 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
25 #include <com/sun/star/accessibility/XAccessible.hpp>
26 #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
27 #include <com/sun/star/accessibility/XAccessibleContext2.hpp>
28 #include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
29 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
30 #include <com/sun/star/lang/XServiceInfo.hpp>
31 #include <cppuhelper/supportsservice.hxx>
32 #include <drawinglayer/processor2d/baseprocessor2d.hxx>
33 #include <drawinglayer/processor2d/processor2dtools.hxx>
34 #include <comphelper/lok.hxx>
35 #include <editeng/eeitem.hxx>
36 #include <editeng/fhgtitem.hxx>
37 #include <editeng/fontitem.hxx>
38 #include <editeng/outliner.hxx>
39 #include <editeng/unoedhlp.hxx>
40 #include <editeng/unoedsrc.hxx>
41 #include <i18nlangtag/languagetag.hxx>
42 #include <osl/diagnose.h>
43 #include <svl/itempool.hxx>
44 #include <svl/itemset.hxx>
45 #include <sal/log.hxx>
46 #include <svx/sdr/overlay/overlayselection.hxx>
47 #include <svtools/optionsdrawinglayer.hxx>
48 #include <svx/AccessibleTextHelper.hxx>
49 #include <svx/weldeditview.hxx>
50 #include <comphelper/diagnose_ex.hxx>
51 #include <vcl/canvastools.hxx>
52 #include <vcl/cursor.hxx>
53 #include <vcl/event.hxx>
54 #include <vcl/ptrstyle.hxx>
55 #include <vcl/settings.hxx>
56 #include <vcl/svapp.hxx>
57 #include <vcl/window.hxx>
58 #include <vcl/uitest/uiobject.hxx>
60 void WeldEditView::SetText(const OUString& rStr) { GetEditEngine()->SetText(rStr); }
62 OUString WeldEditView::GetText() const { return GetEditEngine()->GetText(); }
64 void WeldEditView::SetModifyHdl(const Link<LinkParamNone*, void>& rLink)
66 GetEditEngine()->SetModifyHdl(rLink);
69 EditView* WeldEditView::GetEditView() const { return m_xEditView.get(); }
71 EditEngine* WeldEditView::GetEditEngine() const { return m_xEditEngine.get(); }
73 bool WeldEditView::HasSelection() const
75 EditView* pEditView = GetEditView();
76 return pEditView && pEditView->HasSelection();
79 void WeldEditView::Delete()
81 if (EditView* pEditView = GetEditView())
82 pEditView->DeleteSelected();
85 void WeldEditView::Cut()
87 if (EditView* pEditView = GetEditView())
88 pEditView->Cut();
91 void WeldEditView::Copy()
93 if (EditView* pEditView = GetEditView())
94 pEditView->Copy();
97 void WeldEditView::Paste()
99 if (EditView* pEditView = GetEditView())
100 pEditView->Paste();
103 WeldEditView::WeldEditView()
104 : m_bAcceptsTab(false)
108 // tdf#127033 want to use UI font so override makeEditEngine to enable that
109 void WeldEditView::makeEditEngine()
111 rtl::Reference<SfxItemPool> pItemPool = EditEngine::CreatePool();
113 vcl::Font aAppFont(Application::GetSettings().GetStyleSettings().GetAppFont());
115 pItemPool->SetUserDefaultItem(SvxFontItem(aAppFont.GetFamilyType(), aAppFont.GetFamilyName(),
116 u""_ustr, PITCH_DONTKNOW, RTL_TEXTENCODING_DONTKNOW,
117 EE_CHAR_FONTINFO));
118 pItemPool->SetUserDefaultItem(SvxFontItem(aAppFont.GetFamilyType(), aAppFont.GetFamilyName(),
119 u""_ustr, PITCH_DONTKNOW, RTL_TEXTENCODING_DONTKNOW,
120 EE_CHAR_FONTINFO_CJK));
121 pItemPool->SetUserDefaultItem(SvxFontItem(aAppFont.GetFamilyType(), aAppFont.GetFamilyName(),
122 u""_ustr, PITCH_DONTKNOW, RTL_TEXTENCODING_DONTKNOW,
123 EE_CHAR_FONTINFO_CTL));
125 pItemPool->SetUserDefaultItem(
126 SvxFontHeightItem(aAppFont.GetFontHeight() * 20, 100, EE_CHAR_FONTHEIGHT));
127 pItemPool->SetUserDefaultItem(
128 SvxFontHeightItem(aAppFont.GetFontHeight() * 20, 100, EE_CHAR_FONTHEIGHT_CJK));
129 pItemPool->SetUserDefaultItem(
130 SvxFontHeightItem(aAppFont.GetFontHeight() * 20, 100, EE_CHAR_FONTHEIGHT_CTL));
132 m_xEditEngine.reset(new EditEngine(pItemPool.get()));
135 void WeldEditView::Resize()
137 if (EditView* pEditView = GetEditView())
139 OutputDevice& rDevice = GetDrawingArea()->get_ref_device();
140 Size aOutputSize(rDevice.PixelToLogic(GetOutputSizePixel()));
141 // Resizes the edit engine to adjust to the size of the output area
142 pEditView->SetOutputArea(tools::Rectangle(Point(0, 0), aOutputSize));
143 GetEditEngine()->SetPaperSize(aOutputSize);
144 pEditView->ShowCursor();
146 const tools::Long nMaxVisAreaStart
147 = pEditView->getEditEngine().GetTextHeight() - aOutputSize.Height();
148 tools::Rectangle aVisArea(pEditView->GetVisArea());
149 if (aVisArea.Top() > nMaxVisAreaStart)
151 aVisArea.SetTop(std::max<tools::Long>(nMaxVisAreaStart, 0));
152 aVisArea.SetSize(aOutputSize);
153 pEditView->SetVisArea(aVisArea);
154 pEditView->ShowCursor();
157 EditViewScrollStateChange();
159 weld::CustomWidgetController::Resize();
162 void WeldEditView::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
164 DoPaint(rRenderContext, rRect);
167 void WeldEditView::DoPaint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
169 rRenderContext.Push(vcl::PushFlags::ALL);
170 rRenderContext.SetClipRegion();
172 std::vector<tools::Rectangle> aLogicRects;
174 if (EditView* pEditView = GetEditView())
176 pEditView->Paint(comphelper::LibreOfficeKit::isActive() ? rRenderContext.PixelToLogic(rRect)
177 : rRect,
178 &rRenderContext);
180 if (HasFocus())
182 pEditView->ShowCursor(false);
183 vcl::Cursor* pCursor = pEditView->GetCursor();
184 pCursor->DrawToDevice(rRenderContext);
187 // get logic selection
188 pEditView->GetSelectionRectangles(aLogicRects);
191 if (!aLogicRects.empty())
193 std::vector<basegfx::B2DRange> aLogicRanges;
194 aLogicRanges.reserve(aLogicRects.size());
196 tools::Long nMinX(LONG_MAX), nMaxX(0), nMinY(LONG_MAX), nMaxY(0);
197 for (const auto& aRect : aLogicRects)
199 nMinX = std::min(nMinX, aRect.Left());
200 nMinY = std::min(nMinY, aRect.Top());
201 nMaxX = std::max(nMaxX, aRect.Right());
202 nMaxY = std::max(nMaxY, aRect.Bottom());
205 const Size aLogicPixel(rRenderContext.PixelToLogic(Size(1, 1)));
206 for (const auto& aRect : aLogicRects)
208 // Extend each range by one pixel so multiple lines touch each
209 // other if adjacent, so the whole set is drawn with a single
210 // border around the lot. But keep the selection within the
211 // original max extents.
212 auto nTop = aRect.Top();
213 if (nTop > nMinY)
214 nTop -= aLogicPixel.Height();
215 auto nBottom = aRect.Bottom();
216 if (nBottom < nMaxY)
217 nBottom += aLogicPixel.Height();
218 auto nLeft = aRect.Left();
219 if (nLeft > nMinX)
220 nLeft -= aLogicPixel.Width();
221 auto nRight = aRect.Right();
222 if (nRight < nMaxX)
223 nRight += aLogicPixel.Width();
225 aLogicRanges.emplace_back(nLeft, nTop, nRight, nBottom);
228 // get the system's highlight color
229 const Color aHighlight(SvtOptionsDrawinglayer::getHilightColor());
231 sdr::overlay::OverlaySelection aCursorOverlay(sdr::overlay::OverlayType::Transparent,
232 aHighlight, std::move(aLogicRanges), true);
234 drawinglayer::geometry::ViewInformation2D aViewInformation2D;
235 aViewInformation2D.setViewTransformation(rRenderContext.GetViewTransformation());
236 aViewInformation2D.setViewport(vcl::unotools::b2DRectangleFromRectangle(rRect));
238 std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> xProcessor(
239 drawinglayer::processor2d::createProcessor2DFromOutputDevice(rRenderContext,
240 aViewInformation2D));
242 xProcessor->process(aCursorOverlay.getOverlayObjectPrimitive2DSequence());
245 rRenderContext.Pop();
248 bool WeldEditView::MouseMove(const MouseEvent& rMEvt)
250 EditView* pEditView = GetEditView();
251 return pEditView && pEditView->MouseMove(rMEvt);
254 bool WeldEditView::MouseButtonDown(const MouseEvent& rMEvt)
256 if (!IsMouseCaptured())
257 CaptureMouse();
259 if (!HasFocus() && CanFocus())
260 GrabFocus();
262 EditView* pEditView = GetEditView();
263 return pEditView && pEditView->MouseButtonDown(rMEvt);
266 bool WeldEditView::MouseButtonUp(const MouseEvent& rMEvt)
268 if (IsMouseCaptured())
269 ReleaseMouse();
270 EditView* pEditView = GetEditView();
271 return pEditView && pEditView->MouseButtonUp(rMEvt);
274 bool WeldEditView::KeyInput(const KeyEvent& rKEvt)
276 EditView* pEditView = GetEditView();
278 sal_uInt16 nKey = rKEvt.GetKeyCode().GetCode();
280 if (nKey == KEY_TAB && !GetAcceptsTab())
282 return false;
284 else if (pEditView && !pEditView->PostKeyEvent(rKEvt))
286 if (rKEvt.GetKeyCode().IsMod1() && !rKEvt.GetKeyCode().IsMod2())
288 if (nKey == KEY_A)
290 if (GetEditEngine()->GetParagraphCount())
292 pEditView->SetSelection(ESelection::All());
294 return true;
298 return false;
301 return true;
304 bool WeldEditView::Command(const CommandEvent& rCEvt)
306 EditView* pEditView = GetEditView();
307 if (!pEditView)
308 return false;
309 return pEditView->Command(rCEvt);
312 Point WeldEditView::EditViewPointerPosPixel() const
314 return GetDrawingArea()->get_pointer_position();
317 class WeldEditAccessible;
319 namespace
321 class WeldViewForwarder : public SvxViewForwarder
323 WeldEditAccessible& m_rEditAcc;
325 WeldViewForwarder(const WeldViewForwarder&) = delete;
326 WeldViewForwarder& operator=(const WeldViewForwarder&) = delete;
328 public:
329 explicit WeldViewForwarder(WeldEditAccessible& rAcc)
330 : m_rEditAcc(rAcc)
334 virtual bool IsValid() const override;
335 virtual Point LogicToPixel(const Point& rPoint, const MapMode& rMapMode) const override;
336 virtual Point PixelToLogic(const Point& rPoint, const MapMode& rMapMode) const override;
340 class WeldEditAccessible;
342 namespace
344 class WeldEditSource;
346 /* analog to SvxEditEngineForwarder */
347 class WeldTextForwarder : public SvxTextForwarder
349 WeldEditAccessible& m_rEditAcc;
350 WeldEditSource& m_rEditSource;
352 DECL_LINK(NotifyHdl, EENotify&, void);
354 WeldTextForwarder(const WeldTextForwarder&) = delete;
355 WeldTextForwarder& operator=(const WeldTextForwarder&) = delete;
357 public:
358 WeldTextForwarder(WeldEditAccessible& rAcc, WeldEditSource& rSource);
359 virtual ~WeldTextForwarder() override;
361 virtual sal_Int32 GetParagraphCount() const override;
362 virtual sal_Int32 GetTextLen(sal_Int32 nParagraph) const override;
363 virtual OUString GetText(const ESelection& rSel) const override;
364 virtual SfxItemSet GetAttribs(const ESelection& rSel, EditEngineAttribs nOnlyHardAttrib
365 = EditEngineAttribs::All) const override;
366 virtual SfxItemSet GetParaAttribs(sal_Int32 nPara) const override;
367 virtual void SetParaAttribs(sal_Int32 nPara, const SfxItemSet& rSet) override;
368 virtual void RemoveAttribs(const ESelection& rSelection) override;
369 virtual void GetPortions(sal_Int32 nPara, std::vector<sal_Int32>& rList) const override;
371 virtual OUString GetStyleSheet(sal_Int32 nPara) const override;
372 virtual void SetStyleSheet(sal_Int32 nPara, const OUString& rStyleName) override;
374 virtual SfxItemState GetItemState(const ESelection& rSel, sal_uInt16 nWhich) const override;
375 virtual SfxItemState GetItemState(sal_Int32 nPara, sal_uInt16 nWhich) const override;
377 virtual void QuickInsertText(const OUString& rText, const ESelection& rSel) override;
378 virtual void QuickInsertField(const SvxFieldItem& rFld, const ESelection& rSel) override;
379 virtual void QuickSetAttribs(const SfxItemSet& rSet, const ESelection& rSel) override;
380 virtual void QuickInsertLineBreak(const ESelection& rSel) override;
382 virtual SfxItemPool* GetPool() const override;
384 virtual OUString CalcFieldValue(const SvxFieldItem& rField, sal_Int32 nPara, sal_Int32 nPos,
385 std::optional<Color>& rpTxtColor,
386 std::optional<Color>& rpFldColor,
387 std::optional<FontLineStyle>& rpFldLineStyle) override;
388 virtual void FieldClicked(const SvxFieldItem&) override;
389 virtual bool IsValid() const override;
391 virtual LanguageType GetLanguage(sal_Int32, sal_Int32) const override;
392 virtual std::vector<EFieldInfo> GetFieldInfo(sal_Int32 nPara) const override;
393 virtual EBulletInfo GetBulletInfo(sal_Int32 nPara) const override;
394 virtual tools::Rectangle GetCharBounds(sal_Int32 nPara, sal_Int32 nIndex) const override;
395 virtual tools::Rectangle GetParaBounds(sal_Int32 nPara) const override;
396 virtual MapMode GetMapMode() const override;
397 virtual OutputDevice* GetRefDevice() const override;
398 virtual bool GetIndexAtPoint(const Point&, sal_Int32& nPara, sal_Int32& nIndex) const override;
399 virtual bool GetWordIndices(sal_Int32 nPara, sal_Int32 nIndex, sal_Int32& nStart,
400 sal_Int32& nEnd) const override;
401 virtual bool GetAttributeRun(sal_Int32& nStartIndex, sal_Int32& nEndIndex, sal_Int32 nPara,
402 sal_Int32 nIndex, bool bInCell = false) const override;
403 virtual sal_Int32 GetLineCount(sal_Int32 nPara) const override;
404 virtual sal_Int32 GetLineLen(sal_Int32 nPara, sal_Int32 nLine) const override;
405 virtual void GetLineBoundaries(/*out*/ sal_Int32& rStart, /*out*/ sal_Int32& rEnd,
406 sal_Int32 nParagraph, sal_Int32 nLine) const override;
407 virtual sal_Int32 GetLineNumberAtIndex(sal_Int32 nPara, sal_Int32 nLine) const override;
408 virtual bool Delete(const ESelection&) override;
409 virtual bool InsertText(const OUString&, const ESelection&) override;
410 virtual bool QuickFormatDoc(bool bFull = false) override;
412 virtual bool SupportsOutlineDepth() const override { return false; };
413 virtual sal_Int16 GetDepth(sal_Int32 nPara) const override;
414 virtual bool SetDepth(sal_Int32 nPara, sal_Int16 nNewDepth) override;
416 virtual const SfxItemSet* GetEmptyItemSetPtr() override;
417 // implementation functions for XParagraphAppend and XTextPortionAppend
418 virtual void AppendParagraph() override;
419 virtual sal_Int32 AppendTextPortion(sal_Int32 nPara, const OUString& rText,
420 const SfxItemSet& rSet) override;
422 virtual void CopyText(const SvxTextForwarder& rSource) override;
425 /* analog to SvxEditEngineViewForwarder */
426 class WeldEditViewForwarder : public SvxEditViewForwarder
428 WeldEditAccessible& m_rEditAcc;
430 WeldEditViewForwarder(const WeldEditViewForwarder&) = delete;
431 WeldEditViewForwarder& operator=(const WeldEditViewForwarder&) = delete;
433 public:
434 explicit WeldEditViewForwarder(WeldEditAccessible& rAcc);
436 virtual bool IsValid() const override;
438 virtual Point LogicToPixel(const Point& rPoint, const MapMode& rMapMode) const override;
439 virtual Point PixelToLogic(const Point& rPoint, const MapMode& rMapMode) const override;
441 virtual bool GetSelection(ESelection& rSelection) const override;
442 virtual bool SetSelection(const ESelection& rSelection) override;
443 virtual bool Copy() override;
444 virtual bool Cut() override;
445 virtual bool Paste() override;
448 class WeldEditSource : public SvxEditSource
450 SfxBroadcaster m_aBroadCaster;
451 WeldViewForwarder m_aViewFwd;
452 WeldTextForwarder m_aTextFwd;
453 WeldEditViewForwarder m_aEditViewFwd;
454 WeldEditAccessible& m_rEditAcc;
456 WeldEditSource(const WeldEditSource& rSrc)
457 : SvxEditSource()
458 , m_aViewFwd(rSrc.m_rEditAcc)
459 , m_aTextFwd(rSrc.m_rEditAcc, *this)
460 , m_aEditViewFwd(rSrc.m_rEditAcc)
461 , m_rEditAcc(rSrc.m_rEditAcc)
465 WeldEditSource& operator=(const WeldEditSource&) = delete;
467 public:
468 WeldEditSource(WeldEditAccessible& rAcc)
469 : m_aViewFwd(rAcc)
470 , m_aTextFwd(rAcc, *this)
471 , m_aEditViewFwd(rAcc)
472 , m_rEditAcc(rAcc)
476 virtual std::unique_ptr<SvxEditSource> Clone() const override
478 return std::unique_ptr<SvxEditSource>(new WeldEditSource(*this));
481 virtual SvxTextForwarder* GetTextForwarder() override { return &m_aTextFwd; }
483 virtual SvxViewForwarder* GetViewForwarder() override { return &m_aViewFwd; }
485 virtual SvxEditViewForwarder* GetEditViewForwarder(bool /*bCreate*/) override
487 return &m_aEditViewFwd;
490 virtual void UpdateData() override
492 // would possibly only by needed if the XText interface is implemented
493 // and its text needs to be updated.
495 virtual SfxBroadcaster& GetBroadcaster() const override
497 return const_cast<WeldEditSource*>(this)->m_aBroadCaster;
502 typedef cppu::WeakImplHelper<css::lang::XServiceInfo, css::accessibility::XAccessible,
503 css::accessibility::XAccessibleComponent,
504 css::accessibility::XAccessibleContext2,
505 css::accessibility::XAccessibleEventBroadcaster>
506 WeldEditAccessibleBaseClass;
508 class WeldEditAccessible : public WeldEditAccessibleBaseClass
510 weld::CustomWidgetController* m_pController;
511 EditEngine* m_pEditEngine;
512 EditView* m_pEditView;
513 std::unique_ptr<::accessibility::AccessibleTextHelper> m_xTextHelper;
515 public:
516 WeldEditAccessible(weld::CustomWidgetController* pController)
517 : m_pController(pController)
518 , m_pEditEngine(nullptr)
519 , m_pEditView(nullptr)
523 ::accessibility::AccessibleTextHelper* GetTextHelper() { return m_xTextHelper.get(); }
525 void Init(EditEngine* pEditEngine, EditView* pEditView)
527 m_pEditEngine = pEditEngine;
528 m_pEditView = pEditView;
529 m_xTextHelper.reset(
530 new ::accessibility::AccessibleTextHelper(std::make_unique<WeldEditSource>(*this)));
531 m_xTextHelper->SetEventSource(this);
534 EditEngine* GetEditEngine() { return m_pEditEngine; }
535 EditView* GetEditView() { return m_pEditView; }
537 void ClearWin()
539 // remove handler before current object gets destroyed
540 // (avoid handler being called for already dead object)
541 m_pEditEngine->SetNotifyHdl(Link<EENotify&, void>());
543 m_pEditEngine = nullptr;
544 m_pEditView = nullptr;
545 m_pController = nullptr; // implicitly results in AccessibleStateType::DEFUNC set
547 //! make TextHelper implicitly release C++ references to some core objects
548 m_xTextHelper->SetEditSource(::std::unique_ptr<SvxEditSource>());
550 //! make TextHelper release references
551 //! (e.g. the one set by the 'SetEventSource' call)
552 m_xTextHelper->Dispose();
553 m_xTextHelper.reset();
556 // XAccessible
557 virtual css::uno::Reference<css::accessibility::XAccessibleContext>
558 SAL_CALL getAccessibleContext() override
560 return this;
563 // XAccessibleComponent
564 virtual sal_Bool SAL_CALL containsPoint(const css::awt::Point& rPoint) override
566 //! the arguments coordinates are relative to the current window !
567 //! Thus the top left-point is (0, 0)
568 SolarMutexGuard aGuard;
569 if (!m_pController)
570 throw css::uno::RuntimeException();
572 Size aSz(m_pController->GetOutputSizePixel());
573 return rPoint.X >= 0 && rPoint.Y >= 0 && rPoint.X < aSz.Width() && rPoint.Y < aSz.Height();
576 virtual css::uno::Reference<css::accessibility::XAccessible>
577 SAL_CALL getAccessibleAtPoint(const css::awt::Point& rPoint) override
579 SolarMutexGuard aGuard;
580 if (!m_xTextHelper)
581 throw css::uno::RuntimeException();
583 return m_xTextHelper->GetAt(rPoint);
586 virtual css::awt::Rectangle SAL_CALL getBounds() override
588 SolarMutexGuard aGuard;
589 if (!m_pController)
590 throw css::uno::RuntimeException();
592 const Point aOutPos;
593 const Size aOutSize(m_pController->GetOutputSizePixel());
594 css::awt::Rectangle aRet;
596 aRet.X = aOutPos.X();
597 aRet.Y = aOutPos.Y();
598 aRet.Width = aOutSize.Width();
599 aRet.Height = aOutSize.Height();
601 return aRet;
604 virtual css::awt::Point SAL_CALL getLocation() override
606 SolarMutexGuard aGuard;
607 if (!m_pController)
608 throw css::uno::RuntimeException();
610 const css::awt::Rectangle aRect(getBounds());
611 css::awt::Point aRet;
613 aRet.X = aRect.X;
614 aRet.Y = aRect.Y;
616 return aRet;
619 virtual css::awt::Point SAL_CALL getLocationOnScreen() override
621 SolarMutexGuard aGuard;
622 if (!m_pController)
623 throw css::uno::RuntimeException();
625 css::awt::Point aScreenLoc(0, 0);
627 if (weld::DrawingArea* pDrawingArea = m_pController->GetDrawingArea())
629 AbsoluteScreenPixelPoint aPos = pDrawingArea->get_accessible_location_on_screen();
630 aScreenLoc.X = aPos.X();
631 aScreenLoc.Y = aPos.Y();
634 return aScreenLoc;
637 virtual css::awt::Size SAL_CALL getSize() override
639 SolarMutexGuard aGuard;
640 if (!m_pController)
641 throw css::uno::RuntimeException();
643 Size aSz(m_pController->GetOutputSizePixel());
644 return css::awt::Size(aSz.Width(), aSz.Height());
647 virtual void SAL_CALL grabFocus() override { m_pController->GrabFocus(); }
649 virtual sal_Int32 SAL_CALL getForeground() override
651 SolarMutexGuard aGuard;
652 if (!m_pController)
653 throw css::uno::RuntimeException();
655 Color nCol = m_pEditEngine->GetAutoColor();
656 return static_cast<sal_Int32>(nCol);
659 virtual sal_Int32 SAL_CALL getBackground() override
661 SolarMutexGuard aGuard;
662 if (!m_pController)
663 throw css::uno::RuntimeException();
665 Color nCol = m_pEditEngine->GetBackgroundColor();
666 return static_cast<sal_Int32>(nCol);
669 // XAccessibleContext
670 virtual sal_Int64 SAL_CALL getAccessibleChildCount() override
672 if (m_xTextHelper)
673 return m_xTextHelper->GetChildCount();
674 return 0;
677 virtual css::uno::Reference<css::accessibility::XAccessible>
678 SAL_CALL getAccessibleChild(sal_Int64 i) override
680 if (m_xTextHelper)
681 return m_xTextHelper->GetChild(i);
682 throw css::lang::IndexOutOfBoundsException(); // there is no child...
685 virtual css::uno::Reference<css::accessibility::XAccessible>
686 SAL_CALL getAccessibleParent() override
688 SolarMutexGuard aGuard;
689 if (!m_pController)
690 throw css::uno::RuntimeException();
692 return m_pController->GetDrawingArea()->get_accessible_parent();
695 virtual sal_Int64 SAL_CALL getAccessibleIndexInParent() override
697 SolarMutexGuard aGuard;
698 if (!m_pController)
699 throw css::uno::RuntimeException();
701 // -1 for child not found/no parent (according to specification)
702 sal_Int64 nRet = -1;
704 css::uno::Reference<css::accessibility::XAccessible> xParent(getAccessibleParent());
705 if (!xParent)
706 return nRet;
710 css::uno::Reference<css::accessibility::XAccessibleContext> xParentContext(
711 xParent->getAccessibleContext());
713 // iterate over parent's children and search for this object
714 if (xParentContext.is())
716 sal_Int64 nChildCount = xParentContext->getAccessibleChildCount();
717 for (sal_Int64 nChild = 0; (nChild < nChildCount) && (-1 == nRet); ++nChild)
719 css::uno::Reference<css::accessibility::XAccessible> xChild(
720 xParentContext->getAccessibleChild(nChild));
721 if (xChild.get() == this)
722 nRet = nChild;
726 catch (const css::uno::Exception&)
728 TOOLS_WARN_EXCEPTION("svx", "WeldEditAccessible::getAccessibleIndexInParent");
731 return nRet;
734 virtual sal_Int16 SAL_CALL getAccessibleRole() override
736 return css::accessibility::AccessibleRole::TEXT_FRAME;
739 virtual OUString SAL_CALL getAccessibleDescription() override
741 SolarMutexGuard aGuard;
743 OUString aRet;
745 if (m_pController)
747 aRet = m_pController->GetAccessibleDescription();
750 return aRet;
753 virtual OUString SAL_CALL getAccessibleId() override
755 SolarMutexGuard aGuard;
757 if (m_pController)
758 return m_pController->GetAccessibleId();
760 return OUString();
763 virtual OUString SAL_CALL getAccessibleName() override
765 SolarMutexGuard aGuard;
767 OUString aRet;
769 if (m_pController)
771 aRet = m_pController->GetAccessibleName();
774 return aRet;
777 virtual css::uno::Reference<css::accessibility::XAccessibleRelationSet>
778 SAL_CALL getAccessibleRelationSet() override
780 SolarMutexGuard aGuard;
781 if (!m_pController)
782 throw css::uno::RuntimeException();
784 return m_pController->GetDrawingArea()->get_accessible_relation_set();
787 virtual sal_Int64 SAL_CALL getAccessibleStateSet() override
789 SolarMutexGuard aGuard;
790 sal_Int64 nStateSet = 0;
792 if (!m_pController || !m_xTextHelper)
793 nStateSet |= css::accessibility::AccessibleStateType::DEFUNC;
794 else
796 nStateSet |= css::accessibility::AccessibleStateType::MULTI_LINE;
797 nStateSet |= css::accessibility::AccessibleStateType::ENABLED;
798 nStateSet |= css::accessibility::AccessibleStateType::EDITABLE;
799 nStateSet |= css::accessibility::AccessibleStateType::FOCUSABLE;
800 nStateSet |= css::accessibility::AccessibleStateType::SELECTABLE;
801 if (m_pController->HasFocus())
802 nStateSet |= css::accessibility::AccessibleStateType::FOCUSED;
803 if (m_pController->IsActive())
804 nStateSet |= css::accessibility::AccessibleStateType::ACTIVE;
805 if (m_pController->IsVisible())
806 nStateSet |= css::accessibility::AccessibleStateType::SHOWING;
807 if (m_pController->IsReallyVisible())
808 nStateSet |= css::accessibility::AccessibleStateType::VISIBLE;
809 if (COL_TRANSPARENT != m_pEditEngine->GetBackgroundColor())
810 nStateSet |= css::accessibility::AccessibleStateType::OPAQUE;
813 return nStateSet;
816 virtual css::lang::Locale SAL_CALL getLocale() override
818 SolarMutexGuard aGuard;
819 return LanguageTag(m_pEditEngine->GetDefaultLanguage()).getLocale();
822 // XAccessibleEventBroadcaster
823 virtual void SAL_CALL addAccessibleEventListener(
824 const css::uno::Reference<css::accessibility::XAccessibleEventListener>& rListener) override
826 if (!m_xTextHelper) // not disposing (about to destroy view shell)
827 return;
828 m_xTextHelper->AddEventListener(rListener);
831 virtual void SAL_CALL removeAccessibleEventListener(
832 const css::uno::Reference<css::accessibility::XAccessibleEventListener>& rListener) override
834 if (!m_xTextHelper) // not disposing (about to destroy view shell)
835 return;
836 m_xTextHelper->RemoveEventListener(rListener);
839 virtual OUString SAL_CALL getImplementationName() override
841 return u"WeldEditAccessible"_ustr;
844 virtual sal_Bool SAL_CALL supportsService(const OUString& rServiceName) override
846 return cppu::supportsService(this, rServiceName);
849 virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
851 return { u"css::accessibility::Accessible"_ustr,
852 u"css::accessibility::AccessibleComponent"_ustr,
853 u"css::accessibility::AccessibleContext"_ustr };
857 css::uno::Reference<css::accessibility::XAccessible> WeldEditView::CreateAccessible()
859 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
860 if (!m_xAccessible.is())
861 m_xAccessible.set(new WeldEditAccessible(this));
862 #endif
863 return m_xAccessible;
866 WeldEditView::~WeldEditView()
868 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
869 if (m_xAccessible.is())
871 m_xAccessible->ClearWin(); // make Accessible nonfunctional
872 m_xAccessible.clear();
874 #endif
877 bool WeldViewForwarder::IsValid() const { return m_rEditAcc.GetEditView() != nullptr; }
879 Point WeldViewForwarder::LogicToPixel(const Point& rPoint, const MapMode& rMapMode) const
881 EditView* pEditView = m_rEditAcc.GetEditView();
882 if (!pEditView)
883 return Point();
884 OutputDevice& rOutDev = pEditView->GetOutputDevice();
885 MapMode aMapMode(rOutDev.GetMapMode());
886 Point aPoint(OutputDevice::LogicToLogic(rPoint, rMapMode, MapMode(aMapMode.GetMapUnit())));
887 aMapMode.SetOrigin(Point());
888 return rOutDev.LogicToPixel(aPoint, aMapMode);
891 Point WeldViewForwarder::PixelToLogic(const Point& rPoint, const MapMode& rMapMode) const
893 EditView* pEditView = m_rEditAcc.GetEditView();
894 if (!pEditView)
895 return Point();
896 OutputDevice& rOutDev = pEditView->GetOutputDevice();
897 MapMode aMapMode(rOutDev.GetMapMode());
898 aMapMode.SetOrigin(Point());
899 Point aPoint(rOutDev.PixelToLogic(rPoint, aMapMode));
900 return OutputDevice::LogicToLogic(aPoint, MapMode(aMapMode.GetMapUnit()), rMapMode);
903 WeldTextForwarder::WeldTextForwarder(WeldEditAccessible& rAcc, WeldEditSource& rSource)
904 : m_rEditAcc(rAcc)
905 , m_rEditSource(rSource)
907 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
908 if (pEditEngine)
909 pEditEngine->SetNotifyHdl(LINK(this, WeldTextForwarder, NotifyHdl));
912 WeldTextForwarder::~WeldTextForwarder()
914 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
915 if (pEditEngine)
916 pEditEngine->SetNotifyHdl(Link<EENotify&, void>());
919 IMPL_LINK(WeldTextForwarder, NotifyHdl, EENotify&, rNotify, void)
921 if (EditEngine* pEditEngine = m_rEditAcc.GetEditEngine())
923 if (rNotify.eNotificationType == EE_NOTIFY_PROCESSNOTIFICATIONS
924 && !pEditEngine->IsUpdateLayout())
926 // tdf#143088 an UpdateMode of false will just to on to cause
927 // AccessibleTextHelper_Impl::GetTextForwarder to throw an
928 // exception as a Frozen EditEngine is considered Invalid so return
929 // early instead
930 return;
934 ::std::unique_ptr<SfxHint> aHint = SvxEditSourceHelper::EENotification2Hint(&rNotify);
935 if (aHint)
936 m_rEditSource.GetBroadcaster().Broadcast(*aHint);
939 sal_Int32 WeldTextForwarder::GetParagraphCount() const
941 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
942 return pEditEngine ? pEditEngine->GetParagraphCount() : 0;
945 sal_Int32 WeldTextForwarder::GetTextLen(sal_Int32 nParagraph) const
947 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
948 return pEditEngine ? pEditEngine->GetTextLen(nParagraph) : 0;
951 OUString WeldTextForwarder::GetText(const ESelection& rSel) const
953 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
954 OUString aRet;
955 if (pEditEngine)
956 aRet = pEditEngine->GetText(rSel);
957 return convertLineEnd(aRet, GetSystemLineEnd());
960 SfxItemSet WeldTextForwarder::GetAttribs(const ESelection& rSel,
961 EditEngineAttribs nOnlyHardAttrib) const
963 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
964 assert(pEditEngine && "EditEngine missing");
965 if (rSel.start.nPara == rSel.end.nPara)
967 GetAttribsFlags nFlags = GetAttribsFlags::NONE;
968 switch (nOnlyHardAttrib)
970 case EditEngineAttribs::All:
971 nFlags = GetAttribsFlags::ALL;
972 break;
973 case EditEngineAttribs::OnlyHard:
974 nFlags = GetAttribsFlags::CHARATTRIBS;
975 break;
976 default:
977 SAL_WARN("svx", "unknown flags for WeldTextForwarder::GetAttribs");
980 return pEditEngine->GetAttribs(rSel.start.nPara, rSel.start.nIndex, rSel.end.nIndex,
981 nFlags);
983 else
985 return pEditEngine->GetAttribs(rSel, nOnlyHardAttrib);
989 SfxItemSet WeldTextForwarder::GetParaAttribs(sal_Int32 nPara) const
991 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
992 assert(pEditEngine && "EditEngine missing");
994 SfxItemSet aSet(pEditEngine->GetParaAttribs(nPara));
996 sal_uInt16 nWhich = EE_PARA_START;
997 while (nWhich <= EE_PARA_END)
999 if (aSet.GetItemState(nWhich) != SfxItemState::SET)
1001 if (pEditEngine->HasParaAttrib(nPara, nWhich))
1002 aSet.Put(pEditEngine->GetParaAttrib(nPara, nWhich));
1004 nWhich++;
1007 return aSet;
1010 void WeldTextForwarder::SetParaAttribs(sal_Int32 nPara, const SfxItemSet& rSet)
1012 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1013 if (pEditEngine)
1014 pEditEngine->SetParaAttribs(nPara, rSet);
1017 SfxItemPool* WeldTextForwarder::GetPool() const
1019 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1020 return pEditEngine ? pEditEngine->GetEmptyItemSet().GetPool() : nullptr;
1023 void WeldTextForwarder::RemoveAttribs(const ESelection& rSelection)
1025 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1026 if (pEditEngine)
1027 pEditEngine->RemoveAttribs(rSelection, false /*bRemoveParaAttribs*/, 0);
1030 void WeldTextForwarder::GetPortions(sal_Int32 nPara, std::vector<sal_Int32>& rList) const
1032 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1033 if (pEditEngine)
1034 pEditEngine->GetPortions(nPara, rList);
1037 OUString WeldTextForwarder::GetStyleSheet(sal_Int32 nPara) const
1039 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1040 if (auto pStyle = pEditEngine ? pEditEngine->GetStyleSheet(nPara) : nullptr)
1041 return pStyle->GetName();
1042 return OUString();
1045 void WeldTextForwarder::SetStyleSheet(sal_Int32 nPara, const OUString& rStyleName)
1047 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1048 auto pStyleSheetPool = pEditEngine ? pEditEngine->GetStyleSheetPool() : nullptr;
1049 if (auto pStyle
1050 = pStyleSheetPool ? pStyleSheetPool->Find(rStyleName, SfxStyleFamily::Para) : nullptr)
1051 pEditEngine->SetStyleSheet(nPara, static_cast<SfxStyleSheet*>(pStyle));
1054 void WeldTextForwarder::QuickInsertText(const OUString& rText, const ESelection& rSel)
1056 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1057 if (pEditEngine)
1058 pEditEngine->QuickInsertText(rText, rSel);
1061 void WeldTextForwarder::QuickInsertLineBreak(const ESelection& rSel)
1063 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1064 if (pEditEngine)
1065 pEditEngine->QuickInsertLineBreak(rSel);
1068 void WeldTextForwarder::QuickInsertField(const SvxFieldItem& rFld, const ESelection& rSel)
1070 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1071 if (pEditEngine)
1072 pEditEngine->QuickInsertField(rFld, rSel);
1075 void WeldTextForwarder::QuickSetAttribs(const SfxItemSet& rSet, const ESelection& rSel)
1077 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1078 if (pEditEngine)
1079 pEditEngine->QuickSetAttribs(rSet, rSel);
1082 bool WeldTextForwarder::IsValid() const
1084 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1085 // cannot reliably query EditEngine state
1086 // while in the middle of an update
1087 return pEditEngine && pEditEngine->IsUpdateLayout();
1090 OUString WeldTextForwarder::CalcFieldValue(const SvxFieldItem& rField, sal_Int32 nPara,
1091 sal_Int32 nPos, std::optional<Color>& rpTxtColor,
1092 std::optional<Color>& rpFldColor,
1093 std::optional<FontLineStyle>& rpFldLineStyle)
1095 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1096 return pEditEngine ? pEditEngine->CalcFieldValue(rField, nPara, nPos, rpTxtColor, rpFldColor,
1097 rpFldLineStyle)
1098 : OUString();
1101 void WeldTextForwarder::FieldClicked(const SvxFieldItem&) {}
1103 static SfxItemState GetSvxEditEngineItemState(EditEngine const& rEditEngine, const ESelection& rSel,
1104 sal_uInt16 nWhich)
1106 std::vector<EECharAttrib> aAttribs;
1108 const SfxPoolItem* pLastItem = nullptr;
1110 SfxItemState eState = SfxItemState::DEFAULT;
1112 // check all paragraphs inside the selection
1113 for (sal_Int32 nPara = rSel.start.nPara; nPara <= rSel.end.nPara; nPara++)
1115 SfxItemState eParaState = SfxItemState::DEFAULT;
1117 // calculate start and endpos for this paragraph
1118 sal_Int32 nPos = 0;
1119 if (rSel.start.nPara == nPara)
1120 nPos = rSel.start.nIndex;
1122 sal_Int32 nEndPos = rSel.end.nIndex;
1123 if (rSel.end.nPara != nPara)
1124 nEndPos = rEditEngine.GetTextLen(nPara);
1126 // get list of char attribs
1127 rEditEngine.GetCharAttribs(nPara, aAttribs);
1129 bool bEmpty = true; // we found no item inside the selection of this paragraph
1130 bool bGaps = false; // we found items but there are gaps between them
1131 sal_Int32 nLastEnd = nPos;
1133 const SfxPoolItem* pParaItem = nullptr;
1135 for (const auto& rAttrib : aAttribs)
1137 assert(rAttrib.pAttr && "GetCharAttribs gives corrupt data");
1139 const bool bEmptyPortion = (rAttrib.nStart == rAttrib.nEnd);
1140 if ((!bEmptyPortion && (rAttrib.nStart >= nEndPos))
1141 || (bEmptyPortion && (rAttrib.nStart > nEndPos)))
1142 break; // break if we are already behind our selection
1144 if ((!bEmptyPortion && (rAttrib.nEnd <= nPos))
1145 || (bEmptyPortion && (rAttrib.nEnd < nPos)))
1146 continue; // or if the attribute ends before our selection
1148 if (rAttrib.pAttr->Which() != nWhich)
1149 continue; // skip if is not the searched item
1151 // if we already found an item
1152 if (pParaItem)
1154 // ... and its different to this one than the state is don't care
1155 if (*pParaItem != *(rAttrib.pAttr))
1156 return SfxItemState::INVALID;
1158 else
1160 pParaItem = rAttrib.pAttr;
1163 if (bEmpty)
1164 bEmpty = false;
1166 if (!bGaps && rAttrib.nStart > nLastEnd)
1167 bGaps = true;
1169 nLastEnd = rAttrib.nEnd;
1172 if (!bEmpty && !bGaps && nLastEnd < (nEndPos - 1))
1173 bGaps = true;
1174 if (bEmpty)
1175 eParaState = SfxItemState::DEFAULT;
1176 else if (bGaps)
1177 eParaState = SfxItemState::INVALID;
1178 else
1179 eParaState = SfxItemState::SET;
1181 // if we already found an item check if we found the same
1182 if (pLastItem)
1184 if ((pParaItem == nullptr) || (*pLastItem != *pParaItem))
1185 return SfxItemState::INVALID;
1187 else
1189 pLastItem = pParaItem;
1190 eState = eParaState;
1194 return eState;
1197 SfxItemState WeldTextForwarder::GetItemState(const ESelection& rSel, sal_uInt16 nWhich) const
1199 SfxItemState nState = SfxItemState::DISABLED;
1200 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1201 if (pEditEngine)
1202 nState = GetSvxEditEngineItemState(*pEditEngine, rSel, nWhich);
1203 return nState;
1206 SfxItemState WeldTextForwarder::GetItemState(sal_Int32 nPara, sal_uInt16 nWhich) const
1208 SfxItemState nState = SfxItemState::DISABLED;
1209 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1210 if (pEditEngine)
1212 const SfxItemSet& rSet = pEditEngine->GetParaAttribs(nPara);
1213 nState = rSet.GetItemState(nWhich);
1215 return nState;
1218 LanguageType WeldTextForwarder::GetLanguage(sal_Int32 nPara, sal_Int32 nIndex) const
1220 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1221 return pEditEngine ? pEditEngine->GetLanguage(nPara, nIndex).nLang : LANGUAGE_NONE;
1224 std::vector<EFieldInfo> WeldTextForwarder::GetFieldInfo(sal_Int32 nPara) const
1226 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1227 if (!pEditEngine)
1228 return {};
1229 return pEditEngine->GetFieldInfo(nPara);
1232 EBulletInfo WeldTextForwarder::GetBulletInfo(sal_Int32 /*nPara*/) const { return EBulletInfo(); }
1234 tools::Rectangle WeldTextForwarder::GetCharBounds(sal_Int32 nPara, sal_Int32 nIndex) const
1236 tools::Rectangle aRect(0, 0, 0, 0);
1237 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1239 if (pEditEngine)
1241 // Handle virtual position one-past-the end of the string
1242 if (nIndex >= pEditEngine->GetTextLen(nPara))
1244 if (nIndex)
1245 aRect = pEditEngine->GetCharacterBounds(EPaM(nPara, nIndex - 1));
1247 aRect.Move(aRect.Right() - aRect.Left(), 0);
1248 aRect.SetSize(Size(1, pEditEngine->GetTextHeight()));
1250 else
1252 aRect = pEditEngine->GetCharacterBounds(EPaM(nPara, nIndex));
1255 return aRect;
1258 tools::Rectangle WeldTextForwarder::GetParaBounds(sal_Int32 nPara) const
1260 tools::Rectangle aRect(0, 0, 0, 0);
1261 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1263 if (pEditEngine)
1265 const Point aPnt = pEditEngine->GetDocPosTopLeft(nPara);
1266 const sal_Int32 nWidth = pEditEngine->CalcTextWidth();
1267 const sal_Int32 nHeight = pEditEngine->GetTextHeight(nPara);
1268 aRect = tools::Rectangle(aPnt.X(), aPnt.Y(), aPnt.X() + nWidth, aPnt.Y() + nHeight);
1271 return aRect;
1274 MapMode WeldTextForwarder::GetMapMode() const
1276 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1277 return pEditEngine ? pEditEngine->GetRefMapMode() : MapMode(MapUnit::Map100thMM);
1280 OutputDevice* WeldTextForwarder::GetRefDevice() const
1282 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1283 return pEditEngine ? pEditEngine->GetRefDevice() : nullptr;
1286 bool WeldTextForwarder::GetIndexAtPoint(const Point& rPos, sal_Int32& nPara,
1287 sal_Int32& nIndex) const
1289 bool bRes = false;
1290 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1291 if (pEditEngine)
1293 EPaM aDocPos = pEditEngine->FindDocPosition(rPos);
1294 nPara = aDocPos.nPara;
1295 nIndex = aDocPos.nIndex;
1296 bRes = true;
1298 return bRes;
1301 bool WeldTextForwarder::GetWordIndices(sal_Int32 nPara, sal_Int32 nIndex, sal_Int32& nStart,
1302 sal_Int32& nEnd) const
1304 bool bRes = false;
1305 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1306 if (pEditEngine)
1308 ESelection aRes
1309 = pEditEngine->GetWord(ESelection(nPara, nIndex), css::i18n::WordType::DICTIONARY_WORD);
1311 if (aRes.start.nPara == nPara && aRes.start.nPara == aRes.end.nPara)
1313 nStart = aRes.start.nIndex;
1314 nEnd = aRes.end.nIndex;
1316 bRes = true;
1320 return bRes;
1323 bool WeldTextForwarder::GetAttributeRun(sal_Int32& nStartIndex, sal_Int32& nEndIndex,
1324 sal_Int32 nPara, sal_Int32 nIndex, bool bInCell) const
1326 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1327 if (!pEditEngine)
1328 return false;
1329 SvxEditSourceHelper::GetAttributeRun(nStartIndex, nEndIndex, *pEditEngine, nPara, nIndex,
1330 bInCell);
1331 return true;
1334 sal_Int32 WeldTextForwarder::GetLineCount(sal_Int32 nPara) const
1336 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1337 return pEditEngine ? pEditEngine->GetLineCount(nPara) : 0;
1340 sal_Int32 WeldTextForwarder::GetLineLen(sal_Int32 nPara, sal_Int32 nLine) const
1342 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1343 return pEditEngine ? pEditEngine->GetLineLen(nPara, nLine) : 0;
1346 void WeldTextForwarder::GetLineBoundaries(/*out*/ sal_Int32& rStart, /*out*/ sal_Int32& rEnd,
1347 sal_Int32 nPara, sal_Int32 nLine) const
1349 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1350 if (pEditEngine)
1351 pEditEngine->GetLineBoundaries(rStart, rEnd, nPara, nLine);
1352 else
1353 rStart = rEnd = 0;
1356 sal_Int32 WeldTextForwarder::GetLineNumberAtIndex(sal_Int32 nPara, sal_Int32 nIndex) const
1358 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1359 return pEditEngine ? pEditEngine->GetLineNumberAtIndex(nPara, nIndex) : 0;
1362 bool WeldTextForwarder::QuickFormatDoc(bool /*bFull*/)
1364 bool bRes = false;
1365 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1366 if (pEditEngine)
1368 pEditEngine->QuickFormatDoc();
1369 bRes = true;
1371 return bRes;
1374 sal_Int16 WeldTextForwarder::GetDepth(sal_Int32 /*nPara*/) const
1376 // math has no outliner...
1377 return -1;
1380 bool WeldTextForwarder::SetDepth(sal_Int32 /*nPara*/, sal_Int16 nNewDepth)
1382 // math has no outliner...
1383 return -1 == nNewDepth; // is it the value from 'GetDepth' ?
1386 bool WeldTextForwarder::Delete(const ESelection& rSelection)
1388 bool bRes = false;
1389 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1390 if (pEditEngine)
1392 pEditEngine->QuickDelete(rSelection);
1393 pEditEngine->QuickFormatDoc();
1394 bRes = true;
1396 return bRes;
1399 bool WeldTextForwarder::InsertText(const OUString& rStr, const ESelection& rSelection)
1401 bool bRes = false;
1402 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1403 if (pEditEngine)
1405 pEditEngine->QuickInsertText(rStr, rSelection);
1406 pEditEngine->QuickFormatDoc();
1407 bRes = true;
1409 return bRes;
1412 const SfxItemSet* WeldTextForwarder::GetEmptyItemSetPtr()
1414 const SfxItemSet* pItemSet = nullptr;
1415 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1416 if (pEditEngine)
1418 pItemSet = &pEditEngine->GetEmptyItemSet();
1420 return pItemSet;
1423 void WeldTextForwarder::AppendParagraph()
1425 // append an empty paragraph
1426 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1427 if (pEditEngine)
1429 sal_Int32 nParaCount = pEditEngine->GetParagraphCount();
1430 pEditEngine->InsertParagraph(nParaCount, OUString());
1434 sal_Int32 WeldTextForwarder::AppendTextPortion(sal_Int32 nPara, const OUString& rText,
1435 const SfxItemSet& rSet)
1437 sal_uInt16 nRes = 0;
1438 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1439 if (pEditEngine && nPara < pEditEngine->GetParagraphCount())
1441 // append text
1442 ESelection aSel(nPara, pEditEngine->GetTextLen(nPara));
1443 pEditEngine->QuickInsertText(rText, aSel);
1445 // set attributes for new appended text
1446 nRes = aSel.end.nIndex = pEditEngine->GetTextLen(nPara);
1447 pEditEngine->QuickSetAttribs(rSet, aSel);
1449 return nRes;
1452 void WeldTextForwarder::CopyText(const SvxTextForwarder& rSource)
1454 const WeldTextForwarder* pSourceForwarder = dynamic_cast<const WeldTextForwarder*>(&rSource);
1455 if (!pSourceForwarder)
1456 return;
1457 EditEngine* pSourceEditEngine = pSourceForwarder->m_rEditAcc.GetEditEngine();
1458 EditEngine* pEditEngine = m_rEditAcc.GetEditEngine();
1459 if (pEditEngine && pSourceEditEngine)
1461 std::unique_ptr<EditTextObject> pNewTextObject = pSourceEditEngine->CreateTextObject();
1462 pEditEngine->SetText(*pNewTextObject);
1466 WeldEditViewForwarder::WeldEditViewForwarder(WeldEditAccessible& rAcc)
1467 : m_rEditAcc(rAcc)
1471 bool WeldEditViewForwarder::IsValid() const { return m_rEditAcc.GetEditView() != nullptr; }
1473 Point WeldEditViewForwarder::LogicToPixel(const Point& rPoint, const MapMode& rMapMode) const
1475 EditView* pEditView = m_rEditAcc.GetEditView();
1476 if (!pEditView)
1477 return Point();
1478 OutputDevice& rOutDev = pEditView->GetOutputDevice();
1479 MapMode aMapMode(rOutDev.GetMapMode());
1480 Point aPoint(OutputDevice::LogicToLogic(rPoint, rMapMode, MapMode(aMapMode.GetMapUnit())));
1481 aMapMode.SetOrigin(Point());
1482 return rOutDev.LogicToPixel(aPoint, aMapMode);
1485 Point WeldEditViewForwarder::PixelToLogic(const Point& rPoint, const MapMode& rMapMode) const
1487 EditView* pEditView = m_rEditAcc.GetEditView();
1488 if (!pEditView)
1489 return Point();
1490 OutputDevice& rOutDev = pEditView->GetOutputDevice();
1491 MapMode aMapMode(rOutDev.GetMapMode());
1492 aMapMode.SetOrigin(Point());
1493 Point aPoint(rOutDev.PixelToLogic(rPoint, aMapMode));
1494 return OutputDevice::LogicToLogic(aPoint, MapMode(aMapMode.GetMapUnit()), rMapMode);
1497 bool WeldEditViewForwarder::GetSelection(ESelection& rSelection) const
1499 bool bRes = false;
1500 EditView* pEditView = m_rEditAcc.GetEditView();
1501 if (pEditView)
1503 rSelection = pEditView->GetSelection();
1504 bRes = true;
1506 return bRes;
1509 bool WeldEditViewForwarder::SetSelection(const ESelection& rSelection)
1511 bool bRes = false;
1512 EditView* pEditView = m_rEditAcc.GetEditView();
1513 if (pEditView)
1515 pEditView->SetSelection(rSelection);
1516 bRes = true;
1518 return bRes;
1521 bool WeldEditViewForwarder::Copy()
1523 bool bRes = false;
1524 EditView* pEditView = m_rEditAcc.GetEditView();
1525 if (pEditView)
1527 pEditView->Copy();
1528 bRes = true;
1530 return bRes;
1533 bool WeldEditViewForwarder::Cut()
1535 bool bRes = false;
1536 EditView* pEditView = m_rEditAcc.GetEditView();
1537 if (pEditView)
1539 pEditView->Cut();
1540 bRes = true;
1542 return bRes;
1545 bool WeldEditViewForwarder::Paste()
1547 bool bRes = false;
1548 EditView* pEditView = m_rEditAcc.GetEditView();
1549 if (pEditView)
1551 pEditView->Paste();
1552 bRes = true;
1554 return bRes;
1557 void WeldEditView::SetDrawingArea(weld::DrawingArea* pDrawingArea)
1559 Size aSize(pDrawingArea->get_size_request());
1560 if (aSize.Width() == -1)
1561 aSize.setWidth(500);
1562 if (aSize.Height() == -1)
1563 aSize.setHeight(100);
1564 pDrawingArea->set_size_request(aSize.Width(), aSize.Height());
1566 SetOutputSizePixel(aSize);
1568 weld::CustomWidgetController::SetDrawingArea(pDrawingArea);
1570 EnableRTL(false);
1572 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1573 Color aBgColor = rStyleSettings.GetFieldColor();
1575 OutputDevice& rDevice = pDrawingArea->get_ref_device();
1577 rDevice.SetMapMode(MapMode(MapUnit::MapTwip));
1578 rDevice.SetBackground(aBgColor);
1580 Size aOutputSize(rDevice.PixelToLogic(aSize));
1582 makeEditEngine();
1583 m_xEditEngine->SetPaperSize(aOutputSize);
1584 m_xEditEngine->SetRefDevice(&rDevice);
1586 m_xEditEngine->SetControlWord(m_xEditEngine->GetControlWord() | EEControlBits::MARKFIELDS);
1588 m_xEditView.reset(new EditView(m_xEditEngine.get(), nullptr));
1589 m_xEditView->setEditViewCallbacks(this);
1590 m_xEditView->SetOutputArea(tools::Rectangle(Point(0, 0), aOutputSize));
1592 m_xEditView->SetBackgroundColor(aBgColor);
1593 m_xEditEngine->SetBackgroundColor(aBgColor);
1594 m_xEditEngine->InsertView(m_xEditView.get());
1596 pDrawingArea->set_cursor(PointerStyle::Text);
1598 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1599 InitAccessible();
1600 #endif
1603 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1604 void WeldEditView::InitAccessible()
1606 if (m_xAccessible.is())
1607 m_xAccessible->Init(GetEditEngine(), GetEditView());
1609 #endif
1611 int WeldEditView::GetSurroundingText(OUString& rSurrounding)
1613 EditView* pEditView = GetEditView();
1614 if (!pEditView)
1615 return -1;
1616 rSurrounding = pEditView->GetSurroundingText();
1617 return pEditView->GetSurroundingTextSelection().Min();
1620 bool WeldEditView::DeleteSurroundingText(const Selection& rRange)
1622 EditView* pEditView = GetEditView();
1623 if (!pEditView)
1624 return false;
1625 return pEditView->DeleteSurroundingText(rRange);
1628 void WeldEditView::GetFocus()
1630 EditView* pEditView = GetEditView();
1631 if (pEditView)
1633 pEditView->ShowCursor(false);
1634 Invalidate(); // redraw with cursor
1637 weld::CustomWidgetController::GetFocus();
1639 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1640 if (m_xAccessible.is())
1642 // Note: will implicitly send the AccessibleStateType::FOCUSED event
1643 ::accessibility::AccessibleTextHelper* pHelper = m_xAccessible->GetTextHelper();
1644 if (pHelper)
1645 pHelper->SetFocus();
1647 #endif
1650 void WeldEditView::LoseFocus()
1652 weld::CustomWidgetController::LoseFocus();
1653 Invalidate(); // redraw without cursor
1655 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1656 if (m_xAccessible.is())
1658 // Note: will implicitly send the AccessibleStateType::FOCUSED event
1659 ::accessibility::AccessibleTextHelper* pHelper = m_xAccessible->GetTextHelper();
1660 if (pHelper)
1661 pHelper->SetFocus(false);
1663 #endif
1666 bool WeldEditView::CanFocus() const { return true; }
1668 css::uno::Reference<css::datatransfer::dnd::XDropTarget> WeldEditView::GetDropTarget()
1670 if (!m_xDropTarget)
1671 m_xDropTarget = weld::CustomWidgetController::GetDropTarget();
1672 return m_xDropTarget;
1675 css::uno::Reference<css::datatransfer::clipboard::XClipboard> WeldEditView::GetClipboard() const
1677 return weld::CustomWidgetController::GetClipboard();
1680 void WeldEditView::EditViewSelectionChange()
1682 Invalidate();
1684 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1685 if (m_xAccessible.is())
1687 ::accessibility::AccessibleTextHelper* pHelper = m_xAccessible->GetTextHelper();
1688 if (pHelper)
1689 pHelper->UpdateSelection();
1691 #endif
1694 namespace
1696 class WeldEditViewUIObject final : public DrawingAreaUIObject
1698 private:
1699 WeldEditView* mpEditView;
1701 public:
1702 WeldEditViewUIObject(const VclPtr<vcl::Window>& rDrawingArea)
1703 : DrawingAreaUIObject(rDrawingArea)
1704 , mpEditView(static_cast<WeldEditView*>(mpController))
1708 static std::unique_ptr<UIObject> create(vcl::Window* pWindow)
1710 return std::unique_ptr<UIObject>(new WeldEditViewUIObject(pWindow));
1713 virtual StringMap get_state() override
1715 StringMap aMap = WindowUIObject::get_state();
1716 aMap[u"Text"_ustr] = mpEditView->GetText();
1717 return aMap;
1720 private:
1721 virtual OUString get_name() const override { return u"WeldEditViewUIObject"_ustr; }
1725 FactoryFunction WeldEditView::GetUITestFactory() const { return WeldEditViewUIObject::create; }
1727 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */