1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
25 #include <svl/itemset.hxx>
26 #include <editeng/editdata.hxx>
27 #include <editeng/outliner.hxx>
28 #include <svx/svdmodel.hxx>
29 #include <svx/svdobj.hxx>
30 #include <svx/svdpool.hxx>
33 // Project-local header
36 #include "AccessibleEmptyEditSource.hxx"
37 #include <svx/unoshtxt.hxx>
39 namespace accessibility
42 /** This class simply wraps a SvxTextEditSource, forwarding all
43 methods except the GetBroadcaster() call
45 class AccessibleProxyEditSource_Impl
: public SvxEditSource
48 /** Construct AccessibleEmptyEditSource_Impl
52 Proxy broadcaster to allow seamless flipping of edit source implementations. ProxyEditSource and EmptyEditSource
54 AccessibleProxyEditSource_Impl( SdrObject
& rObj
,
56 const OutputDevice
& rViewWindow
);
58 // from the SvxEditSource interface
59 SvxTextForwarder
* GetTextForwarder() override
;
60 SvxViewForwarder
* GetViewForwarder() override
;
61 SvxEditViewForwarder
* GetEditViewForwarder( bool bCreate
= false ) override
;
63 std::unique_ptr
<SvxEditSource
> Clone() const override
;
65 void UpdateData() override
;
67 SfxBroadcaster
& GetBroadcaster() const override
;
70 SvxTextEditSource maEditSource
;
74 /** Dummy class, faking exactly one empty paragraph for EditEngine accessibility
76 class AccessibleEmptyEditSource_Impl
: public SvxEditSource
, public SvxViewForwarder
, public SvxTextForwarder
, public SfxBroadcaster
80 AccessibleEmptyEditSource_Impl() {}
83 SvxTextForwarder
* GetTextForwarder() override
{ return this; }
84 SvxViewForwarder
* GetViewForwarder() override
{ return this; }
85 std::unique_ptr
<SvxEditSource
> Clone() const override
{ return nullptr; }
86 void UpdateData() override
{}
87 SfxBroadcaster
& GetBroadcaster() const override
{ return *const_cast<AccessibleEmptyEditSource_Impl
*>(this); }
90 sal_Int32
GetParagraphCount() const override
{ return 1; }
91 sal_Int32
GetTextLen( sal_Int32
/*nParagraph*/ ) const override
{ return 0; }
92 OUString
GetText( const ESelection
& /*rSel*/ ) const override
{ return OUString(); }
93 SfxItemSet
GetAttribs( const ESelection
& /*rSel*/, EditEngineAttribs
/*nOnlyHardAttrib*/ = EditEngineAttribs::All
) const override
95 // AW: Very dangerous: The former implementation used a SfxItemPool created on the
96 // fly which of course was deleted again ASAP. Thus, the returned SfxItemSet was using
97 // a deleted Pool by design.
98 return SfxItemSet(SdrObject::GetGlobalDrawObjectItemPool());
100 SfxItemSet
GetParaAttribs( sal_Int32
/*nPara*/ ) const override
{ return GetAttribs(ESelection()); }
101 void SetParaAttribs( sal_Int32
/*nPara*/, const SfxItemSet
& /*rSet*/ ) override
{}
102 void RemoveAttribs( const ESelection
& /*rSelection*/ ) override
{}
103 void GetPortions( sal_Int32
/*nPara*/, std::vector
<sal_Int32
>& /*rList*/ ) const override
{}
105 SfxItemState
GetItemState( const ESelection
& /*rSel*/, sal_uInt16
/*nWhich*/ ) const override
{ return SfxItemState::UNKNOWN
; }
106 SfxItemState
GetItemState( sal_Int32
/*nPara*/, sal_uInt16
/*nWhich*/ ) const override
{ return SfxItemState::UNKNOWN
; }
108 SfxItemPool
* GetPool() const override
{ return nullptr; }
110 void QuickInsertText( const OUString
& /*rText*/, const ESelection
& /*rSel*/ ) override
{}
111 void QuickInsertField( const SvxFieldItem
& /*rFld*/, const ESelection
& /*rSel*/ ) override
{}
112 void QuickSetAttribs( const SfxItemSet
& /*rSet*/, const ESelection
& /*rSel*/ ) override
{}
113 void QuickInsertLineBreak( const ESelection
& /*rSel*/ ) override
{}
115 const SfxItemSet
* GetEmptyItemSetPtr() override
{ return nullptr; }
117 void AppendParagraph() override
{}
118 sal_Int32
AppendTextPortion( sal_Int32
/*nPara*/, const OUString
& /*rText*/, const SfxItemSet
& /*rSet*/ ) override
{ return 0; }
121 void CopyText(const SvxTextForwarder
& ) override
{}
123 OUString
CalcFieldValue( const SvxFieldItem
& /*rField*/, sal_Int32
/*nPara*/, sal_Int32
/*nPos*/, boost::optional
<Color
>& /*rpTxtColor*/, boost::optional
<Color
>& /*rpFldColor*/ ) override
127 void FieldClicked( const SvxFieldItem
& ) override
{}
129 bool IsValid() const override
{ return true; }
131 LanguageType
GetLanguage( sal_Int32
, sal_Int32
) const override
{ return LANGUAGE_DONTKNOW
; }
132 sal_Int32
GetFieldCount( sal_Int32
) const override
{ return 0; }
133 EFieldInfo
GetFieldInfo( sal_Int32
, sal_uInt16
) const override
{ return EFieldInfo(); }
134 EBulletInfo
GetBulletInfo( sal_Int32
) const override
{ return EBulletInfo(); }
135 tools::Rectangle
GetCharBounds( sal_Int32
, sal_Int32
) const override
{ return tools::Rectangle(); }
136 tools::Rectangle
GetParaBounds( sal_Int32
) const override
{ return tools::Rectangle(); }
137 MapMode
GetMapMode() const override
{ return MapMode(); }
138 OutputDevice
* GetRefDevice() const override
{ return nullptr; }
139 bool GetIndexAtPoint( const Point
&, sal_Int32
&, sal_Int32
& ) const override
{ return false; }
140 bool GetWordIndices( sal_Int32
, sal_Int32
, sal_Int32
&, sal_Int32
& ) const override
{ return false; }
141 bool GetAttributeRun( sal_Int32
&, sal_Int32
&, sal_Int32
, sal_Int32
, bool ) const override
{ return false; }
142 sal_Int32
GetLineCount( sal_Int32 nPara
) const override
{ return nPara
== 0 ? 1 : 0; }
143 sal_Int32
GetLineLen( sal_Int32
, sal_Int32
) const override
{ return 0; }
144 void GetLineBoundaries( /*out*/sal_Int32
& rStart
, /*out*/sal_Int32
& rEnd
, sal_Int32
/*nParagraph*/, sal_Int32
/*nLine*/ ) const override
{ rStart
= rEnd
= 0; }
145 sal_Int32
GetLineNumberAtIndex( sal_Int32
/*nPara*/, sal_Int32
/*nIndex*/ ) const override
{ return 0; }
147 // the following two methods would, strictly speaking, require
148 // a switch to a real EditSource, too. Fortunately, the
149 // AccessibleEditableTextPara implementation currently always
150 // calls GetEditViewForwarder(true) before doing
151 // changes. Thus, we rely on this behaviour here (problem
152 // when that changes: via accessibility API, it would no
153 // longer be possible to enter text in previously empty
155 bool Delete( const ESelection
& ) override
{ return false; }
156 bool InsertText( const OUString
&, const ESelection
& ) override
{ return false; }
157 bool QuickFormatDoc( bool ) override
{ return true; }
158 sal_Int16
GetDepth( sal_Int32
) const override
{ return -1; }
159 bool SetDepth( sal_Int32
, sal_Int16
) override
{ return true; }
161 Point
LogicToPixel( const Point
& rPoint
, const MapMode
& /*rMapMode*/ ) const override
{ return rPoint
; }
162 Point
PixelToLogic( const Point
& rPoint
, const MapMode
& /*rMapMode*/ ) const override
{ return rPoint
; }
167 // Implementing AccessibleProxyEditSource_Impl
170 AccessibleProxyEditSource_Impl::AccessibleProxyEditSource_Impl( SdrObject
& rObj
,
172 const OutputDevice
& rViewWindow
) :
173 maEditSource( rObj
, nullptr, rView
, rViewWindow
)
177 SvxTextForwarder
* AccessibleProxyEditSource_Impl::GetTextForwarder()
179 return maEditSource
.GetTextForwarder();
182 SvxViewForwarder
* AccessibleProxyEditSource_Impl::GetViewForwarder()
184 return maEditSource
.GetViewForwarder();
187 SvxEditViewForwarder
* AccessibleProxyEditSource_Impl::GetEditViewForwarder( bool bCreate
)
189 return maEditSource
.GetEditViewForwarder( bCreate
);
192 std::unique_ptr
<SvxEditSource
> AccessibleProxyEditSource_Impl::Clone() const
194 return maEditSource
.Clone();
197 void AccessibleProxyEditSource_Impl::UpdateData()
199 maEditSource
.UpdateData();
202 SfxBroadcaster
& AccessibleProxyEditSource_Impl::GetBroadcaster() const
204 return maEditSource
.GetBroadcaster();
208 // Implementing AccessibleEmptyEditSource
211 AccessibleEmptyEditSource::AccessibleEmptyEditSource( SdrObject
& rObj
,
213 const OutputDevice
& rViewWindow
) :
214 mpEditSource( new AccessibleEmptyEditSource_Impl() ),
217 mrViewWindow(rViewWindow
),
218 mbEditSourceEmpty( true )
220 StartListening( mrObj
.getSdrModelFromSdrObject() );
223 AccessibleEmptyEditSource::~AccessibleEmptyEditSource()
225 if( !mbEditSourceEmpty
)
227 // deregister as listener
229 EndListening( mpEditSource
->GetBroadcaster() );
233 EndListening( mrObj
.getSdrModelFromSdrObject() );
237 SvxTextForwarder
* AccessibleEmptyEditSource::GetTextForwarder()
242 return mpEditSource
->GetTextForwarder();
245 SvxViewForwarder
* AccessibleEmptyEditSource::GetViewForwarder()
250 return mpEditSource
->GetViewForwarder();
253 void AccessibleEmptyEditSource::Switch2ProxyEditSource()
255 // deregister EmptyEditSource model listener
256 EndListening( mrObj
.getSdrModelFromSdrObject() );
258 ::std::unique_ptr
< SvxEditSource
> pProxySource( new AccessibleProxyEditSource_Impl(mrObj
, mrView
, mrViewWindow
) );
259 mpEditSource
.swap(pProxySource
);
261 // register as listener
262 StartListening( mpEditSource
->GetBroadcaster() );
264 // we've irrevocably a full EditSource now.
265 mbEditSourceEmpty
= false;
268 SvxEditViewForwarder
* AccessibleEmptyEditSource::GetEditViewForwarder( bool bCreate
)
273 // switch edit source, if not yet done
274 if( mbEditSourceEmpty
&& bCreate
)
275 Switch2ProxyEditSource();
277 return mpEditSource
->GetEditViewForwarder( bCreate
);
280 std::unique_ptr
<SvxEditSource
> AccessibleEmptyEditSource::Clone() const
285 return mpEditSource
->Clone();
288 void AccessibleEmptyEditSource::UpdateData()
291 mpEditSource
->UpdateData();
294 SfxBroadcaster
& AccessibleEmptyEditSource::GetBroadcaster() const
296 return *const_cast<AccessibleEmptyEditSource
*>(this);
299 void AccessibleEmptyEditSource::Notify( SfxBroadcaster
& /*rBC*/, const SfxHint
& rHint
)
301 const SdrHint
* pSdrHint
= ( rHint
.GetId() == SfxHintId::ThisIsAnSdrHint
? static_cast<const SdrHint
*>(&rHint
) : nullptr );
303 if( pSdrHint
&& pSdrHint
->GetKind() == SdrHintKind::BeginEdit
&&
304 &mrObj
== pSdrHint
->GetObject() && mpEditSource
.get() )
306 // switch edit source, if not yet done. This is necessary
307 // to become a full-fledged EditSource the first time a
308 // user start entering text in a previously empty object.
309 if( mbEditSourceEmpty
)
310 Switch2ProxyEditSource();
312 else if (pSdrHint
&& pSdrHint
->GetObject()!=nullptr)
314 // When the SdrObject just got a para outliner object then
315 // switch the edit source.
316 if (pSdrHint
->GetObject()->GetOutlinerParaObject() != nullptr)
317 Switch2ProxyEditSource();
324 } // end of namespace accessibility
327 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */