/src/libreoffice/svx/source/unodraw/unoshtxt.cxx
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
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/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
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 . |
18 | | */ |
19 | | |
20 | | #include <sal/config.h> |
21 | | |
22 | | #include <memory> |
23 | | |
24 | | #include <vcl/svapp.hxx> |
25 | | |
26 | | #include <svx/unoshtxt.hxx> |
27 | | #include <editeng/unoedhlp.hxx> |
28 | | #include <svl/lstner.hxx> |
29 | | #include <rtl/ref.hxx> |
30 | | #include <tools/debug.hxx> |
31 | | #include <svl/hint.hxx> |
32 | | #include <svl/style.hxx> |
33 | | #include <svx/svdmodel.hxx> |
34 | | #include <svx/svdoutl.hxx> |
35 | | #include <svx/svdobj.hxx> |
36 | | #include <svx/svdview.hxx> |
37 | | #include <editeng/outliner.hxx> |
38 | | #include <editeng/unoforou.hxx> |
39 | | #include <editeng/unoviwou.hxx> |
40 | | #include <editeng/outlobj.hxx> |
41 | | #include <svx/svdotext.hxx> |
42 | | #include <svx/svdpage.hxx> |
43 | | #include <editeng/editeng.hxx> |
44 | | |
45 | | #include <editeng/unotext.hxx> |
46 | | #include <com/sun/star/linguistic2/LinguServiceManager.hpp> |
47 | | #include <comphelper/processfactory.hxx> |
48 | | #include <svx/svdotable.hxx> |
49 | | #include <cell.hxx> |
50 | | #include <comphelper/configuration.hxx> |
51 | | |
52 | | |
53 | | // SvxTextEditSourceImpl |
54 | | |
55 | | |
56 | | /** @descr |
57 | | <p>This class essentially provides the text and view forwarders. If |
58 | | no SdrView is given, this class handles the UNO objects, which are |
59 | | currently not concerned with view issues. In this case, |
60 | | GetViewForwarder() always returns NULL and the underlying |
61 | | EditEngine of the SvxTextForwarder is a background one (i.e. not |
62 | | the official DrawOutliner, but one created exclusively for this |
63 | | object, with no relation to a view). |
64 | | </p> |
65 | | |
66 | | <p>If a SdrView is given at construction time, the caller is |
67 | | responsible for destroying this object when the view becomes |
68 | | invalid (the views cannot notify). If GetViewForwarder(sal_True) |
69 | | is called, the underlying shape is put into edit mode, the view |
70 | | forwarder returned encapsulates the OutlinerView and the next call |
71 | | to GetTextForwarder() yields a forwarder encapsulating the actual |
72 | | DrawOutliner. Thus, changes on that Outliner are immediately |
73 | | reflected on the screen. If the object leaves edit mode, the old |
74 | | behaviour is restored.</p> |
75 | | */ |
76 | | class SvxTextEditSourceImpl : public SfxListener, public SfxBroadcaster, public sdr::ObjectUser |
77 | | { |
78 | | private: |
79 | | oslInterlockedCount maRefCount; |
80 | | |
81 | | SdrObject* mpObject; // TTTT could be reference (?) |
82 | | SdrText* mpText; |
83 | | SdrView* mpView; |
84 | | VclPtr<const OutputDevice> mpWindow; |
85 | | SdrModel* mpModel; // TTTT probably not needed -> use SdrModel from SdrObject (?) |
86 | | std::unique_ptr<SdrOutliner> mpOutliner; |
87 | | std::unique_ptr<SvxOutlinerForwarder> mpTextForwarder; |
88 | | std::unique_ptr<SvxDrawOutlinerViewForwarder> mpViewForwarder; // if non-NULL, use GetViewModeTextForwarder text forwarder |
89 | | css::uno::Reference< css::linguistic2::XLinguServiceManager2 > m_xLinguServiceManager; |
90 | | Point maTextOffset; |
91 | | bool mbDataValid; |
92 | | bool mbIsLocked; |
93 | | bool mbNeedsUpdate; |
94 | | bool mbOldUndoMode; |
95 | | bool mbForwarderIsEditMode; // have to reflect that, since ENDEDIT can happen more often |
96 | | bool mbShapeIsEditMode; // only true, if SdrHintKind::BeginEdit was received |
97 | | bool mbNotificationsDisabled; // prevent EditEngine/Outliner notifications (e.g. when setting up forwarder) |
98 | | bool mbNotifyEditOutlinerSet; |
99 | | |
100 | | SvxUnoTextRangeBaseVec mvTextRanges; |
101 | | |
102 | | SvxTextForwarder* GetBackgroundTextForwarder(); |
103 | | SvxTextForwarder* GetEditModeTextForwarder(); |
104 | | std::unique_ptr<SvxDrawOutlinerViewForwarder> CreateViewForwarder(); |
105 | | |
106 | | void SetupOutliner(); |
107 | | |
108 | 12.8M | bool HasView() const { return mpView != nullptr; } |
109 | | bool IsEditMode() const |
110 | 11.0M | { |
111 | 11.0M | if (!mbShapeIsEditMode) |
112 | 11.0M | return false; |
113 | 0 | SdrTextObj* pTextObj = DynCastSdrTextObj( mpObject ); |
114 | 0 | return pTextObj && pTextObj->IsTextEditActive(); |
115 | 11.0M | } |
116 | | |
117 | | void dispose(); |
118 | | |
119 | | public: |
120 | | SvxTextEditSourceImpl( SdrObject* pObject, SdrText* pText ); |
121 | | SvxTextEditSourceImpl( SdrObject& rObject, SdrText* pText, SdrView& rView, const OutputDevice& rWindow ); |
122 | | virtual ~SvxTextEditSourceImpl() override; |
123 | | |
124 | | void acquire(); |
125 | | void release(); |
126 | | |
127 | | virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override; |
128 | | |
129 | | SvxTextForwarder* GetTextForwarder(); |
130 | | SvxEditViewForwarder* GetEditViewForwarder( bool ); |
131 | | void UpdateData(); |
132 | | |
133 | | void addRange( SvxUnoTextRangeBase* pNewRange ); |
134 | | void removeRange( SvxUnoTextRangeBase* pOldRange ); |
135 | 195 | const SvxUnoTextRangeBaseVec& getRanges() const { return mvTextRanges;} |
136 | | |
137 | | void lock(); |
138 | | void unlock(); |
139 | | |
140 | | bool IsValid() const; |
141 | | |
142 | | Point LogicToPixel( const Point&, const MapMode& rMapMode ); |
143 | | Point PixelToLogic( const Point&, const MapMode& rMapMode ); |
144 | | |
145 | | DECL_LINK( NotifyHdl, EENotify&, void ); |
146 | | |
147 | | virtual void ObjectInDestruction(const SdrObject& rObject) override; |
148 | | |
149 | | void UpdateOutliner(); |
150 | | }; |
151 | | |
152 | | |
153 | | SvxTextEditSourceImpl::SvxTextEditSourceImpl( SdrObject* pObject, SdrText* pText ) |
154 | 526k | : maRefCount ( 0 ), |
155 | 526k | mpObject ( pObject ), |
156 | 526k | mpText ( pText ), |
157 | 526k | mpView ( nullptr ), |
158 | 526k | mpWindow ( nullptr ), |
159 | 526k | mpModel ( pObject ? &pObject->getSdrModelFromSdrObject() : nullptr ), // TTTT should be reference |
160 | 526k | mbDataValid ( false ), |
161 | 526k | mbIsLocked ( false ), |
162 | 526k | mbNeedsUpdate ( false ), |
163 | 526k | mbOldUndoMode ( false ), |
164 | 526k | mbForwarderIsEditMode ( false ), |
165 | 526k | mbShapeIsEditMode ( false ), |
166 | 526k | mbNotificationsDisabled ( false ), |
167 | 526k | mbNotifyEditOutlinerSet ( false ) |
168 | 526k | { |
169 | 526k | DBG_ASSERT( mpObject, "invalid pObject!" ); |
170 | | |
171 | 526k | if( !mpText ) |
172 | 403k | { |
173 | 403k | SdrTextObj* pTextObj = DynCastSdrTextObj( mpObject ); |
174 | 403k | if( pTextObj ) |
175 | 403k | mpText = pTextObj->getText( 0 ); |
176 | 403k | } |
177 | | |
178 | 526k | if( mpObject ) |
179 | 526k | { |
180 | 526k | mpObject->AddListener( *this ); |
181 | 526k | mpObject->AddObjectUser( *this ); |
182 | 526k | } |
183 | 526k | } |
184 | | |
185 | | |
186 | | SvxTextEditSourceImpl::SvxTextEditSourceImpl( SdrObject& rObject, SdrText* pText, SdrView& rView, const OutputDevice& rWindow ) |
187 | 0 | : maRefCount ( 0 ), |
188 | 0 | mpObject ( &rObject ), |
189 | 0 | mpText ( pText ), |
190 | 0 | mpView ( &rView ), |
191 | 0 | mpWindow ( &rWindow ), |
192 | 0 | mpModel ( &rObject.getSdrModelFromSdrObject() ), // TTTT should be reference |
193 | 0 | mbDataValid ( false ), |
194 | 0 | mbIsLocked ( false ), |
195 | 0 | mbNeedsUpdate ( false ), |
196 | 0 | mbOldUndoMode ( false ), |
197 | 0 | mbForwarderIsEditMode ( false ), |
198 | 0 | mbShapeIsEditMode ( true ), |
199 | 0 | mbNotificationsDisabled ( false ), |
200 | 0 | mbNotifyEditOutlinerSet ( false ) |
201 | 0 | { |
202 | 0 | if( !mpText ) |
203 | 0 | { |
204 | 0 | SdrTextObj* pTextObj = DynCastSdrTextObj( mpObject ); |
205 | 0 | if( pTextObj ) |
206 | 0 | mpText = pTextObj->getText( 0 ); |
207 | 0 | } |
208 | |
|
209 | 0 | rObject.AddListener( *this ); |
210 | 0 | StartListening( *mpView ); |
211 | 0 | mpObject->AddObjectUser( *this ); |
212 | | |
213 | | // Init edit mode state from shape info (IsTextEditActive()) |
214 | 0 | mbShapeIsEditMode = IsEditMode(); |
215 | 0 | } |
216 | | |
217 | | |
218 | | SvxTextEditSourceImpl::~SvxTextEditSourceImpl() |
219 | 526k | { |
220 | 526k | DBG_ASSERT( !mbIsLocked, "text edit source was not unlocked before dispose!" ); |
221 | 526k | if( mpObject ) |
222 | 522k | mpObject->RemoveObjectUser( *this ); |
223 | | |
224 | 526k | dispose(); |
225 | 526k | } |
226 | | |
227 | | |
228 | | void SvxTextEditSourceImpl::addRange( SvxUnoTextRangeBase* pNewRange ) |
229 | 961k | { |
230 | 961k | if( pNewRange ) |
231 | 961k | if( std::find( mvTextRanges.begin(), mvTextRanges.end(), pNewRange ) == mvTextRanges.end() ) |
232 | 961k | mvTextRanges.push_back( pNewRange ); |
233 | 961k | } |
234 | | |
235 | | |
236 | | void SvxTextEditSourceImpl::removeRange( SvxUnoTextRangeBase* pOldRange ) |
237 | 961k | { |
238 | 961k | if( pOldRange ) |
239 | 961k | std::erase(mvTextRanges, pOldRange); |
240 | 961k | } |
241 | | |
242 | | |
243 | | void SvxTextEditSourceImpl::acquire() |
244 | 1.12M | { |
245 | 1.12M | osl_atomic_increment( &maRefCount ); |
246 | 1.12M | } |
247 | | |
248 | | |
249 | | void SvxTextEditSourceImpl::release() |
250 | 1.12M | { |
251 | 1.12M | if( ! osl_atomic_decrement( &maRefCount ) ) |
252 | 526k | delete this; |
253 | 1.12M | } |
254 | | |
255 | | void SvxTextEditSourceImpl::Notify(SfxBroadcaster& rBC, const SfxHint& rHint) |
256 | 167k | { |
257 | | // #i105988 keep reference to this object |
258 | 167k | rtl::Reference< SvxTextEditSourceImpl > xThis( this ); |
259 | | |
260 | 167k | if (SfxHintId::Dying == rHint.GetId()) |
261 | 3.78k | { |
262 | 3.78k | if (&rBC == mpView) |
263 | 0 | { |
264 | 0 | mpView = nullptr; |
265 | 0 | mpViewForwarder.reset(); |
266 | 0 | } |
267 | 3.78k | } |
268 | 163k | else if (rHint.GetId() == SfxHintId::ThisIsAnSdrHint) |
269 | 163k | { |
270 | 163k | const SdrHint* pSdrHint = static_cast<const SdrHint*>(&rHint); |
271 | 163k | switch( pSdrHint->GetKind() ) |
272 | 163k | { |
273 | 0 | case SdrHintKind::ObjectChange: |
274 | 0 | { |
275 | 0 | mbDataValid = false; // Text has to be get again |
276 | |
|
277 | 0 | if( HasView() ) |
278 | 0 | { |
279 | | // Update maTextOffset, object has changed |
280 | | // Cannot call that here, since TakeTextRect() (called from there) |
281 | | // changes outliner content. |
282 | | // UpdateOutliner(); |
283 | | |
284 | | // Broadcast object changes, as they might change visible attributes |
285 | 0 | SvxViewChangedHint aHint; |
286 | 0 | Broadcast( aHint ); |
287 | 0 | } |
288 | 0 | break; |
289 | 0 | } |
290 | | |
291 | 0 | case SdrHintKind::BeginEdit: |
292 | 0 | if( mpObject == pSdrHint->GetObject() ) |
293 | 0 | { |
294 | | // Once SdrHintKind::BeginEdit is broadcast, each EditSource of |
295 | | // AccessibleCell will handle it here and call below: |
296 | | // mpView->GetTextEditOutliner()->SetNotifyHdl(), which |
297 | | // will replace the Notifier for current editable cell. It |
298 | | // is totally wrong. So add check here to avoid the |
299 | | // incorrect replacement of notifier. |
300 | | |
301 | | // Currently it only happens on the editsource of |
302 | | // AccessibleCell |
303 | 0 | if (mpObject && mpText) |
304 | 0 | { |
305 | 0 | sdr::table::SdrTableObj* pTableObj = dynamic_cast< sdr::table::SdrTableObj* >( mpObject ); |
306 | 0 | if(pTableObj) |
307 | 0 | { |
308 | 0 | const sdr::table::CellRef& xCell = pTableObj->getActiveCell(); |
309 | 0 | if (xCell.is()) |
310 | 0 | { |
311 | 0 | sdr::table::Cell* pCellObj = dynamic_cast< sdr::table::Cell* >( mpText ); |
312 | 0 | if (pCellObj && xCell.get() != pCellObj) |
313 | 0 | break; |
314 | 0 | } |
315 | 0 | } |
316 | 0 | } |
317 | | // invalidate old forwarder |
318 | 0 | if( !mbForwarderIsEditMode ) |
319 | 0 | { |
320 | 0 | mpTextForwarder.reset(); |
321 | 0 | } |
322 | | |
323 | | // register as listener - need to broadcast state change messages |
324 | 0 | if( mpView && mpView->GetTextEditOutliner() ) |
325 | 0 | { |
326 | 0 | mpView->GetTextEditOutliner()->SetNotifyHdl( LINK(this, SvxTextEditSourceImpl, NotifyHdl) ); |
327 | 0 | mbNotifyEditOutlinerSet = true; |
328 | 0 | } |
329 | | |
330 | | // Only now we're really in edit mode |
331 | 0 | mbShapeIsEditMode = true; |
332 | |
|
333 | 0 | Broadcast( *pSdrHint ); |
334 | 0 | } |
335 | 0 | break; |
336 | | |
337 | 0 | case SdrHintKind::EndEdit: |
338 | 0 | if( mpObject == pSdrHint->GetObject() ) |
339 | 0 | { |
340 | 0 | Broadcast( *pSdrHint ); |
341 | | |
342 | | // We're no longer in edit mode |
343 | 0 | mbShapeIsEditMode = false; |
344 | | |
345 | | // remove as listener - outliner might outlive ourselves |
346 | 0 | if( mpView && mpView->GetTextEditOutliner() ) |
347 | 0 | { |
348 | 0 | mpView->GetTextEditOutliner()->SetNotifyHdl( Link<EENotify&,void>() ); |
349 | 0 | mbNotifyEditOutlinerSet = false; |
350 | 0 | } |
351 | | |
352 | | // destroy view forwarder, OutlinerView no longer |
353 | | // valid (no need for UpdateData(), it's been |
354 | | // synched on SdrEndTextEdit) |
355 | 0 | mpViewForwarder.reset(); |
356 | | |
357 | | // Invalidate text forwarder, we might |
358 | | // not be called again before entering edit mode a |
359 | | // second time! Then, the old outliner might be |
360 | | // invalid. |
361 | 0 | if( mbForwarderIsEditMode ) |
362 | 0 | { |
363 | 0 | mbForwarderIsEditMode = false; |
364 | 0 | mpTextForwarder.reset(); |
365 | 0 | } |
366 | 0 | } |
367 | 0 | break; |
368 | | |
369 | 163k | default: |
370 | 163k | break; |
371 | 163k | } |
372 | 163k | } |
373 | 0 | else if (rHint.GetId() == SfxHintId::SvxViewChanged) |
374 | 0 | { |
375 | 0 | const SvxViewChangedHint* pViewHint = static_cast<const SvxViewChangedHint*>(&rHint); |
376 | 0 | Broadcast( *pViewHint ); |
377 | 0 | } |
378 | 167k | } |
379 | | |
380 | | /* this is a callback from the attached SdrObject when it is actually deleted */ |
381 | | void SvxTextEditSourceImpl::ObjectInDestruction(const SdrObject&) |
382 | 3.78k | { |
383 | 3.78k | mpObject = nullptr; |
384 | 3.78k | dispose(); |
385 | 3.78k | Broadcast( SfxHint( SfxHintId::Dying ) ); |
386 | 3.78k | } |
387 | | |
388 | | /* unregister at all objects and set all references to 0 */ |
389 | | void SvxTextEditSourceImpl::dispose() |
390 | 530k | { |
391 | 530k | mpTextForwarder.reset(); |
392 | 530k | mpViewForwarder.reset(); |
393 | | |
394 | 530k | if( mpOutliner ) |
395 | 91.9k | { |
396 | 91.9k | if( mpModel ) |
397 | 91.9k | { |
398 | 91.9k | mpModel->disposeOutliner( std::move(mpOutliner) ); |
399 | 91.9k | } |
400 | 0 | else |
401 | 0 | { |
402 | 0 | mpOutliner.reset(); |
403 | 0 | } |
404 | 91.9k | } |
405 | | |
406 | 530k | if( mpModel ) |
407 | 526k | mpModel = nullptr; |
408 | | |
409 | 530k | if( mpView ) |
410 | 0 | { |
411 | | // remove as listener - outliner might outlive ourselves |
412 | 0 | if (mbNotifyEditOutlinerSet && mpView->GetTextEditOutliner()) |
413 | 0 | { |
414 | 0 | mpView->GetTextEditOutliner()->SetNotifyHdl(Link<EENotify&,void>()); |
415 | 0 | mbNotifyEditOutlinerSet = false; |
416 | 0 | } |
417 | 0 | EndListening( *mpView ); |
418 | 0 | mpView = nullptr; |
419 | 0 | } |
420 | | |
421 | 530k | if( mpObject ) |
422 | 522k | { |
423 | 522k | mpObject->RemoveListener( *this ); |
424 | 522k | mpObject->RemoveObjectUser( *this ); |
425 | 522k | mpObject = nullptr; |
426 | 522k | } |
427 | 530k | mpWindow = nullptr; |
428 | 530k | } |
429 | | |
430 | | |
431 | | void SvxTextEditSourceImpl::SetupOutliner() |
432 | 0 | { |
433 | | // only for UAA edit source: setup outliner equivalently as in |
434 | | // SdrTextObj::Paint(), such that formatting equals screen |
435 | | // layout |
436 | 0 | if( !(mpObject && mpOutliner) ) |
437 | 0 | return; |
438 | | |
439 | 0 | SdrTextObj* pTextObj = DynCastSdrTextObj( mpObject ); |
440 | 0 | if( pTextObj ) |
441 | 0 | { |
442 | 0 | tools::Rectangle aPaintRect; |
443 | 0 | tools::Rectangle aBoundRect( pTextObj->GetCurrentBoundRect() ); |
444 | 0 | pTextObj->SetupOutlinerFormatting( *mpOutliner, aPaintRect ); |
445 | | |
446 | | // calc text offset from shape anchor |
447 | 0 | maTextOffset = aPaintRect.TopLeft() - aBoundRect.TopLeft(); |
448 | 0 | } |
449 | 0 | } |
450 | | |
451 | | |
452 | | void SvxTextEditSourceImpl::UpdateOutliner() |
453 | 0 | { |
454 | | // only for UAA edit source: update outliner equivalently as in |
455 | | // SdrTextObj::Paint(), such that formatting equals screen |
456 | | // layout |
457 | 0 | if( !(mpObject && mpOutliner) ) |
458 | 0 | return; |
459 | | |
460 | 0 | SdrTextObj* pTextObj = DynCastSdrTextObj( mpObject ); |
461 | 0 | if( pTextObj ) |
462 | 0 | { |
463 | 0 | tools::Rectangle aPaintRect; |
464 | 0 | tools::Rectangle aBoundRect( pTextObj->GetCurrentBoundRect() ); |
465 | 0 | pTextObj->UpdateOutlinerFormatting( *mpOutliner, aPaintRect ); |
466 | | |
467 | | // calc text offset from shape anchor |
468 | 0 | maTextOffset = aPaintRect.TopLeft() - aBoundRect.TopLeft(); |
469 | 0 | } |
470 | 0 | } |
471 | | |
472 | | |
473 | | SvxTextForwarder* SvxTextEditSourceImpl::GetBackgroundTextForwarder() |
474 | 11.0M | { |
475 | 11.0M | bool bCreated = false; |
476 | | |
477 | | // prevent EE/Outliner notifications during setup |
478 | 11.0M | mbNotificationsDisabled = true; |
479 | | |
480 | 11.0M | if (!mpTextForwarder) |
481 | 91.9k | { |
482 | 91.9k | if( mpOutliner == nullptr ) |
483 | 91.9k | { |
484 | 91.9k | SdrTextObj* pTextObj = DynCastSdrTextObj( mpObject ); |
485 | 91.9k | OutlinerMode nOutlMode = OutlinerMode::TextObject; |
486 | 91.9k | if( pTextObj && pTextObj->IsTextFrame() && pTextObj->GetTextKind() == SdrObjKind::OutlineText ) |
487 | 14.1k | nOutlMode = OutlinerMode::OutlineObject; |
488 | | |
489 | 91.9k | mpOutliner = mpModel->createOutliner( nOutlMode ); |
490 | | |
491 | | // Do the setup after outliner creation, would be useless otherwise |
492 | 91.9k | if( HasView() ) |
493 | 0 | { |
494 | | // Setup outliner _before_ filling it |
495 | 0 | SetupOutliner(); |
496 | 0 | } |
497 | | |
498 | 91.9k | mpOutliner->SetTextObjNoInit( pTextObj ); |
499 | 91.9k | if( mbIsLocked ) |
500 | 84.7k | { |
501 | 84.7k | const_cast<EditEngine*>(&(mpOutliner->GetEditEngine()))->SetUpdateLayout( false ); |
502 | 84.7k | mbOldUndoMode = mpOutliner->GetEditEngine().IsUndoEnabled(); |
503 | 84.7k | const_cast<EditEngine*>(&(mpOutliner->GetEditEngine()))->EnableUndo( false ); |
504 | 84.7k | } |
505 | | |
506 | 91.9k | if (!comphelper::IsFuzzing()) |
507 | 0 | { |
508 | 0 | if ( !m_xLinguServiceManager.is() ) |
509 | 0 | { |
510 | 0 | const css::uno::Reference< css::uno::XComponentContext >& xContext( ::comphelper::getProcessComponentContext() ); |
511 | 0 | m_xLinguServiceManager.set(css::linguistic2::LinguServiceManager::create(xContext)); |
512 | 0 | } |
513 | |
|
514 | 0 | css::uno::Reference< css::linguistic2::XHyphenator > xHyphenator = m_xLinguServiceManager->getHyphenator(); |
515 | 0 | if( xHyphenator.is() ) |
516 | 0 | mpOutliner->SetHyphenator( xHyphenator ); |
517 | 0 | } |
518 | 91.9k | } |
519 | | |
520 | | |
521 | 91.9k | mpTextForwarder.reset(new SvxOutlinerForwarder( *mpOutliner, (mpObject->GetObjInventor() == SdrInventor::Default) && (mpObject->GetObjIdentifier() == SdrObjKind::OutlineText) )); |
522 | | // delay listener subscription and UAA initialization until Outliner is fully setup |
523 | 91.9k | bCreated = true; |
524 | | |
525 | 91.9k | mbForwarderIsEditMode = false; |
526 | 91.9k | mbDataValid = false; |
527 | 91.9k | } |
528 | | |
529 | 11.0M | if( mpObject && mpText && !mbDataValid && mpObject->IsInserted() && mpObject->getSdrPageFromSdrObject() ) |
530 | 91.2k | { |
531 | 91.2k | mpTextForwarder->flushCache(); |
532 | | |
533 | 91.2k | std::optional<OutlinerParaObject> pOutlinerParaObject; |
534 | 91.2k | SdrTextObj* pTextObj = DynCastSdrTextObj( mpObject ); |
535 | 91.2k | if( pTextObj && pTextObj->getActiveText() == mpText ) |
536 | 87.5k | pOutlinerParaObject = pTextObj->CreateEditOutlinerParaObject(); // Get the OutlinerParaObject if text edit is active |
537 | 91.2k | bool bTextEditActive(false); |
538 | | |
539 | 91.2k | if( pOutlinerParaObject ) |
540 | 0 | bTextEditActive = true; // text edit active |
541 | 91.2k | else if (mpText->GetOutlinerParaObject()) |
542 | 46.5k | pOutlinerParaObject = *mpText->GetOutlinerParaObject(); |
543 | | |
544 | 91.2k | if( pOutlinerParaObject && ( bTextEditActive || !mpObject->IsEmptyPresObj() || mpObject->getSdrPageFromSdrObject()->IsMasterPage() ) ) |
545 | 45.9k | { |
546 | 45.9k | mpOutliner->SetText( *pOutlinerParaObject ); |
547 | | |
548 | | // put text to object and set EmptyPresObj to FALSE |
549 | 45.9k | if (mpText && bTextEditActive && mpObject->IsEmptyPresObj() && pTextObj && pTextObj->IsReallyEdited()) |
550 | 0 | { |
551 | 0 | mpObject->SetEmptyPresObj( false ); |
552 | 0 | static_cast<SdrTextObj*>(mpObject)->NbcSetOutlinerParaObjectForText(std::move(pOutlinerParaObject), mpText); |
553 | 0 | } |
554 | 45.9k | } |
555 | 45.2k | else |
556 | 45.2k | { |
557 | 45.2k | bool bVertical = pOutlinerParaObject && pOutlinerParaObject->IsEffectivelyVertical(); |
558 | | |
559 | | // set objects style sheet on empty outliner |
560 | 45.2k | SfxStyleSheetPool* pPool = static_cast<SfxStyleSheetPool*>(mpObject->getSdrModelFromSdrObject().GetStyleSheetPool()); |
561 | 45.2k | if( pPool ) |
562 | 38.0k | mpOutliner->SetStyleSheetPool( pPool ); |
563 | | |
564 | 45.2k | SfxStyleSheet* pStyleSheet = mpObject->getSdrPageFromSdrObject()->GetTextStyleSheetForObject( mpObject ); |
565 | 45.2k | if( pStyleSheet ) |
566 | 38.0k | mpOutliner->SetStyleSheet( 0, pStyleSheet ); |
567 | | |
568 | 45.2k | if( bVertical ) |
569 | 0 | { |
570 | 0 | mpOutliner->SetVertical( pOutlinerParaObject->GetVertical()); |
571 | 0 | mpOutliner->SetRotation( pOutlinerParaObject->GetRotation()); |
572 | 0 | } |
573 | 45.2k | } |
574 | | |
575 | | // maybe we have to set the border attributes |
576 | 91.2k | if (mpOutliner->GetParagraphCount()==1) |
577 | 77.1k | { |
578 | | // if we only have one paragraph we check if it is empty |
579 | 77.1k | OUString aStr(mpOutliner->GetText(mpOutliner->GetParagraph(0))); |
580 | | |
581 | 77.1k | if (aStr.isEmpty()) |
582 | 46.8k | { |
583 | | // its empty, so we have to force the outliner to initialise itself |
584 | 46.8k | mpOutliner->SetText( u""_ustr, mpOutliner->GetParagraph( 0 ) ); |
585 | | |
586 | 46.8k | auto pCell = dynamic_cast<sdr::table::Cell*>(mpText); |
587 | 46.8k | if (pCell && pCell->GetStyleSheet()) |
588 | 3 | mpOutliner->SetStyleSheet( 0, pCell->GetStyleSheet()); |
589 | 46.8k | else if (mpObject->GetStyleSheet()) |
590 | 38.3k | mpOutliner->SetStyleSheet( 0, mpObject->GetStyleSheet()); |
591 | 46.8k | } |
592 | 77.1k | } |
593 | | |
594 | 91.2k | mbDataValid = true; |
595 | 91.2k | } |
596 | | |
597 | 11.0M | if( bCreated && mpOutliner && HasView() ) |
598 | 0 | { |
599 | | // register as listener - need to broadcast state change messages |
600 | | // registration delayed until outliner is completely set up |
601 | 0 | mpOutliner->SetNotifyHdl( LINK(this, SvxTextEditSourceImpl, NotifyHdl) ); |
602 | 0 | } |
603 | | |
604 | | // prevent EE/Outliner notifications during setup |
605 | 11.0M | mbNotificationsDisabled = false; |
606 | | |
607 | 11.0M | return mpTextForwarder.get(); |
608 | 11.0M | } |
609 | | |
610 | | |
611 | | SvxTextForwarder* SvxTextEditSourceImpl::GetEditModeTextForwarder() |
612 | 0 | { |
613 | 0 | if( !mpTextForwarder && HasView() ) |
614 | 0 | { |
615 | 0 | SdrOutliner* pEditOutliner = mpView->GetTextEditOutliner(); |
616 | |
|
617 | 0 | if( pEditOutliner ) |
618 | 0 | { |
619 | 0 | mpTextForwarder.reset(new SvxOutlinerForwarder( *pEditOutliner, (mpObject->GetObjInventor() == SdrInventor::Default) && (mpObject->GetObjIdentifier() == SdrObjKind::OutlineText) )); |
620 | 0 | mbForwarderIsEditMode = true; |
621 | 0 | } |
622 | 0 | } |
623 | |
|
624 | 0 | return mpTextForwarder.get(); |
625 | 0 | } |
626 | | |
627 | | |
628 | | SvxTextForwarder* SvxTextEditSourceImpl::GetTextForwarder() |
629 | 11.0M | { |
630 | 11.0M | if( mpObject == nullptr ) |
631 | 0 | return nullptr; |
632 | | |
633 | 11.0M | if( mpModel == nullptr ) |
634 | 0 | mpModel = &mpObject->getSdrModelFromSdrObject(); |
635 | | |
636 | | // distinguish the cases |
637 | | // a) connected to view, maybe edit mode is active, can work directly on the EditOutliner |
638 | | // b) background Outliner, reflect changes into ParaOutlinerObject (this is exactly the old UNO code) |
639 | | |
640 | | // IASS: testing for HasView() is *not* sufficient - there may be more views of one document |
641 | | // open and TextEdit is only active in one of them, or - as with IASS - it may even be the view |
642 | | // of the running SlideShow itself which also will have no active TextEdit and thus no Outliner. |
643 | | // Thus, to identify the view which indeed does have an outliner (and is in TextEdit mode), |
644 | | // also check if it has an active Outliner by using GetTextEditOutliner() |
645 | 11.0M | if( HasView() && nullptr != mpView->GetTextEditOutliner() ) |
646 | 0 | { |
647 | 0 | if( IsEditMode() != mbForwarderIsEditMode ) |
648 | 0 | { |
649 | | // forwarder mismatch - create new |
650 | 0 | mpTextForwarder.reset(); |
651 | 0 | } |
652 | |
|
653 | 0 | if( IsEditMode() ) |
654 | 0 | return GetEditModeTextForwarder(); |
655 | 0 | else |
656 | 0 | return GetBackgroundTextForwarder(); |
657 | 0 | } |
658 | 11.0M | else |
659 | 11.0M | { |
660 | | // tdf#123470 if the text edit mode of the shape is active, then we |
661 | | // cannot trust a previously cached TextForwarder state as the text may |
662 | | // be out of date, so force a refetch in that case, unless locked against |
663 | | // changes |
664 | 11.0M | if (IsEditMode() && mpTextForwarder && !mbIsLocked) |
665 | 0 | { |
666 | 0 | assert(!mbForwarderIsEditMode); // because without a view there is no other option except !mbForwarderIsEditMode |
667 | 0 | bool bTextEditActive = false; |
668 | 0 | SdrTextObj* pTextObj = DynCastSdrTextObj(mpObject); |
669 | | // similar to the GetBackgroundTextForwarder check, see if the text edit is active |
670 | 0 | if (pTextObj && pTextObj->getActiveText() == mpText && pTextObj->CanCreateEditOutlinerParaObject()) |
671 | 0 | bTextEditActive = true; // text edit active |
672 | 0 | if (bTextEditActive) |
673 | 0 | mbDataValid = false; |
674 | 0 | } |
675 | | |
676 | 11.0M | return GetBackgroundTextForwarder(); |
677 | 11.0M | } |
678 | 11.0M | } |
679 | | |
680 | | std::unique_ptr<SvxDrawOutlinerViewForwarder> SvxTextEditSourceImpl::CreateViewForwarder() |
681 | 0 | { |
682 | 0 | if( mpView->GetTextEditOutlinerView() && mpObject ) |
683 | 0 | { |
684 | | // register as listener - need to broadcast state change messages |
685 | 0 | mpView->GetTextEditOutliner()->SetNotifyHdl( LINK(this, SvxTextEditSourceImpl, NotifyHdl) ); |
686 | 0 | mbNotifyEditOutlinerSet = true; |
687 | |
|
688 | 0 | SdrTextObj* pTextObj = DynCastSdrTextObj( mpObject ); |
689 | 0 | if( pTextObj ) |
690 | 0 | { |
691 | 0 | tools::Rectangle aBoundRect( pTextObj->GetCurrentBoundRect() ); |
692 | 0 | OutlinerView& rOutlView = *mpView->GetTextEditOutlinerView(); |
693 | |
|
694 | 0 | return std::unique_ptr<SvxDrawOutlinerViewForwarder>(new SvxDrawOutlinerViewForwarder( rOutlView, aBoundRect.TopLeft() )); |
695 | 0 | } |
696 | 0 | } |
697 | | |
698 | 0 | return nullptr; |
699 | 0 | } |
700 | | |
701 | | SvxEditViewForwarder* SvxTextEditSourceImpl::GetEditViewForwarder( bool bCreate ) |
702 | 0 | { |
703 | 0 | if( mpObject == nullptr ) |
704 | 0 | return nullptr; |
705 | | |
706 | 0 | if( mpModel == nullptr ) |
707 | 0 | mpModel = &mpObject->getSdrModelFromSdrObject(); |
708 | | |
709 | | // shall we delete? |
710 | 0 | if( mpViewForwarder ) |
711 | 0 | { |
712 | 0 | if( !IsEditMode() ) |
713 | 0 | { |
714 | | // destroy all forwarders (no need for UpdateData(), |
715 | | // it's been synched on SdrEndTextEdit) |
716 | 0 | mpViewForwarder.reset(); |
717 | 0 | } |
718 | 0 | } |
719 | | // which to create? Directly in edit mode, create new, or none? |
720 | 0 | else if( mpView ) |
721 | 0 | { |
722 | 0 | if( IsEditMode() ) |
723 | 0 | { |
724 | | // create new view forwarder |
725 | 0 | mpViewForwarder = CreateViewForwarder(); |
726 | 0 | } |
727 | 0 | else if( bCreate ) |
728 | 0 | { |
729 | | // dispose old text forwarder |
730 | 0 | UpdateData(); |
731 | |
|
732 | 0 | mpTextForwarder.reset(); |
733 | | |
734 | | // enter edit mode |
735 | 0 | mpView->SdrEndTextEdit(); |
736 | |
|
737 | 0 | if(mpView->SdrBeginTextEdit(mpObject)) |
738 | 0 | { |
739 | 0 | SdrTextObj* pTextObj = DynCastSdrTextObj( mpObject ); |
740 | 0 | if (pTextObj && pTextObj->IsTextEditActive()) |
741 | 0 | { |
742 | | // create new view forwarder |
743 | 0 | mpViewForwarder = CreateViewForwarder(); |
744 | 0 | } |
745 | 0 | else |
746 | 0 | { |
747 | | // failure. Somehow, SdrBeginTextEdit did not set |
748 | | // our SdrTextObj into edit mode |
749 | 0 | mpView->SdrEndTextEdit(); |
750 | 0 | } |
751 | 0 | } |
752 | 0 | } |
753 | 0 | } |
754 | |
|
755 | 0 | return mpViewForwarder.get(); |
756 | 0 | } |
757 | | |
758 | | |
759 | | void SvxTextEditSourceImpl::UpdateData() |
760 | 1.56M | { |
761 | | // if we have a view and in edit mode, we're working with the |
762 | | // DrawOutliner. Thus, all changes made on the text forwarder are |
763 | | // reflected on the view and committed to the model on |
764 | | // SdrEndTextEdit(). Thus, no need for explicit updates here. |
765 | 1.56M | if( HasView() && IsEditMode() ) |
766 | 0 | return; |
767 | | |
768 | 1.56M | if( mbIsLocked ) |
769 | 1.34M | { |
770 | 1.34M | mbNeedsUpdate = true; |
771 | 1.34M | } |
772 | 223k | else |
773 | 223k | { |
774 | 223k | if( mpOutliner && mpObject && mpText ) |
775 | 223k | { |
776 | 223k | SdrTextObj* pTextObj = DynCastSdrTextObj( mpObject ); |
777 | 223k | if( pTextObj ) |
778 | 223k | { |
779 | 223k | if( (mpOutliner->GetParagraphCount() == 1 && mpOutliner->GetEditEngine().GetTextLen( 0 ) == 0 ) |
780 | 223k | || (mpOutliner->GetParagraphCount() == 2 && mpOutliner->GetEditEngine().GetTextLen( 0 ) == 0 |
781 | 169k | && mpOutliner->GetEditEngine().GetTextLen( 1 ) == 0) ) |
782 | 59.6k | { |
783 | 59.6k | pTextObj->NbcSetOutlinerParaObjectForText( std::nullopt, mpText ); |
784 | 59.6k | } |
785 | 163k | else |
786 | 163k | { |
787 | 163k | pTextObj->NbcSetOutlinerParaObjectForText( mpOutliner->CreateParaObject(), mpText ); |
788 | 163k | } |
789 | 223k | } |
790 | | |
791 | 223k | if( mpObject->IsEmptyPresObj() ) |
792 | 23.4k | mpObject->SetEmptyPresObj(false); |
793 | 223k | } |
794 | 223k | } |
795 | 1.56M | } |
796 | | |
797 | | void SvxTextEditSourceImpl::lock() |
798 | 125k | { |
799 | | // if this assert ever fires, we will need to make this a counter instead of a boolean |
800 | 125k | assert(!mbIsLocked && "cannot nest these loc() calls"); |
801 | 125k | mbIsLocked = true; |
802 | 125k | if( mpOutliner ) |
803 | 11.4k | { |
804 | 11.4k | const_cast<EditEngine*>(&(mpOutliner->GetEditEngine()))->SetUpdateLayout( false ); |
805 | 11.4k | mbOldUndoMode = mpOutliner->GetEditEngine().IsUndoEnabled(); |
806 | 11.4k | const_cast<EditEngine*>(&(mpOutliner->GetEditEngine()))->EnableUndo( false ); |
807 | 11.4k | } |
808 | 125k | } |
809 | | |
810 | | void SvxTextEditSourceImpl::unlock() |
811 | 137k | { |
812 | 137k | mbIsLocked = false; |
813 | | |
814 | 137k | if( mbNeedsUpdate ) |
815 | 94.2k | { |
816 | 94.2k | UpdateData(); |
817 | 94.2k | mbNeedsUpdate = false; |
818 | 94.2k | } |
819 | | |
820 | 137k | if( mpOutliner ) |
821 | 94.2k | { |
822 | 94.2k | const_cast<EditEngine*>(&(mpOutliner->GetEditEngine()))->SetUpdateLayout( true ); |
823 | 94.2k | const_cast<EditEngine*>(&(mpOutliner->GetEditEngine()))->EnableUndo( mbOldUndoMode ); |
824 | 94.2k | } |
825 | 137k | } |
826 | | |
827 | | bool SvxTextEditSourceImpl::IsValid() const |
828 | 0 | { |
829 | 0 | return mpView && mpWindow; |
830 | 0 | } |
831 | | |
832 | | Point SvxTextEditSourceImpl::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) |
833 | 0 | { |
834 | | // The responsibilities of ViewForwarder happen to be |
835 | | // somewhat mixed in this case. On the one hand, we need the |
836 | | // different interface queries on the SvxEditSource interface, |
837 | | // since we need both VisAreas. On the other hand, if an |
838 | | // EditViewForwarder exists, maTextOffset does not remain static, |
839 | | // but may change with every key press. |
840 | 0 | if( IsEditMode() ) |
841 | 0 | { |
842 | 0 | SvxEditViewForwarder* pForwarder = GetEditViewForwarder(false); |
843 | |
|
844 | 0 | if( pForwarder ) |
845 | 0 | return pForwarder->LogicToPixel( rPoint, rMapMode ); |
846 | 0 | } |
847 | 0 | else if( IsValid() && mpModel ) |
848 | 0 | { |
849 | 0 | Point aPoint1( rPoint ); |
850 | 0 | aPoint1.AdjustX(maTextOffset.X() ); |
851 | 0 | aPoint1.AdjustY(maTextOffset.Y() ); |
852 | |
|
853 | 0 | Point aPoint2( OutputDevice::LogicToLogic( aPoint1, rMapMode, |
854 | 0 | MapMode(mpModel->GetScaleUnit()) ) ); |
855 | 0 | MapMode aMapMode(mpWindow->GetMapMode()); |
856 | 0 | aMapMode.SetOrigin(Point()); |
857 | 0 | return mpWindow->LogicToPixel( aPoint2, aMapMode ); |
858 | 0 | } |
859 | | |
860 | 0 | return Point(); |
861 | 0 | } |
862 | | |
863 | | Point SvxTextEditSourceImpl::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) |
864 | 0 | { |
865 | | // The responsibilities of ViewForwarder happen to be |
866 | | // somewhat mixed in this case. On the one hand, we need the |
867 | | // different interface queries on the SvxEditSource interface, |
868 | | // since we need both VisAreas. On the other hand, if an |
869 | | // EditViewForwarder exists, maTextOffset does not remain static, |
870 | | // but may change with every key press. |
871 | 0 | if( IsEditMode() ) |
872 | 0 | { |
873 | 0 | SvxEditViewForwarder* pForwarder = GetEditViewForwarder(false); |
874 | |
|
875 | 0 | if( pForwarder ) |
876 | 0 | return pForwarder->PixelToLogic( rPoint, rMapMode ); |
877 | 0 | } |
878 | 0 | else if( IsValid() && mpModel ) |
879 | 0 | { |
880 | 0 | MapMode aMapMode(mpWindow->GetMapMode()); |
881 | 0 | aMapMode.SetOrigin(Point()); |
882 | 0 | Point aPoint1( mpWindow->PixelToLogic( rPoint, aMapMode ) ); |
883 | 0 | Point aPoint2( OutputDevice::LogicToLogic( aPoint1, |
884 | 0 | MapMode(mpModel->GetScaleUnit()), |
885 | 0 | rMapMode ) ); |
886 | 0 | aPoint2.AdjustX( -(maTextOffset.X()) ); |
887 | 0 | aPoint2.AdjustY( -(maTextOffset.Y()) ); |
888 | |
|
889 | 0 | return aPoint2; |
890 | 0 | } |
891 | | |
892 | 0 | return Point(); |
893 | 0 | } |
894 | | |
895 | | IMPL_LINK(SvxTextEditSourceImpl, NotifyHdl, EENotify&, rNotify, void) |
896 | 0 | { |
897 | 0 | if( !mbNotificationsDisabled ) |
898 | 0 | { |
899 | 0 | std::unique_ptr< SfxHint > aHint( SvxEditSourceHelper::EENotification2Hint( &rNotify) ); |
900 | |
|
901 | 0 | if (aHint) |
902 | 0 | Broadcast(*aHint); |
903 | 0 | } |
904 | 0 | } |
905 | | |
906 | | SvxTextEditSource::SvxTextEditSource( SdrObject* pObject, SdrText* pText ) |
907 | 526k | { |
908 | 526k | mpImpl = new SvxTextEditSourceImpl( pObject, pText ); |
909 | 526k | } |
910 | | |
911 | | |
912 | | SvxTextEditSource::SvxTextEditSource( SdrObject& rObj, SdrText* pText, SdrView& rView, const OutputDevice& rWindow ) |
913 | 0 | { |
914 | 0 | mpImpl = new SvxTextEditSourceImpl( rObj, pText, rView, rWindow ); |
915 | 0 | } |
916 | | |
917 | | |
918 | | SvxTextEditSource::SvxTextEditSource( SvxTextEditSourceImpl* pImpl ) |
919 | 434k | { |
920 | 434k | mpImpl = pImpl; |
921 | 434k | } |
922 | | |
923 | | |
924 | | SvxTextEditSource::~SvxTextEditSource() |
925 | 961k | { |
926 | 961k | ::SolarMutexGuard aGuard; |
927 | 961k | mpImpl.clear(); |
928 | 961k | } |
929 | | |
930 | | |
931 | | std::unique_ptr<SvxEditSource> SvxTextEditSource::Clone() const |
932 | 434k | { |
933 | 434k | return std::unique_ptr<SvxEditSource>(new SvxTextEditSource( mpImpl.get() )); |
934 | 434k | } |
935 | | |
936 | | |
937 | | SvxTextForwarder* SvxTextEditSource::GetTextForwarder() |
938 | 11.0M | { |
939 | 11.0M | return mpImpl->GetTextForwarder(); |
940 | 11.0M | } |
941 | | |
942 | | |
943 | | SvxEditViewForwarder* SvxTextEditSource::GetEditViewForwarder( bool bCreate ) |
944 | 0 | { |
945 | 0 | return mpImpl->GetEditViewForwarder( bCreate ); |
946 | 0 | } |
947 | | |
948 | | |
949 | | SvxViewForwarder* SvxTextEditSource::GetViewForwarder() |
950 | 0 | { |
951 | 0 | return this; |
952 | 0 | } |
953 | | |
954 | | |
955 | | void SvxTextEditSource::UpdateData() |
956 | 1.47M | { |
957 | 1.47M | mpImpl->UpdateData(); |
958 | 1.47M | } |
959 | | |
960 | | SfxBroadcaster& SvxTextEditSource::GetBroadcaster() const |
961 | 0 | { |
962 | 0 | return *mpImpl; |
963 | 0 | } |
964 | | |
965 | | void SvxTextEditSource::lock() |
966 | 125k | { |
967 | 125k | mpImpl->lock(); |
968 | 125k | } |
969 | | |
970 | | void SvxTextEditSource::unlock() |
971 | 137k | { |
972 | 137k | mpImpl->unlock(); |
973 | 137k | } |
974 | | |
975 | | bool SvxTextEditSource::IsValid() const |
976 | 0 | { |
977 | 0 | return mpImpl->IsValid(); |
978 | 0 | } |
979 | | |
980 | | Point SvxTextEditSource::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const |
981 | 0 | { |
982 | 0 | return mpImpl->LogicToPixel( rPoint, rMapMode ); |
983 | 0 | } |
984 | | |
985 | | Point SvxTextEditSource::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const |
986 | 0 | { |
987 | 0 | return mpImpl->PixelToLogic( rPoint, rMapMode ); |
988 | 0 | } |
989 | | |
990 | | void SvxTextEditSource::addRange( SvxUnoTextRangeBase* pNewRange ) |
991 | 961k | { |
992 | 961k | mpImpl->addRange( pNewRange ); |
993 | 961k | } |
994 | | |
995 | | void SvxTextEditSource::removeRange( SvxUnoTextRangeBase* pOldRange ) |
996 | 961k | { |
997 | 961k | mpImpl->removeRange( pOldRange ); |
998 | 961k | } |
999 | | |
1000 | | const SvxUnoTextRangeBaseVec& SvxTextEditSource::getRanges() const |
1001 | 195 | { |
1002 | 195 | return mpImpl->getRanges(); |
1003 | 195 | } |
1004 | | |
1005 | | void SvxTextEditSource::UpdateOutliner() |
1006 | 0 | { |
1007 | 0 | mpImpl->UpdateOutliner(); |
1008 | 0 | } |
1009 | | |
1010 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |