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