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