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 .
21 //------------------------------------------------------------------------
25 //------------------------------------------------------------------------
26 #include <svl/itemset.hxx>
27 #include <editeng/editdata.hxx>
28 #include <editeng/outliner.hxx>
29 #include <svx/svdmodel.hxx>
30 #include <svx/svdobj.hxx>
31 #include <svx/svdpool.hxx>
33 //------------------------------------------------------------------------
35 // Project-local header
37 //------------------------------------------------------------------------
39 #include "AccessibleEmptyEditSource.hxx"
40 #include <svx/unoshtxt.hxx>
42 namespace accessibility
45 /** This class simply wraps a SvxTextEditSource, forwarding all
46 methods except the GetBroadcaster() call
48 class AccessibleProxyEditSource_Impl
: public SvxEditSource
51 /** Construct AccessibleEmptyEditSource_Impl
55 Proxy broadcaster to allow seamless flipping of edit source implementations. ProxyEditSource and EmptyEditSource
57 AccessibleProxyEditSource_Impl( SdrObject
& rObj
,
59 const Window
& rViewWindow
);
60 ~AccessibleProxyEditSource_Impl();
62 // from the SvxEditSource interface
63 SvxTextForwarder
* GetTextForwarder();
64 SvxViewForwarder
* GetViewForwarder();
65 SvxEditViewForwarder
* GetEditViewForwarder( sal_Bool bCreate
= sal_False
);
67 SvxEditSource
* Clone() const;
71 SfxBroadcaster
& GetBroadcaster() const;
74 SvxTextEditSource maEditSource
;
78 /** Dummy class, faking exactly one empty paragraph for EditEngine accessibility
80 class AccessibleEmptyEditSource_Impl
: public SvxEditSource
, public SvxViewForwarder
, public SvxTextForwarder
, public SfxBroadcaster
84 AccessibleEmptyEditSource_Impl() {}
85 ~AccessibleEmptyEditSource_Impl() {}
87 // from the SfxListener interface
88 void Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
);
91 SvxTextForwarder
* GetTextForwarder() { return this; }
92 SvxViewForwarder
* GetViewForwarder() { return this; }
93 SvxEditSource
* Clone() const { return NULL
; }
95 SfxBroadcaster
& GetBroadcaster() const { return *(const_cast<AccessibleEmptyEditSource_Impl
*>(this)); }
98 sal_Int32
GetParagraphCount() const { return 1; }
99 sal_uInt16
GetTextLen( sal_Int32
/*nParagraph*/ ) const { return 0; }
100 String
GetText( const ESelection
& /*rSel*/ ) const { return String(); }
101 SfxItemSet
GetAttribs( const ESelection
& /*rSel*/, sal_Bool
/*bOnlyHardAttrib*/ = 0 ) const
103 // AW: Very dangerous: The former implementation used a SfxItemPool created on the
104 // fly which of course was deleted again ASAP. Thus, the returned SfxItemSet was using
105 // a deleted Pool by design.
106 return SfxItemSet(SdrObject::GetGlobalDrawObjectItemPool());
108 SfxItemSet
GetParaAttribs( sal_Int32
/*nPara*/ ) const { return GetAttribs(ESelection()); }
109 void SetParaAttribs( sal_Int32
/*nPara*/, const SfxItemSet
& /*rSet*/ ) {}
110 void RemoveAttribs( const ESelection
& /*rSelection*/, sal_Bool
/*bRemoveParaAttribs*/, sal_uInt16
/*nWhich*/ ){}
111 void GetPortions( sal_Int32
/*nPara*/, std::vector
<sal_uInt16
>& /*rList*/ ) const {}
113 sal_uInt16
GetItemState( const ESelection
& /*rSel*/, sal_uInt16
/*nWhich*/ ) const { return 0; }
114 sal_uInt16
GetItemState( sal_Int32
/*nPara*/, sal_uInt16
/*nWhich*/ ) const { return 0; }
116 SfxItemPool
* GetPool() const { return NULL
; }
118 void QuickInsertText( const String
& /*rText*/, const ESelection
& /*rSel*/ ) {}
119 void QuickInsertField( const SvxFieldItem
& /*rFld*/, const ESelection
& /*rSel*/ ) {}
120 void QuickSetAttribs( const SfxItemSet
& /*rSet*/, const ESelection
& /*rSel*/ ) {}
121 void QuickInsertLineBreak( const ESelection
& /*rSel*/ ) {}
123 const SfxItemSet
* GetEmptyItemSetPtr() { return 0; }
125 void AppendParagraph() {}
126 xub_StrLen
AppendTextPortion( sal_Int32
/*nPara*/, const String
& /*rText*/, const SfxItemSet
& /*rSet*/ ) { return 0; }
129 void CopyText(const SvxTextForwarder
& ){}
131 OUString
CalcFieldValue( const SvxFieldItem
& /*rField*/, sal_Int32
/*nPara*/, sal_uInt16
/*nPos*/, Color
*& /*rpTxtColor*/, Color
*& /*rpFldColor*/ )
135 void FieldClicked( const SvxFieldItem
&, sal_Int32
, xub_StrLen
) {;}
137 sal_Bool
IsValid() const { return sal_True
; }
139 void SetNotifyHdl( const Link
& ) {}
140 LanguageType
GetLanguage( sal_Int32
, sal_uInt16
) const { return LANGUAGE_DONTKNOW
; }
141 sal_uInt16
GetFieldCount( sal_Int32
) const { return 0; }
142 EFieldInfo
GetFieldInfo( sal_Int32
, sal_uInt16
) const { return EFieldInfo(); }
143 EBulletInfo
GetBulletInfo( sal_Int32
) const { return EBulletInfo(); }
144 Rectangle
GetCharBounds( sal_Int32
, sal_uInt16
) const { return Rectangle(); }
145 Rectangle
GetParaBounds( sal_Int32
) const { return Rectangle(); }
146 MapMode
GetMapMode() const { return MapMode(); }
147 OutputDevice
* GetRefDevice() const { return NULL
; }
148 sal_Bool
GetIndexAtPoint( const Point
&, sal_Int32
&, sal_uInt16
& ) const { return sal_False
; }
149 sal_Bool
GetWordIndices( sal_Int32
, sal_uInt16
, sal_uInt16
&, sal_uInt16
& ) const { return sal_False
; }
150 sal_Bool
GetAttributeRun( sal_uInt16
&, sal_uInt16
&, sal_Int32
, sal_uInt16
) const { return sal_False
; }
151 sal_uInt16
GetLineCount( sal_Int32 nPara
) const { return nPara
== 0 ? 1 : 0; }
152 sal_uInt16
GetLineLen( sal_Int32
, sal_uInt16
) const { return 0; }
153 void GetLineBoundaries( /*out*/sal_uInt16
& rStart
, /*out*/sal_uInt16
& rEnd
, sal_Int32
/*nParagraph*/, sal_uInt16
/*nLine*/ ) const { rStart
= rEnd
= 0; }
154 sal_uInt16
GetLineNumberAtIndex( sal_Int32
/*nPara*/, sal_uInt16
/*nIndex*/ ) const { return 0; }
156 // the following two methods would, strictly speaking, require
157 // a switch to a real EditSource, too. Fortunately, the
158 // AccessibleEditableTextPara implementation currently always
159 // calls GetEditViewForwarder(true) before doing
160 // changes. Thus, we rely on this behabviour here (problem
161 // when that changes: via accessibility API, it would no
162 // longer be possible to enter text in previously empty
164 sal_Bool
Delete( const ESelection
& ) { return sal_False
; }
165 sal_Bool
InsertText( const String
&, const ESelection
& ) { return sal_False
; }
166 sal_Bool
QuickFormatDoc( sal_Bool
) { return sal_True
; }
167 sal_Int16
GetDepth( sal_Int32
) const { return -1; }
168 sal_Bool
SetDepth( sal_Int32
, sal_Int16
) { return sal_True
; }
170 Rectangle
GetVisArea() const { return Rectangle(); }
171 Point
LogicToPixel( const Point
& rPoint
, const MapMode
& /*rMapMode*/ ) const { return rPoint
; }
172 Point
PixelToLogic( const Point
& rPoint
, const MapMode
& /*rMapMode*/ ) const { return rPoint
; }
176 // -------------------------------------------------------------------------
177 // Implementing AccessibleProxyEditSource_Impl
178 // -------------------------------------------------------------------------
180 AccessibleProxyEditSource_Impl::AccessibleProxyEditSource_Impl( SdrObject
& rObj
,
182 const Window
& rViewWindow
) :
183 maEditSource( rObj
, 0, rView
, rViewWindow
)
187 AccessibleProxyEditSource_Impl::~AccessibleProxyEditSource_Impl()
191 SvxTextForwarder
* AccessibleProxyEditSource_Impl::GetTextForwarder()
193 return maEditSource
.GetTextForwarder();
196 SvxViewForwarder
* AccessibleProxyEditSource_Impl::GetViewForwarder()
198 return maEditSource
.GetViewForwarder();
201 SvxEditViewForwarder
* AccessibleProxyEditSource_Impl::GetEditViewForwarder( sal_Bool bCreate
)
203 return maEditSource
.GetEditViewForwarder( bCreate
);
206 SvxEditSource
* AccessibleProxyEditSource_Impl::Clone() const
208 return maEditSource
.Clone();
211 void AccessibleProxyEditSource_Impl::UpdateData()
213 maEditSource
.UpdateData();
216 SfxBroadcaster
& AccessibleProxyEditSource_Impl::GetBroadcaster() const
218 return maEditSource
.GetBroadcaster();
222 // -------------------------------------------------------------------------
223 // Implementing AccessibleEmptyEditSource
224 // -------------------------------------------------------------------------
226 AccessibleEmptyEditSource::AccessibleEmptyEditSource( SdrObject
& rObj
,
228 const Window
& rViewWindow
) :
229 mpEditSource( new AccessibleEmptyEditSource_Impl() ),
232 mrViewWindow(rViewWindow
),
233 mbEditSourceEmpty( true )
235 if( mrObj
.GetModel() )
236 StartListening( *mrObj
.GetModel() );
239 AccessibleEmptyEditSource::~AccessibleEmptyEditSource()
241 if( !mbEditSourceEmpty
)
243 // deregister as listener
244 if( mpEditSource
.get() )
245 EndListening( mpEditSource
->GetBroadcaster() );
249 if( mrObj
.GetModel() )
250 EndListening( *mrObj
.GetModel() );
254 SvxTextForwarder
* AccessibleEmptyEditSource::GetTextForwarder()
256 if( !mpEditSource
.get() )
259 return mpEditSource
->GetTextForwarder();
262 SvxViewForwarder
* AccessibleEmptyEditSource::GetViewForwarder()
264 if( !mpEditSource
.get() )
267 return mpEditSource
->GetViewForwarder();
270 void AccessibleEmptyEditSource::Switch2ProxyEditSource()
272 // deregister EmptyEditSource model listener
273 if( mrObj
.GetModel() )
274 EndListening( *mrObj
.GetModel() );
276 SAL_WNODEPRECATED_DECLARATIONS_PUSH
277 ::std::auto_ptr
< SvxEditSource
> pProxySource( new AccessibleProxyEditSource_Impl(mrObj
, mrView
, mrViewWindow
) );
278 ::std::auto_ptr
< SvxEditSource
> tmp
= mpEditSource
;
279 SAL_WNODEPRECATED_DECLARATIONS_POP
280 mpEditSource
= pProxySource
;
283 // register as listener
284 StartListening( mpEditSource
->GetBroadcaster() );
286 // we've irrevocably a full EditSource now.
287 mbEditSourceEmpty
= false;
290 SvxEditViewForwarder
* AccessibleEmptyEditSource::GetEditViewForwarder( sal_Bool bCreate
)
292 if( !mpEditSource
.get() )
295 // switch edit source, if not yet done
296 if( mbEditSourceEmpty
&& bCreate
)
297 Switch2ProxyEditSource();
299 return mpEditSource
->GetEditViewForwarder( bCreate
);
302 SvxEditSource
* AccessibleEmptyEditSource::Clone() const
304 if( !mpEditSource
.get() )
307 return mpEditSource
->Clone();
310 void AccessibleEmptyEditSource::UpdateData()
312 if( mpEditSource
.get() )
313 mpEditSource
->UpdateData();
316 SfxBroadcaster
& AccessibleEmptyEditSource::GetBroadcaster() const
318 return *(const_cast<AccessibleEmptyEditSource
*>(this));
321 void AccessibleEmptyEditSource::Notify( SfxBroadcaster
& /*rBC*/, const SfxHint
& rHint
)
323 const SdrHint
* pSdrHint
= PTR_CAST( SdrHint
, &rHint
);
325 if( pSdrHint
&& pSdrHint
->GetKind() == HINT_BEGEDIT
&&
326 &mrObj
== pSdrHint
->GetObject() && mpEditSource
.get() )
328 // switch edit source, if not yet done. This is necessary
329 // to become a full-fledged EditSource the first time a
330 // user start entering text in a previously empty object.
331 if( mbEditSourceEmpty
)
332 Switch2ProxyEditSource();
334 else if (pSdrHint
&& pSdrHint
->GetObject()!=NULL
)
336 // When the SdrObject just got a para outliner object then
337 // switch the edit source.
338 if (pSdrHint
->GetObject()->GetOutlinerParaObject() != NULL
)
339 Switch2ProxyEditSource();
346 } // end of namespace accessibility
348 //------------------------------------------------------------------------
350 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */