Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : //------------------------------------------------------------------------
31 : : //
32 : : // Global header
33 : : //
34 : : //------------------------------------------------------------------------
35 : : #include <svl/itemset.hxx>
36 : : #include <editeng/editdata.hxx>
37 : : #include <editeng/outliner.hxx>
38 : : #include <svx/svdmodel.hxx>
39 : : #include <svx/svdobj.hxx>
40 : : #include <svx/svdpool.hxx>
41 : :
42 : : //------------------------------------------------------------------------
43 : : //
44 : : // Project-local header
45 : : //
46 : : //------------------------------------------------------------------------
47 : :
48 : : #include "AccessibleEmptyEditSource.hxx"
49 : : #include <svx/unoshtxt.hxx>
50 : :
51 : : namespace accessibility
52 : : {
53 : :
54 : : /** This class simply wraps a SvxTextEditSource, forwarding all
55 : : methods except the GetBroadcaster() call
56 : : */
57 : : class AccessibleProxyEditSource_Impl : public SvxEditSource
58 : : {
59 : : public:
60 : : /** Construct AccessibleEmptyEditSource_Impl
61 : :
62 : : @param rBrdCast
63 : :
64 : : Proxy broadcaster to allow seamless flipping of edit source implementations. ProxyEditSource and EmptyEditSource
65 : : */
66 : : AccessibleProxyEditSource_Impl( SdrObject& rObj,
67 : : SdrView& rView,
68 : : const Window& rViewWindow );
69 : : ~AccessibleProxyEditSource_Impl();
70 : :
71 : : // from the SvxEditSource interface
72 : : SvxTextForwarder* GetTextForwarder();
73 : : SvxViewForwarder* GetViewForwarder();
74 : : SvxEditViewForwarder* GetEditViewForwarder( sal_Bool bCreate = sal_False );
75 : :
76 : : SvxEditSource* Clone() const;
77 : :
78 : : void UpdateData();
79 : :
80 : : SfxBroadcaster& GetBroadcaster() const;
81 : :
82 : : private:
83 : : SvxTextEditSource maEditSource;
84 : :
85 : : };
86 : :
87 : : /** Dummy class, faking exactly one empty paragraph for EditEngine accessibility
88 : : */
89 : : class AccessibleEmptyEditSource_Impl : public SvxEditSource, public SvxViewForwarder, public SvxTextForwarder, public SfxBroadcaster
90 : : {
91 : : public:
92 : :
93 [ + - ]: 8 : AccessibleEmptyEditSource_Impl() {}
94 [ + - ][ + - ]: 16 : ~AccessibleEmptyEditSource_Impl() {}
[ + - ][ - + ]
95 : :
96 : : // from the SfxListener interface
97 : : void Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
98 : :
99 : : // SvxEditSource
100 : 24 : SvxTextForwarder* GetTextForwarder() { return this; }
101 : 8 : SvxViewForwarder* GetViewForwarder() { return this; }
102 : 0 : SvxEditSource* Clone() const { return NULL; }
103 : 0 : void UpdateData() {}
104 : 0 : SfxBroadcaster& GetBroadcaster() const { return *(const_cast<AccessibleEmptyEditSource_Impl*>(this)); }
105 : :
106 : : // SvxTextForwarder
107 : 24 : sal_uInt16 GetParagraphCount() const { return 1; }
108 : 0 : sal_uInt16 GetTextLen( sal_uInt16 /*nParagraph*/ ) const { return 0; }
109 : 0 : String GetText( const ESelection& /*rSel*/ ) const { return String(); }
110 : 0 : SfxItemSet GetAttribs( const ESelection& /*rSel*/, sal_Bool /*bOnlyHardAttrib*/ = 0 ) const
111 : : {
112 : : // AW: Very dangerous: The former implementation used a SfxItemPool created on the
113 : : // fly which of course was deleted again ASAP. Thus, the returned SfxItemSet was using
114 : : // a deleted Pool by design.
115 : 0 : return SfxItemSet(SdrObject::GetGlobalDrawObjectItemPool());
116 : : }
117 [ # # ]: 0 : SfxItemSet GetParaAttribs( sal_uInt16 /*nPara*/ ) const { return GetAttribs(ESelection()); }
118 : 0 : void SetParaAttribs( sal_uInt16 /*nPara*/, const SfxItemSet& /*rSet*/ ) {}
119 : 0 : void RemoveAttribs( const ESelection& /*rSelection*/, sal_Bool /*bRemoveParaAttribs*/, sal_uInt16 /*nWhich*/ ){}
120 : 0 : void GetPortions( sal_uInt16 /*nPara*/, std::vector<sal_uInt16>& /*rList*/ ) const {}
121 : :
122 : 0 : sal_uInt16 GetItemState( const ESelection& /*rSel*/, sal_uInt16 /*nWhich*/ ) const { return 0; }
123 : 0 : sal_uInt16 GetItemState( sal_uInt16 /*nPara*/, sal_uInt16 /*nWhich*/ ) const { return 0; }
124 : :
125 : 0 : SfxItemPool* GetPool() const { return NULL; }
126 : :
127 : 0 : void QuickInsertText( const String& /*rText*/, const ESelection& /*rSel*/ ) {}
128 : 0 : void QuickInsertField( const SvxFieldItem& /*rFld*/, const ESelection& /*rSel*/ ) {}
129 : 0 : void QuickSetAttribs( const SfxItemSet& /*rSet*/, const ESelection& /*rSel*/ ) {}
130 : 0 : void QuickInsertLineBreak( const ESelection& /*rSel*/ ) {}
131 : :
132 : 0 : const SfxItemSet * GetEmptyItemSetPtr() { return 0; }
133 : :
134 : 0 : void AppendParagraph() {}
135 : 0 : xub_StrLen AppendTextPortion( sal_uInt16 /*nPara*/, const String & /*rText*/, const SfxItemSet & /*rSet*/ ) { return 0; }
136 : :
137 : : //XTextCopy
138 : 0 : void CopyText(const SvxTextForwarder& ){}
139 : :
140 : 0 : XubString CalcFieldValue( const SvxFieldItem& /*rField*/, sal_uInt16 /*nPara*/, sal_uInt16 /*nPos*/, Color*& /*rpTxtColor*/, Color*& /*rpFldColor*/ )
141 : : {
142 : 0 : return XubString();
143 : : }
144 : 0 : void FieldClicked( const SvxFieldItem&, sal_uInt16, xub_StrLen ) {;}
145 : :
146 : 32 : sal_Bool IsValid() const { return sal_True; }
147 : :
148 : : void SetNotifyHdl( const Link& ) {}
149 : 0 : LanguageType GetLanguage( sal_uInt16, sal_uInt16 ) const { return LANGUAGE_DONTKNOW; }
150 : 0 : sal_uInt16 GetFieldCount( sal_uInt16 ) const { return 0; }
151 : 0 : EFieldInfo GetFieldInfo( sal_uInt16, sal_uInt16 ) const { return EFieldInfo(); }
152 : 8 : EBulletInfo GetBulletInfo( sal_uInt16 ) const { return EBulletInfo(); }
153 : 0 : Rectangle GetCharBounds( sal_uInt16, sal_uInt16 ) const { return Rectangle(); }
154 : 8 : Rectangle GetParaBounds( sal_uInt16 ) const { return Rectangle(); }
155 : 8 : MapMode GetMapMode() const { return MapMode(); }
156 : 0 : OutputDevice* GetRefDevice() const { return NULL; }
157 : 0 : sal_Bool GetIndexAtPoint( const Point&, sal_uInt16&, sal_uInt16& ) const { return sal_False; }
158 : 0 : sal_Bool GetWordIndices( sal_uInt16, sal_uInt16, sal_uInt16&, sal_uInt16& ) const { return sal_False; }
159 : 0 : sal_Bool GetAttributeRun( sal_uInt16&, sal_uInt16&, sal_uInt16, sal_uInt16 ) const { return sal_False; }
160 [ # # ]: 0 : sal_uInt16 GetLineCount( sal_uInt16 nPara ) const { return nPara == 0 ? 1 : 0; }
161 : 0 : sal_uInt16 GetLineLen( sal_uInt16, sal_uInt16 ) const { return 0; }
162 : 0 : void GetLineBoundaries( /*out*/sal_uInt16 & rStart, /*out*/sal_uInt16 & rEnd, sal_uInt16 /*nParagraph*/, sal_uInt16 /*nLine*/ ) const { rStart = rEnd = 0; }
163 : 0 : sal_uInt16 GetLineNumberAtIndex( sal_uInt16 /*nPara*/, sal_uInt16 /*nIndex*/ ) const { return 0; }
164 : :
165 : : // the following two methods would, strictly speaking, require
166 : : // a switch to a real EditSource, too. Fortunately, the
167 : : // AccessibleEditableTextPara implementation currently always
168 : : // calls GetEditViewForwarder(true) before doing
169 : : // changes. Thus, we rely on this behabviour here (problem
170 : : // when that changes: via accessibility API, it would no
171 : : // longer be possible to enter text in previously empty
172 : : // shapes).
173 : 0 : sal_Bool Delete( const ESelection& ) { return sal_False; }
174 : 0 : sal_Bool InsertText( const String&, const ESelection& ) { return sal_False; }
175 : 0 : sal_Bool QuickFormatDoc( sal_Bool ) { return sal_True; }
176 : 0 : sal_Int16 GetDepth( sal_uInt16 ) const { return -1; }
177 : 0 : sal_Bool SetDepth( sal_uInt16, sal_Int16 ) { return sal_True; }
178 : :
179 : 8 : Rectangle GetVisArea() const { return Rectangle(); }
180 : 16 : Point LogicToPixel( const Point& rPoint, const MapMode& /*rMapMode*/ ) const { return rPoint; }
181 : 0 : Point PixelToLogic( const Point& rPoint, const MapMode& /*rMapMode*/ ) const { return rPoint; }
182 : :
183 : : };
184 : :
185 : : // -------------------------------------------------------------------------
186 : : // Implementing AccessibleProxyEditSource_Impl
187 : : // -------------------------------------------------------------------------
188 : :
189 : 0 : AccessibleProxyEditSource_Impl::AccessibleProxyEditSource_Impl( SdrObject& rObj,
190 : : SdrView& rView,
191 : : const Window& rViewWindow ) :
192 [ # # ]: 0 : maEditSource( rObj, 0, rView, rViewWindow )
193 : : {
194 : 0 : }
195 : :
196 [ # # ]: 0 : AccessibleProxyEditSource_Impl::~AccessibleProxyEditSource_Impl()
197 : : {
198 [ # # ]: 0 : }
199 : :
200 : 0 : SvxTextForwarder* AccessibleProxyEditSource_Impl::GetTextForwarder()
201 : : {
202 : 0 : return maEditSource.GetTextForwarder();
203 : : }
204 : :
205 : 0 : SvxViewForwarder* AccessibleProxyEditSource_Impl::GetViewForwarder()
206 : : {
207 : 0 : return maEditSource.GetViewForwarder();
208 : : }
209 : :
210 : 0 : SvxEditViewForwarder* AccessibleProxyEditSource_Impl::GetEditViewForwarder( sal_Bool bCreate )
211 : : {
212 : 0 : return maEditSource.GetEditViewForwarder( bCreate );
213 : : }
214 : :
215 : 0 : SvxEditSource* AccessibleProxyEditSource_Impl::Clone() const
216 : : {
217 : 0 : return maEditSource.Clone();
218 : : }
219 : :
220 : 0 : void AccessibleProxyEditSource_Impl::UpdateData()
221 : : {
222 : 0 : maEditSource.UpdateData();
223 : 0 : }
224 : :
225 : 0 : SfxBroadcaster& AccessibleProxyEditSource_Impl::GetBroadcaster() const
226 : : {
227 : 0 : return maEditSource.GetBroadcaster();
228 : : }
229 : :
230 : :
231 : : // -------------------------------------------------------------------------
232 : : // Implementing AccessibleEmptyEditSource
233 : : // -------------------------------------------------------------------------
234 : :
235 : 8 : AccessibleEmptyEditSource::AccessibleEmptyEditSource( SdrObject& rObj,
236 : : SdrView& rView,
237 : : const Window& rViewWindow ) :
238 : 0 : mpEditSource( new AccessibleEmptyEditSource_Impl() ),
239 : : mrObj(rObj),
240 : : mrView(rView),
241 : : mrViewWindow(rViewWindow),
242 [ + - ][ + - ]: 8 : mbEditSourceEmpty( true )
[ + - ][ + - ]
243 : : {
244 [ + - ][ + - ]: 8 : if( mrObj.GetModel() )
245 [ + - ][ + - ]: 8 : StartListening( *mrObj.GetModel() );
246 : 8 : }
247 : :
248 [ + - ][ + - ]: 8 : AccessibleEmptyEditSource::~AccessibleEmptyEditSource()
[ + - ]
249 : : {
250 [ - + ]: 8 : if( !mbEditSourceEmpty )
251 : : {
252 : : // deregister as listener
253 [ # # ]: 0 : if( mpEditSource.get() )
254 [ # # ][ # # ]: 0 : EndListening( mpEditSource->GetBroadcaster() );
255 : : }
256 : : else
257 : : {
258 [ + - ][ + - ]: 8 : if( mrObj.GetModel() )
259 [ + - ][ + - ]: 8 : EndListening( *mrObj.GetModel() );
260 : : }
261 [ - + ]: 16 : }
262 : :
263 : 24 : SvxTextForwarder* AccessibleEmptyEditSource::GetTextForwarder()
264 : : {
265 [ - + ]: 24 : if( !mpEditSource.get() )
266 : 0 : return NULL;
267 : :
268 : 24 : return mpEditSource->GetTextForwarder();
269 : : }
270 : :
271 : 8 : SvxViewForwarder* AccessibleEmptyEditSource::GetViewForwarder()
272 : : {
273 [ - + ]: 8 : if( !mpEditSource.get() )
274 : 0 : return NULL;
275 : :
276 : 8 : return mpEditSource->GetViewForwarder();
277 : : }
278 : :
279 : 0 : void AccessibleEmptyEditSource::Switch2ProxyEditSource()
280 : : {
281 : : // deregister EmptyEditSource model listener
282 [ # # ][ # # ]: 0 : if( mrObj.GetModel() )
283 [ # # ][ # # ]: 0 : EndListening( *mrObj.GetModel() );
284 : :
285 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
286 [ # # ][ # # ]: 0 : ::std::auto_ptr< SvxEditSource > pProxySource( new AccessibleProxyEditSource_Impl(mrObj, mrView, mrViewWindow) );
287 : 0 : ::std::auto_ptr< SvxEditSource > tmp = mpEditSource;
288 : : SAL_WNODEPRECATED_DECLARATIONS_POP
289 : 0 : mpEditSource = pProxySource;
290 : 0 : pProxySource = tmp;
291 : :
292 : : // register as listener
293 [ # # ][ # # ]: 0 : StartListening( mpEditSource->GetBroadcaster() );
294 : :
295 : : // we've irrevocably a full EditSource now.
296 [ # # ][ # # ]: 0 : mbEditSourceEmpty = false;
297 : 0 : }
298 : :
299 : 10 : SvxEditViewForwarder* AccessibleEmptyEditSource::GetEditViewForwarder( sal_Bool bCreate )
300 : : {
301 [ - + ]: 10 : if( !mpEditSource.get() )
302 : 0 : return NULL;
303 : :
304 : : // switch edit source, if not yet done
305 [ + - ][ - + ]: 10 : if( mbEditSourceEmpty && bCreate )
306 : 0 : Switch2ProxyEditSource();
307 : :
308 : 10 : return mpEditSource->GetEditViewForwarder( bCreate );
309 : : }
310 : :
311 : 0 : SvxEditSource* AccessibleEmptyEditSource::Clone() const
312 : : {
313 [ # # ]: 0 : if( !mpEditSource.get() )
314 : 0 : return NULL;
315 : :
316 : 0 : return mpEditSource->Clone();
317 : : }
318 : :
319 : 0 : void AccessibleEmptyEditSource::UpdateData()
320 : : {
321 [ # # ]: 0 : if( mpEditSource.get() )
322 : 0 : mpEditSource->UpdateData();
323 : 0 : }
324 : :
325 : 16 : SfxBroadcaster& AccessibleEmptyEditSource::GetBroadcaster() const
326 : : {
327 : 16 : return *(const_cast<AccessibleEmptyEditSource*>(this));
328 : : }
329 : :
330 : 4 : void AccessibleEmptyEditSource::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
331 : : {
332 [ + - ][ + - ]: 4 : const SdrHint* pSdrHint = PTR_CAST( SdrHint, &rHint );
333 : :
334 [ + - ][ - + : 4 : if( pSdrHint && pSdrHint->GetKind() == HINT_BEGEDIT &&
# # # # ]
[ - + ]
335 : 0 : &mrObj == pSdrHint->GetObject() && mpEditSource.get() )
336 : : {
337 : : // switch edit source, if not yet done. This is necessary
338 : : // to become a full-fledged EditSource the first time a
339 : : // user start entering text in a previously empty object.
340 [ # # ]: 0 : if( mbEditSourceEmpty )
341 : 0 : Switch2ProxyEditSource();
342 : : }
343 [ + - ][ + - ]: 4 : else if (pSdrHint && pSdrHint->GetObject()!=NULL)
[ + - ]
344 : : {
345 : : // When the SdrObject just got a para outliner object then
346 : : // switch the edit source.
347 [ - + ]: 4 : if (pSdrHint->GetObject()->GetOutlinerParaObject() != NULL)
348 : 0 : Switch2ProxyEditSource();
349 : : }
350 : :
351 : : // forward messages
352 : 4 : Broadcast( rHint );
353 : 4 : }
354 : :
355 : : } // end of namespace accessibility
356 : :
357 : : //------------------------------------------------------------------------
358 : :
359 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|