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