Line data Source code
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 "richtextcontrol.hxx"
21 : #include "frm_module.hxx"
22 : #include "property.hrc"
23 : #include "services.hxx"
24 :
25 : #include "richtextmodel.hxx"
26 : #include "richtextvclcontrol.hxx"
27 : #include "clipboarddispatcher.hxx"
28 : #include "parametrizedattributedispatcher.hxx"
29 : #include "specialdispatchers.hxx"
30 :
31 : #include <com/sun/star/awt/PosSize.hpp>
32 :
33 : #include <toolkit/helper/vclunohelper.hxx>
34 : #include <tools/diagnose_ex.h>
35 : #include <vcl/svapp.hxx>
36 :
37 : #include <svx/svxids.hrc>
38 : #include <editeng/editview.hxx>
39 : #include <svl/itemset.hxx>
40 : #include <svl/itempool.hxx>
41 : #include <sfx2/msgpool.hxx>
42 :
43 :
44 40 : extern "C" void SAL_CALL createRegistryInfo_ORichTextControl()
45 : {
46 40 : static ::frm::OMultiInstanceAutoRegistration< ::frm::ORichTextControl > aAutoRegistration;
47 40 : }
48 :
49 :
50 : namespace frm
51 : {
52 :
53 :
54 : using namespace ::com::sun::star::uno;
55 : using namespace ::com::sun::star::beans;
56 : using namespace ::com::sun::star::awt;
57 : using namespace ::com::sun::star::lang;
58 : using namespace ::com::sun::star::frame;
59 :
60 : #define FORWARD_TO_PEER_1_RET( returnType, unoInterface, method, param1 ) \
61 : returnType aReturn; \
62 : Reference< unoInterface > xTypedPeer( getPeer(), UNO_QUERY ); \
63 : if ( xTypedPeer.is() ) \
64 : { \
65 : aReturn = xTypedPeer->method( param1 ); \
66 : } \
67 : return aReturn;
68 :
69 : #define FORWARD_TO_PEER_3_RET( returnType, unoInterface, method, param1, param2, param3 ) \
70 : returnType aReturn; \
71 : Reference< unoInterface > xTypedPeer( getPeer(), UNO_QUERY ); \
72 : if ( xTypedPeer.is() ) \
73 : { \
74 : aReturn = xTypedPeer->method( param1, param2, param3 ); \
75 : } \
76 : return aReturn;
77 :
78 116 : ORichTextControl::ORichTextControl()
79 116 : :UnoEditControl()
80 : {
81 116 : }
82 :
83 :
84 164 : ORichTextControl::~ORichTextControl()
85 : {
86 164 : }
87 :
88 :
89 0 : IMPLEMENT_FORWARD_XTYPEPROVIDER2( ORichTextControl, UnoEditControl, ORichTextControl_Base )
90 :
91 :
92 2276 : Any SAL_CALL ORichTextControl::queryAggregation( const Type& _rType ) throw ( RuntimeException, std::exception )
93 : {
94 2276 : Any aReturn = UnoEditControl::queryAggregation( _rType );
95 :
96 2276 : if ( !aReturn.hasValue() )
97 230 : aReturn = ORichTextControl_Base::queryInterface( _rType );
98 :
99 2276 : return aReturn;
100 : }
101 :
102 :
103 : namespace
104 : {
105 :
106 40 : static void implAdjustTriStateFlag( const Reference< XPropertySet >& _rxProps, const OUString& _rPropertyName,
107 : WinBits& _rAllBits, WinBits _nPositiveFlag, WinBits nNegativeFlag )
108 : {
109 40 : bool bFlagValue = false;
110 40 : if ( _rxProps->getPropertyValue( _rPropertyName ) >>= bFlagValue )
111 0 : _rAllBits |= ( bFlagValue ? _nPositiveFlag : nNegativeFlag );
112 40 : }
113 :
114 :
115 248 : static void implAdjustTwoStateFlag( const Any& _rValue, WinBits& _rAllBits, WinBits _nFlag, bool _bInvert = false )
116 : {
117 248 : bool bFlagValue = false;
118 248 : if ( _rValue >>= bFlagValue )
119 : {
120 248 : if ( _bInvert )
121 88 : bFlagValue = !bFlagValue;
122 248 : if ( bFlagValue )
123 120 : _rAllBits |= _nFlag;
124 : else
125 128 : _rAllBits &= ~_nFlag;
126 : }
127 248 : }
128 :
129 :
130 120 : static void implAdjustTwoStateFlag( const Reference< XPropertySet >& _rxProps, const OUString& _rPropertyName,
131 : WinBits& _rAllBits, WinBits _nFlag, bool _bInvert = false )
132 : {
133 120 : implAdjustTwoStateFlag( _rxProps->getPropertyValue( _rPropertyName ), _rAllBits, _nFlag, _bInvert );
134 120 : }
135 :
136 :
137 128 : static void adjustTwoStateWinBit( vcl::Window* _pWindow, const Any& _rValue, WinBits _nFlag, bool _bInvert = false )
138 : {
139 128 : WinBits nBits = _pWindow->GetStyle();
140 128 : implAdjustTwoStateFlag( _rValue, nBits, _nFlag, _bInvert );
141 128 : _pWindow->SetStyle( nBits );
142 128 : }
143 :
144 :
145 40 : static WinBits getWinBits( const Reference< XControlModel >& _rxModel, WinBits nBaseBits = 0 )
146 : {
147 40 : WinBits nBits = nBaseBits;
148 : try
149 : {
150 40 : Reference< XPropertySet > xProps( _rxModel, UNO_QUERY );
151 40 : if ( xProps.is() )
152 : {
153 40 : sal_Int16 nBorder = 0;
154 40 : xProps->getPropertyValue( PROPERTY_BORDER ) >>= nBorder;
155 40 : if ( nBorder )
156 40 : nBits |= WB_BORDER;
157 :
158 40 : implAdjustTriStateFlag( xProps, PROPERTY_TABSTOP, nBits, WB_TABSTOP, WB_NOTABSTOP );
159 40 : implAdjustTwoStateFlag( xProps, PROPERTY_HSCROLL, nBits, WB_HSCROLL );
160 40 : implAdjustTwoStateFlag( xProps, PROPERTY_VSCROLL, nBits, WB_VSCROLL );
161 40 : implAdjustTwoStateFlag( xProps, PROPERTY_HARDLINEBREAKS, nBits, WB_WORDBREAK, true );
162 40 : }
163 : }
164 0 : catch( const Exception& )
165 : {
166 : DBG_UNHANDLED_EXCEPTION();
167 : }
168 40 : return nBits;
169 : }
170 : }
171 :
172 :
173 168 : void SAL_CALL ORichTextControl::createPeer( const Reference< XToolkit >& _rToolkit, const Reference< XWindowPeer >& _rParentPeer ) throw( RuntimeException, std::exception )
174 : {
175 168 : bool bReallyActAsRichText = false;
176 : try
177 : {
178 168 : Reference< XPropertySet > xModelProps( getModel(), UNO_QUERY_THROW );
179 168 : xModelProps->getPropertyValue( PROPERTY_RICH_TEXT ) >>= bReallyActAsRichText;
180 : }
181 0 : catch( const Exception& )
182 : {
183 : DBG_UNHANDLED_EXCEPTION();
184 : }
185 :
186 168 : if ( !bReallyActAsRichText )
187 : {
188 128 : UnoEditControl::createPeer( _rToolkit, _rParentPeer );
189 128 : OControl::initFormControlPeer( getPeer() );
190 296 : return;
191 : }
192 :
193 40 : SolarMutexGuard aGuard;
194 :
195 40 : if (!getPeer().is())
196 : {
197 40 : mbCreatingPeer = true;
198 :
199 : // determine the VLC window for the parent
200 40 : vcl::Window* pParentWin = NULL;
201 40 : if ( _rParentPeer.is() )
202 : {
203 40 : VCLXWindow* pParentXWin = VCLXWindow::GetImplementation( _rParentPeer );
204 40 : if ( pParentXWin )
205 40 : pParentWin = pParentXWin->GetWindow();
206 : DBG_ASSERT( pParentWin, "ORichTextControl::createPeer: could not obtain the VCL-level parent window!" );
207 : }
208 :
209 : // create the peer
210 40 : Reference< XControlModel > xModel( getModel() );
211 40 : ORichTextPeer* pPeer = ORichTextPeer::Create( xModel, pParentWin, getWinBits( xModel ) );
212 : DBG_ASSERT( pPeer, "ORichTextControl::createPeer: invalid peer returned!" );
213 40 : if ( pPeer )
214 : {
215 : // by definition, the returned component is acquired once
216 40 : pPeer->release();
217 :
218 : // announce the peer to the base class
219 40 : setPeer( pPeer );
220 :
221 : // initialize ourself (and thus the peer) with the model properties
222 40 : updateFromModel();
223 :
224 40 : Reference< XView > xPeerView( getPeer(), UNO_QUERY );
225 40 : if ( xPeerView.is() )
226 : {
227 40 : xPeerView->setZoom( maComponentInfos.nZoomX, maComponentInfos.nZoomY );
228 40 : xPeerView->setGraphics( mxGraphics );
229 : }
230 :
231 : // a lot of initial settings from our component infos
232 40 : setPosSize( maComponentInfos.nX, maComponentInfos.nY, maComponentInfos.nWidth, maComponentInfos.nHeight, PosSize::POSSIZE );
233 :
234 40 : pPeer->setVisible ( maComponentInfos.bVisible && !mbDesignMode );
235 40 : pPeer->setEnable ( maComponentInfos.bEnable );
236 40 : pPeer->setDesignMode( mbDesignMode );
237 :
238 40 : peerCreated();
239 : }
240 :
241 40 : mbCreatingPeer = false;
242 :
243 40 : OControl::initFormControlPeer( getPeer() );
244 40 : }
245 : }
246 :
247 :
248 0 : OUString SAL_CALL ORichTextControl::getImplementationName() throw( RuntimeException, std::exception )
249 : {
250 0 : return getImplementationName_Static();
251 : }
252 :
253 :
254 0 : Sequence< OUString > SAL_CALL ORichTextControl::getSupportedServiceNames() throw( RuntimeException, std::exception )
255 : {
256 0 : return getSupportedServiceNames_Static();
257 : }
258 :
259 :
260 80 : OUString SAL_CALL ORichTextControl::getImplementationName_Static()
261 : {
262 80 : return OUString( "com.sun.star.comp.form.ORichTextControl" );
263 : }
264 :
265 :
266 40 : Sequence< OUString > SAL_CALL ORichTextControl::getSupportedServiceNames_Static()
267 : {
268 40 : Sequence< OUString > aServices( 3 );
269 40 : aServices[ 0 ] = "com.sun.star.awt.UnoControl";
270 40 : aServices[ 1 ] = "com.sun.star.awt.UnoControlEdit";
271 40 : aServices[ 2 ] = FRM_SUN_CONTROL_RICHTEXTCONTROL;
272 40 : return aServices;
273 : }
274 :
275 :
276 116 : Reference< XInterface > SAL_CALL ORichTextControl::Create( const Reference< XMultiServiceFactory >& )
277 : {
278 116 : return *( new ORichTextControl() );
279 : }
280 :
281 :
282 0 : Reference< XDispatch > SAL_CALL ORichTextControl::queryDispatch( const ::com::sun::star::util::URL& _rURL, const OUString& _rTargetFrameName, sal_Int32 _nSearchFlags ) throw (RuntimeException, std::exception)
283 : {
284 0 : FORWARD_TO_PEER_3_RET( Reference< XDispatch >, XDispatchProvider, queryDispatch, _rURL, _rTargetFrameName, _nSearchFlags );
285 : }
286 :
287 :
288 0 : Sequence< Reference< XDispatch > > SAL_CALL ORichTextControl::queryDispatches( const Sequence< DispatchDescriptor >& _rRequests ) throw (RuntimeException, std::exception)
289 : {
290 0 : FORWARD_TO_PEER_1_RET( Sequence< Reference< XDispatch > >, XDispatchProvider, queryDispatches, _rRequests );
291 : }
292 :
293 :
294 210 : bool ORichTextControl::requiresNewPeer( const OUString& _rPropertyName ) const
295 : {
296 210 : return UnoControl::requiresNewPeer( _rPropertyName ) || _rPropertyName.equals( PROPERTY_RICH_TEXT );
297 : }
298 :
299 :
300 : // ORichTextPeer
301 :
302 :
303 40 : ORichTextPeer* ORichTextPeer::Create( const Reference< XControlModel >& _rxModel, vcl::Window* _pParentWindow, WinBits _nStyle )
304 : {
305 : DBG_TESTSOLARMUTEX();
306 :
307 : // the EditEngine of the model
308 40 : RichTextEngine* pEngine = ORichTextModel::getEditEngine( _rxModel );
309 : OSL_ENSURE( pEngine, "ORichTextPeer::Create: could not obtaine the edit engine from the model!" );
310 40 : if ( !pEngine )
311 0 : return NULL;
312 :
313 : // the peer itself
314 40 : ORichTextPeer* pPeer = new ORichTextPeer;
315 40 : pPeer->acquire(); // by definition, the returned object is acquired once
316 :
317 : // the VCL control for the peer
318 40 : RichTextControl* pRichTextControl = new RichTextControl( pEngine, _pParentWindow, _nStyle, NULL, pPeer );
319 :
320 : // some knittings
321 40 : pRichTextControl->SetComponentInterface( pPeer );
322 :
323 : // outta here
324 40 : return pPeer;
325 : }
326 :
327 :
328 40 : ORichTextPeer::ORichTextPeer()
329 : {
330 40 : }
331 :
332 :
333 80 : ORichTextPeer::~ORichTextPeer()
334 : {
335 80 : }
336 :
337 :
338 80 : void ORichTextPeer::dispose( ) throw(RuntimeException, std::exception)
339 : {
340 : {
341 80 : SolarMutexGuard aGuard;
342 80 : RichTextControl* pRichTextControl = static_cast< RichTextControl* >( GetWindow() );
343 :
344 80 : if ( pRichTextControl )
345 : {
346 120 : for ( AttributeDispatchers::iterator aDisposeLoop = m_aDispatchers.begin();
347 80 : aDisposeLoop != m_aDispatchers.end();
348 : ++aDisposeLoop
349 : )
350 : {
351 0 : pRichTextControl->disableAttributeNotification( aDisposeLoop->first );
352 0 : aDisposeLoop->second->dispose();
353 : }
354 : }
355 :
356 160 : AttributeDispatchers aEmpty;
357 160 : m_aDispatchers.swap( aEmpty );
358 : }
359 :
360 80 : VCLXWindow::dispose();
361 80 : }
362 :
363 :
364 69 : void SAL_CALL ORichTextPeer::draw( sal_Int32 _nX, sal_Int32 _nY ) throw(::com::sun::star::uno::RuntimeException, std::exception)
365 : {
366 69 : SolarMutexGuard aGuard;
367 :
368 69 : RichTextControl* pControl = static_cast< RichTextControl* >( GetWindow() );
369 69 : if ( !pControl )
370 0 : return;
371 :
372 69 : OutputDevice* pTargetDevice = VCLUnoHelper::GetOutputDevice( getGraphics() );
373 : OSL_ENSURE( pTargetDevice != NULL, "ORichTextPeer::draw: no graphics -> no drawing!" );
374 69 : if ( !pTargetDevice )
375 0 : return;
376 :
377 69 : ::Size aSize = pControl->GetSizePixel();
378 69 : const MapUnit eTargetUnit = pTargetDevice->GetMapMode().GetMapUnit();
379 69 : if ( eTargetUnit != MAP_PIXEL )
380 0 : aSize = pTargetDevice->PixelToLogic( aSize );
381 :
382 69 : ::Point aPos( _nX, _nY );
383 : // the XView::draw API talks about pixels, always ...
384 69 : if ( eTargetUnit != MAP_PIXEL )
385 0 : aPos = pTargetDevice->PixelToLogic( aPos );
386 :
387 69 : pControl->Draw( pTargetDevice, aPos, aSize, WINDOW_DRAW_NOCONTROLS );
388 : }
389 :
390 :
391 5378 : void SAL_CALL ORichTextPeer::setProperty( const OUString& _rPropertyName, const Any& _rValue )
392 : throw (RuntimeException,
393 : std::exception)
394 : {
395 5378 : if ( !GetWindow() )
396 : {
397 0 : VCLXWindow::setProperty( _rPropertyName, _rValue );
398 5378 : return;
399 : }
400 :
401 5378 : if ( _rPropertyName.equals( PROPERTY_BACKGROUNDCOLOR ) )
402 : {
403 40 : RichTextControl* pControl = static_cast< RichTextControl* >( GetWindow() );
404 40 : if ( !_rValue.hasValue() )
405 : {
406 40 : pControl->SetBackgroundColor( );
407 : }
408 : else
409 : {
410 0 : sal_Int32 nColor = COL_TRANSPARENT;
411 0 : _rValue >>= nColor;
412 0 : pControl->SetBackgroundColor( Color( nColor ) );
413 : }
414 : }
415 5338 : else if ( _rPropertyName.equals( PROPERTY_HSCROLL ) )
416 : {
417 40 : adjustTwoStateWinBit( GetWindow(), _rValue, WB_HSCROLL );
418 : }
419 5298 : else if ( _rPropertyName.equals( PROPERTY_VSCROLL ) )
420 : {
421 40 : adjustTwoStateWinBit( GetWindow(), _rValue, WB_VSCROLL );
422 : }
423 5258 : else if ( _rPropertyName.equals( PROPERTY_HARDLINEBREAKS ) )
424 : {
425 48 : adjustTwoStateWinBit( GetWindow(), _rValue, WB_WORDBREAK, true );
426 : }
427 5210 : else if ( _rPropertyName.equals( PROPERTY_READONLY ) )
428 : {
429 48 : RichTextControl* pControl = static_cast< RichTextControl* >( GetWindow() );
430 48 : bool bReadOnly( pControl->IsReadOnly() );
431 48 : OSL_VERIFY( _rValue >>= bReadOnly );
432 48 : pControl->SetReadOnly( bReadOnly );
433 :
434 : // update the dispatchers
435 144 : for ( AttributeDispatchers::iterator aDispatcherLoop = m_aDispatchers.begin();
436 96 : aDispatcherLoop != m_aDispatchers.end();
437 : ++aDispatcherLoop
438 : )
439 : {
440 0 : aDispatcherLoop->second->invalidate();
441 : }
442 : }
443 5162 : else if ( _rPropertyName.equals( PROPERTY_HIDEINACTIVESELECTION ) )
444 : {
445 48 : RichTextControl* pRichTextControl = static_cast< RichTextControl* >( GetWindow() );
446 48 : bool bHide = pRichTextControl->GetHideInactiveSelection();
447 48 : OSL_VERIFY( _rValue >>= bHide );
448 48 : pRichTextControl->SetHideInactiveSelection( bHide );
449 : }
450 : else
451 5114 : VCLXWindow::setProperty( _rPropertyName, _rValue );
452 : }
453 :
454 :
455 14683 : IMPLEMENT_FORWARD_XINTERFACE2( ORichTextPeer, VCLXWindow, ORichTextPeer_Base )
456 :
457 :
458 0 : IMPLEMENT_FORWARD_XTYPEPROVIDER2( ORichTextPeer, VCLXWindow, ORichTextPeer_Base )
459 :
460 :
461 : namespace
462 : {
463 0 : static SfxSlotId lcl_translateConflictingSlot( SfxSlotId _nIDFromPool )
464 : {
465 : // HACK HACK HACK
466 : // unfortunately, some of our applications have some conflicting slots,
467 : // i.e. slots which have the same UNO name as an existing other (common)
468 : // slot.
469 : // For instance, both the slots SID_SET_SUPER_SCRIPT (from SVX) and FN_SET_SUPER_SCRIPT
470 : // (from SW) have the UNO name "SuperScript".
471 : // Now, if the controls lives in a text document, and asks the SfxSlotPool for
472 : // the id belonging to "SuperScript", it gets the FN_SET_SUPER_SCRIPT - which
473 : // is completely unknown to the EditEngine.
474 : // So, we need to translate such conflicting ids.
475 :
476 : // Note that the real solution would be to fix the applications to
477 : // *not* define conflicting slots. Alternatively, if SFX would provide a slot pool
478 : // which is *static* (i.e. independent on the active application), then we
479 : // would also never encounter such a conflict.
480 0 : SfxSlotId nReturn( _nIDFromPool );
481 0 : switch ( _nIDFromPool )
482 : {
483 : case 20411: /* FM_SET_SUPER_SCRIPT, originating in SW */
484 0 : nReturn = SID_SET_SUPER_SCRIPT;
485 0 : break;
486 : case 20412: /* FN_SET_SUB_SCRIPT, originating in SW */
487 0 : nReturn = SID_SET_SUB_SCRIPT;
488 0 : break;
489 : }
490 0 : return nReturn;
491 : }
492 : }
493 :
494 :
495 0 : ORichTextPeer::SingleAttributeDispatcher ORichTextPeer::implCreateDispatcher( SfxSlotId _nSlotId, const ::com::sun::star::util::URL& _rURL )
496 : {
497 0 : RichTextControl* pRichTextControl = static_cast< RichTextControl* >( GetWindow() );
498 : OSL_PRECOND( pRichTextControl, "ORichTextPeer::implCreateDispatcher: invalid window!" );
499 0 : if ( !pRichTextControl )
500 0 : return SingleAttributeDispatcher( NULL );
501 :
502 0 : ORichTextFeatureDispatcher* pDispatcher = NULL;
503 0 : OAttributeDispatcher* pAttributeDispatcher = NULL;
504 0 : switch ( _nSlotId )
505 : {
506 : case SID_CUT:
507 0 : pDispatcher = new OClipboardDispatcher( pRichTextControl->getView(), OClipboardDispatcher::eCut );
508 0 : break;
509 :
510 : case SID_COPY:
511 0 : pDispatcher = new OClipboardDispatcher( pRichTextControl->getView(), OClipboardDispatcher::eCopy );
512 0 : break;
513 :
514 : case SID_PASTE:
515 0 : pDispatcher = new OPasteClipboardDispatcher( pRichTextControl->getView() );
516 0 : break;
517 :
518 : case SID_SELECTALL:
519 0 : pDispatcher = new OSelectAllDispatcher( pRichTextControl->getView(), _rURL );
520 0 : break;
521 :
522 : case SID_ATTR_PARA_LEFT_TO_RIGHT:
523 : case SID_ATTR_PARA_RIGHT_TO_LEFT:
524 0 : pAttributeDispatcher = new OParagraphDirectionDispatcher( pRichTextControl->getView(), _nSlotId, _rURL, pRichTextControl );
525 0 : break;
526 :
527 : case SID_TEXTDIRECTION_TOP_TO_BOTTOM:
528 : case SID_TEXTDIRECTION_LEFT_TO_RIGHT:
529 0 : pDispatcher = new OTextDirectionDispatcher( pRichTextControl->getView(), _rURL );
530 0 : break;
531 :
532 : case SID_ATTR_PARA_HANGPUNCTUATION:
533 : case SID_ATTR_PARA_FORBIDDEN_RULES:
534 : case SID_ATTR_PARA_SCRIPTSPACE:
535 0 : pAttributeDispatcher = new OAsianFontLayoutDispatcher( pRichTextControl->getView(), _nSlotId, _rURL, pRichTextControl );
536 0 : break;
537 :
538 : default:
539 : {
540 : // is it a supported slot?
541 0 : bool bSupportedSlot = false;
542 0 : if ( !bSupportedSlot )
543 : {
544 0 : const SfxItemPool& rPool = *pRichTextControl->getView().GetEmptyItemSet().GetPool();
545 0 : bSupportedSlot = rPool.IsInRange( rPool.GetWhich( _nSlotId ) );
546 : }
547 0 : if ( !bSupportedSlot )
548 0 : bSupportedSlot = RichTextControl::isMappableSlot( _nSlotId );
549 :
550 0 : if ( bSupportedSlot )
551 : { // it's really a slot which is supported by the EditEngine
552 :
553 0 : bool bNeedParametrizedDispatcher = true;
554 0 : if ( ( _nSlotId == SID_ATTR_CHAR_POSTURE )
555 0 : || ( _nSlotId == SID_ATTR_CHAR_CJK_POSTURE )
556 0 : || ( _nSlotId == SID_ATTR_CHAR_CTL_POSTURE )
557 0 : || ( _nSlotId == SID_ATTR_CHAR_LATIN_POSTURE )
558 0 : || ( _nSlotId == SID_ATTR_CHAR_WEIGHT )
559 0 : || ( _nSlotId == SID_ATTR_CHAR_CJK_WEIGHT )
560 0 : || ( _nSlotId == SID_ATTR_CHAR_CTL_WEIGHT )
561 0 : || ( _nSlotId == SID_ATTR_CHAR_LATIN_WEIGHT )
562 0 : || ( _nSlotId == SID_ATTR_CHAR_LANGUAGE )
563 0 : || ( _nSlotId == SID_ATTR_CHAR_CJK_LANGUAGE )
564 0 : || ( _nSlotId == SID_ATTR_CHAR_CTL_LANGUAGE )
565 0 : || ( _nSlotId == SID_ATTR_CHAR_LATIN_LANGUAGE )
566 0 : || ( _nSlotId == SID_ATTR_CHAR_CONTOUR )
567 0 : || ( _nSlotId == SID_ATTR_CHAR_SHADOWED )
568 0 : || ( _nSlotId == SID_ATTR_CHAR_WORDLINEMODE )
569 0 : || ( _nSlotId == SID_ATTR_CHAR_COLOR )
570 0 : || ( _nSlotId == SID_ATTR_CHAR_RELIEF )
571 0 : || ( _nSlotId == SID_ATTR_CHAR_KERNING )
572 0 : || ( _nSlotId == SID_ATTR_CHAR_AUTOKERN )
573 0 : || ( _nSlotId == SID_ATTR_CHAR_SCALEWIDTH )
574 : )
575 : {
576 0 : bNeedParametrizedDispatcher = true;
577 : }
578 : else
579 : {
580 0 : SfxSlotPool& rSlotPool = SfxSlotPool::GetSlotPool( NULL );
581 0 : const SfxSlot* pSlot = rSlotPool.GetSlot( _nSlotId );
582 0 : const SfxType* pType = pSlot ? pSlot->GetType() : NULL;
583 0 : if ( pType )
584 : {
585 0 : bNeedParametrizedDispatcher = ( pType->nAttribs > 0 );
586 : }
587 : }
588 :
589 0 : if ( bNeedParametrizedDispatcher )
590 : {
591 : #if OSL_DEBUG_LEVEL > 0
592 : OString sTrace( "ORichTextPeer::implCreateDispatcher: creating *parametrized* dispatcher for " );
593 : sTrace += OString( _rURL.Complete.getStr(), _rURL.Complete.getLength(), RTL_TEXTENCODING_ASCII_US );
594 : OSL_TRACE( "%s", sTrace.getStr() );
595 : #endif
596 0 : pAttributeDispatcher = new OParametrizedAttributeDispatcher( pRichTextControl->getView(), _nSlotId, _rURL, pRichTextControl );
597 : }
598 : else
599 : {
600 : #if OSL_DEBUG_LEVEL > 0
601 : OString sTrace( "ORichTextPeer::implCreateDispatcher: creating *normal* dispatcher for " );
602 : sTrace += OString( _rURL.Complete.getStr(), _rURL.Complete.getLength(), RTL_TEXTENCODING_ASCII_US );
603 : OSL_TRACE( "%s", sTrace.getStr() );
604 : #endif
605 0 : pAttributeDispatcher = new OAttributeDispatcher( pRichTextControl->getView(), _nSlotId, _rURL, pRichTextControl );
606 : }
607 : }
608 : #if OSL_DEBUG_LEVEL > 0
609 : else
610 : {
611 : OString sTrace( "ORichTextPeer::implCreateDispatcher: not creating dispatcher (unsupported slot) for " );
612 : sTrace += OString( _rURL.Complete.getStr(), _rURL.Complete.getLength(), RTL_TEXTENCODING_ASCII_US );
613 : OSL_TRACE( "%s", sTrace.getStr() );
614 : }
615 : #endif
616 : }
617 0 : break;
618 : }
619 :
620 0 : SingleAttributeDispatcher xDispatcher( pDispatcher );
621 0 : if ( pAttributeDispatcher )
622 : {
623 0 : xDispatcher = SingleAttributeDispatcher( pAttributeDispatcher );
624 0 : pRichTextControl->enableAttributeNotification( _nSlotId, pAttributeDispatcher );
625 : }
626 :
627 0 : return xDispatcher;
628 : }
629 :
630 :
631 : namespace
632 : {
633 0 : SfxSlotId lcl_getSlotFromUnoName( SfxSlotPool& _rSlotPool, const OUString& _rUnoSlotName )
634 : {
635 0 : const SfxSlot* pSlot = _rSlotPool.GetUnoSlot( _rUnoSlotName );
636 0 : if ( pSlot )
637 : {
638 : // okay, there's a slot with the given UNO name
639 0 : return lcl_translateConflictingSlot( pSlot->GetSlotId() );
640 : }
641 :
642 : // some hard-coded slots, which do not have a UNO name at SFX level, but which
643 : // we nevertheless need to transport via UNO mechanisms, so we need a name
644 0 : if ( _rUnoSlotName == "AllowHangingPunctuation" )
645 0 : return SID_ATTR_PARA_HANGPUNCTUATION;
646 0 : if ( _rUnoSlotName == "ApplyForbiddenCharacterRules" )
647 0 : return SID_ATTR_PARA_FORBIDDEN_RULES;
648 0 : if ( _rUnoSlotName == "UseScriptSpacing" )
649 0 : return SID_ATTR_PARA_SCRIPTSPACE;
650 :
651 : OSL_ENSURE( pSlot, "lcl_getSlotFromUnoName: unknown UNO slot name!" );
652 0 : return 0;
653 : }
654 : }
655 :
656 :
657 0 : Reference< XDispatch > SAL_CALL ORichTextPeer::queryDispatch( const ::com::sun::star::util::URL& _rURL, const OUString& /*_rTargetFrameName*/, sal_Int32 /*_nSearchFlags*/ ) throw (RuntimeException, std::exception)
658 : {
659 0 : Reference< XDispatch > xReturn;
660 0 : if ( !GetWindow() )
661 : {
662 : OSL_FAIL( "ORichTextPeer::queryDispatch: already disposed?" );
663 0 : return xReturn;
664 : }
665 :
666 : // is it an UNO slot?
667 0 : OUString sUnoProtocolPrefix( ".uno:" );
668 0 : if ( _rURL.Complete.startsWith( sUnoProtocolPrefix ) )
669 : {
670 0 : OUString sUnoSlotName = _rURL.Complete.copy( sUnoProtocolPrefix.getLength() );
671 0 : SfxSlotId nSlotId = lcl_getSlotFromUnoName( SfxSlotPool::GetSlotPool( NULL ), sUnoSlotName );
672 0 : if ( nSlotId > 0 )
673 : {
674 : // do we already have a dispatcher for this?
675 0 : AttributeDispatchers::const_iterator aDispatcherPos = m_aDispatchers.find( nSlotId );
676 0 : if ( aDispatcherPos == m_aDispatchers.end() )
677 : {
678 0 : SingleAttributeDispatcher pDispatcher = implCreateDispatcher( nSlotId, _rURL );
679 0 : if ( pDispatcher.is() )
680 : {
681 0 : aDispatcherPos = m_aDispatchers.insert( AttributeDispatchers::value_type( nSlotId, pDispatcher ) ).first;
682 0 : }
683 : }
684 :
685 0 : if ( aDispatcherPos != m_aDispatchers.end() )
686 0 : xReturn = aDispatcherPos->second.get();
687 0 : }
688 : }
689 :
690 0 : return xReturn;
691 : }
692 :
693 :
694 0 : Sequence< Reference< XDispatch > > SAL_CALL ORichTextPeer::queryDispatches( const Sequence< DispatchDescriptor >& _rRequests ) throw (RuntimeException, std::exception)
695 : {
696 0 : Sequence< Reference< XDispatch > > aReturn( _rRequests.getLength() );
697 0 : Reference< XDispatch >* pReturn = aReturn.getArray();
698 :
699 0 : const DispatchDescriptor* pRequest = _rRequests.getConstArray();
700 0 : const DispatchDescriptor* pRequestEnd = pRequest + _rRequests.getLength();
701 0 : for ( ; pRequest != pRequestEnd; ++pRequest, ++pReturn )
702 : {
703 0 : *pReturn = queryDispatch( pRequest->FeatureURL, pRequest->FrameName, pRequest->SearchFlags );
704 : }
705 0 : return aReturn;
706 : }
707 :
708 :
709 0 : void ORichTextPeer::onSelectionChanged( const ESelection& /*_rSelection*/ )
710 : {
711 0 : AttributeDispatchers::iterator aDispatcherPos = m_aDispatchers.find( SID_COPY );
712 0 : if ( aDispatcherPos != m_aDispatchers.end() )
713 0 : aDispatcherPos->second.get()->invalidate();
714 :
715 0 : aDispatcherPos = m_aDispatchers.find( SID_CUT );
716 0 : if ( aDispatcherPos != m_aDispatchers.end() )
717 0 : aDispatcherPos->second.get()->invalidate();
718 0 : }
719 :
720 :
721 192 : } // namespace frm
722 :
723 :
724 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|